1 static char *sccsid = "@(#)units.c 4.1 (Berkeley) 10/01/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 } 467