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