Annotation of researchv10no/cmd/awk/tran.c, revision 1.1

1.1     ! root        1: /*
        !             2: Copyright (c) 1989 AT&T
        !             3:        All Rights Reserved
        !             4: 
        !             5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.
        !             6: 
        !             7: The copyright notice above does not evidence any
        !             8: actual or intended publication of such source code.
        !             9: */
        !            10: 
        !            11: #define        DEBUG
        !            12: #include <stdio.h>
        !            13: #include <math.h>
        !            14: #include <ctype.h>
        !            15: #include <string.h>
        !            16: #include <stdlib.h>
        !            17: #include "awk.h"
        !            18: #include "y.tab.h"
        !            19: 
        !            20: #define        FULLTAB 2       /* rehash when table gets this x full */
        !            21: #define        GROWTAB 4       /* grow table by this factor */
        !            22: 
        !            23: Array  *symtab;        /* main symbol table */
        !            24: 
        !            25: uchar  **FS;           /* initial field sep */
        !            26: uchar  **RS;           /* initial record sep */
        !            27: uchar  **OFS;          /* output field sep */
        !            28: uchar  **ORS;          /* output record sep */
        !            29: uchar  **OFMT;         /* output format for numbers*/
        !            30: Awkfloat *NF;          /* number of fields in current record */
        !            31: Awkfloat *NR;          /* number of current record */
        !            32: Awkfloat *FNR;         /* number of current record in current file */
        !            33: uchar  **FILENAME;     /* current filename argument */
        !            34: Awkfloat *ARGC;                /* number of arguments from command line */
        !            35: uchar  **SUBSEP;       /* subscript separator for a[i,j,k]; default \034 */
        !            36: Awkfloat *RSTART;      /* start of re matched with ~; origin 1 (!) */
        !            37: Awkfloat *RLENGTH;     /* length of same */
        !            38: 
        !            39: Cell   *recloc;        /* location of record */
        !            40: Cell   *nrloc;         /* NR */
        !            41: Cell   *nfloc;         /* NF */
        !            42: Cell   *fnrloc;        /* FNR */
        !            43: Array  *ARGVtab;       /* symbol table containing ARGV[...] */
        !            44: Array  *ENVtab;        /* symbol table containing ENVIRON[...] */
        !            45: Cell   *rstartloc;     /* RSTART */
        !            46: Cell   *rlengthloc;    /* RLENGTH */
        !            47: Cell   *symtabloc;     /* SYMTAB */
        !            48: 
        !            49: Cell   *nullloc;
        !            50: Node   *nullnode;      /* zero&null, converted into a node for comparisons */
        !            51: 
        !            52: extern Cell *fldtab;
        !            53: 
        !            54: void syminit(void)
        !            55: {
        !            56:        /* symtab = makesymtab(NSYMTAB); */
        !            57:        setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
        !            58:        /* this is used for if(x)... tests: */
        !            59:        nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
        !            60:        nullnode = valtonode(nullloc, CCON);
        !            61:        /* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */
        !            62:        recloc = &fldtab[0];
        !            63:        FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
        !            64:        RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
        !            65:        OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
        !            66:        ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
        !            67:        OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
        !            68:        FILENAME = &setsymtab("FILENAME", "-", 0.0, STR|DONTFREE, symtab)->sval;
        !            69:        nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
        !            70:        NF = &nfloc->fval;
        !            71:        nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
        !            72:        NR = &nrloc->fval;
        !            73:        fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
        !            74:        FNR = &fnrloc->fval;
        !            75:        SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
        !            76:        rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
        !            77:        RSTART = &rstartloc->fval;
        !            78:        rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
        !            79:        RLENGTH = &rlengthloc->fval;
        !            80:        symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
        !            81:        symtabloc->sval = (uchar *) symtab;
        !            82: }
        !            83: 
        !            84: void arginit(int ac, uchar *av[])
        !            85: {
        !            86:        Cell *cp;
        !            87:        int i;
        !            88:        uchar temp[5];
        !            89: 
        !            90:        for (i = 1; i < ac; i++)        /* first make FILENAME first real argument */
        !            91:                if (!isclvar(av[i])) {
        !            92:                        setsval(lookup("FILENAME", symtab), av[i]);
        !            93:                        break;
        !            94:                }
        !            95:        ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
        !            96:        cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
        !            97:        ARGVtab = makesymtab(NSYMTAB);  /* could be (int) ARGC as well */
        !            98:        cp->sval = (uchar *) ARGVtab;
        !            99:        for (i = 0; i < ac; i++) {
        !           100:                sprintf((char *)temp, "%d", i);
        !           101:                if (isnumber(*av))
        !           102:                        setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
        !           103:                else
        !           104:                        setsymtab(temp, *av, 0.0, STR, ARGVtab);
        !           105:                av++;
        !           106:        }
        !           107: }
        !           108: 
        !           109: void envinit(uchar **envp)
        !           110: {
        !           111:        Cell *cp;
        !           112:        uchar *p;
        !           113: 
        !           114:        cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
        !           115:        ENVtab = makesymtab(NSYMTAB);
        !           116:        cp->sval = (uchar *) ENVtab;
        !           117:        for ( ; *envp; envp++) {
        !           118:                if ((p = (uchar *) strchr((char *) *envp, '=')) == NULL)        /* index() on bsd */
        !           119:                        continue;
        !           120:                *p++ = 0;       /* split into two strings at = */
        !           121:                if (isnumber(p))
        !           122:                        setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
        !           123:                else
        !           124:                        setsymtab(*envp, p, 0.0, STR, ENVtab);
        !           125:                p[-1] = '=';    /* restore in case env is passed down to a shell */
        !           126:        }
        !           127: }
        !           128: 
        !           129: Array *makesymtab(int n)
        !           130: {
        !           131:        Array *ap;
        !           132:        Cell **tp;
        !           133: 
        !           134:        ap = (Array *) malloc(sizeof(Array));
        !           135:        tp = (Cell **) calloc(n, sizeof(Cell *));
        !           136:        if (ap == NULL || tp == NULL)
        !           137:                ERROR "out of space in makesymtab" FATAL;
        !           138:        ap->nelem = 0;
        !           139:        ap->size = n;
        !           140:        ap->tab = tp;
        !           141:        return(ap);
        !           142: }
        !           143: 
        !           144: void freesymtab(Cell *ap)      /* free symbol table */
        !           145: {
        !           146:        Cell *cp, *temp;
        !           147:        Array *tp;
        !           148:        int i;
        !           149: 
        !           150:        if (!isarr(ap))
        !           151:                return;
        !           152:        tp = (Array *) ap->sval;
        !           153:        if (tp == NULL)
        !           154:                return;
        !           155:        for (i = 0; i < tp->size; i++) {
        !           156:                for (cp = tp->tab[i]; cp != NULL; cp = temp) {
        !           157:                        xfree(cp->nval);
        !           158:                        if (freeable(cp))
        !           159:                                xfree(cp->sval);
        !           160:                        temp = cp->cnext;       /* avoids freeing then using */
        !           161:                        free((char *) cp); 
        !           162:                }
        !           163:        }
        !           164:        free((char *) (tp->tab));
        !           165:        free((char *) tp);
        !           166: }
        !           167: 
        !           168: void freeelem(Cell *ap, uchar *s)      /* free elem s from ap (i.e., ap["s"] */
        !           169: {
        !           170:        Array *tp;
        !           171:        Cell *p, *prev = NULL;
        !           172:        int h;
        !           173:        
        !           174:        tp = (Array *) ap->sval;
        !           175:        h = hash(s, tp->size);
        !           176:        for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
        !           177:                if (strcmp((char *) s, (char *) p->nval) == 0) {
        !           178:                        if (prev == NULL)       /* 1st one */
        !           179:                                tp->tab[h] = p->cnext;
        !           180:                        else                    /* middle somewhere */
        !           181:                                prev->cnext = p->cnext;
        !           182:                        if (freeable(p))
        !           183:                                xfree(p->sval);
        !           184:                        free(p->nval);
        !           185:                        free((char *) p);
        !           186:                        tp->nelem--;
        !           187:                        return;
        !           188:                }
        !           189: }
        !           190: 
        !           191: Cell *setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned t, Array *tp)
        !           192: {
        !           193:        register int h;
        !           194:        register Cell *p;
        !           195: 
        !           196:        if (n != NULL && (p = lookup(n, tp)) != NULL) {
        !           197:                dprintf( ("setsymtab found %o: n=%s", p, p->nval) );
        !           198:                dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
        !           199:                return(p);
        !           200:        }
        !           201:        p = (Cell *) malloc(sizeof(Cell));
        !           202:        if (p == NULL)
        !           203:                ERROR "out of space for symbol table at %s", n FATAL;
        !           204:        p->nval = tostring(n);
        !           205:        p->sval = s ? tostring(s) : tostring("");
        !           206:        p->fval = f;
        !           207:        p->tval = t;
        !           208:        tp->nelem++;
        !           209:        if (tp->nelem > FULLTAB * tp->size)
        !           210:                rehash(tp);
        !           211:        h = hash(n, tp->size);
        !           212:        p->cnext = tp->tab[h];
        !           213:        tp->tab[h] = p;
        !           214:        dprintf( ("setsymtab set %o: n=%s", p, p->nval) );
        !           215:        dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
        !           216:        return(p);
        !           217: }
        !           218: 
        !           219: hash(uchar *s, int n)  /* form hash value for string s */
        !           220: {
        !           221:        register unsigned hashval;
        !           222: 
        !           223:        for (hashval = 0; *s != '\0'; s++)
        !           224:                hashval = (*s + 31 * hashval);
        !           225:        return hashval % n;
        !           226: }
        !           227: 
        !           228: void rehash(Array *tp) /* rehash items in small table into big one */
        !           229: {
        !           230:        int i, nh, nsz;
        !           231:        Cell *cp, *op, **np;
        !           232: 
        !           233:        nsz = GROWTAB * tp->size;
        !           234:        np = (Cell **) calloc(nsz, sizeof(Cell *));
        !           235:        if (np == NULL)         /* can't do it, but can keep running. */
        !           236:                return;         /* someone else will run out later. */
        !           237:        for (i = 0; i < tp->size; i++) {
        !           238:                for (cp = tp->tab[i]; cp; cp = op) {
        !           239:                        op = cp->cnext;
        !           240:                        nh = hash(cp->nval, nsz);
        !           241:                        cp->cnext = np[nh];
        !           242:                        np[nh] = cp;
        !           243:                }
        !           244:        }
        !           245:        free((char *) (tp->tab));
        !           246:        tp->tab = np;
        !           247:        tp->size = nsz;
        !           248: }
        !           249: 
        !           250: Cell *lookup(uchar *s, Array *tp)      /* look for s in tp */
        !           251: {
        !           252:        register Cell *p, *prev = NULL;
        !           253:        int h;
        !           254: 
        !           255:        h = hash(s, tp->size);
        !           256:        for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
        !           257:                if (strcmp((char *) s, (char *) p->nval) == 0)
        !           258:                        return(p);      /* found it */
        !           259:        return(NULL);                   /* not found */
        !           260: }
        !           261: 
        !           262: Awkfloat setfval(Cell *vp, Awkfloat f)
        !           263: {
        !           264:        if ((vp->tval & (NUM | STR)) == 0) 
        !           265:                funnyvar(vp, "assign to");
        !           266:        if (vp->tval & FLD) {
        !           267:                donerec = 0;    /* mark $0 invalid */
        !           268:                if (vp-fldtab > *NF)
        !           269:                        newfld(vp-fldtab);
        !           270:                dprintf( ("setting field %d to %g\n", vp-fldtab, f) );
        !           271:        } else if (vp->tval & REC) {
        !           272:                donefld = 0;    /* mark $1... invalid */
        !           273:                donerec = 1;
        !           274:        }
        !           275:        vp->tval &= ~STR;       /* mark string invalid */
        !           276:        vp->tval |= NUM;        /* mark number ok */
        !           277:        dprintf( ("setfval %o: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) );
        !           278:        return vp->fval = f;
        !           279: }
        !           280: 
        !           281: void funnyvar(Cell *vp, char *rw)
        !           282: {
        !           283:        if (vp->tval & ARR)
        !           284:                ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL;
        !           285:        if (vp->tval & FCN)
        !           286:                ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL;
        !           287:        ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o",
        !           288:                vp, vp->nval, vp->sval, vp->fval, vp->tval WARNING;
        !           289: }
        !           290: 
        !           291: uchar *setsval(Cell *vp, uchar *s)
        !           292: {
        !           293:        if ((vp->tval & (NUM | STR)) == 0)
        !           294:                funnyvar(vp, "assign to");
        !           295:        if (vp->tval & FLD) {
        !           296:                donerec = 0;    /* mark $0 invalid */
        !           297:                if (vp-fldtab > *NF)
        !           298:                        newfld(vp-fldtab);
        !           299:                dprintf( ("setting field %d to %s\n", vp-fldtab, s) );
        !           300:        } else if (vp->tval & REC) {
        !           301:                donefld = 0;    /* mark $1... invalid */
        !           302:                donerec = 1;
        !           303:        }
        !           304:        vp->tval &= ~NUM;
        !           305:        vp->tval |= STR;
        !           306:        if (freeable(vp))
        !           307:                xfree(vp->sval);
        !           308:        vp->tval &= ~DONTFREE;
        !           309:        dprintf( ("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
        !           310:        return(vp->sval = tostring(s));
        !           311: }
        !           312: 
        !           313: Awkfloat r_getfval(Cell *vp)
        !           314: {
        !           315:        /* if (vp->tval & ARR)
        !           316:                ERROR "illegal reference to array %s", vp->nval FATAL;
        !           317:                return 0.0; */
        !           318:        if ((vp->tval & (NUM | STR)) == 0)
        !           319:                funnyvar(vp, "read value of");
        !           320:        if ((vp->tval & FLD) && donefld == 0)
        !           321:                fldbld();
        !           322:        else if ((vp->tval & REC) && donerec == 0)
        !           323:                recbld();
        !           324:        if (!isnum(vp)) {       /* not a number */
        !           325:                vp->fval = atof(vp->sval);      /* best guess */
        !           326:                if (isnumber(vp->sval) && !(vp->tval&CON))
        !           327:                        vp->tval |= NUM;        /* make NUM only sparingly */
        !           328:        }
        !           329:        dprintf( ("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
        !           330:        return(vp->fval);
        !           331: }
        !           332: 
        !           333: uchar *r_getsval(Cell *vp)
        !           334: {
        !           335:        uchar s[100];
        !           336:        double dtemp;
        !           337: 
        !           338:        /* if (vp->tval & ARR)
        !           339:                ERROR "illegal reference to array %s", vp->nval FATAL;
        !           340:                return ""; */
        !           341:        if ((vp->tval & (NUM | STR)) == 0)
        !           342:                funnyvar(vp, "read value of");
        !           343:        if ((vp->tval & FLD) && donefld == 0)
        !           344:                fldbld();
        !           345:        else if ((vp->tval & REC) && donerec == 0)
        !           346:                recbld();
        !           347:        if ((vp->tval & STR) == 0) {
        !           348:                if (!(vp->tval&DONTFREE))
        !           349:                        xfree(vp->sval);
        !           350:                if (modf(vp->fval, &dtemp) == 0)        /* it's integral */
        !           351:                        sprintf((char *)s, "%.20g", vp->fval);
        !           352:                else
        !           353:                        sprintf((char *)s, (char *)*OFMT, vp->fval);
        !           354:                vp->sval = tostring(s);
        !           355:                vp->tval &= ~DONTFREE;
        !           356:                vp->tval |= STR;
        !           357:        }
        !           358:        dprintf( ("getsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval) );
        !           359:        return(vp->sval);
        !           360: }
        !           361: 
        !           362: uchar *tostring(uchar *s)
        !           363: {
        !           364:        register uchar *p;
        !           365: 
        !           366:        p = (uchar *) malloc(strlen((char *) s)+1);
        !           367:        if (p == NULL)
        !           368:                ERROR "out of space in tostring on %s", s FATAL;
        !           369:        strcpy((char *) p, (char *) s);
        !           370:        return(p);
        !           371: }
        !           372: 
        !           373: uchar *qstring(uchar *s, int delim)    /* collect string up to delim */
        !           374: {
        !           375:        uchar *q;
        !           376:        int c, n;
        !           377: 
        !           378:        for (q = cbuf; (c = *s) != delim; s++) {
        !           379:                if (q >= cbuf + CBUFLEN - 1)
        !           380:                        ERROR "string %.10s... too long", cbuf SYNTAX;
        !           381:                else if (c == '\n')
        !           382:                        ERROR "newline in string %.10s...", cbuf SYNTAX;
        !           383:                else if (c != '\\')
        !           384:                        *q++ = c;
        !           385:                else    /* \something */        
        !           386:                        switch (c = *++s) {
        !           387:                        case '\\':      *q++ = '\\'; break;
        !           388:                        case 'n':       *q++ = '\n'; break;
        !           389:                        case 't':       *q++ = '\t'; break;
        !           390:                        case 'b':       *q++ = '\b'; break;
        !           391:                        case 'f':       *q++ = '\f'; break;
        !           392:                        case 'r':       *q++ = '\r'; break;
        !           393:                        default:
        !           394:                                if (!isdigit(c)) {
        !           395:                                        *q++ = c;
        !           396:                                        break;
        !           397:                                }
        !           398:                                n = c - '0';
        !           399:                                if (isdigit(s[1])) {
        !           400:                                        n = 8 * n + *++s - '0';
        !           401:                                        if (isdigit(s[1]))
        !           402:                                                n = 8 * n + *++s - '0';
        !           403:                                }
        !           404:                                *q++ = n;
        !           405:                                break;
        !           406:                        }
        !           407:        }
        !           408:        *q = '\0';
        !           409:        return cbuf;
        !           410: }

unix.superglobalmegacorp.com

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