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