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