#if !defined(lint) static char *sccsid = "@(#)units.c 4.1.1 (2.11BSD) 1996/10/23"; #endif #include #define NDIM 10 #define NTAB 601 char *dfile = "/usr/share/misc/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; ifactor); f = 0; for(i=0; idim[i], i, f); if(f&1) { putchar('/'); f = 0; for(i=0; idim[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; cdim[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; idim[i] -= q->dim[i]; } else { p->factor *= q->factor*e; for(i=0; idim[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; iname = 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("%d units; %d 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; cdim[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; cdim[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'; if( ((int)h)<0) h= -(int)h; 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++; }