home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / s2 / units.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-05-13  |  5.9 KB  |  457 lines

  1. #define    NDIM    10
  2. #define    NTAB    601
  3. char    *dfile    "/usr/lib/units";
  4. char    *unames[NDIM];
  5. double    getflt();
  6. int    fperr();
  7. struct unit
  8. {
  9.     double    factor;
  10.     char    dim[NDIM];
  11. };
  12.  
  13. struct table
  14. {
  15.     double    factor;
  16.     char    dim[NDIM];
  17.     char    *name;
  18. } table[NTAB];
  19. char    names[NTAB*10];
  20. struct prefix
  21. {
  22.     double    factor;
  23.     char    *pname;
  24. } prefix[]
  25. {
  26.     1e-18,    "atto",
  27.     1e-15,    "femto",
  28.     1e-12,    "pico",
  29.     1e-9,    "nano",
  30.     1e-6,    "micro",
  31.     1e-3,    "milli",
  32.     1e-2,    "centi",
  33.     1e-1,    "deci",
  34.     1e1,    "deka",
  35.     1e2,    "hecta",
  36.     1e2,    "hecto",
  37.     1e3,    "kilo",
  38.     1e6,    "mega",
  39.     1e6,    "meg",
  40.     1e9,    "giga",
  41.     1e12,    "tera",
  42.     0.0,    0
  43. };
  44. int    ibuf[259];
  45. int    fperrc;
  46. int    peekc;
  47. int    dumpflg;
  48.  
  49. main(argc, argv)
  50. char *argv[];
  51. {
  52.     register i;
  53.     register char *file;
  54.     struct unit u1, u2;
  55.     double f;
  56.  
  57.     if(argc>1 && *argv[1]=='-') {
  58.         argc--;
  59.         argv++;
  60.         dumpflg++;
  61.     }
  62.     file = dfile;
  63.     if(argc > 1)
  64.         file = argv[1];
  65.     if(fopen(file, ibuf) < 0) {
  66.         printf("no table\n");
  67.         exit();
  68.     }
  69.     ldfps(07600); /* interrupt on fp errors */
  70.     signal(8, fperr);
  71.     init();
  72.     close(ibuf[0]);
  73.     ibuf[0] = 0;
  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.         return;
  300.     }
  301.     if(c == '/')
  302.         while(c != '\n')
  303.             c = get();
  304.     if(c == '\n')
  305.         goto l0;
  306.     np = cp;
  307.     while(c != ' ' && c != '\t') {
  308.         *cp++ = c;
  309.         c = get();
  310.         if(c == '\n') {
  311.             *cp++ = 0;
  312.             tp = hash(np);
  313.             if(tp->name)
  314.                 goto redef;
  315.             tp->name = np;
  316.             tp->factor = lp->factor;
  317.             for(c=0; c<NDIM; c++)
  318.                 tp->dim[c] = lp->dim[c];
  319.             i++;
  320.             goto l0;
  321.         }
  322.     }
  323.     *cp++ = 0;
  324.     lp = hash(np);
  325.     if(lp->name)
  326.         goto redef;
  327.     convr(lp);
  328.     lp->name = np;
  329.     f = 0;
  330.     i++;
  331.     if(lp->factor != 1.0)
  332.         goto l0;
  333.     for(c=0; c<NDIM; c++) {
  334.         t = lp->dim[c];
  335.         if(t>1 || (f>0 && t!=0))
  336.             goto l0;
  337.         if(f==0 && t==1) {
  338.             if(unames[c])
  339.                 goto l0;
  340.             f = c+1;
  341.         }
  342.     }
  343.     if(f>0)
  344.         unames[f-1] = np;
  345.     goto l0;
  346.  
  347. redef:
  348.     printf("redefination %s\n", np);
  349.     goto l0;
  350. }
  351.  
  352. double
  353. getflt()
  354. {
  355.     register c, i, dp;
  356.     double d, e;
  357.     int f;
  358.  
  359.     d = 0.;
  360.     dp = 0;
  361.     do
  362.         c = get();
  363.     while(c == ' ' || c == '\t');
  364.  
  365. l1:
  366.     if(c >= '0' && c <= '9') {
  367.         d = d*10. + c-'0';
  368.         if(dp)
  369.             dp++;
  370.         c = get();
  371.         goto l1;
  372.     }
  373.     if(c == '.') {
  374.         dp++;
  375.         c = get();
  376.         goto l1;
  377.     }
  378.     if(dp)
  379.         dp--;
  380.     if(c == '+' || c == '-') {
  381.         f = 0;
  382.         if(c == '-')
  383.             f++;
  384.         i = 0;
  385.         c = get();
  386.         while(c >= '0' && c <= '9') {
  387.             i = i*10 + c-'0';
  388.             c = get();
  389.         }
  390.         if(f)
  391.             i = -i;
  392.         dp =- i;
  393.     }
  394.     e = 1.;
  395.     i = dp;
  396.     if(i < 0)
  397.         i = -i;
  398.     while(i--)
  399.         e =* 10.;
  400.     if(dp < 0)
  401.         d =* e; else
  402.         d =/ e;
  403.     if(c == '|')
  404.         return(d/getflt());
  405.     peekc = c;
  406.     return(d);
  407. }
  408.  
  409. get()
  410. {
  411.     register c;
  412.  
  413.     if(c=peekc) {
  414.         peekc = 0;
  415.         return(c);
  416.     }
  417.     c = getc(ibuf);
  418.     if(c <= 0) {
  419.         if(ibuf[0])
  420.             return(0);
  421.         printf("\n");
  422.         exit();
  423.     }
  424.     return(c);
  425. }
  426.  
  427. hash(name)
  428. char *name;
  429. {
  430.     register struct table *tp;
  431.     register char *np;
  432.     register h;
  433.  
  434.     h = 0;
  435.     np = name;
  436.     while(*np)
  437.         h = h*57 + *np++ - '0';
  438.     h = lrem(0, h, NTAB);
  439.     tp = &table[h];
  440. l0:
  441.     if(tp->name == 0)
  442.         return(tp);
  443.     if(equal(name, tp->name))
  444.         return(tp);
  445.     tp++;
  446.     if(tp >= &table[NTAB])
  447.         tp = table;
  448.     goto l0;
  449. }
  450.  
  451. fperr()
  452. {
  453.  
  454.     signal(8, fperr);
  455.     fperrc++;
  456. }
  457.