Annotation of coherent/d/bin/awk/awk1.c, revision 1.1.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.