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