1 /*- 2 * %sccs.include.proprietary.c% 3 */ 4 5 #ifndef lint 6 static char sccsid[] = "@(#)units.c 4.3 (Berkeley) 04/18/91"; 7 #endif /* not lint */ 8 9 #include <stdio.h> 10 #include "pathnames.h" 11 12 #define NDIM 10 13 #define NTAB 601 14 char *dfile = _PATH_UNITS; 15 char *unames[NDIM]; 16 double getflt(); 17 int fperr(); 18 struct table *hash(); 19 struct unit 20 { 21 double factor; 22 char dim[NDIM]; 23 }; 24 25 struct table 26 { 27 double factor; 28 char dim[NDIM]; 29 char *name; 30 } table[NTAB]; 31 char names[NTAB*10]; 32 struct prefix 33 { 34 double factor; 35 char *pname; 36 } prefix[] = 37 { 38 1e-18, "atto", 39 1e-15, "femto", 40 1e-12, "pico", 41 1e-9, "nano", 42 1e-6, "micro", 43 1e-3, "milli", 44 1e-2, "centi", 45 1e-1, "deci", 46 1e1, "deka", 47 1e2, "hecta", 48 1e2, "hecto", 49 1e3, "kilo", 50 1e6, "mega", 51 1e6, "meg", 52 1e9, "giga", 53 1e12, "tera", 54 0.0, 0 55 }; 56 FILE *inp; 57 int fperrc; 58 int peekc; 59 int dumpflg; 60 61 main(argc, argv) 62 char *argv[]; 63 { 64 register i; 65 register char *file; 66 struct unit u1, u2; 67 double f; 68 69 if(argc>1 && *argv[1]=='-') { 70 argc--; 71 argv++; 72 dumpflg++; 73 } 74 file = dfile; 75 if(argc > 1) 76 file = argv[1]; 77 if ((inp = fopen(file, "r")) == NULL) { 78 printf("no table\n"); 79 exit(1); 80 } 81 signal(8, fperr); 82 init(); 83 84 loop: 85 fperrc = 0; 86 printf("you have: "); 87 if(convr(&u1)) 88 goto loop; 89 if(fperrc) 90 goto fp; 91 loop1: 92 printf("you want: "); 93 if(convr(&u2)) 94 goto loop1; 95 for(i=0; i<NDIM; i++) 96 if(u1.dim[i] != u2.dim[i]) 97 goto conform; 98 f = u1.factor/u2.factor; 99 if(fperrc) 100 goto fp; 101 printf("\t* %e\n", f); 102 printf("\t/ %e\n", 1./f); 103 goto loop; 104 105 conform: 106 if(fperrc) 107 goto fp; 108 printf("conformability\n"); 109 units(&u1); 110 units(&u2); 111 goto loop; 112 113 fp: 114 printf("underflow or overflow\n"); 115 goto loop; 116 } 117 118 units(up) 119 struct unit *up; 120 { 121 register struct unit *p; 122 register f, i; 123 124 p = up; 125 printf("\t%e ", p->factor); 126 f = 0; 127 for(i=0; i<NDIM; i++) 128 f |= pu(p->dim[i], i, f); 129 if(f&1) { 130 putchar('/'); 131 f = 0; 132 for(i=0; i<NDIM; i++) 133 f |= pu(-p->dim[i], i, f); 134 } 135 putchar('\n'); 136 } 137 138 pu(u, i, f) 139 { 140 141 if(u > 0) { 142 if(f&2) 143 putchar('-'); 144 if(unames[i]) 145 printf("%s", unames[i]); else 146 printf("*%c*", i+'a'); 147 if(u > 1) 148 putchar(u+'0'); 149 return(2); 150 } 151 if(u < 0) 152 return(1); 153 return(0); 154 } 155 156 convr(up) 157 struct unit *up; 158 { 159 register struct unit *p; 160 register c; 161 register char *cp; 162 char name[20]; 163 int den, err; 164 165 p = up; 166 for(c=0; c<NDIM; c++) 167 p->dim[c] = 0; 168 p->factor = getflt(); 169 if(p->factor == 0.) 170 p->factor = 1.0; 171 err = 0; 172 den = 0; 173 cp = name; 174 175 loop: 176 switch(c=get()) { 177 178 case '1': 179 case '2': 180 case '3': 181 case '4': 182 case '5': 183 case '6': 184 case '7': 185 case '8': 186 case '9': 187 case '-': 188 case '/': 189 case ' ': 190 case '\t': 191 case '\n': 192 if(cp != name) { 193 *cp++ = 0; 194 cp = name; 195 err |= lookup(cp, p, den, c); 196 } 197 if(c == '/') 198 den++; 199 if(c == '\n') 200 return(err); 201 goto loop; 202 } 203 *cp++ = c; 204 goto loop; 205 } 206 207 lookup(name, up, den, c) 208 char *name; 209 struct unit *up; 210 { 211 register struct unit *p; 212 register struct table *q; 213 register i; 214 char *cp1, *cp2; 215 double e; 216 217 p = up; 218 e = 1.0; 219 220 loop: 221 q = hash(name); 222 if(q->name) { 223 l1: 224 if(den) { 225 p->factor /= q->factor*e; 226 for(i=0; i<NDIM; i++) 227 p->dim[i] -= q->dim[i]; 228 } else { 229 p->factor *= q->factor*e; 230 for(i=0; i<NDIM; i++) 231 p->dim[i] += q->dim[i]; 232 } 233 if(c >= '2' && c <= '9') { 234 c--; 235 goto l1; 236 } 237 return(0); 238 } 239 for(i=0; cp1 = prefix[i].pname; i++) { 240 cp2 = name; 241 while(*cp1 == *cp2++) 242 if(*cp1++ == 0) { 243 cp1--; 244 break; 245 } 246 if(*cp1 == 0) { 247 e *= prefix[i].factor; 248 name = cp2-1; 249 goto loop; 250 } 251 } 252 for(cp1 = name; *cp1; cp1++); 253 if(cp1 > name+1 && *--cp1 == 's') { 254 *cp1 = 0; 255 goto loop; 256 } 257 printf("cannot recognize %s\n", name); 258 return(1); 259 } 260 261 equal(s1, s2) 262 char *s1, *s2; 263 { 264 register char *c1, *c2; 265 266 c1 = s1; 267 c2 = s2; 268 while(*c1++ == *c2) 269 if(*c2++ == 0) 270 return(1); 271 return(0); 272 } 273 274 init() 275 { 276 register char *cp; 277 register struct table *tp, *lp; 278 int c, i, f, t; 279 char *np; 280 281 cp = names; 282 for(i=0; i<NDIM; i++) { 283 np = cp; 284 *cp++ = '*'; 285 *cp++ = i+'a'; 286 *cp++ = '*'; 287 *cp++ = 0; 288 lp = hash(np); 289 lp->name = np; 290 lp->factor = 1.0; 291 lp->dim[i] = 1; 292 } 293 lp = hash(""); 294 lp->name = cp-1; 295 lp->factor = 1.0; 296 297 l0: 298 c = get(); 299 if(c == 0) { 300 printf("%d units; %d bytes\n\n", i, cp-names); 301 if(dumpflg) 302 for(tp = &table[0]; tp < &table[NTAB]; tp++) { 303 if(tp->name == 0) 304 continue; 305 printf("%s", tp->name); 306 units(tp); 307 } 308 fclose(inp); 309 inp = stdin; 310 return; 311 } 312 if(c == '/') { 313 while(c != '\n' && c != 0) 314 c = get(); 315 goto l0; 316 } 317 if(c == '\n') 318 goto l0; 319 np = cp; 320 while(c != ' ' && c != '\t') { 321 *cp++ = c; 322 c = get(); 323 if (c==0) 324 goto l0; 325 if(c == '\n') { 326 *cp++ = 0; 327 tp = hash(np); 328 if(tp->name) 329 goto redef; 330 tp->name = np; 331 tp->factor = lp->factor; 332 for(c=0; c<NDIM; c++) 333 tp->dim[c] = lp->dim[c]; 334 i++; 335 goto l0; 336 } 337 } 338 *cp++ = 0; 339 lp = hash(np); 340 if(lp->name) 341 goto redef; 342 convr(lp); 343 lp->name = np; 344 f = 0; 345 i++; 346 if(lp->factor != 1.0) 347 goto l0; 348 for(c=0; c<NDIM; c++) { 349 t = lp->dim[c]; 350 if(t>1 || (f>0 && t!=0)) 351 goto l0; 352 if(f==0 && t==1) { 353 if(unames[c]) 354 goto l0; 355 f = c+1; 356 } 357 } 358 if(f>0) 359 unames[f-1] = np; 360 goto l0; 361 362 redef: 363 printf("redefinition %s\n", np); 364 goto l0; 365 } 366 367 double 368 getflt() 369 { 370 register c, i, dp; 371 double d, e; 372 int f; 373 374 d = 0.; 375 dp = 0; 376 do 377 c = get(); 378 while(c == ' ' || c == '\t'); 379 380 l1: 381 if(c >= '0' && c <= '9') { 382 d = d*10. + c-'0'; 383 if(dp) 384 dp++; 385 c = get(); 386 goto l1; 387 } 388 if(c == '.') { 389 dp++; 390 c = get(); 391 goto l1; 392 } 393 if(dp) 394 dp--; 395 if(c == '+' || c == '-') { 396 f = 0; 397 if(c == '-') 398 f++; 399 i = 0; 400 c = get(); 401 while(c >= '0' && c <= '9') { 402 i = i*10 + c-'0'; 403 c = get(); 404 } 405 if(f) 406 i = -i; 407 dp -= i; 408 } 409 e = 1.; 410 i = dp; 411 if(i < 0) 412 i = -i; 413 while(i--) 414 e *= 10.; 415 if(dp < 0) 416 d *= e; else 417 d /= e; 418 if(c == '|') 419 return(d/getflt()); 420 peekc = c; 421 return(d); 422 } 423 424 get() 425 { 426 register c; 427 428 if(c=peekc) { 429 peekc = 0; 430 return(c); 431 } 432 c = getc(inp); 433 if (c == EOF) { 434 if (inp == stdin) { 435 printf("\n"); 436 exit(0); 437 } 438 return(0); 439 } 440 return(c); 441 } 442 443 struct table * 444 hash(name) 445 char *name; 446 { 447 register struct table *tp; 448 register char *np; 449 register unsigned h; 450 451 h = 0; 452 np = name; 453 while(*np) 454 h = h*57 + *np++ - '0'; 455 if( ((int)h)<0) h= -(int)h; 456 h %= NTAB; 457 tp = &table[h]; 458 l0: 459 if(tp->name == 0) 460 return(tp); 461 if(equal(name, tp->name)) 462 return(tp); 463 tp++; 464 if(tp >= &table[NTAB]) 465 tp = table; 466 goto l0; 467 } 468 469 fperr() 470 { 471 472 signal(8, fperr); 473 fperrc++; 474 } 475