bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] fix cmd and hist nums in ${var@P} inside $PS[012]


From: Grisha Levit
Subject: [PATCH] fix cmd and hist nums in ${var@P} inside $PS[012]
Date: Tue, 26 Mar 2024 09:02:58 -0400

When \# or \! is decoded in a ${var@P} expansion embedded in a prompt
string, the value can be off by one from that of the same sequence
embedded directly in the prompt string.

    $ H='\!'
    $ PS1='(\!:${H@P}) $'
    (3:2 501:500) $

* parse.y
- decode_prompt_string: accept new int flag to signify a real prompt
  string is being decoded; update callers
* externs.h
- decode_prompt_string: update declaration
---
 eval.c      |  2 +-
 externs.h   |  2 +-
 parse.y     | 23 ++++++++++++++++-------
 print_cmd.c |  2 +-
 subst.c     |  2 +-
 5 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/eval.c b/eval.c
index a08cb578..2fee976c 100644
--- a/eval.c
+++ b/eval.c
@@ -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);
diff --git a/externs.h b/externs.h
index b60fb79e..683c72f6 100644
--- a/externs.h
+++ b/externs.h
@@ -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);
diff --git a/parse.y b/parse.y
index 3e28d24d..3211ea64 100644
--- a/parse.y
+++ b/parse.y
@@ -6036,7 +6036,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)
@@ -6139,10 +6139,10 @@ prompt_history_number (char *pmt)
 */
 #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)
@@ -6155,11 +6155,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++)
     {
@@ -6175,7 +6180,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;
@@ -6436,7 +6441,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;
@@ -6445,7 +6450,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;
 
@@ -6570,6 +6575,10 @@ not_escape:
     }
 
   dstack = save_dstack;
+#if defined (PROMPT_STRING_DECODE)
+  if (is_prompt)
+    decoding_prompt = (char *)NULL;
+#endif
 
   return (result);
 }
diff --git a/print_cmd.c b/print_cmd.c
index 9d3ab73b..36268e19 100644
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -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);
 
diff --git a/subst.c b/subst.c
index 2c51021b..ee0afd67 100644
--- a/subst.c
+++ b/subst.c
@@ -8745,7 +8745,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);
-- 
2.44.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]