1: #include <stdio.h> 2: 3: #define NDIM 10 4: #define NTAB 601 5: char *dfile = "/usr/lib/units"; 6: char *unames[NDIM]; 7: double getflt(); 8: int fperr(); 9: struct table *hash(); 10: struct unit 11: { 12: double factor; 13: char dim[NDIM]; 14: }; 15: 16: struct table 17: { 18: double factor; 19: char dim[NDIM]; 20: char *name; 21: } table[NTAB]; 22: char names[NTAB*10]; 23: struct prefix 24: { 25: double factor; 26: char *pname; 27: } prefix[] = 28: { 29: 1e-18, "atto", 30: 1e-15, "femto", 31: 1e-12, "pico", 32: 1e-9, "nano", 33: 1e-6, "micro", 34: 1e-3, "milli", 35: 1e-2, "centi", 36: 1e-1, "deci", 37: 1e1, "deka", 38: 1e2, "hecta", 39: 1e2, "hecto", 40: 1e3, "kilo", 41: 1e6, "mega", 42: 1e6, "meg", 43: 1e9, "giga", 44: 1e12, "tera", 45: 0.0, 0 46: }; 47: FILE *inp; 48: int fperrc; 49: int peekc; 50: int dumpflg; 51: 52: main(argc, argv) 53: char *argv[]; 54: { 55: register i; 56: register char *file; 57: struct unit u1, u2; 58: double f; 59: 60: if(argc>1 && *argv[1]=='-') { 61: argc--; 62: argv++; 63: dumpflg++; 64: } 65: file = dfile; 66: if(argc > 1) 67: file = argv[1]; 68: if ((inp = fopen(file, "r")) == NULL) { 69: printf("no table\n"); 70: exit(1); 71: } 72: signal(8, fperr); 73: init(); 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: fclose(inp); 300: inp = stdin; 301: return; 302: } 303: if(c == '/') { 304: while(c != '\n' && c != 0) 305: c = get(); 306: goto l0; 307: } 308: if(c == '\n') 309: goto l0; 310: np = cp; 311: while(c != ' ' && c != '\t') { 312: *cp++ = c; 313: c = get(); 314: if (c==0) 315: goto l0; 316: if(c == '\n') { 317: *cp++ = 0; 318: tp = hash(np); 319: if(tp->name) 320: goto redef; 321: tp->name = np; 322: tp->factor = lp->factor; 323: for(c=0; c<NDIM; c++) 324: tp->dim[c] = lp->dim[c]; 325: i++; 326: goto l0; 327: } 328: } 329: *cp++ = 0; 330: lp = hash(np); 331: if(lp->name) 332: goto redef; 333: convr(lp); 334: lp->name = np; 335: f = 0; 336: i++; 337: if(lp->factor != 1.0) 338: goto l0; 339: for(c=0; c<NDIM; c++) { 340: t = lp->dim[c]; 341: if(t>1 || (f>0 && t!=0)) 342: goto l0; 343: if(f==0 && t==1) { 344: if(unames[c]) 345: goto l0; 346: f = c+1; 347: } 348: } 349: if(f>0) 350: unames[f-1] = np; 351: goto l0; 352: 353: redef: 354: printf("redefinition %s\n", np); 355: goto l0; 356: } 357: 358: double 359: getflt() 360: { 361: register c, i, dp; 362: double d, e; 363: int f; 364: 365: d = 0.; 366: dp = 0; 367: do 368: c = get(); 369: while(c == ' ' || c == '\t'); 370: 371: l1: 372: if(c >= '0' && c <= '9') { 373: d = d*10. + c-'0'; 374: if(dp) 375: dp++; 376: c = get(); 377: goto l1; 378: } 379: if(c == '.') { 380: dp++; 381: c = get(); 382: goto l1; 383: } 384: if(dp) 385: dp--; 386: if(c == '+' || c == '-') { 387: f = 0; 388: if(c == '-') 389: f++; 390: i = 0; 391: c = get(); 392: while(c >= '0' && c <= '9') { 393: i = i*10 + c-'0'; 394: c = get(); 395: } 396: if(f) 397: i = -i; 398: dp -= i; 399: } 400: e = 1.; 401: i = dp; 402: if(i < 0) 403: i = -i; 404: while(i--) 405: e *= 10.; 406: if(dp < 0) 407: d *= e; else 408: d /= e; 409: if(c == '|') 410: return(d/getflt()); 411: peekc = c; 412: return(d); 413: } 414: 415: get() 416: { 417: register c; 418: 419: if(c=peekc) { 420: peekc = 0; 421: return(c); 422: } 423: c = getc(inp); 424: if (c == EOF) { 425: if (inp == stdin) { 426: printf("\n"); 427: exit(0); 428: } 429: return(0); 430: } 431: return(c); 432: } 433: 434: struct table * 435: hash(name) 436: char *name; 437: { 438: register struct table *tp; 439: register char *np; 440: register unsigned h; 441: 442: h = 0; 443: np = name; 444: while(*np) 445: h = h*57 + *np++ - '0'; 446: h %= NTAB; 447: tp = &table[h]; 448: l0: 449: if(tp->name == 0) 450: return(tp); 451: if(equal(name, tp->name)) 452: return(tp); 453: tp++; 454: if(tp >= &table[NTAB]) 455: tp = table; 456: goto l0; 457: } 458: 459: fperr() 460: { 461: 462: signal(8, fperr); 463: fperrc++; 464: }