- 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
+
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 \
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
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)
}
}
-void
-uw_restore_parser_state (void *ps)
-{
- restore_parser_state (ps);
-}
-
void
uw_rl_set_signals (void *ignore)
{
/* 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.
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 *);
/* 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.
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);
int
parse_command (void)
{
- int r;
+ int r, old_parsing;
need_here_doc = 0;
if ((parser_state & (PST_CMDSUBST|PST_FUNSUBST)) == 0)
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);
}
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);
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 == '{')
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)
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)
\\ 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)
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++)
{
#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;
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;
#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;
}
dstack = save_dstack;
+#if defined (PROMPT_STRING_DECODE)
+ if (is_prompt)
+ decoding_prompt = (char *)NULL;
+#endif
return (result);
}
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;
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;
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)
/* 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.
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);
/* 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;
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;
/* parsing state */
int parser_state;
int *token_state;
+ int parsing_command;
char *token;
size_t token_buffer_size;
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 *);
comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
variable_context = 0;
+ executing = parsing_command = 0;
+
if (interactive && print_newline)
{
fflush (stdout);
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 == '|'))
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;
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);
}
PTR_T
-sh_xreallocarray (PTR_T ptr, size_t nmemb, size_t size, const char *file, int line)
+sh_xreallocarray (PTR_T ptr, size_t nmemb, size_t size, char *file, int line)
{
size_t nbytes;