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

1.1     ! root        1: /*
        !             2: Copyright (c) 1989 AT&T
        !             3:        All Rights Reserved
        !             4: 
        !             5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.
        !             6: 
        !             7: The copyright notice above does not evidence any
        !             8: actual or intended publication of such source code.
        !             9: */
        !            10: 
        !            11: #define DEBUG
        !            12: #include <stdio.h>
        !            13: #include <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.