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