Annotation of coherent/d/bin/awk/awk1.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * AWK
        !             3:  * Main routine.
        !             4:  * Lexical analysis of input.
        !             5:  * Program input routines.
        !             6:  * Error message routines.
        !             7:  */
        !             8: 
        !             9: #include "awk.h"
        !            10: #include "y.tab.h"
        !            11: 
        !            12: CHAR   *readclass();
        !            13: NODE   *instring();
        !            14: NODE   *innumber();
        !            15: 
        !            16: /*
        !            17:  * Main routine of AWK.
        !            18:  */
        !            19: main(argc, argv)
        !            20: int argc;
        !            21: CHAR *argv[];
        !            22: {
        !            23:        register int i;
        !            24:        register CHAR *ap;
        !            25:        register FILE *fp;
        !            26:        register CHAR *prog = NULL;
        !            27:        register CHAR *progfile;
        !            28:        NODE *yyparse();
        !            29: 
        !            30:        awkinit();
        !            31:        while (argc>1 && *argv[1]=='-') {
        !            32:                if (argv[1][1] == '\0')
        !            33:                        break;          /* - is stdin */
        !            34:                switch (argv[1][1]) {
        !            35:                case 'F':
        !            36:                        sassign(FSp, &argv[1][2]);
        !            37:                        break;
        !            38: 
        !            39:                case 'f':
        !            40:                        if (argc < 2)
        !            41:                                usage();
        !            42:                        if ((pfp = fopen(argv[2], "r")) == NULL)
        !            43:                                awkerr("Cannot open %s", argv[2]);
        !            44:                        setbuf(pfp, inbuf);
        !            45:                        progfile = argv[2];
        !            46:                        argv++;
        !            47:                        argc--;
        !            48:                        break;
        !            49: 
        !            50:                case 'y':
        !            51:                        yflag++;
        !            52:                        break;
        !            53: 
        !            54:                default:
        !            55:                        usage();
        !            56:                }
        !            57:                argv++;
        !            58:                argc--;
        !            59:        }
        !            60:        if (argc>1 && pfp==NULL) {
        !            61:                prog = argv[1];
        !            62:                argv++;
        !            63:                argc--;
        !            64:        }
        !            65:        if (pfp==NULL && prog==NULL)
        !            66:                usage();
        !            67:        while (argc>1 && parameter(argv[1])) {
        !            68:                argv++;
        !            69:                argc--;
        !            70:        }
        !            71:        pgetinit(prog);
        !            72:        if (pfp != NULL) {
        !            73:                lineno = 1;
        !            74:                sassign(FILENAMEp, progfile);
        !            75:        }
        !            76:        yyparse();
        !            77:        if (pfp != NULL)
        !            78:                fclose(pfp);
        !            79:        fsmapinit(FS);
        !            80:        runflag = 1;
        !            81:        beginflag = 1;
        !            82:        if (setjmp(nextenv) == 0)
        !            83:                awk(codep, NULL, SNULL);
        !            84:        beginflag = 0;
        !            85:        if (argc > 1) {
        !            86:                for (i=1; i<argc; i++) {
        !            87:                        ap = argv[i];
        !            88:                        if (ap[0]=='-' && ap[1]=='\0')
        !            89:                                fp = stdin;
        !            90:                        else if ((fp = fopen(ap, "r")) == NULL) {
        !            91:                                fprintf(stderr, "awk: cannot open %s\n", ap);
        !            92:                                exit(1);
        !            93:                        }
        !            94:                        awk(codep, fp, ap);
        !            95:                }
        !            96:        } else
        !            97:                awk(codep, stdin, SNULL);
        !            98:        awkexit(0);
        !            99: }
        !           100: 
        !           101: /*
        !           102:  * Read a parameter from the command line.
        !           103:  * Return non-zero if the string is a parameter.
        !           104:  * We have to fudge a bit to make sure `yylex'
        !           105:  * is properly reset.
        !           106:  */
        !           107: parameter(s)
        !           108: CHAR *s;
        !           109: {
        !           110:        register CHAR *cp;
        !           111:        register int c;
        !           112:        NODE *left, *right;
        !           113: 
        !           114:        cp = s;
        !           115:        if (!isalpha(*cp))
        !           116:                return (0);
        !           117:        for (; (c = *cp)!='='; cp++) {
        !           118:                if (c == '\0')
        !           119:                        return (0);
        !           120:                if (isspace(c)) {
        !           121:                        *cp = '\0';
        !           122:                        continue;
        !           123:                }
        !           124:                if (!(isalpha(c) || isdigit(c)))
        !           125:                        return (0);
        !           126:        }
        !           127:        *cp++ = '\0';
        !           128:        left = lookup(s);
        !           129:        while (isspace(c = *cp++))
        !           130:                ;
        !           131:        pgetinit(cp);
        !           132:        if (c == '"')
        !           133:                right = instring(c);
        !           134:        else if (isdigit(c) || c=='.')
        !           135:                right = innumber(c);
        !           136:        else
        !           137:                awkerr("non-constant assignment to parameter `%s'", s);
        !           138:        xassign(left, right);
        !           139:        return (1);
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * Leave awk and run the
        !           144:  * cleanup (`END') phase.
        !           145:  */
        !           146: awkexit(s)
        !           147: int s;
        !           148: {
        !           149:        register OFILE *ofp;
        !           150: 
        !           151:        beginflag = 0;
        !           152:        endflag = 1;
        !           153:        exitflag = 1;
        !           154:        if (setjmp(nextenv) == 0)
        !           155:                awk(codep, NULL, SNULL);
        !           156:        for (ofp = files; ofp < endof(files); ofp++)
        !           157:                if (ofp->of_fp != NULL) {
        !           158:                        if (ofp->of_flag & OFPIPE)
        !           159:                                pclose(ofp->of_fp); else
        !           160:                                fclose(ofp->of_fp);
        !           161:                }
        !           162:        exit(s);
        !           163: }
        !           164: 
        !           165: /*
        !           166:  * Lexical analyser.
        !           167:  * This must have flags to
        !           168:  * determine when certain
        !           169:  * types of characters are
        !           170:  * special (e.g. reading regular
        !           171:  * expressions)
        !           172:  * Delete multiple newlines.
        !           173:  */
        !           174: yylex()
        !           175: {
        !           176:        static int nlf = 1;
        !           177:        static int prev, next;
        !           178:        register CHAR *cp;
        !           179:        register int c;
        !           180:        register int t;
        !           181:        register NODE *np;
        !           182: 
        !           183:        if (lexre)
        !           184:                return (relex());
        !           185: again:
        !           186:        if (next) {
        !           187:                t = next;
        !           188:                next = 0;
        !           189:        } else if ((t = c = pgetc()) == EOF)
        !           190:                ;
        !           191:        else if (!isascii(c))
        !           192:                awkerr("%o is an illegal character", c);
        !           193:        else if (isdigit(c) || c=='.') {
        !           194:                yylval.u_node = innumber(c);
        !           195:                t = NUMBER_;
        !           196:        } else if (isalpha(c)) {
        !           197:                cp = wordbuf;
        !           198:                do {
        !           199:                        *cp++ = c;
        !           200:                        c = pgetc();
        !           201:                } while (isalpha(c) || isdigit(c));
        !           202:                pungetc(c);
        !           203:                *cp = '\0';
        !           204:                np = lookup(wordbuf);
        !           205:                if (np->t_op == AKEYW)
        !           206:                        t = np->t_INT;
        !           207:                else if (np->t_op == AFUNC) {
        !           208:                        t = FUNCTION_;
        !           209:                        yylval.u_node = np;
        !           210:                } else {
        !           211:                        t = ID_;
        !           212:                        yylval.u_node = np;
        !           213:                }
        !           214:        } else switch (c) {
        !           215: 
        !           216:        case '"':
        !           217:                yylval.u_node = instring(c);
        !           218:                t = STRING_;
        !           219:                break;
        !           220: 
        !           221:        case '#':
        !           222:                while ((c = pgetc())!=EOF && c!='\n')
        !           223:                        ;
        !           224:                pungetc(c);
        !           225:                goto again;
        !           226: 
        !           227:        case '{':
        !           228:                brlevel++;
        !           229:                break;
        !           230: 
        !           231:        case '}':
        !           232:                if (--brlevel < 0) {
        !           233:                        awkerr("Unbalanced braces");
        !           234:                        brlevel = 0;
        !           235:                }
        !           236:                next = '}';
        !           237:                t = ';';
        !           238:                break;
        !           239: 
        !           240:        case '!':
        !           241:                if (checkop('~'))
        !           242:                        t = NMATCH_;
        !           243:                else if (checkop('='))
        !           244:                        t = NE_;
        !           245:                break;
        !           246: 
        !           247:        case '|':
        !           248:                if (checkop('|'))
        !           249:                        t = OROR_;
        !           250:                break;
        !           251: 
        !           252:        case '&':
        !           253:                if (checkop('&'))
        !           254:                        t = ANDAND_;
        !           255:                break;
        !           256: 
        !           257:        case '+':
        !           258:                if (checkop('='))
        !           259:                        t = ASADD_;
        !           260:                else if (checkop('+'))
        !           261:                        t = INC_;
        !           262:                break;
        !           263: 
        !           264:        case '-':
        !           265:                if (checkop('='))
        !           266:                        t = ASSUB_;
        !           267:                else if (checkop('-'))
        !           268:                        t = DEC_;
        !           269:                break;
        !           270: 
        !           271:        case '*':
        !           272:                if (checkop('='))
        !           273:                        t = ASMUL_;
        !           274:                break;
        !           275: 
        !           276:        case '/':
        !           277:                if (checkop('='))
        !           278:                        t = ASDIV_;
        !           279:                break;
        !           280: 
        !           281:        case '%':
        !           282:                if (checkop('='))
        !           283:                        t = ASDIV_;
        !           284:                break;
        !           285: 
        !           286:        case '>':
        !           287:                if (checkop('='))
        !           288:                        t = GE_;
        !           289:                else if (checkop('>'))
        !           290:                        t = FAPPEND_;
        !           291:                else if (outflag)
        !           292:                        t = FOUT_;
        !           293:                break;
        !           294: 
        !           295:        case '<':
        !           296:                if (checkop('='))
        !           297:                        t = LE_;
        !           298:                break;
        !           299: 
        !           300:        case '=':
        !           301:                if (checkop('='))
        !           302:                        t = EQ_;
        !           303:                break;
        !           304: 
        !           305:        case '\n':
        !           306:                if (nlf || nlskip)
        !           307:                        goto again;
        !           308:                if (brlevel)
        !           309:                        t = ';';
        !           310:                break;
        !           311: 
        !           312:        case ' ':
        !           313:        case '\t':
        !           314:                goto again;
        !           315:        }
        !           316:        nlf = nlskip = 0;
        !           317:        if (t==ELSE_ && prev!=';' && prev!='\n' && prev!='}') {
        !           318:                next = t;
        !           319:                t = ';';
        !           320:        } else if (t == '\n')
        !           321:                nlf++;
        !           322:        if (t==';') {
        !           323:                outflag = 0;
        !           324:                if (prev == ';')
        !           325:                        goto again;
        !           326:        }
        !           327:        return (prev = t);
        !           328: }
        !           329: 
        !           330: /*
        !           331:  * Part of lexical analyser
        !           332:  * for reading regular expressions.
        !           333:  */
        !           334: relex()
        !           335: {
        !           336:        register int c;
        !           337:        register int n, max;
        !           338: 
        !           339:        switch (c = pgetc()) {
        !           340:        case '?':
        !           341:                return (REZOCL_);
        !           342: 
        !           343:        case '*':
        !           344:                return (RECLOS_);
        !           345: 
        !           346:        case '+':
        !           347:                return (RENECL_);
        !           348: 
        !           349:        case '^':
        !           350:                return (REBOL_);
        !           351: 
        !           352:        case '$':
        !           353:                return (REEOL_);
        !           354: 
        !           355:        case '.':
        !           356:                return (REANY_);
        !           357: 
        !           358:        case '|':
        !           359:                return (REOR_);
        !           360: 
        !           361:        case '(':
        !           362:        case ')':
        !           363:        case '/':
        !           364:                return (c);
        !           365: 
        !           366:        case '[':
        !           367:                yylval.u_charp = readclass();
        !           368:                return (RECLASS_);
        !           369: 
        !           370:        case EOF:
        !           371:        case '\n':
        !           372:                awkerr("Non-terminated regular expression");
        !           373: 
        !           374:        case '\\':
        !           375:                c = pgetc();
        !           376:                if (c>='0' && c<='7') {
        !           377:                        n = 0;
        !           378:                        max = 3;
        !           379:                        do {
        !           380:                                n = (n<<3) + c - '0';
        !           381:                                if ((c=pgetc())<'0' || c>'7')
        !           382:                                        break;
        !           383:                        } while (--max);
        !           384:                        pungetc(c);
        !           385:                        c = n;
        !           386:                }
        !           387:        default:
        !           388:                yylval.u_char = c;
        !           389:                return (RECHAR_);
        !           390:        }
        !           391: }
        !           392: 
        !           393: /*
        !           394:  * Check for dual-character operators.
        !           395:  * such as `+=' and return 1 if so.
        !           396:  * This looks for a match on the next
        !           397:  * character `nc'.
        !           398:  */
        !           399: checkop(nc)
        !           400: int nc;
        !           401: {
        !           402:        register int c;
        !           403: 
        !           404:        if ((c = pgetc()) == nc)
        !           405:                return (1);
        !           406:        pungetc(c);
        !           407:        return (0);
        !           408: }
        !           409: 
        !           410: /*
        !           411:  * Read in a character class from
        !           412:  * a regular expression (called from relex).
        !           413:  */
        !           414: CHAR *
        !           415: readclass()
        !           416: {
        !           417:        register CHAR *cc;
        !           418:        register c, i, pc;
        !           419:        int comp;
        !           420: 
        !           421:        cc = xalloc(NCLASS);
        !           422:        for (i=0; i<NCLASS; i++)
        !           423:                cc[i] = 0;
        !           424:        if ((c = pgetc()) != '^') {
        !           425:                comp = 0;
        !           426:                pungetc(c);
        !           427:        } else
        !           428:                comp = 1;
        !           429:        pc = EOF;
        !           430:        while ((c = pgetc()) != ']') {
        !           431:                if (c==EOF || c=='\n')
        !           432:                        awkerr("Non-terminated character class");
        !           433:                if (c=='-' && pc!=EOF) {
        !           434:                        if ((c = pgetc()) == ']')
        !           435:                                break;
        !           436:                        for (i=pc; i<=c; i++)
        !           437:                                cc[i/NBPC] |= 1<<(i%NBPC);
        !           438:                        pc = EOF;
        !           439:                } else {
        !           440:                        cc[c/NBPC] |= 1<<(c%NBPC);
        !           441:                        pc = c;
        !           442:                }
        !           443:        }
        !           444:        if (comp) {
        !           445:                cc[0] ^= 1;
        !           446:                for (i=0; i<NCLASS; i++)
        !           447:                        cc[i] ^= -1;
        !           448:        }
        !           449:        return (cc);
        !           450: }
        !           451: 
        !           452: /*
        !           453:  * Return a string read from
        !           454:  * the program file.
        !           455:  * The string is to be terminated
        !           456:  * with `ec'.
        !           457:  */
        !           458: NODE *
        !           459: instring(ec)
        !           460: register int ec;
        !           461: {
        !           462:        register CHAR *cp;
        !           463:        register int c;
        !           464:        register int octal, nc;
        !           465: 
        !           466:        cp = wordbuf;
        !           467:        while ((c = pgetc()) != ec) {
        !           468:                if (c=='\n' || c==EOF)
        !           469:                        awkerr("%s in string", c==EOF ? "EOF" : "Newline");
        !           470:                if (c == '\\') {
        !           471:                        switch (c = pgetc()) {
        !           472:                        case 'r':
        !           473:                                c = '\r';
        !           474:                                break;
        !           475: 
        !           476:                        case 'n':
        !           477:                                c = '\n';
        !           478:                                break;
        !           479: 
        !           480:                        case 'b':
        !           481:                                c = '\b';
        !           482:                                break;
        !           483: 
        !           484:                        case 't':
        !           485:                                c = '\t';
        !           486:                                break;
        !           487: 
        !           488:                        default:
        !           489:                                if (c>='0' && c<='7') {
        !           490:                                        octal = 0;
        !           491:                                        nc = 3;
        !           492:                                        for (;;) {
        !           493:                                                octal = octal*8 + c - '0';
        !           494:                                                if (--nc <= 0)
        !           495:                                                        break;
        !           496:                                                c = pgetc();
        !           497:                                                if (c==ec || c<'0' || c>'7') {
        !           498:                                                        pungetc(c);
        !           499:                                                        break;
        !           500:                                                }
        !           501:                                        }
        !           502:                                        c = octal;
        !           503:                                }
        !           504:                        }
        !           505:                }
        !           506:                if (cp < &wordbuf[NWORD-1])
        !           507:                        *cp++ = c;
        !           508:                else {
        !           509:                        awkerr("Character string too long");
        !           510:                        break;
        !           511:                }
        !           512:        }
        !           513:        *cp = '\0';
        !           514:        cp = xalloc(strlen(wordbuf)+sizeof(CHAR));
        !           515:        strcpy(cp, wordbuf);
        !           516:        return (snode(cp, T_ALLOC));
        !           517: }
        !           518: 
        !           519: /*
        !           520:  * Read a number from the
        !           521:  * program file.
        !           522:  */
        !           523: NODE *
        !           524: innumber(c)
        !           525: register int c;
        !           526: {
        !           527:        register CHAR *np;
        !           528:        register int floatflag = 0;
        !           529: 
        !           530:        np = wordbuf;
        !           531:        for (;;) {
        !           532:                if (c == '.')
        !           533:                        floatflag++;
        !           534:                *np++ = c;
        !           535:                c = pgetc();
        !           536:                if (c=='e' || c=='E') {
        !           537:                        floatflag++;
        !           538:                        *np++ = c;
        !           539:                        if ((c = pgetc())=='-' || c=='+') {
        !           540:                                *np++ = c;
        !           541:                                c = pgetc();
        !           542:                        }
        !           543:                        do {
        !           544:                                *np++ = c;
        !           545:                                c = pgetc();
        !           546:                        } while (c>='0' && c<='9');
        !           547:                        break;
        !           548:                }
        !           549:                if (c!='.' && !(c>='0' && c<='9'))
        !           550:                        break;
        !           551:        }
        !           552:        pungetc(c);
        !           553:        *np = '\0';
        !           554:        return (floatflag ? fnode(stof(wordbuf)) : inode(stoi(wordbuf)));
        !           555: }

unix.superglobalmegacorp.com

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