1*48325Sbostic /*-
2*48325Sbostic * %sccs.include.proprietary.c%
3*48325Sbostic */
4*48325Sbostic
5*48325Sbostic #ifndef lint
6*48325Sbostic static char sccsid[] = "@(#)units.c 4.3 (Berkeley) 04/18/91";
7*48325Sbostic #endif /* not lint */
8*48325Sbostic
91147Sbill #include <stdio.h>
1037910Sbostic #include "pathnames.h"
111147Sbill
121147Sbill #define NDIM 10
131147Sbill #define NTAB 601
1437910Sbostic char *dfile = _PATH_UNITS;
151147Sbill char *unames[NDIM];
161147Sbill double getflt();
171147Sbill int fperr();
181147Sbill struct table *hash();
191147Sbill struct unit
201147Sbill {
211147Sbill double factor;
221147Sbill char dim[NDIM];
231147Sbill };
241147Sbill
251147Sbill struct table
261147Sbill {
271147Sbill double factor;
281147Sbill char dim[NDIM];
291147Sbill char *name;
301147Sbill } table[NTAB];
311147Sbill char names[NTAB*10];
321147Sbill struct prefix
331147Sbill {
341147Sbill double factor;
351147Sbill char *pname;
361147Sbill } prefix[] =
371147Sbill {
381147Sbill 1e-18, "atto",
391147Sbill 1e-15, "femto",
401147Sbill 1e-12, "pico",
411147Sbill 1e-9, "nano",
421147Sbill 1e-6, "micro",
431147Sbill 1e-3, "milli",
441147Sbill 1e-2, "centi",
451147Sbill 1e-1, "deci",
461147Sbill 1e1, "deka",
471147Sbill 1e2, "hecta",
481147Sbill 1e2, "hecto",
491147Sbill 1e3, "kilo",
501147Sbill 1e6, "mega",
511147Sbill 1e6, "meg",
521147Sbill 1e9, "giga",
531147Sbill 1e12, "tera",
541147Sbill 0.0, 0
551147Sbill };
561147Sbill FILE *inp;
571147Sbill int fperrc;
581147Sbill int peekc;
591147Sbill int dumpflg;
601147Sbill
main(argc,argv)611147Sbill main(argc, argv)
621147Sbill char *argv[];
631147Sbill {
641147Sbill register i;
651147Sbill register char *file;
661147Sbill struct unit u1, u2;
671147Sbill double f;
681147Sbill
691147Sbill if(argc>1 && *argv[1]=='-') {
701147Sbill argc--;
711147Sbill argv++;
721147Sbill dumpflg++;
731147Sbill }
741147Sbill file = dfile;
751147Sbill if(argc > 1)
761147Sbill file = argv[1];
771147Sbill if ((inp = fopen(file, "r")) == NULL) {
781147Sbill printf("no table\n");
791147Sbill exit(1);
801147Sbill }
811147Sbill signal(8, fperr);
821147Sbill init();
831147Sbill
841147Sbill loop:
851147Sbill fperrc = 0;
861147Sbill printf("you have: ");
871147Sbill if(convr(&u1))
881147Sbill goto loop;
891147Sbill if(fperrc)
901147Sbill goto fp;
911147Sbill loop1:
921147Sbill printf("you want: ");
931147Sbill if(convr(&u2))
941147Sbill goto loop1;
951147Sbill for(i=0; i<NDIM; i++)
961147Sbill if(u1.dim[i] != u2.dim[i])
971147Sbill goto conform;
981147Sbill f = u1.factor/u2.factor;
991147Sbill if(fperrc)
1001147Sbill goto fp;
1011147Sbill printf("\t* %e\n", f);
1021147Sbill printf("\t/ %e\n", 1./f);
1031147Sbill goto loop;
1041147Sbill
1051147Sbill conform:
1061147Sbill if(fperrc)
1071147Sbill goto fp;
1081147Sbill printf("conformability\n");
1091147Sbill units(&u1);
1101147Sbill units(&u2);
1111147Sbill goto loop;
1121147Sbill
1131147Sbill fp:
1141147Sbill printf("underflow or overflow\n");
1151147Sbill goto loop;
1161147Sbill }
1171147Sbill
1181147Sbill units(up)
1191147Sbill struct unit *up;
1201147Sbill {
1211147Sbill register struct unit *p;
1221147Sbill register f, i;
1231147Sbill
1241147Sbill p = up;
1251147Sbill printf("\t%e ", p->factor);
1261147Sbill f = 0;
1271147Sbill for(i=0; i<NDIM; i++)
1281147Sbill f |= pu(p->dim[i], i, f);
1291147Sbill if(f&1) {
1301147Sbill putchar('/');
1311147Sbill f = 0;
1321147Sbill for(i=0; i<NDIM; i++)
1331147Sbill f |= pu(-p->dim[i], i, f);
1341147Sbill }
1351147Sbill putchar('\n');
1361147Sbill }
1371147Sbill
pu(u,i,f)1381147Sbill pu(u, i, f)
1391147Sbill {
1401147Sbill
1411147Sbill if(u > 0) {
1421147Sbill if(f&2)
1431147Sbill putchar('-');
1441147Sbill if(unames[i])
1451147Sbill printf("%s", unames[i]); else
1461147Sbill printf("*%c*", i+'a');
1471147Sbill if(u > 1)
1481147Sbill putchar(u+'0');
1491147Sbill return(2);
1501147Sbill }
1511147Sbill if(u < 0)
1521147Sbill return(1);
1531147Sbill return(0);
1541147Sbill }
1551147Sbill
1561147Sbill convr(up)
1571147Sbill struct unit *up;
1581147Sbill {
1591147Sbill register struct unit *p;
1601147Sbill register c;
1611147Sbill register char *cp;
1621147Sbill char name[20];
1631147Sbill int den, err;
1641147Sbill
1651147Sbill p = up;
1661147Sbill for(c=0; c<NDIM; c++)
1671147Sbill p->dim[c] = 0;
1681147Sbill p->factor = getflt();
1691147Sbill if(p->factor == 0.)
1701147Sbill p->factor = 1.0;
1711147Sbill err = 0;
1721147Sbill den = 0;
1731147Sbill cp = name;
1741147Sbill
1751147Sbill loop:
1761147Sbill switch(c=get()) {
1771147Sbill
1781147Sbill case '1':
1791147Sbill case '2':
1801147Sbill case '3':
1811147Sbill case '4':
1821147Sbill case '5':
1831147Sbill case '6':
1841147Sbill case '7':
1851147Sbill case '8':
1861147Sbill case '9':
1871147Sbill case '-':
1881147Sbill case '/':
1891147Sbill case ' ':
1901147Sbill case '\t':
1911147Sbill case '\n':
1921147Sbill if(cp != name) {
1931147Sbill *cp++ = 0;
1941147Sbill cp = name;
1951147Sbill err |= lookup(cp, p, den, c);
1961147Sbill }
1971147Sbill if(c == '/')
1981147Sbill den++;
1991147Sbill if(c == '\n')
2001147Sbill return(err);
2011147Sbill goto loop;
2021147Sbill }
2031147Sbill *cp++ = c;
2041147Sbill goto loop;
2051147Sbill }
2061147Sbill
lookup(name,up,den,c)2071147Sbill lookup(name, up, den, c)
2081147Sbill char *name;
2091147Sbill struct unit *up;
2101147Sbill {
2111147Sbill register struct unit *p;
2121147Sbill register struct table *q;
2131147Sbill register i;
2141147Sbill char *cp1, *cp2;
2151147Sbill double e;
2161147Sbill
2171147Sbill p = up;
2181147Sbill e = 1.0;
2191147Sbill
2201147Sbill loop:
2211147Sbill q = hash(name);
2221147Sbill if(q->name) {
2231147Sbill l1:
2241147Sbill if(den) {
2251147Sbill p->factor /= q->factor*e;
2261147Sbill for(i=0; i<NDIM; i++)
2271147Sbill p->dim[i] -= q->dim[i];
2281147Sbill } else {
2291147Sbill p->factor *= q->factor*e;
2301147Sbill for(i=0; i<NDIM; i++)
2311147Sbill p->dim[i] += q->dim[i];
2321147Sbill }
2331147Sbill if(c >= '2' && c <= '9') {
2341147Sbill c--;
2351147Sbill goto l1;
2361147Sbill }
2371147Sbill return(0);
2381147Sbill }
2391147Sbill for(i=0; cp1 = prefix[i].pname; i++) {
2401147Sbill cp2 = name;
2411147Sbill while(*cp1 == *cp2++)
2421147Sbill if(*cp1++ == 0) {
2431147Sbill cp1--;
2441147Sbill break;
2451147Sbill }
2461147Sbill if(*cp1 == 0) {
2471147Sbill e *= prefix[i].factor;
2481147Sbill name = cp2-1;
2491147Sbill goto loop;
2501147Sbill }
2511147Sbill }
2521147Sbill for(cp1 = name; *cp1; cp1++);
2531147Sbill if(cp1 > name+1 && *--cp1 == 's') {
2541147Sbill *cp1 = 0;
2551147Sbill goto loop;
2561147Sbill }
2571147Sbill printf("cannot recognize %s\n", name);
2581147Sbill return(1);
2591147Sbill }
2601147Sbill
equal(s1,s2)2611147Sbill equal(s1, s2)
2621147Sbill char *s1, *s2;
2631147Sbill {
2641147Sbill register char *c1, *c2;
2651147Sbill
2661147Sbill c1 = s1;
2671147Sbill c2 = s2;
2681147Sbill while(*c1++ == *c2)
2691147Sbill if(*c2++ == 0)
2701147Sbill return(1);
2711147Sbill return(0);
2721147Sbill }
2731147Sbill
init()2741147Sbill init()
2751147Sbill {
2761147Sbill register char *cp;
2771147Sbill register struct table *tp, *lp;
2781147Sbill int c, i, f, t;
2791147Sbill char *np;
2801147Sbill
2811147Sbill cp = names;
2821147Sbill for(i=0; i<NDIM; i++) {
2831147Sbill np = cp;
2841147Sbill *cp++ = '*';
2851147Sbill *cp++ = i+'a';
2861147Sbill *cp++ = '*';
2871147Sbill *cp++ = 0;
2881147Sbill lp = hash(np);
2891147Sbill lp->name = np;
2901147Sbill lp->factor = 1.0;
2911147Sbill lp->dim[i] = 1;
2921147Sbill }
2931147Sbill lp = hash("");
2941147Sbill lp->name = cp-1;
2951147Sbill lp->factor = 1.0;
2961147Sbill
2971147Sbill l0:
2981147Sbill c = get();
2991147Sbill if(c == 0) {
3001147Sbill printf("%d units; %d bytes\n\n", i, cp-names);
3011147Sbill if(dumpflg)
3021147Sbill for(tp = &table[0]; tp < &table[NTAB]; tp++) {
3031147Sbill if(tp->name == 0)
3041147Sbill continue;
3051147Sbill printf("%s", tp->name);
3061147Sbill units(tp);
3071147Sbill }
3081147Sbill fclose(inp);
3091147Sbill inp = stdin;
3101147Sbill return;
3111147Sbill }
3121147Sbill if(c == '/') {
3131147Sbill while(c != '\n' && c != 0)
3141147Sbill c = get();
3151147Sbill goto l0;
3161147Sbill }
3171147Sbill if(c == '\n')
3181147Sbill goto l0;
3191147Sbill np = cp;
3201147Sbill while(c != ' ' && c != '\t') {
3211147Sbill *cp++ = c;
3221147Sbill c = get();
3231147Sbill if (c==0)
3241147Sbill goto l0;
3251147Sbill if(c == '\n') {
3261147Sbill *cp++ = 0;
3271147Sbill tp = hash(np);
3281147Sbill if(tp->name)
3291147Sbill goto redef;
3301147Sbill tp->name = np;
3311147Sbill tp->factor = lp->factor;
3321147Sbill for(c=0; c<NDIM; c++)
3331147Sbill tp->dim[c] = lp->dim[c];
3341147Sbill i++;
3351147Sbill goto l0;
3361147Sbill }
3371147Sbill }
3381147Sbill *cp++ = 0;
3391147Sbill lp = hash(np);
3401147Sbill if(lp->name)
3411147Sbill goto redef;
3421147Sbill convr(lp);
3431147Sbill lp->name = np;
3441147Sbill f = 0;
3451147Sbill i++;
3461147Sbill if(lp->factor != 1.0)
3471147Sbill goto l0;
3481147Sbill for(c=0; c<NDIM; c++) {
3491147Sbill t = lp->dim[c];
3501147Sbill if(t>1 || (f>0 && t!=0))
3511147Sbill goto l0;
3521147Sbill if(f==0 && t==1) {
3531147Sbill if(unames[c])
3541147Sbill goto l0;
3551147Sbill f = c+1;
3561147Sbill }
3571147Sbill }
3581147Sbill if(f>0)
3591147Sbill unames[f-1] = np;
3601147Sbill goto l0;
3611147Sbill
3621147Sbill redef:
3631147Sbill printf("redefinition %s\n", np);
3641147Sbill goto l0;
3651147Sbill }
3661147Sbill
3671147Sbill double
getflt()3681147Sbill getflt()
3691147Sbill {
3701147Sbill register c, i, dp;
3711147Sbill double d, e;
3721147Sbill int f;
3731147Sbill
3741147Sbill d = 0.;
3751147Sbill dp = 0;
3761147Sbill do
3771147Sbill c = get();
3781147Sbill while(c == ' ' || c == '\t');
3791147Sbill
3801147Sbill l1:
3811147Sbill if(c >= '0' && c <= '9') {
3821147Sbill d = d*10. + c-'0';
3831147Sbill if(dp)
3841147Sbill dp++;
3851147Sbill c = get();
3861147Sbill goto l1;
3871147Sbill }
3881147Sbill if(c == '.') {
3891147Sbill dp++;
3901147Sbill c = get();
3911147Sbill goto l1;
3921147Sbill }
3931147Sbill if(dp)
3941147Sbill dp--;
3951147Sbill if(c == '+' || c == '-') {
3961147Sbill f = 0;
3971147Sbill if(c == '-')
3981147Sbill f++;
3991147Sbill i = 0;
4001147Sbill c = get();
4011147Sbill while(c >= '0' && c <= '9') {
4021147Sbill i = i*10 + c-'0';
4031147Sbill c = get();
4041147Sbill }
4051147Sbill if(f)
4061147Sbill i = -i;
4071147Sbill dp -= i;
4081147Sbill }
4091147Sbill e = 1.;
4101147Sbill i = dp;
4111147Sbill if(i < 0)
4121147Sbill i = -i;
4131147Sbill while(i--)
4141147Sbill e *= 10.;
4151147Sbill if(dp < 0)
4161147Sbill d *= e; else
4171147Sbill d /= e;
4181147Sbill if(c == '|')
4191147Sbill return(d/getflt());
4201147Sbill peekc = c;
4211147Sbill return(d);
4221147Sbill }
4231147Sbill
get()4241147Sbill get()
4251147Sbill {
4261147Sbill register c;
4271147Sbill
4281147Sbill if(c=peekc) {
4291147Sbill peekc = 0;
4301147Sbill return(c);
4311147Sbill }
4321147Sbill c = getc(inp);
4331147Sbill if (c == EOF) {
4341147Sbill if (inp == stdin) {
4351147Sbill printf("\n");
4361147Sbill exit(0);
4371147Sbill }
4381147Sbill return(0);
4391147Sbill }
4401147Sbill return(c);
4411147Sbill }
4421147Sbill
4431147Sbill struct table *
hash(name)4441147Sbill hash(name)
4451147Sbill char *name;
4461147Sbill {
4471147Sbill register struct table *tp;
4481147Sbill register char *np;
4491147Sbill register unsigned h;
4501147Sbill
4511147Sbill h = 0;
4521147Sbill np = name;
4531147Sbill while(*np)
4541147Sbill h = h*57 + *np++ - '0';
4551147Sbill if( ((int)h)<0) h= -(int)h;
4561147Sbill h %= NTAB;
4571147Sbill tp = &table[h];
4581147Sbill l0:
4591147Sbill if(tp->name == 0)
4601147Sbill return(tp);
4611147Sbill if(equal(name, tp->name))
4621147Sbill return(tp);
4631147Sbill tp++;
4641147Sbill if(tp >= &table[NTAB])
4651147Sbill tp = table;
4661147Sbill goto l0;
4671147Sbill }
4681147Sbill
fperr()4691147Sbill fperr()
4701147Sbill {
4711147Sbill
4721147Sbill signal(8, fperr);
4731147Sbill fperrc++;
4741147Sbill }
475