Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / lib / readline / bind.c
index 8821599..bd899ca 100644 (file)
    675 Mass Ave, Cambridge, MA 02139, USA. */
 #define READLINE_LIBRARY
 
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <fcntl.h>
-#if !defined (NO_SYS_FILE)
+#if defined (HAVE_SYS_FILE_H)
 #  include <sys/file.h>
-#endif /* !NO_SYS_FILE */
-#include <signal.h>
+#endif /* HAVE_SYS_FILE_H */
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
@@ -39,8 +42,9 @@
 #  include "ansi_stdlib.h"
 #endif /* HAVE_STDLIB_H */
 
+#include <signal.h>
 #include <errno.h>
-/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
@@ -65,6 +69,8 @@ extern int _rl_meta_flag;
 extern int _rl_convert_meta_chars_to_ascii;
 extern int _rl_output_meta_chars;
 extern int _rl_complete_show_all;
+extern int _rl_complete_mark_directories;
+extern int _rl_enable_keypad;
 #if defined (PAREN_MATCHING)
 extern int rl_blink_matching_paren;
 #endif /* PAREN_MATCHING */
@@ -73,36 +79,31 @@ extern int rl_visible_stats;
 #endif /* VISIBLE_STATS */
 extern int rl_complete_with_tilde_expansion;
 extern int rl_completion_query_items;
-#if defined (VI_MODE)
-extern char *rl_vi_comment_begin;
-#endif
+extern int rl_inhibit_completion;
+extern char *_rl_comment_begin;
 
 extern int rl_explicit_arg;
 extern int rl_editing_mode;
-extern unsigned short _rl_parsing_conditionalized_out;
+extern unsigned char _rl_parsing_conditionalized_out;
 extern Keymap _rl_keymap;
 
 extern char *possible_control_prefixes[], *possible_meta_prefixes[];
 
 extern char **rl_funmap_names ();
+extern int rl_add_funmap_entry ();
+
+extern char *_rl_strindex ();
+
+/* Variables exported by this file. */
+Keymap rl_binding_keymap;
 
 /* Forward declarations */
 void rl_set_keymap_from_edit_mode ();
 
 static int glean_key_from_name ();
+static int substring_member_of_array ();
 
-#if defined (HAVE_STRCASECMP)
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#else
-static int stricmp (), strnicmp ();
-#endif
-
-#if defined (STATIC_MALLOC)
-static char *xmalloc (), *xrealloc ();
-#else
 extern char *xmalloc (), *xrealloc ();
-#endif /* STATIC_MALLOC */
 
 /* **************************************************************** */
 /*                                                                 */
@@ -113,6 +114,7 @@ extern char *xmalloc (), *xrealloc ();
 /* rl_add_defun (char *name, Function *function, int key)
    Add NAME to the list of named functions.  Make FUNCTION be the function
    that gets called.  If KEY is not -1, then bind it. */
+int
 rl_add_defun (name, function, key)
      char *name;
      Function *function;
@@ -150,6 +152,7 @@ rl_bind_key (key, function)
 
   _rl_keymap[key].type = ISFUNC;
   _rl_keymap[key].function = function;
+  rl_binding_keymap = _rl_keymap;
   return (0);
 }
 
@@ -162,8 +165,9 @@ rl_bind_key_in_map (key, function, map)
      Keymap map;
 {
   int result;
-  Keymap oldmap = _rl_keymap;
+  Keymap oldmap;
 
+  oldmap = _rl_keymap;
   _rl_keymap = map;
   result = rl_bind_key (key, function);
   _rl_keymap = oldmap;
@@ -192,6 +196,7 @@ rl_unbind_key_in_map (key, map)
 /* Bind the key sequence represented by the string KEYSEQ to
    FUNCTION.  This makes new keymaps as necessary.  The initial
    place to do bindings is in MAP. */
+int
 rl_set_key (keyseq, function, map)
      char *keyseq;
      Function *function;
@@ -203,6 +208,7 @@ rl_set_key (keyseq, function, map)
 /* Bind the key sequence represented by the string KEYSEQ to
    the string of characters MACRO.  This makes new keymaps as
    necessary.  The initial place to do bindings is in MAP. */
+int
 rl_macro_bind (keyseq, macro, map)
      char *keyseq, *macro;
      Keymap map;
@@ -226,6 +232,7 @@ rl_macro_bind (keyseq, macro, map)
    pointed to by DATA, right now this can be a function (ISFUNC),
    a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
    as necessary.  The initial place to do bindings is in MAP. */
+int
 rl_generic_bind (type, keyseq, data, map)
      int type;
      char *keyseq, *data;
@@ -286,6 +293,8 @@ rl_generic_bind (type, keyseq, data, map)
          map[ic].function = KEYMAP_TO_FUNCTION (data);
          map[ic].type = type;
        }
