1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.lex.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * sh.lex.c: Lexical analysis into tokens
   4:  */
   5: /*-
   6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
   7:  * All rights reserved.
   8:  *
   9:  * Redistribution and use in source and binary forms, with or without
  10:  * modification, are permitted provided that the following conditions
  11:  * are met:
  12:  * 1. Redistributions of source code must retain the above copyright
  13:  *    notice, this list of conditions and the following disclaimer.
  14:  * 2. Redistributions in binary form must reproduce the above copyright
  15:  *    notice, this list of conditions and the following disclaimer in the
  16:  *    documentation and/or other materials provided with the distribution.
  17:  * 3. All advertising materials mentioning features or use of this software
  18:  *    must display the following acknowledgement:
  19:  *	This product includes software developed by the University of
  20:  *	California, Berkeley and its contributors.
  21:  * 4. Neither the name of the University nor the names of its contributors
  22:  *    may be used to endorse or promote products derived from this software
  23:  *    without specific prior written permission.
  24:  *
  25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35:  * SUCH DAMAGE.
  36:  */
  37: #include "config.h"
  38: #if !defined(lint) && !defined(pdp11)
  39: static char *rcsid()
  40:     { return "$Id: sh.lex.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  41: #endif
  42: 
  43: #include "sh.h"
  44: #include "ed.h"
  45: 
  46: /*
  47:  * C shell
  48:  */
  49: 
  50: /*
  51:  * These lexical routines read input and form lists of words.
  52:  * There is some involved processing here, because of the complications
  53:  * of input buffering, and especially because of history substitution.
  54:  */
  55: static  Char        *word       __P((void));
  56: static  int      getC1      __P((int));
  57: static  void         getdol     __P((void));
  58: static  void         getexcl    __P((int));
  59: static  struct Hist     *findev     __P((Char *, bool));
  60: static  void         setexclp   __P((Char *));
  61: static  int      bgetc      __P((void));
  62: static  void         bfree      __P((void));
  63: static  struct wordent  *gethent    __P((int));
  64: static  int      matchs     __P((Char *, Char *));
  65: static  int      getsel     __P((int *, int *, int));
  66: static  struct wordent  *getsub     __P((struct wordent *));
  67: static  Char        *subword    __P((Char *, int, bool *));
  68: static  struct wordent  *dosub      __P((int, struct wordent *, bool));
  69: 
  70: /*
  71:  * Peekc is a peek character for getC, peekread for readc.
  72:  * There is a subtlety here in many places... history routines
  73:  * will read ahead and then insert stuff into the input stream.
  74:  * If they push back a character then they must push it behind
  75:  * the text substituted by the history substitution.  On the other
  76:  * hand in several places we need 2 peek characters.  To make this
  77:  * all work, the history routines read with getC, and make use both
  78:  * of ungetC and unreadc.  The key observation is that the state
  79:  * of getC at the call of a history reference is such that calls
  80:  * to getC from the history routines will always yield calls of
  81:  * readc, unless this peeking is involved.  That is to say that during
  82:  * getexcl the variables lap, exclp, and exclnxt are all zero.
  83:  *
  84:  * Getdol invokes history substitution, hence the extra peek, peekd,
  85:  * which it can ungetD to be before history substitutions.
  86:  */
  87: static Char peekc = 0, peekd = 0;
  88: static Char peekread = 0;
  89: 
  90: /* (Tail of) current word from ! subst */
  91: static Char *exclp = NULL;
  92: 
  93: /* The rest of the ! subst words */
  94: static struct wordent *exclnxt = NULL;
  95: 
  96: /* Count of remaining words in ! subst */
  97: static int exclc = 0;
  98: 
  99: /* "Globp" for alias resubstitution */
 100: static Char *alvecp = NULL;
 101: 
 102: /*
 103:  * Labuf implements a general buffer for lookahead during lexical operations.
 104:  * Text which is to be placed in the input stream can be stuck here.
 105:  * We stick parsed ahead $ constructs during initial input,
 106:  * process id's from `$$', and modified variable values (from qualifiers
 107:  * during expansion in sh.dol.c) here.
 108:  */
 109: static Char labuf[BUFSIZ];
 110: 
 111: /*
 112:  * Lex returns to its caller not only a wordlist (as a "var" parameter)
 113:  * but also whether a history substitution occurred.  This is used in
 114:  * the main (process) routine to determine whether to echo, and also
 115:  * when called by the alias routine to determine whether to keep the
 116:  * argument list.
 117:  */
 118: static bool hadhist = 0;
 119: 
 120: /*
 121:  * Avoid alias expansion recursion via \!#
 122:  */
 123: int     hleft;
 124: 
 125: Char    histline[BUFSIZ + 2];   /* last line input */
 126: 
 127:  /* The +2 is to fool hp's optimizer */
 128: bool    histvalid = 0;      /* is histline valid */
 129: static Char *hist_p_line = NULL;    /* current pointer into histline */
 130: 
 131: static Char getCtmp;
 132: 
 133: #define getC(f)     ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f))
 134: #define ungetC(c)   peekc = c
 135: #define ungetD(c)   peekd = c
 136: 
 137: int
 138: lex(hp)
 139:     register struct wordent *hp;
 140: {
 141:     register struct wordent *wdp;
 142:     int     c;
 143: 
 144:     histvalid = 0;
 145:     hist_p_line = histline;
 146:     *hist_p_line = '\0';
 147: 
 148:     lineloc = btell();
 149:     hp->next = hp->prev = hp;
 150:     hp->word = STRNULL;
 151:     alvecp = 0, hadhist = 0;
 152:     do
 153:     c = readc(0);
 154:     while (c == ' ' || c == '\t');
 155:     if (c == HISTSUB && intty)
 156:     /* ^lef^rit	from tty is short !:s^lef^rit */
 157:     getexcl(c);
 158:     else
 159:     unreadc(c);
 160:     wdp = hp;
 161:     /*
 162:      * The following loop is written so that the links needed by freelex will
 163:      * be ready and rarin to go even if it is interrupted.
 164:      */
 165:     do {
 166:     register struct wordent *new;
 167: 
 168:     new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));
 169:     new->word = 0;
 170:     new->prev = wdp;
 171:     new->next = hp;
 172:     wdp->next = new;
 173:     wdp = new;
 174:     wdp->word = word();
 175:     } while (wdp->word[0] != '\n');
 176:     hp->prev = wdp;
 177:     if (hist_p_line < histline + BUFSIZ) {
 178:     *hist_p_line = '\0';
 179:     if (hist_p_line > histline && hist_p_line[-1] == '\n')
 180:         hist_p_line[-1] = '\0';
 181:     histvalid = 1;
 182:     }
 183:     else {
 184:     histline[BUFSIZ - 1] = '\0';
 185:     }
 186:     return (hadhist);
 187: }
 188: 
 189: void
 190: prlex(sp0)
 191:     struct wordent *sp0;
 192: {
 193:     register struct wordent *sp = sp0->next;
 194: 
 195:     for (;;) {
 196:     xprintf("%s", short2str(sp->word));
 197:     sp = sp->next;
 198:     if (sp == sp0)
 199:         break;
 200:     if (sp->word[0] != '\n')
 201:         xputchar(' ');
 202:     }
 203: }
 204: 
 205: void
 206: copylex(hp, fp)
 207:     register struct wordent *hp;
 208:     register struct wordent *fp;
 209: {
 210:     register struct wordent *wdp;
 211: 
 212:     wdp = hp;
 213:     fp = fp->next;
 214:     do {
 215:     register struct wordent *new;
 216: 
 217:     new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));
 218:     new->prev = wdp;
 219:     new->next = hp;
 220:     wdp->next = new;
 221:     wdp = new;
 222:     wdp->word = Strsave(fp->word);
 223:     fp = fp->next;
 224:     } while (wdp->word[0] != '\n');
 225:     hp->prev = wdp;
 226: }
 227: 
 228: void
 229: freelex(vp)
 230:     register struct wordent *vp;
 231: {
 232:     register struct wordent *fp;
 233: 
 234:     while (vp->next != vp) {
 235:     fp = vp->next;
 236:     vp->next = fp->next;
 237:     xfree((ptr_t) fp->word);
 238:     xfree((ptr_t) fp);
 239:     }
 240:     vp->prev = vp;
 241: }
 242: 
 243: static Char *
 244: word()
 245: {
 246:     register Char c, c1;
 247:     register Char *wp;
 248:     Char    wbuf[BUFSIZ];
 249:     register bool dolflg;
 250:     register int i;
 251: 
 252:     wp = wbuf;
 253:     i = BUFSIZ - 4;
 254: loop:
 255:     while ((c = getC(DOALL)) == ' ' || c == '\t');
 256:     if (cmap(c, _META | _ESC))
 257:     switch (c) {
 258:     case '&':
 259:     case '|':
 260:     case '<':
 261:     case '>':
 262:         *wp++ = c;
 263:         c1 = getC(DOALL);
 264:         if (c1 == c)
 265:         *wp++ = c1;
 266:         else
 267:         ungetC(c1);
 268:         goto ret;
 269: 
 270:     case '#':
 271:         if (intty)
 272:         break;
 273:         c = 0;
 274:         do {
 275:         c1 = c;
 276:         c = getC(0);
 277:         } while (c != '\n');
 278:         if (c1 == '\\')
 279:         goto loop;
 280:         /* fall into ... */
 281: 
 282:     case ';':
 283:     case '(':
 284:     case ')':
 285:     case '\n':
 286:         *wp++ = c;
 287:         goto ret;
 288: 
 289:     case '\\':
 290:         c = getC(0);
 291:         if (c == '\n') {
 292:         if (onelflg == 1)
 293:             onelflg = 2;
 294:         goto loop;
 295:         }
 296:         if (c != HIST)
 297:         *wp++ = '\\', --i;
 298:         c |= QUOTE;
 299:     }
 300:     c1 = 0;
 301:     dolflg = DOALL;
 302:     for (;;) {
 303:     if (c1) {
 304:         if (c == c1) {
 305:         c1 = 0;
 306:         dolflg = DOALL;
 307:         }
 308:         else if (c == '\\') {
 309:         c = getC(0);
 310: /*
 311:  * PWP: this is dumb, but how all of the other shells work.  If \ quotes
 312:  * a character OUTSIDE of a set of ''s, why shouldn't it quote EVERY
 313:  * following character INSIDE a set of ''s.
 314:  *
 315:  * Actually, all I really want to be able to say is 'foo\'bar' --> foo'bar
 316:  */
 317:         if (c == HIST)
 318:             c |= QUOTE;
 319:         else {
 320:             if (bslash_quote &&
 321:             ((c == '\'') || (c == '"') ||
 322:              (c == '\\'))) {
 323:             c |= QUOTE;
 324:             }
 325:             else {
 326:             if (c == '\n')
 327:                 /*
 328: 			     * if (c1 == '`') c = ' '; else
 329: 			     */
 330:                 c |= QUOTE;
 331:             ungetC(c);
 332:             c = '\\';
 333:             }
 334:         }
 335:         }
 336:         else if (c == '\n') {
 337:         seterror(ERR_UNMATCHED, c1);
 338:         ungetC(c);
 339:         break;
 340:         }
 341:     }
 342:     else if (cmap(c, _META | _Q | _Q1 | _ESC)) {
 343:         if (c == '\\') {
 344:         c = getC(0);
 345:         if (c == '\n') {
 346:             if (onelflg == 1)
 347:             onelflg = 2;
 348:             break;
 349:         }
 350:         if (c != HIST)
 351:             *wp++ = '\\', --i;
 352:         c |= QUOTE;
 353:         }
 354:         else if (cmap(c, _Q | _Q1)) {   /* '"` */
 355:         c1 = c;
 356:         dolflg = c == '"' ? DOALL : DOEXCL;
 357:         }
 358:         else if (c != '#' || !intty) {
 359:         ungetC(c);
 360:         break;
 361:         }
 362:     }
 363:     if (--i > 0) {
 364:         *wp++ = c;
 365:         c = getC(dolflg);
 366:     }
 367:     else {
 368:         seterror(ERR_WTOOLONG);
 369:         wp = &wbuf[1];
 370:         break;
 371:     }
 372:     }
 373: ret:
 374:     *wp = 0;
 375:     return (Strsave(wbuf));
 376: }
 377: 
 378: static int
 379: getC1(flag)
 380:     register int flag;
 381: {
 382:     register Char c;
 383: 
 384:     while (1) {
 385:     if (c = peekc) {
 386:         peekc = 0;
 387:         return (c);
 388:     }
 389:     if (lap) {
 390:         if ((c = *lap++) == 0)
 391:         lap = 0;
 392:         else {
 393:         if (cmap(c, _META | _Q | _Q1))
 394:             c |= QUOTE;
 395:         return (c);
 396:         }
 397:     }
 398:     if (c = peekd) {
 399:         peekd = 0;
 400:         return (c);
 401:     }
 402:     if (exclp) {
 403:         if (c = *exclp++)
 404:         return (c);
 405:         if (exclnxt && --exclc >= 0) {
 406:         exclnxt = exclnxt->next;
 407:         setexclp(exclnxt->word);
 408:         return (' ');
 409:         }
 410:         exclp = 0;
 411:         exclnxt = 0;
 412:     }
 413:     if (exclnxt) {
 414:         exclnxt = exclnxt->next;
 415:         if (--exclc < 0)
 416:         exclnxt = 0;
 417:         else
 418:         setexclp(exclnxt->word);
 419:         continue;
 420:     }
 421:     c = readc(0);
 422:     if (c == '$' && (flag & DODOL)) {
 423:         getdol();
 424:         continue;
 425:     }
 426:     if (c == HIST && (flag & DOEXCL)) {
 427:         getexcl(0);
 428:         continue;
 429:     }
 430:     break;
 431:     }
 432:     return (c);
 433: }
 434: 
 435: static void
 436: getdol()
 437: {
 438:     register Char *np, *ep;
 439:     Char    name[4 * MAXVARLEN + 1];
 440:     register int c;
 441:     int     sc;
 442:     bool    special = 0, toolong;
 443: 
 444:     np = name, *np++ = '$';
 445:     c = sc = getC(DOEXCL);
 446:     if (any("\t \n", c)) {
 447:     ungetD(c);
 448:     ungetC('$' | QUOTE);
 449:     return;
 450:     }
 451:     if (c == '{')
 452:     *np++ = c, c = getC(DOEXCL);
 453:     if (c == '#' || c == '?')
 454:     special++, *np++ = c, c = getC(DOEXCL);
 455:     *np++ = c;
 456:     switch (c) {
 457: 
 458:     case '<':
 459:     case '$':
 460:     if (special)
 461:         seterror(ERR_SPDOLLT);
 462:     *np = 0;
 463:     addla(name);
 464:     return;
 465: 
 466:     case '\n':
 467:     ungetD(c);
 468:     np--;
 469:     seterror(ERR_NEWLINE);
 470:     *np = 0;
 471:     addla(name);
 472:     return;
 473: 
 474:     case '*':
 475:     if (special)
 476:         seterror(ERR_SPSTAR);
 477:     *np = 0;
 478:     addla(name);
 479:     return;
 480: 
 481:     default:
 482:     toolong = 0;
 483:     if (Isdigit(c)) {
 484: #ifdef notdef
 485:         /* let $?0 pass for now */
 486:         if (special) {
 487:         seterror(ERR_DIGIT);
 488:         *np = 0;
 489:         addla(name);
 490:         return;
 491:         }
 492: #endif
 493:         /* we know that np < &name[4] */
 494:         ep = &np[MAXVARLEN];
 495:         while (c = getC(DOEXCL)) {
 496:         if (!Isdigit(c))
 497:             break;
 498:         if (np < ep)
 499:             *np++ = c;
 500:         else
 501:             toolong = 1;
 502:         }
 503:     }
 504:     else if (letter(c)) {
 505:         /* we know that np < &name[4] */
 506:         ep = &np[MAXVARLEN];
 507:         toolong = 0;
 508:         while (c = getC(DOEXCL)) {
 509:         /* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */
 510:         if (!letter(c) && !Isdigit(c))
 511:             break;
 512:         if (np < ep)
 513:             *np++ = c;
 514:         else
 515:             toolong = 1;
 516:         }
 517:     }
 518:     else {
 519:         *np = 0;
 520:         seterror(ERR_VARILL);
 521:         addla(name);
 522:         return;
 523:     }
 524:     if (toolong) {
 525:         seterror(ERR_VARTOOLONG);
 526:         *np = 0;
 527:         addla(name);
 528:         return;
 529:     }
 530:     break;
 531:     }
 532:     if (c == '[') {
 533:     *np++ = c;
 534:     /*
 535: 	 * Name up to here is a max of MAXVARLEN + 8.
 536: 	 */
 537:     ep = &np[2 * MAXVARLEN + 8];
 538:     do {
 539:         /*
 540: 	     * Michael Greim: Allow $ expansion to take place in selector
 541: 	     * expressions. (limits the number of characters returned)
 542: 	     */
 543:         c = getC(DOEXCL | DODOL);
 544:         if (c == '\n') {
 545:         ungetD(c);
 546:         np--;
 547:         seterror(ERR_NLINDEX);
 548:         *np = 0;
 549:         addla(name);
 550:         return;
 551:         }
 552:         if (np < ep)
 553:         *np++ = c;
 554:     } while (c != ']');
 555:     *np = '\0';
 556:     if (np >= ep) {
 557:         seterror(ERR_SELOVFL);
 558:         addla(name);
 559:         return;
 560:     }
 561:     c = getC(DOEXCL);
 562:     }
 563:     /*
 564:      * Name up to here is a max of 2 * MAXVARLEN + 8.
 565:      */
 566:     if (c == ':') {
 567:     /*
 568: 	 * if the :g modifier is followed by a newline, then error right away!
 569: 	 * -strike
 570: 	 */
 571: 
 572:     int     gmodflag = 0;
 573: 
 574:     *np++ = c, c = getC(DOEXCL);
 575:     if (c == 'g')
 576:         gmodflag++, *np++ = c, c = getC(DOEXCL);
 577:     *np++ = c;
 578:     if (!any("htrqxe", c)) {
 579:         if (gmodflag && c == '\n')
 580:         stderror(ERR_VARSYN);   /* strike */
 581:         seterror(ERR_VARMOD, c);
 582:         *np = 0;
 583:         addla(name);
 584:         return;
 585:     }
 586:     }
 587:     else
 588:     ungetD(c);
 589:     if (sc == '{') {
 590:     c = getC(DOEXCL);
 591:     if (c != '}') {
 592:         ungetD(c);
 593:         seterror(ERR_MISSING, '}');
 594:         *np = 0;
 595:         addla(name);
 596:         return;
 597:     }
 598:     *np++ = c;
 599:     }
 600:     *np = 0;
 601:     addla(name);
 602:     return;
 603: }
 604: 
 605: void
 606: addla(cp)
 607:     Char   *cp;
 608: {
 609:     Char    buf[BUFSIZ];
 610: 
 611:     if (Strlen(cp) + (lap ? Strlen(lap) : 0) >=
 612:     (sizeof(labuf) - 4) / sizeof(Char)) {
 613:     seterror(ERR_EXPOVFL);
 614:     return;
 615:     }
 616:     if (lap)
 617:     (void) Strcpy(buf, lap);
 618:     (void) Strcpy(labuf, cp);
 619:     if (lap)
 620:     (void) Strcat(labuf, buf);
 621:     lap = labuf;
 622: }
 623: 
 624: static Char lhsb[32];
 625: static Char slhs[32];
 626: static Char rhsb[64];
 627: static int quesarg;
 628: 
 629: static void
 630: getexcl(sc)
 631:     Char    sc;
 632: {
 633:     register struct wordent *hp, *ip;
 634:     int     left, right, dol;
 635:     register int c;
 636: 
 637:     if (sc == 0) {
 638:     sc = getC(0);
 639:     if (sc != '{') {
 640:         ungetC(sc);
 641:         sc = 0;
 642:     }
 643:     }
 644:     quesarg = -1;
 645:     lastev = eventno;
 646:     hp = gethent(sc);
 647:     if (hp == 0)
 648:     return;
 649:     hadhist = 1;
 650:     dol = 0;
 651:     if (hp == alhistp)
 652:     for (ip = hp->next->next; ip != alhistt; ip = ip->next)
 653:         dol++;
 654:     else
 655:     for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
 656:         dol++;
 657:     left = 0, right = dol;
 658:     if (sc == HISTSUB) {
 659:     ungetC('s'), unreadc(HISTSUB), c = ':';
 660:     goto subst;
 661:     }
 662:     c = getC(0);
 663:     if (!any(":^$*-%", c))
 664:     goto subst;
 665:     left = right = -1;
 666:     if (c == ':') {
 667:     c = getC(0);
 668:     unreadc(c);
 669:     if (letter(c) || c == '&') {
 670:         c = ':';
 671:         left = 0, right = dol;
 672:         goto subst;
 673:     }
 674:     }
 675:     else
 676:     ungetC(c);
 677:     if (!getsel(&left, &right, dol))
 678:     return;
 679:     c = getC(0);
 680:     if (c == '*')
 681:     ungetC(c), c = '-';
 682:     if (c == '-') {
 683:     if (!getsel(&left, &right, dol))
 684:         return;
 685:     c = getC(0);
 686:     }
 687: subst:
 688:     exclc = right - left + 1;
 689:     while (--left >= 0)
 690:     hp = hp->next;
 691:     if (sc == HISTSUB || c == ':') {
 692:     do {
 693:         hp = getsub(hp);
 694:         c = getC(0);
 695:     } while (c == ':');
 696:     }
 697:     unreadc(c);
 698:     if (sc == '{') {
 699:     c = getC(0);
 700:     if (c != '}')
 701:         seterror(ERR_BADBANG);
 702:     }
 703:     exclnxt = hp;
 704: }
 705: 
 706: static struct wordent *
 707: getsub(en)
 708:     struct wordent *en;
 709: {
 710:     register Char *cp;
 711:     int     delim;
 712:     register int c;
 713:     int     sc;
 714:     bool global = 0;
 715:     Char    orhsb[sizeof(rhsb) / sizeof(Char)];
 716: 
 717:     exclnxt = 0;
 718:     sc = c = getC(0);
 719:     if (c == 'g')
 720:     global++, sc = c = getC(0);
 721: 
 722:     switch (c) {
 723:     case 'p':
 724:     justpr++;
 725:     return (en);
 726: 
 727:     case 'x':
 728:     case 'q':
 729:     global++;
 730: 
 731:     /* fall into ... */
 732: 
 733:     case 'h':
 734:     case 'r':
 735:     case 't':
 736:     case 'e':
 737:     break;
 738: 
 739:     case '&':
 740:     if (slhs[0] == 0) {
 741:         seterror(ERR_NOSUBST);
 742:         return (en);
 743:     }
 744:     (void) Strcpy(lhsb, slhs);
 745:     break;
 746: 
 747: #ifdef notdef
 748:     case '~':
 749:     if (lhsb[0] == 0)
 750:         goto badlhs;
 751:     break;
 752: #endif
 753: 
 754:     case 's':
 755:     delim = getC(0);
 756:     if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) {
 757:         unreadc(delim);
 758:         lhsb[0] = 0;
 759:         seterror(ERR_BADSUBST);
 760:         return (en);
 761:     }
 762:     cp = lhsb;
 763:     for (;;) {
 764:         c = getC(0);
 765:         if (c == '\n') {
 766:         unreadc(c);
 767:         break;
 768:         }
 769:         if (c == delim)
 770:         break;
 771:         if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) {
 772:         lhsb[0] = 0;
 773:         seterror(ERR_BADSUBST);
 774:         return (en);
 775:         }
 776:         if (c == '\\') {
 777:         c = getC(0);
 778:         if (c != delim && c != '\\')
 779:             *cp++ = '\\';
 780:         }
 781:         *cp++ = c;
 782:     }
 783:     if (cp != lhsb)
 784:         *cp++ = 0;
 785:     else if (lhsb[0] == 0) {
 786:         seterror(ERR_LHS);
 787:         return (en);
 788:     }
 789:     cp = rhsb;
 790:     (void) Strcpy(orhsb, cp);
 791:     for (;;) {
 792:         c = getC(0);
 793:         if (c == '\n') {
 794:         unreadc(c);
 795:         break;
 796:         }
 797:         if (c == delim)
 798:         break;
 799: #ifdef notdef
 800:         if (c == '~') {
 801:         if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) /
 802:                            sizeof(Char) - 2])
 803:             goto toorhs;
 804:         (void) Strcpy(cp, orhsb);
 805:         cp = Strend(cp);
 806:         continue;
 807:         }
 808: #endif
 809:         if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) {
 810:         seterror(ERR_RHSLONG);
 811:         return (en);
 812:         }
 813:         if (c == '\\') {
 814:         c = getC(0);
 815:         if (c != delim /* && c != '~' */ )
 816:             *cp++ = '\\';
 817:         }
 818:         *cp++ = c;
 819:     }
 820:     *cp++ = 0;
 821:     break;
 822: 
 823:     default:
 824:     if (c == '\n')
 825:         unreadc(c);
 826:     seterror(ERR_BADBANGMOD, c);
 827:     return (en);
 828:     }
 829:     (void) Strcpy(slhs, lhsb);
 830:     if (exclc)
 831:     en = dosub(sc, en, global);
 832:     return (en);
 833: }
 834: 
 835: static struct wordent *
 836: dosub(sc, en, global)
 837:     int     sc;
 838:     struct wordent *en;
 839:     bool global;
 840: {
 841:     struct wordent lexi;
 842:     bool    didsub = 0;
 843:     struct wordent *hp = &lexi;
 844:     register struct wordent *wdp;
 845:     register int i = exclc;
 846: 
 847:     wdp = hp;
 848:     while (--i >= 0) {
 849:     register struct wordent *new = (struct wordent *)
 850:     xcalloc(1, sizeof *wdp);
 851: 
 852:     new->word = 0;
 853:     new->prev = wdp;
 854:     new->next = hp;
 855:     wdp->next = new;
 856:     wdp = new;
 857:     en = en->next;
 858:     wdp->word = (en->word && (global ||didsub == 0)) ?
 859:         subword(en->word, sc, &didsub) : Strsave(en->word);
 860:     }
 861:     if (didsub == 0)
 862:     seterror(ERR_MODFAIL);
 863:     hp->prev = wdp;
 864:     return (&enthist(-1000, &lexi, 0)->Hlex);
 865: }
 866: 
 867: static Char *
 868: subword(cp, type, adid)
 869:     Char   *cp;
 870:     int     type;
 871:     bool   *adid;
 872: {
 873:     Char    wbuf[BUFSIZ];
 874:     register Char *wp, *mp, *np;
 875:     register int i;
 876: 
 877:     switch (type) {
 878: 
 879:     case 'r':
 880:     case 'e':
 881:     case 'h':
 882:     case 't':
 883:     case 'q':
 884:     case 'x':
 885:     wp = domod(cp, type);
 886:     if (wp == 0)
 887:         return (Strsave(cp));
 888:     *adid = 1;
 889:     return (wp);
 890: 
 891:     default:
 892:     wp = wbuf;
 893:     i = BUFSIZ - 4;
 894:     for (mp = cp; *mp; mp++)
 895:         if (matchs(mp, lhsb)) {
 896:         for (np = cp; np < mp;)
 897:             *wp++ = *np++, --i;
 898:         for (np = rhsb; *np; np++)
 899:             switch (*np) {
 900: 
 901:             case '\\':
 902:             if (np[1] == '&')
 903:                 np++;
 904:             /* fall into ... */
 905: 
 906:             default:
 907:             if (--i < 0) {
 908:                 seterror(ERR_SUBOVFL);
 909:                 return (STRNULL);
 910:             }
 911:             *wp++ = *np;
 912:             continue;
 913: 
 914:             case '&':
 915:             i -= Strlen(lhsb);
 916:             if (i < 0) {
 917:                 seterror(ERR_SUBOVFL);
 918:                 return (STRNULL);
 919:             }
 920:             *wp = 0;
 921:             (void) Strcat(wp, lhsb);
 922:             wp = Strend(wp);
 923:             continue;
 924:             }
 925:         mp += Strlen(lhsb);
 926:         i -= Strlen(mp);
 927:         if (i < 0) {
 928:             seterror(ERR_SUBOVFL);
 929:             return (STRNULL);
 930:         }
 931:         *wp = 0;
 932:         (void) Strcat(wp, mp);
 933:         *adid = 1;
 934:         return (Strsave(wbuf));
 935:         }
 936:     return (Strsave(cp));
 937:     }
 938: }
 939: 
 940: Char   *
 941: domod(cp, type)
 942:     Char   *cp;
 943:     int     type;
 944: {
 945:     register Char *wp, *xp;
 946:     register int c;
 947: 
 948:     switch (type) {
 949: 
 950:     case 'x':
 951:     case 'q':
 952:     wp = Strsave(cp);
 953:     for (xp = wp; c = *xp; xp++)
 954:         if ((c != ' ' && c != '\t') || type == 'q')
 955:         *xp |= QUOTE;
 956:     return (wp);
 957: 
 958:     case 'h':
 959:     case 't':
 960:     if (!any(short2str(cp), '/'))
 961:         return (type == 't' ? Strsave(cp) : 0);
 962:     wp = Strend(cp);
 963:     while (*--wp != '/')
 964:         continue;
 965:     if (type == 'h')
 966:         xp = Strsave(cp), xp[wp - cp] = 0;
 967:     else
 968:         xp = Strsave(wp + 1);
 969:     return (xp);
 970: 
 971:     case 'e':
 972:     case 'r':
 973:     wp = Strend(cp);
 974:     for (wp--; wp >= cp && *wp != '/'; wp--)
 975:         if (*wp == '.') {
 976:         if (type == 'e')
 977:             xp = Strsave(wp + 1);
 978:         else
 979:             xp = Strsave(cp), xp[wp - cp] = 0;
 980:         return (xp);
 981:         }
 982:     return (Strsave(type == 'e' ? STRNULL : cp));
 983:     }
 984:     return (0);
 985: }
 986: 
 987: static int
 988: matchs(str, pat)
 989:     register Char *str, *pat;
 990: {
 991:     while (*str && *pat && *str == *pat)
 992:     str++, pat++;
 993:     return (*pat == 0);
 994: }
 995: 
 996: static int
 997: getsel(al, ar, dol)
 998:     register int *al, *ar;
 999:     int     dol;
