home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / units.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  6.0 KB  |  465 lines

  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.     h %= NTAB;
  447.     tp = &table[h];
  448. l0:
  449.     if(tp->name == 0)
  450.         return(tp);
  451.     if(equal(name, tp->name))
  452.         return(tp);
  453.     tp++;
  454.     if(tp >= &table[NTAB])
  455.         tp = table;
  456.     goto l0;
  457. }
  458.  
  459. fperr()
  460. {
  461.  
  462.     signal(8, fperr);
  463.     fperrc++;
  464. }
  465.