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