1 /* $NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd 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 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93"; 39 #else 40 static char rcsid[] = "$NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $"; 41 #endif 42 #endif /* not lint */ 43 44 #include <sys/types.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #if __STDC__ 48 # include <stdarg.h> 49 #else 50 # include <varargs.h> 51 #endif 52 53 #include "csh.h" 54 #include "extern.h" 55 56 static void asyntax __P((struct wordent *, struct wordent *)); 57 static void asyn0 __P((struct wordent *, struct wordent *)); 58 static void asyn3 __P((struct wordent *, struct wordent *)); 59 static struct wordent 60 *freenod __P((struct wordent *, struct wordent *)); 61 static struct command 62 *syn0 __P((struct wordent *, struct wordent *, int)); 63 static struct command 64 *syn1 __P((struct wordent *, struct wordent *, int)); 65 static struct command 66 *syn1a __P((struct wordent *, struct wordent *, int)); 67 static struct command 68 *syn1b __P((struct wordent *, struct wordent *, int)); 69 static struct command 70 *syn2 __P((struct wordent *, struct wordent *, int)); 71 static struct command 72 *syn3 __P((struct wordent *, struct wordent *, int)); 73 74 #define ALEFT 21 /* max of 20 alias expansions */ 75 #define HLEFT 11 /* max of 10 history expansions */ 76 /* 77 * Perform aliasing on the word list lex 78 * Do a (very rudimentary) parse to separate into commands. 79 * If word 0 of a command has an alias, do it. 80 * Repeat a maximum of 20 times. 81 */ 82 static int aleft; 83 extern int hleft; 84 void 85 alias(lex) 86 register struct wordent *lex; 87 { 88 jmp_buf osetexit; 89 90 aleft = ALEFT; 91 hleft = HLEFT; 92 getexit(osetexit); 93 (void) setexit(); 94 if (haderr) { 95 resexit(osetexit); 96 reset(); 97 } 98 if (--aleft == 0) 99 stderror(ERR_ALIASLOOP); 100 asyntax(lex->next, lex); 101 resexit(osetexit); 102 } 103 104 static void 105 asyntax(p1, p2) 106 register struct wordent *p1, *p2; 107 { 108 while (p1 != p2) 109 if (any(";&\n", p1->word[0])) 110 p1 = p1->next; 111 else { 112 asyn0(p1, p2); 113 return; 114 } 115 } 116 117 static void 118 asyn0(p1, p2) 119 struct wordent *p1; 120 register struct wordent *p2; 121 { 122 register struct wordent *p; 123 register int l = 0; 124 125 for (p = p1; p != p2; p = p->next) 126 switch (p->word[0]) { 127 128 case '(': 129 l++; 130 continue; 131 132 case ')': 133 l--; 134 if (l < 0) 135 stderror(ERR_TOOMANYRP); 136 continue; 137 138 case '>': 139 if (p->next != p2 && eq(p->next->word, STRand)) 140 p = p->next; 141 continue; 142 143 case '&': 144 case '|': 145 case ';': 146 case '\n': 147 if (l != 0) 148 continue; 149 asyn3(p1, p); 150 asyntax(p->next, p2); 151 return; 152 } 153 if (l == 0) 154 asyn3(p1, p2); 155 } 156 157 static void 158 asyn3(p1, p2) 159 struct wordent *p1; 160 register struct wordent *p2; 161 { 162 register struct varent *ap; 163 struct wordent alout; 164 register bool redid; 165 166 if (p1 == p2) 167 return; 168 if (p1->word[0] == '(') { 169 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 170 if (p2 == p1) 171 return; 172 if (p2 == p1->next) 173 return; 174 asyn0(p1->next, p2); 175 return; 176 } 177 ap = adrof1(p1->word, &aliases); 178 if (ap == 0) 179 return; 180 alhistp = p1->prev; 181 alhistt = p2; 182 alvec = ap->vec; 183 redid = lex(&alout); 184 alhistp = alhistt = 0; 185 alvec = 0; 186 if (seterr) { 187 freelex(&alout); 188 stderror(ERR_OLD); 189 } 190 if (p1->word[0] && eq(p1->word, alout.next->word)) { 191 Char *cp = alout.next->word; 192 193 alout.next->word = Strspl(STRQNULL, cp); 194 xfree((ptr_t) cp); 195 } 196 p1 = freenod(p1, redid ? p2 : p1->next); 197 if (alout.next != &alout) { 198 p1->next->prev = alout.prev->prev; 199 alout.prev->prev->next = p1->next; 200 alout.next->prev = p1; 201 p1->next = alout.next; 202 xfree((ptr_t) alout.prev->word); 203 xfree((ptr_t) (alout.prev)); 204 } 205 reset(); /* throw! */ 206 } 207 208 static struct wordent * 209 freenod(p1, p2) 210 register struct wordent *p1, *p2; 211 { 212 register struct wordent *retp = p1->prev; 213 214 while (p1 != p2) { 215 xfree((ptr_t) p1->word); 216 p1 = p1->next; 217 xfree((ptr_t) (p1->prev)); 218 } 219 retp->next = p2; 220 p2->prev = retp; 221 return (retp); 222 } 223 224 #define PHERE 1 225 #define PIN 2 226 #define POUT 4 227 #define PERR 8 228 229 /* 230 * syntax 231 * empty 232 * syn0 233 */ 234 struct command * 235 syntax(p1, p2, flags) 236 register struct wordent *p1, *p2; 237 int flags; 238 { 239 240 while (p1 != p2) 241 if (any(";&\n", p1->word[0])) 242 p1 = p1->next; 243 else 244 return (syn0(p1, p2, flags)); 245 return (0); 246 } 247 248 /* 249 * syn0 250 * syn1 251 * syn1 & syntax 252 */ 253 static struct command * 254 syn0(p1, p2, flags) 255 struct wordent *p1, *p2; 256 int flags; 257 { 258 register struct wordent *p; 259 register struct command *t, *t1; 260 int l; 261 262 l = 0; 263 for (p = p1; p != p2; p = p->next) 264 switch (p->word[0]) { 265 266 case '(': 267 l++; 268 continue; 269 270 case ')': 271 l--; 272 if (l < 0) 273 seterror(ERR_TOOMANYRP); 274 continue; 275 276 case '|': 277 if (p->word[1] == '|') 278 continue; 279 /* fall into ... */ 280 281 case '>': 282 if (p->next != p2 && eq(p->next->word, STRand)) 283 p = p->next; 284 continue; 285 286 case '&': 287 if (l != 0) 288 break; 289 if (p->word[1] == '&') 290 continue; 291 t1 = syn1(p1, p, flags); 292 if (t1->t_dtyp == NODE_LIST || 293 t1->t_dtyp == NODE_AND || 294 t1->t_dtyp == NODE_OR) { 295 t = (struct command *) xcalloc(1, sizeof(*t)); 296 t->t_dtyp = NODE_PAREN; 297 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 298 t->t_dspr = t1; 299 t1 = t; 300 } 301 else 302 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 303 t = (struct command *) xcalloc(1, sizeof(*t)); 304 t->t_dtyp = NODE_LIST; 305 t->t_dflg = 0; 306 t->t_dcar = t1; 307 t->t_dcdr = syntax(p, p2, flags); 308 return (t); 309 } 310 if (l == 0) 311 return (syn1(p1, p2, flags)); 312 seterror(ERR_TOOMANYLP); 313 return (0); 314 } 315 316 /* 317 * syn1 318 * syn1a 319 * syn1a ; syntax 320 */ 321 static struct command * 322 syn1(p1, p2, flags) 323 struct wordent *p1, *p2; 324 int flags; 325 { 326 register struct wordent *p; 327 register struct command *t; 328 int l; 329 330 l = 0; 331 for (p = p1; p != p2; p = p->next) 332 switch (p->word[0]) { 333 334 case '(': 335 l++; 336 continue; 337 338 case ')': 339 l--; 340 continue; 341 342 case ';': 343 case '\n': 344 if (l != 0) 345 break; 346 t = (struct command *) xcalloc(1, sizeof(*t)); 347 t->t_dtyp = NODE_LIST; 348 t->t_dcar = syn1a(p1, p, flags); 349 t->t_dcdr = syntax(p->next, p2, flags); 350 if (t->t_dcdr == 0) 351 t->t_dcdr = t->t_dcar, t->t_dcar = 0; 352 return (t); 353 } 354 return (syn1a(p1, p2, flags)); 355 } 356 357 /* 358 * syn1a 359 * syn1b 360 * syn1b || syn1a 361 */ 362 static struct command * 363 syn1a(p1, p2, flags) 364 struct wordent *p1, *p2; 365 int flags; 366 { 367 register struct wordent *p; 368 register struct command *t; 369 register int l = 0; 370 371 for (p = p1; p != p2; p = p->next) 372 switch (p->word[0]) { 373 374 case '(': 375 l++; 376 continue; 377 378 case ')': 379 l--; 380 continue; 381 382 case '|': 383 if (p->word[1] != '|') 384 continue; 385 if (l == 0) { 386 t = (struct command *) xcalloc(1, sizeof(*t)); 387 t->t_dtyp = NODE_OR; 388 t->t_dcar = syn1b(p1, p, flags); 389 t->t_dcdr = syn1a(p->next, p2, flags); 390 t->t_dflg = 0; 391 return (t); 392 } 393 continue; 394 } 395 return (syn1b(p1, p2, flags)); 396 } 397 398 /* 399 * syn1b 400 * syn2 401 * syn2 && syn1b 402 */ 403 static struct command * 404 syn1b(p1, p2, flags) 405 struct wordent *p1, *p2; 406 int flags; 407 { 408 register struct wordent *p; 409 register struct command *t; 410 register int l = 0; 411 412 for (p = p1; p != p2; p = p->next) 413 switch (p->word[0]) { 414 415 case '(': 416 l++; 417 continue; 418 419 case ')': 420 l--; 421 continue; 422 423 case '&': 424 if (p->word[1] == '&' && l == 0) { 425 t = (struct command *) xcalloc(1, sizeof(*t)); 426 t->t_dtyp = NODE_AND; 427 t->t_dcar = syn2(p1, p, flags); 428 t->t_dcdr = syn1b(p->next, p2, flags); 429 t->t_dflg = 0; 430 return (t); 431 } 432 continue; 433 } 434 return (syn2(p1, p2, flags)); 435 } 436 437 /* 438 * syn2 439 * syn3 440 * syn3 | syn2 441 * syn3 |& syn2 442 */ 443 static struct command * 444 syn2(p1, p2, flags) 445 struct wordent *p1, *p2; 446 int flags; 447 { 448 register struct wordent *p, *pn; 449 register struct command *t; 450 register int l = 0; 451 int f; 452 453 for (p = p1; p != p2; p = p->next) 454 switch (p->word[0]) { 455 456 case '(': 457 l++; 458 continue; 459 460 case ')': 461 l--; 462 continue; 463 464 case '|': 465 if (l != 0) 466 continue; 467 t = (struct command *) xcalloc(1, sizeof(*t)); 468 f = flags | POUT; 469 pn = p->next; 470 if (pn != p2 && pn->word[0] == '&') { 471 f |= PERR; 472 t->t_dflg |= F_STDERR; 473 } 474 t->t_dtyp = NODE_PIPE; 475 t->t_dcar = syn3(p1, p, f); 476 if (pn != p2 && pn->word[0] == '&') 477 p = pn; 478 t->t_dcdr = syn2(p->next, p2, flags | PIN); 479 return (t); 480 } 481 return (syn3(p1, p2, flags)); 482 } 483 484 static char RELPAR[] = {'<', '>', '(', ')', '\0'}; 485 486 /* 487 * syn3 488 * ( syn0 ) [ < in ] [ > out ] 489 * word word* [ < in ] [ > out ] 490 * KEYWORD ( word* ) word* [ < in ] [ > out ] 491 * 492 * KEYWORD = (@ exit foreach if set switch test while) 493 */ 494 static struct command * 495 syn3(p1, p2, flags) 496 struct wordent *p1, *p2; 497 int flags; 498 { 499 register struct wordent *p; 500 struct wordent *lp, *rp; 501 register struct command *t; 502 register int l; 503 Char **av; 504 int n, c; 505 bool specp = 0; 506 507 if (p1 != p2) { 508 p = p1; 509 again: 510 switch (srchx(p->word)) { 511 512 case T_ELSE: 513 p = p->next; 514 if (p != p2) 515 goto again; 516 break; 517 518 case T_EXIT: 519 case T_FOREACH: 520 case T_IF: 521 case T_LET: 522 case T_SET: 523 case T_SWITCH: 524 case T_WHILE: 525 specp = 1; 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 & (POUT | PERR)) { 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 & POUT) && ((flags & PERR) == 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 & PHERE) && (t->t_dflg & F_READ)) 640 seterror(ERR_REDPAR); 641 else if ((flags & PIN) || 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, PHERE); 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 } 703 xfree((ptr_t) t); 704 } 705