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