]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
several fixes for printing readline key bindings and macro values containing characte...
authorChet Ramey <chet.ramey@case.edu>
Tue, 8 Aug 2023 14:49:46 +0000 (10:49 -0400)
committerChet Ramey <chet.ramey@case.edu>
Tue, 8 Aug 2023 14:49:46 +0000 (10:49 -0400)
CWRU/CWRU.chlog
builtins/bind.def
execute_cmd.c
lib/readline/bind.c
lib/readline/chardefs.h
lib/readline/doc/rltech.texi
lib/readline/readline.h

index 5b5f3bab1dc11e20bbe6434a17c311abe9924445..4b992109dc89049146865d2c02bc68cc9dcbd994 100644 (file)
@@ -7360,3 +7360,32 @@ subst.c
        - do_compound_assignment: don't attempt to convert a global associative
          array to an indexed array with declare -g.
          From a report and patch by Grisha Levit <grishalevit@gmail.com>
+
+                                   8/7
+                                   ---
+lib/readline/bind.c
+       - rl_print_keybinding: new function, prints a the key bindings for a
+         single function specified by name
+       - rl_function_dumper: call rl_print_keybinding for every function name
+
+lib/readline/readline.h
+       - rl_print_keybinding: extern declaration
+
+lib/readline/bind.c
+       - _rl_untranslate_macro_value: make sure characters betweeen 128 and
+         159 (metafied control characters) are printed using the \M-\C-
+         notation instead of directly writing the control character.
+         From a report and patch by Grisha Levit <grishalevit@gmail.com>
+       - rl_get_keyname: if a key binding shadows a function or macro, print
+         the ANYOTHERKEY binding as a null string
+         From a report and patch by Grisha Levit <grishalevit@gmail.com>
+       - rl_untranslate_keyseq: make changes analogous to
+         _rl_untranslate_macro_value so that we don't print control characters
+         directly
+       - rl_invoking_keyseqs_in_map: if the key corresponds to a keymap, use
+         _rl_get_keyname to get its text representation, so this function
+         returns consistent results
+       - rl_translate_keyseq: if convert-meta is on, don't convert meta chars
+         that are, e.g., \M-\C-@ (128) into \e followed by a NUL, resulting
+         in truncated key sequences. Just don't honor convert-meta in this
+         case
index 99dd1fa97e78f50246bb95b39829741b8a9eca0d..3cf9015415924f5bcd69db8ff4540255142f3b09 100644 (file)
@@ -116,14 +116,7 @@ bind_builtin (WORD_LIST *list)
   char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq, *t;
 
   if (no_line_editing)
-    {
-#if 0
-      builtin_error (_("line editing not enabled"));
-      return (EXECUTION_FAILURE);
-#else
-      builtin_warning (_("line editing not enabled"));
-#endif
-    }
+    builtin_warning (_("line editing not enabled"));
 
   kmap = saved_keymap = (Keymap) NULL;
   flags = 0;
@@ -226,10 +219,37 @@ bind_builtin (WORD_LIST *list)
     rl_list_funmap_names ();
 
   if (flags & PFLAG)
-    rl_function_dumper (1);
+    {
+#if 0  /* TAG:bash-5.3 */
+      if (list == 0)
+       rl_function_dumper (1);
+      else
+       while (list)
+         {
+           rl_print_keybinding (list->word->word, kmap, 1);
+           list = list->next;
+         }
+#else
+      rl_function_dumper (1);
+#endif
+    }
 
   if (flags & PPFLAG)
-    rl_function_dumper (0);
+    {
+#if 0  /* TAG:bash-5.3 */
+      if (list == 0)
+       rl_function_dumper (0);
+      else
+       while (list)
+         {
+           rl_print_keybinding (list->word->word, kmap, 0);
+           list = list->next;
+         }
+#else
+      rl_function_dumper (0);
+#endif
+    }
+
 
   if (flags & SFLAG)
     rl_macro_dumper (1);
index 0c02a7df0cac400cc7c16f07b3f68cc10fd8f4ff..53537c41765d53f810b7a1c8a5ac2ec6faa9f477 100644 (file)
@@ -4729,7 +4729,7 @@ run_builtin:
              setup_async_signals ();
            }
 