1000: {
1001:     register int c = getC(0);
1002:     register int i;
1003:     bool    first = *al < 0;
1004: 
1005:     switch (c) {
1006: 
1007:     case '%':
1008:     if (quesarg == -1) {
1009:         seterror(ERR_BADBANGARG);
1010:         return (0);
1011:     }
1012:     if (*al < 0)
1013:         *al = quesarg;
1014:     *ar = quesarg;
1015:     break;
1016: 
1017:     case '-':
1018:     if (*al < 0) {
1019:         *al = 0;
1020:         *ar = dol - 1;
1021:         unreadc(c);
1022:     }
1023:     return (1);
1024: 
1025:     case '^':
1026:     if (*al < 0)
1027:         *al = 1;
1028:     *ar = 1;
1029:     break;
1030: 
1031:     case '$':
1032:     if (*al < 0)
1033:         *al = dol;
1034:     *ar = dol;
1035:     break;
1036: 
1037:     case '*':
1038:     if (*al < 0)
1039:         *al = 1;
1040:     *ar = dol;
1041:     if (*ar < *al) {
1042:         *ar = 0;
1043:         *al = 1;
1044:         return (1);
1045:     }
1046:     break;
1047: 
1048:     default:
1049:     if (Isdigit(c)) {
1050:         i = 0;
1051:         while (Isdigit(c)) {
1052:         i = i * 10 + c - '0';
1053:         c = getC(0);
1054:         }
1055:         if (i < 0)
1056:         i = dol + 1;
1057:         if (*al < 0)
1058:         *al = i;
1059:         *ar = i;
1060:     }
1061:     else if (*al < 0)
1062:         *al = 0, *ar = dol;
1063:     else
1064:         *ar = dol - 1;
1065:     unreadc(c);
1066:     break;
1067:     }
1068:     if (first) {
1069:     c = getC(0);
1070:     unreadc(c);
1071:     if (any("-$*", c))
1072:         return (1);
1073:     }
1074:     if (*al > *ar || *ar > dol) {
1075:     seterror(ERR_BADBANGARG);
1076:     return (0);
1077:     }
1078:     return (1);
1079: 
1080: }
1081: 
1082: static struct wordent *
1083: gethent(sc)
1084:     int     sc;
1085: {
1086:     register struct Hist *hp;
1087:     register Char *np;
1088:     register int c;
1089:     int     event;
1090:     bool    back = 0;
1091: 
1092:     c = sc == HISTSUB ? HIST : getC(0);
1093:     if (c == HIST) {
1094:     if (alhistp)
1095:         return (alhistp);
1096:     event = eventno;
1097:     }
1098:     else
1099:     switch (c) {
1100: 
1101:     case ':':
1102:     case '^':
1103:     case '$':
1104:     case '*':
1105:     case '%':
1106:         ungetC(c);
1107:         if (lastev == eventno && alhistp)
1108:         return (alhistp);
1109:         event = lastev;
1110:         break;
1111: 
1112:     case '#':       /* !# is command being typed in (mrh) */
1113:         if (--hleft == 0) {
1114:         seterror(ERR_HISTLOOP);
1115:         return (0);
1116:         }
1117:         else
1118:         return (&paraml);
1119:         /* NOTREACHED */
1120: 
1121:     case '-':
1122:         back = 1;
1123:         c = getC(0);
1124:         /* FALLSTHROUGH */
1125: 
1126:     default:
1127:         if (any("(=~", c)) {
1128:         unreadc(c);
1129:         ungetC(HIST);
1130:         return (0);
1131:         }
1132:         np = lhsb;
1133:         event = 0;
1134:         while (!any(": \t\\\n}", c)) {
1135:         if (event != -1 && Isdigit(c))
1136:             event = event * 10 + c - '0';
1137:         else
1138:             event = -1;
1139:         if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2])
1140:             *np++ = c;
1141:         c = getC(0);
1142:         }
1143:         unreadc(c);
1144:         if (np == lhsb) {
1145:         ungetC(HIST);
1146:         return (0);
1147:         }
1148:         *np++ = 0;
1149:         if (event != -1) {
1150:         /*
1151: 		 * History had only digits
1152: 		 */
1153:         if (back)
1154:             event = eventno + (alhistp == 0) - (event ? event : 0);
1155:         break;
1156:         }
1157:         hp = findev(lhsb, 0);
1158:         if (hp)
1159:         lastev = hp->Hnum;
1160:         return (&hp->Hlex);
1161: 
1162:     case '?':
1163:         np = lhsb;
1164:         for (;;) {
1165:         c = getC(0);
1166:         if (c == '\n') {
1167:             unreadc(c);
1168:             break;
1169:         }
1170:         if (c == '?')
1171:             break;
1172:         if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2])
1173:             *np++ = c;
1174:         }
1175:         if (np == lhsb) {
1176:         if (lhsb[0] == 0) {
1177:             seterror(ERR_NOSEARCH);
1178:             return (0);
1179:         }
1180:         }
1181:         else
1182:         *np++ = 0;
1183:         hp = findev(lhsb, 1);
1184:         if (hp)
1185:         lastev = hp->Hnum;
1186:         return (&hp->Hlex);
1187:     }
1188: 
1189:     for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
1190:     if (hp->Hnum == event) {
1191:         hp->Href = eventno;
1192:         lastev = hp->Hnum;
1193:         return (&hp->Hlex);
1194:     }
1195:     np = putn(event);
1196:     seterror(ERR_NOEVENT, short2str(np));
1197:     return (0);
1198: }
1199: 
1200: static struct Hist *
1201: findev(cp, anyarg)
1202:     Char   *cp;
1203:     bool    anyarg;
1204: {
1205:     register struct Hist *hp;
1206: 
1207:     for (hp = Histlist.Hnext; hp; hp = hp->Hnext) {
1208:     Char   *dp;
1209:     register Char *p, *q;
1210:     register struct wordent *lp = hp->Hlex.next;
1211:     int     argno = 0;
1212: 
1213:     /*
1214: 	 * The entries added by alias substitution don't have a newline but do
1215: 	 * have a negative event number. Savehist() trims off these entries,
1216: 	 * but it happens before alias expansion, too early to delete those
1217: 	 * from the previous command.
1218: 	 */
1219:     if (hp->Hnum < 0)
1220:         continue;
1221:     if (lp->word[0] == '\n')
1222:         continue;
1223:     if (!anyarg) {
1224:         p = cp;
1225:         q = lp->word;
1226:         do
1227:         if (!*p)
1228:             return (hp);
1229:         while (*p++ == *q++);
1230:         continue;
1231:     }
1232:     do {
1233:         for (dp = lp->word; *dp; dp++) {
1234:         p = cp;
1235:         q = dp;
1236:         do
1237:             if (!*p) {
1238:             quesarg = argno;
1239:             return (hp);
1240:             }
1241:         while (*p++ == *q++);
1242:         }
1243:         lp = lp->next;
1244:         argno++;
1245:     } while (lp->word[0] != '\n');
1246:     }
1247:     seterror(ERR_NOEVENT, short2str(cp));
1248:     return (0);
1249: }
1250: 
1251: 
1252: static void
1253: setexclp(cp)
1254:     register Char *cp;
1255: {
1256:     if (cp && cp[0] == '\n')
1257:     return;
1258:     exclp = cp;
1259: }
1260: 
1261: void
1262: unreadc(c)
1263:     Char    c;
1264: {
1265:     peekread = c;
1266: }
1267: 
1268: int
1269: readc(wanteof)
1270:     bool    wanteof;
1271: {
1272:     register int c;
1273:     static  sincereal;
1274: 
1275:     if (c = peekread) {
1276:     peekread = 0;
1277:     return (c);
1278:     }
1279: top:
1280:     if (alvecp) {
1281:     if (c = *alvecp++)
1282:         return (c);
1283:     if (*alvec) {
1284:         alvecp = *alvec++;
1285:         return (' ');
1286:     }
1287:     }
1288:     if (alvec) {
1289:     if (alvecp = *alvec) {
1290:         alvec++;
1291:         goto top;
1292:     }
1293:     /* Infinite source! */
1294:     return ('\n');
1295:     }
1296:     if (evalp) {
1297:     if (c = *evalp++)
1298:         return (c);
1299:     if (*evalvec) {
1300:         evalp = *evalvec++;
1301:         return (' ');
1302:     }
1303:     evalp = 0;
1304:     }
1305:     if (evalvec) {
1306:     if (evalvec == (Char **) 1) {
1307:         doneinp = 1;
1308:         reset();
1309:     }
1310:     if (evalp = *evalvec) {
1311:         evalvec++;
1312:         goto top;
1313:     }
1314:     evalvec = (Char **) 1;
1315:     return ('\n');
1316:     }
1317:     do {
1318:     if (arginp == (Char *) 1 || onelflg == 1) {
1319:         if (wanteof)
1320:         return (-1);
1321:         exitstat();
1322:     }
1323:     if (arginp) {
1324:         if ((c = *arginp++) == 0) {
1325:         arginp = (Char *) 1;
1326:         return ('\n');
1327:         }
1328:         return (c);
1329:     }
1330: reread:
1331:     c = bgetc();
1332:     if (c < 0) {
1333: #ifndef POSIX
1334: #ifdef TERMIO
1335: #include <termio.h>
1336:         struct termio tty;
1337: 
1338: #else               /* SGTTYB */
1339: #include <sys/ioctl.h>
1340:         struct sgttyb tty;
1341: 
1342: #endif				/* TERMIO */
1343: #else               /* POSIX */
1344: #include <termios.h>
1345:         struct termios tty;
1346: 
1347: #endif				/* POSIX */
1348:         if (wanteof)
1349:         return (-1);
1350:         /* was isatty but raw with ignoreeof yields problems */
1351: #ifndef POSIX
1352: #ifdef TERMIO
1353:         if (ioctl(SHIN, TCGETA, (ioctl_t) & tty) == 0 &&
1354:         (tty.c_lflag & ICANON))
1355: #else               /* GSTTYB */
1356:         if (ioctl(SHIN, TIOCGETP, (ioctl_t) & tty) == 0 &&
1357:         (tty.sg_flags & RAW) == 0)
1358: #endif				/* TERMIO */
1359: #else               /* POSIX */
1360:         if (tcgetattr(SHIN, &tty) == 0 &&
1361:         (tty.c_lflag & ICANON))
1362: #endif				/* POSIX */
1363:         {
1364:         /* was 'short' for FILEC */
1365:         int     ctpgrp;
1366: 
1367:         if (++sincereal > 25)
1368:             goto oops;
1369: #ifdef BSDJOBS
1370:         if (tpgrp != -1 &&
1371:             (ctpgrp = tcgetpgrp(FSHTTY)) != -1 &&
1372:             tpgrp != ctpgrp) {
1373:             (void) tcsetpgrp(FSHTTY, tpgrp);
1374:             (void) killpg((pid_t) ctpgrp, SIGHUP);
1375:             xprintf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp);
1376:             goto reread;
1377:         }
1378: #endif				/* BSDJOBS */
1379:         if (adrof(STRig_eof)) {
1380:             if (loginsh)
1381:             xprintf("\nUse \"logout\" to logout.\n");
1382:             else
1383:             xprintf("\nUse \"exit\" to leave tcsh.\n");
1384:             reset();
1385:         }
1386:         if (chkstop == 0)
1387:             panystop(1);
1388:         }
1389:     oops:
1390:         doneinp = 1;
1391:         reset();
1392:     }
1393:     sincereal = 0;
1394:     if (c == '\n' && onelflg)
1395:         onelflg--;
1396:     } while (c == 0);
1397:     if (hist_p_line < histline + BUFSIZ)
1398:     *hist_p_line++ = c;
1399:     return (c);
1400: }
1401: 
1402: static int
1403: bgetc()
1404: {
1405:     register int buf, off, c;
1406:     register int numleft = 0, roomleft;
1407:     extern Char InputBuf[];
1408:     char    tbuf[BUFSIZ + 1];
1409: 
1410:     if (cantell) {
1411:     if (fseekp < fbobp || fseekp > feobp) {
1412:         fbobp = feobp = fseekp;
1413:         (void) lseek(SHIN, fseekp, L_SET);
1414:     }
1415:     if (fseekp == feobp) {
1416:         int     i;
1417: 
1418:         fbobp = feobp;
1419:         do
1420:         c = read(SHIN, tbuf, BUFSIZ);
1421:         while (c < 0 && errno == EINTR);
1422:         if (c <= 0)
1423:         return (-1);
1424:         for (i = 0; i < c; i++)
1425:         fbuf[0][i] = (unsigned char) tbuf[i];
1426:         feobp += c;
1427:     }
1428:     c = fbuf[0][fseekp - fbobp];
1429:     fseekp++;
1430:     return (c);
1431:     }
1432: again:
1433:     buf = (int) fseekp / BUFSIZ;
1434:     if (buf >= fblocks) {
1435:     register Char **nfbuf =
1436:     (Char **) xcalloc((size_t) (fblocks + 2),
1437:               sizeof(Char **));
1438: 
1439:     if (fbuf) {
1440:         (void) blkcpy(nfbuf, fbuf);
1441:         xfree((ptr_t) fbuf);
1442:     }
1443:     fbuf = nfbuf;
1444:     fbuf[fblocks] = (Char *) xcalloc(BUFSIZ, sizeof(Char));
1445:     fblocks++;
1446:     if (!intty)
1447:         goto again;
1448:     }
1449:     if (fseekp >= feobp) {
1450:     buf = (int) feobp / BUFSIZ;
1451:     off = (int) feobp % BUFSIZ;
1452:     roomleft = BUFSIZ - off;
1453:     for (;;) {
1454:         if (editing && intty) { /* then use twenex routine */
1455:         c = numleft ? numleft : Inputl();   /* PWP: get a line */
1456:         if (c > roomleft) { /* No room in this buffer? */
1457:             /* start with fresh buffer */
1458:             feobp = fseekp = fblocks * BUFSIZ;
1459:             numleft = c;
1460:             goto again;
1461:         }
1462:         if (c > 0)
1463:             copy((char *) (fbuf[buf] + off),
1464:              (char *) InputBuf, (int) (c * sizeof(Char)));
1465:         /* copy (fbuf[buf] + off, ttyline, c); */
1466:         numleft = 0;
1467:         }
1468:         else {
1469:         c = read(SHIN, tbuf, (size_t) roomleft);
1470:         if (c > 0) {
1471:             int     i;
1472:             Char   *ptr = fbuf[buf] + off;
1473: 
1474:             for (i = 0; i < c; i++)
1475:             ptr[i] = (unsigned char) tbuf[i];
1476:         }
1477:         }
1478:         if (c >= 0)
1479:         break;
1480:         switch (errno) {
1481: #ifdef FIONBIO
1482:         static int zero = 0;
1483: 
1484: #endif				/* FIONBIO */
1485: #ifdef EWOULDBLOCK
1486:         case EWOULDBLOCK:
1487: #endif				/* EWOULDBLOCK */
1488: #if defined(POSIX) && defined(EAGAIN)
1489: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1490:         case EAGAIN:
1491: #endif				/* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
1492: #endif				/* POSIX && EAGAIN */
1493: #if defined(F_SETFL) && defined(O_NDELAY)
1494:         (void) fcntl(SHIN, F_SETFL,
1495:                  fcntl(SHIN, F_GETFL, 0) & ~O_NDELAY);
1496: #endif				/* F_SETFL && O_NDELAY */
1497: #ifdef FIONBIO
1498:         (void) ioctl(SHIN, FIONBIO, (ioctl_t) & zero);
1499: #endif				/* FIONBIO */
1500: #if (defined(F_SETFL) && defined(O_NDELAY)) || defined(FIONBIO)
1501:         c = 0;
1502: #endif				/* (F_SETFL && O_NDELAY) || FIONBIO */
1503:         break;
1504: #ifdef _SEQUENT_
1505:         case EBADF:
1506: #endif				/* _SEQUENT_ */
1507:         case EINTR:
1508:         c = 0;
1509:         break;
1510:         default:
1511:         c = -1;
1512:         break;
1513:         }
1514:         if (c == -1)
1515:         break;
1516:     }
1517:     if (c <= 0)
1518:         return (-1);
1519:     feobp += c;
1520:     if (editing && !intty)
1521:         goto again;
1522:     }
1523:     c = fbuf[buf][(int) fseekp % BUFSIZ];
1524:     fseekp++;
1525:     return (c);
1526: }
1527: 
1528: static void
1529: bfree()
1530: {
1531:     register int sb, i;
1532: 
1533:     if (cantell)
1534:     return;
1535:     if (whyles)
1536:     return;
1537:     sb = (int) (fseekp - 1) / BUFSIZ;
1538:     if (sb > 0) {
1539:     for (i = 0; i < sb; i++)
1540:         xfree((ptr_t) fbuf[i]);
1541:     (void) blkcpy(fbuf, &fbuf[sb]);
1542:     fseekp -= BUFSIZ * sb;
1543:     feobp -= BUFSIZ * sb;
1544:     fblocks -= sb;
1545:     }
1546: }
1547: 
1548: void
1549: bseek(l)
1550:     off_t   l;
1551: {
1552: 
1553:     fseekp = l;
1554:     if (!cantell) {
1555: #ifdef notdef
1556:     register struct whyle *wp;
1557: #endif
1558:     if (!whyles)
1559:         return;
1560: #ifdef notdef
1561:     /*
1562: 	 * Christos: I don't understand this? both wp and l are local. What is
1563: 	 * this used for? I suspect the author meant fseek = wp->w_start
1564: 	 */
1565:     for (wp = whyles; wp->w_next; wp = wp->w_next)
1566:         continue;
1567:     if (wp->w_start > l)
1568:         l = wp->w_start;
1569: #endif
1570:     }
1571: }
1572: 
1573: /* any similarity to bell telephone is purely accidental */
1574: #ifndef btell
1575: off_t
1576: btell()
1577: {
1578:     return (fseekp);
1579: }
1580: 
1581: #endif
1582: 
1583: void
1584: btoeof()
1585: {
1586:     (void) lseek(SHIN, (off_t) 0, L_XTND);
1587:     fseekp = feobp;
1588:     wfree();
1589:     bfree();
1590: }
1591: 
1592: void
1593: settell()
1594: {
1595:     cantell = 0;
1596:     if (arginp || onelflg || intty)
1597:     return;
1598:     if (lseek(SHIN, (off_t) 0, L_INCR) < 0 || errno == ESPIPE)
1599:     return;
1600:     fbuf = (Char **) xcalloc(2, sizeof(Char **));
1601:     fblocks = 1;
1602:     fbuf[0] = (Char *) xcalloc(BUFSIZ, sizeof(Char));
1603:     fseekp = fbobp = feobp = lseek(SHIN, (off_t) 0, L_INCR);
1604:     cantell = 1;
1605: }

