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