-         if (async == 0)
+         if (async == 0)               /* XXX why async == 0? */
            subshell_level++;
          execute_subshell_builtin_or_function
            (words, simple_command->redirects, builtin, func,
index a8b139f0b660fae8f79dc5ec6c953ec6446cdd43..3a44fefb97d186904280591a967e9ea9cc0f94e6 100644 (file)
@@ -526,8 +526,7 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
 
   /* When there are incomplete prefixes \C- or \M- (has_control || has_meta)
      without base character at the end of SEQ, they are processed as the
-     prefixes for '\0'.
-  */
+     prefixes for '\0'. */
   for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++)
     {
       /* Only backslashes followed by a non-null character are handled
@@ -624,11 +623,17 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
          has_meta = 0;
        }
 
-      /* If convert-meta is turned on, convert a meta char to a key sequence  */
+      /* If convert-meta is turned on, convert a meta char to a key sequence */
       if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
        {
-         array[l++] = ESC;     /* ESC is meta-prefix */
-         array[l++] = UNMETA (c);
+         int x = UNMETA (c);
+         if (x)
+           {
+             array[l++] = ESC; /* ESC is meta-prefix */
+             array[l++] = x;
+           }
+         else
+           array[l++] = c;     /* just do the best we can without sticking a NUL in there. */
        }
       else
        array[l++] = (c);
@@ -680,7 +685,8 @@ char *
 rl_untranslate_keyseq (int seq)
 {
   static char kseq[16];
-  int i, c;
+  int i;
+  unsigned char c;
 
   i = 0;
   c = seq;
@@ -691,35 +697,22 @@ rl_untranslate_keyseq (int seq)
       kseq[i++] = '-';
       c = UNMETA (c);
     }
-  else if (c == ESC)
+
+  if (c == ESC)
     {
       kseq[i++] = '\\';
       c = 'e';
     }
-  else if (CTRL_CHAR (c))
+  else if (CTRL_CHAR (c) || c == RUBOUT)
     {
       kseq[i++] = '\\';
       kseq[i++] = 'C';
       kseq[i++] = '-';
-      c = _rl_to_lower (UNCTRL (c));
-    }
-  else if (c == RUBOUT)
-    {
-      kseq[i++] = '\\';
-      kseq[i++] = 'C';
-      kseq[i++] = '-';
-      c = '?';
+      c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
     }
 
-  if (c == ESC)
-    {
-      kseq[i++] = '\\';
-      c = 'e';
-    }
-  else if (c == '\\' || c == '"')
-    {
-      kseq[i++] = '\\';
-    }
+  if (c == '\\' || c == '"')
+    kseq[i++] = '\\';
 
   kseq[i++] = (unsigned char) c;
   kseq[i] = '\0';
@@ -730,9 +723,9 @@ char *
 _rl_untranslate_macro_value (char *seq, int use_escapes)
 {
   char *ret, *r, *s;
-  int c;
+  unsigned char c;
 
-  r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
+  r = ret = (char *)xmalloc (8 * strlen (seq) + 1);
   for (s = seq; *s; s++)
     {
       c = *s;
@@ -743,7 +736,9 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
          *r++ = '-';
          c = UNMETA (c);
        }
-      else if (c == ESC)
+
+      /* We want to keep from printing literal control chars */
+      if (c == ESC)
        {
          *r++ = '\\';
          c = 'e';
@@ -768,15 +763,10 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
          c = '?';
        }
 
-      if (c == ESC)
-       {
-         *r++ = '\\';
-         c = 'e';
-       }
-      else if (c == '\\' || c == '"')
+      if (c == '\\' || c == '"')
        *r++ = '\\';
 
-      *r++ = (unsigned char)c;
+      *r++ = c;
     }
   *r = '\0';
   return ret;
@@ -2574,17 +2564,13 @@ _rl_get_keyname (int key)
   char *keyname;
   int i, c;
 
-  keyname = (char *)xmalloc (8);
+  keyname = (char *)xmalloc (9);
 
   c = key;
   /* Since this is going to be used to write out keysequence-function
      pairs for possible inclusion in an inputrc file, we don't want to
      do any special meta processing on KEY. */
 
-#if 1
-  /* XXX - Experimental */
-  /* We might want to do this, but the old version of the code did not. */
-
   /* If this is an escape character, we don't want to do any more processing.
      Just add the special ESC key sequence and return. */
   if (c == ESC)
@@ -2594,28 +2580,23 @@ _rl_get_keyname (int key)
       keyname[2] = '\0';
       return keyname;
     }
-#endif
 
