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