# 2.11BSD#431 - /usr/src/bin/tcsh/sh.lex.c

##### Functions

    addla             X
    bseek             X
    btell             X
    btoeof            X
    copylex           X
    domod             X
    freelex           X
    lex               X
    prlex             X
    readc             X
    settell           X
    unreadc           X

##### Variables

    histline          X
    histvalid         X
    hleft             X

##### Macros

    getC              X
    ungetC            X
    ungetD            X

       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

- in line 463, 471, 478, 489, 521, 527, 549, 558, 583, 595, 601
- in /usr/src/bin/tcsh/sh.dol.c line 587, 637-641(2)
- in /usr/src/bin/tcsh/sh.lex.c line 463, 471, 478, 489, 521, 527, 549, 558, 583, 595, 601

bfree defined in line 1528; used 1 times

- in line 1589

bgetc defined in line 1402; used 1 times

- in line 1331

bseek defined in line 1548; used 5 times

- in /usr/src/bin/tcsh/sh.func.c line 369, 550, 563, 665, 868

btell defined in line 1575; never used
btoeof defined in line 1583; used 2 times

- in /usr/src/bin/tcsh/sh.err.c line 464
- in /usr/src/bin/tcsh/sh.func.c line 420

copylex defined in line 205; used 1 times

- in /usr/src/bin/tcsh/sh.hist.c line 99

domod defined in line 940; used 3 times

- in line 885
- in /usr/src/bin/tcsh/ed.chared.c line 405
- in /usr/src/bin/tcsh/sh.dol.c line 634

dosub defined in line 835; used 1 times

- in line 831

findev defined in line 1200; used 2 times

- in line 1157, 1183

freelex defined in line 228; used 6 times

- in /usr/src/bin/tcsh/sh.exp.c line 622
- in /usr/src/bin/tcsh/sh.hist.c line 122
- in /usr/src/bin/tcsh/sh.parse.c line 172
- in /usr/src/bin/tcsh/tc.func.c line 252, 681
- in /usr/src/bin/tcsh/tc.sched.c line 255

getC1 defined in line 378; used 1 times

- in line 133

getdol defined in line 435; used 1 times

- in line 423

getexcl defined in line 629; used 2 times

- in line 157, 427

gethent defined in line 1082; used 1 times

- in line 646

getsel defined in line 996; used 2 times

- in line 677, 683

getsub defined in line 706; used 1 times

- in line 693

lex defined in line 137; used 32 times

- in /usr/src/bin/tcsh/sh.exec.c line 607-612(3), 618-619(2), 653, 676, 684-689(2)
- in /usr/src/bin/tcsh/sh.glob.c line 689
- in /usr/src/bin/tcsh/sh.parse.c line 70-71(2), 85(2), 168
- in /usr/src/bin/tcsh/tc.func.c line 365-377(15), 386-387(2)

matchs defined in line 987; used 1 times

- in line 895

prlex defined in line 189; used 5 times

- in /usr/src/bin/tcsh/sh.exec.c line 653, 676, 684-689(2)
- in /usr/src/bin/tcsh/sh.hist.c line 225

rcsid defined in line 39; never used
readc defined in line 1268; used 10 times

- in line 153, 421
- in /usr/src/bin/tcsh/sh.dol.c line 727
- in /usr/src/bin/tcsh/sh.func.c line 760-767(3), 779-780(2)
- in /usr/src/bin/tcsh/sh.lex.c line 153, 421

setexclp defined in line 1252; used 2 times

- in line 407, 418

settell defined in line 1592; never used
subword defined in line 867; used 1 times

- in line 859

unreadc defined in line 1261; used 30 times

- in line 159, 659, 668, 697, 757, 766, 794, 825, 1021, 1065-1070(2), 1128, 1143, 1167
- in /usr/src/bin/tcsh/sh.func.c line 776, 802
- in /usr/src/bin/tcsh/sh.lex.c line 159, 659, 668, 697, 757, 766, 794, 825, 1021, 1065-1070(2), 1128, 1143, 1167

word defined in line 243; used 22 times

- in line 150, 169-175(4), 196-200(2), 222-224(3), 237, 407, 418, 852, 858-859(4), 1221-1225(2), 1233, 1245

#### Defined variables

alvecp defined in line 100; used 5 times

- in line 151, 1280-1289(4)

exclc defined in line 97; used 5 times

- in line 405, 415, 688, 830, 845

exclnxt defined in line 94; used 12 times

- in line 405-418(10), 703, 717

exclp defined in line 91; used 4 times

- in line 402-403(2), 410, 1258

getCtmp defined in line 131; used 2 times

- in line 133(2)

hadhist defined in line 118; used 3 times

- in line 151, 186, 649

hist_p_line defined in line 129; used 9 times

- in line 145-146(2), 177-180(5), 1397-1398(2)

histline defined in line 125; used 13 times

- in line 145, 177-184(3), 1397
- in /usr/src/bin/tcsh/sh.hist.c line 101-103(3), 110, 123-124(2), 222-223(2)

histvalid defined in line 128; used 3 times

- in line 144, 181
- in /usr/src/bin/tcsh/sh.hist.c line 100

hleft defined in line 123; used 2 times

- in line 1113
- in /usr/src/bin/tcsh/sh.parse.c line 76

labuf defined in line 109; used 4 times

- in line 612, 618-621(3)

lhsb defined in line 624; used 25 times

- in line 744-749(2), 758-762(2), 771-772(3), 783-785(2), 829, 895, 915, 921-925(2), 1132, 1139-1144(3), 1157, 1163, 1172-1176(4), 1183

peekc defined in line 87; used 5 times

- in line 133-134(3), 385-386(2)

peekread defined in line 88; used 3 times

- in line 1265, 1275-1276(2)

quesarg defined in line 627; used 5 times

- in line 644, 1008-1014(3), 1238

rhsb defined in line 626; used 7 times

- in line 715, 789, 801(2), 809(2), 898

slhs defined in line 625; used 3 times

- in line 740-744(2), 829

#### Defined macros

getC defined in line 133; used 38 times

- in line 255, 263, 276, 290, 309, 344, 365, 445, 452-454(2), 495, 508, 543, 561, 574-576(2), 590, 638, 662-667(2), 679, 685, 694-699(2), 718-720(2), 755, 764, 777, 792, 814, 1001, 1053, 1069, 1092, 1123, 1141, 1165

ungetC defined in line 134; used 12 times

- in line 267, 331, 338, 359, 448, 640, 659, 676-681(2), 1106, 1129, 1145

ungetD defined in line 135; used 5 times

- in line 447, 467, 545, 588-592(2)

Last modified: 1991-08-20 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3607 |