Defined functions

addla defined in line 605; used 25 times
bfree defined in line 1528; used 1 times
bgetc defined in line 1402; used 1 times
bseek defined in line 1548; used 5 times
btell defined in line 1575; never used
btoeof defined in line 1583; used 2 times
copylex defined in line 205; used 1 times
domod defined in line 940; used 3 times
dosub defined in line 835; used 1 times
findev defined in line 1200; used 2 times
getC1 defined in line 378; used 1 times
getdol defined in line 435; used 1 times
getexcl defined in line 629; used 2 times
gethent defined in line 1082; used 1 times
getsel defined in line 996; used 2 times
getsub defined in line 706; used 1 times
lex defined in line 137; used 32 times
matchs defined in line 987; used 1 times
prlex defined in line 189; used 5 times
rcsid defined in line 39; never used
readc defined in line 1268; used 10 times
setexclp defined in line 1252; used 2 times
settell defined in line 1592; never used
subword defined in line 867; used 1 times
unreadc defined in line 1261; used 30 times
word defined in line 243; used 22 times

Defined variables

alvecp defined in line 100; used 5 times
exclc defined in line 97; used 5 times
exclnxt defined in line 94; used 12 times
exclp defined in line 91; used 4 times
getCtmp defined in line 131; used 2 times
  • in line 133(2)
hadhist defined in line 118; used 3 times
hist_p_line defined in line 129; used 9 times
histline defined in line 125; used 13 times
histvalid defined in line 128; used 3 times
hleft defined in line 123; used 2 times
labuf defined in line 109; used 4 times
lhsb defined in line 624; used 25 times
peekc defined in line 87; used 5 times
peekread defined in line 88; used 3 times
quesarg defined in line 627; used 5 times
rhsb defined in line 626; used 7 times
slhs defined in line 625; used 3 times

Defined macros

getC defined in line 133; used 38 times
ungetC defined in line 134; used 12 times
ungetD defined in line 135; used 5 times
Last modified: 1991-08-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8693
Valid CSS Valid XHTML 1.0 Strict