1: static char *sccsid = "@(#)units.c 4.1 (Berkeley) 10/1/80"; 2: #include <stdio.h> 3: 4: #define NDIM 10 5: #define NTAB 601 6: char *dfile = "/usr/lib/units"; 7: char *unames[NDIM]; 8: double getflt(); 9: int fperr(); 10: struct table *hash(); 11: struct unit 12: { 13: double factor; 14: char dim[NDIM]; 15: }; 16: 17: struct table 18: { 19: double factor; 20: char dim[NDIM]; 21: char *name; 22: } table[NTAB]; 23: char names[NTAB*10]; 24: struct prefix 25: { 26: double factor; 27: char *pname; 28: } prefix[] = 29: { 30: 1e-18, "atto", 31: 1e-15, "femto", 32: 1e-12, "pico", 33: 1e-9, "nano", 34: 1e-6, "micro", 35: 1e-3, "milli", 36: 1e-2, "centi", 37: 1e-1, "deci", 38: 1e1, "deka", 39: 1e2, "hecta", 40: 1e2, "hecto", 41: 1e3, "kilo", 42: 1e6, "mega", 43: 1e6, "meg", 44: 1e9, "giga", 45: 1e12, "tera", 46: 0.0, 0 47: }; 48: FILE *inp; 49: int fperrc; 50: int peekc; 51: int dumpflg; 52: 53: main(argc, argv) 54: char *argv[]; 55: { 56: register i; 57: register char *file; 58: struct unit u1, u2; 59: double f; 60: 61: if(argc>1 && *argv[1]=='-') { 62: argc--; 63: argv++; 64: dumpflg++; 65: } 66: file = dfile; 67: if(argc > 1) 68: file = argv[1]; 69: if ((inp = fopen(file, "r")) == NULL) { 70: printf("no table\n"); 71: exit(1); 72: } 73: signal(8, fperr); 74: init(); 75: 76: loop: 77: fperrc = 0; 78: printf("you have: "); 79: if(convr(&u1)) 80: goto loop; 81: if(fperrc) 82: goto fp; 83: loop1: 84: printf("you want: "); 85: if(convr(&u2)) 86: goto loop1; 87: for(i=0; i<NDIM; i++) 88: if(u1.dim[i] != u2.dim[i]) 89: goto conform; 90: f = u1.factor/u2.factor; 91: if(fperrc) 92: goto fp; 93: printf("\t* %e\n", f); 94: printf("\t/ %e\n", 1./f); 95: goto loop; 96: 97: conform: 98: if(fperrc) 99: goto fp; 100: printf("conformability\n"); 101: units(&u1); 102: units(&u2); 103: goto loop; 104: 105: fp: 106: printf("underflow or overflow\n"); 107: goto loop; 108: } 109: 110: units(up) 111: struct unit *up; 112: { 113: register struct unit *p; 114: register f, i; 115: 116: p = up; 117: printf("\t%e ", p->factor); 118: f = 0; 119: for(i=0; i<NDIM; i++) 120: f |= pu(p->dim[i], i, f); 121: if(f&1) { 122: putchar('/'); 123: f = 0; 124: for(i=0; i<NDIM; i++) 125: f |= pu(-p->dim[i], i, f); 126: } 127: putchar('\n'); 128: } 129: 130: pu(u, i, f) 131: { 132: 133: if(u > 0) { 134: if(f&2) 135: putchar('-'); 136: if(unames[i]) 137: printf("%s", unames[i]); else 138: printf("*%c*", i+'a'); 139: if(u > 1) 140: putchar(u+'0'); 141: return(2); 142: } 143: if(u < 0) 144: return(1); 145: return(0); 146: } 147: 148: convr(up) 149: struct unit *up; 150: { 151: register struct unit *p; 152: register c; 153: register char *cp; 154: char name[20]; 155: int den, err; 156: 157: p = up; 158: for(c=0; c<NDIM; c++) 159: p->dim[c] = 0; 160: p->factor = getflt(); 161: if(p->factor == 0.) 162: p->factor = 1.0; 163: err = 0; 164: den = 0; 165: cp = name; 166: 167: loop: 168: switch(c=get()) { 169: 170: case '1': 171: case '2': 172: case '3': 173: case '4': 174: case '5': 175: case '6': 176: case '7': 177: case '8': 178: case '9': 179: case '-': 180: case '/': 181: case ' ': 182: case '\t': 183: case '\n': 184: if(cp != name) { 185: *cp++ = 0; 186: cp = name; 187: err |= lookup(cp, p, den, c); 188: } 189: if(c == '/') 190: den++; 191: if(c == '\n') 192: return(err); 193: goto loop; 194: } 195: *cp++ = c; 196: goto loop; 197: } 198: 199: lookup(name, up, den, c) 200: char *name; 201: struct unit *up; 202: { 203: register struct unit *p; 204: register struct table *q; 205: register i; 206: char *cp1, *cp2; 207: double e; 208: 209: p = up; 210: e = 1.0; 211: 212: loop: 213: q = hash(name); 214: if(q->name) { 215: l1: 216: if(den) { 217: p->factor /= q->factor*e; 218: for(i=0; i<NDIM; i++) 219: p->dim[i] -= q->dim[i]; 220: } else { 221: p->factor *= q->factor*e; 222: for(i=0; i<NDIM; i++) 223: p->dim[i] += q->dim[i]; 224: } 225: if(c >= '2' && c <= '9') { 226: c--; 227: goto l1; 228: } 229: return(0); 230: } 231: for(i=0; cp1 = prefix[i].pname; i++) { 232: cp2 = name; 233: while(*cp1 == *cp2++) 234: if(*cp1++ == 0) { 235: cp1--; 236: break; 237: } 238: if(*cp1 == 0) { 239: e *= prefix[i].factor; 240: name = cp2-1; 241: goto loop; 242: } 243: } 244: for(cp1 = name; *cp1; cp1++); 245: if(cp1 > name+1 && *--cp1 == 's') { 246: *cp1 = 0; 247: goto loop; 248: } 249: printf("cannot recognize %s\n", name); 250: return(1); 251: } 252: 253: equal(s1, s2) 254: char *s1, *s2; 255: { 256: register char *c1, *c2; 257: 258: c1 = s1; 259: c2 = s2; 260: while(*c1++ == *c2) 261: if(*c2++ == 0) 262: return(1); 263: return(0); 264: } 265: 266: init() 267: { 268: register char *cp; 269: register struct table *tp, *lp; 270: int c, i, f, t; 271: char *np; 272: 273: cp = names; 274: for(i=0; i<NDIM; i++) { 275: np = cp; 276: *cp++ = '*'; 277: *cp++ = i+'a'; 278: *cp++ = '*'; 279: *cp++ = 0; 280: lp = hash(np); 281: lp->name = np; 282: lp->factor = 1.0; 283: lp->dim[i] = 1; 284: } 285: lp = hash(""); 286: lp->name = cp-1; 287: lp->factor = 1.0; 288: 289: l0: 290: c = get(); 291: if(c == 0) { 292: printf("%d units; %d bytes\n\n", i, cp-names); 293: if(dumpflg) 294: for(tp = &table[0]; tp < &table[NTAB]; tp++) { 295: if(tp->name == 0) 296: continue; 297: printf("%s", tp->name); 298: units(tp); 299: } 300: fclose(inp); 301: inp = stdin; 302: return; 303: } 304: if(c == '/') { 305: while(c != '\n' && c != 0) 306: c = get(); 307: goto l0; 308: } 309: if(c == '\n') 310: goto l0; 311: np = cp; 312: while(c != ' ' && c != '\t') { 313: *cp++ = c; 314: c = get(); 315: if (c==0) 316: goto l0; 317: if(c == '\n') { 318: *cp++ = 0; 319: tp = hash(np); 320: if(tp->name) 321: goto redef; 322: tp->name = np; 323: tp->factor = lp->factor; 324: for(c=0; c<NDIM; c++) 325: tp->dim[c] = lp->dim[c]; 326: i++; 327: goto l0; 328: } 329: } 330: *cp++ = 0; 331: lp = hash(np); 332: if(lp->name) 333: goto redef; 334: convr(lp); 335: lp->name = np; 336: f = 0; 337: i++; 338: if(lp->factor != 1.0) 339: goto l0; 340: for(c=0; c<NDIM; c++) { 341: t = lp->dim[c]; 342: if(t>1 || (f>0 && t!=0)) 343: goto l0; 344: if(f==0 && t==1) { 345: if(unames[c]) 346: goto l0; 347: f = c+1; 348: } 349: } 350: if(f>0) 351: unames[f-1] = np; 352: goto l0; 353: 354: redef: 355: printf("redefinition %s\n", np); 356: goto l0; 357: } 358: 359: double 360: getflt() 361: { 362: register c, i, dp; 363: double d, e; 364: int f; 365: 366: d = 0.; 367: dp = 0; 368: do 369: c = get(); 370: while(c == ' ' || c == '\t'); 371: 372: l1: 373: if(c >= '0' && c <= '9') { 374: d = d*10. + c-'0'; 375: if(dp) 376: dp++; 377: c = get(); 378: goto l1; 379: } 380: if(c == '.') { 381: dp++; 382: c = get(); 383: goto l1; 384: } 385: if(dp) 386: dp--; 387: if(c == '+' || c == '-') { 388: f = 0; 389: if(c == '-') 390: f++; 391: i = 0; 392: c = get(); 393: while(c >= '0' && c <= '9') { 394: i = i*10 + c-'0'; 395: c = get(); 396: } 397: if(f) 398: i = -i; 399: dp -= i; 400: } 401: e = 1.; 402: i = dp; 403: if(i < 0) 404: i = -i; 405: while(i--) 406: e *= 10.; 407: if(dp < 0) 408: d *= e; else 409: d /= e; 410: if(c == '|') 411: return(d/getflt()); 412: peekc = c; 413: return(d); 414: } 415: 416: get() 417: { 418: register c; 419: 420: if(c=peekc) { 421: peekc = 0; 422: return(c); 423: } 424: c = getc(inp); 425: if (c == EOF) { 426: if (inp == stdin) { 427: printf("\n"); 428: exit(0); 429: } 430: return(0); 431: } 432: return(c); 433: } 434: 435: struct table * 436: hash(name) 437: char *name; 438: { 439: register struct table *tp; 440: register char *np; 441: register unsigned h; 442: 443: h = 0; 444: np = name; 445: while(*np) 446: h = h*57 + *np++ - '0'; 447: if( ((int)h)<0) h= -(int)h; 448: h %= NTAB; 449: tp = &table[h]; 450: l0: 451: if(tp->name == 0) 452: return(tp); 453: if(equal(name, tp->name)) 454: return(tp); 455: tp++; 456: if(tp >= &table[NTAB]) 457: tp = table; 458: goto l0; 459: } 460: 461: fperr() 462: { 463: 464: signal(8, fperr); 465: fperrc++; 466: }