home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / units / part01 < prev    next >
Encoding:
Text File  |  1993-07-22  |  40.1 KB  |  1,707 lines

  1. Newsgroups: comp.sources.misc
  2. From: adrian@stein2.u.washington.edu (Adrian Mariano)
  3. Subject: v38i061:  units - clone of the unix program for unit conversion, Part01/01
  4. Message-ID: <1993Jul22.203650.4325@sparky.sterling.com>
  5. X-Md4-Signature: 8504f729b95a325b66badcc518bd2061
  6. Keywords: units
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: University of Washington
  9. Date: Thu, 22 Jul 1993 20:36:50 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: adrian@stein2.u.washington.edu (Adrian Mariano)
  13. Posting-number: Volume 38, Issue 61
  14. Archive-name: units/part01
  15. Environment: UNIX, DOS
  16.  
  17. This is a program which I wrote as a clone of the UNIX 'units'
  18. command.  I threw it together in a couple days, but it seems to work,
  19. with some restrictions.  I have tested it under DOS with Borland C and
  20. Ultrix 4.2.
  21.  
  22. Adrian Mariano (adrian@u.washington.edu or mariano@geom.umn.edu)
  23. -------------
  24. #! /bin/sh
  25. # This is a shell archive.  Remove anything before this line, then feed it
  26. # into a shell via "sh file" or similar.  To overwrite existing files,
  27. # type "sh file -c".
  28. # Contents:  README Makefile Makefile.dos getopt.c getopt.h units.1
  29. #   units.c units.doc units.lib
  30. # Wrapped by kent@sparky on Thu Jul 22 15:24:17 1993
  31. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  32. echo If this archive is complete, you will see the following message:
  33. echo '          "shar: End of archive 1 (of 1)."'
  34. if test -f 'README' -a "${1}" != "-c" ; then 
  35.   echo shar: Will not clobber existing file \"'README'\"
  36. else
  37.   echo shar: Extracting \"'README'\" \(283 characters\)
  38.   sed "s/^X//" >'README' <<'END_OF_FILE'
  39. XThis is a program which I wrote as a clone of the UNIX 'units'
  40. Xcommand.  I threw it together in a couple days, but it seems to work,
  41. Xwith some restrictions.  I have tested it under DOS with Borland C and
  42. XUltrix 4.2.
  43. X
  44. XAdrian Mariano (adrian@u.washington.edu or mariano@geom.umn.edu)
  45. X
  46. END_OF_FILE
  47.   if test 283 -ne `wc -c <'README'`; then
  48.     echo shar: \"'README'\" unpacked with wrong size!
  49.   fi
  50.   # end of 'README'
  51. fi
  52. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'Makefile'\"
  54. else
  55.   echo shar: Extracting \"'Makefile'\" \(81 characters\)
  56.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  57. XCC=gcc
  58. XCFLAGS= -DUNITSFILE=\"units.lib\"
  59. X
  60. Xunits:    units.o
  61. X    $(CC) -o units units.o
  62. END_OF_FILE
  63.   if test 81 -ne `wc -c <'Makefile'`; then
  64.     echo shar: \"'Makefile'\" unpacked with wrong size!
  65.   fi
  66.   # end of 'Makefile'
  67. fi
  68. if test -f 'Makefile.dos' -a "${1}" != "-c" ; then 
  69.   echo shar: Will not clobber existing file \"'Makefile.dos'\"
  70. else
  71.   echo shar: Extracting \"'Makefile.dos'\" \(152 characters\)
  72.   sed "s/^X//" >'Makefile.dos' <<'END_OF_FILE'
  73. XCC=bccx
  74. X
  75. Xunits.exe: units.obj getopt.obj
  76. X    $(CC) units.obj getopt.obj
  77. X
  78. Xunits.obj: units.c 
  79. X    $(CC) -c units.c
  80. X
  81. Xgetopt.obj: getopt.c
  82. X    $(CC) -c getopt.c
  83. X
  84. X
  85. X
  86. END_OF_FILE
  87.   if test 152 -ne `wc -c <'Makefile.dos'`; then
  88.     echo shar: \"'Makefile.dos'\" unpacked with wrong size!
  89.   fi
  90.   # end of 'Makefile.dos'
  91. fi
  92. if test -f 'getopt.c' -a "${1}" != "-c" ; then 
  93.   echo shar: Will not clobber existing file \"'getopt.c'\"
  94. else
  95.   echo shar: Extracting \"'getopt.c'\" \(1950 characters\)
  96.   sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
  97. X/* optarg - parse command-line arguments */
  98. X/* Author: AT&T */
  99. X
  100. X#include <stdio.h>
  101. X
  102. X#define ERR(s, c)                if(opterr){\
  103. X    char errbuf[2];\
  104. X    errbuf[0] = c; errbuf[1] = '\n';\
  105. X    fwrite(argv[0], 1, (unsigned)strlen(argv[0]),stderr);\
  106. X    fwrite(s, 1, (unsigned)strlen(s),stderr);\
  107. X    fwrite(errbuf, 1, 2, stderr);}
  108. X
  109. Xextern int strcmp();
  110. Xextern char *strchr();
  111. Xextern int strlen();
  112. X
  113. Xint    opterr = 1;        /* getopt prints errors if this is on */
  114. Xint    optind = 1;        /* token pointer */
  115. Xint    optopt;            /* option character passed back to user */
  116. Xchar    *optarg;        /* flag argument (or value) */
  117. X
  118. Xint    /* return option character, EOF if no more or ? if problem */
  119. Xgetopt(argc, argv, opts)
  120. Xint    argc;
  121. Xchar    **argv;
  122. Xchar    *opts;                /* option string */
  123. X{
  124. X    static int sp = 1;        /* character index in current token */
  125. X    register char *cp;        /* pointer into current token */
  126. X
  127. X    if(sp == 1)
  128. X        /* check for more flag-like tokens */
  129. X        if(optind >= argc ||
  130. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  131. X            return(EOF);
  132. X        else if(strcmp(argv[optind], "--") == 0) {
  133. X            optind++;
  134. X            return(EOF);
  135. X        }
  136. X    optopt = argv[optind][sp];
  137. X    if(optopt == ':' || (cp=strchr(opts, optopt)) == 0) {
  138. X        ERR(": illegal option -- ", optopt);
  139. X        /* if no chars left in this token, move to next token */
  140. X        if(argv[optind][++sp] == '\0') {
  141. X            optind++;
  142. X            sp = 1;
  143. X        }
  144. X        return('?');
  145. X    }
  146. X
  147. X    if(*++cp == ':') {    /* if a value is expected, get it */
  148. X        if(argv[optind][sp+1] != '\0')
  149. X            /* flag value is rest of current token */
  150. X            optarg = &argv[optind++][sp+1];
  151. X        else if(++optind >= argc) {
  152. X            ERR(": option requires an argument -- ", optopt);
  153. X            sp = 1;
  154. X            return('?');
  155. X        } else
  156. X            /* flag value is next token */
  157. X            optarg = argv[optind++];
  158. X        sp = 1;
  159. X    } else {
  160. X        /* set up to look at next char in token, next time */
  161. X        if(argv[optind][++sp] == '\0') {
  162. X            /* no more in current token, so setup next token */
  163. X            sp = 1;
  164. X            optind++;
  165. X        }
  166. X        optarg = 0;
  167. X    }
  168. X    return(optopt);/* return the current flag character found */
  169. X}
  170. END_OF_FILE
  171.   if test 1950 -ne `wc -c <'getopt.c'`; then
  172.     echo shar: \"'getopt.c'\" unpacked with wrong size!
  173.   fi
  174.   # end of 'getopt.c'
  175. fi
  176. if test -f 'getopt.h' -a "${1}" != "-c" ; then 
  177.   echo shar: Will not clobber existing file \"'getopt.h'\"
  178. else
  179.   echo shar: Extracting \"'getopt.h'\" \(336 characters\)
  180.   sed "s/^X//" >'getopt.h' <<'END_OF_FILE'
  181. X#ifndef GETOPT_H
  182. X#define GETOPT_H
  183. X#include "proto.h"                /* define PROTO */
  184. X
  185. Xint getopt PROTO((int, char **, char *));
  186. Xextern char *optarg;                /* current argv string */
  187. Xextern int optind;                /* current argv index */
  188. Xextern int optopt;                /* option character */
  189. Xextern int opterr;                /* getopt prints errors if 1 */
  190. X#endif /* GETOPT_H */
  191. END_OF_FILE
  192.   if test 336 -ne `wc -c <'getopt.h'`; then
  193.     echo shar: \"'getopt.h'\" unpacked with wrong size!
  194.   fi
  195.   # end of 'getopt.h'
  196. fi
  197. if test -f 'units.1' -a "${1}" != "-c" ; then 
  198.   echo shar: Will not clobber existing file \"'units.1'\"
  199. else
  200.   echo shar: Extracting \"'units.1'\" \(3782 characters\)
  201.   sed "s/^X//" >'units.1' <<'END_OF_FILE'
  202. X.TH UNITS 1  "14 July 1993"
  203. X.SH NAME
  204. Xunits - conversion program
  205. X.SH SYNTAX
  206. X.B units
  207. X[-f filename] [-q] [to-unit from-unit]
  208. X.SH SUMMARY
  209. X.TP 4
  210. X.B -f filename
  211. XSpecifies the name of the units data file to load.
  212. X.LP
  213. X.TP 4
  214. X.B -q 
  215. XSupresses prompting of the user for units and the display of statistics
  216. Xabout the number of units loaded.
  217. X.LP
  218. X.TP 4
  219. X.B from-unit to-unit
  220. XAllows a single unit converstion to be done directly from the command
  221. Xline.  No prompting will occur.  The units program will print out
  222. Xonly the result of this single conversion.
  223. X
  224. X.SH DESCRIPTION
  225. XThe units program converts quantities expression in various scales to 
  226. Xtheir equivalents in other scales.  The units program can only
  227. Xhandle multiplicative scale changes.  It cannot convert Centigrade
  228. Xto Fahrenheit, for example.  It works interactively by prompting
  229. Xthe user for input:
  230. X.nf
  231. X
  232. X    You have: meters
  233. X    You want: feet
  234. X            * 3.2808399
  235. X            / 0.3048
  236. X
  237. X    You have: cm^3
  238. X    You want: gallons
  239. X            * 0.00026417205
  240. X            / 3785.4118
  241. X
  242. X.fi
  243. XPowers of units can be specified using the '^' character as shown in
  244. Xthe example, or by simple concatenation: 'cm3' is equivalent to 'cm^3'.
  245. XMultiplication of units can be specified by using spaces, a dash or
  246. Xan asterisk.  Division of units is indicated by the slash ('/').  
  247. XNote that multiplication has a higher precedence than division, so
  248. X'm/s/s' is the same as 'm/s^2' or 'm/s s'
  249. XIf the user enters incompatible unit types, the units program will
  250. Xprint a message indicating that the units are not conformable and
  251. Xit will display the reduced form for each unit:
  252. X.nf
  253. X
  254. X    You have: ergs/hour
  255. X    You want: fathoms kg^2 / day 
  256. X    conformability error
  257. X            2.7777778e-11 kg m^2 / sec^3
  258. X            2.1166667e-05 kg^2 m / sec
  259. X
  260. X.fi
  261. X.LP
  262. XThe conversion information is read from a units data file.  The default
  263. Xfile includes definitions for most familiar units, abbreviations and
  264. Xmetric prefixes.  Some constants of nature included are:
  265. X.in +4m
  266. X.ta
  267. X.ta 9m +
  268. X.nf
  269. X
  270. Xpi    ratio of circumference to diameter
  271. Xc    speed of light
  272. Xe    charge on an electron
  273. Xg    acceleration of gravity
  274. Xforce    same as g
  275. Xmole    Avogadro's number
  276. Xwater    pressure per unit height of water
  277. Xmercury    pressure per unit height of mercury
  278. Xau    astronomical unit
  279. X
  280. X.fi
  281. X.in -4m
  282. X\'Pound' is a unit of mass.  Compound names are run together
  283. Xso 'poundforce' is a unit of force.  British units that differ from their
  284. XUS counterparts are prefixed with 'br', and currency is prefixed with
  285. Xits country name: 'belgiumfranc', 'britainpound'.  When searching for
  286. Xa unit, if the specified string does not appear exactly as a unit
  287. Xname, then the units program will try to remove a trailing 's' or
  288. Xa trailing 'es' and check again for a match.  
  289. X.LP
  290. XAll of these definitions can be read in the standard units file, or you
  291. Xcan supply your own file.  A unit is specified on a single line by
  292. Xgiving its name and an equivalence.  One should be careful to define
  293. Xnew units in terms of old ones so that a reduction leads to the
  294. Xprimitive units which are marked with '!' characters.  
  295. XThe units program will not detect infinite loops that could be caused
  296. Xby careless unit definitions.
  297. X.LP
  298. XPrefixes are defined in the same was as standard units, but with 
  299. Xa trailing dash at the end of the prefix name.  
  300. X.SH BUGS
  301. X.LP
  302. XThe effect of including a '/' in a prefix is surprising.
  303. X.LP
  304. XExponents entered by the user can be only one digit.
  305. X.LP
  306. XThe user must use | to indicate division of numbers and / to
  307. Xindicate division of symbols.  This distinction should not
  308. Xbe necessary.
  309. X.LP
  310. XThe program contains various arbitrary limits on the length
  311. Xof the units converted and on the length of the data file.
  312. X.SH FILES
  313. Xunits.lib - the standard units library
  314. X.SH AUTHOR
  315. XAdrian Mariano (adrian@u.washington.edu or mariano@geom.umn.edu)
  316. X
  317. X
  318. X
  319. END_OF_FILE
  320.   if test 3782 -ne `wc -c <'units.1'`; then
  321.     echo shar: \"'units.1'\" unpacked with wrong size!
  322.   fi
  323.   # end of 'units.1'
  324. fi
  325. if test -f 'units.c' -a "${1}" != "-c" ; then 
  326.   echo shar: Will not clobber existing file \"'units.c'\"
  327. else
  328.   echo shar: Extracting \"'units.c'\" \(13465 characters\)
  329.   sed "s/^X//" >'units.c' <<'END_OF_FILE'
  330. X/* 
  331. X   units.c   Copyright (c) 1993 by Adrian Mariano
  332. X
  333. X   This program can be freely distributed as long as no money is
  334. X   charged for it. 
  335. X*/
  336. X
  337. X
  338. X#include<stdio.h>
  339. X#include<string.h>
  340. X#include<stdlib.h>
  341. X
  342. X#define VERSION "1.0"
  343. X
  344. X#ifndef UNITSFILE
  345. X#define UNITSFILE "units.lib"
  346. X#endif
  347. X
  348. X#define MAXUNITS 1000
  349. X#define MAXPREFIXES 50
  350. X
  351. X#define MAXSUBUNITS 500
  352. X
  353. X#define PRIMITIVECHAR '!'
  354. X
  355. Xchar *powerstring="^";
  356. X
  357. Xstruct {
  358. X   char *uname;
  359. X   char *uval;
  360. X} unittable[MAXUNITS];
  361. X
  362. Xstruct unittype {
  363. X   char *numerator[MAXSUBUNITS];
  364. X   char *denominator[MAXSUBUNITS];
  365. X   double factor;
  366. X};
  367. X
  368. Xstruct {
  369. X   char *prefixname;
  370. X   char *prefixval;
  371. X} prefixtable[MAXPREFIXES];
  372. X
  373. X
  374. Xchar *NULLUNIT="";
  375. X
  376. Xint unitcount;
  377. Xint prefixcount;
  378. X
  379. X
  380. Xchar *dupstr(char *str)
  381. X{
  382. X  char *ret;
  383. X  ret=malloc(strlen(str)+1);
  384. X  if (!ret) {
  385. X    fprintf(stderr,"Memory allocation error\n");
  386. X    exit(3);
  387. X  }
  388. X  strcpy(ret,str);
  389. X  return(ret);
  390. X} 
  391. X
  392. X
  393. Xvoid readerror(int linenum)
  394. X{
  395. X  fprintf(stderr,"Error in units file '%s' line %d\n",UNITSFILE,linenum);
  396. X}
  397. X
  398. X
  399. Xvoid readunits(char *userfile)
  400. X{
  401. X  FILE *unitfile;
  402. X  char line[80],*lineptr;
  403. X  int len,linenum,i;
  404. X
  405. X  unitcount=0;
  406. X  linenum=0;
  407. X
  408. X  if (userfile){
  409. X    unitfile=fopen(userfile,"rt");
  410. X    if (!unitfile) {
  411. X      fprintf(stderr,"Unable to open units file '%s'\n",userfile);
  412. X      exit(1);
  413. X    }
  414. X  } else {
  415. X    unitfile=fopen(UNITSFILE,"rt");
  416. X    if (!unitfile) { 
  417. X      char *direc,*env;
  418. X      char filename[1000];
  419. X      char separator[2];
  420. X      env=getenv("PATH");
  421. X      if (env){
  422. X        if (strchr(env,';')) strcpy(separator,";");
  423. X        else strcpy(separator,":");
  424. X        direc=strtok(env,separator);
  425. X        while(direc){
  426. X          strcpy(filename,"");
  427. X          strncat(filename,direc,999);
  428. X          strncat(filename,"/",999-strlen(filename));
  429. X          strncat(filename,UNITSFILE,999-strlen(filename));
  430. X          unitfile=fopen(filename,"rt");
  431. X          if (unitfile) break;
  432. X          direc=strtok(NULL,separator);
  433. X        }
  434. X      }
  435. X      if (!unitfile){
  436. X        fprintf(stderr,"Can't find units file '%s'\n",UNITSFILE);
  437. X        exit(1);
  438. X      }
  439. X    }
  440. X  }
  441. X  while (!feof(unitfile)){
  442. X    if (!fgets(line,79,unitfile)) break;
  443. X    linenum++;
  444. X    lineptr=line;
  445. X    if (*lineptr=='/') continue;
  446. X    lineptr+=strspn(lineptr," \n\t");
  447. X    len = strcspn(lineptr, " \n\t");
  448. X    lineptr[len]=0;
  449. X    if (!strlen(lineptr)) continue;
  450. X    if (lineptr[strlen(lineptr)-1]=='-'){   /* it's a prefix */
  451. X      if (prefixcount==MAXPREFIXES) {
  452. X        fprintf(stderr,"Memory for prefixes exceeded in line %d\n",linenum);
  453. X        continue;
  454. X      }
  455. X      lineptr[strlen(lineptr)-1]=0;
  456. X      prefixtable[prefixcount].prefixname=dupstr(lineptr);
  457. X      for(i=0;i<prefixcount;i++) 
  458. X        if (!strcmp(prefixtable[i].prefixname,lineptr)){
  459. X        fprintf(stderr,"Redefinition of prefix '%s' on line %d ignored\n",
  460. X            lineptr,linenum);
  461. X    continue;
  462. X      }
  463. X      lineptr+=len+1;
  464. X      if (!strlen(lineptr)) { readerror(linenum); continue;}
  465. X      lineptr+=strspn(lineptr," \n\t");
  466. X      len = strcspn(lineptr, "\n\t");
  467. X      lineptr[len]=0;
  468. X      prefixtable[prefixcount++].prefixval=dupstr(lineptr);
  469. X    } else {  /* it's not a prefix */
  470. X      if (unitcount==MAXUNITS) {
  471. X        fprintf(stderr,"Memory for units exceeded in line %d\n",linenum);
  472. X        continue;
  473. X      }
  474. X      unittable[unitcount].uname=dupstr(lineptr);
  475. X      for(i=0;i<unitcount;i++) if (!strcmp(unittable[i].uname,lineptr)){
  476. X        fprintf(stderr,"Redefinition of unit '%s' on line %d ignored\n",
  477. X            lineptr,linenum);
  478. X    continue;
  479. X      }
  480. X      lineptr+=len+1;
  481. X      lineptr+=strspn(lineptr," \n\t");
  482. X      if (!strlen(lineptr)) { readerror(linenum); continue;}
  483. X      len = strcspn(lineptr, "\n\t");
  484. X      lineptr[len]=0;
  485. X      unittable[unitcount++].uval=dupstr(lineptr);
  486. X    }
  487. X  }
  488. X  fclose(unitfile);
  489. X}
  490. X
  491. Xvoid initializeunit(struct unittype *theunit)
  492. X{
  493. X  theunit->factor=1.0;
  494. X  theunit->numerator[0]=theunit->denominator[0]=NULL;
  495. X}
  496. X
  497. X
  498. Xint addsubunit(char *product[], char *toadd)
  499. X{
  500. X  char **ptr;
  501. X
  502. X  for(ptr=product;*ptr && *ptr!=NULLUNIT;ptr++);
  503. X  if (ptr>=product+MAXSUBUNITS){
  504. X    fprintf(stderr,"Memory overflow in unit reduction\n");
  505. X    return 1;
  506. X  }
  507. X  if (!*ptr) *(ptr+1)=0;
  508. X  *ptr=dupstr(toadd);
  509. X  return 0;
  510. X}
  511. X
  512. X
  513. Xvoid showunit(struct unittype *theunit)
  514. X{
  515. X  char **ptr;
  516. X  int printedslash;
  517. X  int counter=1;
  518. X
  519. X  printf("\t%.8g",theunit->factor);
  520. X  for(ptr=theunit->numerator;*ptr;ptr++){
  521. X    if (ptr>theunit->numerator && **ptr &&
  522. X       !strcmp(*ptr,*(ptr-1))) counter++;
  523. X      else {
  524. X        if (counter>1) printf("%s%d",powerstring,counter);
  525. X        if (**ptr) printf(" %s",*ptr);
  526. X    counter=1;
  527. X      }
  528. X  }
  529. X  if (counter>1) printf("%s%d",powerstring,counter);
  530. X  counter=1;
  531. X  printedslash=0;
  532. X  for(ptr=theunit->denominator;*ptr;ptr++){
  533. X    if (ptr>theunit->denominator && **ptr && 
  534. X         !strcmp(*ptr,*(ptr-1))) counter++;
  535. X      else {
  536. X        if (counter>1) printf("%s%d",powerstring,counter);
  537. X        if (**ptr) { 
  538. X      if (!printedslash) printf(" /");
  539. X      printedslash=1;
  540. X          printf(" %s",*ptr);
  541. X    }
  542. X    counter=1;
  543. X      }
  544. X  }
  545. X  if (counter>1) printf("%s%d",powerstring,counter);
  546. X  printf("\n");
  547. X}
  548. X
  549. X
  550. Xvoid zeroerror()
  551. X{
  552. X   fprintf(stderr,"Unit reduces to zero\n");
  553. X}   
  554. X
  555. X/* 
  556. X   Adds the specified string to the unit. 
  557. X   Flip is 0 for adding normally, 1 for adding reciprocal.
  558. X   Returns 0 for successful addition, nonzero on error.
  559. X*/
  560. X
  561. Xint addunit(struct unittype *theunit,char *toadd,int flip)
  562. X{
  563. X  char *scratch,*savescr;
  564. X  char *item;
  565. X  char *divider,*subunit,*slash;
  566. X  int doingtop;
  567. X
  568. X  savescr=scratch=dupstr(toadd);
  569. X  for(slash=scratch+1;*slash;slash++) 
  570. X    if (*slash=='-' && 
  571. X      (tolower(*(slash-1))!='e' || !strchr(".0123456789",*(slash+1))))
  572. X      *slash=' ';
  573. X  slash=strchr(scratch,'/');
  574. X  if (slash) *slash=0;
  575. X  doingtop=1;
  576. X  do{
  577. X  item=strtok(scratch," *\t\n/");
  578. X  while(item){
  579. X    if (strchr("0123456789.",*item)){  /* item is a number */
  580. X      double num;
  581. X
  582. X      divider=strchr(item,'|');
  583. X      if (divider){
  584. X    *divider=0;
  585. X    num=atof(item);
  586. X    if (!num) {
  587. X          zeroerror();
  588. X          return 1;
  589. X        }
  590. X    if (doingtop^flip) theunit->factor *= num;
  591. X         else  theunit->factor /=num;
  592. X    num=atof(divider+1);
  593. X    if (!num)  {
  594. X          zeroerror();
  595. X          return 1;
  596. X        }
  597. X    if (doingtop^flip) theunit->factor /= num;
  598. X     else theunit->factor *= num;
  599. X      } else {
  600. X    num=atof(item);
  601. X    if (!num)  {
  602. X          zeroerror();
  603. X          return 1;
  604. X        }
  605. X    if (doingtop^flip) theunit->factor *= num;
  606. X    else theunit->factor /= num;
  607. X
  608. X      }
  609. X    } else {                         /* item is not a number */
  610. X      int repeat=1;
  611. X      if (strchr("23456789",item[strlen(item)-1])){
  612. X    repeat=item[strlen(item)-1]-'0';
  613. X    item[strlen(item)-1]=0;
  614. X      }
  615. X      for(;repeat;repeat--)
  616. X    if (addsubunit(doingtop^flip?theunit->numerator:theunit->denominator,item))
  617. X  return 1;
  618. X    }
  619. X    item=strtok(NULL," *\t/\n");
  620. X  }
  621. X  doingtop--;
  622. X  if (slash){
  623. X    scratch=slash+1;
  624. X  } else doingtop--;
  625. X  }while (doingtop>=0 );
  626. X  free(savescr);
  627. X  return 0;
  628. X}
  629. X
  630. X
  631. Xint compare(const void *item1, const void *item2)
  632. X{
  633. X  return strcmp(*(char **) item1, * (char **) item2);
  634. X}
  635. X
  636. X
  637. Xvoid sortunit(struct unittype *theunit)
  638. X{
  639. X  char **ptr;
  640. X  int count;
  641. X
  642. X  for(count=0,ptr=theunit->numerator;*ptr;ptr++,count++);
  643. X  qsort(theunit->numerator, count, sizeof(char *), compare);
  644. X  for(count=0,ptr=theunit->denominator;*ptr;ptr++,count++);
  645. X  qsort(theunit->denominator, count, sizeof(char *), compare);
  646. X}
  647. X
  648. X
  649. Xvoid cancelunit(struct unittype *theunit)
  650. X{
  651. X  char **den,**num;
  652. X  int comp;
  653. X
  654. X  den=theunit->denominator;
  655. X  num=theunit->numerator;
  656. X
  657. X  while(*num && *den){
  658. X    comp=strcmp(*den,*num);
  659. X    if (!comp) {
  660. X/*      if (*den!=NULLUNIT) free(*den);
  661. X      if (*num!=NULLUNIT) free(*num);*/
  662. X      *den++=NULLUNIT;
  663. X      *num++=NULLUNIT;
  664. X    }
  665. X    else if (comp<0) den++;
  666. X    else num++;
  667. X  }
  668. X}
  669. X
  670. X
  671. X
  672. X
  673. X/*
  674. X   Looks up the definition for the specified unit.  
  675. X   Returns a pointer to the definition or a null pointer
  676. X   if the specified unit does not appear in the units table.
  677. X*/
  678. X
  679. Xstatic char buffer[100];  /* buffer for lookupunit answers with prefixes */
  680. X
  681. Xchar *lookupunit(char *unit)
  682. X{
  683. X  int i;
  684. X  char *copy;
  685. X
  686. X  for(i=0;i<unitcount;i++){
  687. X    if (!strcmp(unittable[i].uname,unit)) return unittable[i].uval;
  688. X  }
  689. X
  690. X  if (unit[strlen(unit)-1]=='^') {
  691. X    copy=dupstr(unit);
  692. X    copy[strlen(copy)-1]=0;
  693. X    for(i=0;i<unitcount;i++){
  694. X      if (!strcmp(unittable[i].uname,copy)) {
  695. X        strcpy(buffer,copy);
  696. X        free(copy);
  697. X        return buffer;
  698. X      }
  699. X    } 
  700. X    free(copy);
  701. X  }
  702. X  if (unit[strlen(unit)-1]=='s') {
  703. X    copy=dupstr(unit);
  704. X    copy[strlen(copy)-1]=0;
  705. X    for(i=0;i<unitcount;i++){
  706. X      if (!strcmp(unittable[i].uname,copy)) {
  707. X        strcpy(buffer,copy);
  708. X        free(copy);
  709. X        return buffer;
  710. X      }
  711. X    }
  712. X    if (copy[strlen(copy)-1]=='e') {
  713. X      copy[strlen(copy)-1]=0;
  714. X      for(i=0;i<unitcount;i++){
  715. X        if (!strcmp(unittable[i].uname,copy)){
  716. X          strcpy(buffer,copy);
  717. X          free(copy);
  718. X          return buffer;
  719. X        }
  720. X      }
  721. X    }
  722. X    free(copy);
  723. X  }
  724. X  for(i=0;i<prefixcount;i++){
  725. X    if (!strncmp(prefixtable[i].prefixname,unit,
  726. X        strlen(prefixtable[i].prefixname))) {
  727. X      unit += strlen(prefixtable[i].prefixname);
  728. X      if (!strlen(unit) || lookupunit(unit)){
  729. X        strcpy(buffer,prefixtable[i].prefixval);
  730. X        strcat(buffer," ");
  731. X        strcat(buffer,unit);
  732. X        return buffer;
  733. X      }
  734. X    }
  735. X  }
  736. X  return 0;
  737. X}
  738. X
  739. X
  740. X
  741. X/*
  742. X   reduces a product of symbolic units to primitive units. 
  743. X   The three low bits are used to return flags:
  744. X
  745. X     bit 0 (1) set on if reductions were performed without error.
  746. X     bit 1 (2) set on if no reductions are performed.
  747. X     bit 2 (4) set on if an unknown unit is discovered.
  748. X*/
  749. X
  750. X
  751. X#define ERROR 4
  752. X
  753. Xint reduceproduct(struct unittype *theunit, int flip)
  754. X{
  755. X
  756. X  char *toadd;
  757. X  char **product;
  758. X  int didsomething=2;
  759. X
  760. X  if (flip) product=theunit->denominator;
  761. X  else product=theunit->numerator;
  762. X
  763. X  for(;*product;product++){
  764. X    
  765. X    for(;;){
  766. X      if (!strlen(*product)) break;
  767. X      toadd=lookupunit(*product);
  768. X      if (!toadd) { 
  769. X        printf("unknown unit '%s'\n",*product);
  770. X        return ERROR;
  771. X      }
  772. X      if (strchr(toadd,PRIMITIVECHAR)) break;
  773. X      didsomething=1;
  774. X      if (*product!=NULLUNIT) {
  775. X        free (*product);
  776. X        *product=NULLUNIT;
  777. X      }
  778. X      if (addunit(theunit, toadd, flip)) return ERROR;
  779. X    }
  780. X  }
  781. X  return didsomething;
  782. X}
  783. X
  784. X
  785. X/* 
  786. X   Reduces numerator and denominator of the specified unit.
  787. X   Returns 0 on success, or 1 on unknown unit error.
  788. X*/
  789. X
  790. Xint reduceunit(struct unittype *theunit)
  791. X{
  792. X  int ret;
  793. X  ret=1;
  794. X  while(ret & 1){
  795. X    ret = reduceproduct(theunit,0) | reduceproduct(theunit,1);
  796. X    if (ret & 4) return 1;
  797. X  }
  798. X  return 0;
  799. X}
  800. X
  801. X
  802. Xint compareproducts(char **one,char **two)
  803. X{
  804. X  while(*one || *two){
  805. X    if (!*one && *two!=NULLUNIT) return 1;
  806. X    if (!*two && *one!=NULLUNIT) return 1;
  807. X    if (*one==NULLUNIT) one++;
  808. X    else if (*two==NULLUNIT) two++;
  809. X    else if (strcmp(*one,*two)) return 1;
  810. X    else one++,two++;
  811. X  }
  812. X  return 0;
  813. X}
  814. X
  815. X
  816. X/* Return zero if units are compatible, nonzero otherwise */
  817. X
  818. Xint compareunits(struct unittype *first, struct unittype *second)
  819. X{
  820. X  return 
  821. X    compareproducts(first->numerator,second->numerator) ||
  822. X    compareproducts(first->denominator,second->denominator);
  823. X}
  824. X
  825. X
  826. Xint completereduce(struct unittype *unit)
  827. X{
  828. X  if (reduceunit(unit)) return 1;
  829. X  sortunit(unit);
  830. X  cancelunit(unit);
  831. X  return 0;
  832. X}
  833. X
  834. X
  835. Xvoid showanswer(struct unittype *have, struct unittype *want)
  836. X{
  837. X  if (compareunits(have,want)) {
  838. X    printf("conformability error\n");
  839. X    showunit(have);
  840. X    showunit(want);
  841. X  }
  842. X  else printf("\t* %.8g\n\t/ %.8g\n",have->factor/want->factor,
  843. X                           want->factor/have->factor);
  844. X}
  845. X
  846. X
  847. Xvoid usage()
  848. X{
  849. X  fprintf(stderr,"\nunits [-f unitsfile] [-q] [-v] [from-unit to-unit]\n");
  850. X  fprintf(stderr,"\n    -f specify units file\n");
  851. X  fprintf(stderr,"    -q supress prompting (quiet)\n");
  852. X  fprintf(stderr,"    -v print version number\n");
  853. X  exit(3);
  854. X}
  855. X
  856. X
  857. Xvoid main(int argc, char **argv){
  858. X
  859. X  struct unittype have,want;
  860. X  char havestr[81],wantstr[81];
  861. X  char optchar;
  862. X  char *userfile=0;
  863. X  int quiet=0;
  864. X
  865. X  extern char *optarg;
  866. X  extern int optind;
  867. X
  868. X  while (EOF != (optchar = getopt(argc,argv,"vqf:"))) {
  869. X    switch(optchar) {
  870. X      case 'f':
  871. X        userfile=optarg;
  872. X        break;
  873. X      case 'q':
  874. X        quiet=1;
  875. X        break;
  876. X      case 'v':
  877. X        fprintf(stderr,"\n  units version %s  Copyright (c) 1993 by Adrian Mariano\n",VERSION);
  878. X        fprintf(stderr,"                    This program may be freely distributed\n");
  879. X        usage();
  880. X      default:
  881. X        usage();
  882. X        break;
  883. X     }
  884. X  }
  885. X    
  886. X  if (optind != argc-2 && optind!=argc) usage();
  887. X
  888. X  readunits(userfile);
  889. X
  890. X  if (optind==argc-2){
  891. X    strcpy(havestr,argv[optind]);
  892. X    strcpy(wantstr,argv[optind+1]);
  893. X    initializeunit(&have);
  894. X    addunit(&have,havestr,0);
  895. X    completereduce(&have);
  896. X    initializeunit(&want);
  897. X    addunit(&want,wantstr,0);
  898. X    completereduce(&want);
  899. X    showanswer(&have,&want);
  900. X  } else {
  901. X    if (!quiet) printf("%d units, %d prefixes\n\n",unitcount,prefixcount);
  902. X    for(;;){
  903. X      do{
  904. X        initializeunit(&have);
  905. X        if (!quiet) printf("You have: ");
  906. X        if (!fgets(havestr,80,stdin)) { if (!quiet);putchar('\n');exit(0);}
  907. X      } while(addunit(&have,havestr,0) || completereduce(&have));
  908. X      do{
  909. X        initializeunit(&want);
  910. X        if (!quiet) printf("You want: ");
  911. X        if (!fgets(wantstr,80,stdin)) {if (!quiet) putchar('\n');exit(0);}
  912. X      } while(addunit(&want,wantstr,0) || completereduce(&want));
  913. X      showanswer(&have,&want);
  914. X    }
  915. X  }
  916. X}
  917. X
  918. X
  919. X
  920. X
  921. END_OF_FILE
  922.   if test 13465 -ne `wc -c <'units.c'`; then
  923.     echo shar: \"'units.c'\" unpacked with wrong size!
  924.   fi
  925.   # end of 'units.c'
  926. fi
  927. if test -f 'units.doc' -a "${1}" != "-c" ; then 
  928.   echo shar: Will not clobber existing file \"'units.doc'\"
  929. else
  930.   echo shar: Extracting \"'units.doc'\" \(4315 characters\)
  931.   sed "s/^X//" >'units.doc' <<'END_OF_FILE'
  932. X
  933. X
  934. X
  935. X   14 July 1993                                                      UNITS(1)
  936. X
  937. X
  938. X
  939. X   NAME
  940. X     units - conversion program
  941. X
  942. X   SYNTAX
  943. X     units [-f filename] [-q] [to-unit from-unit]
  944. X
  945. X   SUMMARY
  946. X
  947. X     -f filename
  948. X         Specifies the name of the units data file to load.
  949. X
  950. X     -q  Supresses prompting of the user for units and the display of statis-
  951. X         tics about the number of units loaded.
  952. X
  953. X     from-unit to-unit
  954. X         Allows a single unit converstion to be done directly from the com-
  955. X         mand line.  No prompting will occur.  The units program will print
  956. X         out only the result of this single conversion.
  957. X
  958. X
  959. X   DESCRIPTION
  960. X     The units program converts quantities expression in various scales to
  961. X     their equivalents in other scales.  The units program can only handle
  962. X     multiplicative scale changes.  It cannot convert Centigrade to
  963. X     Fahrenheit, for example.  It works interactively by prompting the user
  964. X     for input:
  965. X
  966. X         You have: meters
  967. X         You want: feet
  968. X                 * 3.2808399
  969. X                 / 0.3048
  970. X
  971. X         You have: cm^3
  972. X         You want: gallons
  973. X                 * 0.00026417205
  974. X                 / 3785.4118
  975. X
  976. X     Powers of units can be specified using the '^' character as shown in the
  977. X     example, or by simple concatenation: 'cm3' is equivalent to 'cm^3'.
  978. X     Multiplication of units can be specified by using spaces, a dash or an
  979. X     asterisk.  Division of units is indicated by the slash ('/'). Note that
  980. X     multiplication has a higher precedence than division, so If the user
  981. X     enters incompatible unit types, the units program will print a message
  982. X     indicating that the units are not conformable and it will display the
  983. X     reduced form for each unit:
  984. X
  985. X         You have: ergs/hour
  986. X         You want: fathoms kg^2 / day
  987. X         conformability error
  988. X                 2.7777778e-11 kg m^2 / sec^3
  989. X                 2.1166667e-05 kg^2 m / sec
  990. X
  991. X
  992. X
  993. X
  994. X                                                                            1
  995. X
  996. X
  997. X
  998. X
  999. X
  1000. X
  1001. X   UNITS(1)                                                      14 July 1993
  1002. X
  1003. X
  1004. X     The conversion information is read from a units data file.  The default
  1005. X     file includes definitions for most familiar units, abbreviations and
  1006. X     metric prefixes.  Some constants of nature included are:
  1007. X
  1008. X         pi       ratio of circumference to diameter
  1009. X         c        speed of light
  1010. X         e        charge on an electron
  1011. X         g        acceleration of gravity
  1012. X         force    same as g
  1013. X         mole     Avogadro's number
  1014. X         water    pressure per unit height of water
  1015. X         mercury  pressure per unit height of mercury
  1016. X         au       astronomical unit
  1017. X
  1018. X     'Pound' is a unit of mass.  Compound names are run together so 'pound-
  1019. X     force' is a unit of force.  British units that differ from their US
  1020. X     counterparts are prefixed with 'br', and currency is prefixed with its
  1021. X     country name: 'belgiumfranc', 'britainpound'.  When searching for a
  1022. X     unit, if the specified string does not appear exactly as a unit name,
  1023. X     then the units program will try to remove a trailing 's' or a trailing
  1024. X     'es' and check again for a match.
  1025. X
  1026. X     All of these definitions can be read in the standard units file, or you
  1027. X     can supply your own file.  A unit is specified on a single line by giv-
  1028. X     ing its name and an equivalence.  One should be careful to define new
  1029. X     units in terms of old ones so that a reduction leads to the primitive
  1030. X     units which are marked with '!' characters. The units program will not
  1031. X     detect infinite loops that could be caused by careless unit definitions.
  1032. X
  1033. X     Prefixes are defined in the same was as standard units, but with a
  1034. X     trailing dash at the end of the prefix name.
  1035. X
  1036. X   BUGS
  1037. X
  1038. X     The effect of including a '/' in a prefix is surprising.
  1039. X
  1040. X     Exponents entered by the user can be only one digit.
  1041. X
  1042. X     The user must use | to indicate division of numbers and / to indicate
  1043. X     division of symbols.  This distinction should not be necessary.
  1044. X
  1045. X     The program contains various arbitrary limits on the length of the units
  1046. X     converted and on the length of the data file.
  1047. X
  1048. X   FILES
  1049. X     units.lib - the standard units library
  1050. X
  1051. X   AUTHOR
  1052. X     Adrian Mariano (adrian@u.washington.edu or mariano@geom.umn.edu)
  1053. X
  1054. X
  1055. X
  1056. X
  1057. X
  1058. X
  1059. X
  1060. X   2
  1061. X
  1062. X
  1063. X
  1064. END_OF_FILE
  1065.   if test 4315 -ne `wc -c <'units.doc'`; then
  1066.     echo shar: \"'units.doc'\" unpacked with wrong size!
  1067.   fi
  1068.   # end of 'units.doc'
  1069. fi
  1070. if test -f 'units.lib' -a "${1}" != "-c" ; then 
  1071.   echo shar: Will not clobber existing file \"'units.lib'\"
  1072. else
  1073.   echo shar: Extracting \"'units.lib'\" \(10159 characters\)
  1074.   sed "s/^X//" >'units.lib' <<'END_OF_FILE'
  1075. X/ primitive units
  1076. X
  1077. Xm            !a!
  1078. Xkg            !b!
  1079. Xsec            !c!
  1080. Xcoul            !d!
  1081. Xcandela            !e!
  1082. Xdollar            !f!
  1083. Xbit            !h!
  1084. Xerlang            !i!
  1085. XK            !j!
  1086. X
  1087. X/ prefixes
  1088. X
  1089. Xyotta-            1e24
  1090. Xzetta-            1e21
  1091. Xexa-            1e18
  1092. Xpeta-            1e15
  1093. Xtera-            1e12
  1094. Xgiga-            1e9
  1095. Xmega-            1e6
  1096. Xmyria-            1e4
  1097. Xkilo-            1e3
  1098. Xhecto-            1e2
  1099. Xdeka-            1e1
  1100. Xdeci-            1e-1
  1101. Xcenti-            1e-2
  1102. Xmilli-            1e-3
  1103. Xmicro-            1e-6
  1104. Xnano-            1e-9
  1105. Xpico-            1e-12
  1106. Xfemto-            1e-15
  1107. Xatto-            1e-18
  1108. Xzopto-            1e-21
  1109. Xyocto-            1e-24
  1110. X
  1111. Xsemi-            .5
  1112. Xdemi-            .5
  1113. X
  1114. XY-            yotta
  1115. XZ-            zetta
  1116. XE-            exa
  1117. XP-            peta
  1118. XT-            tera
  1119. XG-            giga
  1120. XM-            mega
  1121. Xk-            kilo
  1122. Xh-            hecto
  1123. Xda-            deka
  1124. Xd-            deci
  1125. Xc-            centi
  1126. Xm-            milli
  1127. Xp-            pico
  1128. Xf-            femto
  1129. Xa-            atto
  1130. Xz-            zopto
  1131. Xy-            yocto
  1132. X
  1133. X/ constants
  1134. X
  1135. Xfuzz            1
  1136. Xpi            3.14159265358979323846
  1137. Xc            2.99792458e+8 m/sec fuzz
  1138. Xg            9.80665 m/sec2
  1139. Xau            1.49597871e+11 m fuzz
  1140. Xmole            6.022169e+23 fuzz
  1141. Xe            1.6021917e-19 coul fuzz
  1142. Xenergy            c2
  1143. Xforce            g
  1144. Xmercury            1.33322e+5 kg/m2-sec2
  1145. Xhg            mercury
  1146. X
  1147. X/ dimensionless
  1148. X
  1149. Xradian            .5 / pi
  1150. Xdegree            1|180 pi-radian
  1151. Xcircle            2 pi-radian
  1152. Xturn            2 pi-radian
  1153. Xrevolution            turn
  1154. Xrev            turn
  1155. Xgrade            .9 degree
  1156. Xarcdeg            1 degree
  1157. Xarcmin            1|60 arcdeg
  1158. Xccs            1|36 erlang
  1159. Xarcsec            1|60 arcmin
  1160. X
  1161. Xsteradian        radian2
  1162. Xsphere            4 pi-steradian
  1163. Xsr            steradian
  1164. X
  1165. X/ Time
  1166. X
  1167. Xsecond            sec
  1168. Xs            sec
  1169. Xminute            60 sec
  1170. Xmin            minute
  1171. Xhour            60 min
  1172. Xhr            hour
  1173. Xday            24 hr
  1174. Xda            day
  1175. Xweek            7 day
  1176. Xyear            365.24219879 day fuzz
  1177. Xyr            year
  1178. Xmonth            1|12 year
  1179. Xms            millisec
  1180. Xus            microsec
  1181. X
  1182. X/ Mass
  1183. X
  1184. Xgram            millikg
  1185. Xgm            gram
  1186. Xmg            milligram
  1187. Xmetricton        kilokg
  1188. X
  1189. X/ Avoirdupois
  1190. X
  1191. Xlb            .45359237 kg
  1192. Xpound            lb
  1193. Xlbf            lb g
  1194. Xounce            1|16 lb
  1195. Xoz            ounce
  1196. Xdram            1|16 oz
  1197. Xdr            dram
  1198. Xgrain            1|7000 lb
  1199. Xgr            grain
  1200. Xshortton        2000 lb
  1201. Xton            shortton
  1202. Xlongton            2240 lb
  1203. X
  1204. X/ Apothecary
  1205. X
  1206. Xscruple            20 grain
  1207. Xapdram            60 grain
  1208. Xapounce            480 grain
  1209. Xappound            5760 grain
  1210. Xtroypound        appound
  1211. X
  1212. X/ Length
  1213. X
  1214. Xmeter            m
  1215. Xcm            centimeter
  1216. Xmm            millimeter
  1217. Xkm            kilometer
  1218. Xnm            nanometer
  1219. Xmicron            micrometer
  1220. Xangstrom        decinanometer
  1221. X
  1222. Xinch            2.54 cm
  1223. Xin            inch
  1224. Xfoot            12 in
  1225. Xfeet            foot
  1226. Xft            foot
  1227. Xyard            3 ft
  1228. Xyd            yard
  1229. Xrod            5.5 yd
  1230. Xrd            rod
  1231. Xmile            5280 ft
  1232. Xmi            mile
  1233. X
  1234. Xbritish            1200|3937 m/ft
  1235. Xnmile            1852m
  1236. X
  1237. Xacre            4840 yd2
  1238. X
  1239. Xcc            cm3
  1240. Xliter            kilocc
  1241. Xml            milliliter
  1242. X
  1243. X/ US Liquid
  1244. X
  1245. Xgallon            231 in3
  1246. Ximperial        1.20095
  1247. Xgal            gallon
  1248. Xquart            1|4 gal
  1249. Xqt            quart
  1250. Xpint            1|2 qt
  1251. Xpt            pint
  1252. X
  1253. Xfloz            1|16 pt
  1254. Xfldr            1|8 floz
  1255. X
  1256. X/ US Dry
  1257. X
  1258. Xdry            268.8025 in3/gallon fuzz
  1259. Xpeck            8 dry-quart
  1260. Xpk            peck
  1261. Xbushel            4 peck
  1262. Xbu            bushel
  1263. Xchaldron        36 bushel
  1264. X
  1265. X/ British
  1266. X
  1267. Xbrgallon        277.420 in3 fuzz
  1268. Xbrquart            1|4 brgallon
  1269. Xbrpint            1|2 brquart
  1270. Xbrfloz            1|20 brpint
  1271. Xbrpeck            554.84 in3 fuzz
  1272. Xbrbushel        4 brpeck
  1273. X
  1274. X/ Energy Work
  1275. X
  1276. Xnewton            kg-m/sec2
  1277. Xnt            newton
  1278. XN            newton
  1279. Xjoule            nt-m
  1280. Xcal            4.1868 joule
  1281. X
  1282. X/ Electrical
  1283. X
  1284. Xcoulomb            coul
  1285. XC            coul
  1286. Xampere            coul/sec
  1287. Xamp            ampere
  1288. Xwatt            joule/sec
  1289. Xvolt            watt/amp
  1290. Xohm            volt/amp
  1291. Xmho            /ohm
  1292. Xfarad            coul/volt
  1293. Xhenry            sec2/farad
  1294. Xweber            volt-sec
  1295. X
  1296. X/ Light
  1297. X
  1298. Xcd            candela
  1299. Xlumen            cd sr
  1300. Xlux            cd sr/m2
  1301. X
  1302. X/ Wall Street Journal, July 2, 1993
  1303. X
  1304. X$            dollar
  1305. Xargentinapeso        $
  1306. Xaustraliadollar        .66 $
  1307. Xaustriaschilling    .83 $
  1308. Xbahraindinar        2.6522 $
  1309. Xbelgiumfranc        .028 $
  1310. Xbrazilcruzeiro        .000019 $
  1311. Xbritainpound        1.49 $
  1312. Xcanadadollar        .77 $
  1313. Xczechkoruna        .034 $
  1314. Xchilepeso        .0025 $
  1315. Xchinarenminbi        .174856 $
  1316. Xcolombiapeso        .001495 $
  1317. Xdenmarkkrone        .15 $
  1318. Xecuadorsucre        .000539 $
  1319. Xfinlandmarkka        .17 $
  1320. Xfrancefranc        .17 $
  1321. Xgermanymark        .58 $
  1322. Xgreatbritainpound    britainpound
  1323. Xgreecedrachma        .0043 $
  1324. Xhongkongdollar        .13  $
  1325. Xhungaryforint        .011 $
  1326. Xindiarupee        .03211 $
  1327. Xindonesiarupiah        .0004782 $
  1328. Xirelandpunt        1.43 $
  1329. Xisraelshekel        .3642 $
  1330. Xitalylira        .00064 $
  1331. Xjapanyen        .0093 $
  1332. Xjordandinar        1.4682 $
  1333. Xkuwaitdinar        3.3173 $
  1334. Xlebanonpound        .000578 $
  1335. Xmalaysiaringgit        .338 $
  1336. Xmaltalira        2.6042 $
  1337. Xmexicopeso        .3205128 $
  1338. Xnetherlandguilder    .52 $
  1339. Xnewzealanddollar    .539 $
  1340. Xnorwaykrone        .139 $
  1341. Xpakistanrupee        .037 $
  1342. Xperunewsol        .5065 $
  1343. Xphilippinespeso        .03738 $
  1344. Xpolandzloty        .000059 $
  1345. Xportugalescudo        .00617 $
  1346. Xsaudiarabiariyal    .26702 $
  1347. Xsingaporedollar        .6157 $
  1348. Xslovakkoruna        .034 $
  1349. Xsouthamericarand    .21 $
  1350. Xsouthkoreawon        .001 $
  1351. Xspainpeseta        .007 $
  1352. Xswedenkrona        .13 $
  1353. Xswitzerlandfranc    .66 $
  1354. Xtaiwandollar        .038285 $
  1355. Xthailandbaht        .03962 $
  1356. Xturkeylira        .0000929 $
  1357. Xunitedarabdirham    .2723 $
  1358. Xuruguaynewpeso        .246852 $
  1359. Xvenezuelabolivar    .011 $
  1360. X
  1361. Xmark            germanymark
  1362. Xbolivar            venezuelabolivar
  1363. Xpeseta            spainpeseta
  1364. Xrand            southafricarand
  1365. Xescudo            portugalescudo
  1366. Xsol            perusol
  1367. Xguilder            netherlandsguilder
  1368. Xhollandguilder        netherlandsguilder
  1369. Xpeso            mexicopeso
  1370. Xyen            japanyen
  1371. Xlira            italylira
  1372. Xrupee            indiarupee
  1373. Xdrachma            greecedrachma
  1374. Xfranc            francefranc
  1375. Xmarkka            finlandmarkka
  1376. Xsucre            ecuadorsucre
  1377. Xpoundsterling        britainpound
  1378. Xcruzeiro        brazilcruzeiro
  1379. X
  1380. X/ computer
  1381. X
  1382. Xbaud            bit/sec
  1383. Xbyte            8 bit
  1384. Xblock            512 byte
  1385. Xkbyte            1024 byte
  1386. Xmegabyte        1024 kbyte
  1387. Xgigabyte        1024 megabyte
  1388. Xmeg            megabyte
  1389. X
  1390. X
  1391. X/ Trivia
  1392. X
  1393. X%            1|100
  1394. Xadmiraltyknot        6080 ft/hr
  1395. Xapostilb        cd/pi-m2
  1396. Xare            1e+2 m2
  1397. Xarpentcan        27.52 mi
  1398. Xarpentlin        191.835 ft
  1399. Xastronomicalunit    au
  1400. Xatmosphere        1.01325e+5 nt/m2
  1401. Xatm            atmosphere
  1402. Xatomicmassunit        1.66044e-27 kg fuzz
  1403. Xamu            atomicmassunit
  1404. Xbag            94 lb
  1405. Xbakersdozen        13
  1406. Xbar            1e+5 nt/m2
  1407. Xbarie            1e-1 nt/m2
  1408. Xbarleycorn        1|3 in
  1409. Xbarn            1e-28 m2
  1410. Xbarrel            42 gal
  1411. Xbarye            1e-1 nt/m2
  1412. Xbev            1e+9 e-volt
  1413. Xbiot            10 amp
  1414. Xblondel            cd/pi-m2
  1415. Xboardfoot        144 in3
  1416. Xbolt            40 yd
  1417. Xbottommeasure        1|40 in
  1418. Xbritishthermalunit    1.05506e+3 joule fuzz
  1419. Xbtu            britishthermalunit
  1420. Xrefrigeration        12000 btu/ton-hour
  1421. Xbuck            dollar
  1422. Xcable            720 ft
  1423. Xcaliber            1e-2 in
  1424. Xcalorie            cal
  1425. Xcarat            205 mg
  1426. Xcaratgold        1|24
  1427. Xcent            centidollar
  1428. Xcental            100 lb
  1429. Xcentesimalminute    1e-2 grade
  1430. Xcentesimalsecond    1e-4 grade
  1431. Xcentury            100 year
  1432. Xcfs            ft3/sec
  1433. Xchain            66 ft
  1434. Xcircularinch        1|4 pi-in2
  1435. Xcircularmil        1e-6|4 pi-in2
  1436. Xclusec            1e-8 mm-hg m3/s
  1437. Xcoomb            4 bu
  1438. Xcord            128 ft3
  1439. Xcordfoot        cord
  1440. Xcrith            9.06e-2 gm
  1441. Xcubit            18 in
  1442. Xcup            1|2 pt
  1443. Xcurie            3.7e+10 /sec
  1444. Xdalton            amu
  1445. Xdecade            10 yr
  1446. Xdipotre            /m
  1447. Xdisplacementton        35 ft3
  1448. Xdoppelzentner        100 kg
  1449. Xdozen            12
  1450. Xdrop            .03 cm3
  1451. Xdyne            cm-gm/sec2
  1452. Xelectronvolt        e-volt
  1453. Xell            45 in
  1454. Xengineerschain        100 ft
  1455. Xengineerslink        100|100 ft
  1456. Xequivalentfootcandle    lumen/pi-ft2
  1457. Xequivalentlux        lumen/pi-m2
  1458. Xequivalentphot        cd/pi-cm2
  1459. Xerg            cm2-gm/sec2
  1460. Xev            e-volt
  1461. Xfaraday            9.652e+4 coul
  1462. Xfathom            6 ft
  1463. Xfermi            1e-15 m
  1464. Xfifth            4|5 qt
  1465. Xfin            5 dollar
  1466. Xfinger            7|8 in
  1467. Xfirkin            9 gal
  1468. Xfootcandle        lumen/ft2
  1469. Xfootlambert        cd/pi-ft2
  1470. Xfortnight        14 da
  1471. Xfranklin        3.33564e-10 coul
  1472. Xfrigorie        kilocal
  1473. Xfurlong            220 yd
  1474. Xgalileo            1e-2 m/sec2
  1475. Xgamma            1e-9 weber/m2
  1476. Xgauss            1e-4 weber/m2
  1477. Xgeodeticfoot        british-ft
  1478. Xgeographicalmile    1852 m
  1479. Xgilbert            7.95775e-1 amp
  1480. Xgill            1|4 pt
  1481. Xgross            144
  1482. Xgunterschain        22 yd
  1483. Xhand            4 in
  1484. Xhectare            1e+4 m2
  1485. Xhefnercandle        .92 cd
  1486. Xhertz            /sec
  1487. XHz            hertz
  1488. Xhogshead        2 barrel
  1489. Xhd            hogshead
  1490. Xhomestead        1|4 mi2
  1491. Xhorsepower        550 ft-lb-g/sec
  1492. Xhp            horsepower
  1493. Xhyl            gm force sec2/m
  1494. Xhz            /sec
  1495. Ximaginarycubicfoot    1.4 ft3
  1496. Xjeroboam        4|5 gal
  1497. Xkarat            1|24
  1498. Xkcal            kilocal
  1499. Xkcalorie        kilocal
  1500. Xkev            1e+3 e-volt
  1501. Xkey            kg
  1502. Xkhz            1e+3 /sec
  1503. Xkilderkin        18 gal
  1504. Xknot            nmile/hr
  1505. Xlambert            cd/pi-cm2
  1506. Xlangley            cal/cm2
  1507. Xlast            80 bu
  1508. Xleague            3 mi
  1509. Xlightyear        c-yr
  1510. Xline            1|12 in
  1511. Xlink            66|100 ft
  1512. Xlonghundredweight    112 lb
  1513. Xlongquarter        28 lb
  1514. Xlusec            1e-6 mm-hg m3/s
  1515. Xmach            331.46 m/sec
  1516. Xmagnum            2 qt
  1517. Xmarineleague        3 nmile
  1518. Xmaxwell            1e-8 weber
  1519. Xmetriccarat        200 mg
  1520. Xmgd            megagal/day
  1521. Xmh            millihenry
  1522. Xmhz            1e+6 /sec
  1523. Xmil            1e-3 in
  1524. Xmillenium        1000 year
  1525. Xminersinch        1.5 ft3/min
  1526. Xminim            1|60 fldr
  1527. Xmo            month
  1528. Xmpg            mile/gal
  1529. Xmph            mile/hr
  1530. Xnail            1|16 yd
  1531. Xnauticalmile        nmile
  1532. Xnit            cd/m2
  1533. Xnoggin            1|8 qt
  1534. Xnox            1e-3 lux
  1535. Xns            nanosec
  1536. Xoersted            2.5e+2 pi-amp/m
  1537. Xoe            oersted
  1538. Xpace            36 in
  1539. Xpalm            3 in
  1540. Xparasang        3.5 mi
  1541. Xparsec            au-radian/arcsec
  1542. Xpascal            nt/m2
  1543. Xpc            parsec
  1544. Xpennyweight        1|20 oz
  1545. Xpwt            pennyweight
  1546. Xpercent            %
  1547. Xperch            rd
  1548. Xpf            picofarad
  1549. Xphot            lumen/cm2
  1550. Xpica            1|6 in
  1551. Xpieze            1e+3 nt/m2
  1552. Xpipe            4 barrel
  1553. Xpoint            1|72 in
  1554. Xpoise            gm/cm-sec
  1555. Xpole            rd
  1556. Xpoundal            ft-lb/sec2
  1557. Xpdl            poundal
  1558. Xproof            1|200
  1559. Xpsi            lb-g/in2
  1560. Xquarter            9 in
  1561. Xquartersection        1|4 mi2
  1562. Xquintal            100 kg
  1563. Xquire            25
  1564. Xrad            100 erg/gm
  1565. Xream            500
  1566. Xregisterton        100 ft3
  1567. Xrehoboam        156 floz
  1568. Xrhe            10 m2/nt-sec
  1569. Xrontgen            2.58e-4 curie/kg
  1570. Xrood            1.21e+3 yd
  1571. Xrope            20 ft
  1572. Xrutherford        1e+6 /sec
  1573. Xrydberg            1.36054e+1 ev
  1574. Xsabin            1 ft2
  1575. Xsack            3 bu
  1576. Xseam            8 bu
  1577. Xsection            mi2
  1578. Xshippington        40 ft3
  1579. Xshorthundredweight    100 lb
  1580. Xshortquarter        25 lb
  1581. Xsiemens            /ohm
  1582. Xsigma            microsec
  1583. Xskein            120 yd
  1584. Xskot            1e-3 apostilb
  1585. Xslug            lb-g-sec2/ft
  1586. Xspan            9 in
  1587. Xspat            4 pi sr
  1588. Xspindle            14400 yd
  1589. Xsquare            100 ft2
  1590. Xstere            m3
  1591. Xsthene            1e+3 nt
  1592. Xstilb            cd/cm2
  1593. Xstoke            1e-4 m2/sec
  1594. Xstone            14 lb
  1595. Xstrike            2 bu
  1596. Xsurveyfoot        british-ft
  1597. Xsurveyyard        3 surveyfoot
  1598. Xsurveyorschain        66 ft
  1599. Xsurveyorslink        66|100 ft
  1600. Xtablespoon        4 fldr
  1601. Xteaspoon        4|3 fldr
  1602. Xtesla            weber/m2
  1603. Xtherm            1e+5 btu
  1604. Xthermie            1e+6 cal
  1605. Xtimberfoot        ft3
  1606. Xtnt            4.6e+6 m2/sec2
  1607. Xtonne            1e+6 gm
  1608. Xtorr            mm hg
  1609. Xtownship        36 mi2
  1610. Xtun            8 barrel
  1611. Xwater            gram g / cc
  1612. Xwey            40 bu
  1613. Xweymass            252 lb
  1614. XXunit            1.00202e-13m
  1615. Xk            1.38047e-16 erg/degC
  1616. X
  1617. X
  1618. XdegC            K
  1619. Xkelvin            K
  1620. Xbrewster        1e-12 m2/newton
  1621. XdegF            5|9 degC
  1622. Xdegreesrankine        degF
  1623. Xdegrankine        degreesrankine
  1624. Xdegreerankine        degF
  1625. Xdegreaumur        10|8 degC
  1626. Xdrachm            60 grain
  1627. Xponcelet        100 kg m g / sec
  1628. Xdenier            .05|450 gram / m
  1629. Xtex            .001 gram / m
  1630. Xenglishell        45 inch
  1631. Xscottishell        37.2 inch
  1632. Xflemishell        27 inch
  1633. Xplanck            6.626e-34 joule-sec
  1634. Xhbar            1.055e-34 joule-sec
  1635. Xelectronmass        9.1095e-31 kg
  1636. Xprotonmass        1.6726e-27 kg
  1637. Xneutronmass        1.6606e-27 kg
  1638. XV            volt
  1639. XeV            e V
  1640. Xbohrradius        hbar2-C2/8.988e9 N m2-e2-electronmass
  1641. Xbecquerel        1|3.7e10 curie
  1642. Xfresnel            1e12 hertz
  1643. Xstatcoul        1|2.99792458e9 coul
  1644. Xstatamp            1|2.99792458e9 amp
  1645. Xstatvolt        2.99792458e2 volt
  1646. Xstatcoulomb        statcoul
  1647. Xstatampere        statamp
  1648. Xdebye            3.336e-30 coul-m
  1649. Xpulsatance        2 pi/sec
  1650. Xrpm            rev/minute
  1651. Xrps            rev/sec
  1652. Xkilohm            kiloohm
  1653. Xmegohm            megaohm
  1654. Xsiderealyear        365.256360417 day
  1655. Xsiderealday        23.934469444 hour
  1656. Xsiderealhour        1|24 sidereal day
  1657. Xlunarmonth        29.5305555 day
  1658. Xsynodicmonth        lunarmonth
  1659. Xsiderealmonth        27.32152777 day
  1660. Xtropicalyear        year
  1661. Xsolaryear        year
  1662. Xlunaryear        12 lunarmonth
  1663. Xcran            37.5 brgallon
  1664. Xkip            1000 lbf
  1665. Xfrenchfoot        16|15 ft
  1666. Xfrenchfeet        frenchfoot
  1667. Xtoise            6 frenchfeet
  1668. Xsievert            8.4 rontgen
  1669. Xcandle            1.02 candela
  1670. Xmilitarypace        2.5 feet
  1671. Xmetre            meter
  1672. Xlitre            liter
  1673. Xgramme            gram
  1674. Xiudiptheria        62.8 microgram
  1675. Xiupenicillin        .6 microgram
  1676. Xiuinsulin        41.67 microgram
  1677. Xcottonyarncount        2520 ft/pound
  1678. Xlinenyarncount        900 ft/pound
  1679. Xworstedyarncount    1680 ft/pound
  1680. Xmetricyarncount        meter/gram
  1681. Xjewlerspoint        2 milligram
  1682. X
  1683. END_OF_FILE
  1684.   if test 10159 -ne `wc -c <'units.lib'`; then
  1685.     echo shar: \"'units.lib'\" unpacked with wrong size!
  1686.   fi
  1687.   # end of 'units.lib'
  1688. fi
  1689. echo shar: End of archive 1 \(of 1\).
  1690. cp /dev/null ark1isdone
  1691. MISSING=""
  1692. for I in 1 ; do
  1693.     if test ! -f ark${I}isdone ; then
  1694.     MISSING="${MISSING} ${I}"
  1695.     fi
  1696. done
  1697. if test "${MISSING}" = "" ; then
  1698.     echo You have the archive.
  1699.     rm -f ark[1-9]isdone
  1700. else
  1701.     echo You still must unpack the following archives:
  1702.     echo "        " ${MISSING}
  1703. fi
  1704. exit 0
  1705. exit 0 # Just in case...
  1706.