+
+      rl_binding_keymap = map;
     }
   free (keys);
   return 0;
@@ -294,30 +303,30 @@ rl_generic_bind (type, keyseq, data, map)
 /* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
    an array of characters.  LEN gets the final length of ARRAY.  Return
    non-zero if there was an error parsing SEQ. */
+int
 rl_translate_keyseq (seq, array, len)
      char *seq, *array;
      int *len;
 {
-  register int i, c, l = 0;
+  register int i, c, l;
 
-  for (i = 0; c = seq[i]; i++)
+  for (i = l = 0; c = seq[i]; i++)
     {
       if (c == '\\')
        {
          c = seq[++i];
 
-         if (!c)
+         if (c == 0)
            break;
 
-         if (((c == 'C' || c == 'M') &&  seq[i + 1] == '-') ||
-             (c == 'e'))
+         if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || (c == 'e'))
            {
              /* Handle special case of backwards define. */
              if (strncmp (&seq[i], "C-\\M-", 5) == 0)
                {
                  array[l++] = ESC;
                  i += 5;
-                 array[l++] = CTRL (to_upper (seq[i]));
+                 array[l++] = CTRL (_rl_to_upper (seq[i]));
                  if (!seq[i])
                    i--;
                  continue;
@@ -327,16 +336,13 @@ rl_translate_keyseq (seq, array, len)
                {
                case 'M':
                  i++;
-                 array[l++] = ESC;
+                 array[l++] = ESC;     /* XXX */
                  break;
 
                case 'C':
                  i += 2;
                  /* Special hack for C-?... */
-                 if (seq[i] == '?')
-                   array[l++] = RUBOUT;
-                 else
-                   array[l++] = CTRL (to_upper (seq[i]));
+                 array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
                  break;
 
                case 'e':
@@ -354,6 +360,52 @@ rl_translate_keyseq (seq, array, len)
   return (0);
 }
 
+char *
+rl_untranslate_keyseq (seq)
+     int seq;
+{
+  static char kseq[16];
+  int i, c;
+
+  i = 0;
+  c = seq;
+  if (META_CHAR (c))
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'M';
+      kseq[i++] = '-';
+      c = UNMETA (c);
+    }
+  else if (CTRL_CHAR (c))
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'C';
+      kseq[i++] = '-';
+      c = UNCTRL (c);
+    }
+  else if (c == RUBOUT)
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'C';
+      kseq[i++] = '-';
+      c = '?';
+    }
+
+  if (c == ESC)
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'e';
+    }
+  else if (c == '\\' || c == '"')
+    {
+      kseq[i++] = '\\';
+    }
+
+  kseq[i++] = (unsigned char) c;
+  kseq[i] = '\0';
+  return kseq;
+}
+
 /* Return a pointer to the function that STRING represents.
    If STRING doesn't have a matching function, then a NULL pointer
    is returned. */
@@ -366,7 +418,7 @@ rl_named_function (string)
   rl_initialize_funmap ();
 
   for (i = 0; funmap[i]; i++)
-    if (stricmp (funmap[i]->name, string) == 0)
+    if (_rl_stricmp (funmap[i]->name, string) == 0)
       return (funmap[i]->function);
   return ((Function *)NULL);
 }
@@ -435,7 +487,12 @@ rl_function_of_keyseq (keyseq, map, type)
 /* The last key bindings file read. */
 static char *last_readline_init_file = (char *)NULL;
 
+/* The file we're currently reading key bindings from. */
+static char *current_readline_init_file;
+static int current_readline_init_lineno;
+
 /* Re-read the current keybindings file. */
