Annotation of coherent/a/usr/bob/korn/syn.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * shell parser (C version)
        !             3:  */
        !             4: 
        !             5: static char *RCSid = "$Header: syn.c,v 3.1 88/11/03 09:17:23 egisin Exp $";
        !             6: 
        !             7: #include <stddef.h>
        !             8: #include <stdlib.h>
        !             9: #include <stdio.h>
        !            10: #include <string.h>
        !            11: #include <errno.h>
        !            12: #include <setjmp.h>
        !            13: #include "sh.h"
        !            14: #include "lex.h"
        !            15: #include "tree.h"
        !            16: #include "table.h"
        !            17: #include "expand.h"
        !            18: 
        !            19: static void    zzerr();
        !            20: static struct  op *block(), *newtp();
        !            21: static struct  op *pipeline(), *andor(), *command();
        !            22: static struct  op *nested(), *c_list();
        !            23: static struct  op *dogroup(), *thenpart(), *casepart(), *caselist();
        !            24: static struct  op *elsepart();
        !            25: static char  **wordlist();
        !            26: static void    musthave();
        !            27: static struct ioword *synio(), *io();
        !            28: 
        !            29: static struct  op      *outtree; /* yyparse output */
        !            30: 
        !            31: static int     reject;         /* token(cf) gets symbol again */
        !            32: static int     symbol;         /* yylex value */
        !            33: 
        !            34: #define        REJECT  (reject = 1)
        !            35: #define        ACCEPT  (reject = 0)
        !            36: #define        token(cf) \
        !            37:        ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
        !            38: #define        tpeek(cf) \
        !            39:        ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
        !            40: 
        !            41: int
        !            42: yyparse()
        !            43: {
        !            44:        ACCEPT;
        !            45:        yynerrs = 0;
        !            46:        if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
        !            47:                outtree = newtp(TEOF);
        !            48:                return 0;
        !            49:        }
        !            50:        outtree = c_list();
        !            51:        musthave('\n', 0);
        !            52:        return (yynerrs != 0);
        !            53: }
        !            54: 
        !            55: static struct op *
        !            56: pipeline(cf)
        !            57:        int cf;
        !            58: {
        !            59:        register struct op *t, *p, *tl = NULL;
        !            60:        register int c;
        !            61: 
        !            62:        t = command(cf);
        !            63:        if (t != NULL) {
        !            64:                while ((c = token(0)) == '|') {
        !            65:                        if ((p = command(CONTIN)) == NULL)
        !            66:                                SYNTAXERR;
        !            67:                        if (tl == NULL)
        !            68:                                t = tl = block(TPIPE, t, p, NOWORDS);
        !            69:                        else
        !            70:                                tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
        !            71:                        /*t = block(TPIPE, t, p, NOWORDS);*/
        !            72:                }
        !            73:                REJECT;
        !            74:        }
        !            75:        return (t);
        !            76: }
        !            77: 
        !            78: static struct op *
        !            79: andor()
        !            80: {
        !            81:        register struct op *t, *p;
        !            82:        register int c;
        !            83: 
        !            84:        t = pipeline(0);
        !            85:        if (t != NULL) {
        !            86:                while ((c = token(0)) == LOGAND || c == LOGOR) {
        !            87:                        if ((p = pipeline(CONTIN)) == NULL)
        !            88:                                SYNTAXERR;
        !            89:                        t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
        !            90:                }
        !            91:                REJECT;
        !            92:        }
        !            93:        return (t);
        !            94: }
        !            95: 
        !            96: static struct op *
        !            97: c_list()
        !            98: {
        !            99:        register struct op *t, *p, *tl = NULL;
        !           100:        register int c;
        !           101: 
        !           102:        t = andor();
        !           103:        if (t != NULL) {
        !           104:                while ((c = token(0)) == ';' || c == '&' ||
        !           105:                       multiline && c == '\n') {
        !           106:                        if (c == '&')
        !           107:                                t = block(TASYNC, t, NOBLOCK, NOWORDS);
        !           108:                        if ((p = andor()) == NULL)
        !           109:                                return (t);
        !           110:                        if (tl == NULL)
        !           111:                                t = tl = block(TLIST, t, p, NOWORDS);
        !           112:                        else
        !           113:                                tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
        !           114:                }
        !           115:                REJECT;
        !           116:        }
        !           117:        return (t);
        !           118: }
        !           119: 
        !           120: static struct ioword *
        !           121: synio(cf)
        !           122:        int cf;
        !           123: {
        !           124:        register struct ioword *iop;
        !           125:        register int i;
        !           126: 
        !           127:        if (tpeek(cf) != REDIR)
        !           128:                return NULL;
        !           129:        ACCEPT;
        !           130:        i = yylval.i;           /* IO* flags */
        !           131:        musthave(LWORD, 0);
        !           132:        iop = io(iounit, i, yylval.cp);
        !           133:        if (i&IOHERE) {
        !           134:                if (*ident != 0) /* unquoted */
        !           135:                        iop->flag |= IOXHERE;
        !           136:                if (herep >= &heres[HERES])
        !           137:                        errorf("too many <<'s\n");
        !           138:                *herep++ = iop;
        !           139:        }
        !           140:        return iop;
        !           141: }
        !           142: 
        !           143: static void
        !           144: musthave(c, cf)
        !           145:        int c, cf;
        !           146: {
        !           147:        if ((token(cf)) != c)
        !           148:                SYNTAXERR;
        !           149: }
        !           150: 
        !           151: static struct op *
        !           152: nested(type, mark)
        !           153:        int type, mark;
        !           154: {
        !           155:        register struct op *t;
        !           156: 
        !           157:        multiline++;
        !           158:        t = c_list();
        !           159:        musthave(mark, KEYWORD);
        !           160:        multiline--;
        !           161:        return (block(type, t, NOBLOCK, NOWORDS));
        !           162: }
        !           163: 
        !           164: static struct op *
        !           165: command(cf)
        !           166:        int cf;
        !           167: {
        !           168:        register struct op *t;
        !           169:        register int c, iopn = 0;
        !           170:        struct ioword *iop, **iops;
        !           171:        XPtrV args, vars;
        !           172: 
        !           173:        iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
        !           174:        XPinit(args, 16);
        !           175:        XPinit(vars, 16);
        !           176: 
        !           177:        if (multiline)
        !           178:                cf = CONTIN;
        !           179:        cf |= KEYWORD|ALIAS;
        !           180: 
        !           181:        while ((iop = synio(cf)) != NULL) {
        !           182:                if (iopn >= NUFILE)
        !           183:                        yyerror("too many redirections");
        !           184:                iops[iopn++] = iop;
        !           185:                cf &=~ CONTIN;
        !           186:        }
        !           187: 
        !           188:        switch (c = token(cf)) {
        !           189:          case 0:
        !           190:                yyerror("unexpected EOF");
        !           191:                return NULL;
        !           192: 
        !           193:          default:
        !           194:                REJECT;
        !           195:                if (iopn == 0)
        !           196:                        return NULL; /* empty line */
        !           197:                t = newtp(TCOM);
        !           198:                break;
        !           199: 
        !           200:          case LWORD:
        !           201:                REJECT;
        !           202:                t = newtp(TCOM);
        !           203:                while (1)
        !           204:                        switch (tpeek(0)) {
        !           205:                          case REDIR:
        !           206:                                if (iopn >= NUFILE)
        !           207:                                        yyerror("too many redirections");
        !           208:                                iops[iopn++] = synio(0);
        !           209:                                break;
        !           210: 
        !           211:                          case LWORD:
        !           212:                                ACCEPT;
        !           213:                                if ((XPsize(args) == 0 || flag[FKEYWORD])
        !           214:                                    && strchr(ident+1, '='))
        !           215:                                        {XPput(vars, yylval.cp);}
        !           216:                                else
        !           217:                                        {XPput(args, yylval.cp);}
        !           218:                                break;
        !           219: 
        !           220:                          case MPAREN:
        !           221:                                ACCEPT;
        !           222:                                if (XPsize(args) != 1)
        !           223:                                        SYNTAXERR;
        !           224:                                if (*ident == 0)
        !           225:                                        yyerror("invalid function name\n");
        !           226:                                t = newtp(TFUNCT);
        !           227:                                t->str = strsave(ident, ATEMP);
        !           228:                                musthave('{', CONTIN|KEYWORD);
        !           229:                                t->left = nested(TBRACE, '}');
        !           230:                                return t;
        !           231: 
        !           232:                          default:
        !           233:                                goto Leave;
        !           234:                        }
        !           235:          Leave:
        !           236:                break;
        !           237: 
        !           238:          case '(':
        !           239:                t = nested(TPAREN, ')');
        !           240:                break;
        !           241: 
        !           242:          case '{':
        !           243:                t = nested(TBRACE, '}');
        !           244:                break;
        !           245: 
        !           246:          case FOR:
        !           247:                t = newtp(TFOR);
        !           248:                musthave(LWORD, 0);
        !           249:                t->str = strsave(ident, ATEMP);
        !           250:                multiline++;
        !           251:                t->vars = wordlist();
        !           252:                t->left = dogroup(0);
        !           253:                multiline--;
        !           254:                break;
        !           255: 
        !           256:          case WHILE:
        !           257:          case UNTIL:
        !           258:                multiline++;
        !           259:                t = newtp((c == WHILE) ? TWHILE: TUNTIL);
        !           260:                t->left = c_list();
        !           261:                t->right = dogroup(1);
        !           262:                multiline--;
        !           263:                break;
        !           264: 
        !           265:          case CASE:
        !           266:                t = newtp(TCASE);
        !           267:                musthave(LWORD, 0);
        !           268:                t->str = yylval.cp;
        !           269:                multiline++;
        !           270:                musthave(IN, KEYWORD|CONTIN);
        !           271:                t->left = caselist();
        !           272:                musthave(ESAC, KEYWORD);
        !           273:                multiline--;
        !           274:                break;
        !           275: 
        !           276:          case IF:
        !           277:                multiline++;
        !           278:                t = newtp(TIF);
        !           279:                t->left = c_list();
        !           280:                t->right = thenpart();
        !           281:                musthave(FI, KEYWORD);
        !           282:                multiline--;
        !           283:                break;
        !           284: 
        !           285:          case TIME:
        !           286:                t = pipeline(CONTIN);
        !           287:                t = block(TTIME, t, NOBLOCK, NOWORDS);
        !           288:                break;
        !           289: 
        !           290:          case FUNCTION:
        !           291:                t = newtp(TFUNCT);
        !           292:                musthave(LWORD, 0);
        !           293:                t->str = strsave(ident, ATEMP);
        !           294:                musthave('{', CONTIN|KEYWORD);
        !           295:                t->left = nested(TBRACE, '}');
        !           296:                break;
        !           297:        }
        !           298: 
        !           299:        while ((iop = synio(0)) != NULL) {
        !           300:                if (iopn >= NUFILE)
        !           301:                        yyerror("too many redirections");
        !           302:                iops[iopn++] = iop;
        !           303:        }
        !           304: 
        !           305:        if (iopn == 0) {
        !           306:                afree((Void*) iops, ATEMP);
        !           307:                t->ioact = NULL;
        !           308:        } else {
        !           309:                iops[iopn++] = NULL;
        !           310:                aresize((Void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
        !           311:                t->ioact = iops;
        !           312:        }
        !           313: 
        !           314:        if (t->type == TCOM) {
        !           315:                XPput(args, NULL);
        !           316:                t->args = (char **) XPclose(args);
        !           317:                XPput(vars, NULL);
        !           318:                t->vars = (char **) XPclose(vars);
        !           319:        } else {
        !           320:                XPfree(args);
        !           321:                XPfree(vars);
        !           322:        }
        !           323: 
        !           324:        return t;
        !           325: }
        !           326: 
        !           327: static struct op *
        !           328: dogroup(onlydone)
        !           329:        int onlydone;
        !           330: {
        !           331:        register int c;
        !           332:        register struct op *list;
        !           333: 
        !           334:        c = token(CONTIN|KEYWORD);
        !           335:        if (c == DONE && onlydone)
        !           336:                return NULL;
        !           337:        if (c != DO)
        !           338:                SYNTAXERR;
        !           339:        list = c_list();
        !           340:        musthave(DONE, KEYWORD);
        !           341:        return list;
        !           342: }
        !           343: 
        !           344: static struct op *
        !           345: thenpart()
        !           346: {
        !           347:        register int c;
        !           348:        register struct op *t;
        !           349: 
        !           350:        if ((c = token(0)) != THEN) {
        !           351:                REJECT;
        !           352:                return NULL;
        !           353:        }
        !           354:        t = newtp(0);
        !           355:        t->left = c_list();
        !           356:        if (t->left == NULL)
        !           357:                SYNTAXERR;
        !           358:        t->right = elsepart();
        !           359:        return (t);
        !           360: }
        !           361: 
        !           362: static struct op *
        !           363: elsepart()
        !           364: {
        !           365:        register int c;
        !           366:        register struct op *t;
        !           367: 
        !           368:        switch (c = token(0)) {
        !           369:          case ELSE:
        !           370:                if ((t = c_list()) == NULL)
        !           371:                        SYNTAXERR;
        !           372:                return (t);
        !           373: 
        !           374:          case ELIF:
        !           375:                t = newtp(TELIF);
        !           376:                t->left = c_list();
        !           377:                t->right = thenpart();
        !           378:                return (t);
        !           379: 
        !           380:          default:
        !           381:                REJECT;
        !           382:                return NULL;
        !           383:        }
        !           384: }
        !           385: 
        !           386: static struct op *
        !           387: caselist()
        !           388: {
        !           389:        register struct op *t, *tl;
        !           390: 
        !           391:        t = tl = NULL;
        !           392:        while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
        !           393:                struct op *tc = casepart();
        !           394:                if (tl == NULL)
        !           395:                        t = tl = tc, tl->right = NULL;
        !           396:                else
        !           397:                        tl->right = tc, tl = tc;
        !           398:        }
        !           399:        return (t);
        !           400: }
        !           401: 
        !           402: static struct op *
        !           403: casepart()
        !           404: {
        !           405:        register struct op *t;
        !           406:        register int c, cf;
        !           407:        XPtrV ptns;
        !           408: 
        !           409:        XPinit(ptns, 16);
        !           410:        t = newtp(TPAT);
        !           411:        cf = CONTIN|KEYWORD;
        !           412:        c = token(cf);
        !           413:        if (c != '(')
        !           414:                REJECT;
        !           415:        else
        !           416:                cf = 0;
        !           417:        do {
        !           418:                musthave(LWORD, cf);
        !           419:                XPput(ptns, yylval.cp);
        !           420:                cf = 0;
        !           421:        } while ((c = token(0)) == '|');
        !           422:        REJECT;
        !           423:        XPput(ptns, NULL);
        !           424:        t->vars = (char **) XPclose(ptns);
        !           425:        musthave(')', 0);
        !           426: 
        !           427:        t->left = c_list();
        !           428:        if ((tpeek(CONTIN|KEYWORD)) != ESAC)
        !           429:                musthave(BREAK, CONTIN|KEYWORD);
        !           430:        return (t);
        !           431: }
        !           432: 
        !           433: static char **
        !           434: wordlist()
        !           435: {
        !           436:        register int c;
        !           437:        XPtrV args;
        !           438: 
        !           439:        XPinit(args, 16);
        !           440:        if ((c = token(CONTIN|KEYWORD)) != IN) {
        !           441:                REJECT;
        !           442:                return NULL;
        !           443:        }
        !           444:        while ((c = token(0)) == LWORD)
        !           445:                XPput(args, yylval.cp);
        !           446:        if (c != '\n' && c != ';')
        !           447:                SYNTAXERR;
        !           448:        if (XPsize(args) == 0) {
        !           449:                XPfree(args);
        !           450:                return NULL;
        !           451:        } else {
        !           452:                XPput(args, NULL);
        !           453:                return (char **) XPclose(args);
        !           454:        }
        !           455: }
        !           456: 
        !           457: /*
        !           458:  * supporting functions
        !           459:  */
        !           460: 
        !           461: static struct op *
        !           462: block(type, t1, t2, wp)
        !           463:        struct op *t1, *t2;
        !           464:        char **wp;
        !           465: {
        !           466:        register struct op *t;
        !           467: 
        !           468:        t = newtp(type);
        !           469:        t->left = t1;
        !           470:        t->right = t2;
        !           471:        t->vars = wp;
        !           472:        return (t);
        !           473: }
        !           474: 
        !           475: Const  struct res {
        !           476:        char    *name;
        !           477:        int     val;
        !           478: } restab[] = {
        !           479:        "for",          FOR,
        !           480:        "case",         CASE,
        !           481:        "esac",         ESAC,
        !           482:        "while",        WHILE,
        !           483:        "do",           DO,
        !           484:        "done",         DONE,
        !           485:        "if",           IF,
        !           486:        "in",           IN,
        !           487:        "then",         THEN,
        !           488:        "else",         ELSE,
        !           489:        "elif",         ELIF,
        !           490:        "until",        UNTIL,
        !           491:        "fi",           FI,
        !           492:        "function",     FUNCTION,
        !           493:        "time",         TIME,
        !           494:        "{",            '{',
        !           495:        "}",            '}',
        !           496:        0
        !           497: };
        !           498: 
        !           499: keywords()
        !           500: {
        !           501:        register struct res Const *rp;
        !           502:        register struct tbl *p;
        !           503: 
        !           504:        for (rp = restab; rp->name; rp++) {
        !           505:                p = tenter(&lexicals, rp->name, hash(rp->name));
        !           506:                p->flag |= DEFINED|ISSET;
        !           507:                p->type = CKEYWD;
        !           508:                p->val.i = rp->val;
        !           509:        }
        !           510: }
        !           511: 
        !           512: static struct op *
        !           513: newtp(type)
        !           514:        int type;
        !           515: {
        !           516:        register struct op *t;
        !           517: 
        !           518:        t = (struct op *) alloc(sizeof(*t), ATEMP);
        !           519:        t->type = type;
        !           520:        t->args = t->vars = NULL;
        !           521:        t->ioact = NULL;
        !           522:        t->left = t->right = NULL;
        !           523:        t->str = NULL;
        !           524:        return (t);
        !           525: }
        !           526: 
        !           527: static struct ioword *
        !           528: io(u, f, cp)
        !           529:        int u, f;               /* unit, flags */
        !           530:        char *cp;
        !           531: {
        !           532:        register struct ioword *iop;
        !           533: 
        !           534:        iop = (struct ioword *) alloc(sizeof(*iop), ATEMP);
        !           535:        iop->unit = !(u < 0) ? u : (f&(IOREAD|IOHERE)) ? 0 : 1;
        !           536:        iop->flag = f;
        !           537:        iop->name = cp;
        !           538:        return iop;
        !           539: }
        !           540: 
        !           541: static void
        !           542: zzerr()
        !           543: {
        !           544:        yyerror("syntax error");
        !           545: }
        !           546: 
        !           547: struct op *
        !           548: compile(s)
        !           549:        Source *s;
        !           550: {
        !           551:        yynerrs = 0;
        !           552:        multiline = 0;
        !           553:        herep = heres;
        !           554:        source = s;
        !           555:        if (yyparse())
        !           556:                unwind();
        !           557:        if (s->type == STTY || s->type == SFILE)
        !           558:                s->str = null;  /* line is not preserved */
        !           559:        return outtree;
        !           560: }
        !           561: 

unix.superglobalmegacorp.com

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