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