+int
 rl_re_read_init_file (count, ignore)
      int count, ignore;
 {
@@ -462,18 +519,19 @@ rl_read_init_file (filename)
   int file;
 
   /* Default the filename. */
-  if (!filename)
+  if (filename == 0)
     {
       filename = last_readline_init_file;
-      if (!filename)
+      if (filename == 0)
         filename = getenv ("INPUTRC");
-      if (!filename)
+      if (filename == 0)
        filename = DEFAULT_INPUTRC;
     }
 
-  if (!*filename)
+  if (*filename == 0)
     filename = DEFAULT_INPUTRC;
 
+  current_readline_init_file = filename;
   openname = tilde_expand (filename);
 
   if ((stat (openname, &finfo) < 0) ||
@@ -503,6 +561,7 @@ rl_read_init_file (filename)
 
   /* Loop over the lines in the file.  Lines that start with `#' are
      comments; all other lines are commands for readline initialization. */
+  current_readline_init_lineno = 1;
   line = buffer;
   end = buffer + finfo.st_size;
   while (line < end)
@@ -526,11 +585,21 @@ rl_read_init_file (filename)
 
       /* Move to the next line. */
       line += i + 1;
+      current_readline_init_lineno++;
     }
   free (buffer);
   return (0);
 }
 
+static void
+_rl_init_file_error (msg)
+     char *msg;
+{
+  fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
+                  current_readline_init_lineno,
+                  msg);
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Parser Directives                           */
@@ -544,8 +613,8 @@ char *rl_readline_name = "other";
 
 /* Stack of previous values of parsing_conditionalized_out. */
 static unsigned char *if_stack = (unsigned char *)NULL;
-static int if_stack_depth = 0;
-static int if_stack_size = 0;
+static int if_stack_depth;
+static int if_stack_size;
 
 /* Push _rl_parsing_conditionalized_out, and set parser state based
    on ARGS. */
@@ -579,7 +648,7 @@ parser_if (args)
   /* Handle "if term=foo" and "if mode=emacs" constructs.  If this
      isn't term=foo, or mode=emacs, then check to see if the first
      word in ARGS is the same as the value stored in rl_readline_name. */
-  if (rl_terminal_name && strnicmp (args, "term=", 5) == 0)
+  if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
     {
       char *tem, *tname;
 
@@ -593,35 +662,28 @@ parser_if (args)
         if someone has a `sun-cmd' and does not want to have bindings
         that will be executed if the terminal is a `sun', they can put
         `$if term=sun-cmd' into their .inputrc. */
-      if ((stricmp (args + 5, tname) == 0) ||
-         (stricmp (args + 5, rl_terminal_name) == 0))
-       _rl_parsing_conditionalized_out = 0;
-      else
-       _rl_parsing_conditionalized_out = 1;
-
+      _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
+                                       _rl_stricmp (args + 5, rl_terminal_name);
       free (tname);
     }
 #if defined (VI_MODE)
-  else if (strnicmp (args, "mode=", 5) == 0)
+  else if (_rl_strnicmp (args, "mode=", 5) == 0)
     {
       int mode;
 
-      if (stricmp (args + 5, "emacs") == 0)
+      if (_rl_stricmp (args + 5, "emacs") == 0)
        mode = emacs_mode;
-      else if (stricmp (args + 5, "vi") == 0)
+      else if (_rl_stricmp (args + 5, "vi") == 0)
        mode = vi_mode;
       else
        mode = no_mode;
 
-      if (mode == rl_editing_mode)
-       _rl_parsing_conditionalized_out = 0;
-      else
-       _rl_parsing_conditionalized_out = 1;
+      _rl_parsing_conditionalized_out = mode != rl_editing_mode;
     }
 #endif /* VI_MODE */
   /* Check to see if the first word in ARGS is the same as the
      value stored in rl_readline_name. */
-  else if (stricmp (args, rl_readline_name) == 0)
+  else if (_rl_stricmp (args, rl_readline_name) == 0)
     _rl_parsing_conditionalized_out = 0;
   else
     _rl_parsing_conditionalized_out = 1;
@@ -705,7 +767,7 @@ handle_parser_directive (statement)
 
   /* Lookup the command, and act on it. */
   for (i = 0; parser_directives[i].name; i++)
-    if (stricmp (directive, parser_directives[i].name) == 0)
+    if (_rl_stricmp (directive, parser_directives[i].name) == 0)
       {
        (*parser_directives[i].function) (args);
        return (0);
@@ -715,12 +777,11 @@ handle_parser_directive (statement)
   return (1);
 }
 
-static int substring_member_of_array ();
-
 /* Read the binding command from STRING and perform it.
    A key binding command looks like: Keyname: function-name\0,
    a variable binding command looks like: set variable value.
    A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+int
 rl_parse_and_bind (string)
      char *string;
 {
@@ -770,6 +831,12 @@ rl_parse_and_bind (string)
          if (c == '"')
            break;
        }
+      /* If we didn't find a closing quote, abort the line. */
+      if (string[i] == '\0')
+        {
+          _rl_init_file_error ("no closing `\"' in key binding");
+          return 1;
+        }
     }
 
   /* Advance to the colon (:) or whitespace which separates the two objects. */
