home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- #define NDIM 10
- #define NTAB 601
- char *dfile = "/usr/lib/units";
- char *unames[NDIM];
- double getflt();
- int fperr();
- struct table *hash();
- struct unit
- {
- double factor;
- char dim[NDIM];
- };
-
- struct table
- {
- double factor;
- char dim[NDIM];
- char *name;
- } table[NTAB];
- char names[NTAB*10];
- struct prefix
- {
- double factor;
- char *pname;
- } prefix[] =
- {
- 1e-18, "atto",
- 1e-15, "femto",
- 1e-12, "pico",
- 1e-9, "nano",
- 1e-6, "micro",
- 1e-3, "milli",
- 1e-2, "centi",
- 1e-1, "deci",
- 1e1, "deka",
- 1e2, "hecta",
- 1e2, "hecto",
- 1e3, "kilo",
- 1e6, "mega",
- 1e6, "meg",
- 1e9, "giga",
- 1e12, "tera",
- 0.0, 0
- };
- FILE *inp;
- int fperrc;
- int peekc;
- int dumpflg;
-
- main(argc, argv)
- char *argv[];
- {
- register i;
- register char *file;
- struct unit u1, u2;
- double f;
-
- if(argc>1 && *argv[1]=='-') {
- argc--;
- argv++;
- dumpflg++;
- }
- file = dfile;
- if(argc > 1)
- file = argv[1];
- if ((inp = fopen(file, "r")) == NULL) {
- printf("no table\n");
- exit(1);
- }
- signal(8, fperr);
- init();
-
- loop:
- fperrc = 0;
- printf("you have: ");
- if(convr(&u1))
- goto loop;
- if(fperrc)
- goto fp;
- loop1:
- printf("you want: ");
- if(convr(&u2))
- goto loop1;
- for(i=0; i<NDIM; i++)
- if(u1.dim[i] != u2.dim[i])
- goto conform;
- f = u1.factor/u2.factor;
- if(fperrc)
- goto fp;
- printf("\t* %e\n", f);
- printf("\t/ %e\n", 1./f);
- goto loop;
-
- conform:
- if(fperrc)
- goto fp;
- printf("conformability\n");
- units(&u1);
- units(&u2);
- goto loop;
-
- fp:
- printf("underflow or overflow\n");
- goto loop;
- }
-
- units(up)
- struct unit *up;
- {
- register struct unit *p;
- register f, i;
-
- p = up;
- printf("\t%e ", p->factor);
- f = 0;
- for(i=0; i<NDIM; i++)
- f |= pu(p->dim[i], i, f);
- if(f&1) {
- putchar('/');
- f = 0;
- for(i=0; i<NDIM; i++)
- f |= pu(-p->dim[i], i, f);
- }
- putchar('\n');
- }
-
- pu(u, i, f)
- {
-
- if(u > 0) {
- if(f&2)
- putchar('-');
- if(unames[i])
- printf("%s", unames[i]); else
- printf("*%c*", i+'a');
- if(u > 1)
- putchar(u+'0');
- return(2);
- }
- if(u < 0)
- return(1);
- return(0);
- }
-
- convr(up)
- struct unit *up;
- {
- register struct unit *p;
- register c;
- register char *cp;
- char name[20];
- int den, err;
-
- p = up;
- for(c=0; c<NDIM; c++)
- p->dim[c] = 0;
- p->factor = getflt();
- if(p->factor == 0.)
- p->factor = 1.0;
- err = 0;
- den = 0;
- cp = name;
-
- loop:
- switch(c=get()) {
-
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- case '/':
- case ' ':
- case '\t':
- case '\n':
- if(cp != name) {
- *cp++ = 0;
- cp = name;
- err |= lookup(cp, p, den, c);
- }
- if(c == '/')
- den++;
- if(c == '\n')
- return(err);
- goto loop;
- }
- *cp++ = c;
- goto loop;
- }
-
- lookup(name, up, den, c)
- char *name;
- struct unit *up;
- {
- register struct unit *p;
- register struct table *q;
- register i;
- char *cp1, *cp2;
- double e;
-
- p = up;
- e = 1.0;
-
- loop:
- q = hash(name);
- if(q->name) {
- l1:
- if(den) {
- p->factor /= q->factor*e;
- for(i=0; i<NDIM; i++)
- p->dim[i] -= q->dim[i];
- } else {
- p->factor *= q->factor*e;
- for(i=0; i<NDIM; i++)
- p->dim[i] += q->dim[i];
- }
- if(c >= '2' && c <= '9') {
- c--;
- goto l1;
- }
- return(0);
- }
- for(i=0; cp1 = prefix[i].pname; i++) {
- cp2 = name;
- while(*cp1 == *cp2++)
- if(*cp1++ == 0) {
- cp1--;
- break;
- }
- if(*cp1 == 0) {
- e *= prefix[i].factor;
- name = cp2-1;
- goto loop;
- }
- }
- for(cp1 = name; *cp1; cp1++);
- if(cp1 > name+1 && *--cp1 == 's') {
- *cp1 = 0;
- goto loop;
- }
- printf("cannot recognize %s\n", name);
- return(1);
- }
-
- equal(s1, s2)
- char *s1, *s2;
- {
- register char *c1, *c2;
-
- c1 = s1;
- c2 = s2;
- while(*c1++ == *c2)
- if(*c2++ == 0)
- return(1);
- return(0);
- }
-
- init()
- {
- register char *cp;
- register struct table *tp, *lp;
- int c, i, f, t;
- char *np;
-
- cp = names;
- for(i=0; i<NDIM; i++) {
- np = cp;
- *cp++ = '*';
- *cp++ = i+'a';
- *cp++ = '*';
- *cp++ = 0;
- lp = hash(np);
- lp->name = np;
- lp->factor = 1.0;
- lp->dim[i] = 1;
- }
- lp = hash("");
- lp->name = cp-1;
- lp->factor = 1.0;
-
- l0:
- c = get();
- if(c == 0) {
- printf("%l units; %l bytes\n\n", i, cp-names);
- if(dumpflg)
- for(tp = &table[0]; tp < &table[NTAB]; tp++) {
- if(tp->name == 0)
- continue;
- printf("%s", tp->name);
- units(tp);
- }
- fclose(inp);
- inp = stdin;
- return;
- }
- if(c == '/') {
- while(c != '\n' && c != 0)
- c = get();
- goto l0;
- }
- if(c == '\n')
- goto l0;
- np = cp;
- while(c != ' ' && c != '\t') {
- *cp++ = c;
- c = get();
- if (c==0)
- goto l0;
- if(c == '\n') {
- *cp++ = 0;
- tp = hash(np);
- if(tp->name)
- goto redef;
- tp->name = np;
- tp->factor = lp->factor;
- for(c=0; c<NDIM; c++)
- tp->dim[c] = lp->dim[c];
- i++;
- goto l0;
- }
- }
- *cp++ = 0;
- lp = hash(np);
- if(lp->name)
- goto redef;
- convr(lp);
- lp->name = np;
- f = 0;
- i++;
- if(lp->factor != 1.0)
- goto l0;
- for(c=0; c<NDIM; c++) {
- t = lp->dim[c];
- if(t>1 || (f>0 && t!=0))
- goto l0;
- if(f==0 && t==1) {
- if(unames[c])
- goto l0;
- f = c+1;
- }
- }
- if(f>0)
- unames[f-1] = np;
- goto l0;
-
- redef:
- printf("redefinition %s\n", np);
- goto l0;
- }
-
- double
- getflt()
- {
- register c, i, dp;
- double d, e;
- int f;
-
- d = 0.;
- dp = 0;
- do
- c = get();
- while(c == ' ' || c == '\t');
-
- l1:
- if(c >= '0' && c <= '9') {
- d = d*10. + c-'0';
- if(dp)
- dp++;
- c = get();
- goto l1;
- }
- if(c == '.') {
- dp++;
- c = get();
- goto l1;
- }
- if(dp)
- dp--;
- if(c == '+' || c == '-') {
- f = 0;
- if(c == '-')
- f++;
- i = 0;
- c = get();
- while(c >= '0' && c <= '9') {
- i = i*10 + c-'0';
- c = get();
- }
- if(f)
- i = -i;
- dp -= i;
- }
- e = 1.;
- i = dp;
- if(i < 0)
- i = -i;
- while(i--)
- e *= 10.;
- if(dp < 0)
- d *= e; else
- d /= e;
- if(c == '|')
- return(d/getflt());
- peekc = c;
- return(d);
- }
-
- get()
- {
- register c;
-
- if(c=peekc) {
- peekc = 0;
- return(c);
- }
- c = getc(inp);
- if (c == EOF) {
- if (inp == stdin) {
- printf("\n");
- exit(0);
- }
- return(0);
- }
- return(c);
- }
-
- struct table *
- hash(name)
- char *name;
- {
- register struct table *tp;
- register char *np;
- register unsigned h;
-
- h = 0;
- np = name;
- while(*np)
- h = h*57 + *np++ - '0';
- h %= NTAB;
- tp = &table[h];
- l0:
- if(tp->name == 0)
- return(tp);
- if(equal(name, tp->name))
- return(tp);
- tp++;
- if(tp >= &table[NTAB])
- tp = table;
- goto l0;
- }
-
- fperr()
- {
-
- signal(8, fperr);
- fperrc++;
- }
-