[BACK]Return to tran.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / awk

Annotation of src/usr.bin/awk/tran.c, Revision 1.10

1.10    ! pvalchev    1: /*     $OpenBSD: tran.c,v 1.9 2003/04/04 00:42:34 deraadt Exp $        */
1.1       tholo       2: /****************************************************************
1.3       kstailey    3: Copyright (C) Lucent Technologies 1997
1.1       tholo       4: All Rights Reserved
                      5:
                      6: Permission to use, copy, modify, and distribute this software and
                      7: its documentation for any purpose and without fee is hereby
                      8: granted, provided that the above copyright notice appear in all
                      9: copies and that both that the copyright notice and this
                     10: permission notice and warranty disclaimer appear in supporting
1.3       kstailey   11: documentation, and that the name Lucent Technologies or any of
                     12: its entities not be used in advertising or publicity pertaining
                     13: to distribution of the software without specific, written prior
                     14: permission.
                     15:
                     16: LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
                     17: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
                     18: IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
                     19: SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     20: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
                     21: IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     22: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
                     23: THIS SOFTWARE.
1.1       tholo      24: ****************************************************************/
                     25:
                     26: #define        DEBUG
                     27: #include <stdio.h>
                     28: #include <math.h>
                     29: #include <ctype.h>
                     30: #include <string.h>
                     31: #include <stdlib.h>
                     32: #include "awk.h"
1.3       kstailey   33: #include "ytab.h"
1.1       tholo      34:
                     35: #define        FULLTAB 2       /* rehash when table gets this x full */
                     36: #define        GROWTAB 4       /* grow table by this factor */
                     37:
                     38: Array  *symtab;        /* main symbol table */
                     39:
                     40: char   **FS;           /* initial field sep */
                     41: char   **RS;           /* initial record sep */
                     42: char   **OFS;          /* output field sep */
                     43: char   **ORS;          /* output record sep */
                     44: char   **OFMT;         /* output format for numbers */
                     45: char   **CONVFMT;      /* format for conversions in getsval */
                     46: Awkfloat *NF;          /* number of fields in current record */
                     47: Awkfloat *NR;          /* number of current record */
                     48: Awkfloat *FNR;         /* number of current record in current file */
                     49: char   **FILENAME;     /* current filename argument */
                     50: Awkfloat *ARGC;                /* number of arguments from command line */
                     51: char   **SUBSEP;       /* subscript separator for a[i,j,k]; default \034 */
                     52: Awkfloat *RSTART;      /* start of re matched with ~; origin 1 (!) */
                     53: Awkfloat *RLENGTH;     /* length of same */
                     54:
                     55: Cell   *nrloc;         /* NR */
                     56: Cell   *nfloc;         /* NF */
                     57: Cell   *fnrloc;        /* FNR */
                     58: Array  *ARGVtab;       /* symbol table containing ARGV[...] */
                     59: Array  *ENVtab;        /* symbol table containing ENVIRON[...] */
                     60: Cell   *rstartloc;     /* RSTART */
                     61: Cell   *rlengthloc;    /* RLENGTH */
                     62: Cell   *symtabloc;     /* SYMTAB */
                     63:
                     64: Cell   *nullloc;       /* a guaranteed empty cell */
                     65: Node   *nullnode;      /* zero&null, converted into a node for comparisons */
1.3       kstailey   66: Cell   *literal0;
1.1       tholo      67:
1.3       kstailey   68: extern Cell **fldtab;
1.1       tholo      69:
                     70: void syminit(void)     /* initialize symbol table with builtin vars */
                     71: {
1.3       kstailey   72:        literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
1.1       tholo      73:        /* this is used for if(x)... tests: */
                     74:        nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
1.3       kstailey   75:        nullnode = celltonode(nullloc, CCON);
1.1       tholo      76:
                     77:        FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
                     78:        RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
                     79:        OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
                     80:        ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
                     81:        OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
                     82:        CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
1.2       millert    83:        FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
1.1       tholo      84:        nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
                     85:        NF = &nfloc->fval;
                     86:        nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
                     87:        NR = &nrloc->fval;
                     88:        fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
                     89:        FNR = &fnrloc->fval;
                     90:        SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
                     91:        rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
                     92:        RSTART = &rstartloc->fval;
                     93:        rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
                     94:        RLENGTH = &rlengthloc->fval;
                     95:        symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
                     96:        symtabloc->sval = (char *) symtab;
                     97: }
                     98:
