summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/sh.dol.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcsh/sh.dol.c')
-rw-r--r--contrib/tcsh/sh.dol.c1094
1 files changed, 0 insertions, 1094 deletions
diff --git a/contrib/tcsh/sh.dol.c b/contrib/tcsh/sh.dol.c
deleted file mode 100644
index 73ac3b2..0000000
--- a/contrib/tcsh/sh.dol.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-/* $Header: /p/tcsh/cvsroot/tcsh/sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $ */
-/*
- * sh.dol.c: Variable substitutions
- */
-/*-
- * Copyright (c) 1980, 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "sh.h"
-
-RCSID("$tcsh: sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $")
-
-/*
- * C shell
- */
-
-/*
- * These routines perform variable substitution and quoting via ' and ".
- * To this point these constructs have been preserved in the divided
- * input words. Here we expand variables and turn quoting via ' and " into
- * QUOTE bits on characters (which prevent further interpretation).
- * If the `:q' modifier was applied during history expansion, then
- * some QUOTEing may have occurred already, so we dont "trim()" here.
- */
-
-static Char Dpeekc; /* Peek for DgetC */
-static eChar Dpeekrd; /* Peek for Dreadc */
-static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */
-
-#define DEOF CHAR_ERR
-
-#define unDgetC(c) Dpeekc = c
-
-#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
-
-/*
- * The following variables give the information about the current
- * $ expansion, recording the current word position, the remaining
- * words within this expansion, the count of remaining words, and the
- * information about any : modifier which is being applied.
- */
-static Char *dolp; /* Remaining chars from this word */
-static Char **dolnxt; /* Further words */
-static int dolcnt; /* Count of further words */
-static struct Strbuf dolmod; /* = Strbuf_INIT; : modifier characters */
-static int dolmcnt; /* :gx -> INT_MAX, else 1 */
-static int dol_flag_a; /* :ax -> 1, else 0 */
-
-static Char **Dfix2 (Char *const *);
-static int Dpack (struct Strbuf *);
-static int Dword (struct blk_buf *);
-static void dolerror (Char *);
-static eChar DgetC (int);
-static void Dgetdol (void);
-static void fixDolMod (void);
-static void setDolp (Char *);
-static void unDredc (eChar);
-static eChar Dredc (void);
-static void Dtestq (Char);
-
-/*
- * Fix up the $ expansions and quotations in the
- * argument list to command t.
- */
-void
-Dfix(struct command *t)
-{
- Char **pp;
- Char *p;
-
- if (noexec)
- return;
- /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
- for (pp = t->t_dcom; (p = *pp++) != NULL;) {
- for (; *p; p++) {
- if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
- Char **expanded;
-
- expanded = Dfix2(t->t_dcom); /* found one */
- blkfree(t->t_dcom);
- t->t_dcom = expanded;
- return;
- }
- }
- }
-}
-
-/*
- * $ substitute one word, for i/o redirection
- */
-Char *
-Dfix1(Char *cp)
-{
- Char *Dv[2], **expanded;
-
- if (noexec)
- return (0);
- Dv[0] = cp;
- Dv[1] = NULL;
- expanded = Dfix2(Dv);
- if (expanded[0] == NULL || expanded[1] != NULL) {
- blkfree(expanded);
- setname(short2str(cp));
- stderror(ERR_NAME | ERR_AMBIG);
- }
- cp = Strsave(expanded[0]);
- blkfree(expanded);
- return (cp);
-}
-
-/*
- * Subroutine to do actual fixing after state initialization.
- */
-static Char **
-Dfix2(Char *const *v)
-{
- struct blk_buf bb = BLK_BUF_INIT;
-
- Dvp = v;
- Dcp = STRNULL; /* Setup input vector for Dreadc */
- unDgetC(0);
- unDredc(0); /* Clear out any old peeks (at error) */
- dolp = 0;
- dolcnt = 0; /* Clear out residual $ expands (...) */
- cleanup_push(&bb, bb_cleanup);
- while (Dword(&bb))
- continue;
- cleanup_ignore(&bb);
- cleanup_until(&bb);
- return bb_finish(&bb);
-}
-
-/*
- * Pack up more characters in this word
- */
-static int
-Dpack(struct Strbuf *wbuf)
-{
- eChar c;
-
- for (;;) {
- c = DgetC(DODOL);
- if (c == '\\') {
- c = DgetC(0);
- if (c == DEOF) {
- unDredc(c);
- return 1;
- }
- if (c == '\n')
- c = ' ';
- else
- c |= QUOTE;
- }
- if (c == DEOF) {
- unDredc(c);
- return 1;
- }
- if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
- unDgetC(c);
- if (cmap(c, QUOTES))
- return 0;
- return 1;
- }
- Strbuf_append1(wbuf, (Char) c);
- }
-}
-
-/*
- * Get a word. This routine is analogous to the routine
- * word() in sh.lex.c for the main lexical input. One difference
- * here is that we don't get a newline to terminate our expansion.
- * Rather, DgetC will return a DEOF when we hit the end-of-input.
- */
-static int
-Dword(struct blk_buf *bb)
-{
- eChar c, c1;
- struct Strbuf wbuf = Strbuf_INIT;
- int dolflg;
- int sofar = 0;
-
- cleanup_push(&wbuf, Strbuf_cleanup);
- for (;;) {
- c = DgetC(DODOL);
- switch (c) {
-
- case DEOF:
- if (sofar == 0) {
- cleanup_until(&wbuf);
- return (0);
- }
- /* finish this word and catch the code above the next time */
- unDredc(c);
- /*FALLTHROUGH*/
-
- case '\n':
- goto end;
-
- case ' ':
- case '\t':
- continue;
-
- case '`':
- /* We preserve ` quotations which are done yet later */
- Strbuf_append1(&wbuf, (Char) c);
- /*FALLTHROUGH*/
- case '\'':
- case '"':
- /*
- * Note that DgetC never returns a QUOTES character from an
- * expansion, so only true input quotes will get us here or out.
- */
- c1 = c;
- dolflg = c1 == '"' ? DODOL : 0;
- for (;;) {
- c = DgetC(dolflg);
- if (c == c1)
- break;
- if (c == '\n' || c == DEOF)
- stderror(ERR_UNMATCHED, (int)c1);
- if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) {
- if (wbuf.len != 0 && (wbuf.s[wbuf.len - 1] & TRIM) == '\\')
- wbuf.len--;
- }
- switch (c1) {
-
- case '"':
- /*
- * Leave any `s alone for later. Other chars are all
- * quoted, thus `...` can tell it was within "...".
- */
- Strbuf_append1(&wbuf, c == '`' ? '`' : c | QUOTE);
- break;
-
- case '\'':
- /* Prevent all further interpretation */
- Strbuf_append1(&wbuf, c | QUOTE);
- break;
-
- case '`':
- /* Leave all text alone for later */
- Strbuf_append1(&wbuf, (Char) c);
- break;
-
- default:
- break;
- }
- }
- if (c1 == '`')
- Strbuf_append1(&wbuf, '`');
- sofar = 1;
- if (Dpack(&wbuf) != 0)
- goto end;
- continue;
-
- case '\\':
- c = DgetC(0); /* No $ subst! */
- if (c == '\n' || c == DEOF)
- continue;
- c |= QUOTE;
- break;
-
- default:
- break;
- }
- unDgetC(c);
- sofar = 1;
- if (Dpack(&wbuf) != 0)
- goto end;
- }
-
- end:
- cleanup_ignore(&wbuf);
- cleanup_until(&wbuf);
- bb_append(bb, Strbuf_finish(&wbuf));
- return 1;
-}
-
-
-/*
- * Get a character, performing $ substitution unless flag is 0.
- * Any QUOTES character which is returned from a $ expansion is
- * QUOTEd so that it will not be recognized above.
- */
-static eChar
-DgetC(int flag)
-{
- Char c;
-
-top:
- if ((c = Dpeekc) != 0) {
- Dpeekc = 0;
- return (c);
- }
- if (lap < labuf.len) {
- c = labuf.s[lap++] & (QUOTE | TRIM);
-quotspec:
- if (cmap(c, QUOTES))
- return (c | QUOTE);
- return (c);
- }
- if (dolp) {
- if ((c = *dolp++ & (QUOTE | TRIM)) != 0)
- goto quotspec;
- if (dolcnt > 0) {
- setDolp(*dolnxt++);
- --dolcnt;
- return (' ');
- }
- dolp = 0;
- }
- if (dolcnt > 0) {
- setDolp(*dolnxt++);
- --dolcnt;
- goto top;
- }
- c = Dredc();
- if (c == '$' && flag) {
- Dgetdol();
- goto top;
- }
- return (c);
-}
-
-static Char *nulvec[] = { NULL };
-static struct varent nulargv = {nulvec, STRargv, VAR_READWRITE,
- { NULL, NULL, NULL }, 0 };
-
-static void
-dolerror(Char *s)
-{
- setname(short2str(s));
- stderror(ERR_NAME | ERR_RANGE);
-}
-
-/*
- * Handle the multitudinous $ expansion forms.
- * Ugh.
- */
-static void
-Dgetdol(void)
-{
- Char *np;
- struct varent *vp = NULL;
- struct Strbuf name = Strbuf_INIT;
- eChar c, sc;
- int subscr = 0, lwb = 1, upb = 0;
- int dimen = 0, bitset = 0, length = 0;
- static Char *dolbang = NULL;
-
- cleanup_push(&name, Strbuf_cleanup);
- dolmod.len = dolmcnt = dol_flag_a = 0;
- c = sc = DgetC(0);
- if (c == DEOF) {
- stderror(ERR_SYNTAX);
- return;
- }
- if (c == '{')
- c = DgetC(0); /* sc is { to take } later */
- if ((c & TRIM) == '#')
- dimen++, c = DgetC(0); /* $# takes dimension */
- else if (c == '?')
- bitset++, c = DgetC(0); /* $? tests existence */
- else if (c == '%')
- length++, c = DgetC(0); /* $% returns length in chars */
- switch (c) {
-
- case '!':
- if (dimen || bitset || length)
- stderror(ERR_SYNTAX);
- if (backpid != 0) {
- xfree(dolbang);
- setDolp(dolbang = putn(backpid));
- }
- cleanup_until(&name);
- goto eatbrac;
-
- case '$':
- if (dimen || bitset || length)
- stderror(ERR_SYNTAX);
- setDolp(doldol);
- cleanup_until(&name);
- goto eatbrac;
-
- case '<'|QUOTE: {
- static struct Strbuf wbuf; /* = Strbuf_INIT; */
-
- if (bitset)
- stderror(ERR_NOTALLOWED, "$?<");
- if (dimen)
- stderror(ERR_NOTALLOWED, "$#<");
- if (length)
- stderror(ERR_NOTALLOWED, "$%<");
- wbuf.len = 0;
- {
- char cbuf[MB_LEN_MAX];
- size_t cbp = 0;
- int old_pintr_disabled;
-
- for (;;) {
- int len;
- ssize_t res;
- Char wc;
-
- pintr_push_enable(&old_pintr_disabled);
- res = force_read(OLDSTD, cbuf + cbp, 1);
- cleanup_until(&old_pintr_disabled);
- if (res != 1)
- break;
- cbp++;
- len = normal_mbtowc(&wc, cbuf, cbp);
- if (len == -1) {
- reset_mbtowc();
- if (cbp < MB_LEN_MAX)
- continue; /* Maybe a partial character */
- wc = (unsigned char)*cbuf | INVALID_BYTE;
- }
- if (len <= 0)
- len = 1;
- if (cbp != (size_t)len)
- memmove(cbuf, cbuf + len, cbp - len);
- cbp -= len;
- if (wc == '\n')
- break;
- Strbuf_append1(&wbuf, wc);
- }
- while (cbp != 0) {
- int len;
- Char wc;
-
- len = normal_mbtowc(&wc, cbuf, cbp);
- if (len == -1) {
- reset_mbtowc();
- wc = (unsigned char)*cbuf | INVALID_BYTE;
- }
- if (len <= 0)
- len = 1;
- if (cbp != (size_t)len)
- memmove(cbuf, cbuf + len, cbp - len);
- cbp -= len;
- if (wc == '\n')
- break;
- Strbuf_append1(&wbuf, wc);
- }
- Strbuf_terminate(&wbuf);
- }
-
- fixDolMod();
- setDolp(wbuf.s); /* Kept allocated until next $< expansion */
- cleanup_until(&name);
- goto eatbrac;
- }
-
- case '*':
- Strbuf_append(&name, STRargv);
- Strbuf_terminate(&name);
- vp = adrof(STRargv);
- subscr = -1; /* Prevent eating [...] */
- break;
-
- case DEOF:
- case '\n':
- np = dimen ? STRargv : (bitset ? STRstatus : NULL);
- if (np) {
- bitset = 0;
- Strbuf_append(&name, np);
- Strbuf_terminate(&name);
- vp = adrof(np);
- subscr = -1; /* Prevent eating [...] */
- unDredc(c);
- break;
- }
- else
- stderror(ERR_SYNTAX);
- /*NOTREACHED*/
-
- default:
- if (Isdigit(c)) {
- if (dimen)
- stderror(ERR_NOTALLOWED, "$#<num>");
- subscr = 0;
- do {
- subscr = subscr * 10 + c - '0';
- c = DgetC(0);
- } while (c != DEOF && Isdigit(c));
- unDredc(c);
- if (subscr < 0)
- stderror(ERR_RANGE);
- if (subscr == 0) {
- if (bitset) {
- dolp = dolzero ? STR1 : STR0;
- cleanup_until(&name);
- goto eatbrac;
- }
- if (ffile == 0)
- stderror(ERR_DOLZERO);
- if (length) {
- length = Strlen(ffile);
- addla(putn(length));
- }
- else {
- fixDolMod();
- setDolp(ffile);
- }
- cleanup_until(&name);
- goto eatbrac;
- }
-#if 0
- if (bitset)
- stderror(ERR_NOTALLOWED, "$?<num>");
- if (length)
- stderror(ERR_NOTALLOWED, "$%<num>");
-#endif
- vp = adrof(STRargv);
- if (vp == 0) {
- vp = &nulargv;
- cleanup_until(&name);
- goto eatmod;
- }
- break;
- }
- if (c == DEOF || !alnum(c)) {
- np = dimen ? STRargv : (bitset ? STRstatus : NULL);
- if (np) {
- bitset = 0;
- Strbuf_append(&name, np);
- Strbuf_terminate(&name);
- vp = adrof(np);
- subscr = -1; /* Prevent eating [...] */
- unDredc(c);
- break;
- }
- else
- stderror(ERR_VARALNUM);
- }
- for (;;) {
- Strbuf_append1(&name, (Char) c);
- c = DgetC(0);
- if (c == DEOF || !alnum(c))
- break;
- }
- Strbuf_terminate(&name);
- unDredc(c);
- vp = adrof(name.s);
- }
- if (bitset) {
- dolp = (vp || getenv(short2str(name.s))) ? STR1 : STR0;
- cleanup_until(&name);
- goto eatbrac;
- }
- if (vp == NULL || vp->vec == NULL) {
- np = str2short(getenv(short2str(name.s)));
- if (np) {
- static Char *env_val; /* = NULL; */
-
- cleanup_until(&name);
- fixDolMod();
- xfree(env_val);
- env_val = Strsave(np);
- setDolp(env_val);
- goto eatbrac;
- }
- udvar(name.s);
- /* NOTREACHED */
- }
- cleanup_until(&name);
- c = DgetC(0);
- upb = blklen(vp->vec);
- if (dimen == 0 && subscr == 0 && c == '[') {
- name = Strbuf_init;
- cleanup_push(&name, Strbuf_cleanup);
- np = name.s;
- for (;;) {
- c = DgetC(DODOL); /* Allow $ expand within [ ] */
- if (c == ']')
- break;
- if (c == '\n' || c == DEOF)
- stderror(ERR_INCBR);
- Strbuf_append1(&name, (Char) c);
- }
- Strbuf_terminate(&name);
- np = name.s;
- if (dolp || dolcnt) /* $ exp must end before ] */
- stderror(ERR_EXPORD);
- if (!*np)
- stderror(ERR_SYNTAX);
- if (Isdigit(*np)) {
- int i;
-
- for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
- continue;
- if ((i < 0 || i > upb) && !any("-*", *np)) {
- cleanup_until(&name);
- dolerror(vp->v_name);
- return;
- }
- lwb = i;
- if (!*np)
- upb = lwb, np = STRstar;
- }
- if (*np == '*')
- np++;
- else if (*np != '-')
- stderror(ERR_MISSING, '-');
- else {
- int i = upb;
-
- np++;
- if (Isdigit(*np)) {
- i = 0;
- while (Isdigit(*np))
- i = i * 10 + *np++ - '0';
- if (i < 0 || i > upb) {
- cleanup_until(&name);
- dolerror(vp->v_name);
- return;
- }
- }
- if (i < lwb)
- upb = lwb - 1;
- else
- upb = i;
- }
- if (lwb == 0) {
- if (upb != 0) {
- cleanup_until(&name);
- dolerror(vp->v_name);
- return;
- }
- upb = -1;
- }
- if (*np)
- stderror(ERR_SYNTAX);
- cleanup_until(&name);
- }
- else {
- if (subscr > 0) {
- if (subscr > upb)
- lwb = 1, upb = 0;
- else
- lwb = upb = subscr;
- }
- unDredc(c);
- }
- if (dimen) {
- /* this is a kludge. It prevents Dgetdol() from */
- /* pushing erroneous ${#<error> values into the labuf. */
- if (sc == '{') {
- c = Dredc();
- if (c != '}')
- stderror(ERR_MISSING, '}');
- unDredc(c);
- }
- addla(putn(upb - lwb + 1));
- }
- else if (length) {
- int i;
-
- for (i = lwb - 1, length = 0; i < upb; i++)
- length += Strlen(vp->vec[i]);
-#ifdef notdef
- /* We don't want that, since we can always compute it by adding $#xxx */
- length += i - 1; /* Add the number of spaces in */
-#endif
- addla(putn(length));
- }
- else {
-eatmod:
- fixDolMod();
- dolnxt = &vp->vec[lwb - 1];
- dolcnt = upb - lwb + 1;
- }
-eatbrac:
- if (sc == '{') {
- c = Dredc();
- if (c != '}')
- stderror(ERR_MISSING, '}');
- }
-}
-
-static void
-fixDolMod(void)
-{
- eChar c;
-
- c = DgetC(0);
- if (c == ':') {
- do {
- c = DgetC(0), dolmcnt = 1, dol_flag_a = 0;
- if (c == 'g' || c == 'a') {
- if (c == 'g')
- dolmcnt = INT_MAX;
- else
- dol_flag_a = 1;
- c = DgetC(0);
- }
- if ((c == 'g' && dolmcnt != INT_MAX) ||
- (c == 'a' && dol_flag_a == 0)) {
- if (c == 'g')
- dolmcnt = INT_MAX;
- else
- dol_flag_a = 1;
- c = DgetC(0);
- }
-
- if (c == 's') { /* [eichin:19910926.0755EST] */
- int delimcnt = 2;
- eChar delim = DgetC(0);
- Strbuf_append1(&dolmod, (Char) c);
- Strbuf_append1(&dolmod, (Char) delim);
-
- if (delim == DEOF || !delim || letter(delim)
- || Isdigit(delim) || any(" \t\n", delim)) {
- seterror(ERR_BADSUBST);
- break;
- }
- while ((c = DgetC(0)) != DEOF) {
- Strbuf_append1(&dolmod, (Char) c);
- if(c == delim) delimcnt--;
- if(!delimcnt) break;
- }
- if(delimcnt) {
- seterror(ERR_BADSUBST);
- break;
- }
- continue;
- }
- if (!any("luhtrqxes", c))
- stderror(ERR_BADMOD, (int)c);
- Strbuf_append1(&dolmod, (Char) c);
- if (c == 'q')
- dolmcnt = INT_MAX;
- }
- while ((c = DgetC(0)) == ':');
- unDredc(c);
- }
- else
- unDredc(c);
-}
-
-static void
-setDolp(Char *cp)
-{
- Char *dp;
- size_t i;
-
- if (dolmod.len == 0 || dolmcnt == 0) {
- dolp = cp;
- return;
- }
- cp = Strsave(cp);
- for (i = 0; i < dolmod.len; i++) {
- int didmod = 0;
-
- /* handle s// [eichin:19910926.0510EST] */
- if(dolmod.s[i] == 's') {
- Char delim;
- Char *lhsub, *rhsub, *np;
- size_t lhlen = 0, rhlen = 0;
-
- delim = dolmod.s[++i];
- if (!delim || letter(delim)
- || Isdigit(delim) || any(" \t\n", delim)) {
- seterror(ERR_BADSUBST);
- break;
- }
- lhsub = &dolmod.s[++i];
- while(dolmod.s[i] != delim && dolmod.s[++i]) {
- lhlen++;
- }
- dolmod.s[i] = 0;
- rhsub = &dolmod.s[++i];
- while(dolmod.s[i] != delim && dolmod.s[++i]) {
- rhlen++;
- }
- dolmod.s[i] = 0;
-
- strip(lhsub);
- strip(cp);
- dp = cp;
- do {
- dp = Strstr(dp, lhsub);
- if (dp) {
- ptrdiff_t diff = dp - cp;
- np = xmalloc((Strlen(cp) + 1 - lhlen + rhlen) *
- sizeof(Char));
- (void) Strncpy(np, cp, diff);
- (void) Strcpy(np + diff, rhsub);
- (void) Strcpy(np + diff + rhlen, dp + lhlen);
-
- dp = np + diff + 1;
- xfree(cp);
- cp = np;
- didmod = 1;
- } else {
- /* should this do a seterror? */
- break;
- }
- }
- while (dol_flag_a != 0);
- /*
- * restore dolmod for additional words
- */
- dolmod.s[i] = rhsub[-1] = (Char) delim;
- } else {
-
- do {
- if ((dp = domod(cp, dolmod.s[i])) != NULL) {
- didmod = 1;
- if (Strcmp(cp, dp) == 0) {
- xfree(cp);
- cp = dp;
- break;
- }
- else {
- xfree(cp);
- cp = dp;
- }
- }
- else
- break;
- }
- while (dol_flag_a != 0);
- }
- if (didmod && dolmcnt != INT_MAX)
- dolmcnt--;
-#ifdef notdef
- else
- break;
-#endif
- }
-
- addla(cp);
-
- dolp = STRNULL;
- if (seterr)
- stderror(ERR_OLD);
-}
-
-static void
-unDredc(eChar c)
-{
-
- Dpeekrd = c;
-}
-
-static eChar
-Dredc(void)
-{
- Char c;
-
- if ((c = Dpeekrd) != 0) {
- Dpeekrd = 0;
- return (c);
- }
- if (Dcp && (c = *Dcp++))
- return (c & (QUOTE | TRIM));
- if (*Dvp == 0) {
- Dcp = 0;
- return (DEOF);
- }
- Dcp = *Dvp++;
- return (' ');
-}
-
-static int gflag;
-
-static void
-Dtestq(Char c)
-{
-
- if (cmap(c, QUOTES))
- gflag = 1;
-}
-
-static void
-inheredoc_cleanup(void *dummy)
-{
- USE(dummy);
- inheredoc = 0;
-}
-
-/*
- * Form a shell temporary file (in unit 0) from the words
- * of the shell input up to EOF or a line the same as "term".
- * Unit 0 should have been closed before this call.
- */
-void
-heredoc(Char *term)
-{
- eChar c;
- Char *Dv[2];
- struct Strbuf lbuf = Strbuf_INIT, mbuf = Strbuf_INIT;
- Char obuf[BUFSIZE + 1];
-#define OBUF_END (obuf + sizeof(obuf) / sizeof (*obuf) - 1)
- Char *lbp, *obp, *mbp;
- Char **vp;
- int quoted;
- char *tmp;
-#ifndef WINNT_NATIVE
- struct timeval tv;
-
-again:
-#endif /* WINNT_NATIVE */
- tmp = short2str(shtemp);
-#ifndef O_CREAT
-# define O_CREAT 0
- if (xcreat(tmp, 0600) < 0)
- stderror(ERR_SYSTEM, tmp, strerror(errno));
-#endif
- xclose(0);
-#ifndef O_TEMPORARY
-# define O_TEMPORARY 0
-#endif
-#ifndef O_EXCL
-# define O_EXCL 0
-#endif
- if (xopen(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) ==
- -1) {
- int oerrno = errno;
-#ifndef WINNT_NATIVE
- if (errno == EEXIST) {
- if (unlink(tmp) == -1) {
- (void) gettimeofday(&tv, NULL);
- xfree(shtemp);
- mbp = putn((((int)tv.tv_sec) ^
- ((int)tv.tv_usec) ^ ((int)getpid())) & 0x00ffffff);
- shtemp = Strspl(STRtmpsh, mbp);
- xfree(mbp);
- }
- goto again;
- }
-#endif /* WINNT_NATIVE */
- (void) unlink(tmp);
- errno = oerrno;
- stderror(ERR_SYSTEM, tmp, strerror(errno));
- }
- (void) unlink(tmp); /* 0 0 inode! */
- Dv[0] = term;
- Dv[1] = NULL;
- gflag = 0;
- trim(Dv);
- rscan(Dv, Dtestq);
- quoted = gflag;
- obp = obuf;
- obuf[BUFSIZE] = 0;
- inheredoc = 1;
- cleanup_push(&inheredoc, inheredoc_cleanup);
-#ifdef WINNT_NATIVE
- __dup_stdin = 1;
-#endif /* WINNT_NATIVE */
-#ifdef O_TEXT
- setmode(1, O_TEXT);
-#endif
-#ifdef O_BINARY
- setmode(0, O_BINARY);
-#endif
- cleanup_push(&lbuf, Strbuf_cleanup);
- cleanup_push(&mbuf, Strbuf_cleanup);
- for (;;) {
- Char **words;
-
- /*
- * Read up a line
- */
- lbuf.len = 0;
- for (;;) {
- c = readc(1); /* 1 -> Want EOF returns */
- if (c == CHAR_ERR || c == '\n')
- break;
- if ((c &= TRIM) != 0)
- Strbuf_append1(&lbuf, (Char) c);
- }
- Strbuf_terminate(&lbuf);
-
- /*
- * Check for EOF or compare to terminator -- before expansion
- */
- if (c == CHAR_ERR || eq(lbuf.s, term))
- break;
-
- /*
- * If term was quoted or -n just pass it on
- */
- if (quoted || noexec) {
- Strbuf_append1(&lbuf, '\n');
- Strbuf_terminate(&lbuf);
- for (lbp = lbuf.s; (c = *lbp++) != 0;) {
- *obp++ = (Char) c;
- if (obp == OBUF_END) {
- tmp = short2str(obuf);
- (void) xwrite(0, tmp, strlen (tmp));
- obp = obuf;
- }
- }
- continue;
- }
-
- /*
- * Term wasn't quoted so variable and then command expand the input
- * line
- */
- Dcp = lbuf.s;
- Dvp = Dv + 1;
- mbuf.len = 0;
- for (;;) {
- c = DgetC(DODOL);
- if (c == DEOF)
- break;
- if ((c &= TRIM) == 0)
- continue;
- /* \ quotes \ $ ` here */
- if (c == '\\') {
- c = DgetC(0);
- if (!any("$\\`", c))
- unDgetC(c | QUOTE), c = '\\';
- else
- c |= QUOTE;
- }
- Strbuf_append1(&mbuf, (Char) c);
- }
- Strbuf_terminate(&mbuf);
-
- /*
- * If any ` in line do command substitution
- */
- mbp = mbuf.s;
- if (Strchr(mbp, '`') != NULL) {
- /*
- * 1 arg to dobackp causes substitution to be literal. Words are
- * broken only at newlines so that all blanks and tabs are
- * preserved. Blank lines (null words) are not discarded.
- */
- words = dobackp(mbp, 1);
- }
- else
- /* Setup trivial vector similar to return of dobackp */
- Dv[0] = mbp, Dv[1] = NULL, words = Dv;
-
- /*
- * Resurrect the words from the command substitution each separated by
- * a newline. Note that the last newline of a command substitution
- * will have been discarded, but we put a newline after the last word
- * because this represents the newline after the last input line!
- */
- for (vp= words; *vp; vp++) {
- for (mbp = *vp; *mbp; mbp++) {
- *obp++ = *mbp & TRIM;
- if (obp == OBUF_END) {
- tmp = short2str(obuf);
- (void) xwrite(0, tmp, strlen (tmp));
- obp = obuf;
- }
- }
- *obp++ = '\n';
- if (obp == OBUF_END) {
- tmp = short2str(obuf);
- (void) xwrite(0, tmp, strlen (tmp));
- obp = obuf;
- }
- }
- if (words != Dv)
- blkfree(words);
- }
- *obp = 0;
- tmp = short2str(obuf);
- (void) xwrite(0, tmp, strlen (tmp));
- (void) lseek(0, (off_t) 0, L_SET);
- cleanup_until(&inheredoc);
-}
OpenPOWER on IntegriCloud