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