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