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(&paraml);
 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

Defined functions

addla defined in line 427; used 5 times
bfree defined in line 1223; used 1 times
bgetc defined in line 1169; used 1 times
bseek defined in line 1244; used 5 times
btell defined in line 1265; used 8 times
btoeof defined in line 1272; used 2 times
copylex defined in line 105; used 1 times
domod defined in line 750; used 3 times
dosub defined in line 652; used 2 times
findev defined in line 1002; used 3 times
getC defined in line 273; used 40 times
getdol defined in line 328; used 1 times
getexcl defined in line 449; used 2 times
gethent defined in line 891; used 2 times
getsel defined in line 807; used 2 times
getsub defined in line 524; used 2 times
lex defined in line 54; used 6 times
matchev defined in line 1023; used 1 times
matchs defined in line 798; used 2 times
noev defined in line 1016; used 2 times
prlex defined in line 91; used 2 times
readc defined in line 1065; used 8 times
setexclp defined in line 1049; used 2 times
settell defined in line 1282; used 2 times
subword defined in line 682; used 2 times
unreadc defined in line 1058; used 17 times
word defined in line 142; used 17 times

Defined variables

WORDMETA defined in line 140; used 2 times
alvecp defined in line 40; used 5 times
exclc defined in line 39; used 5 times
exclnxt defined in line 38; used 12 times
exclp defined in line 37; used 4 times
hadhist defined in line 49; used 3 times
lhsb defined in line 444; used 23 times
peekc defined in line 34; used 3 times
peekd defined in line 34; used 3 times
peekread defined in line 35; used 3 times
quesarg defined in line 447; used 5 times
rhsb defined in line 446; used 5 times
sccsid defined in line 1; never used
slhs defined in line 445; used 3 times

Defined macros

ungetC defined in line 51; used 15 times
ungetD defined in line 52; used 4 times
Last modified: 1980-10-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3238
Valid CSS Valid XHTML 1.0 Strict