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: }

Defined functions

convr defined in line 147; used 3 times
equal defined in line 252; used 1 times
fperr defined in line 459; used 3 times
get defined in line 415; used 9 times
getflt defined in line 358; used 3 times
hash defined in line 434; used 6 times
init defined in line 265; used 1 times
  • in line 73
lookup defined in line 198; used 1 times
main defined in line 52; never used
pu defined in line 129; used 2 times
units defined in line 109; used 3 times

Defined variables

dfile defined in line 5; used 1 times
  • in line 65
dumpflg defined in line 50; used 2 times
fperrc defined in line 48; used 5 times
names defined in line 22; used 2 times
peekc defined in line 49; used 3 times
prefix defined in line 27; used 2 times
table defined in line 21; used 5 times
unames defined in line 6; used 4 times

Defined struct's

prefix defined in line 23; never used
table defined in line 16; used 9 times
unit defined in line 10; used 14 times

Defined macros

NDIM defined in line 3; used 12 times
NTAB defined in line 4; used 5 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 908
Valid CSS Valid XHTML 1.0 Strict