ensure aliases in COMSUB are not expanded twice
spotted by Jilles Tjoelker again, thanks
This commit is contained in:
parent
68e8b5ab7c
commit
dd8925a475
18
check.t
18
check.t
@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.504 2011/12/16 20:03:23 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.505 2011/12/29 22:03:12 tg Exp $
|
||||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||||
@ -8226,6 +8226,22 @@ expected-stdout:
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
name: comsub-5
|
||||||
|
description:
|
||||||
|
Check COMSUB works with aliases (does not expand them twice)
|
||||||
|
stdin:
|
||||||
|
alias echo='echo a'
|
||||||
|
foo() {
|
||||||
|
printf '%s\n' "$(echo foo)"
|
||||||
|
}
|
||||||
|
printf '%s\n' "$(echo b)"
|
||||||
|
typeset -f foo
|
||||||
|
expected-stdout:
|
||||||
|
a b
|
||||||
|
foo() {
|
||||||
|
printf "%s\\n" "$(echo foo )"
|
||||||
|
}
|
||||||
|
---
|
||||||
name: comsub-torture
|
name: comsub-torture
|
||||||
description:
|
description:
|
||||||
Check the tree dump functions work correctly
|
Check the tree dump functions work correctly
|
||||||
|
44
syn.c
44
syn.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.71 2011/11/22 18:01:41 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.72 2011/12/29 22:03:15 tg Exp $");
|
||||||
|
|
||||||
extern short subshell_nesting_level;
|
extern short subshell_nesting_level;
|
||||||
extern void yyskiputf8bom(void);
|
extern void yyskiputf8bom(void);
|
||||||
@ -64,6 +64,7 @@ static struct nesting_state nesting; /* \n changed to ; */
|
|||||||
|
|
||||||
static bool reject; /* token(cf) gets symbol again */
|
static bool reject; /* token(cf) gets symbol again */
|
||||||
static int symbol; /* yylex value */
|
static int symbol; /* yylex value */
|
||||||
|
static int sALIAS = ALIAS; /* 0 in yyrecursive */
|
||||||
|
|
||||||
#define REJECT (reject = true)
|
#define REJECT (reject = true)
|
||||||
#define ACCEPT (reject = false)
|
#define ACCEPT (reject = false)
|
||||||
@ -227,7 +228,7 @@ nested(int type, int smark, int emark)
|
|||||||
|
|
||||||
nesting_push(&old_nesting, smark);
|
nesting_push(&old_nesting, smark);
|
||||||
t = c_list(true);
|
t = c_list(true);
|
||||||
musthave(emark, KEYWORD|ALIAS);
|
musthave(emark, KEYWORD|sALIAS);
|
||||||
nesting_pop(&old_nesting);
|
nesting_pop(&old_nesting);
|
||||||
return (block(type, t, NOBLOCK, NOWORDS));
|
return (block(type, t, NOBLOCK, NOWORDS));
|
||||||
}
|
}
|
||||||
@ -260,8 +261,8 @@ get_command(int cf)
|
|||||||
XPinit(args, 16);
|
XPinit(args, 16);
|
||||||
XPinit(vars, 16);
|
XPinit(vars, 16);
|
||||||
|
|
||||||
syniocf = KEYWORD|ALIAS;
|
syniocf = KEYWORD|sALIAS;
|
||||||
switch (c = token(cf|KEYWORD|ALIAS|VARASN)) {
|
switch (c = token(cf|KEYWORD|sALIAS|VARASN)) {
|
||||||
default:
|
default:
|
||||||
REJECT;
|
REJECT;
|
||||||
afree(iops, ATEMP);
|
afree(iops, ATEMP);
|
||||||
@ -273,12 +274,12 @@ get_command(int cf)
|
|||||||
case LWORD:
|
case LWORD:
|
||||||
case REDIR:
|
case REDIR:
|
||||||
REJECT;
|
REJECT;
|
||||||
syniocf &= ~(KEYWORD|ALIAS);
|
syniocf &= ~(KEYWORD|sALIAS);
|
||||||
t = newtp(TCOM);
|
t = newtp(TCOM);
|
||||||
t->lineno = source->line;
|
t->lineno = source->line;
|
||||||
while (/* CONSTCOND */ 1) {
|
while (/* CONSTCOND */ 1) {
|
||||||
cf = (t->u.evalflags ? ARRAYVAR : 0) |
|
cf = (t->u.evalflags ? ARRAYVAR : 0) |
|
||||||
(XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD);
|
(XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD);
|
||||||
switch (tpeek(cf)) {
|
switch (tpeek(cf)) {
|
||||||
case REDIR:
|
case REDIR:
|
||||||
while ((iop = synio(cf)) != NULL) {
|
while ((iop = synio(cf)) != NULL) {
|
||||||
@ -442,12 +443,12 @@ get_command(int cf)
|
|||||||
t = newtp(TIF);
|
t = newtp(TIF);
|
||||||
t->left = c_list(true);
|
t->left = c_list(true);
|
||||||
t->right = thenpart();
|
t->right = thenpart();
|
||||||
musthave(FI, KEYWORD|ALIAS);
|
musthave(FI, KEYWORD|sALIAS);
|
||||||
nesting_pop(&old_nesting);
|
nesting_pop(&old_nesting);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BANG:
|
case BANG:
|
||||||
syniocf &= ~(KEYWORD|ALIAS);
|
syniocf &= ~(KEYWORD|sALIAS);
|
||||||
t = pipeline(0);
|
t = pipeline(0);
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
syntaxerr(NULL);
|
syntaxerr(NULL);
|
||||||
@ -455,7 +456,7 @@ get_command(int cf)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TIME:
|
case TIME:
|
||||||
syniocf &= ~(KEYWORD|ALIAS);
|
syniocf &= ~(KEYWORD|sALIAS);
|
||||||
t = pipeline(0);
|
t = pipeline(0);
|
||||||
if (t) {
|
if (t) {
|
||||||
t->str = alloc(2, ATEMP);
|
t->str = alloc(2, ATEMP);
|
||||||
@ -506,7 +507,7 @@ dogroup(void)
|
|||||||
int c;
|
int c;
|
||||||
struct op *list;
|
struct op *list;
|
||||||
|
|
||||||
c = token(CONTIN|KEYWORD|ALIAS);
|
c = token(CONTIN|KEYWORD|sALIAS);
|
||||||
/*
|
/*
|
||||||
* A {...} can be used instead of do...done for for/select loops
|
* A {...} can be used instead of do...done for for/select loops
|
||||||
* but not for while/until loops - we don't need to check if it
|
* but not for while/until loops - we don't need to check if it
|
||||||
@ -520,7 +521,7 @@ dogroup(void)
|
|||||||
else
|
else
|
||||||
syntaxerr(NULL);
|
syntaxerr(NULL);
|
||||||
list = c_list(true);
|
list = c_list(true);
|
||||||
musthave(c, KEYWORD|ALIAS);
|
musthave(c, KEYWORD|sALIAS);
|
||||||
return (list);
|
return (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +530,7 @@ thenpart(void)
|
|||||||
{
|
{
|
||||||
struct op *t;
|
struct op *t;
|
||||||
|
|
||||||
musthave(THEN, KEYWORD|ALIAS);
|
musthave(THEN, KEYWORD|sALIAS);
|
||||||
t = newtp(0);
|
t = newtp(0);
|
||||||
t->left = c_list(true);
|
t->left = c_list(true);
|
||||||
if (t->left == NULL)
|
if (t->left == NULL)
|
||||||
@ -543,7 +544,7 @@ elsepart(void)
|
|||||||
{
|
{
|
||||||
struct op *t;
|
struct op *t;
|
||||||
|
|
||||||
switch (token(KEYWORD|ALIAS|VARASN)) {
|
switch (token(KEYWORD|sALIAS|VARASN)) {
|
||||||
case ELSE:
|
case ELSE:
|
||||||
if ((t = c_list(true)) == NULL)
|
if ((t = c_list(true)) == NULL)
|
||||||
syntaxerr(NULL);
|
syntaxerr(NULL);
|
||||||
@ -567,7 +568,7 @@ caselist(void)
|
|||||||
struct op *t, *tl;
|
struct op *t, *tl;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = token(CONTIN|KEYWORD|ALIAS);
|
c = token(CONTIN|KEYWORD|sALIAS);
|
||||||
/* A {...} can be used instead of in...esac for case statements */
|
/* A {...} can be used instead of in...esac for case statements */
|
||||||
if (c == IN)
|
if (c == IN)
|
||||||
c = ESAC;
|
c = ESAC;
|
||||||
@ -584,7 +585,7 @@ caselist(void)
|
|||||||
else
|
else
|
||||||
tl->right = tc, tl = tc;
|
tl->right = tc, tl = tc;
|
||||||
}
|
}
|
||||||
musthave(c, KEYWORD|ALIAS);
|
musthave(c, KEYWORD|sALIAS);
|
||||||
return (t);
|
return (t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,7 +614,7 @@ casepart(int endtok)
|
|||||||
/* initialise to default for ;; or omitted */
|
/* initialise to default for ;; or omitted */
|
||||||
t->u.charflag = ';';
|
t->u.charflag = ';';
|
||||||
/* SUSv4 requires the ;; except in the last casepart */
|
/* SUSv4 requires the ;; except in the last casepart */
|
||||||
if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
|
if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok)
|
||||||
switch (symbol) {
|
switch (symbol) {
|
||||||
default:
|
default:
|
||||||
syntaxerr(NULL);
|
syntaxerr(NULL);
|
||||||
@ -659,14 +660,14 @@ function_body(char *name,
|
|||||||
* only accepts an open-brace.
|
* only accepts an open-brace.
|
||||||
*/
|
*/
|
||||||
if (ksh_func) {
|
if (ksh_func) {
|
||||||
if (tpeek(CONTIN|KEYWORD|ALIAS) == '(' /*)*/) {
|
if (tpeek(CONTIN|KEYWORD|sALIAS) == '(' /*)*/) {
|
||||||
/* function foo () { */
|
/* function foo () { */
|
||||||
ACCEPT;
|
ACCEPT;
|
||||||
musthave(')', 0);
|
musthave(')', 0);
|
||||||
/* degrade to POSIX function */
|
/* degrade to POSIX function */
|
||||||
ksh_func = false;
|
ksh_func = false;
|
||||||
}
|
}
|
||||||
musthave('{' /*}*/, CONTIN|KEYWORD|ALIAS);
|
musthave('{' /*}*/, CONTIN|KEYWORD|sALIAS);
|
||||||
REJECT;
|
REJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,7 +712,7 @@ wordlist(void)
|
|||||||
|
|
||||||
XPinit(args, 16);
|
XPinit(args, 16);
|
||||||
/* POSIX does not do alias expansion here... */
|
/* POSIX does not do alias expansion here... */
|
||||||
if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) {
|
if ((c = token(CONTIN|KEYWORD|sALIAS)) != IN) {
|
||||||
if (c != ';')
|
if (c != ';')
|
||||||
/* non-POSIX, but AT&T ksh accepts a ; here */
|
/* non-POSIX, but AT&T ksh accepts a ; here */
|
||||||
REJECT;
|
REJECT;
|
||||||
@ -1107,7 +1108,7 @@ yyrecursive(void)
|
|||||||
struct op *t;
|
struct op *t;
|
||||||
char *cp;
|
char *cp;
|
||||||
bool old_reject;
|
bool old_reject;
|
||||||
int old_symbol;
|
int old_symbol, old_salias;
|
||||||
struct ioword **old_herep;
|
struct ioword **old_herep;
|
||||||
|
|
||||||
/* tell the lexer to accept a closing parenthesis as EOD */
|
/* tell the lexer to accept a closing parenthesis as EOD */
|
||||||
@ -1118,8 +1119,11 @@ yyrecursive(void)
|
|||||||
old_symbol = symbol;
|
old_symbol = symbol;
|
||||||
ACCEPT;
|
ACCEPT;
|
||||||
old_herep = herep;
|
old_herep = herep;
|
||||||
|
old_salias = sALIAS;
|
||||||
|
sALIAS = 0;
|
||||||
/* we use TPAREN as a helper container here */
|
/* we use TPAREN as a helper container here */
|
||||||
t = nested(TPAREN, '(', ')');
|
t = nested(TPAREN, '(', ')');
|
||||||
|
sALIAS = old_salias;
|
||||||
herep = old_herep;
|
herep = old_herep;
|
||||||
reject = old_reject;
|
reject = old_reject;
|
||||||
symbol = old_symbol;
|
symbol = old_symbol;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user