1: /* @(#)sh.lex.c 2.1 SCCS id keyword */ 2: /* Copyright (c) 1980 Regents of the University of California */ 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(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: /* 152: wbuf[0] = wbuf[250] = wbuf[500] = wbuf[750] = wbuf[1000]; 153: */ 154: wp = wbuf; 155: i = BUFSIZ - 4; 156: loop: 157: c = getC(DOALL); 158: switch (c) { 159: 160: case ' ': 161: case '\t': 162: goto loop; 163: 164: case '`': 165: case '\'': 166: case '"': 167: *wp++ = c, --i, c1 = c; 168: dolflg = c == '"' ? DOALL : DOEXCL; 169: for (;;) { 170: c = getC(dolflg); 171: if (c == c1) 172: break; 173: if (c == '\n') { 174: seterrc("Unmatched ", c1); 175: ungetC(c); 176: goto ret; 177: } 178: if (c == '\\') { 179: c = getC(0); 180: if (c == HIST) 181: c |= QUOTE; 182: else { 183: if (c == '\n' && c1 != '`') 184: c |= QUOTE; 185: ungetC(c), c = '\\'; 186: } 187: } 188: if (--i <= 0) 189: goto toochars; 190: *wp++ = c; 191: } 192: *wp++ = c, --i; 193: goto pack; 194: 195: case '&': 196: case '|': 197: case '<': 198: case '>': 199: *wp++ = c; 200: c1 = getC(DOALL); 201: if (c1 == c) 202: *wp++ = c1; 203: else 204: ungetC(c1); 205: goto ret; 206: 207: case '#': 208: if (intty) 209: break; 210: if (wp != wbuf) { 211: ungetC(c); 212: goto ret; 213: } 214: c = 0; 215: do { 216: c1 = c; 217: c = getC(0); 218: } while (c != '\n'); 219: if (c1 == '\\') 220: goto loop; 221: /* fall into ... */ 222: 223: case ';': 224: case '(': 225: case ')': 226: case '\n': 227: *wp++ = c; 228: goto ret; 229: 230: casebksl: 231: case '\\': 232: c = getC(0); 233: if (c == '\n') { 234: if (onelflg == 1) 235: onelflg = 2; 236: goto loop; 237: } 238: if (c != HIST) 239: *wp++ = '\\', --i; 240: c |= QUOTE; 241: break; 242: } 243: ungetC(c); 244: pack: 245: for (;;) { 246: c = getC(DOALL); 247: if (c == '\\') { 248: c = getC(0); 249: if (c == '\n') { 250: if (onelflg == 1) 251: onelflg = 2; 252: goto ret; 253: } 254: if (c != HIST) 255: *wp++ = '\\', --i; 256: c |= QUOTE; 257: } 258: if (any(c, WORDMETA + intty)) { 259: ungetC(c); 260: if (any(c, "\"'`")) 261: goto loop; 262: goto ret; 263: } 264: if (--i <= 0) 265: goto toochars; 266: *wp++ = c; 267: } 268: toochars: 269: seterr("Word too long"); 270: wp = &wbuf[1]; 271: ret: 272: *wp = 0; 273: return (savestr(wbuf)); 274: } 275: 276: getC(flag) 277: register int flag; 278: { 279: register char c; 280: 281: top: 282: if (c = peekc) { 283: peekc = 0; 284: return (c); 285: } 286: if (lap) { 287: c = *lap++; 288: if (c == 0) { 289: lap = 0; 290: goto top; 291: } 292: if (any(c, WORDMETA + intty)) 293: c |= QUOTE; 294: return (c); 295: } 296: if (c = peekd) { 297: peekd = 0; 298: return (c); 299: } 300: if (exclp) { 301: if (c = *exclp++) 302: return (c); 303: if (exclnxt && --exclc >= 0) { 304: exclnxt = exclnxt->next; 305: setexclp(exclnxt->word); 306: return (' '); 307: } 308: exclp = 0; 309: exclnxt = 0; 310: } 311: if (exclnxt) { 312: exclnxt = exclnxt->next; 313: if (--exclc < 0) 314: exclnxt = 0; 315: else 316: setexclp(exclnxt->word); 317: goto top; 318: } 319: c = readc(0); 320: if (c == '$' && (flag & DODOL)) { 321: getdol(); 322: goto top; 323: } 324: if (c == HIST && (flag & DOEXCL)) { 325: getexcl(0); 326: goto top; 327: } 328: return (c); 329: } 330: 331: getdol() 332: { 333: register char *np; 334: char name[40]; 335: register int c; 336: int sc; 337: bool special = 0; 338: 339: np = name, *np++ = '$'; 340: c = sc = getC(DOEXCL); 341: if (any(c, "\t \n")) { 342: ungetD(c); 343: ungetC('$' | QUOTE); 344: return; 345: } 346: if (c == '{') 347: *np++ = c, c = getC(DOEXCL); 348: if (c == '#' || c == '?') 349: special++, *np++ = c, c = getC(DOEXCL); 350: *np++ = c; 351: switch (c) { 352: 353: case '$': 354: if (special) 355: goto vsyn; 356: goto ret; 357: 358: case '\n': 359: ungetD(c); 360: np--; 361: goto vsyn; 362: 363: case '*': 364: if (special) 365: goto vsyn; 366: goto ret; 367: 368: default: 369: if (digit(c)) { 370: /* 371: * let $?0 pass for now 372: if (special) 373: goto vsyn; 374: */ 375: while (digit(c = getC(DOEXCL))) { 376: if (np < &name[sizeof name / 2]) 377: *np++ = c; 378: } 379: } else if (letter(c)) 380: while (letter(c = getC(DOEXCL))) { 381: if (np < &name[sizeof name / 2]) 382: *np++ = c; 383: } 384: else 385: goto vsyn; 386: } 387: if (c == '[') { 388: *np++ = c; 389: do { 390: c = getC(DOEXCL); 391: if (c == '\n') { 392: ungetD(c); 393: np--; 394: goto vsyn; 395: } 396: if (np >= &name[sizeof name - 8]) 397: goto vsyn; 398: *np++ = c; 399: } while (c != ']'); 400: c = getC(DOEXCL); 401: } 402: if (c == ':') { 403: *np++ = c, c = getC(DOEXCL); 404: if (c == 'g') 405: *np++ = c, c = getC(DOEXCL); 406: *np++ = c; 407: if (!any(c, "htrqx")) 408: goto vsyn; 409: } else 410: ungetD(c); 411: if (sc == '{') { 412: c = getC(DOEXCL); 413: if (c != '}') { 414: ungetC(c); 415: goto vsyn; 416: } 417: *np++ = c; 418: } 419: ret: 420: *np = 0; 421: addla(name); 422: return; 423: 424: vsyn: 425: seterr("Variable syntax"); 426: goto ret; 427: } 428: 429: addla(cp) 430: char *cp; 431: { 432: char buf[BUFSIZ]; 433: 434: if (lap != 0 && strlen(cp) + strlen(lap) >= sizeof (labuf) - 4) { 435: seterr("Expansion buf ovflo"); 436: return; 437: } 438: if (lap) 439: strcpy(buf, lap); 440: strcpy(labuf, cp); 441: if (lap) 442: strcat(labuf, buf); 443: lap = labuf; 444: } 445: 446: char lhsb[32]; 447: char slhs[32]; 448: char rhsb[64]; 449: int quesarg; 450: 451: getexcl(sc) 452: char sc; 453: { 454: register struct wordent *hp, *ip; 455: int left, right, dol; 456: register int c; 457: 458: if (sc == 0) { 459: sc = getC(0); 460: if (sc != '{') { 461: ungetC(sc); 462: sc = 0; 463: } 464: } 465: quesarg = -1; 466: lastev = eventno; 467: hp = gethent(sc); 468: if (hp == 0) 469: return; 470: hadhist = 1; 471: dol = 0; 472: if (hp == alhistp) 473: for (ip = hp->next->next; ip != alhistt; ip = ip->next) 474: dol++; 475: else 476: for (ip = hp->next->next; ip != hp->prev; ip = ip->next) 477: dol++; 478: left = 0, right = dol; 479: if (sc == HISTSUB) { 480: ungetC('s'), unreadc(HISTSUB), c = ':'; 481: goto subst; 482: } 483: c = getC(0); 484: if (!any(c, ":^$*-%")) 485: goto subst; 486: left = right = -1; 487: if (c == ':') { 488: c = getC(0); 489: unreadc(c); 490: if (letter(c) || c == '&') { 491: c = ':'; 492: left = 0, right = dol; 493: goto subst; 494: } 495: } else 496: ungetC(c); 497: if (!getsel(&left, &right, dol)) 498: return; 499: c = getC(0); 500: if (c == '*') 501: ungetC(c), c = '-'; 502: if (c == '-') { 503: if (!getsel(&left, &right, dol)) 504: return; 505: c = getC(0); 506: } 507: subst: 508: exclc = right - left + 1; 509: while (--left >= 0) 510: hp = hp->next; 511: if (sc == HISTSUB || c == ':') { 512: do { 513: hp = getsub(hp); 514: c = getC(0); 515: } while (c == ':'); 516: } 517: unreadc(c); 518: if (sc == '{') { 519: c = getC(0); 520: if (c != '}') 521: seterr("Bad ! form"); 522: } 523: exclnxt = hp; 524: } 525: 526: struct wordent * 527: getsub(en) 528: struct wordent *en; 529: { 530: register char *cp; 531: int delim; 532: register int c; 533: int sc; 534: bool global = 0; 535: char orhsb[sizeof rhsb]; 536: 537: exclnxt = 0; 538: sc = c = getC(0); 539: if (c == 'g') 540: global++, c = getC(0); 541: switch (c) { 542: 543: case 'p': 544: justpr++; 545: goto ret; 546: 547: case 'x': 548: case 'q': 549: global++; 550: /* fall into ... */ 551: 552: case 'h': 553: case 'r': 554: case 't': 555: break; 556: 557: case '&': 558: if (slhs[0] == 0) { 559: seterr("No prev sub"); 560: goto ret; 561: } 562: strcpy(lhsb, slhs); 563: break; 564: 565: /* 566: case '~': 567: if (lhsb[0] == 0) 568: goto badlhs; 569: break; 570: */ 571: 572: case 's': 573: delim = getC(0); 574: if (letter(delim) || digit(delim) || any(delim, " \t\n")) { 575: unreadc(delim); 576: bads: 577: lhsb[0] = 0; 578: seterr("Bad substitute"); 579: goto ret; 580: } 581: cp = lhsb; 582: for (;;) { 583: c = getC(0); 584: if (c == '\n') { 585: unreadc(c); 586: goto bads; 587: } 588: if (c == delim) 589: break; 590: if (cp > &lhsb[sizeof lhsb - 2]) 591: goto bads; 592: if (c == '\\') { 593: c = getC(0); 594: if (c != delim && c != '\\') 595: *cp++ = '\\'; 596: } 597: *cp++ = c; 598: } 599: if (cp != lhsb) 600: *cp++ = 0; 601: else if (lhsb[0] == 0) { 602: badlhs: 603: seterr("No prev lhs"); 604: goto ret; 605: } 606: cp = rhsb; 607: strcpy(orhsb, cp); 608: for (;;) { 609: c = getC(0); 610: if (c == '\n') { 611: unreadc(c); 612: break; 613: } 614: if (c == delim) 615: break; 616: /* 617: if (c == '~') { 618: if (&cp[strlen(orhsb)] > &rhsb[sizeof rhsb - 2]) 619: goto toorhs; 620: cp = strend(strcpy(cp, orhsb)); 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)) 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 'r': 783: wp = strend(cp); 784: for (wp--; wp >= cp && *wp != '.'; wp--) 785: if (*wp == '/') 786: return (0); 787: if (wp < cp) 788: return (0); 789: goto take; 790: } 791: return (0); 792: } 793: 794: matchs(str, pat) 795: register char *str, *pat; 796: { 797: 798: while (*str && *pat && *str == *pat) 799: str++, pat++; 800: return (*pat == 0); 801: } 802: 803: getsel(al, ar, dol) 804: register int *al, *ar; 805: int dol; 806: { 807: register int c = getC(0); 808: register int i; 809: bool first = *al < 0; 810: 811: switch (c) { 812: 813: case '%': 814: if (quesarg == -1) 815: goto bad; 816: if (*al < 0) 817: *al = quesarg; 818: *ar = quesarg; 819: break; 820: 821: case '-': 822: if (*al < 0) { 823: *al = 0; 824: *ar = dol - 1; 825: unreadc(c); 826: } 827: return (1); 828: 829: case '^': 830: if (*al < 0) 831: *al = 1; 832: *ar = 1; 833: break; 834: 835: case '$': 836: if (*al < 0) 837: *al = dol; 838: *ar = dol; 839: break; 840: 841: case '*': 842: if (*al < 0) 843: *al = 1; 844: *ar = dol; 845: if (*ar < *al) { 846: *ar = 0; 847: *al = 1; 848: return (1); 849: } 850: break; 851: 852: default: 853: if (digit(c)) { 854: i = 0; 855: while (digit(c)) { 856: i = i * 10 + c - '0'; 857: c = getC(0); 858: } 859: if (i < 0) 860: i = dol + 1; 861: if (*al < 0) 862: *al = i; 863: *ar = i; 864: } else 865: if (*al < 0) 866: *al = 0, *ar = dol; 867: else 868: *ar = dol - 1; 869: unreadc(c); 870: break; 871: } 872: if (first) { 873: c = getC(0); 874: unreadc(c); 875: if (any(c, "-$*")) 876: return (1); 877: } 878: if (*al > *ar || *ar > dol) { 879: bad: 880: seterr("Bad ! arg selector"); 881: return (0); 882: } 883: return (1); 884: 885: } 886: 887: struct wordent * 888: gethent(sc) 889: int sc; 890: { 891: register struct Hist *hp; 892: register char *np; 893: register int c; 894: int event; 895: bool back = 0; 896: 897: c = sc == HISTSUB ? HIST : getC(0); 898: if (c == HIST) { 899: if (alhistp) 900: return (alhistp); 901: event = eventno; 902: goto skip; 903: } 904: switch (c) { 905: 906: case ':': 907: case '^': 908: case '$': 909: case '*': 910: case '%': 911: ungetC(c); 912: if (lastev == eventno && alhistp) 913: return (alhistp); 914: event = lastev; 915: break; 916: 917: case '-': 918: back = 1; 919: c = getC(0); 920: goto number; 921: 922: case '#': /* !# is command being typed in (mrh) */ 923: return(¶ml); 924: 925: default: 926: if (any(c, "(=")) { 927: unreadc(c); 928: ungetC(HIST); 929: return (0); 930: } 931: if (digit(c)) 932: goto number; 933: np = lhsb; 934: while (!any(c, ": \t\\\n}")) { 935: if (np < &lhsb[sizeof lhsb - 2]) 936: *np++ = c; 937: c = getC(0); 938: } 939: unreadc(c); 940: if (np == lhsb) { 941: ungetC(HIST); 942: return (0); 943: } 944: *np++ = 0; 945: hp = findev(lhsb, 0); 946: if (hp) 947: lastev = hp->Hnum; 948: return (&hp->Hlex); 949: 950: case '?': 951: np = lhsb; 952: for (;;) { 953: c = getC(0); 954: if (c == '\n') { 955: unreadc(c); 956: break; 957: } 958: if (c == '?') 959: break; 960: if (np < &lhsb[sizeof lhsb - 2]) 961: *np++ = c; 962: } 963: if (np == lhsb) { 964: if (lhsb[0] == 0) { 965: seterr("No prev search"); 966: return (0); 967: } 968: } else 969: *np++ = 0; 970: hp = findev(lhsb, 1); 971: if (hp) 972: lastev = hp->Hnum; 973: return (&hp->Hlex); 974: 975: number: 976: event = 0; 977: while (digit(c)) { 978: event = event * 10 + c - '0'; 979: c = getC(0); 980: } 981: if (back) 982: event = eventno + (alhistp == 0) - (event ? event : 0); 983: unreadc(c); 984: break; 985: } 986: skip: 987: for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 988: if (hp->Hnum == event) { 989: hp->Href = eventno; 990: lastev = hp->Hnum; 991: return (&hp->Hlex); 992: } 993: np = putn(event); 994: noev(np); 995: return (0); 996: } 997: 998: struct Hist * 999: findev(cp, anyarg) 1000: char *cp; 1001: bool anyarg; 1002: { 1003: register struct Hist *hp; 1004: 1005: for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 1006: if (matchev(hp, cp, anyarg)) 1007: return (hp); 1008: noev(cp); 1009: return (0); 1010: } 1011: 1012: noev(cp) 1013: char *cp; 1014: { 1015: 1016: seterr2(cp, ": Event not found"); 1017: } 1018: 1019: matchev(hp, cp, anyarg) 1020: register struct Hist *hp; 1021: char *cp; 1022: bool anyarg; 1023: { 1024: register char *dp; 1025: struct wordent *lp = &hp->Hlex; 1026: int argno = 0; 1027: 1028: for (;;) { 1029: lp = lp->next; 1030: if (lp->word[0] == '\n') 1031: return (0); 1032: for (dp = lp->word; *dp; dp++) { 1033: if (matchs(dp, cp)) { 1034: if (anyarg) 1035: quesarg = argno; 1036: return (1); 1037: } 1038: if (!anyarg) 1039: return (0); 1040: } 1041: argno++; 1042: } 1043: } 1044: 1045: setexclp(cp) 1046: register char *cp; 1047: { 1048: 1049: if (cp[0] == '\n') 1050: return; 1051: exclp = cp; 1052: } 1053: 1054: unreadc(c) 1055: char c; 1056: { 1057: 1058: peekread = c; 1059: } 1060: 1061: readc(wanteof) 1062: bool wanteof; 1063: { 1064: register int c; 1065: 1066: if (c = peekread) { 1067: peekread = 0; 1068: return (c); 1069: } 1070: top: 1071: if (alvecp) { 1072: if (c = *alvecp++) 1073: return (c); 1074: if (*alvec) { 1075: alvecp = *alvec++; 1076: return (' '); 1077: } 1078: } 1079: if (alvec) { 1080: if (alvecp = *alvec) { 1081: alvec++; 1082: goto top; 1083: } 1084: /* Infinite source! */ 1085: return ('\n'); 1086: } 1087: do { 1088: if (arginp == (char *) 1 || onelflg == 1) { 1089: if (wanteof) 1090: return (-1); 1091: exitstat(); 1092: } 1093: if (arginp) { 1094: if ((c = *arginp++) == 0) { 1095: arginp = (char *) 1; 1096: return ('\n'); 1097: } 1098: return (c); 1099: } 1100: c = bgetc(); 1101: if (c < 0) { 1102: #include <sgtty.h> 1103: struct sgttyb tty; 1104: 1105: if (wanteof) 1106: return (-1); 1107: /* was isatty but raw with ignoreeof yields problems */ 1108: if (adrof("ignoreeof") && gtty(SHIN, &tty)==0 && (tty.sg_flags & RAW) == 0) { 1109: if (loginsh) 1110: printf("\nUse \"logout\" to logout.\n"); 1111: else 1112: printf("\nUse \"exit\" to leave csh.\n"); 1113: reset(); 1114: } 1115: doneinp = 1; 1116: reset(); 1117: } 1118: if (c == '\n' && onelflg) 1119: onelflg--; 1120: } while (c == 0); 1121: return (c); 1122: } 1123: 1124: bgetc() 1125: { 1126: register int buf, off, c; 1127: 1128: #ifdef TELL 1129: if (cantell) { 1130: if (fseekp < fbobp || fseekp > feobp) { 1131: fbobp = feobp = fseekp; 1132: lseek(SHIN, fseekp, 0); 1133: } 1134: if (fseekp == feobp) { 1135: fbobp = feobp; 1136: do 1137: c = read(SHIN, fbuf[0], BUFSIZ); 1138: while (c < 0 && errno == EINTR); 1139: if (c <= 0) 1140: return (-1); 1141: feobp += c; 1142: } 1143: c = fbuf[0][fseekp - fbobp]; 1144: fseekp++; 1145: return (c); 1146: } 1147: #endif 1148: again: 1149: buf = (int) fseekp / BUFSIZ; 1150: if (buf >= fblocks) { 1151: register char **nfbuf = (char **) calloc(fblocks+2, sizeof (char **)); 1152: 1153: if (fbuf) { 1154: blkcpy(nfbuf, fbuf); 1155: xfree(fbuf); 1156: } 1157: fbuf = nfbuf; 1158: fbuf[fblocks] = calloc(BUFSIZ, sizeof (char)); 1159: fblocks++; 1160: goto again; 1161: } 1162: if (fseekp >= feobp) { 1163: buf = (int) feobp / BUFSIZ; 1164: off = (int) feobp % BUFSIZ; 1165: do 1166: c = read(SHIN, fbuf[buf] + off, BUFSIZ - off); 1167: while (c < 0 && errno == EINTR); 1168: if (c <= 0) 1169: return (-1); 1170: feobp += c; 1171: goto again; 1172: } 1173: c = fbuf[buf][(int) fseekp % BUFSIZ]; 1174: fseekp++; 1175: return (c); 1176: } 1177: 1178: bfree() 1179: { 1180: register int sb, i; 1181: 1182: #ifdef TELL 1183: if (cantell) 1184: return; 1185: #endif 1186: if (whyles) 1187: return; 1188: sb = (int) (fseekp - 1) / BUFSIZ; 1189: if (sb > 0) { 1190: for (i = 0; i < sb; i++) 1191: xfree(fbuf[i]); 1192: blkcpy(fbuf, &fbuf[sb]); 1193: fseekp -= BUFSIZ * sb; 1194: feobp -= BUFSIZ * sb; 1195: fblocks -= sb; 1196: } 1197: } 1198: 1199: bseek(l) 1200: long l; 1201: { 1202: register struct whyle *wp; 1203: 1204: fseekp = l; 1205: #ifdef TELL 1206: if (!cantell) { 1207: #endif 1208: if (!whyles) 1209: return; 1210: for (wp = whyles; wp->w_next; wp = wp->w_next) 1211: continue; 1212: if (wp->w_start > l) 1213: l = wp->w_start; 1214: #ifdef TELL 1215: } 1216: #endif 1217: } 1218: 1219: /* any similarity to bell telephone is purely accidental */ 1220: long 1221: btell() 1222: { 1223: 1224: return (fseekp); 1225: } 1226: 1227: btoeof() 1228: { 1229: 1230: lseek(SHIN, 0l, 2); 1231: fseekp = feobp; 1232: wfree(); 1233: bfree(); 1234: } 1235: 1236: #ifdef TELL 1237: settell() 1238: { 1239: 1240: cantell = 0; 1241: if (arginp || onelflg || intty) 1242: return; 1243: if (lseek(SHIN, 0l, 1) < 0 || errno == ESPIPE) 1244: return; 1245: fbuf = (char **) calloc(2, sizeof (char **)); 1246: fblocks = 1; 1247: fbuf[0] = calloc(BUFSIZ, sizeof (char)); 1248: fseekp = fbobp = feobp = tell(SHIN); 1249: cantell = 1; 1250: } 1251: #endif