diff options
Diffstat (limited to 'contrib/tcsh/sh.dol.c')
-rw-r--r-- | contrib/tcsh/sh.dol.c | 698 |
1 files changed, 292 insertions, 406 deletions
diff --git a/contrib/tcsh/sh.dol.c b/contrib/tcsh/sh.dol.c index f5ee7eb..73ac3b2 100644 --- a/contrib/tcsh/sh.dol.c +++ b/contrib/tcsh/sh.dol.c @@ -1,4 +1,4 @@ -/* $Header: /src/pub/tcsh/sh.dol.c,v 3.55 2004/12/25 21:15:06 christos Exp $ */ +/* $Header: /p/tcsh/cvsroot/tcsh/sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $ */ /* * sh.dol.c: Variable substitutions */ @@ -32,7 +32,7 @@ */ #include "sh.h" -RCSID("$Id: sh.dol.c,v 3.55 2004/12/25 21:15:06 christos Exp $") +RCSID("$tcsh: sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $") /* * C shell @@ -49,7 +49,7 @@ RCSID("$Id: sh.dol.c,v 3.55 2004/12/25 21:15:06 christos Exp $") static Char Dpeekc; /* Peek for DgetC */ static eChar Dpeekrd; /* Peek for Dreadc */ -static Char *Dcp, **Dvp; /* Input vector for Dreadc */ +static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */ #define DEOF CHAR_ERR @@ -63,41 +63,31 @@ static Char *Dcp, **Dvp; /* Input vector for Dreadc */ * words within this expansion, the count of remaining words, and the * information about any : modifier which is being applied. */ -#define MAXWLEN (BUFSIZE - 4) -#ifndef COMPAT -#define MAXMOD MAXWLEN /* This cannot overflow */ -#endif /* COMPAT */ static Char *dolp; /* Remaining chars from this word */ static Char **dolnxt; /* Further words */ static int dolcnt; /* Count of further words */ -#ifdef COMPAT -static Char dolmod; /* : modifier character */ -#else -static Char dolmod[MAXMOD]; /* : modifier character */ -static int dolnmod; /* Number of modifiers */ -#endif /* COMPAT */ -static int dolmcnt; /* :gx -> 10000, else 1 */ -static int dolwcnt; /* :ax -> 10000, else 1 */ - -static void Dfix2 __P((Char **)); -static Char *Dpack __P((Char *, Char *)); -static int Dword __P((void)); -static void dolerror __P((Char *)); -static eChar DgetC __P((int)); -static void Dgetdol __P((void)); -static void fixDolMod __P((void)); -static void setDolp __P((Char *)); -static void unDredc __P((eChar)); -static eChar Dredc __P((void)); -static void Dtestq __P((Char)); +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(t) - struct command *t; +Dfix(struct command *t) { Char **pp; Char *p; @@ -108,10 +98,11 @@ Dfix(t) for (pp = t->t_dcom; (p = *pp++) != NULL;) { for (; *p; p++) { if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */ - Dfix2(t->t_dcom); /* found one */ + Char **expanded; + + expanded = Dfix2(t->t_dcom); /* found one */ blkfree(t->t_dcom); - t->t_dcom = gargv; - gargv = 0; + t->t_dcom = expanded; return; } } @@ -122,52 +113,54 @@ Dfix(t) * $ substitute one word, for i/o redirection */ Char * -Dfix1(cp) - Char *cp; +Dfix1(Char *cp) { - Char *Dv[2]; + Char *Dv[2], **expanded; if (noexec) return (0); Dv[0] = cp; Dv[1] = NULL; - Dfix2(Dv); - if (gargc != 1) { + expanded = Dfix2(Dv); + if (expanded[0] == NULL || expanded[1] != NULL) { + blkfree(expanded); setname(short2str(cp)); stderror(ERR_NAME | ERR_AMBIG); } - cp = Strsave(gargv[0]); - blkfree(gargv), gargv = 0; + cp = Strsave(expanded[0]); + blkfree(expanded); return (cp); } /* * Subroutine to do actual fixing after state initialization. */ -static void -Dfix2(v) - Char **v; +static Char ** +Dfix2(Char *const *v) { - ginit(); /* Initialize glob's area pointers */ + 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 (...) */ - while (Dword()) + 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 Char * -Dpack(wbuf, wp) - Char *wbuf, *wp; +static int +Dpack(struct Strbuf *wbuf) { eChar c; - int i = MAXWLEN - (int) (wp - wbuf); for (;;) { c = DgetC(DODOL); @@ -175,9 +168,7 @@ Dpack(wbuf, wp) c = DgetC(0); if (c == DEOF) { unDredc(c); - *wp = 0; - Gcat(STRNULL, wbuf); - return (NULL); + return 1; } if (c == '\n') c = ' '; @@ -186,21 +177,15 @@ Dpack(wbuf, wp) } if (c == DEOF) { unDredc(c); - *wp = 0; - Gcat(STRNULL, wbuf); - return (NULL); + return 1; } if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */ unDgetC(c); if (cmap(c, QUOTES)) - return (wp); - *wp++ = 0; - Gcat(STRNULL, wbuf); - return (NULL); + return 0; + return 1; } - if (--i <= 0) - stderror(ERR_WTOOLONG); - *wp++ = (Char) c; + Strbuf_append1(wbuf, (Char) c); } } @@ -211,40 +196,37 @@ Dpack(wbuf, wp) * Rather, DgetC will return a DEOF when we hit the end-of-input. */ static int -Dword() +Dword(struct blk_buf *bb) { eChar c, c1; - Char wbuf[BUFSIZE]; - Char *wp = wbuf; - int i = MAXWLEN; + struct Strbuf wbuf = Strbuf_INIT; int dolflg; - int sofar = 0, done = 0; + int sofar = 0; - while (!done) { - done = 1; + cleanup_push(&wbuf, Strbuf_cleanup); + for (;;) { c = DgetC(DODOL); switch (c) { case DEOF: - if (sofar == 0) + if (sofar == 0) { + cleanup_until(&wbuf); return (0); + } /* finish this word and catch the code above the next time */ unDredc(c); /*FALLTHROUGH*/ case '\n': - *wp = 0; - Gcat(STRNULL, wbuf); - return (1); + goto end; case ' ': case '\t': - done = 0; - break; + continue; case '`': /* We preserve ` quotations which are done yet later */ - *wp++ = (Char) c, --i; + Strbuf_append1(&wbuf, (Char) c); /*FALLTHROUGH*/ case '\'': case '"': @@ -261,12 +243,9 @@ Dword() if (c == '\n' || c == DEOF) stderror(ERR_UNMATCHED, (int)c1); if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) { - if ((wp[-1] & TRIM) == '\\') - --wp; - ++i; + if (wbuf.len != 0 && (wbuf.s[wbuf.len - 1] & TRIM) == '\\') + wbuf.len--; } - if (--i <= 0) - stderror(ERR_WTOOLONG); switch (c1) { case '"': @@ -274,17 +253,17 @@ Dword() * Leave any `s alone for later. Other chars are all * quoted, thus `...` can tell it was within "...". */ - *wp++ = c == '`' ? '`' : c | QUOTE; + Strbuf_append1(&wbuf, c == '`' ? '`' : c | QUOTE); break; case '\'': /* Prevent all further interpretation */ - *wp++ = c | QUOTE; + Strbuf_append1(&wbuf, c | QUOTE); break; case '`': /* Leave all text alone for later */ - *wp++ = (Char) c; + Strbuf_append1(&wbuf, (Char) c); break; default: @@ -292,63 +271,33 @@ Dword() } } if (c1 == '`') - *wp++ = '`' /* i--; eliminated */; + Strbuf_append1(&wbuf, '`'); sofar = 1; - if ((wp = Dpack(wbuf, wp)) == NULL) - return (1); - else { -#ifdef masscomp - /* - * Avoid a nasty message from the RTU 4.1A & RTU 5.0 compiler concerning - * the "overuse of registers". According to the compiler release notes, - * incorrect code may be produced unless the offending expression is - * rewritten. Therefore, we can't just ignore it, DAS DEC-90. - */ - i = MAXWLEN; - i -= (int) (wp - wbuf); -#else /* !masscomp */ - i = MAXWLEN - (int) (wp - wbuf); -#endif /* masscomp */ - done = 0; - } - break; + if (Dpack(&wbuf) != 0) + goto end; + continue; case '\\': c = DgetC(0); /* No $ subst! */ - if (c == '\n' || c == DEOF) { - done = 0; - break; - } + if (c == '\n' || c == DEOF) + continue; c |= QUOTE; break; default: break; } - if (done) { - unDgetC(c); - sofar = 1; - if ((wp = Dpack(wbuf, wp)) == NULL) - return (1); - else { -#ifdef masscomp - /* - * Avoid a nasty message from the RTU 4.1A & RTU 5.0 compiler concerning - * the "overuse of registers". According to the compiler release notes, - * incorrect code may be produced unless the offending expression is - * rewritten. Therefore, we can't just ignore it, DAS DEC-90. - */ - i = MAXWLEN; - i -= (int) (wp - wbuf); -#else /* !masscomp */ - i = MAXWLEN - (int) (wp - wbuf); -#endif /* masscomp */ - done = 0; - } - } + unDgetC(c); + sofar = 1; + if (Dpack(&wbuf) != 0) + goto end; } - /* Really NOTREACHED */ - return (0); + + end: + cleanup_ignore(&wbuf); + cleanup_until(&wbuf); + bb_append(bb, Strbuf_finish(&wbuf)); + return 1; } @@ -358,8 +307,7 @@ Dword() * QUOTEd so that it will not be recognized above. */ static eChar -DgetC(flag) - int flag; +DgetC(int flag) { Char c; @@ -368,12 +316,8 @@ top: Dpeekc = 0; return (c); } - if (lap) { - c = *lap++ & (QUOTE | TRIM); - if (c == 0) { - lap = 0; - goto top; - } + if (lap < labuf.len) { + c = labuf.s[lap++] & (QUOTE | TRIM); quotspec: if (cmap(c, QUOTES)) return (c | QUOTE); @@ -407,8 +351,7 @@ static struct varent nulargv = {nulvec, STRargv, VAR_READWRITE, { NULL, NULL, NULL }, 0 }; static void -dolerror(s) - Char *s; +dolerror(Char *s) { setname(short2str(s)); stderror(ERR_NAME | ERR_RANGE); @@ -419,23 +362,23 @@ dolerror(s) * Ugh. */ static void -Dgetdol() +Dgetdol(void) { Char *np; struct varent *vp = NULL; - Char name[4 * MAXVARLEN + 1]; + struct Strbuf name = Strbuf_INIT; eChar c, sc; int subscr = 0, lwb = 1, upb = 0; int dimen = 0, bitset = 0, length = 0; - Char wbuf[BUFSIZE]; static Char *dolbang = NULL; -#ifdef COMPAT - dolmod = dolmcnt = dolwcnt = 0; -#else - dolnmod = dolmcnt = dolwcnt = 0; -#endif /* COMPAT */ + 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) == '#') @@ -450,110 +393,91 @@ Dgetdol() if (dimen || bitset || length) stderror(ERR_SYNTAX); if (backpid != 0) { - if (dolbang) - xfree((ptr_t) dolbang); + 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; -#ifdef COHERENT - /* Coherent compiler doesn't allow case-labels that are not - constant-expressions */ -#ifdef WIDE_STRINGS - case 0x4000003C: /* Does Coherent have 32-bit int at all? */ -#elif defined (SHORT_STRINGS) - case 0100074: -#else /* !SHORT_STRINGS */ - case 0274: -#endif -#else /* !COHERENT */ - case '<'|QUOTE: -#endif + 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; -#ifdef BSDSIGS - sigmask_t omask = sigsetmask(sigblock(0) & ~sigmask(SIGINT)); -#else /* !BSDSIGS */ - (void) sigrelse(SIGINT); -#endif /* BSDSIGS */ - np = wbuf; - while (force_read(OLDSTD, cbuf + cbp++, 1) == 1) { + for (;;) { int len; + ssize_t res; + Char wc; - len = normal_mbtowc(np, cbuf, cbp); + 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 */ - *np = (unsigned char)*cbuf | INVALID_BYTE; + 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 (np >= &wbuf[BUFSIZE - 1]) - stderror(ERR_LTOOLONG); - if (*np == '\n') + if (wc == '\n') break; - np++; + Strbuf_append1(&wbuf, wc); } while (cbp != 0) { - *np = (unsigned char)*cbuf; - if (np >= &wbuf[BUFSIZE - 1]) - stderror(ERR_LTOOLONG); - if (*np == '\n') + 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; - np++; - cbp--; - memmove(cbuf, cbuf + 1, cbp); + Strbuf_append1(&wbuf, wc); } - *np = 0; -#ifdef BSDSIGS - (void) sigsetmask(omask); -#else /* !BSDSIGS */ - (void) sighold(SIGINT); -#endif /* BSDSIGS */ + Strbuf_terminate(&wbuf); } -#ifdef COMPAT - /* - * KLUDGE: dolmod is set here because it will cause setDolp to call - * domod and thus to copy wbuf. Otherwise setDolp would use it - * directly. If we saved it ourselves, no one would know when to free - * it. The actual function of the 'q' causes filename expansion not to - * be done on the interpolated value. - */ - /* - * If we do that, then other modifiers don't work. - * in addition, let the user specify :q if wanted - * [christos] - */ -/*old*/ dolmod = 'q'; -/*new*/ dolmod[dolnmod++] = 'q'; - dolmcnt = 10000; -#endif /* COMPAT */ - fixDolMod(); - setDolp(wbuf); + setDolp(wbuf.s); /* Kept allocated until next $< expansion */ + cleanup_until(&name); goto eatbrac; + } case '*': - (void) Strcpy(name, STRargv); + Strbuf_append(&name, STRargv); + Strbuf_terminate(&name); vp = adrof(STRargv); subscr = -1; /* Prevent eating [...] */ break; @@ -563,7 +487,8 @@ Dgetdol() np = dimen ? STRargv : (bitset ? STRstatus : NULL); if (np) { bitset = 0; - (void) Strcpy(name, np); + Strbuf_append(&name, np); + Strbuf_terminate(&name); vp = adrof(np); subscr = -1; /* Prevent eating [...] */ unDredc(c); @@ -574,7 +499,6 @@ Dgetdol() /*NOTREACHED*/ default: - np = name; if (Isdigit(c)) { if (dimen) stderror(ERR_NOTALLOWED, "$#<num>"); @@ -582,28 +506,27 @@ Dgetdol() do { subscr = subscr * 10 + c - '0'; c = DgetC(0); - } while (Isdigit(c)); + } 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) { - Char *cp; - length = NLSChars(ffile); - cp = putn(length); - addla(cp); - xfree((ptr_t) cp); + length = Strlen(ffile); + addla(putn(length)); } else { fixDolMod(); setDolp(ffile); } + cleanup_until(&name); goto eatbrac; } #if 0 @@ -615,15 +538,17 @@ Dgetdol() vp = adrof(STRargv); if (vp == 0) { vp = &nulargv; + cleanup_until(&name); goto eatmod; } break; } - if (!alnum(c)) { + if (c == DEOF || !alnum(c)) { np = dimen ? STRargv : (bitset ? STRstatus : NULL); if (np) { bitset = 0; - (void) Strcpy(name, np); + Strbuf_append(&name, np); + Strbuf_terminate(&name); vp = adrof(np); subscr = -1; /* Prevent eating [...] */ unDredc(c); @@ -633,46 +558,52 @@ Dgetdol() stderror(ERR_VARALNUM); } for (;;) { - *np++ = (Char) c; + Strbuf_append1(&name, (Char) c); c = DgetC(0); - if (!alnum(c)) + if (c == DEOF || !alnum(c)) break; - if (np >= &name[MAXVARLEN]) - stderror(ERR_VARTOOLONG); } - *np++ = 0; + Strbuf_terminate(&name); unDredc(c); - vp = adrof(name); + vp = adrof(name.s); } if (bitset) { - dolp = (vp || getenv(short2str(name))) ? STR1 : STR0; + dolp = (vp || getenv(short2str(name.s))) ? STR1 : STR0; + cleanup_until(&name); goto eatbrac; } if (vp == NULL || vp->vec == NULL) { - np = str2short(getenv(short2str(name))); + np = str2short(getenv(short2str(name.s))); if (np) { + static Char *env_val; /* = NULL; */ + + cleanup_until(&name); fixDolMod(); - setDolp(np); + xfree(env_val); + env_val = Strsave(np); + setDolp(env_val); goto eatbrac; } - udvar(name); + udvar(name.s); /* NOTREACHED */ } + cleanup_until(&name); c = DgetC(0); upb = blklen(vp->vec); if (dimen == 0 && subscr == 0 && c == '[') { - np = name; + 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); - if (np >= &name[sizeof(name) / sizeof(Char) - 2]) - stderror(ERR_VARTOOLONG); - *np++ = (Char) c; + Strbuf_append1(&name, (Char) c); } - *np = 0, np = name; + Strbuf_terminate(&name); + np = name.s; if (dolp || dolcnt) /* $ exp must end before ] */ stderror(ERR_EXPORD); if (!*np) @@ -683,6 +614,7 @@ Dgetdol() 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; } @@ -703,6 +635,7 @@ Dgetdol() while (Isdigit(*np)) i = i * 10 + *np++ - '0'; if (i < 0 || i > upb) { + cleanup_until(&name); dolerror(vp->v_name); return; } @@ -714,6 +647,7 @@ Dgetdol() } if (lwb == 0) { if (upb != 0) { + cleanup_until(&name); dolerror(vp->v_name); return; } @@ -721,6 +655,7 @@ Dgetdol() } if (*np) stderror(ERR_SYNTAX); + cleanup_until(&name); } else { if (subscr > 0) { @@ -732,35 +667,26 @@ Dgetdol() unDredc(c); } if (dimen) { - Char *cp = putn(upb - lwb + 1); - /* this is a kludge. It prevents Dgetdol() from */ /* pushing erroneous ${#<error> values into the labuf. */ if (sc == '{') { c = Dredc(); if (c != '}') - { - xfree((ptr_t) cp); stderror(ERR_MISSING, '}'); - return; - } unDredc(c); } - addla(cp); - xfree((ptr_t) cp); + addla(putn(upb - lwb + 1)); } else if (length) { int i; - Char *cp; + for (i = lwb - 1, length = 0; i < upb; i++) - length += NLSChars(vp->vec[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 - cp = putn(length); - addla(cp); - xfree((ptr_t) cp); + addla(putn(length)); } else { eatmod: @@ -777,45 +703,43 @@ eatbrac: } static void -fixDolMod() +fixDolMod(void) { eChar c; c = DgetC(0); if (c == ':') { -#ifndef COMPAT do { -#endif /* COMPAT */ - c = DgetC(0), dolmcnt = 1, dolwcnt = 1; + c = DgetC(0), dolmcnt = 1, dol_flag_a = 0; if (c == 'g' || c == 'a') { if (c == 'g') - dolmcnt = 10000; + dolmcnt = INT_MAX; else - dolwcnt = 10000; + dol_flag_a = 1; c = DgetC(0); } - if ((c == 'g' && dolmcnt != 10000) || - (c == 'a' && dolwcnt != 10000)) { + if ((c == 'g' && dolmcnt != INT_MAX) || + (c == 'a' && dol_flag_a == 0)) { if (c == 'g') - dolmcnt = 10000; + dolmcnt = INT_MAX; else - dolwcnt = 10000; - c = DgetC(0); + dol_flag_a = 1; + c = DgetC(0); } if (c == 's') { /* [eichin:19910926.0755EST] */ int delimcnt = 2; eChar delim = DgetC(0); - dolmod[dolnmod++] = (Char) c; - dolmod[dolnmod++] = (Char) delim; - - if (!delim || letter(delim) + 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) { - dolmod[dolnmod++] = (Char) c; + Strbuf_append1(&dolmod, (Char) c); if(c == delim) delimcnt--; if(!delimcnt) break; } @@ -827,148 +751,110 @@ fixDolMod() } if (!any("luhtrqxes", c)) stderror(ERR_BADMOD, (int)c); -#ifndef COMPAT - dolmod[dolnmod++] = (Char) c; -#else - dolmod = (Char) c; -#endif /* COMPAT */ + Strbuf_append1(&dolmod, (Char) c); if (c == 'q') - dolmcnt = 10000; -#ifndef COMPAT + dolmcnt = INT_MAX; } while ((c = DgetC(0)) == ':'); unDredc(c); -#endif /* COMPAT */ } else unDredc(c); } static void -setDolp(cp) - Char *cp; +setDolp(Char *cp) { Char *dp; -#ifndef COMPAT - int i; -#endif /* COMPAT */ - -#ifdef COMPAT - if (dolmod == 0 || dolmcnt == 0) { -#else - if (dolnmod == 0 || dolmcnt == 0) { -#endif /* COMPAT */ - for (dp = cp; *dp; dp++) { - if (NLSSize(dp, -1) != 1) { - addla(cp); - return; - } - } + size_t i; + + if (dolmod.len == 0 || dolmcnt == 0) { dolp = cp; return; } -#ifdef COMPAT - dp = domod(cp, dolmod); -#else - dp = cp = Strsave(cp); - for (i = 0; i < dolnmod; i++) { + cp = Strsave(cp); + for (i = 0; i < dolmod.len; i++) { + int didmod = 0; + /* handle s// [eichin:19910926.0510EST] */ - if(dolmod[i] == 's') { + if(dolmod.s[i] == 's') { Char delim; Char *lhsub, *rhsub, *np; size_t lhlen = 0, rhlen = 0; - int didmod = 0; - - delim = dolmod[++i]; + + delim = dolmod.s[++i]; if (!delim || letter(delim) || Isdigit(delim) || any(" \t\n", delim)) { seterror(ERR_BADSUBST); break; } - lhsub = &dolmod[++i]; - while(dolmod[i] != delim && dolmod[++i]) { + lhsub = &dolmod.s[++i]; + while(dolmod.s[i] != delim && dolmod.s[++i]) { lhlen++; } - dolmod[i] = 0; - rhsub = &dolmod[++i]; - while(dolmod[i] != delim && dolmod[++i]) { + dolmod.s[i] = 0; + rhsub = &dolmod.s[++i]; + while(dolmod.s[i] != delim && dolmod.s[++i]) { rhlen++; } - dolmod[i] = 0; + dolmod.s[i] = 0; + strip(lhsub); + strip(cp); + dp = cp; do { - strip(lhsub); - strip(cp); - dp = Strstr(cp, lhsub); + dp = Strstr(dp, lhsub); if (dp) { - np = (Char *) xmalloc((size_t) - ((Strlen(cp) + 1 - lhlen + rhlen) * - sizeof(Char))); - (void) Strncpy(np, cp, (size_t) (dp - cp)); - (void) Strcpy(np + (dp - cp), rhsub); - (void) Strcpy(np + (dp - cp) + rhlen, dp + lhlen); - - xfree((ptr_t) cp); - dp = cp = np; + 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 (dolwcnt == 10000); + while (dol_flag_a != 0); /* * restore dolmod for additional words */ - dolmod[i] = rhsub[-1] = (Char) delim; - if (didmod) - dolmcnt--; -#ifdef notdef - else - break; -#endif + dolmod.s[i] = rhsub[-1] = (Char) delim; } else { - int didmod = 0; do { - if ((dp = domod(cp, dolmod[i])) != NULL) { + if ((dp = domod(cp, dolmod.s[i])) != NULL) { didmod = 1; if (Strcmp(cp, dp) == 0) { - xfree((ptr_t) cp); + xfree(cp); cp = dp; break; } else { - xfree((ptr_t) cp); + xfree(cp); cp = dp; } } else break; } - while (dolwcnt == 10000); - dp = cp; - if (didmod) - dolmcnt--; + while (dol_flag_a != 0); + } + if (didmod && dolmcnt != INT_MAX) + dolmcnt--; #ifdef notdef - else - break; + else + break; #endif - } } -#endif /* COMPAT */ - - if (dp) { -#ifdef COMPAT - dolmcnt--; -#endif /* COMPAT */ - addla(dp); - xfree((ptr_t) dp); - } -#ifndef COMPAT - else - addla(cp); -#endif /* COMPAT */ + + addla(cp); dolp = STRNULL; if (seterr) @@ -976,15 +862,14 @@ setDolp(cp) } static void -unDredc(c) - eChar c; +unDredc(eChar c) { Dpeekrd = c; } static eChar -Dredc() +Dredc(void) { Char c; @@ -1002,28 +887,36 @@ Dredc() return (' '); } +static int gflag; + static void -Dtestq(c) - Char c; +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(term) - Char *term; +heredoc(Char *term) { eChar c; Char *Dv[2]; - Char obuf[BUFSIZE + 1], lbuf[BUFSIZE], mbuf[BUFSIZE]; - int ocnt, lcnt, mcnt; + 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; @@ -1036,24 +929,28 @@ again: tmp = short2str(shtemp); #ifndef O_CREAT # define O_CREAT 0 - if (creat(tmp, 0600) < 0) + if (xcreat(tmp, 0600) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); #endif - (void) close(0); + xclose(0); #ifndef O_TEMPORARY # define O_TEMPORARY 0 #endif #ifndef O_EXCL # define O_EXCL 0 #endif - if (open(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) == -1) { + 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); - shtemp = Strspl(STRtmpsh, putn((((int)tv.tv_sec) ^ - ((int)tv.tv_usec) ^ ((int)getpid())) & 0x00ffffff)); + xfree(shtemp); + mbp = putn((((int)tv.tv_sec) ^ + ((int)tv.tv_usec) ^ ((int)getpid())) & 0x00ffffff); + shtemp = Strspl(STRtmpsh, mbp); + xfree(mbp); } goto again; } @@ -1069,10 +966,10 @@ again: trim(Dv); rscan(Dv, Dtestq); quoted = gflag; - ocnt = BUFSIZE; obp = obuf; obuf[BUFSIZE] = 0; inheredoc = 1; + cleanup_push(&inheredoc, inheredoc_cleanup); #ifdef WINNT_NATIVE __dup_stdin = 1; #endif /* WINNT_NATIVE */ @@ -1082,51 +979,42 @@ again: #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 */ - lbp = lbuf; - lcnt = BUFSIZE - 4; + lbuf.len = 0; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c == CHAR_ERR || c == '\n') break; - if ((c &= TRIM) != 0) { - *lbp++ = (Char) c; - if (--lcnt < 0) { - setname("<<"); - stderror(ERR_NAME | ERR_OVERFLOW); - } - } + if ((c &= TRIM) != 0) + Strbuf_append1(&lbuf, (Char) c); } - *lbp = 0; + Strbuf_terminate(&lbuf); /* * Check for EOF or compare to terminator -- before expansion */ - if (c == CHAR_ERR || eq(lbuf, term)) { - *obp = 0; - tmp = short2str(obuf); - (void) write(0, tmp, strlen (tmp)); - (void) lseek(0, (off_t) 0, L_SET); - inheredoc = 0; - return; - } + if (c == CHAR_ERR || eq(lbuf.s, term)) + break; /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { - *lbp++ = '\n'; - *lbp = 0; - for (lbp = lbuf; (c = *lbp++) != 0;) { + Strbuf_append1(&lbuf, '\n'); + Strbuf_terminate(&lbuf); + for (lbp = lbuf.s; (c = *lbp++) != 0;) { *obp++ = (Char) c; - if (--ocnt == 0) { + if (obp == OBUF_END) { tmp = short2str(obuf); - (void) write(0, tmp, strlen (tmp)); + (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; - ocnt = BUFSIZE; } } continue; @@ -1136,10 +1024,9 @@ again: * Term wasn't quoted so variable and then command expand the input * line */ - Dcp = lbuf; + Dcp = lbuf.s; Dvp = Dv + 1; - mbp = mbuf; - mcnt = BUFSIZE - 4; + mbuf.len = 0; for (;;) { c = DgetC(DODOL); if (c == DEOF) @@ -1154,29 +1041,25 @@ again: else c |= QUOTE; } - *mbp++ = (Char) c; - if (--mcnt == 0) { - setname("<<"); - stderror(ERR_NAME | ERR_OVERFLOW); - } + Strbuf_append1(&mbuf, (Char) c); } - *mbp++ = 0; + Strbuf_terminate(&mbuf); /* * If any ` in line do command substitution */ - mbp = mbuf; + 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. */ - vp = dobackp(mbuf, 1); + words = dobackp(mbp, 1); } else /* Setup trivial vector similar to return of dobackp */ - Dv[0] = mbp, Dv[1] = NULL, vp = Dv; + Dv[0] = mbp, Dv[1] = NULL, words = Dv; /* * Resurrect the words from the command substitution each separated by @@ -1184,25 +1067,28 @@ again: * 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; vp++) { + for (vp= words; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; - if (--ocnt == 0) { + if (obp == OBUF_END) { tmp = short2str(obuf); - (void) write(0, tmp, strlen (tmp)); + (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; - ocnt = BUFSIZE; } } *obp++ = '\n'; - if (--ocnt == 0) { + if (obp == OBUF_END) { tmp = short2str(obuf); - (void) write(0, tmp, strlen (tmp)); + (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; - ocnt = BUFSIZE; } } - if (pargv) - blkfree(pargv), pargv = 0; + 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); } |