hush: fix handling of by backslash-newline in $((arith)) and $(cmd)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d17a91db6e
commit
657086a3dc
54
shell/hush.c
54
shell/hush.c
@ -2387,6 +2387,15 @@ static void o_addchr(o_string *o, int ch)
|
|||||||
o->data[o->length] = '\0';
|
o->data[o->length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Valid only if we know o_string is not empty */
|
||||||
|
static void o_delchr(o_string *o)
|
||||||
|
{
|
||||||
|
o->length--;
|
||||||
|
o->data[o->length] = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void o_addblock(o_string *o, const char *str, int len)
|
static void o_addblock(o_string *o, const char *str, int len)
|
||||||
{
|
{
|
||||||
o_grow_by(o, len);
|
o_grow_by(o, len);
|
||||||
@ -3900,6 +3909,23 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
|||||||
/* command remains "open", available for possible redirects */
|
/* command remains "open", available for possible redirects */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int i_peek_and_eat_bkslash_nl(struct in_str *input)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
int ch, ch2;
|
||||||
|
|
||||||
|
ch = i_peek(input);
|
||||||
|
if (ch != '\\')
|
||||||
|
return ch;
|
||||||
|
ch2 = i_peek2(input);
|
||||||
|
if (ch2 != '\n')
|
||||||
|
return ch;
|
||||||
|
/* backslash+newline, skip it */
|
||||||
|
i_getch(input);
|
||||||
|
i_getch(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
|
#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
|
||||||
/* Subroutines for copying $(...) and `...` things */
|
/* Subroutines for copying $(...) and `...` things */
|
||||||
static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
|
static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
|
||||||
@ -4017,7 +4043,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
|
|||||||
if (!dbl)
|
if (!dbl)
|
||||||
break;
|
break;
|
||||||
/* we look for closing )) of $((EXPR)) */
|
/* we look for closing )) of $((EXPR)) */
|
||||||
if (i_peek(input) == end_ch) {
|
if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
|
||||||
i_getch(input); /* eat second ')' */
|
i_getch(input); /* eat second ')' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4055,6 +4081,13 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
|
|||||||
syntax_error_unterm_ch(')');
|
syntax_error_unterm_ch(')');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if (ch == '\n') {
|
||||||
|
/* "backslash+newline", ignore both */
|
||||||
|
o_delchr(dest); /* undo insertion of '\' */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
o_addchr(dest, ch);
|
o_addchr(dest, ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -4073,7 +4106,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
o_string *dest,
|
o_string *dest,
|
||||||
struct in_str *input, unsigned char quote_mask)
|
struct in_str *input, unsigned char quote_mask)
|
||||||
{
|
{
|
||||||
int ch = i_peek(input); /* first character after the $ */
|
int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */
|
||||||
|
|
||||||
debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
|
debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
|
||||||
if (isalpha(ch)) {
|
if (isalpha(ch)) {
|
||||||
@ -4085,18 +4118,8 @@ static int parse_dollar(o_string *as_string,
|
|||||||
debug_printf_parse(": '%c'\n", ch);
|
debug_printf_parse(": '%c'\n", ch);
|
||||||
o_addchr(dest, ch | quote_mask);
|
o_addchr(dest, ch | quote_mask);
|
||||||
quote_mask = 0;
|
quote_mask = 0;
|
||||||
next_ch:
|
ch = i_peek_and_eat_bkslash_nl(input);
|
||||||
ch = i_peek(input);
|
|
||||||
if (!isalnum(ch) && ch != '_') {
|
if (!isalnum(ch) && ch != '_') {
|
||||||
if (ch == '\\') {
|
|
||||||
/* If backslash+newline, skip it */
|
|
||||||
int ch2 = i_peek2(input);
|
|
||||||
if (ch2 == '\n') {
|
|
||||||
i_getch(input);
|
|
||||||
i_getch(input);
|
|
||||||
goto next_ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* End of variable name reached */
|
/* End of variable name reached */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4126,6 +4149,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
ch = i_getch(input); /* eat '{' */
|
ch = i_getch(input); /* eat '{' */
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
|
|
||||||
|
i_peek_and_eat_bkslash_nl(input);
|
||||||
ch = i_getch(input); /* first char after '{' */
|
ch = i_getch(input); /* first char after '{' */
|
||||||
/* It should be ${?}, or ${#var},
|
/* It should be ${?}, or ${#var},
|
||||||
* or even ${?+subst} - operator acting on a special variable,
|
* or even ${?+subst} - operator acting on a special variable,
|
||||||
@ -4232,7 +4256,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
# if ENABLE_SH_MATH_SUPPORT
|
# if ENABLE_SH_MATH_SUPPORT
|
||||||
if (i_peek(input) == '(') {
|
if (i_peek_and_eat_bkslash_nl(input) == '(') {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
@ -4269,7 +4293,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
case '_':
|
case '_':
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
ch = i_peek(input);
|
ch = i_peek_and_eat_bkslash_nl(input);
|
||||||
if (isalnum(ch)) { /* it's $_name or $_123 */
|
if (isalnum(ch)) { /* it's $_name or $_123 */
|
||||||
ch = '_';
|
ch = '_';
|
||||||
goto make_var;
|
goto make_var;
|
||||||
|
Loading…
Reference in New Issue
Block a user