1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.parse.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */ 2: /* 3: * sh.parse.c: Interpret a list of tokens 4: */ 5: /*- 6: * Copyright (c) 1980, 1991 The Regents of the University of California. 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by the University of 20: * California, Berkeley and its contributors. 21: * 4. Neither the name of the University nor the names of its contributors 22: * may be used to endorse or promote products derived from this software 23: * without specific prior written permission. 24: * 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35: * SUCH DAMAGE. 36: */ 37: #include "config.h" 38: #if !defined(lint) && !defined(pdp11) 39: static char *rcsid() 40: { return "$Id: sh.parse.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; } 41: #endif 42: 43: #include "sh.h" 44: 45: /* 46: * C shell 47: */ 48: static void asyntax __P((struct wordent *, struct wordent *)); 49: static void asyn0 __P((struct wordent *, struct wordent *)); 50: static void asyn3 __P((struct wordent *, struct wordent *)); 51: static struct wordent *freenod __P((struct wordent *, struct wordent *)); 52: static struct command *syn0 __P((struct wordent *, struct wordent *, int)); 53: static struct command *syn1 __P((struct wordent *, struct wordent *, int)); 54: static struct command *syn1a __P((struct wordent *, struct wordent *, int)); 55: static struct command *syn1b __P((struct wordent *, struct wordent *, int)); 56: static struct command *syn2 __P((struct wordent *, struct wordent *, int)); 57: static struct command *syn3 __P((struct wordent *, struct wordent *, int)); 58: 59: #define ALEFT 21 /* max of 20 alias expansions */ 60: #define HLEFT 11 /* max of 10 history expansions */ 61: /* 62: * Perform aliasing on the word list lex 63: * Do a (very rudimentary) parse to separate into commands. 64: * If word 0 of a command has an alias, do it. 65: * Repeat a maximum of 20 times. 66: */ 67: static int aleft; 68: extern int hleft; 69: void 70: alias(lex) 71: register struct wordent *lex; 72: { 73: jmp_buf osetexit; 74: 75: aleft = ALEFT; 76: hleft = HLEFT; 77: getexit(osetexit); 78: (void) setexit(); 79: if (haderr) { 80: resexit(osetexit); 81: reset(); 82: } 83: if (--aleft == 0) 84: stderror(ERR_ALIASLOOP); 85: asyntax(lex->next, lex); 86: resexit(osetexit); 87: } 88: 89: static void 90: asyntax(p1, p2) 91: register struct wordent *p1, *p2; 92: { 93: while (p1 != p2) 94: if (any(";&\n", p1->word[0])) 95: p1 = p1->next; 96: else { 97: asyn0(p1, p2); 98: return; 99: } 100: } 101: 102: static void 103: asyn0(p1, p2) 104: struct wordent *p1; 105: register struct wordent *p2; 106: { 107: register struct wordent *p; 108: register int l = 0; 109: 110: for (p = p1; p != p2; p = p->next) 111: switch (p->word[0]) { 112: 113: case '(': 114: l++; 115: continue; 116: 117: case ')': 118: l--; 119: if (l < 0) 120: stderror(ERR_TOOMANYRP); 121: continue; 122: 123: case '>': 124: if (p->next != p2 && eq(p->next->word, STRand)) 125: p = p->next; 126: continue; 127: 128: case '&': 129: case '|': 130: case ';': 131: case '\n': 132: if (l != 0) 133: continue; 134: asyn3(p1, p); 135: asyntax(p->next, p2); 136: return; 137: } 138: if (l == 0) 139: asyn3(p1, p2); 140: } 141: 142: static void 143: asyn3(p1, p2) 144: struct wordent *p1; 145: register struct wordent *p2; 146: { 147: register struct varent *ap; 148: struct wordent alout; 149: register bool redid; 150: 151: if (p1 == p2) 152: return; 153: if (p1->word[0] == '(') { 154: for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 155: if (p2 == p1) 156: return; 157: if (p2 == p1->next) 158: return; 159: asyn0(p1->next, p2); 160: return; 161: } 162: ap = adrof1(p1->word, &aliases); 163: if (ap == 0) 164: return; 165: alhistp = p1->prev; 166: alhistt = p2; 167: alvec = ap->vec; 168: redid = lex(&alout); 169: alhistp = alhistt = 0; 170: alvec = 0; 171: if (seterr) { 172: freelex(&alout); 173: stderror(ERR_OLD); 174: } 175: if (p1->word[0] && eq(p1->word, alout.next->word)) { 176: Char *cp = alout.next->word; 177: 178: alout.next->word = Strspl(STRQNULL, cp); 179: xfree((ptr_t) cp); 180: } 181: p1 = freenod(p1, redid ? p2 : p1->next); 182: if (alout.next != &alout) { 183: p1->next->prev = alout.prev->prev; 184: alout.prev->prev->next = p1->next; 185: alout.next->prev = p1; 186: p1->next = alout.next; 187: xfree((ptr_t) alout.prev->word); 188: xfree((ptr_t) (alout.prev)); 189: } 190: reset(); /* throw! */ 191: } 192: 193: static struct wordent * 194: freenod(p1, p2) 195: register struct wordent *p1, *p2; 196: { 197: register struct wordent *retp = p1->prev; 198: 199: while (p1 != p2) { 200: xfree((ptr_t) p1->word); 201: p1 = p1->next; 202: xfree((ptr_t) (p1->prev)); 203: } 204: retp->next = p2; 205: p2->prev = retp; 206: return (retp); 207: } 208: 209: #define P_HERE 1 210: #define P_IN 2 211: #define P_OUT 4 212: #define P_DIAG 8 213: 214: /* 215: * syntax 216: * empty 217: * syn0 218: */ 219: struct command * 220: syntax(p1, p2, flags) 221: register struct wordent *p1, *p2; 222: int flags; 223: { 224: 225: while (p1 != p2) 226: if (any(";&\n", p1->word[0])) 227: p1 = p1->next; 228: else 229: return (syn0(p1, p2, flags)); 230: return (0); 231: } 232: 233: /* 234: * syn0 235: * syn1 236: * syn1 & syntax 237: */ 238: static struct command * 239: syn0(p1, p2, flags) 240: struct wordent *p1, *p2; 241: int flags; 242: { 243: register struct wordent *p; 244: register struct command *t, *t1; 245: int l; 246: 247: l = 0; 248: for (p = p1; p != p2; p = p->next) 249: switch (p->word[0]) { 250: 251: case '(': 252: l++; 253: continue; 254: 255: case ')': 256: l--; 257: if (l < 0) 258: seterror(ERR_TOOMANYRP); 259: continue; 260: 261: case '|': 262: if (p->word[1] == '|') 263: continue; 264: /* fall into ... */ 265: 266: case '>': 267: if (p->next != p2 && eq(p->next->word, STRand)) 268: p = p->next; 269: continue; 270: 271: case '&': 272: if (l != 0) 273: break; 274: if (p->word[1] == '&') 275: continue; 276: t1 = syn1(p1, p, flags); 277: if (t1->t_dtyp == NODE_LIST || 278: t1->t_dtyp == NODE_AND || 279: t1->t_dtyp == NODE_OR) { 280: t = (struct command *) xcalloc(1, sizeof(*t)); 281: t->t_dtyp = NODE_PAREN; 282: t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 283: t->t_dspr = t1; 284: t1 = t; 285: } 286: else 287: t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 288: t = (struct command *) xcalloc(1, sizeof(*t)); 289: t->t_dtyp = NODE_LIST; 290: t->t_dflg = 0; 291: t->t_dcar = t1; 292: t->t_dcdr = syntax(p, p2, flags); 293: return (t); 294: } 295: if (l == 0) 296: return (syn1(p1, p2, flags)); 297: seterror(ERR_TOOMANYLP); 298: return (0); 299: } 300: 301: /* 302: * syn1 303: * syn1a 304: * syn1a ; syntax 305: */ 306: static struct command * 307: syn1(p1, p2, flags) 308: struct wordent *p1, *p2; 309: int flags; 310: { 311: register struct wordent *p; 312: register struct command *t; 313: int l; 314: 315: l = 0; 316: for (p = p1; p != p2; p = p->next) 317: switch (p->word[0]) { 318: 319: case '(': 320: l++; 321: continue; 322: 323: case ')': 324: l--; 325: continue; 326: 327: case ';': 328: case '\n': 329: if (l != 0) 330: break; 331: t = (struct command *) xcalloc(1, sizeof(*t)); 332: t->t_dtyp = NODE_LIST; 333: t->t_dcar = syn1a(p1, p, flags); 334: t->t_dcdr = syntax(p->next, p2, flags); 335: if (t->t_dcdr == 0) 336: t->t_dcdr = t->t_dcar, t->t_dcar = 0; 337: return (t); 338: } 339: return (syn1a(p1, p2, flags)); 340: } 341: 342: /* 343: * syn1a 344: * syn1b 345: * syn1b || syn1a 346: */ 347: static struct command * 348: syn1a(p1, p2, flags) 349: struct wordent *p1, *p2; 350: int flags; 351: { 352: register struct wordent *p; 353: register struct command *t; 354: register int l = 0; 355: 356: for (p = p1; p != p2; p = p->next) 357: switch (p->word[0]) { 358: 359: case '(': 360: l++; 361: continue; 362: 363: case ')': 364: l--; 365: continue; 366: 367: case '|': 368: if (p->word[1] != '|') 369: continue; 370: if (l == 0) { 371: t = (struct command *) xcalloc(1, sizeof(*t)); 372: t->t_dtyp = NODE_OR; 373: t->t_dcar = syn1b(p1, p, flags); 374: t->t_dcdr = syn1a(p->next, p2, flags); 375: t->t_dflg = 0; 376: return (t); 377: } 378: continue; 379: } 380: return (syn1b(p1, p2, flags)); 381: } 382: 383: /* 384: * syn1b 385: * syn2 386: * syn2 && syn1b 387: */ 388: static struct command * 389: syn1b(p1, p2, flags) 390: struct wordent *p1, *p2; 391: int flags; 392: { 393: register struct wordent *p; 394: register struct command *t; 395: register int l = 0; 396: 397: for (p = p1; p != p2; p = p->next) 398: switch (p->word[0]) { 399: 400: case '(': 401: l++; 402: continue; 403: 404: case ')': 405: l--; 406: continue; 407: 408: case '&': 409: if (p->word[1] == '&' && l == 0) { 410: t = (struct command *) xcalloc(1, sizeof(*t)); 411: t->t_dtyp = NODE_AND; 412: t->t_dcar = syn2(p1, p, flags); 413: t->t_dcdr = syn1b(p->next, p2, flags); 414: t->t_dflg = 0; 415: return (t); 416: } 417: continue; 418: } 419: return (syn2(p1, p2, flags)); 420: } 421: 422: /* 423: * syn2 424: * syn3 425: * syn3 | syn2 426: * syn3 |& syn2 427: */ 428: static struct command * 429: syn2(p1, p2, flags) 430: struct wordent *p1, *p2; 431: int flags; 432: { 433: register struct wordent *p, *pn; 434: register struct command *t; 435: register int l = 0; 436: int f; 437: 438: for (p = p1; p != p2; p = p->next) 439: switch (p->word[0]) { 440: 441: case '(': 442: l++; 443: continue; 444: 445: case ')': 446: l--; 447: continue; 448: 449: case '|': 450: if (l != 0) 451: continue; 452: t = (struct command *) xcalloc(1, sizeof(*t)); 453: f = flags | P_OUT; 454: pn = p->next; 455: if (pn != p2 && pn->word[0] == '&') { 456: f |= P_DIAG; 457: t->t_dflg |= F_STDERR; 458: } 459: t->t_dtyp = NODE_PIPE; 460: t->t_dcar = syn3(p1, p, f); 461: if (pn != p2 && pn->word[0] == '&') 462: p = pn; 463: t->t_dcdr = syn2(p->next, p2, flags | P_IN); 464: return (t); 465: } 466: return (syn3(p1, p2, flags)); 467: } 468: 469: static char RELPAR[] = {'<', '>', '(', ')', '\0'}; 470: 471: /* 472: * syn3 473: * ( syn0 ) [ < in ] [ > out ] 474: * word word* [ < in ] [ > out ] 475: * KEYWORD ( word* ) word* [ < in ] [ > out ] 476: * 477: * KEYWORD = (@ exit foreach if set switch test while) 478: */ 479: static struct command * 480: syn3(p1, p2, flags) 481: struct wordent *p1, *p2; 482: int flags; 483: { 484: register struct wordent *p; 485: struct wordent *lp, *rp; 486: register struct command *t; 487: register int l; 488: Char **av; 489: int n, c; 490: bool specp = 0; 491: 492: if (p1 != p2) { 493: p = p1; 494: again: 495: switch (srchx(p->word)) { 496: 497: case T_ELSE: 498: p = p->next; 499: if (p != p2) 500: goto again; 501: break; 502: 503: case T_EXIT: 504: case T_FOREACH: 505: case T_IF: 506: case T_LET: 507: case T_SET: 508: case T_SWITCH: 509: case T_WHILE: 510: specp = 1; 511: break; 512: } 513: } 514: n = 0; 515: l = 0; 516: for (p = p1; p != p2; p = p->next) 517: switch (p->word[0]) { 518: 519: case '(': 520: if (specp) 521: n++; 522: l++; 523: continue; 524: 525: case ')': 526: if (specp) 527: n++; 528: l--; 529: continue; 530: 531: case '>': 532: case '<': 533: if (l != 0) { 534: if (specp) 535: n++; 536: continue; 537: } 538: if (p->next == p2) 539: continue; 540: if (any(RELPAR, p->next->word[0])) 541: continue; 542: n--; 543: continue; 544: 545: default: 546: if (!specp && l != 0) 547: continue; 548: n++; 549: continue; 550: } 551: if (n < 0) 552: n = 0; 553: t = (struct command *) xcalloc(1, sizeof(*t)); 554: av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **)); 555: t->t_dcom = av; 556: n = 0; 557: if (p2->word[0] == ')') 558: t->t_dflg = F_NOFORK; 559: lp = 0; 560: rp = 0; 561: l = 0; 562: for (p = p1; p != p2; p = p->next) { 563: c = p->word[0]; 564: switch (c) { 565: 566: case '(': 567: if (l == 0) { 568: if (lp != 0 && !specp) 569: seterror(ERR_BADPLP); 570: lp = p->next; 571: } 572: l++; 573: goto savep; 574: 575: case ')': 576: l--; 577: if (l == 0) 578: rp = p; 579: goto savep; 580: 581: case '>': 582: if (l != 0) 583: goto savep; 584: if (p->word[1] == '>') 585: t->t_dflg |= F_APPEND; 586: if (p->next != p2 && eq(p->next->word, STRand)) { 587: t->t_dflg |= F_STDERR, p = p->next; 588: if (flags & (P_OUT | P_DIAG)) { 589: seterror(ERR_OUTRED); 590: continue; 591: } 592: } 593: if (p->next != p2 && eq(p->next->word, STRbang)) 594: t->t_dflg |= F_OVERWRITE, p = p->next; 595: if (p->next == p2) { 596: seterror(ERR_MISRED); 597: continue; 598: } 599: p = p->next; 600: if (any(RELPAR, p->word[0])) { 601: seterror(ERR_MISRED); 602: continue; 603: } 604: if ((flags & P_OUT) && (flags & P_DIAG) == 0 || t->t_drit) 605: seterror(ERR_OUTRED); 606: else 607: t->t_drit = Strsave(p->word); 608: continue; 609: 610: case '<': 611: if (l != 0) 612: goto savep; 613: if (p->word[1] == '<') 614: t->t_dflg |= F_READ; 615: if (p->next == p2) { 616: seterror(ERR_MISRED); 617: continue; 618: } 619: p = p->next; 620: if (any(RELPAR, p->word[0])) { 621: seterror(ERR_MISRED); 622: continue; 623: } 624: if ((flags & P_HERE) && (t->t_dflg & F_READ)) 625: seterror(ERR_REDPAR); 626: else if ((flags & P_IN) || t->t_dlef) 627: seterror(ERR_INRED); 628: else 629: t->t_dlef = Strsave(p->word); 630: continue; 631: 632: savep: 633: if (!specp) 634: continue; 635: default: 636: if (l != 0 && !specp) 637: continue; 638: if (seterr == 0) 639: av[n] = Strsave(p->word); 640: n++; 641: continue; 642: } 643: } 644: if (lp != 0 && !specp) { 645: if (n != 0) 646: seterror(ERR_BADPLPS); 647: t->t_dtyp = NODE_PAREN; 648: t->t_dspr = syn0(lp, rp, P_HERE); 649: } 650: else { 651: if (n == 0) 652: seterror(ERR_NULLCOM); 653: t->t_dtyp = NODE_COMMAND; 654: } 655: return (t); 656: } 657: 658: void 659: freesyn(t) 660: register struct command *t; 661: { 662: register Char **v; 663: 664: if (t == 0) 665: return; 666: switch (t->t_dtyp) { 667: 668: case NODE_COMMAND: 669: for (v = t->t_dcom; *v; v++) 670: xfree((ptr_t) * v); 671: xfree((ptr_t) (t->t_dcom)); 672: xfree((ptr_t) t->t_dlef); 673: xfree((ptr_t) t->t_drit); 674: break; 675: case NODE_PAREN: 676: freesyn(t->t_dspr); 677: xfree((ptr_t) t->t_dlef); 678: xfree((ptr_t) t->t_drit); 679: break; 680: 681: case NODE_AND: 682: case NODE_OR: 683: case NODE_PIPE: 684: case NODE_LIST: 685: freesyn(t->t_dcar), freesyn(t->t_dcdr); 686: break; 687: } 688: xfree((ptr_t) t); 689: }