c58d3fff91
Resolves: #2140722
207 lines
8.2 KiB
Diff
207 lines
8.2 KiB
Diff
diff --git a/builtins/evalstring.c b/builtins/evalstring.c
|
|
--- a/builtins/evalstring.c
|
|
+++ b/builtins/evalstring.c
|
|
@@ -431,6 +431,8 @@ parse_and_execute (string, from_file, flags)
|
|
|
|
if (parse_command () == 0)
|
|
{
|
|
+ int local_expalias, local_alflag;
|
|
+
|
|
if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute))
|
|
{
|
|
last_result = EXECUTION_SUCCESS;
|
|
@@ -507,6 +509,19 @@ parse_and_execute (string, from_file, flags)
|
|
}
|
|
#endif /* ONESHOT */
|
|
|
|
+ /* We play tricks in the parser and command_substitute() turning
|
|
+ expand_aliases on and off depending on which parsing pass and
|
|
+ whether or not we're in posix mode. This only matters for
|
|
+ parsing, and we let the higher layers deal with that. We just
|
|
+ want to ensure that expand_aliases is set to the appropriate
|
|
+ global value when we go to execute this command, so we save
|
|
+ and restore it around the execution (we don't restore it if
|
|
+ the global value of the flag (expaliases_flag) changes). */
|
|
+ local_expalias = expand_aliases;
|
|
+ local_alflag = expaliases_flag;
|
|
+ if (subshell_environment & SUBSHELL_COMSUB)
|
|
+ expand_aliases = expaliases_flag;
|
|
+
|
|
/* See if this is a candidate for $( <file ). */
|
|
if (startup_state == 2 &&
|
|
(subshell_environment & SUBSHELL_COMSUB) &&
|
|
@@ -524,6 +539,10 @@ parse_and_execute (string, from_file, flags)
|
|
dispose_fd_bitmap (bitmap);
|
|
discard_unwind_frame ("pe_dispose");
|
|
|
|
+ /* If the global value didn't change, we restore what we had. */
|
|
+ if ((subshell_environment & SUBSHELL_COMSUB) && local_alflag == expaliases_flag)
|
|
+ expand_aliases = local_expalias;
|
|
+
|
|
if (flags & SEVAL_ONECMD)
|
|
{
|
|
reset_parser ();
|
|
diff --git a/command.h b/command.h
|
|
--- a/command.h
|
|
+++ b/command.h
|
|
@@ -114,6 +114,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
|
#define PF_COMPLETE 0x10 /* same as W_COMPLETE, sets SX_COMPLETE */
|
|
#define PF_EXPANDRHS 0x20 /* same as W_EXPANDRHS */
|
|
#define PF_ALLINDS 0x40 /* array, act as if [@] was supplied */
|
|
+#define PF_BACKQUOTE 0x80 /* differentiate `` from $() for command_substitute */
|
|
|
|
/* Possible values for subshell_environment */
|
|
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
|
diff --git a/parse.y b/parse.y
|
|
--- a/parse.y
|
|
+++ b/parse.y
|
|
@@ -3612,6 +3612,7 @@ tokword:
|
|
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
|
|
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
|
|
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
|
|
+#define P_ARITH 0x0080 /* parsing a $(( )) arithmetic expansion */
|
|
|
|
/* Lexical state while parsing a grouping construct or $(...). */
|
|
#define LEX_WASDOL 0x0001
|
|
@@ -3910,6 +3911,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|
}
|
|
else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
|
goto parse_dollar_word;
|
|
+ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/
|
|
+ /* $() inside $(( ))/$[ ] */
|
|
+ goto parse_dollar_word;
|
|
#if defined (PROCESS_SUBSTITUTION)
|
|
/* XXX - technically this should only be recognized at the start of
|
|
a word */
|
|
@@ -3940,7 +3944,7 @@ parse_dollar_word:
|
|
else if (ch == '{') /* } */
|
|
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
|
|
else if (ch == '[') /* ] */
|
|
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
|
|
+ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags|P_ARITH);
|
|
|
|
CHECK_NESTRET_ERROR ();
|
|
APPEND_NESTRET ();
|
|
@@ -4079,7 +4083,7 @@ parse_comsub (qc, open, close, lenp, flags)
|
|
peekc = shell_getc (1);
|
|
shell_ungetc (peekc);
|
|
if (peekc == '(') /*)*/
|
|
- return (parse_matched_pair (qc, open, close, lenp, 0));
|
|
+ return (parse_matched_pair (qc, open, close, lenp, P_ARITH));
|
|
}
|
|
|
|
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
|
|
@@ -4500,7 +4504,7 @@ parse_arith_cmd (ep, adddq)
|
|
int ttoklen;
|
|
|
|
exp_lineno = line_number;
|
|
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
|
|
+ ttok = parse_matched_pair (0, '(', ')', &ttoklen, P_ARITH);
|
|
rval = 1;
|
|
if (ttok == &matched_pair_error)
|
|
return -1;
|
|
@@ -5015,7 +5019,7 @@ read_token_word (character)
|
|
pop_delimiter (dstack);
|
|
}
|
|
else
|
|
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
|
|
+ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARITH);
|
|
if (ttok == &matched_pair_error)
|
|
return -1; /* Bail immediately. */
|
|
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
|
|
diff --git a/patchlevel.h b/patchlevel.h
|
|
--- a/patchlevel.h
|
|
+++ b/patchlevel.h
|
|
@@ -25,6 +25,6 @@
|
|
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
|
|
looks for to find the patch level (for the sccs version string). */
|
|
|
|
-#define PATCHLEVEL 6
|
|
+#define PATCHLEVEL 7
|
|
|
|
#endif /* _PATCHLEVEL_H_ */
|
|
diff --git a/subst.c b/subst.c
|
|
--- a/subst.c
|
|
+++ b/subst.c
|
|
@@ -7123,8 +7123,12 @@ command_substitute (string, quoted, flags)
|
|
remove_quoted_escapes (string);
|
|
|
|
/* We want to expand aliases on this pass if we are not in posix mode
|
|
- for backwards compatibility. */
|
|
- if (expand_aliases)
|
|
+ for backwards compatibility. parse_and_execute() takes care of
|
|
+ setting expand_aliases back to the global value when executing the
|
|
+ parsed string. We only do this for $(...) command substitution,
|
|
+ since that is what parse_comsub handles; `` comsubs are processed
|
|
+ using parse.y:parse_matched_pair(). */
|
|
+ if (expand_aliases && (flags & PF_BACKQUOTE) == 0)
|
|
expand_aliases = posixly_correct == 0;
|
|
|
|
startup_state = 2; /* see if we can avoid a fork */
|
|
@@ -11292,7 +11296,7 @@ add_string:
|
|
else
|
|
{
|
|
de_backslash (temp);
|
|
- tword = command_substitute (temp, quoted, 0);
|
|
+ tword = command_substitute (temp, quoted, PF_BACKQUOTE);
|
|
temp1 = tword ? tword->word : (char *)NULL;
|
|
if (tword)
|
|
dispose_word_desc (tword);
|
|
diff --git a/y.tab.c b/y.tab.c
|
|
--- a/y.tab.c
|
|
+++ b/y.tab.c
|
|
@@ -5923,6 +5923,7 @@ tokword:
|
|
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
|
|
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
|
|
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
|
|
+#define P_ARITH 0x0080 /* parsing a $(( )) arithmetic expansion */
|
|
|
|
/* Lexical state while parsing a grouping construct or $(...). */
|
|
#define LEX_WASDOL 0x0001
|
|
@@ -6221,6 +6222,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|
}
|
|
else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
|
goto parse_dollar_word;
|
|
+ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/
|
|
+ /* $() inside $(( ))/$[ ] */
|
|
+ goto parse_dollar_word;
|
|
#if defined (PROCESS_SUBSTITUTION)
|
|
/* XXX - technically this should only be recognized at the start of
|
|
a word */
|
|
@@ -6251,7 +6255,7 @@ parse_dollar_word:
|
|
else if (ch == '{') /* } */
|
|
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
|
|
else if (ch == '[') /* ] */
|
|
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
|
|
+ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags|P_ARITH);
|
|
|
|
CHECK_NESTRET_ERROR ();
|
|
APPEND_NESTRET ();
|
|
@@ -6390,7 +6394,7 @@ parse_comsub (qc, open, close, lenp, flags)
|
|
peekc = shell_getc (1);
|
|
shell_ungetc (peekc);
|
|
if (peekc == '(') /*)*/
|
|
- return (parse_matched_pair (qc, open, close, lenp, 0));
|
|
+ return (parse_matched_pair (qc, open, close, lenp, P_ARITH));
|
|
}
|
|
|
|
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
|
|
@@ -6811,7 +6815,7 @@ parse_arith_cmd (ep, adddq)
|
|
int ttoklen;
|
|
|
|
exp_lineno = line_number;
|
|
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
|
|
+ ttok = parse_matched_pair (0, '(', ')', &ttoklen, P_ARITH);
|
|
rval = 1;
|
|
if (ttok == &matched_pair_error)
|
|
return -1;
|
|
@@ -7326,7 +7330,7 @@ read_token_word (character)
|
|
pop_delimiter (dstack);
|
|
}
|
|
else
|
|
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
|
|
+ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARITH);
|
|
if (ttok == &matched_pair_error)
|
|
return -1; /* Bail immediately. */
|
|
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
|