-  /* RUBOUT is translated directly into \C-? */
-  if (key == RUBOUT)
+  if (key == ANYOTHERKEY)
     {
-      keyname[0] = '\\';
-      keyname[1] = 'C';
-      keyname[2] = '-';
-      keyname[3] = '?';
-      keyname[4] = '\0';
+      keyname[0] = '\0';
       return keyname;
     }
 
   i = 0;
+
   /* Now add special prefixes needed for control characters.  This can
      potentially change C. */
-  if (CTRL_CHAR (c))
+  if (CTRL_CHAR (c) || c == RUBOUT)
     {
       keyname[i++] = '\\';
       keyname[i++] = 'C';
       keyname[i++] = '-';
-      c = _rl_to_lower (UNCTRL (c));
+      c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
     }
 
   /* XXX experimental code.  Turn the characters that are not ASCII or
@@ -2693,53 +2674,24 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
          {
            char **seqs;
            register int i;
+           char *keyname;
+           size_t knlen;
 
            /* Find the list of keyseqs in this map which have FUNCTION as
               their target.  Add the key sequences found to RESULT. */
-           if (map[key].function)
-             seqs =
-               rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
-           else
+           if (map[key].function == 0)
              break;
 
+           seqs = rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
            if (seqs == 0)
              break;
 
+           keyname = _rl_get_keyname (key);
+           knlen = RL_STRLEN (keyname);
+
            for (i = 0; seqs[i]; i++)
              {
-               char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
-
-               if (key == ESC)
-                 {
-                   /* If ESC is the meta prefix and we're converting chars
-                      with the eighth bit set to ESC-prefixed sequences, then
-                      we can use \M-.  Otherwise we need to use the sequence
-                      for ESC. */
-                   if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
-                     sprintf (keyname, "\\M-");
-                   else
-                     sprintf (keyname, "\\e");
-                 }
-               else
-                 {
-                   int c = key, l = 0;
-                   if (CTRL_CHAR (c) || c == RUBOUT)
-                     {
-                       keyname[l++] = '\\';
-                       keyname[l++] = 'C';
-                       keyname[l++] = '-';
-                       c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
-                     }
-
-                   if (c == '\\' || c == '"')
-                     keyname[l++] = '\\';
-
-                   keyname[l++] = (char) c;
-                   keyname[l++] = '\0';
-                 }
-               
-               strcat (keyname, seqs[i]);
-               xfree (seqs[i]);
+               char *x;
 
                if (result_index + 2 > result_size)
                  {
@@ -2747,10 +2699,16 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
                    result = (char **)xrealloc (result, result_size * sizeof (char *));
                  }
 
-               result[result_index++] = keyname;
+               x = xmalloc (knlen + RL_STRLEN (seqs[i]) + 1);
+               strcpy (x, keyname);
+               strcpy (x + knlen, seqs[i]);
+               xfree (seqs[i]);
+
+               result[result_index++] = x;
                result[result_index] = (char *)NULL;
              }
 
+           xfree (keyname);
            xfree (seqs);
          }
          break;
@@ -2767,73 +2725,72 @@ rl_invoking_keyseqs (rl_command_func_t *function)
   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
 }
 
-/* Print all of the functions and their bindings to rl_outstream.  If
-   PRINT_READABLY is non-zero, then print the output in such a way
-   that it can be read back in. */
 void
