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

##### Functions

    Dfix              X
    Dfix1             X
    heredoc           X

##### Macros

    DEOF              X
    MAXWLEN           X
    QUOTES            X
    unDgetC           X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.dol.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
       2: /*
       3:  * sh.dol.c: Variable substitutions
       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.dol.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44:
      45: /*
      46:  * C shell
      47:  */
      48:
      49: /*
      50:  * These routines perform variable substitution and quoting via ' and ".
      51:  * To this point these constructs have been preserved in the divided
      52:  * input words.  Here we expand variables and turn quoting via ' and " into
      53:  * QUOTE bits on characters (which prevent further interpretation).
      54:  * If the `:q' modifier was applied during history expansion, then
      55:  * some QUOTEing may have occurred already, so we dont "trim()" here.
      56:  */
      57:
      58: static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
      59: static Char *Dcp, **Dvp;    /* Input vector for Dreadc */
      60:
      61: #define DEOF    -1
      62:
      63: #define unDgetC(c)  Dpeekc = c
      64:
      65: #define QUOTES      (_Q|_Q1|_ESC)   /* \ ' " ` */
      66:
      67: /*
      68:  * The following variables give the information about the current
      69:  * $ expansion, recording the current word position, the remaining
      70:  * words within this expansion, the count of remaining words, and the
      71:  * information about any : modifier which is being applied.
      72:  */
      73: static Char *dolp;      /* Remaining chars from this word */
      74: static Char **dolnxt;       /* Further words */
      75: static int dolcnt;      /* Count of further words */
      76: static Char dolmod;     /* : modifier character */
      77: static int dolmcnt;     /* :gx -> 10000, else 1 */
      78:
      79: static  void     Dfix2      __P((Char **));
      80: static  Char    *Dpack      __P((Char *, Char *));
      81: static  int  Dword      __P((void));
      82: static  void     dolerror   __P((Char *));
      83: static  int  DgetC      __P((int));
      84: static  void     Dgetdol    __P((void));
      85: static  void     fixDolMod  __P((void));
      86: static  void     setDolp    __P((Char *));
      87: static  void     unDredc    __P((int));
      88: static  int  Dredc      __P((void));
      89: static  void     Dtestq     __P((int));
      90:
      91: /*
      92:  * Fix up the $ expansions and quotations in the
      93:  * argument list to command t.
      94:  */
      95: void
      96: Dfix(t)
      97:     register struct command *t;
      98: {
      99:     register Char **pp;
     100:     register Char *p;
     101:
     102:     if (noexec)
     103:     return;
     104:     /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
     105:     for (pp = t->t_dcom; p = *pp++;)
     106:     for (; *p; p++) {
     107:         if (cmap(*p, _DOL | QUOTES)) {  /* $, \, ', ", ` */
     108:         Dfix2(t->t_dcom);   /* found one */
     109:         blkfree(t->t_dcom);
     110:         t->t_dcom = gargv;
     111:         gargv = 0;
     112:         return;
     113:         }
     114:     }
     115: }
     116:
     117: /*
     118:  * $ substitute one word, for i/o redirection
     119:  */
     120: Char   *
     121: Dfix1(cp)
     122:     register Char *cp;
     123: {
     124:     Char   *Dv[2];
     125:
     126:     if (noexec)
     127:     return (0);
     128:     Dv[0] = cp;
     129:     Dv[1] = NOSTR;
     130:     Dfix2(Dv);
     131:     if ((int)gargc != 1) {
     132:     setname(short2str(cp));
     133:     stderror(ERR_NAME | ERR_AMBIG);
     134:     }
     135:     cp = Strsave(gargv[0]);
     136:     blkfree(gargv), gargv = 0;
     137:     return (cp);
     138: }
     139:
     140: /*
     141:  * Subroutine to do actual fixing after state initialization.
     142:  */
     143: static void
     144: Dfix2(v)
     145:     Char  **v;
     146: {
     147:     ginit();            /* Initialize glob's area pointers */
     148:     Dvp = v;
     149:     Dcp = STRNULL;      /* Setup input vector for Dreadc */
     150:     unDgetC(0);
     151:     unDredc(0);         /* Clear out any old peeks (at error) */
     152:     dolp = 0;
     153:     dolcnt = 0;         /* Clear out residual $ expands (...) */
     154:     while (Dword())
     155:     continue;
     156: }
     157:
     158: #define MAXWLEN (BUFSIZ - 4)
     159: /*
     160:  * Pack up more characters in this word
     161:  */
     162: static Char *
     163: Dpack(wbuf, wp)
     164:     Char   *wbuf, *wp;
     165: {
     166:     register int c;
     167:     register int i = MAXWLEN - (wp - wbuf);
     168:
     169:     for (;;) {
     170:     c = DgetC(DODOL);
     171:     if (c == '\\') {
     172:         c = DgetC(0);
     173:         if (c == DEOF) {
     174:         unDredc(c);
     175:         *wp = 0;
     176:         Gcat(STRNULL, wbuf);
     177:         return (NULL);
     178:         }
     179:         if (c == '\n')
     180:         c = ' ';
     181:         else
     182:         c |= QUOTE;
     183:     }
     184:     if (c == DEOF) {
     185:         unDredc(c);
     186:         *wp = 0;
     187:         Gcat(STRNULL, wbuf);
     188:         return (NULL);
     189:     }
     190:     if (cmap(c, _SP | _NL | _Q | _Q1)) {    /* sp \t\n'"` */
     191:         unDgetC(c);
     192:         if (cmap(c, QUOTES))
     193:         return (wp);
     194:         *wp++ = 0;
     195:         Gcat(STRNULL, wbuf);
     196:         return (NULL);
     197:     }
     198:     if (--i <= 0)
     199:         stderror(ERR_WTOOLONG);
     200:     *wp++ = c;
     201:     }
     202: }
     203:
     204: /*
     205:  * Get a word.  This routine is analogous to the routine
     206:  * word() in sh.lex.c for the main lexical input.  One difference
     207:  * here is that we don't get a newline to terminate our expansion.
     208:  * Rather, DgetC will return a DEOF when we hit the end-of-input.
     209:  */
     210: static int
     211: Dword()
     212: {
     213:     register int c, c1;
     214:     Char    wbuf[BUFSIZ];
     215:     register Char *wp = wbuf;
     216:     register int i = MAXWLEN;
     217:     register bool dolflg;
     218:     bool    sofar = 0, done = 0;
     219:
     220:     while (!done) {
     221:     done = 1;
     222:     c = DgetC(DODOL);
     223:     switch (c) {
     224:
     225:     case DEOF:
     226:         if (sofar == 0)
     227:         return (0);
     228:         /* finish this word and catch the code above the next time */
     229:         unDredc(c);
     230:         /* fall into ... */
     231:
     232:     case '\n':
     233:         *wp = 0;
     234:         Gcat(STRNULL, wbuf);
     235:         return (1);
     236:
     237:     case ' ':
     238:     case '\t':
     239:         done = 0;
     240:         break;
     241:
     242:     case '`':
     243:         /* We preserve ` quotations which are done yet later */
     244:         *wp++ = c, --i;
     245:     case '\'':
     246:     case '"':
     247:         /*
     248: 	     * Note that DgetC never returns a QUOTES character from an
     249: 	     * expansion, so only true input quotes will get us here or out.
     250: 	     */
     251:         c1 = c;
     252:         dolflg = c1 == '"' ? DODOL : 0;
     253:         for (;;) {
     254:         c = DgetC(dolflg);
     255:         if (c == c1)
     256:             break;
     257:         if (c == '\n' || c == DEOF)
     258:             stderror(ERR_UNMATCHED, c1);
     259:         if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))
     260:             --wp, ++i;
     261:         if (--i <= 0)
     262:             stderror(ERR_WTOOLONG);
     263:         switch (c1) {
     264:
     265:         case '"':
     266:             /*
     267: 		     * Leave any `s alone for later. Other chars are all
     268: 		     * quoted, thus `...` can tell it was within "...".
     269: 		     */
     270:             *wp++ = c == '`' ? '`' : c | QUOTE;
     271:             break;
     272:
     273:         case '\'':
     274:             /* Prevent all further interpretation */
     275:             *wp++ = c | QUOTE;
     276:             break;
     277:
     278:         case '`':
     279:             /* Leave all text alone for later */
     280:             *wp++ = c;
     281:             break;
     282:         }
     283:         }
     284:         if (c1 == '`')
     285:         *wp++ = '`' /* i--; eliminated */;
     286:         sofar = 1;
     287:         if ((wp = Dpack(wbuf, wp)) == NULL)
     288:         return (1);
     289:         else {
     290:         i = MAXWLEN - (wp - wbuf);
     291:         done = 0;
     292:         }
     293:         break;
     294:
     295:     case '\\':
     296:         c = DgetC(0);   /* No $ subst! */
     297:         if (c == '\n' || c == DEOF) {
     298:         done = 0;
     299:         break;
     300:         }
     301:         c |= QUOTE;
     302:         break;
     303:     }
     304:     if (done) {
     305:         unDgetC(c);
     306:         sofar = 1;
     307:         if ((wp = Dpack(wbuf, wp)) == NULL)
     308:         return (1);
     309:         else {
     310:         i = MAXWLEN - (wp - wbuf);
     311:         done = 0;
     312:         }
     313:     }
     314:     }
     315:     /* Really NOTREACHED */
     316:     return (0);
     317: }
     318:
     319:
     320: /*
     321:  * Get a character, performing $ substitution unless flag is 0.
     322:  * Any QUOTES character which is returned from a $ expansion is
     323:  * QUOTEd so that it will not be recognized above.
     324:  */
     325: static int
     326: DgetC(flag)
     327:     register int flag;
     328: {
     329:     register int c;
     330:
     331: top:
     332:     if (c = Dpeekc) {
     333:     Dpeekc = 0;
     334:     return (c);
     335:     }
     336:     if (lap) {
     337:     c = *lap++ & (QUOTE | TRIM);
     338:     if (c == 0) {
     339:         lap = 0;
     340:         goto top;
     341:     }
     342: quotspec:
     343:     if (cmap(c, QUOTES))
     344:         return (c | QUOTE);
     345:     return (c);
     346:     }
     347:     if (dolp) {
     348:     if (c = *dolp++ & (QUOTE | TRIM))
     349:         goto quotspec;
     350:     if (dolcnt > 0) {
     351:         setDolp(*dolnxt++);
     352:         --dolcnt;
     353:         return (' ');
     354:     }
     355:     dolp = 0;
     356:     }
     357:     if (dolcnt > 0) {
     358:     setDolp(*dolnxt++);
     359:     --dolcnt;
     360:     goto top;
     361:     }
     362:     c = Dredc();
     363:     if (c == '$' && flag) {
     364:     Dgetdol();
     365:     goto top;
     366:     }
     367:     return (c);
     368: }
     369:
     370: static Char *nulvec[] = {0};
     371: static struct varent nulargv = {nulvec, STRargv, 0};
     372:
     373: static void
     374: dolerror(s)
     375:     Char   *s;
     376: {
     377:     setname(short2str(s));
     378:     stderror(ERR_NAME | ERR_RANGE);
     379: }
     380:
     381: /*
     382:  * Handle the multitudinous $ expansion forms.
     383:  * Ugh.
     384:  */
     385: static void
     386: Dgetdol()
     387: {
     388:     register Char *np;
     389:     register struct varent *vp = NULL;
     390:     Char    name[4 * MAXVARLEN + 1];
     391:     int     c, sc;
     392:     int     subscr = 0, lwb = 1, upb = 0;
     393:     bool    dimen = 0, bitset = 0;
     394:     char    tnp;
     395:     Char    wbuf[BUFSIZ];
     396:
     397:     dolmod = dolmcnt = 0;
     398:     c = sc = DgetC(0);
     399:     if (c == '{')
     400:     c = DgetC(0);       /* sc is { to take } later */
     401:     if ((c & TRIM) == '#')
     402:     dimen++, c = DgetC(0);  /* $# takes dimension */
     403:     else if (c == '?')
     404:     bitset++, c = DgetC(0); /* $? tests existence */
     405:     switch (c) {
     406:
     407:     case '$':
     408:     if (dimen || bitset)
     409:         stderror(ERR_SYNTAX);
     410:     setDolp(doldol);
     411:     goto eatbrac;
     412:
     413:     case '<' | QUOTE:
     414:     if (bitset)
     415:         stderror(ERR_NOTALLOWED, "$?<");
     416:     if (dimen)
     417:         stderror(ERR_NOTALLOWED, "$?#");
     418:     for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
     419:         *np = tnp;
     420:         if (np >= &wbuf[BUFSIZ - 1])
     421:         stderror(ERR_LTOOLONG);
     422:         if (SIGN_EXTEND_CHAR(tnp) <= 0 || tnp == '\n')
     423:         break;
     424:     }
     425:     *np = 0;
     426:     /*
     427: 	 * KLUDGE: dolmod is set here because it will cause setDolp to call
     428: 	 * domod and thus to copy wbuf. Otherwise setDolp would use it
     429: 	 * directly. If we saved it ourselves, no one would know when to free
     430: 	 * it. The actual function of the 'q' causes filename expansion not to
     431: 	 * be done on the interpolated value.
     432: 	 */
     433:     dolmod = 'q';
     434:     dolmcnt = 10000;
     435:     setDolp(wbuf);
     436:     goto eatbrac;
     437:
     438:     case DEOF:
     439:     case '\n':
     440:     stderror(ERR_SYNTAX);
     441:     /* NOTREACHED */
     442:     break;
     443:
     444:     case '*':
     445:     (void) Strcpy(name, STRargv);
     446:     vp = adrof(STRargv);
     447:     subscr = -1;        /* Prevent eating [...] */
     448:     break;
     449:
     450:     default:
     451:     np = name;
     452:     if (Isdigit(c)) {
     453:         if (dimen)
     454:         stderror(ERR_NOTALLOWED, "$#<num>");
     455:         subscr = 0;
     456:         do {
     457:         subscr = subscr * 10 + c - '0';
     458:         c = DgetC(0);
     459:         } while (Isdigit(c));
     460:         unDredc(c);
     461:         if (subscr < 0) {
     462:         dolerror(vp->v_name);
     463:         return;
     464:         }
     465:         if (subscr == 0) {
     466:         if (bitset) {
     467:             dolp = ffile ? STR1 : STR0;
     468:             goto eatbrac;
     469:         }
     470:         if (ffile == 0)
     471:             stderror(ERR_DOLZERO);
     472:         fixDolMod();
     473:         setDolp(ffile);
     474:         goto eatbrac;
     475:         }
     476:         if (bitset)
     477:         stderror(ERR_DOLQUEST);
     478:         vp = adrof(STRargv);
     479:         if (vp == 0) {
     480:         vp = &nulargv;
     481:         goto eatmod;
     482:         }
     483:         break;
     484:     }
     485:     if (!alnum(c))
     486:         stderror(ERR_VARALNUM);
     487:     for (;;) {
     488:         *np++ = c;
     489:         c = DgetC(0);
     490:         if (!alnum(c))
     491:         break;
     492:         if (np >= &name[MAXVARLEN])
     493:         stderror(ERR_VARTOOLONG);
     494:     }
     495:     *np++ = 0;
     496:     unDredc(c);
     497:     vp = adrof(name);
     498:     }
     499:     if (bitset) {
     500:     dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
     501:     goto eatbrac;
     502:     }
     503:     if (vp == 0) {
     504:     np = str2short(getenv(short2str(name)));
     505:     if (np) {
     506:         fixDolMod();
     507:         setDolp(np);
     508:         goto eatbrac;
     509:     }
     510:     udvar(name);
     511:     /* NOTREACHED */
     512:     }
     513:     c = DgetC(0);
     514:     upb = blklen(vp->vec);
     515:     if (dimen == 0 && subscr == 0 && c == '[') {
     516:     np = name;
     517:     for (;;) {
     518:         c = DgetC(DODOL);   /* Allow $ expand within [ ] */
     519:         if (c == ']')
     520:         break;
     521:         if (c == '\n' || c == DEOF)
     522:         stderror(ERR_INCBR);
     523:         if (np >= &name[sizeof(name) / sizeof(Char) - 2])
     524:         stderror(ERR_VARTOOLONG);
     525:         *np++ = c;
     526:     }
     527:     *np = 0, np = name;
     528:     if (dolp || dolcnt) /* $ exp must end before ] */
     529:         stderror(ERR_EXPORD);
     530:     if (!*np)
     531:         stderror(ERR_SYNTAX);
     532:     if (Isdigit(*np)) {
     533:         int     i;
     534:
     535:         for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0');
     536:         if ((i < 0 || i > upb) && !any("-*", *np)) {
     537:         dolerror(vp->v_name);
     538:         return;
     539:         }
     540:         lwb = i;
     541:         if (!*np)
     542:         upb = lwb, np = STRstar;
     543:     }
     544:     if (*np == '*')
     545:         np++;
     546:     else if (*np != '-')
     547:         stderror(ERR_MISSING, '-');
     548:     else {
     549:         register int i = upb;
     550:
     551:         np++;
     552:         if (Isdigit(*np)) {
     553:         i = 0;
     554:         while (Isdigit(*np))
     555:             i = i * 10 + *np++ - '0';
     556:         if (i < 0 || i > upb) {
     557:             dolerror(vp->v_name);
     558:             return;
     559:         }
     560:         }
     561:         if (i < lwb)
     562:         upb = lwb - 1;
     563:         else
     564:         upb = i;
     565:     }
     566:     if (lwb == 0) {
     567:         if (upb != 0) {
     568:         dolerror(vp->v_name);
     569:         return;
     570:         }
     571:         upb = -1;
     572:     }
     573:     if (*np)
     574:         stderror(ERR_SYNTAX);
     575:     }
     576:     else {
     577:     if (subscr > 0)
     578:         if (subscr > upb)
     579:         lwb = 1, upb = 0;
     580:         else
     581:         lwb = upb = subscr;
     582:     unDredc(c);
     583:     }
     584:     if (dimen) {
     585:     Char   *cp = putn(upb - lwb + 1);
     586:
     587:     addla(cp);
     588:     xfree((ptr_t) cp);
     589:     }
     590:     else {
     591: eatmod:
     592:     fixDolMod();
     593:     dolnxt = &vp->vec[lwb - 1];
     594:     dolcnt = upb - lwb + 1;
     595:     }
     596: eatbrac:
     597:     if (sc == '{') {
     598:     c = Dredc();
     599:     if (c != '}')
     600:         stderror(ERR_MISSING, '}');
     601:     }
     602: }
     603:
     604: static void
     605: fixDolMod()
     606: {
     607:     register int c;
     608:
     609:     c = DgetC(0);
     610:     if (c == ':') {
     611:     c = DgetC(0), dolmcnt = 1;
     612:     if (c == 'g')
     613:         c = DgetC(0), dolmcnt = 10000;
     614:     if (!any("htrqxe", c))
     615:         stderror(ERR_BADMOD, c);
     616:     dolmod = c;
     617:     if (c == 'q')
     618:         dolmcnt = 10000;
     619:     }
     620:     else
     621:     unDredc(c);
     622: }
     623:
     624: static void
     625: setDolp(cp)
     626:     register Char *cp;
     627: {
     628:     register Char *dp;
     629:
     630:     if (dolmod == 0 || dolmcnt == 0) {
     631:     dolp = cp;
     632:     return;
     633:     }
     634:     dp = domod(cp, dolmod);
     635:     if (dp) {
     636:     dolmcnt--;
     637:     addla(dp);
     638:     xfree((ptr_t) dp);
     639:     }
     640:     else
     641:     addla(cp);
     642:     dolp = STRNULL;
     643:     if (seterr)
     644:     stderror(ERR_OLD);
     645: }
     646:
     647: static void
     648: unDredc(c)
     649:     int     c;
     650: {
     651:
     652:     Dpeekrd = c;
     653: }
     654:
     655: static int
     656: Dredc()
     657: {
     658:     register int c;
     659:
     660:     if (c = Dpeekrd) {
     661:     Dpeekrd = 0;
     662:     return (c);
     663:     }
     664:     if (Dcp && (c = *Dcp++))
     665:     return (c & (QUOTE | TRIM));
     666:     if (*Dvp == 0) {
     667:     Dcp = 0;
     668:     return (DEOF);
     669:     }
     670:     Dcp = *Dvp++;
     671:     return (' ');
     672: }
     673:
     674: static void
     675: Dtestq(c)
     676:     register int c;
     677: {
     678:
     679:     if (cmap(c, QUOTES))
     680:     gflag = 1;
     681: }
     682:
     683: /*
     684:  * Form a shell temporary file (in unit 0) from the words
     685:  * of the shell input up to EOF or a line the same as "term".
     686:  * Unit 0 should have been closed before this call.
     687:  */
     688: void
     689: heredoc(term)
     690:     Char   *term;
     691: {
     692:     register int c;
     693:     Char   *Dv[2];
     694:     Char    obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ];
     695:     int     ocnt, lcnt, mcnt;
     696:     register Char *lbp, *obp, *mbp;
     697:     Char  **vp;
     698:     bool    quoted;
     699:     char   *tmp;
     700:
     701:     if (creat(tmp = short2str(shtemp), 0600) < 0)
     702:     stderror(ERR_SYSTEM, tmp, strerror(errno));
     703:     (void) close(0);
     704:     if (open(tmp, O_RDWR) < 0) {
     705:     int     oerrno = errno;
     706:
     707:     (void) unlink(tmp);
     708:     errno = oerrno;
     709:     stderror(ERR_SYSTEM, tmp, strerror(errno));
     710:     }
     711:     (void) unlink(tmp);     /* 0 0 inode! */
     712:     Dv[0] = term;
     713:     Dv[1] = NOSTR;
     714:     gflag = 0;
     715:     trim(Dv);
     716:     rscan(Dv, Dtestq);
     717:     quoted = gflag;
     718:     ocnt = BUFSIZ;
     719:     obp = obuf;
     720:     for (;;) {
     721:     /*
     722: 	 * Read up a line
     723: 	 */
     724:     lbp = lbuf;
     725:     lcnt = BUFSIZ - 4;
     726:     for (;;) {
     727:         c = readc(1);   /* 1 -> Want EOF returns */
     728:         if (c < 0 || c == '\n')
     729:         break;
     730:         if (c &= TRIM) {
     731:         *lbp++ = c;
     732:         if (--lcnt < 0) {
     733:             setname("<<");
     734:             stderror(ERR_NAME | ERR_OVERFLOW);
     735:         }
     736:         }
     737:     }
     738:     *lbp = 0;
     739:
     740:     /*
     741: 	 * Check for EOF or compare to terminator -- before expansion
     742: 	 */
     743:     if (c < 0 || eq(lbuf, term)) {
     744:         (void) write(0, short2str(obuf), (size_t) (BUFSIZ - ocnt));
     745:         (void) lseek(0, 0l, L_SET);
     746:         return;
     747:     }
     748:
     749:     /*
     750: 	 * If term was quoted or -n just pass it on
     751: 	 */
     752:     if (quoted || noexec) {
     753:         *lbp++ = '\n';
     754:         *lbp = 0;
     755:         for (lbp = lbuf; c = *lbp++;) {
     756:         *obp++ = c;
     757:         if (--ocnt == 0) {
     758:             (void) write(0, short2str(obuf), BUFSIZ);
     759:             obp = obuf;
     760:             ocnt = BUFSIZ;
     761:         }
     762:         }
     763:         continue;
     764:     }
     765:
     766:     /*
     767: 	 * Term wasn't quoted so variable and then command expand the input
     768: 	 * line
     769: 	 */
     770:     Dcp = lbuf;
     771:     Dvp = Dv + 1;
     772:     mbp = mbuf;
     773:     mcnt = BUFSIZ - 4;
     774:     for (;;) {
     775:         c = DgetC(DODOL);
     776:         if (c == DEOF)
     777:         break;
     778:         if ((c &= TRIM) == 0)
     779:         continue;
     780:         /* \ quotes \ $ ` here */
     781:         if (c == '\\') {
     782:         c = DgetC(0);
     783:         if (!any("$\\`", c))
     784:             unDgetC(c | QUOTE), c = '\\';
     785:         else
     786:             c |= QUOTE;
     787:         }
     788:         *mbp++ = c;
     789:         if (--mcnt == 0) {
     790:         setname("<<");
     791:         stderror(ERR_NAME | ERR_OVERFLOW);
     792:         }
     793:     }
     794:     *mbp++ = 0;
     795:
     796:     /*
     797: 	 * If any ` in line do command substitution
     798: 	 */
     799:     mbp = mbuf;
     800:     if (any(short2str(mbp), '`')) {
     801:         /*
     802: 	     * 1 arg to dobackp causes substitution to be literal. Words are
     803: 	     * broken only at newlines so that all blanks and tabs are
     804: 	     * preserved.  Blank lines (null words) are not discarded.
     805: 	     */
     806:         vp = dobackp(mbuf, 1);
     807:     }
     808:     else
     809:         /* Setup trivial vector similar to return of dobackp */
     810:         Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv;
     811:
     812:     /*
     813: 	 * Resurrect the words from the command substitution each separated by
     814: 	 * a newline.  Note that the last newline of a command substitution
     815: 	 * will have been discarded, but we put a newline after the last word
     816: 	 * because this represents the newline after the last input line!
     817: 	 */
     818:     for (; *vp; vp++) {
     819:         for (mbp = *vp; *mbp; mbp++) {
     820:         *obp++ = *mbp & TRIM;
     821:         if (--ocnt == 0) {
     822:             (void) write(0, short2str(obuf), BUFSIZ);
     823:             obp = obuf;
     824:             ocnt = BUFSIZ;
     825:         }
     826:         }
     827:         *obp++ = '\n';
     828:         if (--ocnt == 0) {
     829:         (void) write(0, short2str(obuf), BUFSIZ);
     830:         obp = obuf;
     831:         ocnt = BUFSIZ;
     832:         }
     833:     }
     834:     if (pargv)
     835:         blkfree(pargv), pargv = 0;
     836:     }
     837: }

