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