-rl_function_dumper (int print_readably)
+rl_print_keybinding (const char *name, Keymap kmap, int print_readably)
 {
-  register int i;
-  const char **names;
-  const char *name;
-
-  names = rl_funmap_names ();
+  rl_command_func_t *function;
+  char **invokers;
 
-  fprintf (rl_outstream, "\n");
+  function = rl_named_function (name);
+  invokers = rl_invoking_keyseqs_in_map (function, kmap ? kmap : _rl_keymap);
 
-  for (i = 0; name = names[i]; i++)
+  if (print_readably)
     {
-      rl_command_func_t *function;
-      char **invokers;
-
-      function = rl_named_function (name);
-      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
-
-      if (print_readably)
+      if (!invokers)
+       fprintf (rl_outstream, "# %s (not bound)\n", name);
+      else
        {
-         if (!invokers)
-           fprintf (rl_outstream, "# %s (not bound)\n", name);
-         else
-           {
-             register int j;
-
-             for (j = 0; invokers[j]; j++)
-               {
-                 fprintf (rl_outstream, "\"%s\": %s\n",
-                          invokers[j], name);
-                 xfree (invokers[j]);
-               }
+         register int j;
 
-             xfree (invokers);
+         for (j = 0; invokers[j]; j++)
+           {
+             fprintf (rl_outstream, "\"%s\": %s\n", invokers[j], name);
+             xfree (invokers[j]);
            }
+
+         xfree (invokers);
        }
+    }
+  else
+    {
+      if (!invokers)
+       fprintf (rl_outstream, "%s is not bound to any keys\n", name);
       else
        {
-         if (!invokers)
-           fprintf (rl_outstream, "%s is not bound to any keys\n",
-                    name);
-         else
-           {
-             register int j;
+         register int j;
 
-             fprintf (rl_outstream, "%s can be found on ", name);
+         fprintf (rl_outstream, "%s can be found on ", name);
 
-             for (j = 0; invokers[j] && j < 5; j++)
-               {
-                 fprintf (rl_outstream, "\"%s\"%s", invokers[j],
-                          invokers[j + 1] ? ", " : ".\n");
-               }
+         for (j = 0; invokers[j] && j < 5; j++)
+           fprintf (rl_outstream, "\"%s\"%s", invokers[j], invokers[j + 1] ? ", " : ".\n");
 
-             if (j == 5 && invokers[j])
-               fprintf (rl_outstream, "...\n");
+         if (j == 5 && invokers[j])
+           fprintf (rl_outstream, "...\n");
 
-             for (j = 0; invokers[j]; j++)
-               xfree (invokers[j]);
+         for (j = 0; invokers[j]; j++)
+           xfree (invokers[j]);
 
-             xfree (invokers);
-           }
+         xfree (invokers);
        }
     }
+}
+
+/* Print all of the functions and their bindings to rl_outstream.  If
+   PRINT_READABLY is non-zero, then print the output in such a way
+   that it can be read back in. */
+void
+rl_function_dumper (int print_readably)
+{
+  register int i;
+  const char **names;
+  const char *name;
+
+  names = rl_funmap_names ();
+
+  fprintf (rl_outstream, "\n");
+
+  for (i = 0; name = names[i]; i++)
+    rl_print_keybinding (name, _rl_keymap, print_readably);
 
   xfree (names);
 }
index 24a25f1f105bb45b41c8eefc5ad9b34d93aa941b..02f7e17e26927bdcc2b54393694a0a812967ff6c 100644 (file)
@@ -55,7 +55,7 @@
 #define largest_char 255                   /* Largest character value. */
 
 #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
-#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+#define META_CHAR(c) ((unsigned char)(c) > meta_character_threshold && (unsigned char)(c) <= largest_char)
 
 #define CTRL(c) ((c) & control_character_mask)
 #define META(c) ((c) | meta_character_bit)
index ad3edf897fd9cdd4de8d5834dc920f0f91d5a384..c83d99d51a481602974f7a3842a20ccc566642c2 100644 (file)
@@ -926,9 +926,19 @@ Return an array of strings representing the key sequences used to
 invoke @var{function} in the keymap @var{map}.
 @end deftypefun
 
+@deftypefun void rl_print_keybinding (const char *name, Keymap map, int readable)
+Print key sequences bound to Readline function name @var{name} in
+keymap @var{map}.
+If @var{map} is NULL, this uses the current keymap.
+If @var{readable} is non-zero,
+the list is formatted in such a way that it can be made part of an
+@code{inputrc} file and re-read.
+@end deftypefun
+
 @deftypefun void rl_function_dumper (int readable)
 Print the Readline function names and the key sequences currently
-bound to them to @code{rl_outstream}.  If @var{readable} is non-zero,
+bound to them to @code{rl_outstream}.
+If @var{readable} is non-zero,
 the list is formatted in such a way that it can be made part of an
 @code{inputrc} file and re-read.
 @end deftypefun
index acd3a9fdd7190a70b64cd8f2a0aca460ee2dd7e1..828a42a626a6170fbc4a07080d61011002720eba 100644 (file)
@@ -341,7 +341,9 @@ extern int rl_trim_arg_from_keyseq (const char *, size_t, Keymap);
 extern void rl_list_funmap_names (void);
 extern char **rl_invoking_keyseqs_in_map (rl_command_func_t *, Keymap);
 extern char **rl_invoking_keyseqs (rl_command_func_t *);
+
+extern void rl_print_keybinding (const char *, Keymap, int);
+
 extern void rl_function_dumper (int);
 extern void rl_macro_dumper (int);
 extern void rl_variable_dumper (int);