Annotation of researchv10no/cmd/awk/tran.c, revision 1.1.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.