fix var=<< implementation
This commit is contained in:
parent
c52133cc4e
commit
97d1d5e4fe
19
check.t
19
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 -*-
|
# -*- 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
56
exec.c
|
@ -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, don’t 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
18
tree.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue