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