fix var=<< implementation

This commit is contained in:
tg 2016-06-26 00:09:35 +00:00
parent c52133cc4e
commit 97d1d5e4fe
3 changed files with 49 additions and 44 deletions

19
check.t
View File

@ -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 -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -2613,6 +2613,10 @@ stdin:
eval "$fnd" eval "$fnd"
foo foo
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |" print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |"
x=y
foo
typeset -f foo
print -r -- "| vc={$vc} vd={$vd} |"
# check append # check append
v=<<- v=<<-
vapp1 vapp1
@ -2638,6 +2642,19 @@ expected-stdout:
} vc={=c u \x40= } vc={=c u \x40=
} vd={=d $x \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^ | | vapp1^vapp2^ |
--- ---
name: heredoc-12 name: heredoc-12

56
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #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 #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -60,7 +60,6 @@ execute(struct op * volatile t,
const char *s, *ccp; const char *s, *ccp;
struct ioword **iowp; struct ioword **iowp;
struct tbl *tp = NULL; struct tbl *tp = NULL;
char *cp;
if (t == NULL) if (t == NULL)
return (0); return (0);
@ -79,11 +78,18 @@ execute(struct op * volatile t,
/* we want to run an executable, do some variance checks */ /* we want to run an executable, do some variance checks */
if (t->type == TCOM) { 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=<<EOF' */ /* check if this is 'var=<<EOF' */
/*XXX this is broken, dont use! */
/*XXX https://bugs.launchpad.net/mksh/+bug/1380389 */
if ( if (
/* we have zero arguments, i.e. no programme to run */ /* we have zero arguments, i.e. no program to run */
t->args[0] == NULL && t->args[0] == NULL &&
/* we have exactly one variable assignment */ /* we have exactly one variable assignment */
t->vars[0] != NULL && t->vars[1] == NULL && 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=") */ /* and has no right-hand side (i.e. "varname=") */
ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) || ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
/* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR && /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
ccp[3] == '=' && ccp[4] == EOS)) && ccp[3] == '=' && ccp[4] == EOS))) {
/* plus we can have a here document content */ char *cp, *dp;
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;
/* drop redirection (will be garbage collected) */ if ((rv = herein(t->ioact[0], &cp) /*? 1 : 0*/))
t->ioact = NULL; cp = NULL;
dp = shf_smprintf("%s%s", evalstr(t->vars[0],
/* set variable to its expanded value */ DOASNTILDE | DOSCALAR), rv ? null : cp);
z = strlen(cp); typeset(dp, Flag(FEXPORT) ? EXPORT : 0, 0, 0, 0);
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;
/* free the expanded value */ /* free the expanded value */
afree(cp, APERM); 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, * POSIX says expand command words first, then redirections,
* and assignments last.. * and assignments last..

18
tree.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #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 #define INDENT 8
@ -49,6 +49,7 @@ ptree(struct op *t, int indent, struct shf *shf)
struct ioword **ioact; struct ioword **ioact;
struct op *t1; struct op *t1;
int i; int i;
const char *ccp;
Chain: Chain:
if (t == NULL) if (t == NULL)
@ -56,12 +57,9 @@ ptree(struct op *t, int indent, struct shf *shf)
switch (t->type) { switch (t->type) {
case TCOM: case TCOM:
prevent_semicolon = false; prevent_semicolon = false;
/* /* special-case 'var=<<EOF' (cf. exec.c:execute) */
* special-case 'var=<<EOF' (rough; see
* exec.c:execute() for full code)
*/
if ( if (
/* we have zero arguments, i.e. no programme to run */ /* we have zero arguments, i.e. no program to run */
t->args[0] == NULL && t->args[0] == NULL &&
/* we have exactly one variable assignment */ /* we have exactly one variable assignment */
t->vars[0] != NULL && t->vars[1] == NULL && 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 != NULL && t->ioact[0] != NULL &&
t->ioact[1] == NULL && t->ioact[1] == NULL &&
/* of type "here document" (or "here string") */ /* 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]); fptreef(shf, indent, "%S", t->vars[0]);
break; break;
} }