17d8fb588SMatthias Schmidt /*
27d8fb588SMatthias Schmidt * sh.dol.c: Variable substitutions
37d8fb588SMatthias Schmidt */
47d8fb588SMatthias Schmidt /*-
57d8fb588SMatthias Schmidt * Copyright (c) 1980, 1991 The Regents of the University of California.
67d8fb588SMatthias Schmidt * All rights reserved.
77d8fb588SMatthias Schmidt *
87d8fb588SMatthias Schmidt * Redistribution and use in source and binary forms, with or without
97d8fb588SMatthias Schmidt * modification, are permitted provided that the following conditions
107d8fb588SMatthias Schmidt * are met:
117d8fb588SMatthias Schmidt * 1. Redistributions of source code must retain the above copyright
127d8fb588SMatthias Schmidt * notice, this list of conditions and the following disclaimer.
137d8fb588SMatthias Schmidt * 2. Redistributions in binary form must reproduce the above copyright
147d8fb588SMatthias Schmidt * notice, this list of conditions and the following disclaimer in the
157d8fb588SMatthias Schmidt * documentation and/or other materials provided with the distribution.
167d8fb588SMatthias Schmidt * 3. Neither the name of the University nor the names of its contributors
177d8fb588SMatthias Schmidt * may be used to endorse or promote products derived from this software
187d8fb588SMatthias Schmidt * without specific prior written permission.
197d8fb588SMatthias Schmidt *
207d8fb588SMatthias Schmidt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217d8fb588SMatthias Schmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227d8fb588SMatthias Schmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237d8fb588SMatthias Schmidt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247d8fb588SMatthias Schmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257d8fb588SMatthias Schmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267d8fb588SMatthias Schmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277d8fb588SMatthias Schmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287d8fb588SMatthias Schmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297d8fb588SMatthias Schmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307d8fb588SMatthias Schmidt * SUCH DAMAGE.
317d8fb588SMatthias Schmidt */
327d8fb588SMatthias Schmidt #include "sh.h"
33*d6ab524cSAntonio Huete Jimenez #include "ed.h"
34*d6ab524cSAntonio Huete Jimenez #include "tw.h"
357d8fb588SMatthias Schmidt
367d8fb588SMatthias Schmidt /*
377d8fb588SMatthias Schmidt * C shell
387d8fb588SMatthias Schmidt */
397d8fb588SMatthias Schmidt
407d8fb588SMatthias Schmidt /*
417d8fb588SMatthias Schmidt * These routines perform variable substitution and quoting via ' and ".
427d8fb588SMatthias Schmidt * To this point these constructs have been preserved in the divided
437d8fb588SMatthias Schmidt * input words. Here we expand variables and turn quoting via ' and " into
447d8fb588SMatthias Schmidt * QUOTE bits on characters (which prevent further interpretation).
457d8fb588SMatthias Schmidt * If the `:q' modifier was applied during history expansion, then
467d8fb588SMatthias Schmidt * some QUOTEing may have occurred already, so we dont "trim()" here.
477d8fb588SMatthias Schmidt */
487d8fb588SMatthias Schmidt
4994afa86dSJohn Marino static eChar Dpeekc; /* Peek for DgetC */
507d8fb588SMatthias Schmidt static eChar Dpeekrd; /* Peek for Dreadc */
517d8fb588SMatthias Schmidt static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */
527d8fb588SMatthias Schmidt
537d8fb588SMatthias Schmidt #define DEOF CHAR_ERR
547d8fb588SMatthias Schmidt
557d8fb588SMatthias Schmidt #define unDgetC(c) Dpeekc = c
567d8fb588SMatthias Schmidt
577d8fb588SMatthias Schmidt #define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
587d8fb588SMatthias Schmidt
597d8fb588SMatthias Schmidt /*
607d8fb588SMatthias Schmidt * The following variables give the information about the current
617d8fb588SMatthias Schmidt * $ expansion, recording the current word position, the remaining
627d8fb588SMatthias Schmidt * words within this expansion, the count of remaining words, and the
637d8fb588SMatthias Schmidt * information about any : modifier which is being applied.
647d8fb588SMatthias Schmidt */
657d8fb588SMatthias Schmidt static Char *dolp; /* Remaining chars from this word */
667d8fb588SMatthias Schmidt static Char **dolnxt; /* Further words */
677d8fb588SMatthias Schmidt static int dolcnt; /* Count of further words */
687d8fb588SMatthias Schmidt static struct Strbuf dolmod; /* = Strbuf_INIT; : modifier characters */
69*d6ab524cSAntonio Huete Jimenez
70*d6ab524cSAntonio Huete Jimenez static int ndolflags; /* keep track of mod counts for each modifier */
71*d6ab524cSAntonio Huete Jimenez static int *dolmcnts; /* :gx -> INT_MAX, else 1 */
72*d6ab524cSAntonio Huete Jimenez static int *dolaflags; /* :ax -> 1, else 0 */
737d8fb588SMatthias Schmidt
747d8fb588SMatthias Schmidt static Char **Dfix2 (Char *const *);
757d8fb588SMatthias Schmidt static int Dpack (struct Strbuf *);
767d8fb588SMatthias Schmidt static int Dword (struct blk_buf *);
777d8fb588SMatthias Schmidt static void dolerror (Char *);
787d8fb588SMatthias Schmidt static eChar DgetC (int);
797d8fb588SMatthias Schmidt static void Dgetdol (void);
807d8fb588SMatthias Schmidt static void fixDolMod (void);
817d8fb588SMatthias Schmidt static void setDolp (Char *);
827d8fb588SMatthias Schmidt static void unDredc (eChar);
837d8fb588SMatthias Schmidt static eChar Dredc (void);
847d8fb588SMatthias Schmidt static void Dtestq (Char);
857d8fb588SMatthias Schmidt
867d8fb588SMatthias Schmidt /*
877d8fb588SMatthias Schmidt * Fix up the $ expansions and quotations in the
887d8fb588SMatthias Schmidt * argument list to command t.
897d8fb588SMatthias Schmidt */
907d8fb588SMatthias Schmidt void
Dfix(struct command * t)917d8fb588SMatthias Schmidt Dfix(struct command *t)
927d8fb588SMatthias Schmidt {
937d8fb588SMatthias Schmidt Char **pp;
947d8fb588SMatthias Schmidt Char *p;
957d8fb588SMatthias Schmidt
967d8fb588SMatthias Schmidt if (noexec)
977d8fb588SMatthias Schmidt return;
987d8fb588SMatthias Schmidt /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
997d8fb588SMatthias Schmidt for (pp = t->t_dcom; (p = *pp++) != NULL;) {
1007d8fb588SMatthias Schmidt for (; *p; p++) {
1017d8fb588SMatthias Schmidt if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
1027d8fb588SMatthias Schmidt Char **expanded;
1037d8fb588SMatthias Schmidt
1047d8fb588SMatthias Schmidt expanded = Dfix2(t->t_dcom); /* found one */
1057d8fb588SMatthias Schmidt blkfree(t->t_dcom);
1067d8fb588SMatthias Schmidt t->t_dcom = expanded;
1077d8fb588SMatthias Schmidt return;
1087d8fb588SMatthias Schmidt }
1097d8fb588SMatthias Schmidt }
1107d8fb588SMatthias Schmidt }
1117d8fb588SMatthias Schmidt }
1127d8fb588SMatthias Schmidt
1137d8fb588SMatthias Schmidt /*
1147d8fb588SMatthias Schmidt * $ substitute one word, for i/o redirection
1157d8fb588SMatthias Schmidt */
1167d8fb588SMatthias Schmidt Char *
Dfix1(Char * cp)1177d8fb588SMatthias Schmidt Dfix1(Char *cp)
1187d8fb588SMatthias Schmidt {
1197d8fb588SMatthias Schmidt Char *Dv[2], **expanded;
1207d8fb588SMatthias Schmidt
1217d8fb588SMatthias Schmidt if (noexec)
1227d8fb588SMatthias Schmidt return (0);
1237d8fb588SMatthias Schmidt Dv[0] = cp;
1247d8fb588SMatthias Schmidt Dv[1] = NULL;
1257d8fb588SMatthias Schmidt expanded = Dfix2(Dv);
1267d8fb588SMatthias Schmidt if (expanded[0] == NULL || expanded[1] != NULL) {
1277d8fb588SMatthias Schmidt blkfree(expanded);
1287d8fb588SMatthias Schmidt setname(short2str(cp));
1297d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_AMBIG);
1307d8fb588SMatthias Schmidt }
1317d8fb588SMatthias Schmidt cp = Strsave(expanded[0]);
1327d8fb588SMatthias Schmidt blkfree(expanded);
1337d8fb588SMatthias Schmidt return (cp);
1347d8fb588SMatthias Schmidt }
1357d8fb588SMatthias Schmidt
1367d8fb588SMatthias Schmidt /*
1377d8fb588SMatthias Schmidt * Subroutine to do actual fixing after state initialization.
1387d8fb588SMatthias Schmidt */
1397d8fb588SMatthias Schmidt static Char **
Dfix2(Char * const * v)1407d8fb588SMatthias Schmidt Dfix2(Char *const *v)
1417d8fb588SMatthias Schmidt {
14257e3f2b5SSimon 'corecode' Schubert struct blk_buf *bb = bb_alloc();
14357e3f2b5SSimon 'corecode' Schubert Char **vec;
1447d8fb588SMatthias Schmidt
1457d8fb588SMatthias Schmidt Dvp = v;
1467d8fb588SMatthias Schmidt Dcp = STRNULL; /* Setup input vector for Dreadc */
1477d8fb588SMatthias Schmidt unDgetC(0);
1487d8fb588SMatthias Schmidt unDredc(0); /* Clear out any old peeks (at error) */
1497d8fb588SMatthias Schmidt dolp = 0;
1507d8fb588SMatthias Schmidt dolcnt = 0; /* Clear out residual $ expands (...) */
15157e3f2b5SSimon 'corecode' Schubert cleanup_push(bb, bb_free);
15257e3f2b5SSimon 'corecode' Schubert while (Dword(bb))
1537d8fb588SMatthias Schmidt continue;
15457e3f2b5SSimon 'corecode' Schubert cleanup_ignore(bb);
15557e3f2b5SSimon 'corecode' Schubert cleanup_until(bb);
15657e3f2b5SSimon 'corecode' Schubert vec = bb_finish(bb);
15757e3f2b5SSimon 'corecode' Schubert xfree(bb);
15857e3f2b5SSimon 'corecode' Schubert return vec;
1597d8fb588SMatthias Schmidt }
1607d8fb588SMatthias Schmidt
1617d8fb588SMatthias Schmidt /*
1627d8fb588SMatthias Schmidt * Pack up more characters in this word
1637d8fb588SMatthias Schmidt */
1647d8fb588SMatthias Schmidt static int
Dpack(struct Strbuf * wbuf)1657d8fb588SMatthias Schmidt Dpack(struct Strbuf *wbuf)
1667d8fb588SMatthias Schmidt {
1677d8fb588SMatthias Schmidt eChar c;
1687d8fb588SMatthias Schmidt
1697d8fb588SMatthias Schmidt for (;;) {
1707d8fb588SMatthias Schmidt c = DgetC(DODOL);
1717d8fb588SMatthias Schmidt if (c == '\\') {
1727d8fb588SMatthias Schmidt c = DgetC(0);
1737d8fb588SMatthias Schmidt if (c == DEOF) {
1747d8fb588SMatthias Schmidt unDredc(c);
1757d8fb588SMatthias Schmidt return 1;
1767d8fb588SMatthias Schmidt }
1777d8fb588SMatthias Schmidt if (c == '\n')
1787d8fb588SMatthias Schmidt c = ' ';
1797d8fb588SMatthias Schmidt else
1807d8fb588SMatthias Schmidt c |= QUOTE;
1817d8fb588SMatthias Schmidt }
1827d8fb588SMatthias Schmidt if (c == DEOF) {
1837d8fb588SMatthias Schmidt unDredc(c);
1847d8fb588SMatthias Schmidt return 1;
1857d8fb588SMatthias Schmidt }
1867d8fb588SMatthias Schmidt if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
1877d8fb588SMatthias Schmidt unDgetC(c);
1887d8fb588SMatthias Schmidt if (cmap(c, QUOTES))
1897d8fb588SMatthias Schmidt return 0;
1907d8fb588SMatthias Schmidt return 1;
1917d8fb588SMatthias Schmidt }
1927d8fb588SMatthias Schmidt Strbuf_append1(wbuf, (Char) c);
1937d8fb588SMatthias Schmidt }
1947d8fb588SMatthias Schmidt }
1957d8fb588SMatthias Schmidt
1967d8fb588SMatthias Schmidt /*
1977d8fb588SMatthias Schmidt * Get a word. This routine is analogous to the routine
1987d8fb588SMatthias Schmidt * word() in sh.lex.c for the main lexical input. One difference
1997d8fb588SMatthias Schmidt * here is that we don't get a newline to terminate our expansion.
2007d8fb588SMatthias Schmidt * Rather, DgetC will return a DEOF when we hit the end-of-input.
2017d8fb588SMatthias Schmidt */
2027d8fb588SMatthias Schmidt static int
Dword(struct blk_buf * bb)2037d8fb588SMatthias Schmidt Dword(struct blk_buf *bb)
2047d8fb588SMatthias Schmidt {
2057d8fb588SMatthias Schmidt eChar c, c1;
20657e3f2b5SSimon 'corecode' Schubert struct Strbuf *wbuf = Strbuf_alloc();
2077d8fb588SMatthias Schmidt int dolflg;
2087d8fb588SMatthias Schmidt int sofar = 0;
20957e3f2b5SSimon 'corecode' Schubert Char *str;
2107d8fb588SMatthias Schmidt
21157e3f2b5SSimon 'corecode' Schubert cleanup_push(wbuf, Strbuf_free);
2127d8fb588SMatthias Schmidt for (;;) {
2137d8fb588SMatthias Schmidt c = DgetC(DODOL);
2147d8fb588SMatthias Schmidt switch (c) {
2157d8fb588SMatthias Schmidt
2167d8fb588SMatthias Schmidt case DEOF:
2177d8fb588SMatthias Schmidt if (sofar == 0) {
21857e3f2b5SSimon 'corecode' Schubert cleanup_until(wbuf);
2197d8fb588SMatthias Schmidt return (0);
2207d8fb588SMatthias Schmidt }
2217d8fb588SMatthias Schmidt /* finish this word and catch the code above the next time */
2227d8fb588SMatthias Schmidt unDredc(c);
2237d8fb588SMatthias Schmidt /*FALLTHROUGH*/
2247d8fb588SMatthias Schmidt
2257d8fb588SMatthias Schmidt case '\n':
2267d8fb588SMatthias Schmidt goto end;
2277d8fb588SMatthias Schmidt
2287d8fb588SMatthias Schmidt case ' ':
2297d8fb588SMatthias Schmidt case '\t':
2307d8fb588SMatthias Schmidt continue;
2317d8fb588SMatthias Schmidt
2327d8fb588SMatthias Schmidt case '`':
2337d8fb588SMatthias Schmidt /* We preserve ` quotations which are done yet later */
23457e3f2b5SSimon 'corecode' Schubert Strbuf_append1(wbuf, (Char) c);
2357d8fb588SMatthias Schmidt /*FALLTHROUGH*/
2367d8fb588SMatthias Schmidt case '\'':
2377d8fb588SMatthias Schmidt case '"':
2387d8fb588SMatthias Schmidt /*
2397d8fb588SMatthias Schmidt * Note that DgetC never returns a QUOTES character from an
2407d8fb588SMatthias Schmidt * expansion, so only true input quotes will get us here or out.
2417d8fb588SMatthias Schmidt */
2427d8fb588SMatthias Schmidt c1 = c;
2437d8fb588SMatthias Schmidt dolflg = c1 == '"' ? DODOL : 0;
2447d8fb588SMatthias Schmidt for (;;) {
2457d8fb588SMatthias Schmidt c = DgetC(dolflg);
2467d8fb588SMatthias Schmidt if (c == c1)
2477d8fb588SMatthias Schmidt break;
24857e3f2b5SSimon 'corecode' Schubert if (c == '\n' || c == DEOF) {
24957e3f2b5SSimon 'corecode' Schubert cleanup_until(bb);
2507d8fb588SMatthias Schmidt stderror(ERR_UNMATCHED, (int)c1);
25157e3f2b5SSimon 'corecode' Schubert }
2527d8fb588SMatthias Schmidt if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) {
25357e3f2b5SSimon 'corecode' Schubert if (wbuf->len != 0 && (wbuf->s[wbuf->len - 1] & TRIM) == '\\')
25457e3f2b5SSimon 'corecode' Schubert wbuf->len--;
2557d8fb588SMatthias Schmidt }
2567d8fb588SMatthias Schmidt switch (c1) {
2577d8fb588SMatthias Schmidt
2587d8fb588SMatthias Schmidt case '"':
2597d8fb588SMatthias Schmidt /*
2607d8fb588SMatthias Schmidt * Leave any `s alone for later. Other chars are all
2617d8fb588SMatthias Schmidt * quoted, thus `...` can tell it was within "...".
2627d8fb588SMatthias Schmidt */
26357e3f2b5SSimon 'corecode' Schubert Strbuf_append1(wbuf, c == '`' ? '`' : c | QUOTE);
2647d8fb588SMatthias Schmidt break;
2657d8fb588SMatthias Schmidt
2667d8fb588SMatthias Schmidt case '\'':
2677d8fb588SMatthias Schmidt /* Prevent all further interpretation */
26857e3f2b5SSimon 'corecode' Schubert Strbuf_append1(wbuf, c | QUOTE);
2697d8fb588SMatthias Schmidt break;
2707d8fb588SMatthias Schmidt
2717d8fb588SMatthias Schmidt case '`':
2727d8fb588SMatthias Schmidt /* Leave all text alone for later */
27357e3f2b5SSimon 'corecode' Schubert Strbuf_append1(wbuf, (Char) c);
2747d8fb588SMatthias Schmidt break;
2757d8fb588SMatthias Schmidt
2767d8fb588SMatthias Schmidt default:
2777d8fb588SMatthias Schmidt break;
2787d8fb588SMatthias Schmidt }
2797d8fb588SMatthias Schmidt }
2807d8fb588SMatthias Schmidt if (c1 == '`')
28157e3f2b5SSimon 'corecode' Schubert Strbuf_append1(wbuf, '`');
2827d8fb588SMatthias Schmidt sofar = 1;
28357e3f2b5SSimon 'corecode' Schubert if (Dpack(wbuf) != 0)
2847d8fb588SMatthias Schmidt goto end;
2857d8fb588SMatthias Schmidt continue;
2867d8fb588SMatthias Schmidt
2877d8fb588SMatthias Schmidt case '\\':
2887d8fb588SMatthias Schmidt c = DgetC(0); /* No $ subst! */
2897d8fb588SMatthias Schmidt if (c == '\n' || c == DEOF)
2907d8fb588SMatthias Schmidt continue;
2917d8fb588SMatthias Schmidt c |= QUOTE;
2927d8fb588SMatthias Schmidt break;
2937d8fb588SMatthias Schmidt
2947d8fb588SMatthias Schmidt default:
2957d8fb588SMatthias Schmidt break;
2967d8fb588SMatthias Schmidt }
2977d8fb588SMatthias Schmidt unDgetC(c);
2987d8fb588SMatthias Schmidt sofar = 1;
29957e3f2b5SSimon 'corecode' Schubert if (Dpack(wbuf) != 0)
3007d8fb588SMatthias Schmidt goto end;
3017d8fb588SMatthias Schmidt }
3027d8fb588SMatthias Schmidt
3037d8fb588SMatthias Schmidt end:
30457e3f2b5SSimon 'corecode' Schubert cleanup_ignore(wbuf);
30557e3f2b5SSimon 'corecode' Schubert cleanup_until(wbuf);
30657e3f2b5SSimon 'corecode' Schubert str = Strbuf_finish(wbuf);
30757e3f2b5SSimon 'corecode' Schubert bb_append(bb, str);
30857e3f2b5SSimon 'corecode' Schubert xfree(wbuf);
3097d8fb588SMatthias Schmidt return 1;
3107d8fb588SMatthias Schmidt }
3117d8fb588SMatthias Schmidt
3127d8fb588SMatthias Schmidt
3137d8fb588SMatthias Schmidt /*
3147d8fb588SMatthias Schmidt * Get a character, performing $ substitution unless flag is 0.
3157d8fb588SMatthias Schmidt * Any QUOTES character which is returned from a $ expansion is
3167d8fb588SMatthias Schmidt * QUOTEd so that it will not be recognized above.
3177d8fb588SMatthias Schmidt */
3187d8fb588SMatthias Schmidt static eChar
DgetC(int flag)3197d8fb588SMatthias Schmidt DgetC(int flag)
3207d8fb588SMatthias Schmidt {
32194afa86dSJohn Marino eChar c;
3227d8fb588SMatthias Schmidt
3237d8fb588SMatthias Schmidt top:
3247d8fb588SMatthias Schmidt if ((c = Dpeekc) != 0) {
3257d8fb588SMatthias Schmidt Dpeekc = 0;
3267d8fb588SMatthias Schmidt return (c);
3277d8fb588SMatthias Schmidt }
3287d8fb588SMatthias Schmidt if (lap < labuf.len) {
3297d8fb588SMatthias Schmidt c = labuf.s[lap++] & (QUOTE | TRIM);
3307d8fb588SMatthias Schmidt quotspec:
3317d8fb588SMatthias Schmidt if (cmap(c, QUOTES))
3327d8fb588SMatthias Schmidt return (c | QUOTE);
3337d8fb588SMatthias Schmidt return (c);
3347d8fb588SMatthias Schmidt }
3357d8fb588SMatthias Schmidt if (dolp) {
3367d8fb588SMatthias Schmidt if ((c = *dolp++ & (QUOTE | TRIM)) != 0)
3377d8fb588SMatthias Schmidt goto quotspec;
3387d8fb588SMatthias Schmidt if (dolcnt > 0) {
3397d8fb588SMatthias Schmidt setDolp(*dolnxt++);
3407d8fb588SMatthias Schmidt --dolcnt;
3417d8fb588SMatthias Schmidt return (' ');
3427d8fb588SMatthias Schmidt }
3437d8fb588SMatthias Schmidt dolp = 0;
3447d8fb588SMatthias Schmidt }
3457d8fb588SMatthias Schmidt if (dolcnt > 0) {
3467d8fb588SMatthias Schmidt setDolp(*dolnxt++);
3477d8fb588SMatthias Schmidt --dolcnt;
3487d8fb588SMatthias Schmidt goto top;
3497d8fb588SMatthias Schmidt }
3507d8fb588SMatthias Schmidt c = Dredc();
3517d8fb588SMatthias Schmidt if (c == '$' && flag) {
3527d8fb588SMatthias Schmidt Dgetdol();
3537d8fb588SMatthias Schmidt goto top;
3547d8fb588SMatthias Schmidt }
3557d8fb588SMatthias Schmidt return (c);
3567d8fb588SMatthias Schmidt }
3577d8fb588SMatthias Schmidt
3587d8fb588SMatthias Schmidt static Char *nulvec[] = { NULL };
3597d8fb588SMatthias Schmidt static struct varent nulargv = {nulvec, STRargv, VAR_READWRITE,
3607d8fb588SMatthias Schmidt { NULL, NULL, NULL }, 0 };
3617d8fb588SMatthias Schmidt
3627d8fb588SMatthias Schmidt static void
dolerror(Char * s)3637d8fb588SMatthias Schmidt dolerror(Char *s)
3647d8fb588SMatthias Schmidt {
3657d8fb588SMatthias Schmidt setname(short2str(s));
3667d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_RANGE);
3677d8fb588SMatthias Schmidt }
3687d8fb588SMatthias Schmidt
3697d8fb588SMatthias Schmidt /*
3707d8fb588SMatthias Schmidt * Handle the multitudinous $ expansion forms.
3717d8fb588SMatthias Schmidt * Ugh.
3727d8fb588SMatthias Schmidt */
3737d8fb588SMatthias Schmidt static void
Dgetdol(void)3747d8fb588SMatthias Schmidt Dgetdol(void)
3757d8fb588SMatthias Schmidt {
3767d8fb588SMatthias Schmidt Char *np;
3777d8fb588SMatthias Schmidt struct varent *vp = NULL;
37857e3f2b5SSimon 'corecode' Schubert struct Strbuf *name = Strbuf_alloc();
3797d8fb588SMatthias Schmidt eChar c, sc;
3807d8fb588SMatthias Schmidt int subscr = 0, lwb = 1, upb = 0;
3817d8fb588SMatthias Schmidt int dimen = 0, bitset = 0, length = 0;
3827d8fb588SMatthias Schmidt static Char *dolbang = NULL;
3837d8fb588SMatthias Schmidt
38457e3f2b5SSimon 'corecode' Schubert cleanup_push(name, Strbuf_free);
385*d6ab524cSAntonio Huete Jimenez dolmod.len = ndolflags = 0;
3867d8fb588SMatthias Schmidt c = sc = DgetC(0);
3877d8fb588SMatthias Schmidt if (c == DEOF) {
3887d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
3897d8fb588SMatthias Schmidt return;
3907d8fb588SMatthias Schmidt }
391*d6ab524cSAntonio Huete Jimenez if ((c & TRIM) == '\'') {
392*d6ab524cSAntonio Huete Jimenez const Char *cp;
393*d6ab524cSAntonio Huete Jimenez struct Strbuf *expanded = Strbuf_alloc();
394*d6ab524cSAntonio Huete Jimenez
395*d6ab524cSAntonio Huete Jimenez cleanup_push(expanded, Strbuf_free);
396*d6ab524cSAntonio Huete Jimenez for (;;) {
397*d6ab524cSAntonio Huete Jimenez c = DgetC(0);
398*d6ab524cSAntonio Huete Jimenez if ((c & TRIM) == '\'')
399*d6ab524cSAntonio Huete Jimenez break;
400*d6ab524cSAntonio Huete Jimenez if ((c & TRIM) == '\\') {
401*d6ab524cSAntonio Huete Jimenez Strbuf_append1(name, (Char) c);
402*d6ab524cSAntonio Huete Jimenez c = DgetC(0);
403*d6ab524cSAntonio Huete Jimenez }
404*d6ab524cSAntonio Huete Jimenez if (c == '\n' || c == DEOF) {
405*d6ab524cSAntonio Huete Jimenez cleanup_until(name);
406*d6ab524cSAntonio Huete Jimenez stderror(ERR_MISSING, '\'');
407*d6ab524cSAntonio Huete Jimenez return;
408*d6ab524cSAntonio Huete Jimenez }
409*d6ab524cSAntonio Huete Jimenez Strbuf_append1(name, (Char) c);
410*d6ab524cSAntonio Huete Jimenez }
411*d6ab524cSAntonio Huete Jimenez Strbuf_terminate(name);
412*d6ab524cSAntonio Huete Jimenez for (cp = name->s; (c = *cp) != 0; cp++) {
413*d6ab524cSAntonio Huete Jimenez if (c == '\\' && (c = parseescape(&cp, TRUE)) == CHAR_ERR)
414*d6ab524cSAntonio Huete Jimenez c = '\\';
415*d6ab524cSAntonio Huete Jimenez Strbuf_append1(expanded, (Char) c | QUOTE);
416*d6ab524cSAntonio Huete Jimenez }
417*d6ab524cSAntonio Huete Jimenez Strbuf_terminate(expanded);
418*d6ab524cSAntonio Huete Jimenez np = Strsave(expanded->s);
419*d6ab524cSAntonio Huete Jimenez cleanup_until(name);
420*d6ab524cSAntonio Huete Jimenez addla(np);
421*d6ab524cSAntonio Huete Jimenez return;
422*d6ab524cSAntonio Huete Jimenez }
4237d8fb588SMatthias Schmidt if (c == '{')
4247d8fb588SMatthias Schmidt c = DgetC(0); /* sc is { to take } later */
4257d8fb588SMatthias Schmidt if ((c & TRIM) == '#')
4267d8fb588SMatthias Schmidt dimen++, c = DgetC(0); /* $# takes dimension */
4277d8fb588SMatthias Schmidt else if (c == '?')
4287d8fb588SMatthias Schmidt bitset++, c = DgetC(0); /* $? tests existence */
4297d8fb588SMatthias Schmidt else if (c == '%')
4307d8fb588SMatthias Schmidt length++, c = DgetC(0); /* $% returns length in chars */
4317d8fb588SMatthias Schmidt switch (c) {
4327d8fb588SMatthias Schmidt
4337d8fb588SMatthias Schmidt case '!':
4347d8fb588SMatthias Schmidt if (dimen || bitset || length)
4357d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
4367d8fb588SMatthias Schmidt if (backpid != 0) {
4377d8fb588SMatthias Schmidt xfree(dolbang);
43894afa86dSJohn Marino setDolp(dolbang = putn((tcsh_number_t)backpid));
4397d8fb588SMatthias Schmidt }
44057e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
4417d8fb588SMatthias Schmidt goto eatbrac;
4427d8fb588SMatthias Schmidt
4437d8fb588SMatthias Schmidt case '$':
4447d8fb588SMatthias Schmidt if (dimen || bitset || length)
4457d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
4467d8fb588SMatthias Schmidt setDolp(doldol);
44757e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
4487d8fb588SMatthias Schmidt goto eatbrac;
4497d8fb588SMatthias Schmidt
4507d8fb588SMatthias Schmidt case '<'|QUOTE: {
4517d8fb588SMatthias Schmidt static struct Strbuf wbuf; /* = Strbuf_INIT; */
4527d8fb588SMatthias Schmidt
4537d8fb588SMatthias Schmidt if (bitset)
4547d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$?<");
4557d8fb588SMatthias Schmidt if (dimen)
4567d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$#<");
4577d8fb588SMatthias Schmidt if (length)
4587d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$%<");
4597d8fb588SMatthias Schmidt wbuf.len = 0;
4607d8fb588SMatthias Schmidt {
4617d8fb588SMatthias Schmidt char cbuf[MB_LEN_MAX];
4627d8fb588SMatthias Schmidt size_t cbp = 0;
4637d8fb588SMatthias Schmidt int old_pintr_disabled;
4647d8fb588SMatthias Schmidt
4657d8fb588SMatthias Schmidt for (;;) {
4667d8fb588SMatthias Schmidt int len;
4677d8fb588SMatthias Schmidt ssize_t res;
4687d8fb588SMatthias Schmidt Char wc;
4697d8fb588SMatthias Schmidt
4707d8fb588SMatthias Schmidt pintr_push_enable(&old_pintr_disabled);
4717d8fb588SMatthias Schmidt res = force_read(OLDSTD, cbuf + cbp, 1);
4727d8fb588SMatthias Schmidt cleanup_until(&old_pintr_disabled);
4737d8fb588SMatthias Schmidt if (res != 1)
4747d8fb588SMatthias Schmidt break;
4757d8fb588SMatthias Schmidt cbp++;
4767d8fb588SMatthias Schmidt len = normal_mbtowc(&wc, cbuf, cbp);
4777d8fb588SMatthias Schmidt if (len == -1) {
4787d8fb588SMatthias Schmidt reset_mbtowc();
4797d8fb588SMatthias Schmidt if (cbp < MB_LEN_MAX)
4807d8fb588SMatthias Schmidt continue; /* Maybe a partial character */
4817d8fb588SMatthias Schmidt wc = (unsigned char)*cbuf | INVALID_BYTE;
4827d8fb588SMatthias Schmidt }
4837d8fb588SMatthias Schmidt if (len <= 0)
4847d8fb588SMatthias Schmidt len = 1;
4857d8fb588SMatthias Schmidt if (cbp != (size_t)len)
4867d8fb588SMatthias Schmidt memmove(cbuf, cbuf + len, cbp - len);
4877d8fb588SMatthias Schmidt cbp -= len;
4887d8fb588SMatthias Schmidt if (wc == '\n')
4897d8fb588SMatthias Schmidt break;
4907d8fb588SMatthias Schmidt Strbuf_append1(&wbuf, wc);
4917d8fb588SMatthias Schmidt }
4927d8fb588SMatthias Schmidt while (cbp != 0) {
4937d8fb588SMatthias Schmidt int len;
4947d8fb588SMatthias Schmidt Char wc;
4957d8fb588SMatthias Schmidt
4967d8fb588SMatthias Schmidt len = normal_mbtowc(&wc, cbuf, cbp);
4977d8fb588SMatthias Schmidt if (len == -1) {
4987d8fb588SMatthias Schmidt reset_mbtowc();
4997d8fb588SMatthias Schmidt wc = (unsigned char)*cbuf | INVALID_BYTE;
5007d8fb588SMatthias Schmidt }
5017d8fb588SMatthias Schmidt if (len <= 0)
5027d8fb588SMatthias Schmidt len = 1;
5037d8fb588SMatthias Schmidt if (cbp != (size_t)len)
5047d8fb588SMatthias Schmidt memmove(cbuf, cbuf + len, cbp - len);
5057d8fb588SMatthias Schmidt cbp -= len;
5067d8fb588SMatthias Schmidt if (wc == '\n')
5077d8fb588SMatthias Schmidt break;
5087d8fb588SMatthias Schmidt Strbuf_append1(&wbuf, wc);
5097d8fb588SMatthias Schmidt }
5107d8fb588SMatthias Schmidt Strbuf_terminate(&wbuf);
5117d8fb588SMatthias Schmidt }
5127d8fb588SMatthias Schmidt
5137d8fb588SMatthias Schmidt fixDolMod();
5147d8fb588SMatthias Schmidt setDolp(wbuf.s); /* Kept allocated until next $< expansion */
51557e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
5167d8fb588SMatthias Schmidt goto eatbrac;
5177d8fb588SMatthias Schmidt }
5187d8fb588SMatthias Schmidt
5197d8fb588SMatthias Schmidt case '*':
52057e3f2b5SSimon 'corecode' Schubert Strbuf_append(name, STRargv);
52157e3f2b5SSimon 'corecode' Schubert Strbuf_terminate(name);
5227d8fb588SMatthias Schmidt vp = adrof(STRargv);
5237d8fb588SMatthias Schmidt subscr = -1; /* Prevent eating [...] */
5247d8fb588SMatthias Schmidt break;
5257d8fb588SMatthias Schmidt
5267d8fb588SMatthias Schmidt case DEOF:
5277d8fb588SMatthias Schmidt case '\n':
5287d8fb588SMatthias Schmidt np = dimen ? STRargv : (bitset ? STRstatus : NULL);
5297d8fb588SMatthias Schmidt if (np) {
5307d8fb588SMatthias Schmidt bitset = 0;
53157e3f2b5SSimon 'corecode' Schubert Strbuf_append(name, np);
53257e3f2b5SSimon 'corecode' Schubert Strbuf_terminate(name);
5337d8fb588SMatthias Schmidt vp = adrof(np);
5347d8fb588SMatthias Schmidt subscr = -1; /* Prevent eating [...] */
5357d8fb588SMatthias Schmidt unDredc(c);
5367d8fb588SMatthias Schmidt break;
5377d8fb588SMatthias Schmidt }
5387d8fb588SMatthias Schmidt else
5397d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
5407d8fb588SMatthias Schmidt /*NOTREACHED*/
5417d8fb588SMatthias Schmidt
5427d8fb588SMatthias Schmidt default:
5437d8fb588SMatthias Schmidt if (Isdigit(c)) {
5447d8fb588SMatthias Schmidt if (dimen)
5457d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$#<num>");
5467d8fb588SMatthias Schmidt subscr = 0;
5477d8fb588SMatthias Schmidt do {
5487d8fb588SMatthias Schmidt subscr = subscr * 10 + c - '0';
5497d8fb588SMatthias Schmidt c = DgetC(0);
5507d8fb588SMatthias Schmidt } while (c != DEOF && Isdigit(c));
5517d8fb588SMatthias Schmidt unDredc(c);
5527d8fb588SMatthias Schmidt if (subscr < 0)
5537d8fb588SMatthias Schmidt stderror(ERR_RANGE);
5547d8fb588SMatthias Schmidt if (subscr == 0) {
5557d8fb588SMatthias Schmidt if (bitset) {
5567d8fb588SMatthias Schmidt dolp = dolzero ? STR1 : STR0;
55757e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
5587d8fb588SMatthias Schmidt goto eatbrac;
5597d8fb588SMatthias Schmidt }
5607d8fb588SMatthias Schmidt if (ffile == 0)
5617d8fb588SMatthias Schmidt stderror(ERR_DOLZERO);
5627d8fb588SMatthias Schmidt if (length) {
5637d8fb588SMatthias Schmidt length = Strlen(ffile);
56494afa86dSJohn Marino addla(putn((tcsh_number_t)length));
5657d8fb588SMatthias Schmidt }
5667d8fb588SMatthias Schmidt else {
5677d8fb588SMatthias Schmidt fixDolMod();
5687d8fb588SMatthias Schmidt setDolp(ffile);
5697d8fb588SMatthias Schmidt }
57057e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
5717d8fb588SMatthias Schmidt goto eatbrac;
5727d8fb588SMatthias Schmidt }
5737d8fb588SMatthias Schmidt #if 0
5747d8fb588SMatthias Schmidt if (bitset)
5757d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$?<num>");
5767d8fb588SMatthias Schmidt if (length)
5777d8fb588SMatthias Schmidt stderror(ERR_NOTALLOWED, "$%<num>");
5787d8fb588SMatthias Schmidt #endif
5797d8fb588SMatthias Schmidt vp = adrof(STRargv);
5807d8fb588SMatthias Schmidt if (vp == 0) {
5817d8fb588SMatthias Schmidt vp = &nulargv;
58257e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
5837d8fb588SMatthias Schmidt goto eatmod;
5847d8fb588SMatthias Schmidt }
5857d8fb588SMatthias Schmidt break;
5867d8fb588SMatthias Schmidt }
5877d8fb588SMatthias Schmidt if (c == DEOF || !alnum(c)) {
5887d8fb588SMatthias Schmidt np = dimen ? STRargv : (bitset ? STRstatus : NULL);
5897d8fb588SMatthias Schmidt if (np) {
5907d8fb588SMatthias Schmidt bitset = 0;
59157e3f2b5SSimon 'corecode' Schubert Strbuf_append(name, np);
59257e3f2b5SSimon 'corecode' Schubert Strbuf_terminate(name);
5937d8fb588SMatthias Schmidt vp = adrof(np);
5947d8fb588SMatthias Schmidt subscr = -1; /* Prevent eating [...] */
5957d8fb588SMatthias Schmidt unDredc(c);
5967d8fb588SMatthias Schmidt break;
5977d8fb588SMatthias Schmidt }
5987d8fb588SMatthias Schmidt else
5997d8fb588SMatthias Schmidt stderror(ERR_VARALNUM);
6007d8fb588SMatthias Schmidt }
6017d8fb588SMatthias Schmidt for (;;) {
60257e3f2b5SSimon 'corecode' Schubert Strbuf_append1(name, (Char) c);
6037d8fb588SMatthias Schmidt c = DgetC(0);
6047d8fb588SMatthias Schmidt if (c == DEOF || !alnum(c))
6057d8fb588SMatthias Schmidt break;
6067d8fb588SMatthias Schmidt }
60757e3f2b5SSimon 'corecode' Schubert Strbuf_terminate(name);
6087d8fb588SMatthias Schmidt unDredc(c);
60957e3f2b5SSimon 'corecode' Schubert vp = adrof(name->s);
6107d8fb588SMatthias Schmidt }
6117d8fb588SMatthias Schmidt if (bitset) {
61257e3f2b5SSimon 'corecode' Schubert dolp = (vp || getenv(short2str(name->s))) ? STR1 : STR0;
61357e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6147d8fb588SMatthias Schmidt goto eatbrac;
6157d8fb588SMatthias Schmidt }
6167d8fb588SMatthias Schmidt if (vp == NULL || vp->vec == NULL) {
61757e3f2b5SSimon 'corecode' Schubert np = str2short(getenv(short2str(name->s)));
6187d8fb588SMatthias Schmidt if (np) {
6197d8fb588SMatthias Schmidt static Char *env_val; /* = NULL; */
6207d8fb588SMatthias Schmidt
62157e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6227d8fb588SMatthias Schmidt fixDolMod();
62357e3f2b5SSimon 'corecode' Schubert if (length) {
62494afa86dSJohn Marino addla(putn((tcsh_number_t)Strlen(np)));
62557e3f2b5SSimon 'corecode' Schubert } else {
6267d8fb588SMatthias Schmidt xfree(env_val);
6277d8fb588SMatthias Schmidt env_val = Strsave(np);
6287d8fb588SMatthias Schmidt setDolp(env_val);
62957e3f2b5SSimon 'corecode' Schubert }
6307d8fb588SMatthias Schmidt goto eatbrac;
6317d8fb588SMatthias Schmidt }
63257e3f2b5SSimon 'corecode' Schubert udvar(name->s);
6337d8fb588SMatthias Schmidt /* NOTREACHED */
6347d8fb588SMatthias Schmidt }
63557e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6367d8fb588SMatthias Schmidt c = DgetC(0);
6377d8fb588SMatthias Schmidt upb = blklen(vp->vec);
6387d8fb588SMatthias Schmidt if (dimen == 0 && subscr == 0 && c == '[') {
63957e3f2b5SSimon 'corecode' Schubert name = Strbuf_alloc();
64057e3f2b5SSimon 'corecode' Schubert cleanup_push(name, Strbuf_free);
64157e3f2b5SSimon 'corecode' Schubert np = name->s;
6427d8fb588SMatthias Schmidt for (;;) {
6437d8fb588SMatthias Schmidt c = DgetC(DODOL); /* Allow $ expand within [ ] */
6447d8fb588SMatthias Schmidt if (c == ']')
6457d8fb588SMatthias Schmidt break;
6467d8fb588SMatthias Schmidt if (c == '\n' || c == DEOF)
6477d8fb588SMatthias Schmidt stderror(ERR_INCBR);
64857e3f2b5SSimon 'corecode' Schubert Strbuf_append1(name, (Char) c);
6497d8fb588SMatthias Schmidt }
65057e3f2b5SSimon 'corecode' Schubert Strbuf_terminate(name);
65157e3f2b5SSimon 'corecode' Schubert np = name->s;
6527d8fb588SMatthias Schmidt if (dolp || dolcnt) /* $ exp must end before ] */
6537d8fb588SMatthias Schmidt stderror(ERR_EXPORD);
6547d8fb588SMatthias Schmidt if (!*np)
6557d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
6567d8fb588SMatthias Schmidt if (Isdigit(*np)) {
6577d8fb588SMatthias Schmidt int i;
6587d8fb588SMatthias Schmidt
6597d8fb588SMatthias Schmidt for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
6607d8fb588SMatthias Schmidt continue;
66194afa86dSJohn Marino if (i < 0 || (i > upb && !any("-*", *np))) {
66257e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6637d8fb588SMatthias Schmidt dolerror(vp->v_name);
6647d8fb588SMatthias Schmidt return;
6657d8fb588SMatthias Schmidt }
6667d8fb588SMatthias Schmidt lwb = i;
6677d8fb588SMatthias Schmidt if (!*np)
6687d8fb588SMatthias Schmidt upb = lwb, np = STRstar;
6697d8fb588SMatthias Schmidt }
6707d8fb588SMatthias Schmidt if (*np == '*')
6717d8fb588SMatthias Schmidt np++;
6727d8fb588SMatthias Schmidt else if (*np != '-')
6737d8fb588SMatthias Schmidt stderror(ERR_MISSING, '-');
6747d8fb588SMatthias Schmidt else {
6757d8fb588SMatthias Schmidt int i = upb;
6767d8fb588SMatthias Schmidt
6777d8fb588SMatthias Schmidt np++;
6787d8fb588SMatthias Schmidt if (Isdigit(*np)) {
6797d8fb588SMatthias Schmidt i = 0;
6807d8fb588SMatthias Schmidt while (Isdigit(*np))
6817d8fb588SMatthias Schmidt i = i * 10 + *np++ - '0';
6827d8fb588SMatthias Schmidt if (i < 0 || i > upb) {
68357e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6847d8fb588SMatthias Schmidt dolerror(vp->v_name);
6857d8fb588SMatthias Schmidt return;
6867d8fb588SMatthias Schmidt }
6877d8fb588SMatthias Schmidt }
6887d8fb588SMatthias Schmidt if (i < lwb)
6897d8fb588SMatthias Schmidt upb = lwb - 1;
6907d8fb588SMatthias Schmidt else
6917d8fb588SMatthias Schmidt upb = i;
6927d8fb588SMatthias Schmidt }
6937d8fb588SMatthias Schmidt if (lwb == 0) {
6947d8fb588SMatthias Schmidt if (upb != 0) {
69557e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
6967d8fb588SMatthias Schmidt dolerror(vp->v_name);
6977d8fb588SMatthias Schmidt return;
6987d8fb588SMatthias Schmidt }
6997d8fb588SMatthias Schmidt upb = -1;
7007d8fb588SMatthias Schmidt }
7017d8fb588SMatthias Schmidt if (*np)
7027d8fb588SMatthias Schmidt stderror(ERR_SYNTAX);
70357e3f2b5SSimon 'corecode' Schubert cleanup_until(name);
7047d8fb588SMatthias Schmidt }
7057d8fb588SMatthias Schmidt else {
7067d8fb588SMatthias Schmidt if (subscr > 0) {
7077d8fb588SMatthias Schmidt if (subscr > upb)
7087d8fb588SMatthias Schmidt lwb = 1, upb = 0;
7097d8fb588SMatthias Schmidt else
7107d8fb588SMatthias Schmidt lwb = upb = subscr;
7117d8fb588SMatthias Schmidt }
7127d8fb588SMatthias Schmidt unDredc(c);
7137d8fb588SMatthias Schmidt }
7147d8fb588SMatthias Schmidt if (dimen) {
7157d8fb588SMatthias Schmidt /* this is a kludge. It prevents Dgetdol() from */
7167d8fb588SMatthias Schmidt /* pushing erroneous ${#<error> values into the labuf. */
7177d8fb588SMatthias Schmidt if (sc == '{') {
7187d8fb588SMatthias Schmidt c = Dredc();
7197d8fb588SMatthias Schmidt if (c != '}')
7207d8fb588SMatthias Schmidt stderror(ERR_MISSING, '}');
7217d8fb588SMatthias Schmidt unDredc(c);
7227d8fb588SMatthias Schmidt }
72394afa86dSJohn Marino addla(putn((tcsh_number_t)(upb - lwb + 1)));
7247d8fb588SMatthias Schmidt }
7257d8fb588SMatthias Schmidt else if (length) {
7267d8fb588SMatthias Schmidt int i;
7277d8fb588SMatthias Schmidt
7287d8fb588SMatthias Schmidt for (i = lwb - 1, length = 0; i < upb; i++)
7297d8fb588SMatthias Schmidt length += Strlen(vp->vec[i]);
7307d8fb588SMatthias Schmidt #ifdef notdef
7317d8fb588SMatthias Schmidt /* We don't want that, since we can always compute it by adding $#xxx */
7327d8fb588SMatthias Schmidt length += i - 1; /* Add the number of spaces in */
7337d8fb588SMatthias Schmidt #endif
73494afa86dSJohn Marino addla(putn((tcsh_number_t)length));
7357d8fb588SMatthias Schmidt }
7367d8fb588SMatthias Schmidt else {
7377d8fb588SMatthias Schmidt eatmod:
7387d8fb588SMatthias Schmidt fixDolMod();
7397d8fb588SMatthias Schmidt dolnxt = &vp->vec[lwb - 1];
7407d8fb588SMatthias Schmidt dolcnt = upb - lwb + 1;
7417d8fb588SMatthias Schmidt }
7427d8fb588SMatthias Schmidt eatbrac:
7437d8fb588SMatthias Schmidt if (sc == '{') {
7447d8fb588SMatthias Schmidt c = Dredc();
7457d8fb588SMatthias Schmidt if (c != '}')
7467d8fb588SMatthias Schmidt stderror(ERR_MISSING, '}');
7477d8fb588SMatthias Schmidt }
7487d8fb588SMatthias Schmidt }
7497d8fb588SMatthias Schmidt
7507d8fb588SMatthias Schmidt static void
fixDolMod(void)7517d8fb588SMatthias Schmidt fixDolMod(void)
7527d8fb588SMatthias Schmidt {
7537d8fb588SMatthias Schmidt eChar c;
7547d8fb588SMatthias Schmidt
7557d8fb588SMatthias Schmidt c = DgetC(0);
7567d8fb588SMatthias Schmidt if (c == ':') {
757*d6ab524cSAntonio Huete Jimenez ndolflags = 0;
7587d8fb588SMatthias Schmidt do {
759*d6ab524cSAntonio Huete Jimenez ++ndolflags;
760*d6ab524cSAntonio Huete Jimenez dolmcnts = xrealloc(dolmcnts, ndolflags * sizeof(int));
761*d6ab524cSAntonio Huete Jimenez dolaflags = xrealloc(dolaflags, ndolflags * sizeof(int));
762*d6ab524cSAntonio Huete Jimenez c = DgetC(0), dolmcnts[ndolflags - 1] = 1, dolaflags[ndolflags - 1] = 0;
7637d8fb588SMatthias Schmidt if (c == 'g' || c == 'a') {
764*d6ab524cSAntonio Huete Jimenez if (c == 'g') {
765*d6ab524cSAntonio Huete Jimenez dolmcnts[ndolflags - 1] = INT_MAX;
766*d6ab524cSAntonio Huete Jimenez } else {
767*d6ab524cSAntonio Huete Jimenez dolaflags[ndolflags - 1] = 1;
768*d6ab524cSAntonio Huete Jimenez }
7697d8fb588SMatthias Schmidt c = DgetC(0);
7707d8fb588SMatthias Schmidt }
771*d6ab524cSAntonio Huete Jimenez if ((c == 'g' && dolmcnts[ndolflags - 1] != INT_MAX) ||
772*d6ab524cSAntonio Huete Jimenez (c == 'a' && dolaflags[ndolflags - 1] == 0)) {
773*d6ab524cSAntonio Huete Jimenez if (c == 'g') {
774*d6ab524cSAntonio Huete Jimenez dolmcnts[ndolflags - 1] = INT_MAX;
775*d6ab524cSAntonio Huete Jimenez } else {
776*d6ab524cSAntonio Huete Jimenez dolaflags[ndolflags - 1] = 1;
777*d6ab524cSAntonio Huete Jimenez }
7787d8fb588SMatthias Schmidt c = DgetC(0);
7797d8fb588SMatthias Schmidt }
7807d8fb588SMatthias Schmidt
7817d8fb588SMatthias Schmidt if (c == 's') { /* [eichin:19910926.0755EST] */
7827d8fb588SMatthias Schmidt int delimcnt = 2;
783*d6ab524cSAntonio Huete Jimenez int esc = 0;
7847d8fb588SMatthias Schmidt eChar delim = DgetC(0);
7857d8fb588SMatthias Schmidt Strbuf_append1(&dolmod, (Char) c);
7867d8fb588SMatthias Schmidt Strbuf_append1(&dolmod, (Char) delim);
7877d8fb588SMatthias Schmidt
7887d8fb588SMatthias Schmidt if (delim == DEOF || !delim || letter(delim)
7897d8fb588SMatthias Schmidt || Isdigit(delim) || any(" \t\n", delim)) {
7907d8fb588SMatthias Schmidt seterror(ERR_BADSUBST);
7917d8fb588SMatthias Schmidt break;
7927d8fb588SMatthias Schmidt }
7937d8fb588SMatthias Schmidt while ((c = DgetC(0)) != DEOF) {
794*d6ab524cSAntonio Huete Jimenez if (esc == 0 && c == '\\') {
795*d6ab524cSAntonio Huete Jimenez esc = 1;
796*d6ab524cSAntonio Huete Jimenez continue;
797*d6ab524cSAntonio Huete Jimenez }
7987d8fb588SMatthias Schmidt Strbuf_append1(&dolmod, (Char) c);
799*d6ab524cSAntonio Huete Jimenez if (!esc && c == delim) delimcnt--;
8007d8fb588SMatthias Schmidt if (!delimcnt) break;
801*d6ab524cSAntonio Huete Jimenez esc = 0;
8027d8fb588SMatthias Schmidt }
8037d8fb588SMatthias Schmidt if (delimcnt) {
8047d8fb588SMatthias Schmidt seterror(ERR_BADSUBST);
8057d8fb588SMatthias Schmidt break;
8067d8fb588SMatthias Schmidt }
8077d8fb588SMatthias Schmidt continue;
8087d8fb588SMatthias Schmidt }
809*d6ab524cSAntonio Huete Jimenez if (!any(TCSH_MODIFIERS, c))
8107d8fb588SMatthias Schmidt stderror(ERR_BADMOD, (int)c);
8117d8fb588SMatthias Schmidt Strbuf_append1(&dolmod, (Char) c);
812*d6ab524cSAntonio Huete Jimenez if (c == 'q') {
813*d6ab524cSAntonio Huete Jimenez dolmcnts[ndolflags - 1] = INT_MAX;
814*d6ab524cSAntonio Huete Jimenez }
8157d8fb588SMatthias Schmidt }
8167d8fb588SMatthias Schmidt while ((c = DgetC(0)) == ':');
8177d8fb588SMatthias Schmidt unDredc(c);
8187d8fb588SMatthias Schmidt }
8197d8fb588SMatthias Schmidt else
8207d8fb588SMatthias Schmidt unDredc(c);
8217d8fb588SMatthias Schmidt }
8227d8fb588SMatthias Schmidt
823*d6ab524cSAntonio Huete Jimenez static int
all_dolmcnts_are_0(void)824*d6ab524cSAntonio Huete Jimenez all_dolmcnts_are_0(void)
825*d6ab524cSAntonio Huete Jimenez {
826*d6ab524cSAntonio Huete Jimenez int i = 0;
827*d6ab524cSAntonio Huete Jimenez for (; i < ndolflags; ++i) {
828*d6ab524cSAntonio Huete Jimenez if (dolmcnts[i] != 0)
829*d6ab524cSAntonio Huete Jimenez return 0;
830*d6ab524cSAntonio Huete Jimenez }
831*d6ab524cSAntonio Huete Jimenez return 1;
832*d6ab524cSAntonio Huete Jimenez }
833*d6ab524cSAntonio Huete Jimenez
8347d8fb588SMatthias Schmidt static void
setDolp(Char * cp)8357d8fb588SMatthias Schmidt setDolp(Char *cp)
8367d8fb588SMatthias Schmidt {
8377d8fb588SMatthias Schmidt Char *dp;
8387d8fb588SMatthias Schmidt size_t i;
839*d6ab524cSAntonio Huete Jimenez int nthMod = 0;
8407d8fb588SMatthias Schmidt
841*d6ab524cSAntonio Huete Jimenez if (dolmod.len == 0 || all_dolmcnts_are_0()) {
8427d8fb588SMatthias Schmidt dolp = cp;
8437d8fb588SMatthias Schmidt return;
8447d8fb588SMatthias Schmidt }
8457d8fb588SMatthias Schmidt cp = Strsave(cp);
8467d8fb588SMatthias Schmidt for (i = 0; i < dolmod.len; i++) {
8477d8fb588SMatthias Schmidt int didmod = 0;
8487d8fb588SMatthias Schmidt
8497d8fb588SMatthias Schmidt /* handle s// [eichin:19910926.0510EST] */
8507d8fb588SMatthias Schmidt if (dolmod.s[i] == 's') {
8517d8fb588SMatthias Schmidt Char delim;
8527d8fb588SMatthias Schmidt Char *lhsub, *rhsub, *np;
8537d8fb588SMatthias Schmidt size_t lhlen = 0, rhlen = 0;
854*d6ab524cSAntonio Huete Jimenez /* keep track of where the last :a match hit */
855*d6ab524cSAntonio Huete Jimenez ptrdiff_t last_match = 0;
8567d8fb588SMatthias Schmidt
8577d8fb588SMatthias Schmidt delim = dolmod.s[++i];
8587d8fb588SMatthias Schmidt if (!delim || letter(delim)
8597d8fb588SMatthias Schmidt || Isdigit(delim) || any(" \t\n", delim)) {
8607d8fb588SMatthias Schmidt seterror(ERR_BADSUBST);
8617d8fb588SMatthias Schmidt break;
8627d8fb588SMatthias Schmidt }
8637d8fb588SMatthias Schmidt lhsub = &dolmod.s[++i];
8647d8fb588SMatthias Schmidt while (dolmod.s[i] != delim && dolmod.s[++i]) {
8657d8fb588SMatthias Schmidt lhlen++;
8667d8fb588SMatthias Schmidt }
8677d8fb588SMatthias Schmidt dolmod.s[i] = 0;
8687d8fb588SMatthias Schmidt rhsub = &dolmod.s[++i];
8697d8fb588SMatthias Schmidt while (dolmod.s[i] != delim && dolmod.s[++i]) {
8707d8fb588SMatthias Schmidt rhlen++;
8717d8fb588SMatthias Schmidt }
8727d8fb588SMatthias Schmidt dolmod.s[i] = 0;
8737d8fb588SMatthias Schmidt
8747d8fb588SMatthias Schmidt strip(lhsub);
87557e3f2b5SSimon 'corecode' Schubert strip(rhsub);
876*d6ab524cSAntonio Huete Jimenez if (dolmcnts[nthMod] != 0) {
8777d8fb588SMatthias Schmidt strip(cp);
8787d8fb588SMatthias Schmidt dp = cp;
8797d8fb588SMatthias Schmidt do {
880*d6ab524cSAntonio Huete Jimenez dp = Strstr(dp + last_match, lhsub);
8817d8fb588SMatthias Schmidt if (dp) {
8827d8fb588SMatthias Schmidt ptrdiff_t diff = dp - cp;
88357e3f2b5SSimon 'corecode' Schubert size_t len = (Strlen(cp) + 1 - lhlen + rhlen);
88457e3f2b5SSimon 'corecode' Schubert np = xmalloc(len * sizeof(Char));
8857d8fb588SMatthias Schmidt (void) Strncpy(np, cp, diff);
8867d8fb588SMatthias Schmidt (void) Strcpy(np + diff, rhsub);
8877d8fb588SMatthias Schmidt (void) Strcpy(np + diff + rhlen, dp + lhlen);
888*d6ab524cSAntonio Huete Jimenez last_match = diff + rhlen;
8897d8fb588SMatthias Schmidt
8907d8fb588SMatthias Schmidt xfree(cp);
89160962bbcSJohn Marino dp = cp = np;
89257e3f2b5SSimon 'corecode' Schubert cp[--len] = '\0';
8937d8fb588SMatthias Schmidt didmod = 1;
89494afa86dSJohn Marino if (diff >= (ssize_t)len)
89557e3f2b5SSimon 'corecode' Schubert break;
8967d8fb588SMatthias Schmidt } else {
8977d8fb588SMatthias Schmidt /* should this do a seterror? */
8987d8fb588SMatthias Schmidt break;
8997d8fb588SMatthias Schmidt }
9007d8fb588SMatthias Schmidt }
901*d6ab524cSAntonio Huete Jimenez while (dolaflags[nthMod] != 0);
902*d6ab524cSAntonio Huete Jimenez }
9037d8fb588SMatthias Schmidt /*
9047d8fb588SMatthias Schmidt * restore dolmod for additional words
9057d8fb588SMatthias Schmidt */
9067d8fb588SMatthias Schmidt dolmod.s[i] = rhsub[-1] = (Char) delim;
907*d6ab524cSAntonio Huete Jimenez } else if (dolmcnts[nthMod] != 0) {
9087d8fb588SMatthias Schmidt
9097d8fb588SMatthias Schmidt do {
9107d8fb588SMatthias Schmidt if ((dp = domod(cp, dolmod.s[i])) != NULL) {
9117d8fb588SMatthias Schmidt didmod = 1;
9127d8fb588SMatthias Schmidt if (Strcmp(cp, dp) == 0) {
9137d8fb588SMatthias Schmidt xfree(cp);
9147d8fb588SMatthias Schmidt cp = dp;
9157d8fb588SMatthias Schmidt break;
9167d8fb588SMatthias Schmidt }
9177d8fb588SMatthias Schmidt else {
9187d8fb588SMatthias Schmidt xfree(cp);
9197d8fb588SMatthias Schmidt cp = dp;
9207d8fb588SMatthias Schmidt }
9217d8fb588SMatthias Schmidt }
9227d8fb588SMatthias Schmidt else
9237d8fb588SMatthias Schmidt break;
9247d8fb588SMatthias Schmidt }
925*d6ab524cSAntonio Huete Jimenez while (dolaflags[nthMod] != 0);
9267d8fb588SMatthias Schmidt }
927*d6ab524cSAntonio Huete Jimenez if (didmod && dolmcnts[nthMod] != INT_MAX)
928*d6ab524cSAntonio Huete Jimenez dolmcnts[nthMod]--;
9297d8fb588SMatthias Schmidt #ifdef notdef
9307d8fb588SMatthias Schmidt else
9317d8fb588SMatthias Schmidt break;
9327d8fb588SMatthias Schmidt #endif
933*d6ab524cSAntonio Huete Jimenez
934*d6ab524cSAntonio Huete Jimenez ++nthMod;
9357d8fb588SMatthias Schmidt }
9367d8fb588SMatthias Schmidt
9377d8fb588SMatthias Schmidt addla(cp);
9387d8fb588SMatthias Schmidt
9397d8fb588SMatthias Schmidt dolp = STRNULL;
9407d8fb588SMatthias Schmidt if (seterr)
9417d8fb588SMatthias Schmidt stderror(ERR_OLD);
9427d8fb588SMatthias Schmidt }
9437d8fb588SMatthias Schmidt
9447d8fb588SMatthias Schmidt static void
unDredc(eChar c)9457d8fb588SMatthias Schmidt unDredc(eChar c)
9467d8fb588SMatthias Schmidt {
9477d8fb588SMatthias Schmidt
9487d8fb588SMatthias Schmidt Dpeekrd = c;
9497d8fb588SMatthias Schmidt }
9507d8fb588SMatthias Schmidt
9517d8fb588SMatthias Schmidt static eChar
Dredc(void)9527d8fb588SMatthias Schmidt Dredc(void)
9537d8fb588SMatthias Schmidt {
95494afa86dSJohn Marino eChar c;
9557d8fb588SMatthias Schmidt
9567d8fb588SMatthias Schmidt if ((c = Dpeekrd) != 0) {
9577d8fb588SMatthias Schmidt Dpeekrd = 0;
9587d8fb588SMatthias Schmidt return (c);
9597d8fb588SMatthias Schmidt }
9607d8fb588SMatthias Schmidt if (Dcp && (c = *Dcp++))
9617d8fb588SMatthias Schmidt return (c & (QUOTE | TRIM));
9627d8fb588SMatthias Schmidt if (*Dvp == 0) {
9637d8fb588SMatthias Schmidt Dcp = 0;
9647d8fb588SMatthias Schmidt return (DEOF);
9657d8fb588SMatthias Schmidt }
9667d8fb588SMatthias Schmidt Dcp = *Dvp++;
9677d8fb588SMatthias Schmidt return (' ');
9687d8fb588SMatthias Schmidt }
9697d8fb588SMatthias Schmidt
9707d8fb588SMatthias Schmidt static int gflag;
9717d8fb588SMatthias Schmidt
9727d8fb588SMatthias Schmidt static void
Dtestq(Char c)9737d8fb588SMatthias Schmidt Dtestq(Char c)
9747d8fb588SMatthias Schmidt {
9757d8fb588SMatthias Schmidt
9767d8fb588SMatthias Schmidt if (cmap(c, QUOTES))
9777d8fb588SMatthias Schmidt gflag = 1;
9787d8fb588SMatthias Schmidt }
9797d8fb588SMatthias Schmidt
9807d8fb588SMatthias Schmidt static void
inheredoc_cleanup(void * dummy)9817d8fb588SMatthias Schmidt inheredoc_cleanup(void *dummy)
9827d8fb588SMatthias Schmidt {
9837d8fb588SMatthias Schmidt USE(dummy);
9847d8fb588SMatthias Schmidt inheredoc = 0;
9857d8fb588SMatthias Schmidt }
9867d8fb588SMatthias Schmidt
98760962bbcSJohn Marino Char *
randsuf(void)98860962bbcSJohn Marino randsuf(void) {
98960962bbcSJohn Marino #ifndef WINNT_NATIVE
99060962bbcSJohn Marino struct timeval tv;
99160962bbcSJohn Marino (void) gettimeofday(&tv, NULL);
99260962bbcSJohn Marino return putn((((tcsh_number_t)tv.tv_sec) ^
99360962bbcSJohn Marino ((tcsh_number_t)tv.tv_usec) ^
99460962bbcSJohn Marino ((tcsh_number_t)getpid())) & 0x00ffffff);
99560962bbcSJohn Marino #else
99660962bbcSJohn Marino return putn(getpid());
99760962bbcSJohn Marino #endif
99860962bbcSJohn Marino }
99960962bbcSJohn Marino
10007d8fb588SMatthias Schmidt /*
10017d8fb588SMatthias Schmidt * Form a shell temporary file (in unit 0) from the words
10027d8fb588SMatthias Schmidt * of the shell input up to EOF or a line the same as "term".
10037d8fb588SMatthias Schmidt * Unit 0 should have been closed before this call.
10047d8fb588SMatthias Schmidt */
10057d8fb588SMatthias Schmidt void
heredoc(Char * term)10067d8fb588SMatthias Schmidt heredoc(Char *term)
10077d8fb588SMatthias Schmidt {
10087d8fb588SMatthias Schmidt eChar c;
10097d8fb588SMatthias Schmidt Char *Dv[2];
10107d8fb588SMatthias Schmidt struct Strbuf lbuf = Strbuf_INIT, mbuf = Strbuf_INIT;
10117d8fb588SMatthias Schmidt Char obuf[BUFSIZE + 1];
10127d8fb588SMatthias Schmidt #define OBUF_END (obuf + sizeof(obuf) / sizeof (*obuf) - 1)
10137d8fb588SMatthias Schmidt Char *lbp, *obp, *mbp;
10147d8fb588SMatthias Schmidt Char **vp;
10157d8fb588SMatthias Schmidt int quoted;
101694afa86dSJohn Marino #ifdef HAVE_MKSTEMP
101794afa86dSJohn Marino char *tmp = short2str(shtemp);
101894afa86dSJohn Marino char *dot = strrchr(tmp, '.');
101994afa86dSJohn Marino
102094afa86dSJohn Marino if (!dot)
102194afa86dSJohn Marino stderror(ERR_NAME | ERR_NOMATCH);
102294afa86dSJohn Marino strcpy(dot, TMP_TEMPLATE);
102394afa86dSJohn Marino
102494afa86dSJohn Marino xclose(0);
102594afa86dSJohn Marino if (mkstemp(tmp) == -1)
102694afa86dSJohn Marino stderror(ERR_SYSTEM, tmp, strerror(errno));
102794afa86dSJohn Marino #else /* !HAVE_MKSTEMP */
10287d8fb588SMatthias Schmidt char *tmp;
10297d8fb588SMatthias Schmidt # ifndef WINNT_NATIVE
10307d8fb588SMatthias Schmidt
10317d8fb588SMatthias Schmidt again:
10327d8fb588SMatthias Schmidt # endif /* WINNT_NATIVE */
10337d8fb588SMatthias Schmidt tmp = short2str(shtemp);
103494afa86dSJohn Marino # if O_CREAT == 0
10357d8fb588SMatthias Schmidt if (xcreat(tmp, 0600) < 0)
10367d8fb588SMatthias Schmidt stderror(ERR_SYSTEM, tmp, strerror(errno));
10377d8fb588SMatthias Schmidt # endif
10387d8fb588SMatthias Schmidt xclose(0);
10397d8fb588SMatthias Schmidt if (xopen(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) ==
10407d8fb588SMatthias Schmidt -1) {
10417d8fb588SMatthias Schmidt int oerrno = errno;
10427d8fb588SMatthias Schmidt # ifndef WINNT_NATIVE
10437d8fb588SMatthias Schmidt if (errno == EEXIST) {
10447d8fb588SMatthias Schmidt if (unlink(tmp) == -1) {
10457d8fb588SMatthias Schmidt xfree(shtemp);
104660962bbcSJohn Marino mbp = randsuf();
10477d8fb588SMatthias Schmidt shtemp = Strspl(STRtmpsh, mbp);
10487d8fb588SMatthias Schmidt xfree(mbp);
10497d8fb588SMatthias Schmidt }
10507d8fb588SMatthias Schmidt goto again;
10517d8fb588SMatthias Schmidt }
10527d8fb588SMatthias Schmidt # endif /* WINNT_NATIVE */
10537d8fb588SMatthias Schmidt (void) unlink(tmp);
10547d8fb588SMatthias Schmidt errno = oerrno;
10557d8fb588SMatthias Schmidt stderror(ERR_SYSTEM, tmp, strerror(errno));
10567d8fb588SMatthias Schmidt }
105794afa86dSJohn Marino #endif /* HAVE_MKSTEMP */
10587d8fb588SMatthias Schmidt (void) unlink(tmp); /* 0 0 inode! */
10597d8fb588SMatthias Schmidt Dv[0] = term;
10607d8fb588SMatthias Schmidt Dv[1] = NULL;
10617d8fb588SMatthias Schmidt gflag = 0;
10627d8fb588SMatthias Schmidt trim(Dv);
10637d8fb588SMatthias Schmidt rscan(Dv, Dtestq);
10647d8fb588SMatthias Schmidt quoted = gflag;
10657d8fb588SMatthias Schmidt obp = obuf;
10667d8fb588SMatthias Schmidt obuf[BUFSIZE] = 0;
10677d8fb588SMatthias Schmidt inheredoc = 1;
10687d8fb588SMatthias Schmidt cleanup_push(&inheredoc, inheredoc_cleanup);
10697d8fb588SMatthias Schmidt #ifdef WINNT_NATIVE
10707d8fb588SMatthias Schmidt __dup_stdin = 1;
10717d8fb588SMatthias Schmidt #endif /* WINNT_NATIVE */
10727d8fb588SMatthias Schmidt cleanup_push(&lbuf, Strbuf_cleanup);
10737d8fb588SMatthias Schmidt cleanup_push(&mbuf, Strbuf_cleanup);
10747d8fb588SMatthias Schmidt for (;;) {
10757d8fb588SMatthias Schmidt Char **words;
10767d8fb588SMatthias Schmidt
10777d8fb588SMatthias Schmidt /*
10787d8fb588SMatthias Schmidt * Read up a line
10797d8fb588SMatthias Schmidt */
10807d8fb588SMatthias Schmidt lbuf.len = 0;
10817d8fb588SMatthias Schmidt for (;;) {
10827d8fb588SMatthias Schmidt c = readc(1); /* 1 -> Want EOF returns */
10837d8fb588SMatthias Schmidt if (c == CHAR_ERR || c == '\n')
10847d8fb588SMatthias Schmidt break;
10857d8fb588SMatthias Schmidt if ((c &= TRIM) != 0)
10867d8fb588SMatthias Schmidt Strbuf_append1(&lbuf, (Char) c);
10877d8fb588SMatthias Schmidt }
10887d8fb588SMatthias Schmidt Strbuf_terminate(&lbuf);
10897d8fb588SMatthias Schmidt
109094afa86dSJohn Marino /* Catch EOF in the middle of a line. */
109194afa86dSJohn Marino if (c == CHAR_ERR && lbuf.len != 0)
109294afa86dSJohn Marino c = '\n';
109394afa86dSJohn Marino
10947d8fb588SMatthias Schmidt /*
10957d8fb588SMatthias Schmidt * Check for EOF or compare to terminator -- before expansion
10967d8fb588SMatthias Schmidt */
10977d8fb588SMatthias Schmidt if (c == CHAR_ERR || eq(lbuf.s, term))
10987d8fb588SMatthias Schmidt break;
10997d8fb588SMatthias Schmidt
11007d8fb588SMatthias Schmidt /*
11017d8fb588SMatthias Schmidt * If term was quoted or -n just pass it on
11027d8fb588SMatthias Schmidt */
11037d8fb588SMatthias Schmidt if (quoted || noexec) {
11047d8fb588SMatthias Schmidt Strbuf_append1(&lbuf, '\n');
11057d8fb588SMatthias Schmidt Strbuf_terminate(&lbuf);
11067d8fb588SMatthias Schmidt for (lbp = lbuf.s; (c = *lbp++) != 0;) {
11077d8fb588SMatthias Schmidt *obp++ = (Char) c;
11087d8fb588SMatthias Schmidt if (obp == OBUF_END) {
11097d8fb588SMatthias Schmidt tmp = short2str(obuf);
11107d8fb588SMatthias Schmidt (void) xwrite(0, tmp, strlen (tmp));
11117d8fb588SMatthias Schmidt obp = obuf;
11127d8fb588SMatthias Schmidt }
11137d8fb588SMatthias Schmidt }
11147d8fb588SMatthias Schmidt continue;
11157d8fb588SMatthias Schmidt }
11167d8fb588SMatthias Schmidt
11177d8fb588SMatthias Schmidt /*
11187d8fb588SMatthias Schmidt * Term wasn't quoted so variable and then command expand the input
11197d8fb588SMatthias Schmidt * line
11207d8fb588SMatthias Schmidt */
11217d8fb588SMatthias Schmidt Dcp = lbuf.s;
11227d8fb588SMatthias Schmidt Dvp = Dv + 1;
11237d8fb588SMatthias Schmidt mbuf.len = 0;
11247d8fb588SMatthias Schmidt for (;;) {
11257d8fb588SMatthias Schmidt c = DgetC(DODOL);
11267d8fb588SMatthias Schmidt if (c == DEOF)
11277d8fb588SMatthias Schmidt break;
11287d8fb588SMatthias Schmidt if ((c &= TRIM) == 0)
11297d8fb588SMatthias Schmidt continue;
11307d8fb588SMatthias Schmidt /* \ quotes \ $ ` here */
11317d8fb588SMatthias Schmidt if (c == '\\') {
11327d8fb588SMatthias Schmidt c = DgetC(0);
11337d8fb588SMatthias Schmidt if (!any("$\\`", c))
11347d8fb588SMatthias Schmidt unDgetC(c | QUOTE), c = '\\';
11357d8fb588SMatthias Schmidt else
11367d8fb588SMatthias Schmidt c |= QUOTE;
11377d8fb588SMatthias Schmidt }
11387d8fb588SMatthias Schmidt Strbuf_append1(&mbuf, (Char) c);
11397d8fb588SMatthias Schmidt }
11407d8fb588SMatthias Schmidt Strbuf_terminate(&mbuf);
11417d8fb588SMatthias Schmidt
11427d8fb588SMatthias Schmidt /*
11437d8fb588SMatthias Schmidt * If any ` in line do command substitution
11447d8fb588SMatthias Schmidt */
11457d8fb588SMatthias Schmidt mbp = mbuf.s;
11467d8fb588SMatthias Schmidt if (Strchr(mbp, '`') != NULL) {
11477d8fb588SMatthias Schmidt /*
11487d8fb588SMatthias Schmidt * 1 arg to dobackp causes substitution to be literal. Words are
11497d8fb588SMatthias Schmidt * broken only at newlines so that all blanks and tabs are
11507d8fb588SMatthias Schmidt * preserved. Blank lines (null words) are not discarded.
11517d8fb588SMatthias Schmidt */
11527d8fb588SMatthias Schmidt words = dobackp(mbp, 1);
11537d8fb588SMatthias Schmidt }
11547d8fb588SMatthias Schmidt else
11557d8fb588SMatthias Schmidt /* Setup trivial vector similar to return of dobackp */
11567d8fb588SMatthias Schmidt Dv[0] = mbp, Dv[1] = NULL, words = Dv;
11577d8fb588SMatthias Schmidt
11587d8fb588SMatthias Schmidt /*
11597d8fb588SMatthias Schmidt * Resurrect the words from the command substitution each separated by
11607d8fb588SMatthias Schmidt * a newline. Note that the last newline of a command substitution
11617d8fb588SMatthias Schmidt * will have been discarded, but we put a newline after the last word
11627d8fb588SMatthias Schmidt * because this represents the newline after the last input line!
11637d8fb588SMatthias Schmidt */
11647d8fb588SMatthias Schmidt for (vp= words; *vp; vp++) {
11657d8fb588SMatthias Schmidt for (mbp = *vp; *mbp; mbp++) {
11667d8fb588SMatthias Schmidt *obp++ = *mbp & TRIM;
11677d8fb588SMatthias Schmidt if (obp == OBUF_END) {
11687d8fb588SMatthias Schmidt tmp = short2str(obuf);
11697d8fb588SMatthias Schmidt (void) xwrite(0, tmp, strlen (tmp));
11707d8fb588SMatthias Schmidt obp = obuf;
11717d8fb588SMatthias Schmidt }
11727d8fb588SMatthias Schmidt }
11737d8fb588SMatthias Schmidt *obp++ = '\n';
11747d8fb588SMatthias Schmidt if (obp == OBUF_END) {
11757d8fb588SMatthias Schmidt tmp = short2str(obuf);
11767d8fb588SMatthias Schmidt (void) xwrite(0, tmp, strlen (tmp));
11777d8fb588SMatthias Schmidt obp = obuf;
11787d8fb588SMatthias Schmidt }
11797d8fb588SMatthias Schmidt }
11807d8fb588SMatthias Schmidt if (words != Dv)
11817d8fb588SMatthias Schmidt blkfree(words);
11827d8fb588SMatthias Schmidt }
11837d8fb588SMatthias Schmidt *obp = 0;
11847d8fb588SMatthias Schmidt tmp = short2str(obuf);
11857d8fb588SMatthias Schmidt (void) xwrite(0, tmp, strlen (tmp));
11867d8fb588SMatthias Schmidt (void) lseek(0, (off_t) 0, L_SET);
11877d8fb588SMatthias Schmidt cleanup_until(&inheredoc);
11887d8fb588SMatthias Schmidt }
1189