Annotation of coherent/a/usr/bob/korn/syn.c, revision 1.1.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.