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