Annotation of rpl/rplawk/tran.c, revision 1.1

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

CVSweb interface <joel.bertrand@systella.fr>