hush: propagate (output,n) parameters into expand_one_var()
This is necessary since expand_one_var() for ${var:+ARG} must create more than one output word, and thus can't simply return a char*. function old new delta expand_one_var 1610 1643 +33 expand_vars_to_list 1139 1125 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 33/-14) Total: 19 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
116b50a5c1
commit
8a6a461504
63
shell/hush.c
63
shell/hush.c
@ -5976,7 +5976,8 @@ static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n
|
|||||||
/* Helper:
|
/* Helper:
|
||||||
* Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
|
* Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
|
||||||
*/
|
*/
|
||||||
static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp)
|
static NOINLINE int expand_one_var(o_string *output,
|
||||||
|
int *ended_in_ifs, int n, int first_ch, char *arg, char **pp)
|
||||||
{
|
{
|
||||||
const char *val;
|
const char *val;
|
||||||
char *to_be_freed;
|
char *to_be_freed;
|
||||||
@ -6038,9 +6039,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
/* Look up the variable in question */
|
/* Look up the variable in question */
|
||||||
if (isdigit(var[0])) {
|
if (isdigit(var[0])) {
|
||||||
/* parse_dollar should have vetted var for us */
|
/* parse_dollar should have vetted var for us */
|
||||||
int n = xatoi_positive(var);
|
int nn = xatoi_positive(var);
|
||||||
if (n < G.global_argc)
|
if (nn < G.global_argc)
|
||||||
val = G.global_argv[n];
|
val = G.global_argv[nn];
|
||||||
/* else val remains NULL: $N with too big N */
|
/* else val remains NULL: $N with too big N */
|
||||||
} else {
|
} else {
|
||||||
switch (var[0]) {
|
switch (var[0]) {
|
||||||
@ -6236,6 +6237,34 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
* Colon forms (${var:-word}, ${var:=word} etc) do the same,
|
* Colon forms (${var:-word}, ${var:=word} etc) do the same,
|
||||||
* but also treat null var as if it is unset.
|
* but also treat null var as if it is unset.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Word-splitting and squote behavior of bash:
|
||||||
|
* $ f() { for i; do echo "|$i|"; done; };
|
||||||
|
*
|
||||||
|
* $ x=; f ${x:?'x y' z}
|
||||||
|
* bash: x: x y z
|
||||||
|
* $ x=; f "${x:?'x y' z}"
|
||||||
|
* bash: x: x y z # dash prints: dash: x: 'x y' z
|
||||||
|
*
|
||||||
|
* $ x=; f ${x:='x y' z}
|
||||||
|
* |x|
|
||||||
|
* |y|
|
||||||
|
* |z|
|
||||||
|
* $ x=; f "${x:='x y' z}"
|
||||||
|
* |'x y' z|
|
||||||
|
*
|
||||||
|
* $ x=x; f ${x:+'x y' z}
|
||||||
|
* |x y|
|
||||||
|
* |z|
|
||||||
|
* $ x=x; f "${x:+'x y' z}"
|
||||||
|
* |'x y' z|
|
||||||
|
*
|
||||||
|
* $ x=; f ${x:-'x y' z}
|
||||||
|
* |x y|
|
||||||
|
* |z|
|
||||||
|
* $ x=; f "${x:-'x y' z}"
|
||||||
|
* |'x y' z|
|
||||||
|
*/
|
||||||
int use_word = (!val || ((exp_save == ':') && !val[0]));
|
int use_word = (!val || ((exp_save == ':') && !val[0]));
|
||||||
if (exp_op == '+')
|
if (exp_op == '+')
|
||||||
use_word = !use_word;
|
use_word = !use_word;
|
||||||
@ -6244,7 +6273,10 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
if (use_word) {
|
if (use_word) {
|
||||||
//FIXME: unquoted ${x:+"b c" d} and ${x:+'b c' d} should expand to two words
|
//FIXME: unquoted ${x:+"b c" d} and ${x:+'b c' d} should expand to two words
|
||||||
//currently it expands to three.
|
//currently it expands to three.
|
||||||
to_be_freed = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ !(arg0 & 0x80), /*unbackslash:*/ 0);
|
to_be_freed = encode_then_expand_vararg(exp_word,
|
||||||
|
/*handle_squotes:*/ !(arg0 & 0x80),
|
||||||
|
/*unbackslash:*/ 0
|
||||||
|
);
|
||||||
if (to_be_freed)
|
if (to_be_freed)
|
||||||
exp_word = to_be_freed;
|
exp_word = to_be_freed;
|
||||||
if (exp_op == '?') {
|
if (exp_op == '?') {
|
||||||
@ -6258,6 +6290,11 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
/*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
|
/*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
|
||||||
);
|
);
|
||||||
//TODO: how interactive bash aborts expansion mid-command?
|
//TODO: how interactive bash aborts expansion mid-command?
|
||||||
|
//It aborts the entire line:
|
||||||
|
// $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
|
||||||
|
// bash: x: x y z
|
||||||
|
// $
|
||||||
|
// ("echo YO" is not executed, neither the f function call)
|
||||||
} else {
|
} else {
|
||||||
val = exp_word;
|
val = exp_word;
|
||||||
}
|
}
|
||||||
@ -6280,10 +6317,12 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
} /* if (exp_op) */
|
} /* if (exp_op) */
|
||||||
|
|
||||||
arg[0] = arg0;
|
arg[0] = arg0;
|
||||||
|
|
||||||
*pp = p;
|
*pp = p;
|
||||||
*to_be_freed_pp = to_be_freed;
|
|
||||||
return val;
|
n = append_str_maybe_ifs_split(output, ended_in_ifs, n, first_ch, val);
|
||||||
|
|
||||||
|
free(to_be_freed);
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand all variable references in given string, adding words to list[]
|
/* Expand all variable references in given string, adding words to list[]
|
||||||
@ -6427,13 +6466,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
default: {
|
default:
|
||||||
char *to_be_freed;
|
n = expand_one_var(output, &ended_in_ifs, n, first_ch, arg, &p);
|
||||||
val = expand_one_var(&to_be_freed, arg, &p);
|
|
||||||
n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, val);
|
|
||||||
free(to_be_freed);
|
|
||||||
goto restore;
|
goto restore;
|
||||||
} /* default: */
|
|
||||||
} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
|
} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
|
||||||
|
|
||||||
if (val && val[0]) {
|
if (val && val[0]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user