mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 16:39:53 +02:00
fix parser state with funsubs in PS2 and line continuations; fix for @P transformation in prompt strings
This commit is contained in:
@@ -8997,3 +8997,44 @@ Makefile.in
|
||||
- distclean,maintainer-clean: remove $(CREATED_HEADERS) and
|
||||
$(CREATED_MACOS)
|
||||
- maintainer-clean: remove ctags/etags files
|
||||
|
||||
3/28
|
||||
----
|
||||
bashline.c,bashline.h
|
||||
- uw_restore_parser_state: moved to parse.y and declaration to shell.h
|
||||
|
||||
shell.c,shell.h
|
||||
- parsing_command: new flag, set to 1 when calling yyparse; saved and
|
||||
restored by save_parser_state/restore_parser_state
|
||||
|
||||
parse.y,shell.h
|
||||
- parsing_command: new element of sh_parser_state_t
|
||||
|
||||
sig.c
|
||||
- throw_to_top_level: reset executing and parsing_command to 0
|
||||
|
||||
parse.y
|
||||
- parse_comsub: set parsing_command to 1 before calling yyparse()
|
||||
|
||||
eval.c
|
||||
- parse_command: set parsing_command to 1 before calling yyparse(),
|
||||
restore old value when yyparse returns
|
||||
|
||||
subst.c
|
||||
- function_substitute: if we are parsing a command, save the parser
|
||||
state with save_parser_state and add an unwind-protect to restore it
|
||||
From a report from Grisha Levit <grishalevit@gmail.com>
|
||||
- function_substitute: only save and restore the pipestatus array if
|
||||
we are not parsing a command, since save_parser_state saves it
|
||||
|
||||
parse.y,externs.h
|
||||
- decode_prompt_string: now takes an additional argument to determine
|
||||
whether this is expanding PS[0124] or the @P transformation
|
||||
- decode_prompt_string: keep track of the (last) real prompt string
|
||||
being decoded so a @P expansion embedded in the prompt returns the
|
||||
same result as the prompt string itself for the \! and \# expansions
|
||||
From a patch from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
parse.y,print_cmd.c,eval.c,subst.c
|
||||
- decode_prompt_string: changed all callers
|
||||
|
||||
|
||||
+4
-3
@@ -586,7 +586,8 @@ CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
|
||||
CREATED_MACOS = recho.dSYM zecho.dSYM printenv.dSYM xcase.dSYM \
|
||||
bashversion.dSYM mksyntax.dSYM ${DEFDIR}/psize.aux.dSYM
|
||||
CREATED_CONFIGURE = config.h config.cache config.status config.log \
|
||||
stamp-h po/POTFILES config.status.lineno
|
||||
stamp-h po/POTFILES config.status.lineno \
|
||||
stdckdint.h
|
||||
CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
|
||||
lib/readline/Makefile lib/glob/Makefile \
|
||||
lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
|
||||
@@ -595,7 +596,7 @@ CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
|
||||
examples/loadables/perl/Makefile support/Makefile \
|
||||
lib/intl/Makefile po/Makefile po/Makefile.in
|
||||
CREATED_HEADERS = signames.h config.h pathnames.h version.h y.tab.h \
|
||||
${DEFDIR}/builtext.h stdckdint.h
|
||||
${DEFDIR}/builtext.h
|
||||
|
||||
OTHER_DOCS = $(srcdir)/CHANGES $(srcdir)/COMPAT $(srcdir)/NEWS $(srcdir)/POSIX \
|
||||
$(srcdir)/RBASH $(srcdir)/README
|
||||
@@ -988,7 +989,7 @@ maintainer-clean: basic-clean
|
||||
done
|
||||
-( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
|
||||
-( cd $(LOADABLES_DIR) && $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
|
||||
$(RM) $(CREATED_CONFIGURE) Makefile $(CREATED_MAKEFILES) tags TAGS
|
||||
$(RM) $(CREATED_CONFIGURE) Makefile $(CREATED_MAKEFILES)
|
||||
$(RM) $(CREATED_SUPPORT) $(CREATED_HEADERS)
|
||||
$(RM) -rf $(CREATED_MACOS)
|
||||
|
||||
|
||||
@@ -4490,12 +4490,6 @@ readline_set_char_offset (int ind, int *varp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
uw_restore_parser_state (void *ps)
|
||||
{
|
||||
restore_parser_state (ps);
|
||||
}
|
||||
|
||||
void
|
||||
uw_rl_set_signals (void *ignore)
|
||||
{
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
/* bashline.h -- interface to the bash readline functions in bashline.c. */
|
||||
|
||||
/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -46,7 +46,6 @@ extern int bash_re_edit (const char *);
|
||||
extern void bashline_set_event_hook (void);
|
||||
extern void bashline_reset_event_hook (void);
|
||||
|
||||
extern void uw_restore_parser_state (void *);
|
||||
extern void uw_rl_set_signals (void *);
|
||||
|
||||
extern int bind_keyseq_to_unix_command (char *);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eval.c -- reading and evaluating commands. */
|
||||
|
||||
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -157,7 +157,7 @@ reader_loop (void)
|
||||
|
||||
old_eof = EOF_Reached;
|
||||
EOF_Reached = 0;
|
||||
ps0_string = decode_prompt_string (ps0_prompt);
|
||||
ps0_string = decode_prompt_string (ps0_prompt, 1);
|
||||
if (ps0_string && *ps0_string)
|
||||
{
|
||||
fprintf (stderr, "%s", ps0_string);
|
||||
@@ -329,7 +329,7 @@ execute_prompt_command (void)
|
||||
int
|
||||
parse_command (void)
|
||||
{
|
||||
int r;
|
||||
int r, old_parsing;
|
||||
|
||||
need_here_doc = 0;
|
||||
if ((parser_state & (PST_CMDSUBST|PST_FUNSUBST)) == 0)
|
||||
@@ -352,11 +352,14 @@ parse_command (void)
|
||||
send_pwd_to_eterm (); /* Yuck */
|
||||
}
|
||||
|
||||
old_parsing = parsing_command;
|
||||
parsing_command = 1;
|
||||
current_command_line_count = 0;
|
||||
r = yyparse ();
|
||||
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
parsing_command = old_parsing;
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ extern void clear_shell_input_line (void);
|
||||
|
||||
extern int handle_ignoreeof (int);
|
||||
|
||||
extern char *decode_prompt_string (char *);
|
||||
extern char *decode_prompt_string (char *, int);
|
||||
|
||||
extern int get_current_prompt_level (void);
|
||||
extern void set_current_prompt_level (int);
|
||||
|
||||
@@ -4462,6 +4462,7 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
|
||||
current_token = '\n'; /* XXX */
|
||||
token_to_read = (open == '(') ? DOLPAREN : DOLBRACE; /* let's trick the parser ) */
|
||||
|
||||
parsing_command = 1; /* saved as part of sh_parser_state_t */
|
||||
r = yyparse ();
|
||||
|
||||
if (open == '{')
|
||||
@@ -5879,7 +5880,7 @@ reset_readline_prompt (void)
|
||||
if (prompt_string_pointer)
|
||||
{
|
||||
temp_prompt = (*prompt_string_pointer)
|
||||
? decode_prompt_string (*prompt_string_pointer)
|
||||
? decode_prompt_string (*prompt_string_pointer, 1)
|
||||
: (char *)NULL;
|
||||
|
||||
if (temp_prompt == 0)
|
||||
@@ -6040,7 +6041,7 @@ prompt_again (int force)
|
||||
prompt_string_pointer = &ps1_prompt;
|
||||
|
||||
temp_prompt = *prompt_string_pointer
|
||||
? decode_prompt_string (*prompt_string_pointer)
|
||||
? decode_prompt_string (*prompt_string_pointer, 1)
|
||||
: (char *)NULL;
|
||||
|
||||
if (temp_prompt == 0)
|
||||
@@ -6140,13 +6141,16 @@ prompt_history_number (char *pmt)
|
||||
\\ a backslash
|
||||
\[ begin a sequence of non-printing chars
|
||||
\] end a sequence of non-printing chars
|
||||
|
||||
IS_PROMPT is non-zero if we are decoding one of the PS[0124] prompt strings
|
||||
instead of an arbitrary string applying the @P transformation.
|
||||
*/
|
||||
#define PROMPT_GROWTH 48
|
||||
char *
|
||||
decode_prompt_string (char *string)
|
||||
decode_prompt_string (char *string, int is_prompt)
|
||||
{
|
||||
WORD_LIST *list;
|
||||
char *result, *t, *orig_string, *last_lastarg;
|
||||
char *result, *t, *last_lastarg;
|
||||
struct dstack save_dstack;
|
||||
int last_exit_value, last_comsub_pid, last_comsub_status;
|
||||
#if defined (PROMPT_STRING_DECODE)
|
||||
@@ -6159,11 +6163,16 @@ decode_prompt_string (char *string)
|
||||
char timebuf[128];
|
||||
char *timefmt;
|
||||
size_t tslen;
|
||||
static char *decoding_prompt;
|
||||
|
||||
result = (char *)xmalloc (result_size = PROMPT_GROWTH);
|
||||
result[result_index = 0] = 0;
|
||||
temp = (char *)NULL;
|
||||
orig_string = string;
|
||||
|
||||
/* Keep track of which (real) prompt string is being decoded so that we can
|
||||
process embedded ${var@P} expansions correctly. */
|
||||
if (is_prompt)
|
||||
decoding_prompt = string;
|
||||
|
||||
while (c = *string++)
|
||||
{
|
||||
@@ -6179,7 +6188,7 @@ decode_prompt_string (char *string)
|
||||
#if !defined (HISTORY)
|
||||
temp = savestring ("1");
|
||||
#else /* HISTORY */
|
||||
temp = itos (prompt_history_number (orig_string));
|
||||
temp = itos (prompt_history_number (decoding_prompt));
|
||||
#endif /* HISTORY */
|
||||
string--; /* add_string increments string again. */
|
||||
goto add_string;
|
||||
@@ -6440,7 +6449,7 @@ decode_prompt_string (char *string)
|
||||
n = current_command_number;
|
||||
/* If we have already incremented current_command_number (PS4,
|
||||
${var@P}), compensate */
|
||||
if (orig_string != ps0_prompt && orig_string != ps1_prompt && orig_string != ps2_prompt)
|
||||
if (decoding_prompt != ps0_prompt && decoding_prompt != ps1_prompt && decoding_prompt != ps2_prompt)
|
||||
n--;
|
||||
temp = itos (n);
|
||||
goto add_string;
|
||||
@@ -6449,7 +6458,7 @@ decode_prompt_string (char *string)
|
||||
#if !defined (HISTORY)
|
||||
temp = savestring ("1");
|
||||
#else /* HISTORY */
|
||||
temp = itos (prompt_history_number (orig_string));
|
||||
temp = itos (prompt_history_number (decoding_prompt));
|
||||
#endif /* HISTORY */
|
||||
goto add_string;
|
||||
|
||||
@@ -6574,6 +6583,10 @@ not_escape:
|
||||
}
|
||||
|
||||
dstack = save_dstack;
|
||||
#if defined (PROMPT_STRING_DECODE)
|
||||
if (is_prompt)
|
||||
decoding_prompt = (char *)NULL;
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
@@ -7081,6 +7094,8 @@ save_parser_state (sh_parser_state_t *ps)
|
||||
ps->parser_state = parser_state;
|
||||
ps->token_state = save_token_state ();
|
||||
|
||||
ps->parsing_command = parsing_command;
|
||||
|
||||
ps->input_line_terminator = shell_input_line_terminator;
|
||||
ps->eof_encountered = eof_encountered;
|
||||
ps->eol_lookahead = eol_ungetc_lookahead;
|
||||
@@ -7143,6 +7158,7 @@ restore_parser_state (sh_parser_state_t *ps)
|
||||
restore_token_state (ps->token_state);
|
||||
free (ps->token_state);
|
||||
}
|
||||
parsing_command = ps->parsing_command;
|
||||
|
||||
shell_input_line_terminator = ps->input_line_terminator;
|
||||
eof_encountered = ps->eof_encountered;
|
||||
@@ -7195,6 +7211,12 @@ restore_parser_state (sh_parser_state_t *ps)
|
||||
shell_eof_token = ps->eof_token;
|
||||
}
|
||||
|
||||
void
|
||||
uw_restore_parser_state (void *ps)
|
||||
{
|
||||
restore_parser_state (ps);
|
||||
}
|
||||
|
||||
/* Free the parts of a parser state struct that have allocated memory. */
|
||||
void
|
||||
flush_parser_state (sh_parser_state_t *ps)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* parser.h -- Everything you wanted to know about the parser, but were
|
||||
afraid to ask. */
|
||||
|
||||
/* Copyright (C) 1995-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -460,7 +460,7 @@ indirection_level_string (void)
|
||||
return (indirection_string);
|
||||
|
||||
old = change_flag ('x', FLAG_OFF);
|
||||
ps4 = decode_prompt_string (ps4);
|
||||
ps4 = decode_prompt_string (ps4, 1);
|
||||
if (old)
|
||||
change_flag ('x', FLAG_ON);
|
||||
|
||||
|
||||
@@ -170,6 +170,9 @@ int debugging_login_shell = 0;
|
||||
/* The environment that the shell passes to other commands. */
|
||||
char **shell_environment;
|
||||
|
||||
/* Non-zero when we are parsing a command, managed by parse_command/parse_comsub */
|
||||
int parsing_command = 0;
|
||||
|
||||
/* Non-zero when we are executing a top-level command. */
|
||||
int executing = 0;
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ extern char *command_execution_string;
|
||||
|
||||
extern int debugging_mode;
|
||||
extern int executing, login_shell;
|
||||
extern int parsing_command;
|
||||
extern int interactive, interactive_shell;
|
||||
extern int startup_state;
|
||||
extern int reading_shell_script;
|
||||
@@ -175,6 +176,7 @@ typedef struct _sh_parser_state_t
|
||||
/* parsing state */
|
||||
int parser_state;
|
||||
int *token_state;
|
||||
int parsing_command;
|
||||
|
||||
char *token;
|
||||
size_t token_buffer_size;
|
||||
@@ -240,6 +242,7 @@ extern char *parser_remaining_input (void);
|
||||
extern sh_parser_state_t *save_parser_state (sh_parser_state_t *);
|
||||
extern void restore_parser_state (sh_parser_state_t *);
|
||||
extern void flush_parser_state (sh_parser_state_t *);
|
||||
extern void uw_restore_parser_state (void *);
|
||||
|
||||
extern sh_input_line_state_t *save_input_line_state (sh_input_line_state_t *);
|
||||
extern void restore_input_line_state (sh_input_line_state_t *);
|
||||
|
||||
@@ -468,6 +468,8 @@ throw_to_top_level (void)
|
||||
comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
|
||||
variable_context = 0;
|
||||
|
||||
executing = parsing_command = 0;
|
||||
|
||||
if (interactive && print_newline)
|
||||
{
|
||||
fflush (stdout);
|
||||
|
||||
@@ -6961,9 +6961,10 @@ function_substitute (char *string, int quoted, int flags)
|
||||
char *afn;
|
||||
sigset_t set, oset;
|
||||
sh_getopt_state_t *gs;
|
||||
sh_parser_state_t ps;
|
||||
SHELL_VAR *gv;
|
||||
#if defined (ARRAY_VARS)
|
||||
ARRAY *ps;
|
||||
ARRAY *psa;
|
||||
#endif
|
||||
|
||||
if (valsub = (string && *string == '|'))
|
||||
@@ -7014,9 +7015,18 @@ function_substitute (char *string, int quoted, int flags)
|
||||
add_unwind_protect (uw_pop_var_context, 0);
|
||||
add_unwind_protect (uw_maybe_restore_getopt_state, gs);
|
||||
|
||||
if (parsing_command)
|
||||
{
|
||||
save_parser_state (&ps);
|
||||
add_unwind_protect (uw_restore_parser_state, &ps);
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
ps = save_pipestatus_array ();
|
||||
add_unwind_protect (uw_restore_pipestatus_array, ps);
|
||||
if (parsing_command == 0)
|
||||
{
|
||||
psa = save_pipestatus_array ();
|
||||
add_unwind_protect (uw_restore_pipestatus_array, psa);
|
||||
}
|
||||
#endif
|
||||
|
||||
subst_assign_varlist = 0;
|
||||
@@ -8756,7 +8766,7 @@ string_transform (int xc, SHELL_VAR *v, char *s)
|
||||
ret = ansicstr (s, strlen (s), 0, 0, 0);
|
||||
break;
|
||||
case 'P':
|
||||
ret = decode_prompt_string (s);
|
||||
ret = decode_prompt_string (s, 0);
|
||||
break;
|
||||
case 'Q':
|
||||
ret = sh_quote_reusable (s, 0);
|
||||
|
||||
Reference in New Issue
Block a user