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