|
|
1.1 ! root 1: static char *sccsid = "@(#)sh.lex.c 4.1 10/9/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.