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