summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y40
1 files changed, 33 insertions, 7 deletions
diff --git a/parse.y b/parse.y
index 2ca3d600..30315803 100644
--- a/parse.y
+++ b/parse.y
@@ -3807,7 +3807,7 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
count--;
/* handle nested ${...} specially. */
else if MBTEST(open != close && (tflags & LEX_WASDOL) && open == '{' && ch == open) /* } */
- count++;
+ count++; /* XXX */
else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
count++;
@@ -3961,10 +3961,21 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
FREE (nestret);
}
else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
+ /* This also handles ${ command; } */
goto parse_dollar_word;
else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/
/* $() inside $(( ))/$[ ] */
goto parse_dollar_word;
+ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '{') /*)*/
+ /* ${} inside $(( ))/$[ ] */
+ {
+ int npeek;
+ npeek = shell_getc (1);
+ shell_ungetc (npeek);
+ if (FUNSUB_CHAR (npeek))
+ goto parse_dollar_word;
+ }
+
#if defined (PROCESS_SUBSTITUTION)
/* XXX - technically this should only be recognized at the start of
a word */
@@ -4272,7 +4283,7 @@ static char *
parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
{
int peekc, r;
- int start_lineno, dolbrace_spec, local_extglob, was_extpat;
+ int start_lineno, dolbrace_spec, local_extglob, was_extpat, was_word;
char *ret, *tcmd;
size_t retlen;
sh_parser_state_t ps;
@@ -4292,7 +4303,11 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
{
peekc = shell_getc (1);
if (FUNSUB_CHAR (peekc))
- dolbrace_spec = peekc;
+ {
+ dolbrace_spec = peekc;
+ if (dolbrace_spec == '(') /* ksh93 compatibility ) */
+ shell_ungetc (peekc);
+ }
else
{
shell_ungetc (peekc);
@@ -4308,6 +4323,7 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
save_parser_state (&ps);
was_extpat = (parser_state & PST_EXTPAT);
+ was_word = 0;
/* State flags we don't want to persist into command substitutions. */
parser_state &= ~(PST_REGEXP|PST_EXTPAT|PST_CONDCMD|PST_CONDEXPR|PST_COMPASSIGN);
@@ -4353,6 +4369,14 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
r = yyparse ();
+ if (open == '{')
+ {
+ if (current_token == shell_eof_token &&
+ (last_read_token == ';' || last_read_token == '\n') &&
+ (token_before_that == WORD || token_before_that == ASSIGNMENT_WORD))
+ was_word = 1;
+ }
+
if (need_here_doc > 0)
{
internal_warning ("command substitution: %d unterminated here-document%s", need_here_doc, (need_here_doc == 1) ? "" : "s");
@@ -4442,6 +4466,8 @@ INTERNAL_DEBUG(("current_token (%d) != shell_eof_token (%c)", current_token, she
strcpy (ret + 1, tcmd); /* ( */
if (lastc != '\n' && lastc != ';' && lastc != '&' && lastc != ')')
ret[retlen++] = ';';
+ else if (lastc == ')' && was_word) /* right paren can end a word */
+ ret[retlen++] = ';';
ret[retlen++] = ' ';
}
ret[retlen++] = close;
@@ -4457,7 +4483,7 @@ INTERNAL_DEBUG(("current_token (%d) != shell_eof_token (%c)", current_token, she
return ret;
}
-/* Recursively call the parser to parse a $(...) command substitution. This is
+/* Recursively call the parser to parse a command substitution. This is
called by the word expansion code and so does not have to reset as much
parser state before calling yyparse(). */
char *
@@ -4515,7 +4541,7 @@ xparse_dolparen (const char *base, char *string, int *indp, int flags)
local_extglob = extended_glob;
#endif
- if (funsub && FUNSUB_CHAR (*string))
+ if (funsub && FUNSUB_CHAR (*string) && *string == '|')
string++;
token_to_read = funsub ? DOLBRACE : DOLPAREN; /* let's trick the parser */
@@ -4531,7 +4557,7 @@ xparse_dolparen (const char *base, char *string, int *indp, int flags)
/* reset_parser() clears shell_input_line and associated variables, including
parser_state, so we want to reset things, then restore what we need. */
restore_input_line_state (&ls);
- restore_parser_state (&ps);
+ restore_parser_state (&ps); /* restores shell_eof_token */
#if defined (EXTENDED_GLOB)
extended_glob = local_extglob;
@@ -4580,7 +4606,7 @@ xparse_dolparen (const char *base, char *string, int *indp, int flags)
{
/*(*/
if ((flags & SX_NOERROR) == 0)
- parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), ')');
+ parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), closer);
jump_to_top_level (DISCARD);
}