1.3       kstailey   99: void arginit(int ac, char **av)        /* set up ARGV and ARGC */
1.1       tholo     100: {
                    101:        Cell *cp;
                    102:        int i;
1.3       kstailey  103:        char temp[50];
1.1       tholo     104:
                    105:        ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
                    106:        cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
                    107:        ARGVtab = makesymtab(NSYMTAB);  /* could be (int) ARGC as well */
                    108:        cp->sval = (char *) ARGVtab;
                    109:        for (i = 0; i < ac; i++) {
1.9       deraadt   110:                snprintf(temp, sizeof temp, "%d", i);
1.4       millert   111:                if (is_number(*av))
1.1       tholo     112:                        setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
                    113:                else
                    114:                        setsymtab(temp, *av, 0.0, STR, ARGVtab);
                    115:                av++;
                    116:        }
                    117: }
                    118:
                    119: void envinit(char **envp)      /* set up ENVIRON variable */
                    120: {
                    121:        Cell *cp;
                    122:        char *p;
                    123:
                    124:        cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
                    125:        ENVtab = makesymtab(NSYMTAB);
                    126:        cp->sval = (char *) ENVtab;
                    127:        for ( ; *envp; envp++) {
1.3       kstailey  128:                if ((p = strchr(*envp, '=')) == NULL)
1.1       tholo     129:                        continue;
1.7       millert   130:                if( p == *envp ) /* no left hand side name in env string */
                    131:                        continue;
1.1       tholo     132:                *p++ = 0;       /* split into two strings at = */
1.4       millert   133:                if (is_number(p))
1.1       tholo     134:                        setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
                    135:                else
                    136:                        setsymtab(*envp, p, 0.0, STR, ENVtab);
                    137:                p[-1] = '=';    /* restore in case env is passed down to a shell */
                    138:        }
                    139: }
                    140:
                    141: Array *makesymtab(int n)       /* make a new symbol table */
                    142: {
                    143:        Array *ap;
                    144:        Cell **tp;
                    145:
                    146:        ap = (Array *) malloc(sizeof(Array));
                    147:        tp = (Cell **) calloc(n, sizeof(Cell *));
                    148:        if (ap == NULL || tp == NULL)
1.6       millert   149:                FATAL("out of space in makesymtab");
1.1       tholo     150:        ap->nelem = 0;
                    151:        ap->size = n;
                    152:        ap->tab = tp;
                    153:        return(ap);
                    154: }
                    155:
                    156: void freesymtab(Cell *ap)      /* free a symbol table */
                    157: {
                    158:        Cell *cp, *temp;
                    159:        Array *tp;
                    160:        int i;
                    161:
                    162:        if (!isarr(ap))
                    163:                return;
                    164:        tp = (Array *) ap->sval;
                    165:        if (tp == NULL)
                    166:                return;
                    167:        for (i = 0; i < tp->size; i++) {
                    168:                for (cp = tp->tab[i]; cp != NULL; cp = temp) {
                    169:                        xfree(cp->nval);
                    170:                        if (freeable(cp))
                    171:                                xfree(cp->sval);
                    172:                        temp = cp->cnext;       /* avoids freeing then using */
1.3       kstailey  173:                        free(cp);
1.8       millert   174:                        tp->nelem--;
1.1       tholo     175:                }
                    176:                tp->tab[i] = 0;
                    177:        }
1.8       millert   178:        if (tp->nelem != 0)
                    179:                WARNING("can't happen: inconsistent element count freeing %s", ap->nval);
1.3       kstailey  180:        free(tp->tab);
                    181:        free(tp);
1.1       tholo     182: }
                    183:
