diff --git a/check.t b/check.t index cd9ee40..ccd12d1 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.737 2016/06/26 00:06:43 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.738 2016/06/26 00:09:32 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, @@ -2613,6 +2613,10 @@ stdin: eval "$fnd" foo print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |" + x=y + foo + typeset -f foo + print -r -- "| vc={$vc} vd={$vd} |" # check append v=<<- vapp1 @@ -2638,6 +2642,19 @@ expected-stdout: } vc={=c u \x40= } vd={=d $x \x40= } | + function foo { + vc=<<- + =c $x \x40= + << + + vd=<<-"" + =d $x \x40= + + + } + | vc={=c y \x40= + } vd={=d $x \x40= + } | | vapp1^vapp2^ | --- name: heredoc-12 diff --git a/exec.c b/exec.c index 962bc2a..a75f489 100644 --- a/exec.c +++ b/exec.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.173 2016/04/09 16:41:07 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.174 2016/06/26 00:09:35 tg Exp $"); #ifndef MKSH_DEFAULT_EXECSHELL #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" @@ -60,7 +60,6 @@ execute(struct op * volatile t, const char *s, *ccp; struct ioword **iowp; struct tbl *tp = NULL; - char *cp; if (t == NULL) return (0); @@ -79,11 +78,18 @@ execute(struct op * volatile t, /* we want to run an executable, do some variance checks */ if (t->type == TCOM) { + /* + * Clear subst_exstat before argument expansion. Used by + * null commands (see comexec() and c_eval()) and by c_set(). + */ + subst_exstat = 0; + + /* for $LINENO */ + current_lineno = t->lineno; + /* check if this is 'var=<args[0] == NULL && /* we have exactly one variable assignment */ t->vars[0] != NULL && t->vars[1] == NULL && @@ -97,42 +103,20 @@ execute(struct op * volatile t, /* and has no right-hand side (i.e. "varname=") */ ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) || /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR && - ccp[3] == '=' && ccp[4] == EOS)) && - /* plus we can have a here document content */ - herein(t->ioact[0], &cp) == 0 && cp && *cp) { - char *sp = cp, *dp; - size_t n = ccp - t->vars[0] + (ccp[1] == '+' ? 4 : 2); - size_t z; + ccp[3] == '=' && ccp[4] == EOS))) { + char *cp, *dp; - /* drop redirection (will be garbage collected) */ - t->ioact = NULL; - - /* set variable to its expanded value */ - z = strlen(cp); - if (notoktomul(z, 2) || notoktoadd(z * 2, n + 1)) - internal_errorf(Toomem, (size_t)-1); - dp = alloc(z * 2 + n + 1, APERM); - memcpy(dp, t->vars[0], n); - t->vars[0] = dp; - dp += n; - while (*sp) { - *dp++ = QCHAR; - *dp++ = *sp++; - } - *dp = EOS; + if ((rv = herein(t->ioact[0], &cp) /*? 1 : 0*/)) + cp = NULL; + dp = shf_smprintf("%s%s", evalstr(t->vars[0], + DOASNTILDE | DOSCALAR), rv ? null : cp); + typeset(dp, Flag(FEXPORT) ? EXPORT : 0, 0, 0, 0); /* free the expanded value */ afree(cp, APERM); + afree(dp, ATEMP); + goto Break; } - /* - * Clear subst_exstat before argument expansion. Used by - * null commands (see comexec() and c_eval()) and by c_set(). - */ - subst_exstat = 0; - - /* for $LINENO */ - current_lineno = t->lineno; - /* * POSIX says expand command words first, then redirections, * and assignments last.. diff --git a/tree.c b/tree.c index 5dc3a76..adf6803 100644 --- a/tree.c +++ b/tree.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.84 2016/06/26 00:07:31 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.85 2016/06/26 00:09:35 tg Exp $"); #define INDENT 8 @@ -49,6 +49,7 @@ ptree(struct op *t, int indent, struct shf *shf) struct ioword **ioact; struct op *t1; int i; + const char *ccp; Chain: if (t == NULL) @@ -56,12 +57,9 @@ ptree(struct op *t, int indent, struct shf *shf) switch (t->type) { case TCOM: prevent_semicolon = false; - /* - * special-case 'var=<args[0] == NULL && /* we have exactly one variable assignment */ t->vars[0] != NULL && t->vars[1] == NULL && @@ -69,7 +67,13 @@ ptree(struct op *t, int indent, struct shf *shf) t->ioact != NULL && t->ioact[0] != NULL && t->ioact[1] == NULL && /* of type "here document" (or "here string") */ - (t->ioact[0]->ioflag & IOTYPE) == IOHERE) { + (t->ioact[0]->ioflag & IOTYPE) == IOHERE && + /* the variable assignment begins with a valid varname */ + (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] && + /* and has no right-hand side (i.e. "varname=") */ + ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) || + /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR && + ccp[3] == '=' && ccp[4] == EOS))) { fptreef(shf, indent, "%S", t->vars[0]); break; }