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