[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: No form commsub if last token ends with & or ;
From: |
Grisha Levit |
Subject: |
Re: No form commsub if last token ends with & or ; |
Date: |
Sun, 18 Jun 2023 04:59:26 -0400 |
On Sunday, May 28, 2023, Grisha Levit <grishalevit@gmail.com> wrote:
> Missing final `;':
>
> "$BASH" --pretty-print <<< $'${ : \;;}'
> ${ : \; }
>
The latest set of fixes to this code solves these cases but others have
issues:
$ bash --pretty-print <<<$'${ : \;;\n}'
${ : \; }
$ bash --pretty-print <<<$'${ : \;\n\n}'
${ : \; }
$ bash --pretty-print <<<$'${ : \&;\n}'
${ : \& }
$ bash --pretty-print <<<$'${ : \&;\n\n}'
${ : \& }
I think it might be ok to just have print_comsub handle adding the final
semicolon when needed instead of trying to add it after the fact in
parse_comsub?
(Patch below includes earlier fixes to semicolon() from
https://lists.gnu.org/archive/html/bug-bash/2023-06/msg00018.html)
---
diff --git a/externs.h b/externs.h
index a1363d4d..b1eb53dc 100644
--- a/externs.h
+++ b/externs.h
@@ -36,7 +36,7 @@ extern intmax_t evalexp (const char *, int, int *);
#define FUNC_EXTERNAL 0x02
extern char *make_command_string (COMMAND *);
-extern char *print_comsub (COMMAND *);
+extern char *print_comsub (COMMAND *, int);
extern char *named_function_string (char *, COMMAND *, int);
extern void print_command (COMMAND *);
diff --git a/parse.y b/parse.y
index c139a4d7..150bba65 100644
--- a/parse.y
+++ b/parse.y
@@ -4297,7 +4297,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, was_word;
+ int start_lineno, dolbrace_spec, local_extglob, was_extpat;
char *ret, *tcmd;
size_t retlen;
sh_parser_state_t ps;
@@ -4342,7 +4342,6 @@ 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);
@@ -4388,14 +4387,6 @@ 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");
@@ -4459,7 +4450,7 @@ INTERNAL_DEBUG(("current_token (%d) !=
shell_eof_token (%c)", current_token, she
restore_parser_state (&ps);
pushed_string_list = saved_strings;
- tcmd = print_comsub (parsed_command); /* returns static
memory */
+ tcmd = print_comsub (parsed_command, open); /* returns static
memory */
retlen = strlen (tcmd);
if (open == '(') /* ) */
{
@@ -4481,17 +4472,10 @@ INTERNAL_DEBUG(("current_token (%d) !=
shell_eof_token (%c)", current_token, she
}
else /* open == '{' } */
{
- int lastc;
-
- lastc = tcmd[retlen - 1];
retlen++;
- ret = xmalloc (retlen + 4);
+ ret = xmalloc (retlen + 3);
ret[0] = (dolbrace_spec == '|') ? '|' : ' ';
- strcpy (ret + 1, tcmd); /* ( */
- if (was_word)
- ret[retlen++] = ';';
- else if (lastc != '\n' && lastc != ';' && lastc != '&')
- ret[retlen++] = ';';
+ strcpy (ret + 1, tcmd);
ret[retlen++] = ' ';
}
ret[retlen++] = close;
diff --git a/print_cmd.c b/print_cmd.c
index 29870837..0a403c6f 100644
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -161,12 +161,14 @@ make_command_string (COMMAND *command)
back into an external representation without turning newlines into `;'.
Placeholder for other changes, if any are necessary. */
char *
-print_comsub (COMMAND *command)
+print_comsub (COMMAND *command, int open)
{
char *ret;
printing_comsub++;
ret = make_command_string (command);
+ if (open == '{')
+ semicolon();
printing_comsub--;
return ret;
}
@@ -1446,9 +1448,11 @@ indent (int amount)
static void
semicolon (void)
{
- if (command_string_index > 0 &&
- (the_printed_command[command_string_index - 1] == '&' ||
- the_printed_command[command_string_index - 1] == '\n'))
+ if ((command_string_index > 1 &&
+ (the_printed_command[command_string_index - 2] == ' ' &&
+ the_printed_command[command_string_index - 1] == '&')) ||
+ (command_string_index > 0 &&
+ (the_printed_command[command_string_index - 1] == '\n')))
return;
cprintf (";");
}
- Re: No form commsub if last token ends with & or ;,
Grisha Levit <=