date and time created 94/04/13 10:27:13 by eric
[unix-history] / usr / src / usr.bin / units / units.c
CommitLineData
94bed826
KB
1/*-
2 * %sccs.include.proprietary.c%
3 */
4
5#ifndef lint
6static char sccsid[] = "@(#)units.c 4.3 (Berkeley) %G%";
7#endif /* not lint */
8
b3bb7316 9#include <stdio.h>
f5506e0f 10#include "pathnames.h"
b3bb7316
BJ
11
12#define NDIM 10
13#define NTAB 601
f5506e0f 14char *dfile = _PATH_UNITS;
b3bb7316
BJ
15char *unames[NDIM];
16double getflt();
17int fperr();
18struct table *hash();
19struct unit
20{
21 double factor;
22 char dim[NDIM];
23};
24
25struct table
26{
27 double factor;
28 char dim[NDIM];
29 char *name;
30} table[NTAB];
31char names[NTAB*10];
32struct 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};
56FILE *inp;
57int fperrc;
58int peekc;
59int dumpflg;
60
61main(argc, argv)
62char *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
84loop:
85 fperrc = 0;
86 printf("you have: ");
87 if(convr(&u1))
88 goto loop;
89 if(fperrc)
90 goto fp;
91loop1:
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
105conform:
106 if(fperrc)
107 goto fp;
108 printf("conformability\n");
109 units(&u1);
110 units(&u2);
111 goto loop;
112
113fp:
114 printf("underflow or overflow\n");
115 goto loop;
116}
117
118units(up)
119struct 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
138pu(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
156convr(up)
157struct 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
175loop:
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
207lookup(name, up, den, c)
208char *name;
209struct 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
220loop:
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
261equal(s1, s2)
262char *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
274init()
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
297l0:
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
362redef:
363 printf("redefinition %s\n", np);
364 goto l0;
365}
366
367double
368getflt()
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
380l1:
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
424get()
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
443struct table *
444hash(name)
445char *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];
458l0:
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
469fperr()
470{
471
472 signal(8, fperr);
473 fperrc++;
474}