1.8       millert   184: void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */
1.1       tholo     185: {
                    186:        Array *tp;
                    187:        Cell *p, *prev = NULL;
                    188:        int h;
                    189:
                    190:        tp = (Array *) ap->sval;
                    191:        h = hash(s, tp->size);
                    192:        for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
1.3       kstailey  193:                if (strcmp(s, p->nval) == 0) {
1.1       tholo     194:                        if (prev == NULL)       /* 1st one */
                    195:                                tp->tab[h] = p->cnext;
                    196:                        else                    /* middle somewhere */
                    197:                                prev->cnext = p->cnext;
                    198:                        if (freeable(p))
                    199:                                xfree(p->sval);
                    200:                        free(p->nval);
1.3       kstailey  201:                        free(p);
1.1       tholo     202:                        tp->nelem--;
                    203:                        return;
                    204:                }
                    205: }
                    206:
1.8       millert   207: Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp)
1.1       tholo     208: {
                    209:        int h;
                    210:        Cell *p;
                    211:
                    212:        if (n != NULL && (p = lookup(n, tp)) != NULL) {
1.3       kstailey  213:                   dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
1.8       millert   214:                        p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
1.1       tholo     215:                return(p);
                    216:        }
                    217:        p = (Cell *) malloc(sizeof(Cell));
                    218:        if (p == NULL)
1.6       millert   219:                FATAL("out of space for symbol table at %s", n);
1.1       tholo     220:        p->nval = tostring(n);
                    221:        p->sval = s ? tostring(s) : tostring("");
                    222:        p->fval = f;
                    223:        p->tval = t;
                    224:        p->csub = CUNK;
                    225:        p->ctype = OCELL;
                    226:        tp->nelem++;
                    227:        if (tp->nelem > FULLTAB * tp->size)
                    228:                rehash(tp);
                    229:        h = hash(n, tp->size);
                    230:        p->cnext = tp->tab[h];
                    231:        tp->tab[h] = p;
1.3       kstailey  232:           dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
1.1       tholo     233:                p, p->nval, p->sval, p->fval, p->tval) );
                    234:        return(p);
                    235: }
                    236:
1.8       millert   237: int hash(const char *s, int n) /* form hash value for string s */
1.1       tholo     238: {
                    239:        unsigned hashval;
                    240:
                    241:        for (hashval = 0; *s != '\0'; s++)
                    242:                hashval = (*s + 31 * hashval);
                    243:        return hashval % n;
                    244: }
                    245:
                    246: void rehash(Array *tp) /* rehash items in small table into big one */
                    247: {
                    248:        int i, nh, nsz;
                    249:        Cell *cp, *op, **np;
                    250:
                    251:        nsz = GROWTAB * tp->size;
                    252:        np = (Cell **) calloc(nsz, sizeof(Cell *));
                    253:        if (np == NULL)         /* can't do it, but can keep running. */
                    254:                return;         /* someone else will run out later. */
                    255:        for (i = 0; i < tp->size; i++) {
                    256:                for (cp = tp->tab[i]; cp; cp = op) {
                    257:                        op = cp->cnext;
                    258:                        nh = hash(cp->nval, nsz);
                    259:                        cp->cnext = np[nh];
                    260:                        np[nh] = cp;
                    261:                }
                    262:        }
1.3       kstailey  263:        free(tp->tab);
1.1       tholo     264:        tp->tab = np;
                    265:        tp->size = nsz;
                    266: }
                    267:
