Annotation of researchv10no/cmd/awk/lib.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 <string.h>
                     14: #include <ctype.h>
                     15: #include <errno.h>
                     16: #include <stdlib.h>
                     17: #include "awk.h"
                     18: #include "y.tab.h"
                     19: 
                     20: #define        getfval(p)      (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
                     21: #define        getsval(p)      (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
                     22: 
                     23: FILE   *infile = NULL;
                     24: uchar  *file   = (uchar*) "";
                     25: int    recsize = RECSIZE;
                     26: uchar  *recdata;
                     27: uchar  *record;
                     28: uchar  *fields;
                     29: Cell   *fldtab;
                     30: 
                     31: #define        MAXFLD  200
                     32: int    nfields = MAXFLD;       /* can be set from commandline in main */
                     33: 
                     34: int    donefld;        /* 1 = implies rec broken into fields */
                     35: int    donerec;        /* 1 = record is valid (no flds have changed) */
                     36: 
                     37: int    maxfld  = 0;    /* last used field */
                     38: int    argno   = 1;    /* current input argument number */
                     39: extern Awkfloat *ARGC;
                     40: 
                     41: void recinit(unsigned int n)
                     42: {
                     43:        static Cell dollar0 = {
                     44:            OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE};
                     45:        static Cell dollar1 = {
                     46:            OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE };
                     47:        int i;
                     48: 
                     49:        record = recdata = (uchar *) malloc(n);
                     50:        fields = (uchar *) malloc(n);
                     51:        fldtab = (Cell *) malloc(nfields * sizeof(Cell));
                     52:        if (recdata == NULL || fields == NULL || fldtab == NULL)
                     53:                ERROR "out of space for $0 and fields" FATAL;
                     54:        fldtab[0] = dollar0;
                     55:        fldtab[0].sval = recdata;
                     56:        for (i = 1; i < nfields; i++)
                     57:                fldtab[i] = dollar1;
                     58: }
                     59: 
                     60: void initgetrec(void)
                     61: {
                     62:        int i;
                     63:        uchar *p;
                     64: 
                     65:        for (i = 1; i < *ARGC; i++) {
                     66:                if (!isclvar(p = getargv(i)))   /* find 1st real filename */
                     67:                        return;
                     68:                setclvar(p);    /* a commandline assignment before filename */
                     69:                argno++;
                     70:        }
                     71:        infile = stdin;         /* no filenames, so use stdin */
                     72:        /* *FILENAME = file = (uchar*) "-"; */
                     73: }
                     74: 
                     75: getrec(uchar *buf)
                     76: {
                     77:        int c;
                     78:        static int firsttime = 1;
                     79: 
                     80:        if (firsttime) {
                     81:                firsttime = 0;
                     82:                initgetrec();
                     83:        }
                     84:        dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
                     85:                *RS, *FS, *ARGC, *FILENAME) );
                     86:        donefld = 0;
                     87:        donerec = 1;
                     88:        buf[0] = 0;
                     89:        while (argno < *ARGC || infile == stdin) {
                     90:                dprintf( ("argno=%d, file=|%s|\n", argno, file) );
                     91:                if (infile == NULL) {   /* have to open a new file */
                     92:                        file = getargv(argno);
                     93:                        if (*file == '\0') {    /* it's been zapped */
                     94:                                argno++;
                     95:                                continue;
                     96:                        }
                     97:                        if (isclvar(file)) {    /* a var=value arg */
                     98:                                setclvar(file);
                     99:                                argno++;
                    100:                                continue;
                    101:                        }
                    102:                        *FILENAME = file;
                    103:                        dprintf( ("opening file %s\n", file) );
                    104:                        if (*file == '-' && *(file+1) == '\0')
                    105:                                infile = stdin;
                    106:                        else if ((infile = fopen((char *)file, "r")) == NULL)
                    107:                                ERROR "can't open file %s", file FATAL;
                    108:                        setfval(fnrloc, 0.0);
                    109:                }
                    110:                c = readrec(buf, recsize, infile);
                    111:                if (c != 0 || buf[0] != '\0') { /* normal record */
                    112:                        if (buf == record) {
                    113:                                if (!(recloc->tval & DONTFREE))
                    114:                                        xfree(recloc->sval);
                    115:                                recloc->sval = record;
                    116:                                recloc->tval = REC | STR | DONTFREE;
                    117:                                if (isnumber(recloc->sval)) {
                    118:                                        recloc->fval = atof(recloc->sval);
                    119:                                        recloc->tval |= NUM;
                    120:                                }
                    121:                        }
                    122:                        setfval(nrloc, nrloc->fval+1);
                    123:                        setfval(fnrloc, fnrloc->fval+1);
                    124:                        return 1;
                    125:                }
                    126:                /* EOF arrived on this file; set up next */
                    127:                if (infile != stdin)
                    128:                        fclose(infile);
                    129:                infile = NULL;
                    130:                argno++;
                    131:        }
                    132:        return 0;       /* true end of file */
                    133: }
                    134: 
                    135: readrec(uchar *buf, int bufsize, FILE *inf)    /* read one record into buf */
                    136: {
                    137:        register int sep, c;
                    138:        register uchar *rr;
                    139:        register int nrr;
                    140: 
                    141:        if ((sep = **RS) == 0) {
                    142:                sep = '\n';
                    143:                while ((c=getc(inf)) == '\n' && c != EOF)       /* skip leading \n's */
                    144:                        ;
                    145:                if (c != EOF)
                    146:                        ungetc(c, inf);
                    147:        }
                    148:        for (rr = buf, nrr = bufsize; ; ) {
                    149:                for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c)
                    150:                        if (--nrr < 0)
                    151:                                ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
                    152:                if (**RS == sep || c == EOF)
                    153:                        break;
                    154:                if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
                    155:                        break;
                    156:                *rr++ = '\n';
                    157:                *rr++ = c;
                    158:        }
                    159:        if (rr > buf + bufsize)
                    160:                ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
                    161:        *rr = 0;
                    162:        dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
                    163:        return c == EOF && rr == buf ? 0 : 1;
                    164: }
                    165: 
                    166: uchar *getargv(int n)  /* get ARGV[n] */
                    167: {
                    168:        Cell *x;
                    169:        uchar *s, temp[10];
                    170:        extern Array *ARGVtab;
                    171: 
                    172:        sprintf((char *)temp, "%d", n);
                    173:        x = setsymtab(temp, "", 0.0, STR, ARGVtab);
                    174:        s = getsval(x);
                    175:        dprintf( ("getargv(%d) returns |%s|\n", n, s) );
                    176:        return s;
                    177: }
                    178: 
                    179: void setclvar(uchar *s)        /* set var=value from s */
                    180: {
                    181:        uchar *p;
                    182:        Cell *q;
                    183: 
                    184:        for (p=s; *p != '='; p++)
                    185:                ;
                    186:        *p++ = 0;
                    187:        p = qstring(p, '\0');
                    188:        q = setsymtab(s, p, 0.0, STR, symtab);
                    189:        setsval(q, p);
                    190:        if (isnumber(q->sval)) {
                    191:                q->fval = atof(q->sval);
                    192:                q->tval |= NUM;
                    193:        }
                    194:        dprintf( ("command line set %s to |%s|\n", s, p) );
                    195: }
                    196: 
                    197: 
                    198: void fldbld(void)
                    199: {
                    200:        register uchar *r, *fr, sep;
                    201:        Cell *p;
                    202:        int i;
                    203: 
                    204:        if (donefld)
                    205:                return;
                    206:        if (!(recloc->tval & STR))
                    207:                getsval(recloc);
                    208:        r = recloc->sval;       /* was record! */
                    209:        fr = fields;
                    210:        i = 0;  /* number of fields accumulated here */
                    211:        if (strlen(*FS) > 1) {  /* it's a regular expression */
                    212:                i = refldbld(r, *FS);
                    213:        } else if ((sep = **FS) == ' ') {
                    214:                for (i = 0; ; ) {
                    215:                        while (*r == ' ' || *r == '\t' || *r == '\n')
                    216:                                r++;
                    217:                        if (*r == 0)
                    218:                                break;
                    219:                        i++;
                    220:                        if (i >= nfields)
                    221:                                break;
                    222:                        if (!(fldtab[i].tval & DONTFREE))
                    223:                                xfree(fldtab[i].sval);
                    224:                        fldtab[i].sval = fr;
                    225:                        fldtab[i].tval = FLD | STR | DONTFREE;
                    226:                        do
                    227:                                *fr++ = *r++;
                    228:                        while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
                    229:                        *fr++ = 0;
                    230:                }
                    231:                *fr = 0;
                    232:        } else if (*r != 0) {   /* if 0, it's a null field */
                    233:                for (;;) {
                    234:                        i++;
                    235:                        if (i >= nfields)
                    236:                                break;
                    237:                        if (!(fldtab[i].tval & DONTFREE))
                    238:                                xfree(fldtab[i].sval);
                    239:                        fldtab[i].sval = fr;
                    240:                        fldtab[i].tval = FLD | STR | DONTFREE;
                    241:                        while (*r != sep && *r != '\n' && *r != '\0')   /* \n always a separator */
                    242:                                *fr++ = *r++;
                    243:                        *fr++ = 0;
                    244:                        if (*r++ == 0)
                    245:                                break;
                    246:                }
                    247:                *fr = 0;
                    248:        }
                    249:        if (i >= nfields)
                    250:                ERROR "record `%.20s...' has too many fields; try -mf n", record FATAL;
                    251:        /* clean out junk from previous record */
                    252:        cleanfld(i, maxfld);
                    253:        maxfld = i;
                    254:        donefld = 1;
                    255:        for (p = fldtab+1; p <= fldtab+maxfld; p++) {
                    256:                if(isnumber(p->sval)) {
                    257:                        p->fval = atof(p->sval);
                    258:                        p->tval |= NUM;
                    259:                }
                    260:        }
                    261:        setfval(nfloc, (Awkfloat) maxfld);
                    262:        if (dbg)
                    263:                for (p = fldtab; p <= fldtab+maxfld; p++)
                    264:                        printf("field %d: |%s|\n", p-fldtab, p->sval);
                    265: }
                    266: 
                    267: void cleanfld(int n1, int n2)  /* clean out fields n1..n2 inclusive */
                    268: {
                    269:        static uchar *nullstat = (uchar *) "";
                    270:        register Cell *p, *q;
                    271: 
                    272:        for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
                    273:                if (!(p->tval & DONTFREE))
                    274:                        xfree(p->sval);
                    275:                p->tval = FLD | STR | DONTFREE;
                    276:                p->sval = nullstat;
                    277:        }
                    278: }
                    279: 
                    280: void newfld(int n)     /* add field n (after end) */
                    281: {
                    282:        if (n >= nfields)
                    283:                ERROR "creating too many fields; try -mf n", record FATAL;
                    284:        cleanfld(maxfld, n);
                    285:        maxfld = n;
                    286:        setfval(nfloc, (Awkfloat) n);
                    287: }
                    288: 
                    289: refldbld(uchar *rec, uchar *fs)        /* build fields from reg expr in FS */
                    290: {
                    291:        uchar *fr;
                    292:        int i, tempstat;
                    293:        fa *pfa;
                    294: 
                    295:        fr = fields;
                    296:        *fr = '\0';
                    297:        if (*rec == '\0')
                    298:                return 0;
                    299:        pfa = makedfa(fs, 1);
                    300:        dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
                    301:        tempstat = pfa->initstat;
                    302:        for (i = 1; i < nfields; i++) {
                    303:                if (!(fldtab[i].tval & DONTFREE))
                    304:                        xfree(fldtab[i].sval);
                    305:                fldtab[i].tval = FLD | STR | DONTFREE;
                    306:                fldtab[i].sval = fr;
                    307:                dprintf( ("refldbld: i=%d\n", i) );
                    308:                if (nematch(pfa, rec)) {
                    309:                        pfa->initstat = 2;
                    310:                        dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
                    311:                        strncpy(fr, rec, patbeg-rec);
                    312:                        fr += patbeg - rec + 1;
                    313:                        *(fr-1) = '\0';
                    314:                        rec = patbeg + patlen;
                    315:                } else {
                    316:                        dprintf( ("no match %s\n", rec) );
                    317:                        strcpy(fr, rec);
                    318:                        pfa->initstat = tempstat;
                    319:                        break;
                    320:                }
                    321:        }
                    322:        return i;               
                    323: }
                    324: 
                    325: void recbld(void)
                    326: {
                    327:        int i;
                    328:        register uchar *r, *p;
                    329:        static uchar *rec = 0;
                    330: 
                    331:        if (donerec == 1)
                    332:                return;
                    333:        if (rec == 0) {
                    334:                rec = (uchar *) malloc(recsize);
                    335:                if (rec == 0)
                    336:                        ERROR "out of space building $0, record size %d", recsize FATAL;
                    337:        }
                    338:        r = rec;
                    339:        for (i = 1; i <= *NF; i++) {
                    340:                p = getsval(&fldtab[i]);
                    341:                while (r < rec+recsize-1 && (*r = *p++))
                    342:                        r++;
                    343:                if (i < *NF)
                    344:                        for (p = *OFS; r < rec+recsize-1 && (*r = *p++); )
                    345:                                r++;
                    346:        }
                    347:        if (r > rec + recsize - 1)
                    348:                ERROR "built giant record `%.20s...'; try -mr n", record FATAL;
                    349:        *r = '\0';
                    350:        dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
                    351:        recloc->tval = REC | STR | DONTFREE;
                    352:        recloc->sval = record = rec;
                    353:        dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
                    354:        dprintf( ("recbld = |%s|\n", record) );
                    355:        donerec = 1;
                    356: }
                    357: 
                    358: Cell *fieldadr(int n)
                    359: {
                    360:        if (n < 0 || n >= nfields)
                    361:                ERROR "trying to access field %d; try -mf n", n FATAL;
                    362:        return(&fldtab[n]);
                    363: }
                    364: 
                    365: int    errorflag       = 0;
                    366: char   errbuf[200];
                    367: 
                    368: void yyerror(uchar *s)
                    369: {
                    370:        extern uchar *cmdname, *curfname;
                    371:        static int been_here = 0;
                    372: 
                    373:        if (been_here++ > 2)
                    374:                return;
                    375:        fprintf(stderr, "%s: %s", cmdname, s);
                    376:        fprintf(stderr, " at source line %d", lineno);
                    377:        if (curfname != NULL)
                    378:                fprintf(stderr, " in function %s", curfname);
                    379:        fprintf(stderr, "\n");
                    380:        errorflag = 2;
                    381:        eprint();
                    382: }
                    383: 
                    384: void fpecatch(int n)
                    385: {
                    386:        ERROR "floating point exception %d", n FATAL;
                    387: }
                    388: 
                    389: extern int bracecnt, brackcnt, parencnt;
                    390: 
                    391: void bracecheck(void)
                    392: {
                    393:        int c;
                    394:        static int beenhere = 0;
                    395: 
                    396:        if (beenhere++)
                    397:                return;
                    398:        while ((c = input()) != EOF && c != '\0')
                    399:                bclass(c);
                    400:        bcheck2(bracecnt, '{', '}');
                    401:        bcheck2(brackcnt, '[', ']');
                    402:        bcheck2(parencnt, '(', ')');
                    403: }
                    404: 
                    405: void bcheck2(int n, int c1, int c2)
                    406: {
                    407:        if (n == 1)
                    408:                fprintf(stderr, "\tmissing %c\n", c2);
                    409:        else if (n > 1)
                    410:                fprintf(stderr, "\t%d missing %c's\n", n, c2);
                    411:        else if (n == -1)
                    412:                fprintf(stderr, "\textra %c\n", c2);
                    413:        else if (n < -1)
                    414:                fprintf(stderr, "\t%d extra %c's\n", -n, c2);
                    415: }
                    416: 
                    417: void error(int f, char *s)
                    418: {
                    419:        extern Node *curnode;
                    420:        extern uchar *cmdname;
                    421: 
                    422:        fflush(stdout);
                    423:        fprintf(stderr, "%s: ", cmdname);
                    424:        fprintf(stderr, "%s", s);
                    425:        fprintf(stderr, "\n");
                    426:        if (compile_time != 2 && NR && *NR > 0) {
                    427:                fprintf(stderr, " input record number %g", *FNR);
                    428:                if (strcmp(*FILENAME, "-") != 0)
                    429:                        fprintf(stderr, ", file %s", *FILENAME);
                    430:                fprintf(stderr, "\n");
                    431:        }
                    432:        if (compile_time != 2 && curnode)
                    433:                fprintf(stderr, " source line number %d\n", curnode->lineno);
                    434:        else if (compile_time != 2 && lineno)
                    435:                fprintf(stderr, " source line number %d\n", lineno);
                    436:        eprint();
                    437:        if (f) {
                    438:                if (dbg > 1)
                    439:                        abort();
                    440:                exit(2);
                    441:        }
                    442: }
                    443: 
                    444: void eprint(void)      /* try to print context around error */
                    445: {
                    446:        uchar *p, *q;
                    447:        int c;
                    448:        static int been_here = 0;
                    449:        extern uchar ebuf[300], *ep;
                    450: 
                    451:        if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
                    452:                return;
                    453:        p = ep - 1;
                    454:        if (p > ebuf && *p == '\n')
                    455:                p--;
                    456:        for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
                    457:                ;
                    458:        while (*p == '\n')
                    459:                p++;
                    460:        fprintf(stderr, " context is\n\t");
                    461:        for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
                    462:                ;
                    463:        for ( ; p < q; p++)
                    464:                if (*p)
                    465:                        putc(*p, stderr);
                    466:        fprintf(stderr, " >>> ");
                    467:        for ( ; p < ep; p++)
                    468:                if (*p)
                    469:                        putc(*p, stderr);
                    470:        fprintf(stderr, " <<< ");
                    471:        if (*ep)
                    472:                while ((c = input()) != '\n' && c != '\0' && c != EOF) {
                    473:                        putc(c, stderr);
                    474:                        bclass(c);
                    475:                }
                    476:        putc('\n', stderr);
                    477:        ep = ebuf;
                    478: }
                    479: 
                    480: void bclass(int c)
                    481: {
                    482:        switch (c) {
                    483:        case '{': bracecnt++; break;
                    484:        case '}': bracecnt--; break;
                    485:        case '[': brackcnt++; break;
                    486:        case ']': brackcnt--; break;
                    487:        case '(': parencnt++; break;
                    488:        case ')': parencnt--; break;
                    489:        }
                    490: }
                    491: 
                    492: double errcheck(double x, uchar *s)
                    493: {
                    494:        extern int errno;
                    495: 
                    496:        if (errno == EDOM) {
                    497:                errno = 0;
                    498:                ERROR "%s argument out of domain", s WARNING;
                    499:                x = 1;
                    500:        } else if (errno == ERANGE) {
                    501:                errno = 0;
                    502:                ERROR "%s result out of range", s WARNING;
                    503:                x = 1;
                    504:        }
                    505:        return x;
                    506: }
                    507: 
                    508: isclvar(uchar *s)      /* is s of form var=something? */
                    509: {
                    510:        uchar *os = s;
                    511: 
                    512:        if (!isalpha(*s) && *s != '_')
                    513:                return 0;
                    514:        for ( ; *s; s++)
                    515:                if (!(isalnum(*s) || *s == '_'))
                    516:                        break;
                    517:        return *s == '=' && s > os && *(s+1) != '=';
                    518: }
                    519: 
                    520: #define        MAXEXPON        38      /* maximum exponent for fp number */
                    521: 
                    522: isnumber(uchar *s)
                    523: {
                    524:        register int d1, d2;
                    525:        int point;
                    526:        uchar *es;
                    527: 
                    528:        d1 = d2 = point = 0;
                    529:        while (*s == ' ' || *s == '\t' || *s == '\n')
                    530:                s++;
                    531:        if (*s == '\0')
                    532:                return(0);      /* empty stuff isn't number */
                    533:        if (*s == '+' || *s == '-')
                    534:                s++;
                    535:        if (!isdigit(*s) && *s != '.')
                    536:                return(0);
                    537:        if (isdigit(*s)) {
                    538:                do {
                    539:                        d1++;
                    540:                        s++;
                    541:                } while (isdigit(*s));
                    542:        }
                    543:        if (*s == '.') {
                    544:                point++;
                    545:                s++;
                    546:        }
                    547:        if (isdigit(*s)) {
                    548:                d2++;
                    549:                do {
                    550:                        s++;
                    551:                } while (isdigit(*s));
                    552:        }
                    553:        if (!(d1 || point && d2))
                    554:                return(0);
                    555:        if (*s == 'e' || *s == 'E') {
                    556:                s++;
                    557:                if (*s == '+' || *s == '-')
                    558:                        s++;
                    559:                if (!isdigit(*s))
                    560:                        return(0);
                    561:                es = s;
                    562:                do {
                    563:                        s++;
                    564:                } while (isdigit(*s));
                    565:                if (s - es > 2)
                    566:                        return(0);
                    567:                else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
                    568:                        return(0);
                    569:        }
                    570:        while (*s == ' ' || *s == '\t' || *s == '\n')
                    571:                s++;
                    572:        if (*s == '\0')
                    573:                return(1);
                    574:        else
                    575:                return(0);
                    576: }

unix.superglobalmegacorp.com

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