|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.