1.8       millert   268: Cell *lookup(const char *s, Array *tp) /* look for s in tp */
1.1       tholo     269: {
1.5       millert   270:        Cell *p;
1.1       tholo     271:        int h;
                    272:
                    273:        h = hash(s, tp->size);
1.5       millert   274:        for (p = tp->tab[h]; p != NULL; p = p->cnext)
1.3       kstailey  275:                if (strcmp(s, p->nval) == 0)
1.1       tholo     276:                        return(p);      /* found it */
                    277:        return(NULL);                   /* not found */
                    278: }
                    279:
                    280: Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
                    281: {
1.3       kstailey  282:        int fldno;
                    283:
1.1       tholo     284:        if ((vp->tval & (NUM | STR)) == 0)
                    285:                funnyvar(vp, "assign to");
1.3       kstailey  286:        if (isfld(vp)) {
1.1       tholo     287:                donerec = 0;    /* mark $0 invalid */
1.3       kstailey  288:                fldno = atoi(vp->nval);
                    289:                if (fldno > *NF)
                    290:                        newfld(fldno);
                    291:                   dprintf( ("setting field %d to %g\n", fldno, f) );
                    292:        } else if (isrec(vp)) {
1.1       tholo     293:                donefld = 0;    /* mark $1... invalid */
                    294:                donerec = 1;
                    295:        }
1.4       millert   296:        if (freeable(vp))
                    297:                xfree(vp->sval); /* free any previous string */
1.1       tholo     298:        vp->tval &= ~STR;       /* mark string invalid */
                    299:        vp->tval |= NUM;        /* mark number ok */
1.8       millert   300:           dprintf( ("setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) );
1.1       tholo     301:        return vp->fval = f;
                    302: }
                    303:
1.8       millert   304: void funnyvar(Cell *vp, const char *rw)
1.1       tholo     305: {
1.3       kstailey  306:        if (isarr(vp))
1.6       millert   307:                FATAL("can't %s %s; it's an array name.", rw, vp->nval);
1.1       tholo     308:        if (vp->tval & FCN)
1.6       millert   309:                FATAL("can't %s %s; it's a function.", rw, vp->nval);
                    310:        WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
                    311:                vp, vp->nval, vp->sval, vp->fval, vp->tval);
1.1       tholo     312: }
                    313:
1.8       millert   314: char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
1.1       tholo     315: {
                    316:        char *t;
1.3       kstailey  317:        int fldno;
1.1       tholo     318:
1.8       millert   319:           dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, NN(vp->nval), s, vp->tval) );
1.1       tholo     320:        if ((vp->tval & (NUM | STR)) == 0)
                    321:                funnyvar(vp, "assign to");
1.3       kstailey  322:        if (isfld(vp)) {
1.1       tholo     323:                donerec = 0;    /* mark $0 invalid */
1.3       kstailey  324:                fldno = atoi(vp->nval);
                    325:                if (fldno > *NF)
                    326:                        newfld(fldno);
                    327:                   dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) );
                    328:        } else if (isrec(vp)) {
1.1       tholo     329:                donefld = 0;    /* mark $1... invalid */
                    330:                donerec = 1;
                    331:        }
                    332:        t = tostring(s);        /* in case it's self-assign */
                    333:        vp->tval &= ~NUM;
                    334:        vp->tval |= STR;
                    335:        if (freeable(vp))
                    336:                xfree(vp->sval);
                    337:        vp->tval &= ~DONTFREE;
