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

Defined functions

convr defined in line 148; used 3 times
equal defined in line 253; used 1 times
fperr defined in line 461; used 3 times
get defined in line 416; used 9 times
getflt defined in line 359; used 3 times
hash defined in line 435; used 6 times
init defined in line 266; used 1 times
  • in line 74
lookup defined in line 199; used 1 times
main defined in line 53; never used
pu defined in line 130; used 2 times
units defined in line 110; used 3 times

Defined variables

dfile defined in line 6; used 1 times
  • in line 66
dumpflg defined in line 51; used 2 times
fperrc defined in line 49; used 5 times
names defined in line 23; used 2 times
peekc defined in line 50; used 3 times
prefix defined in line 28; used 2 times
sccsid defined in line 1; never used
table defined in line 22; used 5 times
unames defined in line 7; used 4 times

Defined struct's

prefix defined in line 24; never used
table defined in line 17; used 9 times
unit defined in line 11; used 14 times

Defined macros

NDIM defined in line 4; used 12 times
NTAB defined in line 5; used 5 times
Last modified: 1982-06-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 850
Valid CSS Valid XHTML 1.0 Strict