1#define Extern extern 2#include <sys/types.h> 3#include <signal.h> 4#define _NSIG NSIG 5#include <errno.h> 6#include <setjmp.h> 7#include "sh.h" 8 9/* -------- csyn.c -------- */ 10/* 11 * shell: syntax (C version) 12 */ 13 14typedef union { 15 char *cp; 16 char **wp; 17 int i; 18 struct op *o; 19} YYSTYPE; 20#define WORD 256 21#define LOGAND 257 22#define LOGOR 258 23#define BREAK 259 24#define IF 260 25#define THEN 261 26#define ELSE 262 27#define ELIF 263 28#define FI 264 29#define CASE 265 30#define ESAC 266 31#define FOR 267 32#define WHILE 268 33#define UNTIL 269 34#define DO 270 35#define DONE 271 36#define IN 272 37#define YYERRCODE 300 38 39/* flags to yylex */ 40#define CONTIN 01 /* skip new lines to complete command */ 41 42/* #include "sh.h" */ 43#define SYNTAXERR zzerr() 44static int startl; 45static int peeksym; 46static int nlseen; 47static int iounit = IODEFAULT; 48 49static YYSTYPE yylval; 50 51_PROTOTYPE(static struct op *pipeline, (int cf )); 52_PROTOTYPE(static struct op *andor, (void)); 53_PROTOTYPE(static struct op *c_list, (void)); 54_PROTOTYPE(static int synio, (int cf )); 55_PROTOTYPE(static void musthave, (int c, int cf )); 56_PROTOTYPE(static struct op *simple, (void)); 57_PROTOTYPE(static struct op *nested, (int type, int mark )); 58_PROTOTYPE(static struct op *command, (int cf )); 59_PROTOTYPE(static struct op *dogroup, (int onlydone )); 60_PROTOTYPE(static struct op *thenpart, (void)); 61_PROTOTYPE(static struct op *elsepart, (void)); 62_PROTOTYPE(static struct op *caselist, (void)); 63_PROTOTYPE(static struct op *casepart, (void)); 64_PROTOTYPE(static char **pattern, (void)); 65_PROTOTYPE(static char **wordlist, (void)); 66_PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 )); 67_PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp )); 68_PROTOTYPE(static struct op *newtp, (void)); 69_PROTOTYPE(static struct op *namelist, (struct op *t )); 70_PROTOTYPE(static char **copyw, (void)); 71_PROTOTYPE(static void word, (char *cp )); 72_PROTOTYPE(static struct ioword **copyio, (void)); 73_PROTOTYPE(static struct ioword *io, (int u, int f, char *cp )); 74_PROTOTYPE(static void zzerr, (void)); 75_PROTOTYPE(void yyerror, (char *s )); 76_PROTOTYPE(static int yylex, (int cf )); 77_PROTOTYPE(int collect, (int c, int c1 )); 78_PROTOTYPE(int dual, (int c )); 79_PROTOTYPE(static void diag, (int ec )); 80_PROTOTYPE(static char *tree, (unsigned size )); 81_PROTOTYPE(void printf, (char *s )); 82 83int 84yyparse() 85{ 86 startl = 1; 87 peeksym = 0; 88 yynerrs = 0; 89 outtree = c_list(); 90 musthave('\n', 0); 91 return(yynerrs!=0); 92} 93 94static struct op * 95pipeline(cf) 96int cf; 97{ 98 register struct op *t, *p; 99 register int c; 100 101 t = command(cf); 102 if (t != NULL) { 103 while ((c = yylex(0)) == '|') { 104 if ((p = command(CONTIN)) == NULL) 105 SYNTAXERR; 106 if (t->type != TPAREN && t->type != TCOM) { 107 /* shell statement */ 108 t = block(TPAREN, t, NOBLOCK, NOWORDS); 109 } 110 t = block(TPIPE, t, p, NOWORDS); 111 } 112 peeksym = c; 113 } 114 return(t); 115} 116 117static struct op * 118andor() 119{ 120 register struct op *t, *p; 121 register int c; 122 123 t = pipeline(0); 124 if (t != NULL) { 125 while ((c = yylex(0)) == LOGAND || c == LOGOR) { 126 if ((p = pipeline(CONTIN)) == NULL) 127 SYNTAXERR; 128 t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); 129 } 130 peeksym = c; 131 } 132 return(t); 133} 134 135static struct op * 136c_list() 137{ 138 register struct op *t, *p; 139 register int c; 140 141 t = andor(); 142 if (t != NULL) { 143 if((peeksym = yylex(0)) == '&') 144 t = block(TASYNC, t, NOBLOCK, NOWORDS); 145 while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) { 146 if ((p = andor()) == NULL) 147 return(t); 148 if((peeksym = yylex(0)) == '&') 149 p = block(TASYNC, p, NOBLOCK, NOWORDS); 150 t = list(t, p); 151 } 152 peeksym = c; 153 } 154 return(t); 155} 156 157 158static int 159synio(cf) 160int cf; 161{ 162 register struct ioword *iop; 163 register int i; 164 register int c; 165 166 if ((c = yylex(cf)) != '<' && c != '>') { 167 peeksym = c; 168 return(0); 169 } 170 i = yylval.i; 171 musthave(WORD, 0); 172 iop = io(iounit, i, yylval.cp); 173 iounit = IODEFAULT; 174 if (i & IOHERE) 175 markhere(yylval.cp, iop); 176 return(1); 177} 178 179static void 180musthave(c, cf) 181int c, cf; 182{ 183 if ((peeksym = yylex(cf)) != c) 184 SYNTAXERR; 185 peeksym = 0; 186} 187 188static struct op * 189simple() 190{ 191 register struct op *t; 192 193 t = NULL; 194 for (;;) { 195 switch (peeksym = yylex(0)) { 196 case '<': 197 case '>': 198 (void) synio(0); 199 break; 200 201 case WORD: 202 if (t == NULL) { 203 t = newtp(); 204 t->type = TCOM; 205 } 206 peeksym = 0; 207 word(yylval.cp); 208 break; 209 210 default: 211 return(t); 212 } 213 } 214} 215 216static struct op * 217nested(type, mark) 218int type, mark; 219{ 220 register struct op *t; 221 222 multiline++; 223 t = c_list(); 224 musthave(mark, 0); 225 multiline--; 226 return(block(type, t, NOBLOCK, NOWORDS)); 227} 228 229static struct op * 230command(cf) 231int cf; 232{ 233 register struct op *t; 234 struct wdblock *iosave; 235 register int c; 236 237 iosave = iolist; 238 iolist = NULL; 239 if (multiline) 240 cf |= CONTIN; 241 while (synio(cf)) 242 cf = 0; 243 switch (c = yylex(cf)) { 244 default: 245 peeksym = c; 246 if ((t = simple()) == NULL) { 247 if (iolist == NULL) 248 return((struct op *)NULL); 249 t = newtp(); 250 t->type = TCOM; 251 } 252 break; 253 254 case '(': 255 t = nested(TPAREN, ')'); 256 break; 257 258 case '{': 259 t = nested(TBRACE, '}'); 260 break; 261 262 case FOR: 263 t = newtp(); 264 t->type = TFOR; 265 musthave(WORD, 0); 266 startl = 1; 267 t->str = yylval.cp; 268 multiline++; 269 t->words = wordlist(); 270 if ((c = yylex(0)) != '\n' && c != ';') 271 peeksym = c; 272 t->left = dogroup(0); 273 multiline--; 274 break; 275 276 case WHILE: 277 case UNTIL: 278 multiline++; 279 t = newtp(); 280 t->type = c == WHILE? TWHILE: TUNTIL; 281 t->left = c_list(); 282 t->right = dogroup(1); 283 t->words = NULL; 284 multiline--; 285 break; 286 287 case CASE: 288 t = newtp(); 289 t->type = TCASE; 290 musthave(WORD, 0); 291 t->str = yylval.cp; 292 startl++; 293 multiline++; 294 musthave(IN, CONTIN); 295 startl++; 296 t->left = caselist(); 297 musthave(ESAC, 0); 298 multiline--; 299 break; 300 301 case IF: 302 multiline++; 303 t = newtp(); 304 t->type = TIF; 305 t->left = c_list(); 306 t->right = thenpart(); 307 musthave(FI, 0); 308 multiline--; 309 break; 310 } 311 while (synio(0)) 312 ; 313 t = namelist(t); 314 iolist = iosave; 315 return(t); 316} 317 318static struct op * 319dogroup(onlydone) 320int onlydone; 321{ 322 register int c; 323 register struct op *list; 324 325 c = yylex(CONTIN); 326 if (c == DONE && onlydone) 327 return((struct op *)NULL); 328 if (c != DO) 329 SYNTAXERR; 330 list = c_list(); 331 musthave(DONE, 0); 332 return(list); 333} 334 335static struct op * 336thenpart() 337{ 338 register int c; 339 register struct op *t; 340 341 if ((c = yylex(0)) != THEN) { 342 peeksym = c; 343 return((struct op *)NULL); 344 } 345 t = newtp(); 346 t->type = 0; 347 t->left = c_list(); 348 if (t->left == NULL) 349 SYNTAXERR; 350 t->right = elsepart(); 351 return(t); 352} 353 354static struct op * 355elsepart() 356{ 357 register int c; 358 register struct op *t; 359 360 switch (c = yylex(0)) { 361 case ELSE: 362 if ((t = c_list()) == NULL) 363 SYNTAXERR; 364 return(t); 365 366 case ELIF: 367 t = newtp(); 368 t->type = TELIF; 369 t->left = c_list(); 370 t->right = thenpart(); 371 return(t); 372 373 default: 374 peeksym = c; 375 return((struct op *)NULL); 376 } 377} 378 379static struct op * 380caselist() 381{ 382 register struct op *t; 383 384 t = NULL; 385 while ((peeksym = yylex(CONTIN)) != ESAC) 386 t = list(t, casepart()); 387 return(t); 388} 389 390static struct op * 391casepart() 392{ 393 register struct op *t; 394 395 t = newtp(); 396 t->type = TPAT; 397 t->words = pattern(); 398 musthave(')', 0); 399 t->left = c_list(); 400 if ((peeksym = yylex(CONTIN)) != ESAC) 401 musthave(BREAK, CONTIN); 402 return(t); 403} 404 405static char ** 406pattern() 407{ 408 register int c, cf; 409 410 cf = CONTIN; 411 do { 412 musthave(WORD, cf); 413 word(yylval.cp); 414 cf = 0; 415 } while ((c = yylex(0)) == '|'); 416 peeksym = c; 417 word(NOWORD); 418 return(copyw()); 419} 420 421static char ** 422wordlist() 423{ 424 register int c; 425 426 if ((c = yylex(0)) != IN) { 427 peeksym = c; 428 return((char **)NULL); 429 } 430 startl = 0; 431 while ((c = yylex(0)) == WORD) 432 word(yylval.cp); 433 word(NOWORD); 434 peeksym = c; 435 return(copyw()); 436} 437 438/* 439 * supporting functions 440 */ 441static struct op * 442list(t1, t2) 443register struct op *t1, *t2; 444{ 445 if (t1 == NULL) 446 return(t2); 447 if (t2 == NULL) 448 return(t1); 449 return(block(TLIST, t1, t2, NOWORDS)); 450} 451 452static struct op * 453block(type, t1, t2, wp) 454int type; 455struct op *t1, *t2; 456char **wp; 457{ 458 register struct op *t; 459 460 t = newtp(); 461 t->type = type; 462 t->left = t1; 463 t->right = t2; 464 t->words = wp; 465 return(t); 466} 467 468struct res { 469 char *r_name; 470 int r_val; 471} restab[] = { 472 "for", FOR, 473 "case", CASE, 474 "esac", ESAC, 475 "while", WHILE, 476 "do", DO, 477 "done", DONE, 478 "if", IF, 479 "in", IN, 480 "then", THEN, 481 "else", ELSE, 482 "elif", ELIF, 483 "until", UNTIL, 484 "fi", FI, 485 486 ";;", BREAK, 487 "||", LOGOR, 488 "&&", LOGAND, 489 "{", '{', 490 "}", '}', 491 492 0, 493}; 494 495int 496rlookup(n) 497register char *n; 498{ 499 register struct res *rp; 500 501 for (rp = restab; rp->r_name; rp++) 502 if (strcmp(rp->r_name, n) == 0) 503 return(rp->r_val); 504 return(0); 505} 506 507static struct op * 508newtp() 509{ 510 register struct op *t; 511 512 t = (struct op *)tree(sizeof(*t)); 513 t->type = 0; 514 t->words = NULL; 515 t->ioact = NULL; 516 t->left = NULL; 517 t->right = NULL; 518 t->str = NULL; 519 return(t); 520} 521 522static struct op * 523namelist(t) 524register struct op *t; 525{ 526 if (iolist) { 527 iolist = addword((char *)NULL, iolist); 528 t->ioact = copyio(); 529 } else 530 t->ioact = NULL; 531 if (t->type != TCOM) { 532 if (t->type != TPAREN && t->ioact != NULL) { 533 t = block(TPAREN, t, NOBLOCK, NOWORDS); 534 t->ioact = t->left->ioact; 535 t->left->ioact = NULL; 536 } 537 return(t); 538 } 539 word(NOWORD); 540 t->words = copyw(); 541 return(t); 542} 543 544static char ** 545copyw() 546{ 547 register char **wd; 548 549 wd = getwords(wdlist); 550 wdlist = 0; 551 return(wd); 552} 553 554static void 555word(cp) 556char *cp; 557{ 558 wdlist = addword(cp, wdlist); 559} 560 561static struct ioword ** 562copyio() 563{ 564 register struct ioword **iop; 565 566 iop = (struct ioword **) getwords(iolist); 567 iolist = 0; 568 return(iop); 569} 570 571static struct ioword * 572io(u, f, cp) 573int u; 574int f; 575char *cp; 576{ 577 register struct ioword *iop; 578 579 iop = (struct ioword *) tree(sizeof(*iop)); 580 iop->io_unit = u; 581 iop->io_flag = f; 582 iop->io_name = cp; 583 iolist = addword((char *)iop, iolist); 584 return(iop); 585} 586 587static void 588zzerr() 589{ 590 yyerror("syntax error"); 591} 592 593void 594yyerror(s) 595char *s; 596{ 597 yynerrs++; 598 if (talking && e.iop <= iostack) { 599 multiline = 0; 600 while (eofc() == 0 && yylex(0) != '\n') 601 ; 602 } 603 err(s); 604 fail(); 605} 606 607static int 608yylex(cf) 609int cf; 610{ 611 register int c, c1; 612 int atstart; 613 614 if ((c = peeksym) > 0) { 615 peeksym = 0; 616 if (c == '\n') 617 startl = 1; 618 return(c); 619 } 620 nlseen = 0; 621 e.linep = line; 622 atstart = startl; 623 startl = 0; 624 yylval.i = 0; 625 626loop: 627 while ((c = getc(0)) == ' ' || c == '\t') 628 ; 629 switch (c) { 630 default: 631 if (any(c, "0123456789")) { 632 unget(c1 = getc(0)); 633 if (c1 == '<' || c1 == '>') { 634 iounit = c - '0'; 635 goto loop; 636 } 637 *e.linep++ = c; 638 c = c1; 639 } 640 break; 641 642 case '#': 643 while ((c = getc(0)) != 0 && c != '\n') 644 ; 645 unget(c); 646 goto loop; 647 648 case 0: 649 return(c); 650 651 case '$': 652 *e.linep++ = c; 653 if ((c = getc(0)) == '{') { 654 if ((c = collect(c, '}')) != '\0') 655 return(c); 656 goto pack; 657 } 658 break; 659 660 case '`': 661 case '\'': 662 case '"': 663 if ((c = collect(c, c)) != '\0') 664 return(c); 665 goto pack; 666 667 case '|': 668 case '&': 669 case ';': 670 if ((c1 = dual(c)) != '\0') { 671 startl = 1; 672 return(c1); 673 } 674 startl = 1; 675 return(c); 676 case '^': 677 startl = 1; 678 return('|'); 679 case '>': 680 case '<': 681 diag(c); 682 return(c); 683 684 case '\n': 685 nlseen++; 686 gethere(); 687 startl = 1; 688 if (multiline || cf & CONTIN) { 689 if (talking && e.iop <= iostack) 690 prs(cprompt->value); 691 if (cf & CONTIN) 692 goto loop; 693 } 694 return(c); 695 696 case '(': 697 case ')': 698 startl = 1; 699 return(c); 700 } 701 702 unget(c); 703 704pack: 705 while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) 706 if (e.linep >= elinep) 707 err("word too long"); 708 else 709 *e.linep++ = c; 710 unget(c); 711 if(any(c, "\"'`$")) 712 goto loop; 713 *e.linep++ = '\0'; 714 if (atstart && (c = rlookup(line))!=0) { 715 startl = 1; 716 return(c); 717 } 718 yylval.cp = strsave(line, areanum); 719 return(WORD); 720} 721 722int 723collect(c, c1) 724register c, c1; 725{ 726 char s[2]; 727 728 *e.linep++ = c; 729 while ((c = getc(c1)) != c1) { 730 if (c == 0) { 731 unget(c); 732 s[0] = c1; 733 s[1] = 0; 734 prs("no closing "); yyerror(s); 735 return(YYERRCODE); 736 } 737 if (talking && c == '\n' && e.iop <= iostack) 738 prs(cprompt->value); 739 *e.linep++ = c; 740 } 741 *e.linep++ = c; 742 return(0); 743} 744 745int 746dual(c) 747register c; 748{ 749 char s[3]; 750 register char *cp = s; 751 752 *cp++ = c; 753 *cp++ = getc(0); 754 *cp = 0; 755 if ((c = rlookup(s)) == 0) 756 unget(*--cp); 757 return(c); 758} 759 760static void 761diag(ec) 762register int ec; 763{ 764 register int c; 765 766 c = getc(0); 767 if (c == '>' || c == '<') { 768 if (c != ec) 769 zzerr(); 770 yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE; 771 c = getc(0); 772 } else 773 yylval.i = ec == '>'? IOWRITE: IOREAD; 774 if (c != '&' || yylval.i == IOHERE) 775 unget(c); 776 else 777 yylval.i |= IODUP; 778} 779 780static char * 781tree(size) 782unsigned size; 783{ 784 register char *t; 785 786 if ((t = getcell(size)) == NULL) { 787 prs("command line too complicated\n"); 788 fail(); 789 /* NOTREACHED */ 790 } 791 return(t); 792} 793 794/* VARARGS1 */ 795/* ARGSUSED */ 796void 797printf(s) /* yyparse calls it */ 798char *s; 799{ 800} 801 802