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