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