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

Defined functions

convr defined in line 151; used 3 times
equal defined in line 256; used 1 times
fperr defined in line 464; used 3 times
get defined in line 419; used 9 times
getflt defined in line 362; used 3 times
hash defined in line 438; used 6 times
init defined in line 269; used 1 times
  • in line 77
lookup defined in line 202; used 1 times
main defined in line 56; never used
pu defined in line 133; used 2 times
units defined in line 113; used 3 times

Defined variables

dfile defined in line 9; used 1 times
  • in line 69
dumpflg defined in line 54; used 2 times
fperrc defined in line 52; used 5 times
names defined in line 26; used 2 times
peekc defined in line 53; used 3 times
prefix defined in line 31; used 2 times
sccsid defined in line 2; never used
table defined in line 25; used 5 times
unames defined in line 10; used 4 times

Defined struct's

prefix defined in line 27; never used
table defined in line 20; used 9 times
unit defined in line 14; used 14 times

Defined macros

NDIM defined in line 7; used 12 times
NTAB defined in line 8; used 5 times
Last modified: 1996-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1682
Valid CSS Valid XHTML 1.0 Strict