Unleashed v1.4
[unleashed.git] / usr / src / cmd / units / units.c
blob9f5eb30aea9c424c086fdb279c495ffeb6ae24ce
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include <stdio.h>
18 #include <locale.h>
19 #include <signal.h>
21 #define NDIM 10
22 #define NTAB 1009
23 char *dfile = "/usr/share/lib/unittab";
24 char *unames[NDIM];
25 struct unit
27 double factor;
28 char dim[NDIM];
31 struct table
33 double factor;
34 char dim[NDIM];
35 char *name;
36 } table[NTAB];
37 char names[NTAB*10];
38 struct prefix
40 double factor;
41 char *pname;
42 } prefix[] =
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
73 FILE *inp;
74 int fperrc;
75 int peekc;
76 int dumpflg;
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);
89 int
90 main(int argc, char *argv[])
92 int i;
93 char *file;
94 struct unit u1, u2;
95 double f;
97 (void) setlocale(LC_ALL, "");
98 #if !defined(TEXT_DOMAIN)
99 #define TEXT_DOMAIN "SYS_TEST"
100 #endif
101 (void) textdomain(TEXT_DOMAIN);
103 if(argc>1 && *argv[1]=='-') {
104 argc--;
105 argv++;
106 dumpflg++;
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);
115 signal(8, fperr);
116 init();
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;
139 conform:
140 if(fperrc)
141 goto fp;
142 printf(gettext("conformability\n"));
143 units(&u1);
144 units(&u2);
145 goto loop;
148 printf(gettext("underflow or overflow\n"));
149 goto loop;
152 void
153 units(struct unit *up)
155 struct unit *p;
156 int f, i;
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);
169 putchar('\n');
173 pu(int u, int i, int f)
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);
186 if(u < 0)
187 return(1);
188 return(0);
192 convr(struct unit *up)
194 struct unit *p;
195 int c;
196 char *cp;
197 char name[20];
198 int den, err;
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;
210 loop:
211 switch(c=get()) {
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);
232 if(c == '/')
233 den++;
234 if(c == '\n')
235 return(err);
236 goto loop;
238 *cp++ = c;
239 goto loop;
243 lookup(char *name, struct unit *up, int den, int c)
245 struct unit *p;
246 struct table *q;
247 int i;
248 char *cp1, *cp2;
249 double e;
251 p = up;
252 e = 1.0;
254 loop:
255 q = hash(name);
256 if(q->name) {
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];
267 if(c >= '2' && c <= '9') {
268 c--;
269 goto l1;
271 return(0);
273 for(i=0; cp1 = prefix[i].pname; i++) {
274 cp2 = name;
275 while(*cp1 == *cp2++)
276 if(*cp1++ == 0) {
277 cp1--;
278 break;
280 if(*cp1 == 0) {
281 e *= prefix[i].factor;
282 name = cp2-1;
283 goto loop;
286 for(cp1 = name; *cp1; cp1++);
287 if(cp1 > name+1 && *--cp1 == 's') {
288 *cp1 = 0;
289 goto loop;
291 printf(gettext("cannot recognize %s\n"), name);
292 return(1);
296 equal(char *s1, char *s2)
298 char *c1, *c2;
300 c1 = s1;
301 c2 = s2;
302 while(*c1++ == *c2)
303 if(*c2++ == 0)
304 return(1);
305 return(0);
308 void
309 init(void)
311 char *cp;
312 struct table *tp, *lp;
313 int c, i, f, t;
314 char *np;
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;
328 lp = hash("");
329 lp->name = cp-1;
330 lp->factor = 1.0;
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);
343 fclose(inp);
344 inp = stdin;
345 return;
347 if(c == '/') {
348 while(c != '\n' && c != 0)
349 c = get();
350 goto l0;
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;
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;
393 if(f>0)
394 unames[f-1] = np;
395 goto l0;
397 redef:
398 printf(gettext("redefinition %s\n"), np);
399 goto l0;
402 double
403 getflt(void)
405 int c, i, dp;
406 double d, e;
407 int f;
409 d = 0.;
410 dp = 0;
412 c = get();
413 while(c == ' ' || c == '\t');
416 if(c >= '0' && c <= '9') {
417 d = d*10. + c-'0';
418 if(dp)
419 dp++;
420 c = get();
421 goto l1;
423 if(c == '.') {
424 dp++;
425 c = get();
426 goto l1;
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();
440 if(f)
441 i = -i;
442 dp -= i;
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);
460 get(void)
462 int c;
464 if(c=peekc) {
465 peekc = 0;
466 return(c);
468 c = getc(inp);
469 if (c == EOF) {
470 if (inp == stdin) {
471 printf("\n");
472 exit(0);
474 return(0);
476 return(c);
479 struct table *
480 hash(char *name)
482 struct table *tp;
483 char *np;
484 unsigned int h;
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];
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;
504 void
505 fperr(int sig)
508 signal(8, fperr);
509 fperrc++;