Bell 32V development
authorTom London <tbl@research.uucp>
Fri, 15 Dec 1978 12:46:50 +0000 (07:46 -0500)
committerTom London <tbl@research.uucp>
Fri, 15 Dec 1978 12:46:50 +0000 (07:46 -0500)
Work on file usr/src/cmd/units.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/cmd/units.c [new file with mode: 0644]

diff --git a/usr/src/cmd/units.c b/usr/src/cmd/units.c
new file mode 100644 (file)
index 0000000..2cb4996
--- /dev/null
@@ -0,0 +1,465 @@
+#include <stdio.h>
+
+#define        NDIM    10
+#define        NTAB    601
+char   *dfile  = "/usr/lib/units";
+char   *unames[NDIM];
+double getflt();
+int    fperr();
+struct table   *hash();
+struct unit
+{
+       double  factor;
+       char    dim[NDIM];
+};
+
+struct table
+{
+       double  factor;
+       char    dim[NDIM];
+       char    *name;
+} table[NTAB];
+char   names[NTAB*10];
+struct prefix
+{
+       double  factor;
+       char    *pname;
+} prefix[] = 
+{
+       1e-18,  "atto",
+       1e-15,  "femto",
+       1e-12,  "pico",
+       1e-9,   "nano",
+       1e-6,   "micro",
+       1e-3,   "milli",
+       1e-2,   "centi",
+       1e-1,   "deci",
+       1e1,    "deka",
+       1e2,    "hecta",
+       1e2,    "hecto",
+       1e3,    "kilo",
+       1e6,    "mega",
+       1e6,    "meg",
+       1e9,    "giga",
+       1e12,   "tera",
+       0.0,    0
+};
+FILE   *inp;
+int    fperrc;
+int    peekc;
+int    dumpflg;
+
+main(argc, argv)
+char *argv[];
+{
+       register i;
+       register char *file;
+       struct unit u1, u2;
+       double f;
+
+       if(argc>1 && *argv[1]=='-') {
+               argc--;
+               argv++;
+               dumpflg++;
+       }
+       file = dfile;
+       if(argc > 1)
+               file = argv[1];
+       if ((inp = fopen(file, "r")) == NULL) {
+               printf("no table\n");
+               exit(1);
+       }
+       signal(8, fperr);
+       init();
+
+loop:
+       fperrc = 0;
+       printf("you have: ");
+       if(convr(&u1))
+               goto loop;
+       if(fperrc)
+               goto fp;
+loop1:
+       printf("you want: ");
+       if(convr(&u2))
+               goto loop1;
+       for(i=0; i<NDIM; i++)
+               if(u1.dim[i] != u2.dim[i])
+                       goto conform;
+       f = u1.factor/u2.factor;
+       if(fperrc)
+               goto fp;
+       printf("\t* %e\n", f);
+       printf("\t/ %e\n", 1./f);
+       goto loop;
+
+conform:
+       if(fperrc)
+               goto fp;
+       printf("conformability\n");
+       units(&u1);
+       units(&u2);
+       goto loop;
+
+fp:
+       printf("underflow or overflow\n");
+       goto loop;
+}
+
+units(up)
+struct unit *up;
+{
+       register struct unit *p;
+       register f, i;
+
+       p = up;
+       printf("\t%e ", p->factor);
+       f = 0;
+       for(i=0; i<NDIM; i++)
+               f |= pu(p->dim[i], i, f);
+       if(f&1) {
+               putchar('/');
+               f = 0;
+               for(i=0; i<NDIM; i++)
+                       f |= pu(-p->dim[i], i, f);
+       }
+       putchar('\n');
+}
+
+pu(u, i, f)
+{
+
+       if(u > 0) {
+               if(f&2)
+                       putchar('-');
+               if(unames[i])
+                       printf("%s", unames[i]); else
+                       printf("*%c*", i+'a');
+               if(u > 1)
+                       putchar(u+'0');
+                       return(2);
+       }
+       if(u < 0)
+               return(1);
+       return(0);
+}
+
+convr(up)
+struct unit *up;
+{
+       register struct unit *p;
+       register c;
+       register char *cp;
+       char name[20];
+       int den, err;
+
+       p = up;
+       for(c=0; c<NDIM; c++)
+               p->dim[c] = 0;
+       p->factor = getflt();
+       if(p->factor == 0.)
+               p->factor = 1.0;
+       err = 0;
+       den = 0;
+       cp = name;
+
+loop:
+       switch(c=get()) {
+
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+       case '-':
+       case '/':
+       case ' ':
+       case '\t':
+       case '\n':
+               if(cp != name) {
+                       *cp++ = 0;
+                       cp = name;
+                       err |= lookup(cp, p, den, c);
+               }
+               if(c == '/')
+                       den++;
+               if(c == '\n')
+                       return(err);
+               goto loop;
+       }
+       *cp++ = c;
+       goto loop;
+}
+
+lookup(name, up, den, c)
+char *name;
+struct unit *up;
+{
+       register struct unit *p;
+       register struct table *q;
+       register i;
+       char *cp1, *cp2;
+       double e;
+
+       p = up;
+       e = 1.0;
+
+loop:
+       q = hash(name);
+       if(q->name) {
+               l1:
+               if(den) {
+                       p->factor /= q->factor*e;
+                       for(i=0; i<NDIM; i++)
+                               p->dim[i] -= q->dim[i];
+               } else {
+                       p->factor *= q->factor*e;
+                       for(i=0; i<NDIM; i++)
+                               p->dim[i] += q->dim[i];
+               }
+               if(c >= '2' && c <= '9') {
+                       c--;
+                       goto l1;
+               }
+               return(0);
+       }
+       for(i=0; cp1 = prefix[i].pname; i++) {
+               cp2 = name;
+               while(*cp1 == *cp2++)
+                       if(*cp1++ == 0) {
+                               cp1--;
+                               break;
+                       }
+               if(*cp1 == 0) {
+                       e *= prefix[i].factor;
+                       name = cp2-1;
+                       goto loop;
+               }
+       }
+       for(cp1 = name; *cp1; cp1++);
+       if(cp1 > name+1 && *--cp1 == 's') {
+               *cp1 = 0;
+               goto loop;
+       }
+       printf("cannot recognize %s\n", name);
+       return(1);
+}
+
+equal(s1, s2)
+char *s1, *s2;
+{
+       register char *c1, *c2;
+
+       c1 = s1;
+       c2 = s2;
+       while(*c1++ == *c2)
+               if(*c2++ == 0)
+                       return(1);
+       return(0);
+}
+
+init()
+{
+       register char *cp;
+       register struct table *tp, *lp;
+       int c, i, f, t;
+       char *np;
+
+       cp = names;
+       for(i=0; i<NDIM; i++) {
+               np = cp;
+               *cp++ = '*';
+               *cp++ = i+'a';
+               *cp++ = '*';
+               *cp++ = 0;
+               lp = hash(np);
+               lp->name = np;
+               lp->factor = 1.0;
+               lp->dim[i] = 1;
+       }
+       lp = hash("");
+       lp->name = cp-1;
+       lp->factor = 1.0;
+
+l0:
+       c = get();
+       if(c == 0) {
+               printf("%l units; %l bytes\n\n", i, cp-names);
+               if(dumpflg)
+               for(tp = &table[0]; tp < &table[NTAB]; tp++) {
+                       if(tp->name == 0)
+                               continue;
+                       printf("%s", tp->name);
+                       units(tp);
+               }
+               fclose(inp);
+               inp = stdin;
+               return;
+       }
+       if(c == '/') {
+               while(c != '\n' && c != 0)
+                       c = get();
+               goto l0;
+       }
+       if(c == '\n')
+               goto l0;
+       np = cp;
+       while(c != ' ' && c != '\t') {
+               *cp++ = c;
+               c = get();
+               if (c==0)
+                       goto l0;
+               if(c == '\n') {
+                       *cp++ = 0;
+                       tp = hash(np);
+                       if(tp->name)
+                               goto redef;
+                       tp->name = np;
+                       tp->factor = lp->factor;
+                       for(c=0; c<NDIM; c++)
+                               tp->dim[c] = lp->dim[c];
+                       i++;
+                       goto l0;
+               }
+       }
+       *cp++ = 0;
+       lp = hash(np);
+       if(lp->name)
+               goto redef;
+       convr(lp);
+       lp->name = np;
+       f = 0;
+       i++;
+       if(lp->factor != 1.0)
+               goto l0;
+       for(c=0; c<NDIM; c++) {
+               t = lp->dim[c];
+               if(t>1 || (f>0 && t!=0))
+                       goto l0;
+               if(f==0 && t==1) {
+                       if(unames[c])
+                               goto l0;
+                       f = c+1;
+               }
+       }
+       if(f>0)
+               unames[f-1] = np;
+       goto l0;
+
+redef:
+       printf("redefinition %s\n", np);
+       goto l0;
+}
+
+double
+getflt()
+{
+       register c, i, dp;
+       double d, e;
+       int f;
+
+       d = 0.;
+       dp = 0;
+       do
+               c = get();
+       while(c == ' ' || c == '\t');
+
+l1:
+       if(c >= '0' && c <= '9') {
+               d = d*10. + c-'0';
+               if(dp)
+                       dp++;
+               c = get();
+               goto l1;
+       }
+       if(c == '.') {
+               dp++;
+               c = get();
+               goto l1;
+       }
+       if(dp)
+               dp--;
+       if(c == '+' || c == '-') {
+               f = 0;
+               if(c == '-')
+                       f++;
+               i = 0;
+               c = get();
+               while(c >= '0' && c <= '9') {
+                       i = i*10 + c-'0';
+                       c = get();
+               }
+               if(f)
+                       i = -i;
+               dp -= i;
+       }
+       e = 1.;
+       i = dp;
+       if(i < 0)
+               i = -i;
+       while(i--)
+               e *= 10.;
+       if(dp < 0)
+               d *= e; else
+               d /= e;
+       if(c == '|')
+               return(d/getflt());
+       peekc = c;
+       return(d);
+}
+
+get()
+{
+       register c;
+
+       if(c=peekc) {
+               peekc = 0;
+               return(c);
+       }
+       c = getc(inp);
+       if (c == EOF) {
+               if (inp == stdin) {
+                       printf("\n");
+                       exit(0);
+               }
+               return(0);
+       }
+       return(c);
+}
+
+struct table *
+hash(name)
+char *name;
+{
+       register struct table *tp;
+       register char *np;
+       register unsigned h;
+
+       h = 0;
+       np = name;
+       while(*np)
+               h = h*57 + *np++ - '0';
+       if( ((int)h)<0) h= -(int)h;
+       h %= NTAB;
+       tp = &table[h];
+l0:
+       if(tp->name == 0)
+               return(tp);
+       if(equal(name, tp->name))
+               return(tp);
+       tp++;
+       if(tp >= &table[NTAB])
+               tp = table;
+       goto l0;
+}
+
+fperr()
+{
+
+       signal(8, fperr);
+       fperrc++;
+}