1.8       millert   338:           dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), t,t, vp->tval) );
1.1       tholo     339:        return(vp->sval = t);
                    340: }
                    341:
                    342: Awkfloat getfval(Cell *vp)     /* get float val of a Cell */
                    343: {
                    344:        if ((vp->tval & (NUM | STR)) == 0)
                    345:                funnyvar(vp, "read value of");
1.3       kstailey  346:        if (isfld(vp) && donefld == 0)
1.1       tholo     347:                fldbld();
1.3       kstailey  348:        else if (isrec(vp) && donerec == 0)
1.1       tholo     349:                recbld();
                    350:        if (!isnum(vp)) {       /* not a number */
                    351:                vp->fval = atof(vp->sval);      /* best guess */
1.4       millert   352:                if (is_number(vp->sval) && !(vp->tval&CON))
1.1       tholo     353:                        vp->tval |= NUM;        /* make NUM only sparingly */
                    354:        }
1.8       millert   355:           dprintf( ("getfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), vp->fval, vp->tval) );
1.1       tholo     356:        return(vp->fval);
                    357: }
                    358:
1.8       millert   359:  static char *get_str_val(Cell *vp, char **fmt)        /* get string val of a Cell */
                    360:
1.1       tholo     361: {
1.3       kstailey  362:        char s[100];    /* BUG: unchecked */
1.1       tholo     363:        double dtemp;
                    364:
                    365:        if ((vp->tval & (NUM | STR)) == 0)
                    366:                funnyvar(vp, "read value of");
1.3       kstailey  367:        if (isfld(vp) && donefld == 0)
1.1       tholo     368:                fldbld();
1.3       kstailey  369:        else if (isrec(vp) && donerec == 0)
1.1       tholo     370:                recbld();
1.3       kstailey  371:        if (isstr(vp) == 0) {
                    372:                if (freeable(vp))
1.1       tholo     373:                        xfree(vp->sval);
                    374:                if (modf(vp->fval, &dtemp) == 0)        /* it's integral */
1.10    ! pvalchev  375:                        snprintf(s, sizeof(s), "%.30g", vp->fval);
1.1       tholo     376:                else
1.10    ! pvalchev  377:                        snprintf(s, sizeof(s), *fmt, vp->fval);
1.1       tholo     378:                vp->sval = tostring(s);
                    379:                vp->tval &= ~DONTFREE;
                    380:                vp->tval |= STR;
                    381:        }
1.8       millert   382:           dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
1.1       tholo     383:        return(vp->sval);
                    384: }
                    385:
1.8       millert   386: char *getsval(Cell *vp)       /* get string val of a Cell */
                    387: {
                    388:       return get_str_val(vp, CONVFMT);
                    389: }
                    390:
                    391: char *getpssval(Cell *vp)     /* get string val of a Cell for print */
                    392: {
                    393:       return get_str_val(vp, OFMT);
                    394: }
                    395:
                    396:
                    397: char *tostring(const char *s)  /* make a copy of string s */
1.1       tholo     398: {
1.10    ! pvalchev  399:        return (strdup(s));
1.1       tholo     400: }
                    401:
1.8       millert   402: char *qstring(const char *is, int delim)       /* collect string up to next delim */
1.1       tholo     403: {
1.8       millert   404:        const char *os = is;
1.1       tholo     405:        int c, n;
1.7       millert   406:        uschar *s = (uschar *) is;
                    407:        uschar *buf, *bp;
1.1       tholo     408:
1.8       millert   409:        if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL)
1.6       millert   410:                FATAL( "out of space in qstring(%s)", s);
1.3       kstailey  411:        for (bp = buf; (c = *s) != delim; s++) {
1.1       tholo     412:                if (c == '\n')
1.6       millert   413:                        SYNTAX( "newline in string %.20s...", os );
1.1       tholo     414:                else if (c != '\\')
1.3       kstailey  415:                        *bp++ = c;
1.6       millert   416:                else {  /* \something */
                    417:                        c = *++s;
                    418:                        if (c == 0) {   /* \ at end */
                    419:                                *bp++ = '\\';
                    420:                                break;  /* for loop */
                    421:                        }
                    422:                        switch (c) {
1.3       kstailey  423:                        case '\\':      *bp++ = '\\'; break;
                    424:                        case 'n':       *bp++ = '\n'; break;
                    425:                        case 't':       *bp++ = '\t'; break;
                    426:                        case 'b':       *bp++ = '\b'; break;
                    427:                        case 'f':       *bp++ = '\f'; break;
                    428:                        case 'r':       *bp++ = '\r'; break;
1.1       tholo     429:                        default:
                    430:                                if (!isdigit(c)) {
1.3       kstailey  431:                                        *bp++ = c;
1.1       tholo     432:                                        break;
                    433:                                }
                    434:                                n = c - '0';
                    435:                                if (isdigit(s[1])) {
                    436:                                        n = 8 * n + *++s - '0';
                    437:                                        if (isdigit(s[1]))
                    438:                                                n = 8 * n + *++s - '0';
                    439:                                }
1.3       kstailey  440:                                *bp++ = n;
1.1       tholo     441:                                break;
                    442:                        }
1.3       kstailey  443:                }
1.1       tholo     444:        }
1.3       kstailey  445:        *bp++ = 0;
1.7       millert   446:        return (char *) buf;
1.1       tholo     447: }