1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #pragma ident "%Z%%M% %I% %E% SMI" 16 17 #include "sh.h" 18 #include "sh.tconst.h" 19 20 /* 21 * C shell 22 */ 23 24 void asyntax(struct wordent *, struct wordent *); 25 void asyn0(struct wordent *, struct wordent *); 26 void asyn3(struct wordent *, struct wordent *); 27 void chr_blkfree(char **); 28 struct command *syn0(struct wordent *, struct wordent *, int); 29 struct command *syn1(struct wordent *, struct wordent *, int); 30 struct command *syn1a(struct wordent *, struct wordent *, int); 31 struct command *syn1b(struct wordent *, struct wordent *, int); 32 struct command *syn2(struct wordent *, struct wordent *, int); 33 struct command *syn3(struct wordent *, struct wordent *, int); 34 struct wordent *freenod(struct wordent *, struct wordent *); 35 36 /* 37 * Perform aliasing on the word list lex 38 * Do a (very rudimentary) parse to separate into commands. 39 * If word 0 of a command has an alias, do it. 40 * Repeat a maximum of 20 times. 41 */ 42 void 43 alias(struct wordent *lex) 44 { 45 int aleft = 21; 46 jmp_buf osetexit; 47 48 #ifdef TRACE 49 tprintf("TRACE- alias()\n"); 50 #endif 51 getexit(osetexit); 52 setexit(); 53 if (haderr) { 54 resexit(osetexit); 55 reset(); 56 } 57 if (--aleft == 0) 58 error("Alias loop"); 59 asyntax(lex->next, lex); 60 resexit(osetexit); 61 } 62 63 void 64 asyntax(struct wordent *p1, struct wordent *p2) 65 { 66 #ifdef TRACE 67 tprintf("TRACE- asyntax()\n"); 68 #endif 69 70 while (p1 != p2) 71 /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */ 72 if (p1->word[0] == ';' || 73 p1->word[0] == '&' || 74 p1->word[0] == '\n') 75 p1 = p1->next; 76 else { 77 asyn0(p1, p2); 78 return; 79 } 80 } 81 82 void 83 asyn0(struct wordent *p1, struct wordent *p2) 84 { 85 struct wordent *p; 86 int l = 0; 87 88 #ifdef TRACE 89 tprintf("TRACE- asyn0()\n"); 90 #endif 91 for (p = p1; p != p2; p = p->next) 92 switch (p->word[0]) { 93 94 case '(': 95 l++; 96 continue; 97 98 case ')': 99 l--; 100 if (l < 0) 101 error("Too many )'s"); 102 continue; 103 104 case '>': 105 if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/)) 106 p = p->next; 107 continue; 108 109 case '&': 110 case '|': 111 case ';': 112 case '\n': 113 if (l != 0) 114 continue; 115 asyn3(p1, p); 116 asyntax(p->next, p2); 117 return; 118 } 119 if (l == 0) 120 asyn3(p1, p2); 121 } 122 123 void 124 asyn3(struct wordent *p1, struct wordent *p2) 125 { 126 struct varent *ap; 127 struct wordent alout; 128 bool redid; 129 130 #ifdef TRACE 131 tprintf("TRACE- asyn3()\n"); 132 #endif 133 if (p1 == p2) 134 return; 135 if (p1->word[0] == '(') { 136 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 137 if (p2 == p1) 138 return; 139 if (p2 == p1->next) 140 return; 141 asyn0(p1->next, p2); 142 return; 143 } 144 ap = adrof1(p1->word, &aliases); 145 if (ap == 0) 146 return; 147 alhistp = p1->prev; 148 alhistt = p2; 149 alvec = ap->vec; 150 redid = lex(&alout); 151 alhistp = alhistt = 0; 152 alvec = 0; 153 if (err) { 154 freelex(&alout); 155 error("%s", gettext(err)); 156 } 157 if (p1->word[0] && eq(p1->word, alout.next->word)) { 158 tchar *cp = alout.next->word; 159 160 alout.next->word = strspl(S_TOPBIT /*"\200"*/, cp); 161 XFREE(cp) 162 } 163 p1 = freenod(p1, redid ? p2 : p1->next); 164 if (alout.next != &alout) { 165 p1->next->prev = alout.prev->prev; 166 alout.prev->prev->next = p1->next; 167 alout.next->prev = p1; 168 p1->next = alout.next; 169 XFREE(alout.prev->word) 170 XFREE( (tchar *)alout.prev) 171 } 172 reset(); /* throw! */ 173 } 174 175 struct wordent * 176 freenod(struct wordent *p1, struct wordent *p2) 177 { 178 struct wordent *retp = p1->prev; 179 180 #ifdef TRACE 181 tprintf("TRACE- freenod()\n"); 182 #endif 183 while (p1 != p2) { 184 XFREE(p1->word) 185 p1 = p1->next; 186 XFREE( (tchar *)p1->prev) 187 } 188 retp->next = p2; 189 p2->prev = retp; 190 return (retp); 191 } 192 193 #define PHERE 1 194 #define PIN 2 195 #define POUT 4 196 #define PDIAG 8 197 198 /* 199 * syntax 200 * empty 201 * syn0 202 */ 203 struct command * 204 syntax(struct wordent *p1, struct wordent *p2, int flags) 205 { 206 #ifdef TRACE 207 tprintf("TRACE- syntax()\n"); 208 #endif 209 210 while (p1 != p2) 211 /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */ 212 if (p1->word[0] == ';' || 213 p1->word[0] == '&' || 214 p1->word[0] == '\n') 215 p1 = p1->next; 216 else 217 return (syn0(p1, p2, flags)); 218 return (0); 219 } 220 221 /* 222 * syn0 223 * syn1 224 * syn1 & syntax 225 */ 226 struct command * 227 syn0(struct wordent *p1, struct wordent *p2, int flags) 228 { 229 struct wordent *p; 230 struct command *t, *t1; 231 int l; 232 233 #ifdef TRACE 234 tprintf("TRACE- syn0()\n"); 235 #endif 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 seterr("Too many )'s"); 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, S_AND /*"&"*/)) 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 == TLST || 267 t1->t_dtyp == TAND || 268 t1->t_dtyp == TOR) { 269 t = (struct command *) calloc(1, sizeof (*t)); 270 t->t_dtyp = TPAR; 271 t->t_dflg = FAND|FINT; 272 t->t_dspr = t1; 273 t1 = t; 274 } else 275 t1->t_dflg |= FAND|FINT; 276 t = (struct command *) calloc(1, sizeof (*t)); 277 t->t_dtyp = TLST; 278 t->t_dflg = 0; 279 t->t_dcar = t1; 280 t->t_dcdr = syntax(p, p2, flags); 281 return(t); 282 } 283 if (l == 0) 284 return (syn1(p1, p2, flags)); 285 seterr("Too many ('s"); 286 return (0); 287 } 288 289 /* 290 * syn1 291 * syn1a 292 * syn1a ; syntax 293 */ 294 struct command * 295 syn1(struct wordent *p1, struct wordent *p2, int flags) 296 { 297 struct wordent *p; 298 struct command *t; 299 int l; 300 301 #ifdef TRACE 302 tprintf("TRACE- syn1()\n"); 303 #endif 304 l = 0; 305 for (p = p1; p != p2; p = p->next) 306 switch (p->word[0]) { 307 308 case '(': 309 l++; 310 continue; 311 312 case ')': 313 l--; 314 continue; 315 316 case ';': 317 case '\n': 318 if (l != 0) 319 break; 320 t = (struct command *) calloc(1, sizeof (*t)); 321 t->t_dtyp = TLST; 322 t->t_dcar = syn1a(p1, p, flags); 323 t->t_dcdr = syntax(p->next, p2, flags); 324 if (t->t_dcdr == 0) 325 t->t_dcdr = t->t_dcar, t->t_dcar = 0; 326 return (t); 327 } 328 return (syn1a(p1, p2, flags)); 329 } 330 331 /* 332 * syn1a 333 * syn1b 334 * syn1b || syn1a 335 */ 336 struct command * 337 syn1a(struct wordent *p1, struct wordent *p2, int flags) 338 { 339 struct wordent *p; 340 struct command *t; 341 int l = 0; 342 343 #ifdef TRACE 344 tprintf("TRACE- syn1a()\n"); 345 #endif 346 for (p = p1; p != p2; p = p->next) 347 switch (p->word[0]) { 348 349 case '(': 350 l++; 351 continue; 352 353 case ')': 354 l--; 355 continue; 356 357 case '|': 358 if (p->word[1] != '|') 359 continue; 360 if (l == 0) { 361 t = (struct command *) calloc(1, sizeof (*t)); 362 t->t_dtyp = TOR; 363 t->t_dcar = syn1b(p1, p, flags); 364 t->t_dcdr = syn1a(p->next, p2, flags); 365 t->t_dflg = 0; 366 return (t); 367 } 368 continue; 369 } 370 return (syn1b(p1, p2, flags)); 371 } 372 373 /* 374 * syn1b 375 * syn2 376 * syn2 && syn1b 377 */ 378 struct command * 379 syn1b(struct wordent *p1, struct wordent *p2, int flags) 380 { 381 struct wordent *p; 382 struct command *t; 383 int l = 0; 384 385 #ifdef TRACE 386 tprintf("TRACE- syn1b()\n"); 387 #endif 388 l = 0; 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 (p->word[1] == '&' && l == 0) { 402 t = (struct command *) calloc(1, sizeof (*t)); 403 t->t_dtyp = TAND; 404 t->t_dcar = syn2(p1, p, flags); 405 t->t_dcdr = syn1b(p->next, p2, flags); 406 t->t_dflg = 0; 407 return (t); 408 } 409 continue; 410 } 411 return (syn2(p1, p2, flags)); 412 } 413 414 /* 415 * syn2 416 * syn3 417 * syn3 | syn2 418 * syn3 |& syn2 419 */ 420 struct command * 421 syn2(struct wordent *p1, struct wordent *p2, int flags) 422 { 423 struct wordent *p, *pn; 424 struct command *t; 425 int l = 0; 426 int f; 427 428 #ifdef TRACE 429 tprintf("TRACE- syn2()\n"); 430 #endif 431 for (p = p1; p != p2; p = p->next) 432 switch (p->word[0]) { 433 434 case '(': 435 l++; 436 continue; 437 438 case ')': 439 l--; 440 continue; 441 442 case '|': 443 if (l != 0) 444 continue; 445 t = (struct command *) calloc(1, sizeof (*t)); 446 f = flags | POUT; 447 pn = p->next; 448 if (pn != p2 && pn->word[0] == '&') { 449 f |= PDIAG; 450 t->t_dflg |= FDIAG; 451 } 452 t->t_dtyp = TFIL; 453 t->t_dcar = syn3(p1, p, f); 454 if (pn != p2 && pn->word[0] == '&') 455 p = pn; 456 t->t_dcdr = syn2(p->next, p2, flags | PIN); 457 return (t); 458 } 459 return (syn3(p1, p2, flags)); 460 } 461 462 tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */ 463 464 /* 465 * syn3 466 * ( syn0 ) [ < in ] [ > out ] 467 * word word* [ < in ] [ > out ] 468 * KEYWORD ( word* ) word* [ < in ] [ > out ] 469 * 470 * KEYWORD = (@ exit foreach if set switch test while) 471 */ 472 struct command * 473 syn3(struct wordent *p1, struct wordent *p2, int flags) 474 { 475 struct wordent *p; 476 struct wordent *lp, *rp; 477 struct command *t; 478 int l; 479 tchar **av; 480 int n, c; 481 bool specp = 0; 482 483 #ifdef TRACE 484 tprintf("TRACE- syn3()\n"); 485 #endif 486 if (p1 != p2) { 487 p = p1; 488 again: 489 switch (srchx(p->word)) { 490 491 case ZELSE: 492 p = p->next; 493 if (p != p2) 494 goto again; 495 break; 496 497 case ZEXIT: 498 case ZFOREACH: 499 case ZIF: 500 case ZLET: 501 case ZSET: 502 case ZSWITCH: 503 case ZWHILE: 504 specp = 1; 505 break; 506 } 507 } 508 n = 0; 509 l = 0; 510 for (p = p1; p != p2; p = p->next) 511 switch (p->word[0]) { 512 513 case '(': 514 if (specp) 515 n++; 516 l++; 517 continue; 518 519 case ')': 520 if (specp) 521 n++; 522 l--; 523 continue; 524 525 case '>': 526 case '<': 527 if (l != 0) { 528 if (specp) 529 n++; 530 continue; 531 } 532 if (p->next == p2) 533 continue; 534 if (any(p->next->word[0], RELPAR)) 535 continue; 536 n--; 537 continue; 538 539 default: 540 if (!specp && l != 0) 541 continue; 542 n++; 543 continue; 544 } 545 if (n < 0) 546 n = 0; 547 t = (struct command *) calloc(1, sizeof (*t)); 548 av = (tchar **) calloc((unsigned) (n + 1), sizeof (tchar **)); 549 t->t_dcom = av; 550 n = 0; 551 if (p2->word[0] == ')') 552 t->t_dflg = FPAR; 553 lp = 0; 554 rp = 0; 555 l = 0; 556 for (p = p1; p != p2; p = p->next) { 557 c = p->word[0]; 558 switch (c) { 559 560 case '(': 561 if (l == 0) { 562 if (lp != 0 && !specp) 563 seterr("Badly placed ("); 564 lp = p->next; 565 } 566 l++; 567 goto savep; 568 569 case ')': 570 l--; 571 if (l == 0) 572 rp = p; 573 goto savep; 574 575 case '>': 576 if (l != 0) 577 goto savep; 578 if (p->word[1] == '>') 579 t->t_dflg |= FCAT; 580 if (p->next != p2 && eq(p->next->word, S_AND /*"&"*/)) { 581 t->t_dflg |= FDIAG, p = p->next; 582 if (flags & (POUT|PDIAG)) 583 goto badout; 584 } 585 if (p->next != p2 && eq(p->next->word, S_EXAS /*"!"*/)) 586 t->t_dflg |= FANY, p = p->next; 587 if (p->next == p2) { 588 missfile: 589 seterr("Missing name for redirect"); 590 continue; 591 } 592 p = p->next; 593 if (any(p->word[0], RELPAR)) 594 goto missfile; 595 if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 596 badout: 597 seterr("Ambiguous output redirect"); 598 else 599 t->t_drit = savestr(p->word); 600 continue; 601 602 case '<': 603 if (l != 0) 604 goto savep; 605 if (p->word[1] == '<') 606 t->t_dflg |= FHERE; 607 if (p->next == p2) 608 goto missfile; 609 p = p->next; 610 if (any(p->word[0], RELPAR)) 611 goto missfile; 612 if ((flags & PHERE) && (t->t_dflg & FHERE)) 613 seterr("Can't << within ()'s"); 614 else if ((flags & PIN) || t->t_dlef) 615 seterr("Ambiguous input redirect"); 616 else 617 t->t_dlef = savestr(p->word); 618 continue; 619 620 savep: 621 if (!specp) 622 continue; 623 default: 624 if (l != 0 && !specp) 625 continue; 626 if (err == 0) 627 av[n] = savestr(p->word); 628 n++; 629 continue; 630 } 631 } 632 if (lp != 0 && !specp) { 633 if (n != 0) 634 seterr("Badly placed ()'s"); 635 t->t_dtyp = TPAR; 636 t->t_dspr = syn0(lp, rp, PHERE); 637 } else { 638 if (n == 0) 639 seterr("Invalid null command"); 640 t->t_dtyp = TCOM; 641 } 642 return (t); 643 } 644 645 void 646 freesyn(struct command *t) 647 { 648 #ifdef TRACE 649 tprintf("TRACE- freesyn()\n"); 650 #endif 651 if (t == 0) 652 return; 653 switch (t->t_dtyp) { 654 655 case TCOM: 656 blkfree(t->t_dcom); 657 if (t->cfname) 658 xfree(t->cfname); 659 if (t->cargs) 660 chr_blkfree(t->cargs); 661 goto lr; 662 663 case TPAR: 664 freesyn(t->t_dspr); 665 /* fall into ... */ 666 667 lr: 668 XFREE(t->t_dlef) 669 XFREE(t->t_drit) 670 break; 671 672 case TAND: 673 case TOR: 674 case TFIL: 675 case TLST: 676 freesyn(t->t_dcar), freesyn(t->t_dcdr); 677 break; 678 } 679 XFREE( (tchar *)t) 680 } 681 682 683 void 684 chr_blkfree(char **vec) 685 { 686 char **av; 687 688 for (av = vec; *av; av++) 689 xfree(*av); 690 xfree(vec); 691 } 692