]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix for multi-level alias expansion with trailing space
authorChet Ramey <chet.ramey@case.edu>
Wed, 18 Jan 2023 18:59:27 +0000 (13:59 -0500)
committerChet Ramey <chet.ramey@case.edu>
Wed, 18 Jan 2023 18:59:27 +0000 (13:59 -0500)
CWRU/CWRU.chlog
parse.y
parser.h
subst.c

index 6e389c07c5764f4f0544af1f201af4d5ef32b24d..b02adc8481994765da1c115f3e6511854bb855a6 100644 (file)
@@ -5057,3 +5057,34 @@ execute_cmd.c
          and isn't trapped, restore the old handler
        - setup_async_signals: call set_signal_async_ignored to set the right
          flags
+
+                                  1/16
+                                  ----
+parse.y
+       - read_token_word: if we're in posix mode, and we find a reserved word
+         before checking a token for aliases, turn off the `check next word
+         for aliases' flag (PST_ALEXPNEXT). This is for compatibility with
+         other shells. From a report by <anonymous4feedback@outlook.com>
+       - shell_getc: make sure the shell is reading a buffered stream before
+         checking the default buffered stream for errors if yy_getc returns 0
+
+                                  1/17
+                                  ----
+subst.c
+       - split_at_delims: if the cursor is at whitespace just preceding a
+         word, and we're doing this for completion (e.g., to build COMP_WORDS),
+         force the creation of an empty word and set the current word to it.
+         This is a change from previous behavior, but a useful one: it makes
+         COMP_WORDS[COMP_CWORD] and $2 to a completion function consistent
+         and the same as the word readline wants to complete. From a report
+         from Naim Favier <n@monade.li> back in 6/2022
+
+parse.y
+       - read_token: turn off PST_ALEXPNEXT if we read a shell metacharacter:
+         we will expand aliases anyway if the token puts the shell in a
+         command word position and we took pains to turn it off for
+         redirection tokens; remove special cases that turned it off
+       - pop_string: don't turn off PST_ALEXPNEXT if it's on; this is what
+         prevents it from being enabled if an alias expansion of more than
+         two aliases ends with a space. Fixes issue reported by
+         <anonymous4feedback@outlook.com>
diff --git a/parse.y b/parse.y
index 14c87c074ede20363a48a376a1c8f20c70895eef..023d5398696664baf507d27f602094fa4046c6c5 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -152,6 +152,11 @@ extern int errno;
 static void debug_parser (int);
 #endif
 
+#if defined (DEBUG)
+static void dump_tflags (int);
+static void dump_pflags (int);
+#endif
+
 static int yy_getc (void);
 static int yy_ungetc (int);
 
@@ -1934,9 +1939,6 @@ push_string (char *s, int expand, alias_t *ap)
   shell_input_line_size = shell_input_line_len = STRLEN (s);
   shell_input_line_index = 0;
   shell_input_line_terminator = '\0';
-#if 0
-  parser_state &= ~PST_ALEXPNEXT;      /* XXX */
-#endif
 
   set_line_mbstate ();
 }
@@ -1962,8 +1964,6 @@ pop_string (void)
 #if defined (ALIAS)
   if (pushed_string_list->expand_alias)
     parser_state |= PST_ALEXPNEXT;
-  else
-    parser_state &= ~PST_ALEXPNEXT;
 #endif
 
   t = pushed_string_list;
@@ -2439,7 +2439,7 @@ shell_getc (int remove_quoted_newline)
              if (i == 0)
                shell_input_line_terminator = EOF;
 #if defined (BUFFERED_INPUT)
-             if (i == 0)
+             if (i == 0 && bash_input.type == st_bstream)
                {
                   BUFFERED_STREAM *bp;
                   bp = get_buffered_stream (default_buffered_input);
@@ -3024,6 +3024,8 @@ static int open_brace_count;
                  word_lineno[word_top] = line_number; \
                } \
 \
+             if (posixly_correct) \
+               parser_state &= ~PST_ALEXPNEXT; \
              return (word_token_alist[i].token); \
            } \
       } \
@@ -3381,6 +3383,7 @@ read_token (int command)
          word_desc_to_read = (WORD_DESC *)NULL;
        }
       token_to_read = 0;
+      /* XXX - PST_ALEXPNEXT? */
       return (result);
     }
 
@@ -3459,10 +3462,9 @@ read_token (int command)
   if MBTEST(shellmeta (character))
     {
 #if defined (ALIAS)
-      /* Turn off alias tokenization iff this character sequence would
-        not leave us ready to read a command. */
-      if (character == '<' || character == '>')
-       parser_state &= ~PST_ALEXPNEXT;
+      /* Turn off alias tokenization, we will perform alias expansion on the
+        next command word if it's one where a command word is acceptable. */
+      parser_state &= ~PST_ALEXPNEXT;
 #endif /* ALIAS */
 
       parser_state &= ~PST_ASSIGNOK;
@@ -3500,10 +3502,6 @@ read_token (int command)
 
            case ';':
              parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
-             parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
              peek_char = shell_getc (1);
              if MBTEST(peek_char == '&')
                return (SEMI_SEMI_AND);
@@ -3553,9 +3551,6 @@ read_token (int command)
       else if MBTEST(character == ';' && peek_char == '&')
        {
          parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
-         parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
          return (SEMI_AND);
        }
 
@@ -3567,9 +3562,6 @@ read_token (int command)
       if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
        {
          parser_state |= PST_ALLOWOPNBRC;
-#if defined (ALIAS)
-         parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
          save_dstart = function_dstart;
          function_dstart = line_number;
        }
@@ -4067,6 +4059,143 @@ dump_tflags (int flags)
   fprintf (stderr, "\n");
   fflush (stderr);
 }
+
+static void
+dump_pflags (int flags)
+{
+  int f;
+
+  f = flags;
+  fprintf (stderr, "%d -> ", f);
+  if (f & PST_CASEPAT)
+    {
+      f &= ~PST_CASEPAT;
+      fprintf (stderr, "PST_CASEPAT%s", f ? "|" : "");
+    }
+  if (f & PST_ALEXPNEXT)
+    {
+      f &= ~PST_ALEXPNEXT;
+      fprintf (stderr, "PST_ALEXPNEXT%s", f ? "|" : "");
+    }
+  if (f & PST_ALLOWOPNBRC)
+    {
+      f &= ~PST_ALLOWOPNBRC;
+      fprintf (stderr, "PST_ALLOWOPNBRC%s", f ? "|" : "");
+    }
+  if (f & PST_NEEDCLOSBRC)
+    {
+      f &= ~PST_NEEDCLOSBRC;
+      fprintf (stderr, "PST_NEEDCLOSBRC%s", f ? "|" : "");
+    }
+  if (f & PST_DBLPAREN)
+    {
+      f &= ~PST_DBLPAREN;
+      fprintf (stderr, "PST_DBLPAREN%s", f ? "|" : "");
+    }
+  if (f & PST_SUBSHELL)
+    {
+      f &= ~PST_SUBSHELL;
+      fprintf (stderr, "PST_SUBSHELL%s", f ? "|" : "");
+    }
+  if (f & PST_CMDSUBST)
+    {
+      f &= ~PST_CMDSUBST;
+      fprintf (stderr, "PST_CMDSUBST%s", f ? "|" : "");
+    }
+  if (f & PST_CASESTMT)
+    {
+      f &= ~PST_CASESTMT;
+      fprintf (stderr, "PST_CASESTMT%s", f ? "|" : "");
+    }
+  if (f & PST_CONDCMD)
+    {
+      f &= ~PST_CONDCMD;
+      fprintf (stderr, "PST_CONDCMD%s", f ? "|" : "");
+    }
+  if (f & PST_CONDEXPR)
+    {
+      f &= ~PST_CONDEXPR;
+      fprintf (stderr, "PST_CONDEXPR%s", f ? "|" : "");
+    }
+  if (f & PST_ARITHFOR)
+    {
+      f &= ~PST_ARITHFOR;
+      fprintf (stderr, "PST_ARITHFOR%s", f ? "|" : "");
+    }
+  if (f & PST_ALEXPAND)
+    {
+      f &= ~PST_ALEXPAND;
+      fprintf (stderr, "PST_ALEXPAND%s", f ? "|" : "");
+    }
+  if (f & PST_EXTPAT)
+    {
+      f &= ~PST_EXTPAT;
+      fprintf (stderr, "PST_EXTPAT%s", f ? "|" : "");
+    }
+  if (f & PST_COMPASSIGN)
+    {
+      f &= ~PST_COMPASSIGN;
+      fprintf (stderr, "PST_COMPASSIGN%s", f ? "|" : "");
+    }
+  if (f & PST_ASSIGNOK)
+    {
+      f &= ~PST_ASSIGNOK;
+      fprintf (stderr, "PST_ASSIGNOK%s", f ? "|" : "");
+    }
+  if (f & PST_EOFTOKEN)
+    {
+      f &= ~PST_EOFTOKEN;
+      fprintf (stderr, "PST_EOFTOKEN%s", f ? "|" : "");
+    }
+  if (f & PST_REGEXP)
+    {
+      f &= ~PST_REGEXP;
+      fprintf (stderr, "PST_REGEXP%s", f ? "|" : "");
+    }
+  if (f & PST_HEREDOC)
+    {
+      f &= ~PST_HEREDOC;
+      fprintf (stderr, "PST_HEREDOC%s", f ? "|" : "");
+    }
+  if (f & PST_REPARSE)
+    {
+      f &= ~PST_REPARSE;
+      fprintf (stderr, "PST_REPARSE%s", f ? "|" : "");
+    }
+  if (f & PST_REDIRLIST)
+    {
+      f &= ~PST_REDIRLIST;
+      fprintf (stderr, "PST_REDIRLIST%s", f ? "|" : "");
+    }
+  if (f & PST_COMMENT)
+    {
+      f &= ~PST_COMMENT;
+      fprintf (stderr, "PST_COMMENT%s", f ? "|" : "");
+    }
+  if (f & PST_ENDALIAS)
+    {
+      f &= ~PST_ENDALIAS;
+      fprintf (stderr, "PST_ENDALIAS%s", f ? "|" : "");
+    }
+  if (f & PST_NOEXPAND)
+    {
+      f &= ~PST_NOEXPAND;
+      fprintf (stderr, "PST_NOEXPAND%s", f ? "|" : "");
+    }
+  if (f & PST_NOERROR)
+    {
+      f &= ~PST_NOERROR;
+      fprintf (stderr, "PST_NOERROR%s", f ? "|" : "");
+    }
+  if (f & PST_STRING)
+    {
+      f &= ~PST_STRING;
+      fprintf (stderr, "PST_STRING%s", f ? "|" : "");
+    }
+
+  fprintf (stderr, "\n");
+  fflush (stderr);
+}
 #endif
 
 /* Parse a $(...) command substitution.  This reads input from the current
index cae3a35f7f10f6b4b16c02874446195a13d1e691..e9c484709dca331ef05934d313830c52e15ffc22 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -29,7 +29,7 @@
 #define PST_CASEPAT    0x000001        /* in a case pattern list */
 #define PST_ALEXPNEXT  0x000002        /* expand next word for aliases */
 #define PST_ALLOWOPNBRC        0x000004        /* allow open brace for function def */
-#define PST_NEEDCLOSBRC        0x000008        /* need close brace */
+#define PST_NEEDCLOSBRC        0x000008        /* need close brace -- unused */
 #define PST_DBLPAREN   0x000010        /* double-paren parsing - unused */
 #define PST_SUBSHELL   0x000020        /* ( ... ) subshell */
 #define PST_CMDSUBST   0x000040        /* $( ... ) command substitution */
diff --git a/subst.c b/subst.c
index 02dbaf03b178c1f0218881d89db7e879420eb8dd..92ca364c599efb9515d808d2b5a6a332850ba7ed 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -2644,8 +2644,10 @@ split_at_delims (const char *string, int slen, const char *delims, int sentinel,
        cw = nw;
 
       /* If the cursor is at whitespace just before word start, set the
-        sentinel word to the current word. */
-      if (cwp && cw == -1 && sentinel == ts-1)
+        sentinel word to the current word. We don't do this if this is
+        being called as part of completion, since readline attempts
+        completion on empty words in this case. */
+      if ((flags & SD_COMPLETE) == 0 && cwp && cw == -1 && sentinel == ts-1)
        cw = nw;
 
       /* If the cursor is at whitespace between two words, make a new, empty