@@ -786,7 +853,7 @@ rl_parse_and_bind (string)
     string[i++] = '\0';
 
   /* If this is a command to set a variable, then do that. */
-  if (stricmp (string, "set") == 0)
+  if (_rl_stricmp (string, "set") == 0)
     {
       char *var = string + i;
       char *value;
@@ -915,7 +982,7 @@ rl_parse_and_bind (string)
 
   /* Add in control and meta bits. */
   if (substring_member_of_array (string, possible_control_prefixes))
-    key = CTRL (to_upper (key));
+    key = CTRL (_rl_to_upper (key));
 
   if (substring_member_of_array (string, possible_meta_prefixes))
     key = META (key);
@@ -934,7 +1001,7 @@ rl_parse_and_bind (string)
     }
 #if defined (PREFIX_META_HACK)
   /* Ugly, but working hack to keep prefix-meta around. */
-  else if (stricmp (funname, "prefix-meta") == 0)
+  else if (_rl_stricmp (funname, "prefix-meta") == 0)
     {
       char seq[2];
 
@@ -956,22 +1023,27 @@ static struct {
   char *name;
   int *value;
 } boolean_varlist [] = {
-  { "horizontal-scroll-mode",  &_rl_horizontal_scroll_mode },
-  { "mark-modified-lines",     &_rl_mark_modified_lines },
-  { "meta-flag",               &_rl_meta_flag },
 #if defined (PAREN_MATCHING)
   { "blink-matching-paren",    &rl_blink_matching_paren },
 #endif
   { "convert-meta",            &_rl_convert_meta_chars_to_ascii },
-  { "show-all-if-ambiguous",   &_rl_complete_show_all },
+  { "disable-completion",      &rl_inhibit_completion },
+  { "enable-keypad",           &_rl_enable_keypad },
+  { "expand-tilde",            &rl_complete_with_tilde_expansion },
+  { "horizontal-scroll-mode",  &_rl_horizontal_scroll_mode },
+  { "input-meta",              &_rl_meta_flag },
+  { "mark-directories",                &_rl_complete_mark_directories },
+  { "mark-modified-lines",     &_rl_mark_modified_lines },
+  { "meta-flag",               &_rl_meta_flag },
   { "output-meta",             &_rl_output_meta_chars },
+  { "show-all-if-ambiguous",   &_rl_complete_show_all },
 #if defined (VISIBLE_STATS)
   { "visible-stats",           &rl_visible_stats },
 #endif /* VISIBLE_STATS */
-  { "expand-tilde",            &rl_complete_with_tilde_expansion },
   { (char *)NULL, (int *)NULL }
 };
 
+int
 rl_variable_bind (name, value)
      char *name, *value;
 {
@@ -980,15 +1052,12 @@ rl_variable_bind (name, value)
   /* Check for simple variables first. */
   for (i = 0; boolean_varlist[i].name; i++)
     {
-      if (stricmp (name, boolean_varlist[i].name) == 0)
+      if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
        {
          /* A variable is TRUE if the "value" is "on", "1" or "". */
-         if ((!*value) ||
-             (stricmp (value, "On") == 0) ||
-             (value[0] == '1' && value[1] == '\0'))
-           *boolean_varlist[i].value = 1;
-         else
-           *boolean_varlist[i].value = 0;
+         *boolean_varlist[i].value = *value == 0 ||
+                                     _rl_stricmp (value, "on") == 0 ||
+                                     (value[0] == '1' && value[1] == '\0');
          return 0;
        }
     }
@@ -996,16 +1065,16 @@ rl_variable_bind (name, value)
   /* Not a boolean variable, so check for specials. */
 
   /* Editing mode change? */
-  if (stricmp (name, "editing-mode") == 0)
+  if (_rl_stricmp (name, "editing-mode") == 0)
     {
-      if (strnicmp (value, "vi", 2) == 0)
+      if (_rl_strnicmp (value, "vi", 2) == 0)
        {
 #if defined (VI_MODE)
          _rl_keymap = vi_insertion_keymap;
          rl_editing_mode = vi_mode;
 #endif /* VI_MODE */
        }
-      else if (strnicmp (value, "emacs", 5) == 0)
+      else if (_rl_strnicmp (value, "emacs", 5) == 0)
        {
          _rl_keymap = emacs_standard_keymap;
          rl_editing_mode = emacs_mode;
@@ -1013,19 +1082,17 @@ rl_variable_bind (name, value)
     }
 
   /* Comment string change? */
-  else if (stricmp (name, "comment-begin") == 0)
+  else if (_rl_stricmp (name, "comment-begin") == 0)
     {
-#if defined (VI_MODE)
       if (*value)
        {
-         if (rl_vi_comment_begin)
-           free (rl_vi_comment_begin);
+         if (_rl_comment_begin)
+           free (_rl_comment_begin);
 
-         rl_vi_comment_begin = savestring (value);
+         _rl_comment_begin = savestring (value);
        }
-#endif /* VI_MODE */
     }
-  else if (stricmp (name, "completion-query-items") == 0)
+  else if (_rl_stricmp (name, "completion-query-items") == 0)
     {
       int nval = 100;
       if (*value)
@@ -1036,31 +1103,31 @@ rl_variable_bind (name, value)
        }
       rl_completion_query_items = nval;
     }
-  else if (stricmp (name, "keymap") == 0)
+  else if (_rl_stricmp (name, "keymap") == 0)
     {
       Keymap kmap;
       kmap = rl_get_keymap_by_name (value);
       if (kmap)
         rl_set_keymap (kmap);
     }
-  else if (stricmp (name, "bell-style") == 0)
+  else if (_rl_stricmp (name, "bell-style") == 0)
     {
       if (!*value)
         _rl_bell_preference = AUDIBLE_BELL;
       else
         {
-          if (stricmp (value, "none") == 0 || stricmp (value, "off") == 0)
+          if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
             _rl_bell_preference = NO_BELL;
-          else if (stricmp (value, "audible") == 0 || stricmp (value, "on") == 0)
+          else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
             _rl_bell_preference = AUDIBLE_BELL;
-          else if (stricmp (value, "visible") == 0)
+          else if (_rl_stricmp (value, "visible") == 0)
             _rl_bell_preference = VISIBLE_BELL;
         }
     }
-  else if (stricmp (name, "prefer-visible-bell") == 0)
+  else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
     {
       /* Backwards compatibility. */
-      if (*value && (stricmp (value, "on") == 0 ||
+      if (*value && (_rl_stricmp (value, "on") == 0 ||
                     (*value == '1' && !value[1])))
         _rl_bell_preference = VISIBLE_BELL;
       else
@@ -1100,7 +1167,7 @@ glean_key_from_name (name)
   register int i;
 
   for (i = 0; name_key_alist[i].name; i++)
-    if (stricmp (name, name_key_alist[i].name) == 0)
+    if (_rl_stricmp (name, name_key_alist[i].name) == 0)
       return (name_key_alist[i].value);
 
   return (*(unsigned char *)name);     /* XXX was return (*name) */
@@ -1136,6 +1203,17 @@ rl_get_keymap_by_name (name)
   return ((Keymap) NULL);
 }
 
+char *
+rl_get_keymap_name (map)
+     Keymap map;
+{
+  register int i;
+  for (i = 0; keymap_names[i].name; i++)
+    if (map == keymap_names[i].map)
+      return (keymap_names[i].name);
+  return ((char *)NULL);
+}
+  
 void
 rl_set_keymap (map)
      Keymap map;
@@ -1160,7 +1238,20 @@ rl_set_keymap_from_edit_mode ()
     _rl_keymap = vi_insertion_keymap;
 #endif /* VI_MODE */
 }
-\f
+
+char *
+rl_get_keymap_name_from_edit_mode ()
+{
+  if (rl_editing_mode == emacs_mode)
+    return "emacs";
+#if defined (VI_MODE)
+  else if (rl_editing_mode == vi_mode)
+    return "vi";
+#endif /* VI_MODE */
+  else
+    return "none";
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*               Key Binding and Function Information              */
@@ -1174,8 +1265,7 @@ rl_set_keymap_from_edit_mode ()
 
 /* Print the names of functions known to Readline. */
 void
-rl_list_funmap_names (count, ignore)
-     int count, ignore;
+rl_list_funmap_names ()
 {
   register int i;
   char **funmap_names;
@@ -1191,6 +1281,67 @@ rl_list_funmap_names (count, ignore)
   free (funmap_names);
 }
 
+static char *
+_rl_get_keyname (key)
+     int key;
+{
+  char *keyname;
+  int i, c;
+
+  keyname = (char *)xmalloc (8);
+
+  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 0
+  /* 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)
+    {
+      keyseq[0] = '\\';
+      keyseq[1] = 'e';
+      keyseq[2] = '\0';
+      return keyseq;
+    }
+#endif
+
+  /* RUBOUT is translated directly into \C-? */
+  if (key == RUBOUT)
+    {
+      keyname[0] = '\\';
+      keyname[1] = 'C';
+      keyname[2] = '-';
+      keyname[3] = '?';
+      keyname[4] = '\0';
+      return keyname;
+    }
+
+  i = 0;
+  /* Now add special prefixes needed for control characters.  This can
+     potentially change C. */
+  if (CTRL_CHAR (c))
+    {
+      keyname[i++] = '\\';
+      keyname[i++] = 'C';
+      keyname[i++] = '-';
+      c = _rl_to_lower (UNCTRL (c));
+    }
+
+  /* Now, if the character needs to be quoted with a backslash, do that. */
+  if (c == '\\' || c == '"')
+    keyname[i++] = '\\';
+
+  /* Now add the key, terminate the string, and return it. */
+  keyname[i++] = (char) c;
+  keyname[i] = '\0';
+
+  return keyname;
+}
+
 /* Return a NULL terminated array of strings which represent the key
    sequences that are used to invoke FUNCTION in MAP. */
 char **
@@ -1205,7 +1356,7 @@ rl_invoking_keyseqs_in_map (function, map)
   result = (char **)NULL;
   result_index = result_size = 0;
 
-  for (key = 0; key < 128; key++)
+  for (key = 0; key < KEYMAP_SIZE; key++)
     {
       switch (map[key].type)
        {
@@ -1217,27 +1368,15 @@ rl_invoking_keyseqs_in_map (function, map)
             then add the current KEY to the list of invoking keys. */
          if (map[key].function == function)
            {
-             char *keyname = (char *)xmalloc (5);
+             char *keyname;
 
-             if (CTRL_CHAR (key))
-               sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
-             else if (key == RUBOUT)
-               sprintf (keyname, "\\C-?");
-             else if (key == '\\' || key == '"')
-               {
-                 keyname[0] = '\\';
-                 keyname[1] = (char) key;
-                 keyname[2] = '\0';
-               }
-             else
-               {
-                 keyname[0] = (char) key;
-                 keyname[1] = '\0';
-               }
+             keyname = _rl_get_keyname (key);
 
              if (result_index + 2 > result_size)
-               result = (char **) xrealloc
-                 (result, (result_size += 10) * sizeof (char *));
+               {
+                 result_size += 10;
+                 result = (char **) xrealloc (result, result_size * sizeof (char *));
+               }
 
              result[result_index++] = keyname;
              result[result_index] = (char *)NULL;
@@ -1246,53 +1385,56 @@ rl_invoking_keyseqs_in_map (function, map)
 
        case ISKMAP:
          {
-           char **seqs = (char **)NULL;
+           char **seqs;
+           register int i;
 
            /* 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
+             break;
+
+           if (seqs == 0)
+             break;
 
-           if (seqs)
+           for (i = 0; seqs[i]; i++)
              {
-               register int i;
+               char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+               if (key == ESC)
+                 sprintf (keyname, "\\e");
+               else if (CTRL_CHAR (key))
+                 sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
+               else if (key == RUBOUT)
+                 sprintf (keyname, "\\C-?");
+               else if (key == '\\' || key == '"')
+                 {
+                   keyname[0] = '\\';
+                   keyname[1] = (char) key;
+                   keyname[2] = '\0';
+                 }
+               else
+                 {
+                   keyname[0] = (char) key;
+                   keyname[1] = '\0';
+                 }
+               
+               strcat (keyname, seqs[i]);
+               free (seqs[i]);
 
-               for (i = 0; seqs[i]; i++)
+               if (result_index + 2 > result_size)
                  {
-                   char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
-
-                   if (key == ESC)
-                     sprintf (keyname, "\\e");
-                   else if (CTRL_CHAR (key))
-                     sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
-                   else if (key == RUBOUT)
-                     sprintf (keyname, "\\C-?");
-                   else if (key == '\\' || key == '"')
-                     {
-                       keyname[0] = '\\';
-                       keyname[1] = (char) key;
-                       keyname[2] = '\0';
-                     }
-                   else
-                     {
-                       keyname[0] = (char) key;
-                       keyname[1] = '\0';
-                     }
-
-                   strcat (keyname, seqs[i]);
-                   free (seqs[i]);
-
-                   if (result_index + 2 > result_size)
-                     result = (char **) xrealloc
-                       (result, (result_size += 10) * sizeof (char *));
-
-                   result[result_index++] = keyname;
-                   result[result_index] = (char *)NULL;
+                   result_size += 10;
+                   result = (char **) xrealloc (result, result_size * sizeof (char *));
                  }
 
-               free (seqs);
+               result[result_index++] = keyname;
+               result[result_index] = (char *)NULL;
              }
+
+           free (seqs);
          }
          break;
        }
@@ -1309,18 +1451,6 @@ rl_invoking_keyseqs (function)
   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
 }
 
-/* Print all of the current functions and their bindings to
-   rl_outstream.  If an explicit argument is given, then print
-   the output in such a way that it can be read back in. */
-int
-rl_dump_functions (count, key)
-     int count, key;
-{
-  rl_function_dumper (rl_explicit_arg);
-  rl_on_new_line ();
-  return (0);
-}
-
 /* 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. */
@@ -1391,6 +1521,164 @@ rl_function_dumper (print_readably)
     }
 }
 
+/* Print all of the current functions and their bindings to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+     int count, key;
+{
+  rl_function_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+static void
+_rl_macro_dumper_internal (print_readably, map, prefix)
+     int print_readably;
+     Keymap map;
+     char *prefix;
+{
+  register int key;
+  char *keyname, *out;
+  int prefix_len;
+
+  for (key = 0; key < KEYMAP_SIZE; key++)
+    {
+      switch (map[key].type)
+       {
+       case ISMACR:
+         keyname = _rl_get_keyname (key);
+         out = (char *)map[key].function;
+         if (print_readably)
+           fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
+                                                        keyname,
+                                                        out ? out : "");
+         else
+           fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
+                                                       keyname,
+                                                       out ? out : "");
+         free (keyname);
+         break;
+       case ISFUNC:
+         break;
+       case ISKMAP:
+         prefix_len = prefix ? strlen (prefix) : 0;
+         if (key == ESC)
+           {
+             keyname = xmalloc (3 + prefix_len);
+             if (prefix)
+               strcpy (keyname, prefix);
+             keyname[prefix_len] = '\\';
+             keyname[prefix_len + 1] = 'e';
+             keyname[prefix_len + 2] = '\0';
+           }
+         else
+           {
+             keyname = _rl_get_keyname (key);
+             if (prefix)
+               {
+                 out = xmalloc (strlen (keyname) + prefix_len + 1);
+                 strcpy (out, prefix);
+                 strcpy (out + prefix_len, keyname);
+                 free (keyname);
+                 keyname = out;
+               }
+           }
+
+         _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
+         free (keyname);
+         break;
+       }
+    }
+}
+
+void
+rl_macro_dumper (print_readably)
+     int print_readably;
+{
+  _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
+}
+
+int
+rl_dump_macros (count, key)
+     int count, key;
+{
+  rl_macro_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+void
+rl_variable_dumper (print_readably)
+     int print_readably;
+{
+  int i;
+  char *kname;
+
+  for (i = 0; boolean_varlist[i].name; i++)
+    {
+      if (print_readably)
+        fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
+                              *boolean_varlist[i].value ? "on" : "off");
+      else
+        fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
+                              *boolean_varlist[i].value ? "on" : "off");
+    }
+
+  /* bell-style */
+  switch (_rl_bell_preference)
+    {
+    case NO_BELL: kname = "none"; break;
+    case VISIBLE_BELL: kname = "visible"; break;
+    case AUDIBLE_BELL:
+    default: kname = "audible"; break;
+    }
+  if (print_readably)
+    fprintf (rl_outstream, "set bell-style %s\n", kname);
+  else
+    fprintf (rl_outstream, "bell-style is set to `%s'\n", kname);
+
+  /* comment-begin */
+  if (print_readably)
+    fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
+  else
+    fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : "");
+
+  /* completion-query-items */
+  if (print_readably)
+    fprintf (rl_outstream, "set completion-query-items %d\n", rl_completion_query_items);
+  else
+    fprintf (rl_outstream, "completion-query-items is set to `%d'\n", rl_completion_query_items);
+
+  /* editing-mode */
+  if (print_readably)
+    fprintf (rl_outstream, "set editing-mode %s\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
+  else
+    fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
+
+  /* keymap */
+  kname = rl_get_keymap_name (_rl_keymap);
+  if (kname == 0)
+    kname = rl_get_keymap_name_from_edit_mode ();
+  if (print_readably)
+    fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
+  else
+    fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
+}
+
+/* Print all of the current variables and their values to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_variables (count, key)
+     int count, key;
+{
+  rl_variable_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
 /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */
 void
 _rl_bind_if_unbound (keyseq, default_func)
@@ -1407,14 +1695,6 @@ _rl_bind_if_unbound (keyseq, default_func)
     }
 }
 
-/* **************************************************************** */
-/*                                                                 */
-/*                     String Utility Functions                    */
-/*                                                                 */
-/* **************************************************************** */
-
-static char *strindex ();
-
 /* Return non-zero if any members of ARRAY are a substring in STRING. */
 static int
 substring_member_of_array (string, array)
@@ -1422,66 +1702,9 @@ substring_member_of_array (string, array)
 {
   while (*array)
     {
-      if (strindex (string, *array))
+      if (_rl_strindex (string, *array))
        return (1);
       array++;
     }
   return (0);
 }
-
-#if !defined (HAVE_STRCASECMP)
-/* Whoops, Unix doesn't have strnicmp. */
-
-/* Compare at most COUNT characters from string1 to string2.  Case
-   doesn't matter. */
-static int
-strnicmp (string1, string2, count)
-     char *string1, *string2;
-     int count;
-{
-  register char ch1, ch2;
-
-  while (count)
-    {
-      ch1 = *string1++;
-      ch2 = *string2++;
-      if (to_upper(ch1) == to_upper(ch2))
-       count--;
-      else
-        break;
-    }
-  return (count);
-}
-
-/* strcmp (), but caseless. */
-static int
-stricmp (string1, string2)
-     char *string1, *string2;
-{
-  register char ch1, ch2;
-
-  while (*string1 && *string2)
-    {
-      ch1 = *string1++;
-      ch2 = *string2++;
-      if (to_upper(ch1) != to_upper(ch2))
-       return (1);
-    }
-  return (*string1 - *string2);
-}
-#endif /* !HAVE_STRCASECMP */
-
-/* Determine if s2 occurs in s1.  If so, return a pointer to the
-   match in s1.  The compare is case insensitive. */
-static char *
-strindex (s1, s2)
-     register char *s1, *s2;
-{
-  register int i, l = strlen (s2);
-  register int len = strlen (s1);
-
-  for (i = 0; (len - i) >= l; i++)
-    if (strnicmp (s1 + i, s2, l) == 0)
-      return (s1 + i);
-  return ((char *)NULL);
-}