1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.10 1996/04/26 19:20:04 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 "sh.h" 38 39 RCSID("$Id: sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $") 40 41 /* 42 * C shell 43 */ 44 static void asyntax __P((struct wordent *, struct wordent *)); 45 static void asyn0 __P((struct wordent *, struct wordent *)); 46 static void asyn3 __P((struct wordent *, struct wordent *)); 47 static struct wordent *freenod __P((struct wordent *, struct wordent *)); 48 static struct command *syn0 __P((struct wordent *, struct wordent *, int)); 49 static struct command *syn1 __P((struct wordent *, struct wordent *, int)); 50 static struct command *syn1a __P((struct wordent *, struct wordent *, int)); 51 static struct command *syn1b __P((struct wordent *, struct wordent *, int)); 52 static struct command *syn2 __P((struct wordent *, struct wordent *, int)); 53 static struct command *syn3 __P((struct wordent *, struct wordent *, int)); 54 55 #define ALEFT 51 /* max of 50 alias expansions */ 56 #define HLEFT 11 /* max of 10 history expansions */ 57 /* 58 * Perform aliasing on the word list lexp 59 * Do a (very rudimentary) parse to separate into commands. 60 * If word 0 of a command has an alias, do it. 61 * Repeat a maximum of 50 times. 62 */ 63 static int aleft; 64 extern int hleft; 65 void 66 alias(lexp) 67 register struct wordent *lexp; 68 { 69 jmp_buf_t osetexit; 70 71 aleft = ALEFT; 72 hleft = HLEFT; 73 getexit(osetexit); 74 (void) setexit(); 75 if (haderr) { 76 resexit(osetexit); 77 reset(); 78 } 79 if (--aleft == 0) 80 stderror(ERR_ALIASLOOP); 81 asyntax(lexp->next, lexp); 82 resexit(osetexit); 83 } 84 85 static void 86 asyntax(p1, p2) 87 register struct wordent *p1, *p2; 88 { 89 while (p1 != p2) 90 if (any(";&\n", p1->word[0])) 91 p1 = p1->next; 92 else { 93 asyn0(p1, p2); 94 return; 95 } 96 } 97 98 static void 99 asyn0(p1, p2) 100 struct wordent *p1; 101 register struct wordent *p2; 102 { 103 register struct wordent *p; 104 register int l = 0; 105 106 for (p = p1; p != p2; p = p->next) 107 switch (p->word[0]) { 108 109 case '(': 110 l++; 111 continue; 112 113 case ')': 114 l--; 115 if (l < 0) 116 stderror(ERR_TOOMANYRP); 117 continue; 118 119 case '>': 120 if (p->next != p2 && eq(p->next->word, STRand)) 121 p = p->next; 122 continue; 123 124 case '&': 125 case '|': 126 case ';': 127 case '\n': 128 if (l != 0) 129 continue; 130 asyn3(p1, p); 131 asyntax(p->next, p2); 132 return; 133 134 default: 135 break; 136 } 137 if (l == 0) 138 asyn3(p1, p2); 139 } 140 141 static void 142 asyn3(p1, p2) 143 struct wordent *p1; 144 register struct wordent *p2; 145 { 146 register struct varent *ap; 147 struct wordent alout; 148 register bool redid; 149 150 if (p1 == p2) 151 return; 152 if (p1->word[0] == '(') { 153 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 154 if (p2 == p1) 155 return; 156 if (p2 == p1->next) 157 return; 158 asyn0(p1->next, p2); 159 return; 160 } 161 ap = adrof1(p1->word, &aliases); 162 if (ap == 0) 163 return; 164 alhistp = p1->prev; 165 alhistt = p2; 166 alvec = ap->vec; 167 redid = lex(&alout); 168 alhistp = alhistt = 0; 169 alvec = 0; 170 if (seterr) { 171 freelex(&alout); 172 stderror(ERR_OLD); 173 } 174 if (p1->word[0] && eq(p1->word, alout.next->word)) { 175 Char *cp = alout.next->word; 176 177 alout.next->word = Strspl(STRQNULL, cp); 178 xfree((ptr_t) cp); 179 } 180 p1 = freenod(p1, redid ? p2 : p1->next); 181 if (alout.next != &alout) { 182 p1->next->prev = alout.prev->prev; 183 alout.prev->prev->next = p1->next; 184 alout.next->prev = p1; 185 p1->next = alout.next; 186 xfree((ptr_t) alout.prev->word); 187 xfree((ptr_t) (alout.prev)); 188 } 189 reset(); /* throw! */ 190 } 191 192 static struct wordent * 193 freenod(p1, p2) 194 register struct wordent *p1, *p2; 195 { 196 register struct wordent *retp = p1->prev; 197 198 while (p1 != p2) { 199 xfree((ptr_t) p1->word); 200 p1 = p1->next; 201 xfree((ptr_t) (p1->prev)); 202 } 203 retp->next = p2; 204 p2->prev = retp; 205 return (retp); 206 } 207 208 #define P_HERE 1 209 #define P_IN 2 210 #define P_OUT 4 211 #define P_DIAG 8 212 213 /* 214 * syntax 215 * empty 216 * syn0 217 */ 218 struct command * 219 syntax(p1, p2, flags) 220 register struct wordent *p1, *p2; 221 int flags; 222 { 223 224 while (p1 != p2) 225 if (any(";&\n", p1->word[0])) 226 p1 = p1->next; 227 else 228 return (syn0(p1, p2, flags)); 229 return (0); 230 } 231 232 /* 233 * syn0 234 * syn1 235 * syn1 & syntax 236 */ 237 static struct command * 238 syn0(p1, p2, flags) 239 struct wordent *p1, *p2; 240 int flags; 241 { 242 register struct wordent *p; 243 register struct command *t, *t1; 244 int l; 245 246 l = 0; 247 for (p = p1; p != p2; p = p->next) 248 switch (p->word[0]) { 249 250 case '(': 251 l++; 252 continue; 253 254 case ')': 255 l--; 256 if (l < 0) 257 seterror(ERR_TOOMANYRP); 258 continue; 259 260 case '|': 261 if (p->word[1] == '|') 262 continue; 263 /*FALLTHROUGH*/ 264 265 case '>': 266 if (p->next != p2 && eq(p->next->word, STRand)) 267 p = p->next; 268 continue; 269 270 case '&': 271 if (l != 0) 272 break; 273 if (p->word[1] == '&') 274 continue; 275 t1 = syn1(p1, p, flags); 276 if (t1->t_dtyp == NODE_LIST || 277 t1->t_dtyp == NODE_AND || 278 t1->t_dtyp == NODE_OR) { 279 t = (struct command *) xcalloc(1, sizeof(*t)); 280 t->t_dtyp = NODE_PAREN; 281 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 282 t->t_dspr = t1; 283 t1 = t; 284 } 285 else 286 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 287 t = (struct command *) xcalloc(1, sizeof(*t)); 288 t->t_dtyp = NODE_LIST; 289 t->t_dflg = 0; 290 t->t_dcar = t1; 291 t->t_dcdr = syntax(p, p2, flags); 292 return (t); 293 default: 294 break; 295 } 296 if (l == 0) 297 return (syn1(p1, p2, flags)); 298 seterror(ERR_TOOMANYLP); 299 return (0); 300 } 301 302 /* 303 * syn1 304 * syn1a 305 * syn1a ; syntax 306 */ 307 static struct command * 308 syn1(p1, p2, flags) 309 struct wordent *p1, *p2; 310 int flags; 311 { 312 register struct wordent *p; 313 register struct command *t; 314 int l; 315 316 l = 0; 317 for (p = p1; p != p2; p = p->next) 318 switch (p->word[0]) { 319 320 case '(': 321 l++; 322 continue; 323 324 case ')': 325 l--; 326 continue; 327 328 case ';': 329 case '\n': 330 if (l != 0) 331 break; 332 t = (struct command *) xcalloc(1, sizeof(*t)); 333 t->t_dtyp = NODE_LIST; 334 t->t_dcar = syn1a(p1, p, flags); 335 t->t_dcdr = syntax(p->next, p2, flags); 336 if (t->t_dcdr == 0) 337 t->t_dcdr = t->t_dcar, t->t_dcar = 0; 338 return (t); 339 340 default: 341 break; 342 } 343 return (syn1a(p1, p2, flags)); 344 } 345 346 /* 347 * syn1a 348 * syn1b 349 * syn1b || syn1a 350 */ 351 static struct command * 352 syn1a(p1, p2, flags) 353 struct wordent *p1, *p2; 354 int flags; 355 { 356 register struct wordent *p; 357 register struct command *t; 358 register int l = 0; 359 360 for (p = p1; p != p2; p = p->next) 361 switch (p->word[0]) { 362 363 case '(': 364 l++; 365 continue; 366 367 case ')': 368 l--; 369 continue; 370 371 case '|': 372 if (p->word[1] != '|') 373 continue; 374 if (l == 0) { 375 t = (struct command *) xcalloc(1, sizeof(*t)); 376 t->t_dtyp = NODE_OR; 377 t->t_dcar = syn1b(p1, p, flags); 378 t->t_dcdr = syn1a(p->next, p2, flags); 379 t->t_dflg = 0; 380 return (t); 381 } 382 continue; 383 384 default: 385 break; 386 } 387 return (syn1b(p1, p2, flags)); 388 } 389 390 /* 391 * syn1b 392 * syn2 393 * syn2 && syn1b 394 */ 395 static struct command * 396 syn1b(p1, p2, flags) 397 struct wordent *p1, *p2; 398 int flags; 399 { 400 register struct wordent *p; 401 register struct command *t; 402 register int l = 0; 403 404 for (p = p1; p != p2; p = p->next) 405 switch (p->word[0]) { 406 407 case '(': 408 l++; 409 continue; 410 411 case ')': 412 l--; 413 continue; 414 415 case '&': 416 if (p->word[1] == '&' && l == 0) { 417 t = (struct command *) xcalloc(1, sizeof(*t)); 418 t->t_dtyp = NODE_AND; 419 t->t_dcar = syn2(p1, p, flags); 420 t->t_dcdr = syn1b(p->next, p2, flags); 421 t->t_dflg = 0; 422 return (t); 423 } 424 continue; 425 426 default: 427 break; 428 } 429 return (syn2(p1, p2, flags)); 430 } 431 432 /* 433 * syn2 434 * syn3 435 * syn3 | syn2 436 * syn3 |& syn2 437 */ 438 static struct command * 439 syn2(p1, p2, flags) 440 struct wordent *p1, *p2; 441 int flags; 442 { 443 register struct wordent *p, *pn; 444 register struct command *t; 445 register int l = 0; 446 int f; 447 448 for (p = p1; p != p2; p = p->next) 449 switch (p->word[0]) { 450 451 case '(': 452 l++; 453 continue; 454 455 case ')': 456 l--; 457 continue; 458 459 case '|': 460 if (l != 0) 461 continue; 462 t = (struct command *) xcalloc(1, sizeof(*t)); 463 f = flags | P_OUT; 464 pn = p->next; 465 if (pn != p2 && pn->word[0] == '&') { 466 f |= P_DIAG; 467 t->t_dflg |= F_STDERR; 468 } 469 t->t_dtyp = NODE_PIPE; 470 t->t_dcar = syn3(p1, p, f); 471 if (pn != p2 && pn->word[0] == '&') 472 p = pn; 473 t->t_dcdr = syn2(p->next, p2, flags | P_IN); 474 return (t); 475 476 default: 477 break; 478 } 479 return (syn3(p1, p2, flags)); 480 } 481 482 static char RELPAR[] = {'<', '>', '(', ')', '\0'}; 483 484 /* 485 * syn3 486 * ( syn0 ) [ < in ] [ > out ] 487 * word word* [ < in ] [ > out ] 488 * KEYWORD ( word* ) word* [ < in ] [ > out ] 489 * 490 * KEYWORD = (@ exit foreach if set switch test while) 491 */ 492 static struct command * 493 syn3(p1, p2, flags) 494 struct wordent *p1, *p2; 495 int flags; 496 { 497 register struct wordent *p; 498 struct wordent *lp, *rp; 499 register struct command *t; 500 register int l; 501 Char **av; 502 int n, c; 503 bool specp = 0; 504 505 if (p1 != p2) { 506 p = p1; 507 again: 508 switch (srchx(p->word)) { 509 510 case TC_ELSE: 511 p = p->next; 512 if (p != p2) 513 goto again; 514 break; 515 516 case TC_EXIT: 517 case TC_FOREACH: 518 case TC_IF: 519 case TC_LET: 520 case TC_SET: 521 case TC_SWITCH: 522 case TC_WHILE: 523 specp = 1; 524 break; 525 default: 526 break; 527 } 528 } 529 n = 0; 530 l = 0; 531 for (p = p1; p != p2; p = p->next) 532 switch (p->word[0]) { 533 534 case '(': 535 if (specp) 536 n++; 537 l++; 538 continue; 539 540 case ')': 541 if (specp) 542 n++; 543 l--; 544 continue; 545 546 case '>': 547 case '<': 548 if (l != 0) { 549 if (specp) 550 n++; 551 continue; 552 } 553 if (p->next == p2) 554 continue; 555 if (any(RELPAR, p->next->word[0])) 556 continue; 557 n--; 558 continue; 559 560 default: 561 if (!specp && l != 0) 562 continue; 563 n++; 564 continue; 565 } 566 if (n < 0) 567 n = 0; 568 t = (struct command *) xcalloc(1, sizeof(*t)); 569 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **)); 570 t->t_dcom = av; 571 n = 0; 572 if (p2->word[0] == ')') 573 t->t_dflg = F_NOFORK; 574 lp = 0; 575 rp = 0; 576 l = 0; 577 for (p = p1; p != p2; p = p->next) { 578 c = p->word[0]; 579 switch (c) { 580 581 case '(': 582 if (l == 0) { 583 if (lp != 0 && !specp) 584 seterror(ERR_BADPLP); 585 lp = p->next; 586 } 587 l++; 588 goto savep; 589 590 case ')': 591 l--; 592 if (l == 0) 593 rp = p; 594 goto savep; 595 596 case '>': 597 if (l != 0) 598 goto savep; 599 if (p->word[1] == '>') 600 t->t_dflg |= F_APPEND; 601 if (p->next != p2 && eq(p->next->word, STRand)) { 602 t->t_dflg |= F_STDERR, p = p->next; 603 if (flags & (P_OUT | P_DIAG)) { 604 seterror(ERR_OUTRED); 605 continue; 606 } 607 } 608 if (p->next != p2 && eq(p->next->word, STRbang)) 609 t->t_dflg |= F_OVERWRITE, p = p->next; 610 if (p->next == p2) { 611 seterror(ERR_MISRED); 612 continue; 613 } 614 p = p->next; 615 if (any(RELPAR, p->word[0])) { 616 seterror(ERR_MISRED); 617 continue; 618 } 619 if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit) 620 seterror(ERR_OUTRED); 621 else 622 t->t_drit = Strsave(p->word); 623 continue; 624 625 case '<': 626 if (l != 0) 627 goto savep; 628 if (p->word[1] == '<') 629 t->t_dflg |= F_READ; 630 if (p->next == p2) { 631 seterror(ERR_MISRED); 632 continue; 633 } 634 p = p->next; 635 if (any(RELPAR, p->word[0])) { 636 seterror(ERR_MISRED); 637 continue; 638 } 639 if ((flags & P_HERE) && (t->t_dflg & F_READ)) 640 seterror(ERR_REDPAR); 641 else if ((flags & P_IN) || t->t_dlef) 642 seterror(ERR_INRED); 643 else 644 t->t_dlef = Strsave(p->word); 645 continue; 646 647 savep: 648 if (!specp) 649 continue; 650 default: 651 if (l != 0 && !specp) 652 continue; 653 if (seterr == 0) 654 av[n] = Strsave(p->word); 655 n++; 656 continue; 657 } 658 } 659 if (lp != 0 && !specp) { 660 if (n != 0) 661 seterror(ERR_BADPLPS); 662 t->t_dtyp = NODE_PAREN; 663 t->t_dspr = syn0(lp, rp, P_HERE); 664 } 665 else { 666 if (n == 0) 667 seterror(ERR_NULLCOM); 668 t->t_dtyp = NODE_COMMAND; 669 } 670 return (t); 671 } 672 673 void 674 freesyn(t) 675 register struct command *t; 676 { 677 register Char **v; 678 679 if (t == 0) 680 return; 681 switch (t->t_dtyp) { 682 683 case NODE_COMMAND: 684 for (v = t->t_dcom; *v; v++) 685 xfree((ptr_t) * v); 686 xfree((ptr_t) (t->t_dcom)); 687 xfree((ptr_t) t->t_dlef); 688 xfree((ptr_t) t->t_drit); 689 break; 690 case NODE_PAREN: 691 freesyn(t->t_dspr); 692 xfree((ptr_t) t->t_dlef); 693 xfree((ptr_t) t->t_drit); 694 break; 695 696 case NODE_AND: 697 case NODE_OR: 698 case NODE_PIPE: 699 case NODE_LIST: 700 freesyn(t->t_dcar), freesyn(t->t_dcdr); 701 break; 702 default: 703 break; 704 } 705 xfree((ptr_t) t); 706 } 707