1 static char *sccsid = "@(#)lex.c 4.1 10/09/80"; 2 3 #include "sh.h" 4 5 /* 6 * C shell 7 */ 8 9 /* 10 * These lexical routines read input and form lists of words. 11 * There is some involved processing here, because of the complications 12 * of input buffering, and especially because of history substitution. 13 */ 14 15 char *word(); 16 17 /* 18 * Peekc is a peek characer for getC, peekread for readc. 19 * There is a subtlety here in many places... history routines 20 * will read ahead and then insert stuff into the input stream. 21 * If they push back a character then they must push it behind 22 * the text substituted by the history substitution. On the other 23 * hand in several places we need 2 peek characters. To make this 24 * all work, the history routines read with getC, and make use both 25 * of ungetC and unreadc. The key observation is that the state 26 * of getC at the call of a history reference is such that calls 27 * to getC from the history routines will always yield calls of 28 * readc, unless this peeking is involved. That is to say that during 29 * getexcl the variables lap, exclp, and exclnxt are all zero. 30 * 31 * Getdol invokes history substitution, hence the extra peek, peekd, 32 * which it can ungetD to be before history substitutions. 33 */ 34 char peekc, peekd; 35 char peekread; 36 37 char *exclp; /* (Tail of) current word from ! subst */ 38 struct wordent *exclnxt; /* The rest of the ! subst words */ 39 int exclc; /* Count of remainig words in ! subst */ 40 char *alvecp; /* "Globp" for alias resubstitution */ 41 42 /* 43 * Lex returns to its caller not only a wordlist (as a "var" parameter) 44 * but also whether a history substitution occurred. This is used in 45 * the main (process) routine to determine whether to echo, and also 46 * when called by the alias routine to determine whether to keep the 47 * argument list. 48 */ 49 bool hadhist; 50 51 #define ungetC(c) peekc = c 52 #define ungetD(c) peekd = c 53 54 lex(hp) 55 register struct wordent *hp; 56 { 57 register struct wordent *wdp; 58 int c; 59 60 lineloc = btell(); 61 hp->next = hp->prev = hp; 62 hp->word = ""; 63 alvecp = 0, hadhist = 0; 64 do 65 c = readc(0); 66 while (c == ' ' || c == '\t'); 67 if (c == HISTSUB && intty) 68 /* ^lef^rit from tty is short !:s^lef^rit */ 69 getexcl(c); 70 else 71 unreadc(c); 72 wdp = hp; 73 /* 74 * The following loop is written so that the links needed 75 * by freelex will be ready and rarin to go even if it is 76 * interrupted. 77 */ 78 do { 79 register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); 80 81 new->prev = wdp; 82 new->next = hp; 83 wdp->next = new; 84 wdp = new; 85 wdp->word = word(); 86 } while (wdp->word[0] != '\n'); 87 hp->prev = wdp; 88 return (hadhist); 89 } 90 91 prlex(sp0) 92 struct wordent *sp0; 93 { 94 register struct wordent *sp = sp0->next; 95 96 for (;;) { 97 printf("%s", sp->word); 98 sp = sp->next; 99 if (sp == sp0) 100 break; 101 printf(" "); 102 } 103 } 104 105 copylex(hp, fp) 106 register struct wordent *hp; 107 struct wordent *fp; 108 { 109 register struct wordent *wdp; 110 111 wdp = hp; 112 fp = fp->next; 113 do { 114 register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); 115 116 new->prev = wdp; 117 new->next = hp; 118 wdp->next = new; 119 wdp = new; 120 wdp->word = savestr(fp->word); 121 fp = fp->next; 122 } while (wdp->word[0] != '\n'); 123 hp->prev = wdp; 124 } 125 126 freelex(vp) 127 register struct wordent *vp; 128 { 129 register struct wordent *fp; 130 131 while (vp->next != vp) { 132 fp = vp->next; 133 vp->next = fp->next; 134 xfree(fp->word); 135 xfree((char *)fp); 136 } 137 vp->prev = vp; 138 } 139 140 char *WORDMETA = "# '`\"\t;&<>()|\n"; 141 142 char * 143 word() 144 { 145 register char c, c1; 146 register char *wp; 147 char wbuf[BUFSIZ]; 148 register bool dolflg; 149 register int i; 150 151 wp = wbuf; 152 i = BUFSIZ - 4; 153 loop: 154 c = getC(DOALL); 155 switch (c) { 156 157 case ' ': 158 case '\t': 159 goto loop; 160 161 case '`': 162 case '\'': 163 case '"': 164 *wp++ = c, --i, c1 = c; 165 dolflg = c == '"' ? DOALL : DOEXCL; 166 for (;;) { 167 c = getC(dolflg); 168 if (c == c1) 169 break; 170 if (c == '\n') { 171 seterrc("Unmatched ", c1); 172 ungetC(c); 173 goto ret; 174 } 175 if (c == '\\') { 176 c = getC(0); 177 if (c == HIST) 178 c |= QUOTE; 179 else { 180 if (c == '\n' && c1 != '`') 181 c |= QUOTE; 182 ungetC(c), c = '\\'; 183 } 184 } 185 if (--i <= 0) 186 goto toochars; 187 *wp++ = c; 188 } 189 *wp++ = c, --i; 190 goto pack; 191 192 case '&': 193 case '|': 194 case '<': 195 case '>': 196 *wp++ = c; 197 c1 = getC(DOALL); 198 if (c1 == c) 199 *wp++ = c1; 200 else 201 ungetC(c1); 202 goto ret; 203 204 case '#': 205 if (intty) 206 break; 207 if (wp != wbuf) { 208 ungetC(c); 209 goto ret; 210 } 211 c = 0; 212 do { 213 c1 = c; 214 c = getC(0); 215 } while (c != '\n'); 216 if (c1 == '\\') 217 goto loop; 218 /* fall into ... */ 219 220 case ';': 221 case '(': 222 case ')': 223 case '\n': 224 *wp++ = c; 225 goto ret; 226 227 casebksl: 228 case '\\': 229 c = getC(0); 230 if (c == '\n') { 231 if (onelflg == 1) 232 onelflg = 2; 233 goto loop; 234 } 235 if (c != HIST) 236 *wp++ = '\\', --i; 237 c |= QUOTE; 238 break; 239 } 240 ungetC(c); 241 pack: 242 for (;;) { 243 c = getC(DOALL); 244 if (c == '\\') { 245 c = getC(0); 246 if (c == '\n') { 247 if (onelflg == 1) 248 onelflg = 2; 249 goto ret; 250 } 251 if (c != HIST) 252 *wp++ = '\\', --i; 253 c |= QUOTE; 254 } 255 if (any(c, WORDMETA + intty)) { 256 ungetC(c); 257 if (any(c, "\"'`")) 258 goto loop; 259 goto ret; 260 } 261 if (--i <= 0) 262 goto toochars; 263 *wp++ = c; 264 } 265 toochars: 266 seterr("Word too long"); 267 wp = &wbuf[1]; 268 ret: 269 *wp = 0; 270 return (savestr(wbuf)); 271 } 272 273 getC(flag) 274 register int flag; 275 { 276 register char c; 277 278 top: 279 if (c = peekc) { 280 peekc = 0; 281 return (c); 282 } 283 if (lap) { 284 c = *lap++; 285 if (c == 0) { 286 lap = 0; 287 goto top; 288 } 289 if (any(c, WORDMETA + intty)) 290 c |= QUOTE; 291 return (c); 292 } 293 if (c = peekd) { 294 peekd = 0; 295 return (c); 296 } 297 if (exclp) { 298 if (c = *exclp++) 299 return (c); 300 if (exclnxt && --exclc >= 0) { 301 exclnxt = exclnxt->next; 302 setexclp(exclnxt->word); 303 return (' '); 304 } 305 exclp = 0; 306 exclnxt = 0; 307 } 308 if (exclnxt) { 309 exclnxt = exclnxt->next; 310 if (--exclc < 0) 311 exclnxt = 0; 312 else 313 setexclp(exclnxt->word); 314 goto top; 315 } 316 c = readc(0); 317 if (c == '$' && (flag & DODOL)) { 318 getdol(); 319 goto top; 320 } 321 if (c == HIST && (flag & DOEXCL)) { 322 getexcl(0); 323 goto top; 324 } 325 return (c); 326 } 327 328 getdol() 329 { 330 register char *np; 331 char name[40]; 332 register int c; 333 int sc; 334 bool special = 0; 335 336 np = name, *np++ = '$'; 337 c = sc = getC(DOEXCL); 338 if (any(c, "\t \n")) { 339 ungetD(c); 340 ungetC('$' | QUOTE); 341 return; 342 } 343 if (c == '{') 344 *np++ = c, c = getC(DOEXCL); 345 if (c == '#' || c == '?') 346 special++, *np++ = c, c = getC(DOEXCL); 347 *np++ = c; 348 switch (c) { 349 350 case '<': 351 case '$': 352 if (special) 353 goto vsyn; 354 goto ret; 355 356 case '\n': 357 ungetD(c); 358 np--; 359 goto vsyn; 360 361 case '*': 362 if (special) 363 goto vsyn; 364 goto ret; 365 366 default: 367 if (digit(c)) { 368 /* 369 * let $?0 pass for now 370 if (special) 371 goto vsyn; 372 */ 373 while (digit(c = getC(DOEXCL))) { 374 if (np < &name[sizeof name / 2]) 375 *np++ = c; 376 } 377 } else if (letter(c)) 378 while (letter(c = getC(DOEXCL))) { 379 if (np < &name[sizeof name / 2]) 380 *np++ = c; 381 } 382 else 383 goto vsyn; 384 } 385 if (c == '[') { 386 *np++ = c; 387 do { 388 c = getC(DOEXCL); 389 if (c == '\n') { 390 ungetD(c); 391 np--; 392 goto vsyn; 393 } 394 if (np >= &name[sizeof name - 8]) 395 goto vsyn; 396 *np++ = c; 397 } while (c != ']'); 398 c = getC(DOEXCL); 399 } 400 if (c == ':') { 401 *np++ = c, c = getC(DOEXCL); 402 if (c == 'g') 403 *np++ = c, c = getC(DOEXCL); 404 *np++ = c; 405 if (!any(c, "htrqxe")) 406 goto vsyn; 407 } else 408 ungetD(c); 409 if (sc == '{') { 410 c = getC(DOEXCL); 411 if (c != '}') { 412 ungetC(c); 413 goto vsyn; 414 } 415 *np++ = c; 416 } 417 ret: 418 *np = 0; 419 addla(name); 420 return; 421 422 vsyn: 423 seterr("Variable syntax"); 424 goto ret; 425 } 426 427 addla(cp) 428 char *cp; 429 { 430 char buf[BUFSIZ]; 431 432 if (lap != 0 && strlen(cp) + strlen(lap) >= sizeof (labuf) - 4) { 433 seterr("Expansion buf ovflo"); 434 return; 435 } 436 if (lap) 437 strcpy(buf, lap); 438 strcpy(labuf, cp); 439 if (lap) 440 strcat(labuf, buf); 441 lap = labuf; 442 } 443 444 char lhsb[32]; 445 char slhs[32]; 446 char rhsb[64]; 447 int quesarg; 448 449 getexcl(sc) 450 char sc; 451 { 452 register struct wordent *hp, *ip; 453 int left, right, dol; 454 register int c; 455 456 if (sc == 0) { 457 sc = getC(0); 458 if (sc != '{') { 459 ungetC(sc); 460 sc = 0; 461 } 462 } 463 quesarg = -1; 464 lastev = eventno; 465 hp = gethent(sc); 466 if (hp == 0) 467 return; 468 hadhist = 1; 469 dol = 0; 470 if (hp == alhistp) 471 for (ip = hp->next->next; ip != alhistt; ip = ip->next) 472 dol++; 473 else 474 for (ip = hp->next->next; ip != hp->prev; ip = ip->next) 475 dol++; 476 left = 0, right = dol; 477 if (sc == HISTSUB) { 478 ungetC('s'), unreadc(HISTSUB), c = ':'; 479 goto subst; 480 } 481 c = getC(0); 482 if (!any(c, ":^$*-%")) 483 goto subst; 484 left = right = -1; 485 if (c == ':') { 486 c = getC(0); 487 unreadc(c); 488 if (letter(c) || c == '&') { 489 c = ':'; 490 left = 0, right = dol; 491 goto subst; 492 } 493 } else 494 ungetC(c); 495 if (!getsel(&left, &right, dol)) 496 return; 497 c = getC(0); 498 if (c == '*') 499 ungetC(c), c = '-'; 500 if (c == '-') { 501 if (!getsel(&left, &right, dol)) 502 return; 503 c = getC(0); 504 } 505 subst: 506 exclc = right - left + 1; 507 while (--left >= 0) 508 hp = hp->next; 509 if (sc == HISTSUB || c == ':') { 510 do { 511 hp = getsub(hp); 512 c = getC(0); 513 } while (c == ':'); 514 } 515 unreadc(c); 516 if (sc == '{') { 517 c = getC(0); 518 if (c != '}') 519 seterr("Bad ! form"); 520 } 521 exclnxt = hp; 522 } 523 524 struct wordent * 525 getsub(en) 526 struct wordent *en; 527 { 528 register char *cp; 529 int delim; 530 register int c; 531 int sc; 532 bool global = 0; 533 char orhsb[sizeof rhsb]; 534 535 exclnxt = 0; 536 sc = c = getC(0); 537 if (c == 'g') 538 global++, c = getC(0); 539 switch (c) { 540 541 case 'p': 542 justpr++; 543 goto ret; 544 545 case 'x': 546 case 'q': 547 global++; 548 /* fall into ... */ 549 550 case 'h': 551 case 'r': 552 case 't': 553 case 'e': 554 break; 555 556 case '&': 557 if (slhs[0] == 0) { 558 seterr("No prev sub"); 559 goto ret; 560 } 561 strcpy(lhsb, slhs); 562 break; 563 564 /* 565 case '~': 566 if (lhsb[0] == 0) 567 goto badlhs; 568 break; 569 */ 570 571 case 's': 572 delim = getC(0); 573 if (letter(delim) || digit(delim) || any(delim, " \t\n")) { 574 unreadc(delim); 575 bads: 576 lhsb[0] = 0; 577 seterr("Bad substitute"); 578 goto ret; 579 } 580 cp = lhsb; 581 for (;;) { 582 c = getC(0); 583 if (c == '\n') { 584 unreadc(c); 585 goto bads; 586 } 587 if (c == delim) 588 break; 589 if (cp > &lhsb[sizeof lhsb - 2]) 590 goto bads; 591 if (c == '\\') { 592 c = getC(0); 593 if (c != delim && c != '\\') 594 *cp++ = '\\'; 595 } 596 *cp++ = c; 597 } 598 if (cp != lhsb) 599 *cp++ = 0; 600 else if (lhsb[0] == 0) { 601 /*badlhs:*/ 602 seterr("No prev lhs"); 603 goto ret; 604 } 605 cp = rhsb; 606 strcpy(orhsb, cp); 607 for (;;) { 608 c = getC(0); 609 if (c == '\n') { 610 unreadc(c); 611 break; 612 } 613 if (c == delim) 614 break; 615 /* 616 if (c == '~') { 617 if (&cp[strlen(orhsb)] > &rhsb[sizeof rhsb - 2]) 618 goto toorhs; 619 strcpy(cp, orhsb); 620 cp = strend(cp); 621 continue; 622 } 623 */ 624 if (cp > &rhsb[sizeof rhsb - 2]) { 625 /*toorhs:*/ 626 seterr("Rhs too long"); 627 goto ret; 628 } 629 if (c == '\\') { 630 c = getC(0); 631 if (c != delim /* && c != '~' */) 632 *cp++ = '\\'; 633 } 634 *cp++ = c; 635 } 636 *cp++ = 0; 637 break; 638 639 default: 640 if (c == '\n') 641 unreadc(c); 642 seterrc("Bad ! modifier: ", c); 643 goto ret; 644 } 645 strcpy(slhs, lhsb); 646 if (exclc) 647 en = dosub(sc, en, global); 648 ret: 649 return (en); 650 } 651 652 struct wordent * 653 dosub(sc, en, global) 654 int sc; 655 struct wordent *en; 656 bool global; 657 { 658 struct wordent lex; 659 bool didsub = 0; 660 struct wordent *hp = &lex; 661 register struct wordent *wdp; 662 register int i = exclc; 663 664 wdp = hp; 665 while (--i >= 0) { 666 register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); 667 668 new->prev = wdp; 669 new->next = hp; 670 wdp->next = new; 671 wdp = new; 672 en = en->next; 673 wdp->word = global || didsub == 0 ? 674 subword(en->word, sc, &didsub) : savestr(en->word); 675 } 676 if (didsub == 0) 677 seterr("Modifier failed"); 678 hp->prev = wdp; 679 return (&enthist(-1000, &lex, 0)->Hlex); 680 } 681 682 char * 683 subword(cp, type, adid) 684 char *cp; 685 int type; 686 bool *adid; 687 { 688 char wbuf[BUFSIZ]; 689 register char *wp, *mp, *np; 690 register int i; 691 692 switch (type) { 693 694 case 'r': 695 case 'h': 696 case 't': 697 case 'q': 698 case 'x': 699 wp = domod(cp, type); 700 if (wp == 0) 701 return (savestr(cp)); 702 *adid = 1; 703 return (wp); 704 705 default: 706 wp = wbuf; 707 i = BUFSIZ - 4; 708 for (mp = cp; *mp; mp++) 709 if (matchs(mp, lhsb)) { 710 for (np = cp; np < mp;) 711 *wp++ = *np++, --i; 712 for (np = rhsb; *np; np++) switch (*np) { 713 714 case '\\': 715 if (np[1] == '&') 716 np++; 717 /* fall into ... */ 718 719 default: 720 if (--i < 0) 721 goto ovflo; 722 *wp++ = *np; 723 continue; 724 725 case '&': 726 i -= strlen(lhsb); 727 if (i < 0) 728 goto ovflo; 729 *wp = 0; 730 strcat(wp, lhsb); 731 wp = strend(wp); 732 continue; 733 } 734 mp += strlen(lhsb); 735 i -= strlen(mp); 736 if (i < 0) { 737 ovflo: 738 seterr("Subst buf ovflo"); 739 return (""); 740 } 741 *wp = 0; 742 strcat(wp, mp); 743 *adid = 1; 744 return (savestr(wbuf)); 745 } 746 return (savestr(cp)); 747 } 748 } 749 750 char * 751 domod(cp, type) 752 char *cp; 753 int type; 754 { 755 register char *wp, *xp; 756 register int c; 757 758 switch (type) { 759 760 case 'x': 761 case 'q': 762 wp = savestr(cp); 763 for (xp = wp; c = *xp; xp++) 764 if ((c != ' ' && c != '\t') || type == 'q') 765 *xp |= QUOTE; 766 return (wp); 767 768 case 'h': 769 case 't': 770 if (!any('/', cp)) /* what if :h :t are both the same? */ 771 return (0); 772 wp = strend(cp); 773 while (*--wp != '/') 774 continue; 775 if (type == 'h') 776 take: 777 xp = savestr(cp), xp[wp - cp] = 0; 778 else 779 xp = savestr(wp + 1); 780 return (xp); 781 782 case 'e': 783 case 'r': 784 wp = strend(cp); 785 for (wp--; wp >= cp && *wp != '/'; wp--) 786 if (*wp == '.') { 787 if (type == 'e') 788 xp = savestr(wp + 1); 789 else 790 xp = savestr(cp), xp[wp - cp] = 0; 791 return (xp); 792 } 793 return (savestr(type == 'e' ? "" : cp)); 794 } 795 return (0); 796 } 797 798 matchs(str, pat) 799 register char *str, *pat; 800 { 801 802 while (*str && *pat && *str == *pat) 803 str++, pat++; 804 return (*pat == 0); 805 } 806 807 getsel(al, ar, dol) 808 register int *al, *ar; 809 int dol; 810 { 811 register int c = getC(0); 812 register int i; 813 bool first = *al < 0; 814 815 switch (c) { 816 817 case '%': 818 if (quesarg == -1) 819 goto bad; 820 if (*al < 0) 821 *al = quesarg; 822 *ar = quesarg; 823 break; 824 825 case '-': 826 if (*al < 0) { 827 *al = 0; 828 *ar = dol - 1; 829 unreadc(c); 830 } 831 return (1); 832 833 case '^': 834 if (*al < 0) 835 *al = 1; 836 *ar = 1; 837 break; 838 839 case '$': 840 if (*al < 0) 841 *al = dol; 842 *ar = dol; 843 break; 844 845 case '*': 846 if (*al < 0) 847 *al = 1; 848 *ar = dol; 849 if (*ar < *al) { 850 *ar = 0; 851 *al = 1; 852 return (1); 853 } 854 break; 855 856 default: 857 if (digit(c)) { 858 i = 0; 859 while (digit(c)) { 860 i = i * 10 + c - '0'; 861 c = getC(0); 862 } 863 if (i < 0) 864 i = dol + 1; 865 if (*al < 0) 866 *al = i; 867 *ar = i; 868 } else 869 if (*al < 0) 870 *al = 0, *ar = dol; 871 else 872 *ar = dol - 1; 873 unreadc(c); 874 break; 875 } 876 if (first) { 877 c = getC(0); 878 unreadc(c); 879 if (any(c, "-$*")) 880 return (1); 881 } 882 if (*al > *ar || *ar > dol) { 883 bad: 884 seterr("Bad ! arg selector"); 885 return (0); 886 } 887 return (1); 888 889 } 890 891 struct wordent * 892 gethent(sc) 893 int sc; 894 { 895 register struct Hist *hp; 896 register char *np; 897 register int c; 898 int event; 899 bool back = 0; 900 901 c = sc == HISTSUB ? HIST : getC(0); 902 if (c == HIST) { 903 if (alhistp) 904 return (alhistp); 905 event = eventno; 906 goto skip; 907 } 908 switch (c) { 909 910 case ':': 911 case '^': 912 case '$': 913 case '*': 914 case '%': 915 ungetC(c); 916 if (lastev == eventno && alhistp) 917 return (alhistp); 918 event = lastev; 919 break; 920 921 case '-': 922 back = 1; 923 c = getC(0); 924 goto number; 925 926 case '#': /* !# is command being typed in (mrh) */ 927 return(¶ml); 928 929 default: 930 if (any(c, "(=~")) { 931 unreadc(c); 932 ungetC(HIST); 933 return (0); 934 } 935 if (digit(c)) 936 goto number; 937 np = lhsb; 938 while (!any(c, ": \t\\\n}")) { 939 if (np < &lhsb[sizeof lhsb - 2]) 940 *np++ = c; 941 c = getC(0); 942 } 943 unreadc(c); 944 if (np == lhsb) { 945 ungetC(HIST); 946 return (0); 947 } 948 *np++ = 0; 949 hp = findev(lhsb, 0); 950 if (hp) 951 lastev = hp->Hnum; 952 return (&hp->Hlex); 953 954 case '?': 955 np = lhsb; 956 for (;;) { 957 c = getC(0); 958 if (c == '\n') { 959 unreadc(c); 960 break; 961 } 962 if (c == '?') 963 break; 964 if (np < &lhsb[sizeof lhsb - 2]) 965 *np++ = c; 966 } 967 if (np == lhsb) { 968 if (lhsb[0] == 0) { 969 seterr("No prev search"); 970 return (0); 971 } 972 } else 973 *np++ = 0; 974 hp = findev(lhsb, 1); 975 if (hp) 976 lastev = hp->Hnum; 977 return (&hp->Hlex); 978 979 number: 980 event = 0; 981 while (digit(c)) { 982 event = event * 10 + c - '0'; 983 c = getC(0); 984 } 985 if (back) 986 event = eventno + (alhistp == 0) - (event ? event : 0); 987 unreadc(c); 988 break; 989 } 990 skip: 991 for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 992 if (hp->Hnum == event) { 993 hp->Href = eventno; 994 lastev = hp->Hnum; 995 return (&hp->Hlex); 996 } 997 np = putn(event); 998 noev(np); 999 return (0); 1000 } 1001 1002 struct Hist * 1003 findev(cp, anyarg) 1004 char *cp; 1005 bool anyarg; 1006 { 1007 register struct Hist *hp; 1008 1009 for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 1010 if (matchev(hp, cp, anyarg)) 1011 return (hp); 1012 noev(cp); 1013 return (0); 1014 } 1015 1016 noev(cp) 1017 char *cp; 1018 { 1019 1020 seterr2(cp, ": Event not found"); 1021 } 1022 1023 matchev(hp, cp, anyarg) 1024 register struct Hist *hp; 1025 char *cp; 1026 bool anyarg; 1027 { 1028 register char *dp; 1029 struct wordent *lp = &hp->Hlex; 1030 int argno = 0; 1031 1032 for (;;) { 1033 lp = lp->next; 1034 if (lp->word[0] == '\n') 1035 return (0); 1036 for (dp = lp->word; *dp; dp++) { 1037 if (matchs(dp, cp)) { 1038 if (anyarg) 1039 quesarg = argno; 1040 return (1); 1041 } 1042 if (!anyarg) 1043 return (0); 1044 } 1045 argno++; 1046 } 1047 } 1048 1049 setexclp(cp) 1050 register char *cp; 1051 { 1052 1053 if (cp[0] == '\n') 1054 return; 1055 exclp = cp; 1056 } 1057 1058 unreadc(c) 1059 char c; 1060 { 1061 1062 peekread = c; 1063 } 1064 1065 readc(wanteof) 1066 bool wanteof; 1067 { 1068 register int c; 1069 static sincereal; 1070 1071 if (c = peekread) { 1072 peekread = 0; 1073 return (c); 1074 } 1075 top: 1076 if (alvecp) { 1077 if (c = *alvecp++) 1078 return (c); 1079 if (*alvec) { 1080 alvecp = *alvec++; 1081 return (' '); 1082 } 1083 } 1084 if (alvec) { 1085 if (alvecp = *alvec) { 1086 alvec++; 1087 goto top; 1088 } 1089 /* Infinite source! */ 1090 return ('\n'); 1091 } 1092 if (evalp) { 1093 if (c = *evalp++) 1094 return (c); 1095 if (*evalvec) { 1096 evalp = *evalvec++; 1097 return (' '); 1098 } 1099 evalp = 0; 1100 } 1101 if (evalvec) { 1102 if (evalvec == (char **)1) { 1103 doneinp = 1; 1104 reset(); 1105 } 1106 if (evalp = *evalvec) { 1107 evalvec++; 1108 goto top; 1109 } 1110 evalvec = (char **)1; 1111 return ('\n'); 1112 } 1113 do { 1114 if (arginp == (char *) 1 || onelflg == 1) { 1115 if (wanteof) 1116 return (-1); 1117 exitstat(); 1118 } 1119 if (arginp) { 1120 if ((c = *arginp++) == 0) { 1121 arginp = (char *) 1; 1122 return ('\n'); 1123 } 1124 return (c); 1125 } 1126 reread: 1127 c = bgetc(); 1128 if (c < 0) { 1129 #include <sgtty.h> 1130 struct sgttyb tty; 1131 1132 if (wanteof) 1133 return (-1); 1134 /* was isatty but raw with ignoreeof yields problems */ 1135 if (ioctl(SHIN, TIOCGETP, &tty)==0 && (tty.sg_flags & RAW) == 0) { 1136 short ctpgrp; 1137 1138 if (++sincereal > 25) 1139 goto oops; 1140 if (tpgrp != -1 && 1141 ioctl(FSHTTY, TIOCGPGRP, &ctpgrp) == 0 && 1142 tpgrp != ctpgrp) { 1143 ioctl(FSHTTY, TIOCSPGRP, &tpgrp); 1144 killpg(ctpgrp, SIGHUP); 1145 printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp); 1146 goto reread; 1147 } 1148 if (adrof("ignoreeof")) { 1149 if (loginsh) 1150 printf("\nUse \"logout\" to logout.\n"); 1151 else 1152 printf("\nUse \"exit\" to leave csh.\n"); 1153 reset(); 1154 } 1155 if (chkstop == 0) 1156 panystop(1); 1157 } 1158 oops: 1159 doneinp = 1; 1160 reset(); 1161 } 1162 sincereal = 0; 1163 if (c == '\n' && onelflg) 1164 onelflg--; 1165 } while (c == 0); 1166 return (c); 1167 } 1168 1169 bgetc() 1170 { 1171 register int buf, off, c; 1172 1173 #ifdef TELL 1174 if (cantell) { 1175 if (fseekp < fbobp || fseekp > feobp) { 1176 fbobp = feobp = fseekp; 1177 lseek(SHIN, fseekp, 0); 1178 } 1179 if (fseekp == feobp) { 1180 fbobp = feobp; 1181 do 1182 c = read(SHIN, fbuf[0], BUFSIZ); 1183 while (c < 0 && errno == EINTR); 1184 if (c <= 0) 1185 return (-1); 1186 feobp += c; 1187 } 1188 c = fbuf[0][fseekp - fbobp]; 1189 fseekp++; 1190 return (c); 1191 } 1192 #endif 1193 again: 1194 buf = (int) fseekp / BUFSIZ; 1195 if (buf >= fblocks) { 1196 register char **nfbuf = (char **) calloc(fblocks+2, sizeof (char **)); 1197 1198 if (fbuf) { 1199 blkcpy(nfbuf, fbuf); 1200 xfree((char *)fbuf); 1201 } 1202 fbuf = nfbuf; 1203 fbuf[fblocks] = calloc(BUFSIZ, sizeof (char)); 1204 fblocks++; 1205 goto again; 1206 } 1207 if (fseekp >= feobp) { 1208 buf = (int) feobp / BUFSIZ; 1209 off = (int) feobp % BUFSIZ; 1210 do 1211 c = read(SHIN, fbuf[buf] + off, BUFSIZ - off); 1212 while (c < 0 && errno == EINTR); 1213 if (c <= 0) 1214 return (-1); 1215 feobp += c; 1216 goto again; 1217 } 1218 c = fbuf[buf][(int) fseekp % BUFSIZ]; 1219 fseekp++; 1220 return (c); 1221 } 1222 1223 bfree() 1224 { 1225 register int sb, i; 1226 1227 #ifdef TELL 1228 if (cantell) 1229 return; 1230 #endif 1231 if (whyles) 1232 return; 1233 sb = (int) (fseekp - 1) / BUFSIZ; 1234 if (sb > 0) { 1235 for (i = 0; i < sb; i++) 1236 xfree(fbuf[i]); 1237 blkcpy(fbuf, &fbuf[sb]); 1238 fseekp -= BUFSIZ * sb; 1239 feobp -= BUFSIZ * sb; 1240 fblocks -= sb; 1241 } 1242 } 1243 1244 bseek(l) 1245 long l; 1246 { 1247 register struct whyle *wp; 1248 1249 fseekp = l; 1250 #ifdef TELL 1251 if (!cantell) { 1252 #endif 1253 if (!whyles) 1254 return; 1255 for (wp = whyles; wp->w_next; wp = wp->w_next) 1256 continue; 1257 if (wp->w_start > l) 1258 l = wp->w_start; 1259 #ifdef TELL 1260 } 1261 #endif 1262 } 1263 1264 /* any similarity to bell telephone is purely accidental */ 1265 long 1266 btell() 1267 { 1268 1269 return (fseekp); 1270 } 1271 1272 btoeof() 1273 { 1274 1275 lseek(SHIN, 0l, 2); 1276 fseekp = feobp; 1277 wfree(); 1278 bfree(); 1279 } 1280 1281 #ifdef TELL 1282 settell() 1283 { 1284 1285 cantell = 0; 1286 if (arginp || onelflg || intty) 1287 return; 1288 if (lseek(SHIN, 0l, 1) < 0 || errno == ESPIPE) 1289 return; 1290 fbuf = (char **) calloc(2, sizeof (char **)); 1291 fblocks = 1; 1292 fbuf[0] = calloc(BUFSIZ, sizeof (char)); 1293 fseekp = fbobp = feobp = tell(SHIN); 1294 cantell = 1; 1295 } 1296 #endif 1297