#### Defined functions

Dfix defined in line 95; used 1 times

- in /usr/src/bin/tcsh/sh.sem.c line 108

Dfix1 defined in line 120; used 3 times

- in /usr/src/bin/tcsh/sh.func.c line 736
- in /usr/src/bin/tcsh/sh.sem.c line 647, 686

Dfix2 defined in line 143; used 2 times

- in line 108, 130

DgetC defined in line 325; used 18 times

- in line 170-172(2), 222, 254, 296, 398-404(4), 458, 489, 513-518(2), 609-613(3), 775, 782

Dgetdol defined in line 385; used 1 times

- in line 364

Dpack defined in line 162; used 2 times

- in line 287, 307

Dredc defined in line 655; used 2 times

- in line 362, 598

Dtestq defined in line 674; used 1 times

- in line 716

Dword defined in line 210; used 1 times

- in line 154

dolerror defined in line 373; used 4 times

- in line 462, 537, 557, 568

fixDolMod defined in line 604; used 3 times

- in line 472, 506, 592

heredoc defined in line 688; used 1 times

- in /usr/src/bin/tcsh/sh.sem.c line 122

rcsid defined in line 39; never used
setDolp defined in line 624; used 6 times

- in line 351, 358, 410, 435, 473, 507

unDredc defined in line 647; used 8 times

