1 /* $NetBSD: parse.c,v 1.12 2001/11/03 13:35:39 lukem 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.12 2001/11/03 13:35:39 lukem Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/types.h> 46 47 #include <stdlib.h> 48 #include <string.h> 49 50 #if __STDC__ 51 # include <stdarg.h> 52 #else 53 # include <varargs.h> 54 #endif 55 56 #include "csh.h" 57 #include "extern.h" 58 59 static void asyntax(struct wordent *, struct wordent *); 60 static void asyn0(struct wordent *, struct wordent *); 61 static void asyn3(struct wordent *, struct wordent *); 62 static struct wordent *freenod(struct wordent *, struct wordent *); 63 static struct command *syn0(struct wordent *, struct wordent *, int); 64 static struct command *syn1(struct wordent *, struct wordent *, int); 65 static struct command *syn1a(struct wordent *, struct wordent *, int); 66 static struct command *syn1b(struct wordent *, struct wordent *, int); 67 static struct command *syn2(struct wordent *, struct wordent *, int); 68 static struct command *syn3(struct wordent *, struct wordent *, int); 69 70 #define ALEFT 21 /* max of 20 alias expansions */ 71 #define HLEFT 11 /* max of 10 history expansions */ 72 /* 73 * Perform aliasing on the word list lex 74 * Do a (very rudimentary) parse to separate into commands. 75 * If word 0 of a command has an alias, do it. 76 * Repeat a maximum of 20 times. 77 */ 78 static int aleft; 79 extern int hleft; 80 81 void 82 alias(struct wordent *lexp) 83 { 84 jmp_buf osetexit; 85 86 aleft = ALEFT; 87 hleft = HLEFT; 88 getexit(osetexit); 89 (void)setexit(); 90 if (haderr) { 91 resexit(osetexit); 92 reset(); 93 } 94 if (--aleft == 0) 95 stderror(ERR_ALIASLOOP); 96 asyntax(lexp->next, lexp); 97 resexit(osetexit); 98 } 99 100 static void 101 asyntax(struct wordent *p1, struct wordent *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(struct wordent *p1, struct wordent *p2) 114 { 115 struct wordent *p; 116 int l; 117 118 l = 0; 119 for (p = p1; p != p2; p = p->next) 120 switch (p->word[0]) { 121 case '(': 122 l++; 123 continue; 124 case ')': 125 l--; 126 if (l < 0) 127 stderror(ERR_TOOMANYRP); 128 continue; 129 case '>': 130 if (p->next != p2 && eq(p->next->word, STRand)) 131 p = p->next; 132 continue; 133 case '&': 134 case '|': 135 case ';': 136 case '\n': 137 if (l != 0) 138 continue; 139 asyn3(p1, p); 140 asyntax(p->next, p2); 141 return; 142 } 143 if (l == 0) 144 asyn3(p1, p2); 145 } 146 147 static void 148 asyn3(struct wordent *p1, struct wordent *p2) 149 { 150 struct varent *ap; 151 struct wordent alout; 152 bool redid; 153 154 if (p1 == p2) 155 return; 156 if (p1->word[0] == '(') { 157 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 158 if (p2 == p1) 159 return; 160 if (p2 == p1->next) 161 return; 162 asyn0(p1->next, p2); 163 return; 164 } 165 ap = adrof1(p1->word, &aliases); 166 if (ap == 0) 167 return; 168 alhistp = p1->prev; 169 alhistt = p2; 170 alvec = ap->vec; 171 redid = lex(&alout); 172 alhistp = alhistt = 0; 173 alvec = 0; 174 if (seterr) { 175 freelex(&alout); 176 stderror(ERR_OLD); 177 } 178 if (p1->word[0] && eq(p1->word, alout.next->word)) { 179 Char *cp; 180 181 cp = alout.next->word; 182 alout.next->word = Strspl(STRQNULL, cp); 183 xfree((ptr_t) cp); 184 } 185 p1 = freenod(p1, redid ? p2 : p1->next); 186 if (alout.next != &alout) { 187 p1->next->prev = alout.prev->prev; 188 alout.prev->prev->next = p1->next; 189 alout.next->prev = p1; 190 p1->next = alout.next; 191 xfree((ptr_t)alout.prev->word); 192 xfree((ptr_t)(alout.prev)); 193 } 194 reset(); /* throw! */ 195 } 196 197 static struct wordent * 198 freenod(struct wordent *p1, struct wordent *p2) 199 { 200 struct wordent *retp; 201 202 retp = p1->prev; 203 while (p1 != p2) { 204 xfree((ptr_t)p1->word); 205 p1 = p1->next; 206 xfree((ptr_t) (p1->prev)); 207 } 208 retp->next = p2; 209 p2->prev = retp; 210 return (retp); 211 } 212 213 #define PHERE 1 214 #define PIN 2 215 #define POUT 4 216 #define PERR 8 217 218 /* 219 * syntax 220 * empty 221 * syn0 222 */ 223 struct command * 224 syntax(struct wordent *p1, struct wordent *p2, int flags) 225 { 226 while (p1 != p2) 227 if (any(";&\n", p1->word[0])) 228 p1 = p1->next; 229 else 230 return (syn0(p1, p2, flags)); 231 return (0); 232 } 233 234 /* 235 * syn0 236 * syn1 237 * syn1 & syntax 238 */ 239 static struct command * 240 syn0(struct wordent *p1, struct wordent *p2, int flags) 241 { 242 struct wordent *p; 243 struct command *t, *t1; 244 int l; 245 246 l = 0; 247 for (p = p1; p != p2; p = p->next) 248 switch (p->word[0]) { 249 case '(': 250 l++; 251 continue; 252 case ')': 253 l--; 254 if (l < 0) 255 seterror(ERR_TOOMANYRP); 256 continue; 257 case '|': 258 if (p->word[1] == '|') 259 continue; 260 /* FALLTHROUGH */ 261 case '>': 262 if (p->next != p2 && eq(p->next->word, STRand)) 263 p = p->next; 264 continue; 265 case '&': 266 if (l != 0) 267 break; 268 if (p->word[1] == '&') 269 continue; 270 t1 = syn1(p1, p, flags); 271 if (t1->t_dtyp == NODE_LIST || 272 t1->t_dtyp == NODE_AND || 273 t1->t_dtyp == NODE_OR) { 274 t = (struct command *)xcalloc(1, sizeof(*t)); 275 t->t_dtyp = NODE_PAREN; 276 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 277 t->t_dspr = t1; 278 t1 = t; 279 } 280 else 281 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 282 t = (struct command *)xcalloc(1, sizeof(*t)); 283 t->t_dtyp = NODE_LIST; 284 t->t_dflg = 0; 285 t->t_dcar = t1; 286 t->t_dcdr = syntax(p, p2, flags); 287 return (t); 288 } 289 if (l == 0) 290 return (syn1(p1, p2, flags)); 291 seterror(ERR_TOOMANYLP); 292 return (0); 293 } 294 295 /* 296 * syn1 297 * syn1a 298 * syn1a ; syntax 299 */ 300 static struct command * 301 syn1(struct wordent *p1, struct wordent *p2, int flags) 302 { 303 struct wordent *p; 304 struct command *t; 305 int l; 306 307 l = 0; 308 for (p = p1; p != p2; p = p->next) 309 switch (p->word[0]) { 310 case '(': 311 l++; 312 continue; 313 case ')': 314 l--; 315 continue; 316 case ';': 317 case '\n': 318 if (l != 0) 319 break; 320 t = (struct command *) xcalloc(1, sizeof(*t)); 321 t->t_dtyp = NODE_LIST; 322 t->t_dcar = syn1a(p1, p, flags); 323 t->t_dcdr = syntax(p->next, p2, flags); 324 if (t->t_dcdr == 0) 325 t->t_dcdr = t->t_dcar, t->t_dcar = 0; 326 return (t); 327 } 328 return (syn1a(p1, p2, flags)); 329 } 330 331 /* 332 * syn1a 333 * syn1b 334 * syn1b || syn1a 335 */ 336 static struct command * 337 syn1a(struct wordent *p1, struct wordent *p2, int flags) 338 { 339 struct wordent *p; 340 struct command *t; 341 int l; 342 343 l = 0; 344 for (p = p1; p != p2; p = p->next) 345 switch (p->word[0]) { 346 case '(': 347 l++; 348 continue; 349 case ')': 350 l--; 351 continue; 352 case '|': 353 if (p->word[1] != '|') 354 continue; 355 if (l == 0) { 356 t = (struct command *)xcalloc(1, sizeof(*t)); 357 t->t_dtyp = NODE_OR; 358 t->t_dcar = syn1b(p1, p, flags); 359 t->t_dcdr = syn1a(p->next, p2, flags); 360 t->t_dflg = 0; 361 return (t); 362 } 363 continue; 364 } 365 return (syn1b(p1, p2, flags)); 366 } 367 368 /* 369 * syn1b 370 * syn2 371 * syn2 && syn1b 372 */ 373 static struct command * 374 syn1b(struct wordent *p1, struct wordent *p2, int flags) 375 { 376 struct wordent *p; 377 struct command *t; 378 int l; 379 380 l = 0; 381 for (p = p1; p != p2; p = p->next) 382 switch (p->word[0]) { 383 case '(': 384 l++; 385 continue; 386 case ')': 387 l--; 388 continue; 389 case '&': 390 if (p->word[1] == '&' && l == 0) { 391 t = (struct command *)xcalloc(1, sizeof(*t)); 392 t->t_dtyp = NODE_AND; 393 t->t_dcar = syn2(p1, p, flags); 394 t->t_dcdr = syn1b(p->next, p2, flags); 395 t->t_dflg = 0; 396 return (t); 397 } 398 continue; 399 } 400 return (syn2(p1, p2, flags)); 401 } 402 403 /* 404 * syn2 405 * syn3 406 * syn3 | syn2 407 * syn3 |& syn2 408 */ 409 static struct command * 410 syn2(struct wordent *p1, struct wordent *p2, int flags) 411 { 412 struct wordent *p, *pn; 413 struct command *t; 414 int f, l; 415 416 l = 0; 417 for (p = p1; p != p2; p = p->next) 418 switch (p->word[0]) { 419 case '(': 420 l++; 421 continue; 422 case ')': 423 l--; 424 continue; 425 case '|': 426 if (l != 0) 427 continue; 428 t = (struct command *)xcalloc(1, sizeof(*t)); 429 f = flags | POUT; 430 pn = p->next; 431 if (pn != p2 && pn->word[0] == '&') { 432 f |= PERR; 433 t->t_dflg |= F_STDERR; 434 } 435 t->t_dtyp = NODE_PIPE; 436 t->t_dcar = syn3(p1, p, f); 437 if (pn != p2 && pn->word[0] == '&') 438 p = pn; 439 t->t_dcdr = syn2(p->next, p2, flags | PIN); 440 return (t); 441 } 442 return (syn3(p1, p2, flags)); 443 } 444 445 static char RELPAR[] = {'<', '>', '(', ')', '\0'}; 446 447 /* 448 * syn3 449 * ( syn0 ) [ < in ] [ > out ] 450 * word word* [ < in ] [ > out ] 451 * KEYWORD ( word* ) word* [ < in ] [ > out ] 452 * 453 * KEYWORD = (@ exit foreach if set switch test while) 454 */ 455 static struct command * 456 syn3(struct wordent *p1, struct wordent *p2, int flags) 457 { 458 struct wordent *lp, *p, *rp; 459 struct command *t; 460 Char **av; 461 int c, l, n; 462 bool specp; 463 464 specp = 0; 465 if (p1 != p2) { 466 p = p1; 467 again: 468 switch (srchx(p->word)) { 469 case T_ELSE: 470 p = p->next; 471 if (p != p2) 472 goto again; 473 break; 474 case T_EXIT: 475 case T_FOREACH: 476 case T_IF: 477 case T_LET: 478 case T_SET: 479 case T_SWITCH: 480 case T_WHILE: 481 specp = 1; 482 break; 483 } 484 } 485 n = 0; 486 l = 0; 487 for (p = p1; p != p2; p = p->next) 488 switch (p->word[0]) { 489 case '(': 490 if (specp) 491 n++; 492 l++; 493 continue; 494 case ')': 495 if (specp) 496 n++; 497 l--; 498 continue; 499 case '>': 500 case '<': 501 if (l != 0) { 502 if (specp) 503 n++; 504 continue; 505 } 506 if (p->next == p2) 507 continue; 508 if (any(RELPAR, p->next->word[0])) 509 continue; 510 n--; 511 continue; 512 default: 513 if (!specp && l != 0) 514 continue; 515 n++; 516 continue; 517 } 518 if (n < 0) 519 n = 0; 520 t = (struct command *)xcalloc(1, sizeof(*t)); 521 av = (Char **)xcalloc((size_t)(n + 1), sizeof(Char **)); 522 t->t_dcom = av; 523 n = 0; 524 if (p2->word[0] == ')') 525 t->t_dflg = F_NOFORK; 526 lp = 0; 527 rp = 0; 528 l = 0; 529 for (p = p1; p != p2; p = p->next) { 530 c = p->word[0]; 531 switch (c) { 532 case '(': 533 if (l == 0) { 534 if (lp != 0 && !specp) 535 seterror(ERR_BADPLP); 536 lp = p->next; 537 } 538 l++; 539 goto savep; 540 case ')': 541 l--; 542 if (l == 0) 543 rp = p; 544 goto savep; 545 case '>': 546 if (l != 0) 547 goto savep; 548 if (p->word[1] == '>') 549 t->t_dflg |= F_APPEND; 550 if (p->next != p2 && eq(p->next->word, STRand)) { 551 t->t_dflg |= F_STDERR, p = p->next; 552 if (flags & (POUT | PERR)) { 553 seterror(ERR_OUTRED); 554 continue; 555 } 556 } 557 if (p->next != p2 && eq(p->next->word, STRbang)) 558 t->t_dflg |= F_OVERWRITE, p = p->next; 559 if (p->next == p2) { 560 seterror(ERR_MISRED); 561 continue; 562 } 563 p = p->next; 564 if (any(RELPAR, p->word[0])) { 565 seterror(ERR_MISRED); 566 continue; 567 } 568 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit)) 569 seterror(ERR_OUTRED); 570 else 571 t->t_drit = Strsave(p->word); 572 continue; 573 case '<': 574 if (l != 0) 575 goto savep; 576 if (p->word[1] == '<') 577 t->t_dflg |= F_READ; 578 if (p->next == p2) { 579 seterror(ERR_MISRED); 580 continue; 581 } 582 p = p->next; 583 if (any(RELPAR, p->word[0])) { 584 seterror(ERR_MISRED); 585 continue; 586 } 587 if ((flags & PHERE) && (t->t_dflg & F_READ)) 588 seterror(ERR_REDPAR); 589 else if ((flags & PIN) || t->t_dlef) 590 seterror(ERR_INRED); 591 else 592 t->t_dlef = Strsave(p->word); 593 continue; 594 savep: 595 if (!specp) 596 continue; 597 /* FALLTHROUGH */ 598 default: 599 if (l != 0 && !specp) 600 continue; 601 if (seterr == 0) 602 av[n] = Strsave(p->word); 603 n++; 604 continue; 605 } 606 } 607 if (lp != 0 && !specp) { 608 if (n != 0) 609 seterror(ERR_BADPLPS); 610 t->t_dtyp = NODE_PAREN; 611 t->t_dspr = syn0(lp, rp, PHERE); 612 } 613 else { 614 if (n == 0) 615 seterror(ERR_NULLCOM); 616 t->t_dtyp = NODE_COMMAND; 617 } 618 return (t); 619 } 620 621 void 622 freesyn(struct command *t) 623 { 624 Char **v; 625 626 if (t == 0) 627 return; 628 switch (t->t_dtyp) { 629 case NODE_COMMAND: 630 for (v = t->t_dcom; *v; v++) 631 xfree((ptr_t) * v); 632 xfree((ptr_t)(t->t_dcom)); 633 xfree((ptr_t)t->t_dlef); 634 xfree((ptr_t)t->t_drit); 635 break; 636 case NODE_PAREN: 637 freesyn(t->t_dspr); 638 xfree((ptr_t)t->t_dlef); 639 xfree((ptr_t)t->t_drit); 640 break; 641 case NODE_AND: 642 case NODE_OR: 643 case NODE_PIPE: 644 case NODE_LIST: 645 freesyn(t->t_dcar), freesyn(t->t_dcdr); 646 break; 647 } 648 xfree((ptr_t)t); 649 } 650