Annotation of coherent/d/usr/lib/units.c, revision 1.1.1.1

1.1       root        1: static char Copyright[] =      "$Copyright: (c) 1985, INETCO Systems, Ltd.$";
                      2: static char Release[] =                "$Release: INETCO COHERENT V8.0$";
                      3: static char Date[] =           "$Date: 91/04/19 12:41:06 $";
                      4: 
                      5: /* (-lgl
                      6:  *     The information contained herein is a trade secret of Mark Williams
                      7:  *     Company, and  is confidential information.  It is provided  under a
                      8:  *     license agreement,  and may be  copied or disclosed  only under the
                      9:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                     10:  *     material without the express written authorization of Mark Williams
                     11:  *     Company or persuant to the license agreement is unlawful.
                     12:  * 
                     13:  *     Coherent Version 2.3.38
                     14:  *     Copyright (c) 1982, 1983, 1984.
                     15:  *     An unpublished work by Mark Williams Company, Chicago.
                     16:  *     All rights reserved.
                     17:  -lgl) */
                     18: /*
                     19:  * units -- do multiplicative unit conversions
                     20:  * td 80.09.04
                     21:  * Modified to keep the intermediate format in a file and
                     22:  * update it automatically when it has changed.
                     23:  * (NOTE: program is setuid to bin)
                     24:  * rec 84.08.13
                     25:  * Changed Waiting for Godot ... to Rebuilding %s from %s.
                     26:  * (Nota Bene:
                     27:  *     cc -o units -f units.c
                     28:  *     chown bin /bin/units
                     29:  *     chmod 4755 /bin/units
                     30:  * )
                     31:  */
                     32: 
                     33: #include <stdio.h>
                     34: #include <sys/stat.h>
                     35: 
                     36: #define        NDIM    12
                     37: #define        NUNITS  900
                     38: #define        NBUF    256             /* Length of longest line */
                     39: #define        UMAGIC  0123456         /* Magic number written in binary header */
                     40: 
                     41: /*
                     42:  * Header for the units file.
                     43:  * This  tells that it is the real
                     44:  * thing and how much to read in.
                     45:  */
                     46: typedef        struct  HDR {
                     47:        unsigned h_magic;
                     48:        unsigned h_nunits;
                     49:        unsigned h_ssize;               /* String space size */
                     50: }      HDR;
                     51: 
                     52: HDR    hdr;
                     53: 
                     54: typedef        struct  UNIT {
                     55:        char    *u_name;
                     56:        double  u_val;
                     57:        char    u_dim[NDIM];
                     58: }      UNIT;
                     59: 
                     60: UNIT   *units;
                     61: struct stat    sb;
                     62: char   ufile[] = "/usr/lib/units";
                     63: char   binufile[] = "/usr/lib/binunits";
                     64: char   buf[NBUF];
                     65: char   inbuf[BUFSIZ];
                     66: 
                     67: int nunits;
                     68: int    uflag;                  /* Update information only */
                     69: FILE *fd;
                     70: int peekc = EOF;
                     71: int lastc = EOF;
                     72: int lineno = 1;
                     73: 
                     74: char   *getname();
                     75: char   *prefix();
                     76: char   *alloc();
                     77: 
                     78: main(argc, argv)
                     79: int argc;
                     80: char *argv[];
                     81: {
                     82:        UNIT have, want;
                     83:        register int i;
                     84: 
                     85:        setbuf(stdout, NULL);
                     86:        setbuf(stderr, NULL);
                     87:        if (argc>1 && *argv[1]=='-') {
                     88:                if (argv[1][1]=='u' && argv[1][2]=='\0')
                     89:                        uflag++;
                     90:                else {
                     91:                        fprintf(stderr, "Usage: units [-u]\n");
                     92:                        exit(1);
                     93:                }
                     94:        }
                     95:        init();
                     96:        setbuf(fd = stdin, inbuf);
                     97: Again:
                     98:        if (!getunit(&have, "You have: ")
                     99:        || !getunit(&want, "You want: "))
                    100:                exit(0);
                    101:        for (i=0; i!=NDIM; i++)
                    102:                if (have.u_dim[i] != want.u_dim[i]) {
                    103:                        printf("Conformability\n");
                    104:                        punit(&have);
                    105:                        punit(&want);
                    106:                        goto Again;
                    107:                }
                    108:        printf("* %g\n/ %g\n", have.u_val/want.u_val, want.u_val/have.u_val);
                    109:        goto Again;
                    110: }
                    111: 
                    112: /*
                    113:  * Initialise by reading in units information
                    114:  * either in binary or ascii form and updating
                    115:  * the binary information.
                    116:  */
                    117: init()
                    118: {
                    119:        if (!binary())
                    120:                update();
                    121:        printf("%d units\n", nunits);
                    122:        peekc = EOF;
                    123:        if (uflag)
                    124:                exit(0);
                    125:        /*
                    126:         * Throw away super-user information
                    127:         */
                    128:        setuid(getuid());
                    129: }
                    130: 
                    131: /*
                    132:  * Attempt to read in the already-stored
                    133:  * binary information.  Return non-zero if
                    134:  * successful.
                    135:  */
                    136: binary()
                    137: {
                    138:        register char *sstart;
                    139:        register int n;
                    140:        register int bfd;
                    141:        time_t timeasc;
                    142: 
                    143:        if (stat(ufile, &sb) < 0)
                    144:                return (0);
                    145:        timeasc = sb.st_mtime;
                    146:        if ((bfd = open(binufile, 0))<0 || fstat(bfd, &sb)<0)
                    147:                return (0);
                    148:        if (timeasc > sb.st_mtime)      /* Out of date? */
                    149:                goto bad1;
                    150:        if (read(bfd, &hdr, sizeof(hdr)) != sizeof(hdr))
                    151:                goto bad1;
                    152:        if (hdr.h_magic != UMAGIC)
                    153:                goto bad1;
                    154:        nunits = hdr.h_nunits;
                    155:        sstart = alloc(hdr.h_ssize);
                    156:        if (read(bfd, sstart, hdr.h_ssize) != hdr.h_ssize)
                    157:                goto bad;
                    158:        units = (UNIT *)alloc(n = nunits*sizeof(UNIT));
                    159:        if (read(bfd, units, n) != n)
                    160:                goto bad;
                    161:        for (n=0; n!=nunits; n++)
                    162:                units[n].u_name += (long)sstart;
                    163:        close(bfd);
                    164:        return (1);
                    165: bad:
                    166:        brk(sstart);
                    167: bad1:
                    168:        close(bfd);
                    169:        return (0);
                    170: }
                    171: 
                    172: /*
                    173:  * Update units information by reading the
                    174:  * units file.
                    175:  */
                    176: update()
                    177: {
                    178:        register char *name;
                    179:        register int i;
                    180:        register char *sstart, *send;
                    181:        register int bfd;
                    182: 
                    183:        fprintf(stderr, "Rebuilding %s from %s ...\n", binufile, ufile);
                    184:        if ((fd = fopen(ufile, "r")) == NULL)
                    185:                cerr("can't open unit file `%s'", ufile);
                    186:        setbuf(fd, inbuf);
                    187:        units = (UNIT *)alloc(NUNITS*sizeof(UNIT));
                    188:        sstart = sbrk(0);
                    189:        for (nunits=0; nunits!=NUNITS; nunits++) {
                    190:                name = getname();
                    191:                for (i=0; i!=nunits; i++)
                    192:                        if (strcmp(units[i].u_name, name) == 0)
                    193:                                fprintf(stderr, "`%s' redefined, line %d\n",
                    194:                                        name, lineno);
                    195:                units[nunits].u_name = name;
                    196:                if (!getunit(&units[nunits], NULL))
                    197:                        break;
                    198:        }
                    199:        send = sbrk(0);
                    200:        if (!feof(fd))
                    201:                cerr("too many units");
                    202:        fclose(fd);
                    203:        /*
                    204:         * Write out, if possible, binary
                    205:         * information for faster response next time.
                    206:         */
                    207:        if ((bfd = creat(binufile, 0644)) >= 0) {
                    208:                hdr.h_magic = UMAGIC;
                    209:                hdr.h_nunits = nunits;
                    210:                hdr.h_ssize = send-sstart;
                    211:                if (write(bfd, &hdr, sizeof(hdr)) != sizeof(hdr))
                    212:                        goto bad;
                    213:                if (write(bfd, sstart, hdr.h_ssize) != hdr.h_ssize)
                    214:                        goto bad;
                    215:                for (i=0; i!=nunits; i++)
                    216:                        units[i].u_name -= (long)sstart;/* Rel. address */
                    217:                write(bfd, units, nunits*sizeof(UNIT));
                    218:                for (i=0; i!=nunits; i++)
                    219:                        units[i].u_name += (long)sstart;
                    220:        bad:
                    221:                close(bfd);
                    222:        }
                    223: }
                    224: 
                    225: nextc()
                    226: {
                    227:        register int c;
                    228: 
                    229:        if (peekc != EOF) {
                    230:                c = peekc;
                    231:                peekc = EOF;
                    232:                return (c);
                    233:        }
                    234:        if (lastc == '\n')
                    235:                lineno++;
                    236:        lastc = getc(fd);
                    237:        if (lastc == '#') {     /* Eat a comment */
                    238:                do {
                    239:                        lastc = getc(fd);
                    240:                } while(lastc!='\n' && lastc!=EOF);
                    241:        }
                    242:        return (lastc);
                    243: }
                    244: 
                    245: char *
                    246: getname()
                    247: {
                    248:        register char *s, *t;
                    249:        register int c;
                    250:        register char *v;
                    251: 
                    252:        do {
                    253:                c = nextc();
                    254:        } while(c==' ' || c=='\n' || c=='\t');
                    255:        s = buf;
                    256:        while(c!=' ' && c!='\t' && c!='\n' && c!=EOF) {
                    257:                *s++ = c;
                    258:                c = nextc();
                    259:        }
                    260:        *s = '\0';
                    261:        peekc = c;
                    262:        v = t = alloc(strlen(buf)+1);
                    263:        s = buf;
                    264:        while (*t++ = *s++)
                    265:                ;
                    266:        return (v);
                    267: }
                    268: 
                    269: punit(u)
                    270: register UNIT *u;
                    271: {
                    272:        register int i;
                    273: 
                    274:        printf("%g", u->u_val);
                    275:        for (i=0; i!=NDIM; i++)
                    276:                if (u->u_dim[i] == 1)
                    277:                        printf(" %s", units[i].u_name);
                    278:                else if (u->u_dim[i] > 0)
                    279:                        printf(" %s+%d", units[i].u_name, u->u_dim[i]);
                    280:                else if (u->u_dim[i] < 0)
                    281:                        printf(" %s-%d", units[i].u_name, -u->u_dim[i]);
                    282:        printf("\n");
                    283: }
                    284: 
                    285: double
                    286: ipow(d, n)
                    287: double d;
                    288: {
                    289:        double v;
                    290: 
                    291:        v = 1.;
                    292:        if (n < 0) {
                    293:                d = 1./d;
                    294:                n = -n;
                    295:        }
                    296:        while (n) {
                    297:                v *= d;
                    298:                --n;
                    299:        }
                    300:        return (v);
                    301: }
                    302: 
                    303: struct{
                    304:        char *prefix;
                    305:        double factor;
                    306: }pre[]={
                    307: "femto",       1e-15,
                    308: "pico",                1e-12,
                    309: "nano",                1e-9,
                    310: "micro",       1e-6,
                    311: "milli",       1e-3,
                    312: "centi",       1e-2,
                    313: "deci",                1e-1,
                    314: "hemi",                .5,
                    315: "demi",                .5,
                    316: "semi",                .5,
                    317: "sesqui",      1.5,
                    318: "deka",                1e1,
                    319: "hecto",       1e2,
                    320: "hekto",       1e2,    /* common (?) misspelling */
                    321: "kilo",                1e3,
                    322: "myria",       1e5,
                    323: "mega",                1e6,
                    324: "giga",                1e9,
                    325: "tera",                1e12,
                    326: NULL,          1.
                    327: };
                    328: /*
                    329:  * Return the string stripped of its
                    330:  * prefix (if any).  Set factor
                    331:  * to the multiplicative factor indicated by
                    332:  * the prefix found.
                    333:  */
                    334: char *
                    335: prefix(str, factor)
                    336: char *str;
                    337: double *factor;
                    338: {
                    339:        register char *s, *t;
                    340:        register int i;
                    341: 
                    342:        for (i=0; pre[i].prefix!=NULL; i++) {
                    343:                s = pre[i].prefix;
                    344:                t = str;
                    345:                while (*s != '\0')
                    346:                        if (*s++ != *t++)
                    347:                                break;
                    348:                if (*s == '\0') {
                    349:                        *factor = *factor * pre[i].factor;
                    350:                        return (t);
                    351:                }
                    352:        }
                    353:        return(NULL);
                    354: }
                    355: 
                    356: getunit(u, prompt)
                    357: UNIT *u;
                    358: char *prompt;
                    359: {
                    360:        register int c;
                    361:        register char *s;
                    362:        register int i;
                    363:        int j, expon, digit, div, pow;
                    364:        double factor;
                    365:        double atof();
                    366: 
                    367: Again:
                    368:        if (prompt != NULL)
                    369:                printf("%s", prompt);
                    370:        u->u_val = 1.;
                    371:        for (i=0; i != NDIM; i++)
                    372:                u->u_dim[i] = 0;
                    373:        div = 0;
                    374:        pow = 1;
                    375:        for(;;)switch(c=nextc()){
                    376:        case ' ':
                    377:        case '\t':
                    378:                break;
                    379:        case '\n':
                    380:                return (1);
                    381:        case EOF:
                    382:                return (0);
                    383:        case '0':case '1':case '2':case '3':case '4':
                    384:        case '5':case '6':case '7':case '8':case '9':
                    385:        case '.':case '-':case '+':
                    386:                /*
                    387:                 * a palpable number
                    388:                 */
                    389:                s = buf;
                    390:                if (c == '+')
                    391:                        c = nextc();
                    392:                digit = 0;
                    393:                while (c>='0' && c<='9') {
                    394:                        *s++ = c;
                    395:                        c = nextc();
                    396:                        digit++;
                    397:                }
                    398:                if (c == '.') {
                    399:                        *s++ = c;
                    400:                        while ((c=nextc())>='0' && c<='9') {
                    401:                                *s++ = c;
                    402:                                digit++;
                    403:                        }
                    404:                }
                    405:                if (!digit) {
                    406:                Badnumber:
                    407:                        *s = '\0';
                    408:                        fprintf(stderr, "Bad number `%s'\n", buf);
                    409:                        goto Bad;
                    410:                }
                    411:                if (c=='e' || c=='E') {
                    412:                        *s++ = 'e';
                    413:                        c = nextc();
                    414:                        if (c == '+')
                    415:                                c = nextc();
                    416:                        else if (c == '-') {
                    417:                                *s++ = c;
                    418:                                c = nextc();
                    419:                        }
                    420:                        if (c<'0' || '9'<c)
                    421:                                goto Badnumber;
                    422:                        do {
                    423:                                *s++ = c;
                    424:                                c = nextc();
                    425:                        } while('0'<=c && c<='9');
                    426:                }
                    427:                *s = '\0';
                    428:                peekc = c;
                    429:                factor = atof(buf);
                    430:                if (div) {
                    431:                        if (factor == 0.) {
                    432:                                fprintf(stderr, "Divide check\n");
                    433:                                goto Bad;
                    434:                        }
                    435:                        u->u_val /= factor;
                    436:                        div = 0;
                    437:                } else
                    438:                        u->u_val *= factor;
                    439:                break;
                    440: 
                    441:        case '/':       /* divide by next unit */
                    442:                if (div) {
                    443:                Baddiv:
                    444:                        fprintf(stderr, "Two division signs in a row\n");
                    445:                        goto Bad;
                    446:                }
                    447:                div++;
                    448:                break;
                    449: 
                    450:        case '!':       /* primitive unit */
                    451:                i = 0;
                    452:                if ((c = nextc())<'0' || c>'9') {
                    453:                        fprintf(stderr, "`!' must precede a number\n");
                    454:                        goto Bad;
                    455:                }
                    456:                do {
                    457:                        i = i*10+c-'0';
                    458:                        c = nextc();
                    459:                } while('0'<=c && c<='9');
                    460:                peekc = c;
                    461:                if (i<0 || NDIM<=i) {
                    462:                        printf("Primitive unit out of range [0,%d]\n", NDIM-1);
                    463:                        goto Bad;
                    464:                }
                    465:                u->u_dim[i]++;
                    466:                break;
                    467: 
                    468:        default:
                    469:                s = buf;
                    470:                do {
                    471:                        *s++ = c;
                    472:                        c = nextc();
                    473:                } while(c!=EOF && !anyc(c, "/0123456789+-. \t\n"));
                    474:                *s = '\0';
                    475:                s = buf;
                    476:                if (strcmp(s, "per") == 0) {
                    477:                        if (div)
                    478:                                goto Baddiv;
                    479:                        div++;
                    480:                        break;
                    481:                }
                    482:                if (strcmp(s, "square")==0 || strcmp(s, "sq")==0) {
                    483:                        pow *= 2;
                    484:                        break;
                    485:                }
                    486:                if (strcmp(s, "cubic")==0 || strcmp(s, "cu")==0) {
                    487:                        pow *= 3;
                    488:                        break;
                    489:                }
                    490:                factor = 1.;
                    491:                do {
                    492:                        for (i=0; i!=nunits; i++)
                    493:                                if (eqplural(s, units[i].u_name))
                    494:                                        break;
                    495:                } while(i==nunits && (s=prefix(s, &factor))!=NULL);
                    496:                if (i == nunits) {
                    497:                        fprintf(stderr, "Unrecognised unit %s\n", buf);
                    498:                        goto Bad;
                    499:                }
                    500:                if (c=='+' || c=='-') {
                    501:                        if (c == '-')
                    502:                                div = !div;
                    503:                        expon = 0;
                    504:                        if ((c = nextc())<'0' || c>'9') {
                    505:                                printf("+ or - must be followed by digits\n");
                    506:                                goto Bad;
                    507:                        }
                    508:                        do {
                    509:                                expon = expon*10+c-'0';
                    510:                                c = nextc();
                    511:                        } while('0'<=c && c<='9');
                    512:                } else
                    513:                        expon = 1;
                    514:                expon *= pow;
                    515:                pow = 1;
                    516:                peekc = c;
                    517:                if (div) {
                    518:                        expon = -expon;
                    519:                        div = 0;
                    520:                }
                    521:                u->u_val *= ipow(factor*units[i].u_val, expon);
                    522:                for (j=0; j!=NDIM; j++)
                    523:                        u->u_dim[j] += units[i].u_dim[j]*expon;
                    524:        }
                    525: Bad:
                    526:        while (c!='\n' && c!=EOF)
                    527:                c = nextc();
                    528:        if (prompt!=NULL)
                    529:                goto Again;
                    530:        printf("line %d\n", lineno);
                    531:        return (1);
                    532: }
                    533: 
                    534: /*
                    535:  * Check for any occurrences of
                    536:  * the character `c' in string `s'.
                    537:  */
                    538: anyc(c, s)
                    539: register char c;
                    540: register char *s;
                    541: {
                    542:        while (*s != '\0')
                    543:                if (c == *s++)
                    544:                        return (1);
                    545:        return (0);
                    546: }
                    547: 
                    548: /*
                    549:  * Return non-zero if string `s' is the
                    550:  * same or plural as string `t'.
                    551:  */
                    552: eqplural(s, t)
                    553: register char *s, *t;
                    554: {
                    555:        while (*t != '\0')
                    556:                if (*s++ != *t++)
                    557:                        return (0);
                    558:        return (*s=='\0' || (*s++=='s' && *s=='\0'));
                    559: }
                    560: 
                    561: /*
                    562:  * Diagnostics
                    563:  */
                    564: /* VARARGS */
                    565: cerr(x)
                    566: {
                    567:        fprintf(stderr, "units: %r\n", &x);
                    568:        exit(1);
                    569: }
                    570: 
                    571: /*
                    572:  * Use sbrk for alloc to get
                    573:  * contiguous memory.
                    574:  */
                    575: char *
                    576: alloc(nb)
                    577: unsigned nb;
                    578: {
                    579:        register char *rp;
                    580: 
                    581:        if ((rp = sbrk(nb)) == NULL)
                    582:                cerr("out of memory");
                    583:        return (rp);
                    584: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.