- in line 151, 174, 185, 229, 460, 496, 582, 621

#### Defined variables

Dcp defined in line 59; used 6 times

- in line 149, 664-670(4), 770

Dpeekc defined in line 58; used 3 times

- in line 63, 332-333(2)

Dpeekrd defined in line 58; used 3 times

- in line 652, 660-661(2)

Dvp defined in line 59; used 4 times

- in line 148, 666-670(2), 771

dolcnt defined in line 75; used 7 times

- in line 153, 350-359(4), 528, 594

dolmcnt defined in line 77; used 7 times

- in line 397, 434, 611-618(3), 630, 636

dolmod defined in line 76; used 5 times

- in line 397, 433, 616, 630-634(2)

dolnxt defined in line 74; used 3 times

- in line 351, 358, 593

dolp defined in line 73; used 9 times

- in line 152, 347-348(2), 355, 467, 500, 528, 631, 642

nulargv defined in line 371; used 1 times

- in line 480

nulvec defined in line 370; used 1 times

- in line 371

#### Defined macros

DEOF defined in line 61; used 7 times

- in line 173, 184, 257, 297, 521, 668, 776

MAXWLEN defined in line 158; used 4 times

- in line 167, 216, 290, 310

QUOTES defined in line 65; used 4 times

- in line 107, 192, 343, 679

unDgetC defined in line 63; used 4 times

- in line 150, 191, 305, 784

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