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
Dfix1 defined in line 120; used 3 times
Dfix2 defined in line 143; used 2 times
DgetC defined in line 325; used 18 times
Dgetdol defined in line 385; used 1 times
Dpack defined in line 162; used 2 times
Dredc defined in line 655; used 2 times
Dtestq defined in line 674; used 1 times
Dword defined in line 210; used 1 times
dolerror defined in line 373; used 4 times
fixDolMod defined in line 604; used 3 times
heredoc defined in line 688; used 1 times
rcsid defined in line 39; never used
setDolp defined in line 624; used 6 times
unDredc defined in line 647; used 8 times

Defined variables

Dcp defined in line 59; used 6 times
Dpeekc defined in line 58; used 3 times
Dpeekrd defined in line 58; used 3 times
Dvp defined in line 59; used 4 times
dolcnt defined in line 75; used 7 times
dolmcnt defined in line 77; used 7 times
dolmod defined in line 76; used 5 times
dolnxt defined in line 74; used 3 times
dolp defined in line 73; used 9 times
nulargv defined in line 371; used 1 times
nulvec defined in line 370; used 1 times

Defined macros

DEOF defined in line 61; used 7 times
MAXWLEN defined in line 158; used 4 times
QUOTES defined in line 65; used 4 times
unDgetC defined in line 63; used 4 times
Last modified: 1991-08-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4724
Valid CSS Valid XHTML 1.0 Strict