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

Defined functions

addla defined in line 429; used 5 times
bfree defined in line 1178; used 1 times
bgetc defined in line 1124; used 1 times
bseek defined in line 1199; used 5 times
btell defined in line 1220; used 7 times
btoeof defined in line 1227; 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 998; used 3 times
getC defined in line 276; used 40 times
getdol defined in line 331; used 1 times
getexcl defined in line 451; used 2 times
gethent defined in line 887; used 2 times
getsel defined in line 803; used 2 times
getsub defined in line 526; used 2 times
lex defined in line 54; used 6 times
matchev defined in line 1019; used 1 times
matchs defined in line 794; used 2 times
noev defined in line 1012; used 2 times
readc defined in line 1061; used 7 times
setexclp defined in line 1045; used 2 times
settell defined in line 1237; used 2 times
subword defined in line 682; used 2 times
unreadc defined in line 1054; 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 446; 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 449; used 5 times
rhsb defined in line 448; used 5 times
slhs defined in line 447; used 3 times

Defined macros

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