Import readline 8.0
[deliverable/binutils-gdb.git] / readline / bind.c
index f1098c48b17ef910b18edea72c4d36926bb362c4..57ae10f7318e521797fb4b8f7e426c7ab1324a49 100644 (file)
@@ -1,6 +1,6 @@
 /* bind.c -- key binding and startup file support for the readline library. */
 
-/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library (Readline), a library
    for reading lines of text with interactive input and history editing.
@@ -80,6 +80,8 @@ static void _rl_init_file_error (const char *, ...)  __attribute__((__format__ (
 static void _rl_init_file_error ();
 #endif
 
+static rl_command_func_t *_rl_function_of_keyseq_internal PARAMS((const char *, size_t, Keymap, int *));
+
 static char *_rl_read_file PARAMS((char *, size_t *));
 static int _rl_read_init_file PARAMS((const char *, int));
 static int glean_key_from_name PARAMS((char *));
@@ -87,14 +89,30 @@ static int glean_key_from_name PARAMS((char *));
 static int find_boolean_var PARAMS((const char *));
 static int find_string_var PARAMS((const char *));
 
+static const char *boolean_varname PARAMS((int));
+static const char *string_varname PARAMS((int));
+
 static char *_rl_get_string_variable_value PARAMS((const char *));
 static int substring_member_of_array PARAMS((const char *, const char * const *));
 
+static int _rl_get_keymap_by_name PARAMS((const char *));
+static int _rl_get_keymap_by_map PARAMS((Keymap));
+
 static int currently_reading_init_file;
 
 /* used only in this file */
 static int _rl_prefer_visible_bell = 1;
 
+#define OP_EQ  1
+#define OP_NE  2
+#define OP_GT  3
+#define OP_GE  4
+#define OP_LT  5
+#define OP_LE  6
+
+#define OPSTART(c)     ((c) == '=' || (c) == '!' || (c) == '<' || (c) == '>')
+#define CMPSTART(c)    ((c) == '=' || (c) == '!')
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Binding keys                                */
@@ -105,10 +123,7 @@ static int _rl_prefer_visible_bell = 1;
    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)
-     const char *name;
-     rl_command_func_t *function;
-     int key;
+rl_add_defun (const char *name, rl_command_func_t *function, int key)
 {
   if (key != -1)
     rl_bind_key (key, function);
@@ -118,9 +133,7 @@ rl_add_defun (name, function, key)
 
 /* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
 int
-rl_bind_key (key, function)
-     int key;
-     rl_command_func_t *function;
+rl_bind_key (int key, rl_command_func_t *function)
 {
   char keyseq[3];
   int l;
@@ -168,10 +181,7 @@ rl_bind_key (key, function)
 /* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
    KEY. */
 int
-rl_bind_key_in_map (key, function, map)
-     int key;
-     rl_command_func_t *function;
-     Keymap map;
+rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map)
 {
   int result;
   Keymap oldmap;
@@ -184,57 +194,44 @@ rl_bind_key_in_map (key, function, map)
 }
 
 /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
-   now, this is always used to attempt to bind the arrow keys, hence the
-   check for rl_vi_movement_mode. */
+   now, this is always used to attempt to bind the arrow keys. */
 int
-rl_bind_key_if_unbound_in_map (key, default_func, kmap)
-     int key;
-     rl_command_func_t *default_func;
-     Keymap kmap;
+rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *default_func, Keymap kmap)
 {
-  char keyseq[2];
+  char *keyseq;
 
-  keyseq[0] = (unsigned char)key;
-  keyseq[1] = '\0';
+  keyseq = rl_untranslate_keyseq ((unsigned char)key);
   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
 }
 
 int
-rl_bind_key_if_unbound (key, default_func)
-     int key;
-     rl_command_func_t *default_func;
+rl_bind_key_if_unbound (int key, rl_command_func_t *default_func)
 {
-  char keyseq[2];
+  char *keyseq;
 
-  keyseq[0] = (unsigned char)key;
-  keyseq[1] = '\0';
+  keyseq = rl_untranslate_keyseq ((unsigned char)key);
   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
 }
 
 /* Make KEY do nothing in the currently selected keymap.
-   Returns non-zero in case of error. */
+   Returns non-zero in case of error.  This is not the same as self-insert;
+   this makes it a dead key. */
 int
-rl_unbind_key (key)
-     int key;
+rl_unbind_key (int key)
 {
   return (rl_bind_key (key, (rl_command_func_t *)NULL));
 }
 
-/* Make KEY do nothing in MAP.
-   Returns non-zero in case of error. */
+/* Make KEY do nothing in MAP. Returns non-zero in case of error. */
 int
-rl_unbind_key_in_map (key, map)
-     int key;
-     Keymap map;
+rl_unbind_key_in_map (int key, Keymap map)
 {
   return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
 }
 
 /* Unbind all keys bound to FUNCTION in MAP. */
 int
-rl_unbind_function_in_map (func, map)
-     rl_command_func_t *func;
-     Keymap map;
+rl_unbind_function_in_map (rl_command_func_t *func, Keymap map)
 {
   register int i, rval;
 
@@ -249,10 +246,9 @@ rl_unbind_function_in_map (func, map)
   return rval;
 }
 
+/* Unbind all keys bound to COMMAND, which is a bindable command name, in MAP */
 int
-rl_unbind_command_in_map (command, map)
-     const char *command;
-     Keymap map;
+rl_unbind_command_in_map (const char *command, Keymap map)
 {
   rl_command_func_t *func;
 
@@ -266,9 +262,7 @@ rl_unbind_command_in_map (command, map)
    FUNCTION, starting in the current keymap.  This makes new
    keymaps as necessary. */
 int
-rl_bind_keyseq (keyseq, function)
-     const char *keyseq;
-     rl_command_func_t *function;
+rl_bind_keyseq (const char *keyseq, rl_command_func_t *function)
 {
   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
 }
@@ -277,20 +271,14 @@ rl_bind_keyseq (keyseq, function)
    FUNCTION.  This makes new keymaps as necessary.  The initial
    place to do bindings is in MAP. */
 int
-rl_bind_keyseq_in_map (keyseq, function, map)
-     const char *keyseq;
-     rl_command_func_t *function;
-     Keymap map;
+rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
 {
   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
 }
 
 /* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
 int
-rl_set_key (keyseq, function, map)
-     const char *keyseq;
-     rl_command_func_t *function;
-     Keymap map;
+rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map)
 {
   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
 }
@@ -299,16 +287,24 @@ rl_set_key (keyseq, function, map)
    now, this is always used to attempt to bind the arrow keys, hence the
    check for rl_vi_movement_mode. */
 int
-rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
-     const char *keyseq;
-     rl_command_func_t *default_func;
-     Keymap kmap;
+rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *default_func, Keymap kmap)
 {
   rl_command_func_t *func;
+  char *keys;
+  int keys_len;
 
   if (keyseq)
     {
-      func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
+      /* Handle key sequences that require translations and `raw' ones that
+        don't. This might be a problem with backslashes. */
+      keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
+      if (rl_translate_keyseq (keyseq, keys, &keys_len))
+       {
+         xfree (keys);
+         return -1;
+       }
+      func = rl_function_of_keyseq_len (keys, keys_len, kmap, (int *)NULL);
+      xfree (keys);
 #if defined (VI_MODE)
       if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
 #else
@@ -322,9 +318,7 @@ rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
 }
 
 int
-rl_bind_keyseq_if_unbound (keyseq, default_func)
-     const char *keyseq;
-     rl_command_func_t *default_func;
+rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *default_func)
 {
   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
 }
@@ -333,9 +327,7 @@ rl_bind_keyseq_if_unbound (keyseq, default_func)
    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)
-     const char *keyseq, *macro;
-     Keymap map;
+rl_macro_bind (const char *keyseq, const char *macro, Keymap map)
 {
   char *macro_keys;
   int macro_keys_len;
@@ -357,16 +349,13 @@ rl_macro_bind (keyseq, macro, map)
    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;
-     const char *keyseq;
-     char *data;
-     Keymap map;
+rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
 {
   char *keys;
-  int keys_len;
+  int keys_len, prevkey;
   register int i;
   KEYMAP_ENTRY k;
+  Keymap prevmap;  
 
   k.function = 0;
 
@@ -389,12 +378,18 @@ rl_generic_bind (type, keyseq, data, map)
       return -1;
     }
 
+  prevmap = map;
+  prevkey = keys[0];
+
   /* Bind keys, making new keymaps as necessary. */
   for (i = 0; i < keys_len; i++)
     {
       unsigned char uc = keys[i];
       int ic;
 
+      if (i > 0)
+       prevkey = ic;
+
       ic = uc;
       if (ic < 0 || ic >= KEYMAP_SIZE)
         {
@@ -406,7 +401,10 @@ rl_generic_bind (type, keyseq, data, map)
        {
          ic = UNMETA (ic);
          if (map[ESC].type == ISKMAP)
-           map = FUNCTION_TO_KEYMAP (map, ESC);
+           {
+             prevmap = map;
+             map = FUNCTION_TO_KEYMAP (map, ESC);
+           }
        }
 
       if ((i + 1) < keys_len)
@@ -425,6 +423,7 @@ rl_generic_bind (type, keyseq, data, map)
              map[ic].type = ISKMAP;
              map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
            }
+         prevmap = map;
          map = FUNCTION_TO_KEYMAP (map, ic);
          /* The dispatch code will return this function if no matching
             key sequence is found in the keymap.  This (with a little
@@ -444,6 +443,7 @@ rl_generic_bind (type, keyseq, data, map)
            xfree ((char *)map[ic].function);
          else if (map[ic].type == ISKMAP)
            {
+             prevmap = map;
              map = FUNCTION_TO_KEYMAP (map, ic);
              ic = ANYOTHERKEY;
              /* If we're trying to override a keymap with a null function
@@ -460,7 +460,28 @@ rl_generic_bind (type, keyseq, data, map)
        }
 
       rl_binding_keymap = map;
+
     }
+
+  /* If we unbound a key (type == ISFUNC, data == 0), and the prev keymap
+     points to the keymap where we unbound the key (sanity check), and the
+     current binding keymap is empty (rl_empty_keymap() returns non-zero),
+     and the binding keymap has ANYOTHERKEY set with type == ISFUNC
+     (overridden function), delete the now-empty keymap, take the previously-
+     overridden function and remove the override. */
+  /* Right now, this only works one level back. */
+  if (type == ISFUNC && data == 0 &&
+      prevmap[prevkey].type == ISKMAP &&
+      (FUNCTION_TO_KEYMAP(prevmap, prevkey) == rl_binding_keymap) &&
+      rl_binding_keymap[ANYOTHERKEY].type == ISFUNC &&
+      rl_empty_keymap (rl_binding_keymap))
+    {
+      prevmap[prevkey].type = rl_binding_keymap[ANYOTHERKEY].type;
+      prevmap[prevkey].function = rl_binding_keymap[ANYOTHERKEY].function;
+      rl_discard_keymap (rl_binding_keymap);
+      rl_binding_keymap = prevmap;
+    }
+
   xfree (keys);
   return 0;
 }
@@ -469,10 +490,7 @@ rl_generic_bind (type, keyseq, data, map)
    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)
-     const char *seq;
-     char *array;
-     int *len;
+rl_translate_keyseq (const char *seq, char *array, int *len)
 {
   register int i, c, l, temp;
 
@@ -483,7 +501,10 @@ rl_translate_keyseq (seq, array, len)
          c = seq[++i];
 
          if (c == 0)
-           break;
+           {
+             array[l++] = '\\';        /* preserve trailing backslash */
+             break;
+           }
 
          /* Handle \C- and \M- prefixes. */
          if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
@@ -494,8 +515,6 @@ rl_translate_keyseq (seq, array, len)
                  array[l++] = ESC;     /* ESC is meta-prefix */
                  i += 5;
                  array[l++] = CTRL (_rl_to_upper (seq[i]));
-                 if (seq[i] == '\0')
-                   i--;
                }
              else if (c == 'M')
                {
@@ -524,6 +543,8 @@ rl_translate_keyseq (seq, array, len)
                  /* Special hack for C-?... */
                  array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
                }
+             if (seq[i] == '\0')
+               break;
              continue;
            }         
 
@@ -596,8 +617,7 @@ rl_translate_keyseq (seq, array, len)
 }
 
 static int
-_rl_isescape (c)
-     int c;
+_rl_isescape (int c)
 {
   switch (c)
     {
@@ -613,8 +633,7 @@ _rl_isescape (c)
 }
 
 static int
-_rl_escchar (c)
-     int c;
+_rl_escchar (int c)
 {
   switch (c)
     {
@@ -630,8 +649,7 @@ _rl_escchar (c)
 }
 
 char *
-rl_untranslate_keyseq (seq)
-     int seq;
+rl_untranslate_keyseq (int seq)
 {
   static char kseq[16];
   int i, c;
@@ -681,9 +699,7 @@ rl_untranslate_keyseq (seq)
 }
 
 char *
-_rl_untranslate_macro_value (seq, use_escapes)
-     char *seq;
-     int use_escapes;
+_rl_untranslate_macro_value (char *seq, int use_escapes)
 {
   char *ret, *r, *s;
   int c;
@@ -742,8 +758,7 @@ _rl_untranslate_macro_value (seq, use_escapes)
    If STRING doesn't have a matching function, then a NULL pointer
    is returned. */
 rl_command_func_t *
-rl_named_function (string)
-     const char *string;
+rl_named_function (const char *string)
 {
   register int i;
 
@@ -760,18 +775,15 @@ rl_named_function (string)
    used.  TYPE, if non-NULL, is a pointer to an int which will receive the
    type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
    or ISMACR (macro). */
-rl_command_func_t *
-rl_function_of_keyseq (keyseq, map, type)
-     const char *keyseq;
-     Keymap map;
-     int *type;
+static rl_command_func_t *
+_rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int *type)
 {
   register int i;
 
   if (map == 0)
     map = _rl_keymap;
 
-  for (i = 0; keyseq && keyseq[i]; i++)
+  for (i = 0; keyseq && i < len; i++)
     {
       unsigned char ic = keyseq[i];
 
@@ -823,6 +835,18 @@ rl_function_of_keyseq (keyseq, map, type)
   return ((rl_command_func_t *) NULL);
 }
 
+rl_command_func_t *
+rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
+{
+  return _rl_function_of_keyseq_internal (keyseq, strlen (keyseq), map, type);
+}
+
+rl_command_func_t *
+rl_function_of_keyseq_len (const char *keyseq, size_t len, Keymap map, int *type)
+{
+  return _rl_function_of_keyseq_internal (keyseq, len, map, type);
+}
+
 /* The last key bindings file read. */
 static char *last_readline_init_file = (char *)NULL;
 
@@ -835,17 +859,20 @@ static int current_readline_init_lineno;
    The size of the buffer is returned in *SIZEP.  Returns NULL if any
    errors were encountered. */
 static char *
-_rl_read_file (filename, sizep)
-     char *filename;
-     size_t *sizep;
+_rl_read_file (char *filename, size_t *sizep)
 {
   struct stat finfo;
   size_t file_size;
   char *buffer;
   int i, file;
 
-  if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
-    return ((char *)NULL);
+  file = -1;
+  if (((file = open (filename, O_RDONLY, 0666)) < 0) || (fstat (file, &finfo) < 0))
+    {
+      if (file >= 0)
+       close (file);
+      return ((char *)NULL);
+    }
 
   file_size = (size_t)finfo.st_size;
 
@@ -882,8 +909,7 @@ _rl_read_file (filename, sizep)
 
 /* Re-read the current keybindings file. */
 int
-rl_re_read_init_file (count, ignore)
-     int count, ignore;
+rl_re_read_init_file (int count, int ignore)
 {
   int r;
   r = rl_read_init_file ((const char *)NULL);
@@ -900,8 +926,7 @@ rl_re_read_init_file (count, ignore)
    If the file existed and could be opened and read, 0 is returned,
    otherwise errno is returned. */
 int
-rl_read_init_file (filename)
-     const char *filename;
+rl_read_init_file (const char *filename)
 {
   /* Default the filename. */
   if (filename == 0)
@@ -926,9 +951,7 @@ rl_read_init_file (filename)
 }
 
 static int
-_rl_read_init_file (filename, include_level)
-     const char *filename;
-     int include_level;
+_rl_read_init_file (const char *filename, int include_level)
 {
   register int i;
   char *buffer, *openname, *line, *end;
@@ -1025,6 +1048,62 @@ _rl_init_file_error (va_alist)
   va_end (args);
 }
 
+/* **************************************************************** */
+/*                                                                 */
+/*                     Parser Helper Functions                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static int
+parse_comparison_op (s, indp)
+     const char *s;
+     int *indp;
+{
+  int i, peekc, op;
+
+  if (OPSTART (s[*indp]) == 0)
+    return -1;
+  i = *indp;
+  peekc = s[i] ? s[i+1] : 0;
+  op = -1;
+
+  if (s[i] == '=')
+    {
+      op = OP_EQ;
+      if (peekc == '=')
+        i++;
+      i++;
+    }
+  else if (s[i] == '!' && peekc == '=')
+    {
+      op = OP_NE;
+      i += 2;
+    }
+  else if (s[i] == '<' && peekc == '=')
+    {
+      op = OP_LE;
+      i += 2;
+    }
+  else if (s[i] == '>' && peekc == '=')
+    {
+      op = OP_GE;
+      i += 2;
+    }
+  else if (s[i] == '<')
+    {
+      op = OP_LT;
+      i += 1;
+    }
+  else if (s[i] == '>')
+    {
+      op = OP_GT;
+      i += 1;
+    }
+
+  *indp = i;
+  return op;        
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Parser Directives                           */
@@ -1055,10 +1134,11 @@ static int if_stack_size;
 /* Push _rl_parsing_conditionalized_out, and set parser state based
    on ARGS. */
 static int
-parser_if (args)
-     char *args;
+parser_if (char *args)
 {
-  register int i;
+  int i, llen, boolvar, strvar;
+
+  boolvar = strvar = -1;
 
   /* Push parser state. */
   if (if_stack_depth + 1 >= if_stack_size)
@@ -1075,6 +1155,8 @@ parser_if (args)
   if (_rl_parsing_conditionalized_out)
     return 0;
 
+  llen = strlen (args);
+
   /* Isolate first argument. */
   for (i = 0; args[i] && !whitespace (args[i]); i++);
 
@@ -1117,10 +1199,138 @@ parser_if (args)
       _rl_parsing_conditionalized_out = mode != rl_editing_mode;
     }
 #endif /* VI_MODE */
+  else if (_rl_strnicmp (args, "version", 7) == 0)
+    {
+      int rlversion, versionarg, op, previ, major, minor;
+
+      _rl_parsing_conditionalized_out = 1;
+      rlversion = RL_VERSION_MAJOR*10 + RL_VERSION_MINOR;
+      /* if "version" is separated from the operator by whitespace, or the
+         operand is separated from the operator by whitespace, restore it.
+         We're more liberal with allowed whitespace for this variable. */
+      if (i > 0 && i <= llen && args[i-1] == '\0')
+        args[i-1] = ' ';
+      args[llen] = '\0';               /* just in case */
+      for (i = 7; whitespace (args[i]); i++)
+       ;
+      if (OPSTART(args[i]) == 0)
+       {
+         _rl_init_file_error ("comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line");
+         return 0;
+       }
+      previ = i;
+      op = parse_comparison_op (args, &i);
+      if (op <= 0)
+       {
+         _rl_init_file_error ("comparison operator expected, found `%s'", args+previ);
+         return 0;
+       }
+      for ( ; args[i] && whitespace (args[i]); i++)
+       ;
+      if (args[i] == 0 || _rl_digit_p (args[i]) == 0)
+       {
+         _rl_init_file_error ("numeric argument expected, found `%s'", args+i);
+         return 0;
+       }
+      major = minor = 0;
+      previ = i;
+      for ( ; args[i] && _rl_digit_p (args[i]); i++)
+       major = major*10 + _rl_digit_value (args[i]);
+      if (args[i] == '.')
+       {
+         if (args[i + 1] && _rl_digit_p (args [i + 1]) == 0)
+           {
+             _rl_init_file_error ("numeric argument expected, found `%s'", args+previ);
+             return 0;
+           }
+         for (++i; args[i] && _rl_digit_p (args[i]); i++)
+           minor = minor*10 + _rl_digit_value (args[i]);
+       }
+      /* optional - check for trailing garbage on the line, allow whitespace
+        and a trailing comment */
+      previ = i;
+      for ( ; args[i] && whitespace (args[i]); i++)
+       ;
+      if (args[i] && args[i] != '#')
+       {
+         _rl_init_file_error ("trailing garbage on line: `%s'", args+previ);
+         return 0;
+       }
+      versionarg = major*10 + minor;
+
+      switch (op)
+       {
+       case OP_EQ:
+         _rl_parsing_conditionalized_out = rlversion == versionarg;
+         break;
+       case OP_NE:
+         _rl_parsing_conditionalized_out = rlversion != versionarg;
+         break;
+       case OP_GT:
+         _rl_parsing_conditionalized_out = rlversion > versionarg;
+         break;
+       case OP_GE:
+         _rl_parsing_conditionalized_out = rlversion >= versionarg;
+         break;
+       case OP_LT:
+         _rl_parsing_conditionalized_out = rlversion < versionarg;
+         break;
+       case OP_LE:
+         _rl_parsing_conditionalized_out = rlversion <= versionarg;
+         break;
+       }
+    }
   /* Check to see if the first word in ARGS is the same as the
      value stored in rl_readline_name. */
   else if (_rl_stricmp (args, rl_readline_name) == 0)
     _rl_parsing_conditionalized_out = 0;
+  else if ((boolvar = find_boolean_var (args)) >= 0 || (strvar = find_string_var (args)) >= 0)
+    {
+      int op, previ;
+      size_t vlen;
+      const char *vname;
+      char *valuearg, *vval, prevc;
+
+      _rl_parsing_conditionalized_out = 1;
+      vname = (boolvar >= 0) ? boolean_varname (boolvar) : string_varname (strvar);
+      vlen = strlen (vname);
+      if (i > 0 && i <= llen && args[i-1] == '\0')
+        args[i-1] = ' ';
+      args[llen] = '\0';               /* just in case */
+      for (i = vlen; whitespace (args[i]); i++)
+       ;
+      if (CMPSTART(args[i]) == 0)
+       {
+         _rl_init_file_error ("equality comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line");
+         return 0;
+       }
+      previ = i;
+      op = parse_comparison_op (args, &i);
+      if (op != OP_EQ && op != OP_NE)
+       {
+         _rl_init_file_error ("equality comparison operator expected, found `%s'", args+previ);
+         return 0;
+       }
+      for ( ; args[i] && whitespace (args[i]); i++)
+       ;
+      if (args[i] == 0)
+       {
+         _rl_init_file_error ("argument expected, found `%s'", args+i);
+         return 0;
+       }
+      previ = i;
+      valuearg = args + i;
+      for ( ; args[i] && whitespace (args[i]) == 0; i++)
+       ;
+      prevc = args[i];
+      args[i] = '\0';          /* null-terminate valuearg */
+      vval = rl_variable_value (vname);
+      if (op == OP_EQ)
+        _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) != 0;
+      else if (op == OP_NE)
+        _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) == 0;
+      args[i] = prevc;
+    }
   else
     _rl_parsing_conditionalized_out = 1;
   return 0;
@@ -1128,8 +1338,7 @@ parser_if (args)
 
 /* Invert the current parser state if there is anything on the stack. */
 static int
-parser_else (args)
-     char *args;
+parser_else (char *args)
 {
   register int i;
 
@@ -1159,8 +1368,7 @@ parser_else (args)
 /* Terminate a conditional, popping the value of
    _rl_parsing_conditionalized_out from the stack. */
 static int
-parser_endif (args)
-     char *args;
+parser_endif (char *args)
 {
   if (if_stack_depth)
     _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
@@ -1170,8 +1378,7 @@ parser_endif (args)
 }
 
 static int
-parser_include (args)
-     char *args;
+parser_include (char *args)
 {
   const char *old_init_file;
   char *e;
@@ -1211,8 +1418,7 @@ static const struct {
 /* Handle a parser directive.  STATEMENT is the line of the directive
    without any leading `$'. */
 static int
-handle_parser_directive (statement)
-     char *statement;
+handle_parser_directive (char *statement)
 {
   register int i;
   char *directive, *args;
@@ -1249,9 +1455,7 @@ handle_parser_directive (statement)
 /* Start at STRING[START] and look for DELIM.  Return I where STRING[I] ==
    DELIM or STRING[I] == 0.  DELIM is usually a double quote. */
 static int
-_rl_skip_to_delim (string, start, delim)
-     char *string;
-     int start, delim;
+_rl_skip_to_delim (char *string, int start, int delim)
 {
   int i, c, passc;
 
@@ -1283,8 +1487,7 @@ _rl_skip_to_delim (string, start, delim)
    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;
+rl_parse_and_bind (char *string)
 {
   char *funname, *kname;
   register int c, i;
@@ -1328,6 +1531,12 @@ rl_parse_and_bind (string)
   /* Advance to the colon (:) or whitespace which separates the two objects. */
   for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
 
+  if (i == 0)
+    {
+      _rl_init_file_error ("`%s': invalid key binding: missing key sequence", string);
+      return 1;
+    }
+
   equivalency = (c == ':' && string[i + 1] == '=');
 
   foundsep = c != 0;
@@ -1406,6 +1615,11 @@ remove_trailing:
       i = _rl_skip_to_delim (string, i+1, *funname);
       if (string[i])
        i++;
+      else
+       {
+         _rl_init_file_error ("`%s': missing closing quote for macro", funname);
+         return 1;
+       }
     }
 
   /* Advance to the end of the string.  */
@@ -1583,8 +1797,7 @@ static const struct {
 };
 
 static int
-find_boolean_var (name)
-     const char *name;
+find_boolean_var (const char *name)
 {
   register int i;
 
@@ -1594,12 +1807,17 @@ find_boolean_var (name)
   return -1;
 }
 
+static const char *
+boolean_varname (int i)
+{
+  return ((i >= 0) ? boolean_varlist[i].name : (char *)NULL);
+}  
+
 /* Hooks for handling special boolean variables, where a
    function needs to be called or another variable needs
    to be changed when they're changed. */
 static void
-hack_special_boolean_var (i)
-     int i;
+hack_special_boolean_var (int i)
 {
   const char *name;
 
@@ -1668,8 +1886,7 @@ static const struct {
 };
 
 static int
-find_string_var (name)
-     const char *name;
+find_string_var (const char *name)
 {
   register int i;
 
@@ -1679,12 +1896,17 @@ find_string_var (name)
   return -1;
 }
 
+static const char *
+string_varname (int i)
+{
+  return ((i >= 0) ? string_varlist[i].name : (char *)NULL);
+}  
+
 /* A boolean value that can appear in a `set variable' command is true if
    the value is null or empty, `on' (case-insensitive), or "1".  Any other
    values result in 0 (false). */
 static int
-bool_to_int (value)
-     const char *value;
+bool_to_int (const char *value)
 {
   return (value == 0 || *value == '\0' ||
                (_rl_stricmp (value, "on") == 0) ||
@@ -1692,8 +1914,7 @@ bool_to_int (value)
 }
 
 char *
-rl_variable_value (name)
-     const char *name;
+rl_variable_value (const char *name)
 {
   register int i;
 
@@ -1711,8 +1932,7 @@ rl_variable_value (name)
 }
 
 int
-rl_variable_bind (name, value)
-     const char *name, *value;
+rl_variable_bind (const char *name, const char *value)
 {
   register int i;
   int  v;
@@ -1743,8 +1963,7 @@ rl_variable_bind (name, value)
 }
 
 static int
-sv_editmode (value)
-     const char *value;
+sv_editmode (const char *value)
 {
   if (_rl_strnicmp (value, "vi", 2) == 0)
     {
@@ -1764,8 +1983,7 @@ sv_editmode (value)
 }
 
 static int
-sv_combegin (value)
-     const char *value;
+sv_combegin (const char *value)
 {
   if (value && *value)
     {
@@ -1777,8 +1995,7 @@ sv_combegin (value)
 }
 
 static int
-sv_dispprefix (value)
-     const char *value;
+sv_dispprefix (const char *value)
 {
   int nval = 0;
 
@@ -1793,8 +2010,7 @@ sv_dispprefix (value)
 }
 
 static int
-sv_compquery (value)
-     const char *value;
+sv_compquery (const char *value)
 {
   int nval = 100;
 
@@ -1809,8 +2025,7 @@ sv_compquery (value)
 }
 
 static int
-sv_compwidth (value)
-     const char *value;
+sv_compwidth (const char *value)
 {
   int nval = -1;
 
@@ -1822,8 +2037,7 @@ sv_compwidth (value)
 }
 
 static int
-sv_histsize (value)
-     const char *value;
+sv_histsize (const char *value)
 {
   int nval;
 
@@ -1842,8 +2056,7 @@ sv_histsize (value)
 }
 
 static int
-sv_keymap (value)
-     const char *value;
+sv_keymap (const char *value)
 {
   Keymap kmap;
 
@@ -1857,8 +2070,7 @@ sv_keymap (value)
 }
 
 static int
-sv_seqtimeout (value)
-     const char *value;
+sv_seqtimeout (const char *value)
 {
   int nval;
 
@@ -1874,8 +2086,7 @@ sv_seqtimeout (value)
 }
 
 static int
-sv_bell_style (value)
-     const char *value;
+sv_bell_style (const char *value)
 {
   if (value == 0 || *value == '\0')
     _rl_bell_preference = AUDIBLE_BELL;
@@ -1891,8 +2102,7 @@ sv_bell_style (value)
 }
 
 static int
-sv_isrchterm (value)
-     const char *value;
+sv_isrchterm (const char *value)
 {
   int beg, end, delim;
   char *v;
@@ -1929,8 +2139,7 @@ sv_isrchterm (value)
 extern char *_rl_emacs_mode_str;
 
 static int
-sv_emacs_modestr (value)
-     const char *value;
+sv_emacs_modestr (const char *value)
 {
   if (value && *value)
     {
@@ -1958,8 +2167,7 @@ sv_emacs_modestr (value)
 }
 
 static int
-sv_viins_modestr (value)
-     const char *value;
+sv_viins_modestr (const char *value)
 {
   if (value && *value)
     {
@@ -1987,8 +2195,7 @@ sv_viins_modestr (value)
 }
 
 static int
-sv_vicmd_modestr (value)
-     const char *value;
+sv_vicmd_modestr (const char *value)
 {
   if (value && *value)
     {
@@ -2039,8 +2246,7 @@ static const assoc_list name_key_alist[] = {
 };
 
 static int
-glean_key_from_name (name)
-     char *name;
+glean_key_from_name (char *name)
 {
   register int i;
 
@@ -2052,10 +2258,12 @@ glean_key_from_name (name)
 }
 
 /* Auxiliary functions to manage keymaps. */
-static const struct {
-  const char * const name;
+struct name_and_keymap {
+  char *name;
   Keymap map;
-} keymap_names[] = {
+};
+
+static struct name_and_keymap builtin_keymap_names[] = {
   { "emacs", emacs_standard_keymap },
   { "emacs-standard", emacs_standard_keymap },
   { "emacs-meta", emacs_meta_keymap },
@@ -2069,45 +2277,116 @@ static const struct {
   { (char *)0x0, (Keymap)0x0 }
 };
 
-Keymap
-rl_get_keymap_by_name (name)
-     const char *name;
+/* -1 for NULL entry */
+#define NUM_BUILTIN_KEYMAPS (sizeof (builtin_keymap_names) / sizeof (builtin_keymap_names[0]) - 1)
+
+static struct name_and_keymap *keymap_names = builtin_keymap_names;
+
+static int
+_rl_get_keymap_by_name (const char *name)
 {
   register int i;
 
   for (i = 0; keymap_names[i].name; i++)
     if (_rl_stricmp (name, keymap_names[i].name) == 0)
-      return (keymap_names[i].map);
-  return ((Keymap) NULL);
+      return (i);
+  return -1;
 }
 
-char *
-rl_get_keymap_name (map)
-     Keymap map;
+Keymap
+rl_get_keymap_by_name (const char *name)
+{
+  int i;
+
+  i = _rl_get_keymap_by_name (name);
+  return ((i >= 0) ? keymap_names[i].map : (Keymap) NULL);
+}
+
+static int
+_rl_get_keymap_by_map (Keymap map)
 {
   register int i;
+
   for (i = 0; keymap_names[i].name; i++)
     if (map == keymap_names[i].map)
-      return ((char *)keymap_names[i].name);
-  return ((char *)NULL);
+      return (i);
+  return -1;
 }
-  
+
+char *
+rl_get_keymap_name (Keymap map)
+{
+  int i;
+
+  i = _rl_get_keymap_by_map (map);
+  return ((i >= 0) ? keymap_names[i].name : (char *)NULL);
+}
+
+int
+rl_set_keymap_name (const char *name, Keymap map)
+{
+  int i, ni, mi;
+
+  /* First check whether or not we're trying to rename a builtin keymap */
+  mi = _rl_get_keymap_by_map (map);
+  if (mi >= 0 && mi < NUM_BUILTIN_KEYMAPS)
+    return -1;
+
+  /* Then reject attempts to set one of the builtin names to a new map */
+  ni = _rl_get_keymap_by_name (name);
+  if (ni >= 0 && ni < NUM_BUILTIN_KEYMAPS)
+    return -1;
+
+  /* Renaming a keymap we already added */
+  if (mi >= 0) /* XXX - could be >= NUM_BUILTIN_KEYMAPS */
+    {
+      xfree (keymap_names[mi].name);
+      keymap_names[mi].name = savestring (name);
+      return mi;
+    }
+
+  /* Associating new keymap with existing name */
+  if (ni >= 0)
+    {
+      keymap_names[ni].map = map;
+      return ni;
+    }
+
+  for (i = 0; keymap_names[i].name; i++)
+    ;
+
+  if (keymap_names == builtin_keymap_names)
+    {
+      keymap_names = xmalloc ((i + 2) * sizeof (struct name_and_keymap));
+      memcpy (keymap_names, builtin_keymap_names, i * sizeof (struct name_and_keymap));
+    }
+  else
+    keymap_names = xrealloc (keymap_names, (i + 2) * sizeof (struct name_and_keymap));
+
+  keymap_names[i].name = savestring (name);
+  keymap_names[i].map = map;
+
+  keymap_names[i+1].name = NULL;
+  keymap_names[i+1].map = NULL;
+
+  return i;
+}
+
 void
-rl_set_keymap (map)
-     Keymap map;
+rl_set_keymap (Keymap map)
 {
   if (map)
     _rl_keymap = map;
 }
 
 Keymap
-rl_get_keymap ()
+rl_get_keymap (void)
 {
   return (_rl_keymap);
 }
 
 void
-rl_set_keymap_from_edit_mode ()
+rl_set_keymap_from_edit_mode (void)
 {
   if (rl_editing_mode == emacs_mode)
     _rl_keymap = emacs_standard_keymap;
@@ -2118,7 +2397,7 @@ rl_set_keymap_from_edit_mode ()
 }
 
 char *
-rl_get_keymap_name_from_edit_mode ()
+rl_get_keymap_name_from_edit_mode (void)
 {
   if (rl_editing_mode == emacs_mode)
     return "emacs";
@@ -2143,7 +2422,7 @@ rl_get_keymap_name_from_edit_mode ()
 
 /* Print the names of functions known to Readline. */
 void
-rl_list_funmap_names ()
+rl_list_funmap_names (void)
 {
   register int i;
   const char **funmap_names;
@@ -2160,8 +2439,7 @@ rl_list_funmap_names ()
 }
 
 static char *
-_rl_get_keyname (key)
-     int key;
+_rl_get_keyname (int key)
 {
   char *keyname;
   int i, c;
@@ -2236,9 +2514,7 @@ _rl_get_keyname (key)
 /* Return a NULL terminated array of strings which represent the key
    sequences that are used to invoke FUNCTION in MAP. */
 char **
-rl_invoking_keyseqs_in_map (function, map)
-     rl_command_func_t *function;
-     Keymap map;
+rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
 {
   register int key;
   char **result;
@@ -2345,8 +2621,7 @@ rl_invoking_keyseqs_in_map (function, map)
 /* Return a NULL terminated array of strings which represent the key
    sequences that can be used to invoke FUNCTION using the current keymap. */
 char **
-rl_invoking_keyseqs (function)
-     rl_command_func_t *function;
+rl_invoking_keyseqs (rl_command_func_t *function)
 {
   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
 }
@@ -2355,8 +2630,7 @@ rl_invoking_keyseqs (function)
    PRINT_READABLY is non-zero, then print the output in such a way
    that it can be read back in. */
 void
-rl_function_dumper (print_readably)
-     int print_readably;
+rl_function_dumper (int print_readably)
 {
   register int i;
   const char **names;
@@ -2427,8 +2701,7 @@ rl_function_dumper (print_readably)
    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_dump_functions (int count, int key)
 {
   if (rl_dispatching)
     fprintf (rl_outstream, "\r\n");
@@ -2438,10 +2711,7 @@ rl_dump_functions (count, key)
 }
 
 static void
-_rl_macro_dumper_internal (print_readably, map, prefix)
-     int print_readably;
-     Keymap map;
-     char *prefix;
+_rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
 {
   register int key;
   char *keyname, *out;
@@ -2500,15 +2770,13 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
 }
 
 void
-rl_macro_dumper (print_readably)
-     int print_readably;
+rl_macro_dumper (int print_readably)
 {
   _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
 }
 
 int
-rl_dump_macros (count, key)
-     int count, key;
+rl_dump_macros (int count, int key)
 {
   if (rl_dispatching)
     fprintf (rl_outstream, "\r\n");
@@ -2518,8 +2786,7 @@ rl_dump_macros (count, key)
 }
 
 static char *
-_rl_get_string_variable_value (name)
-     const char *name;
+_rl_get_string_variable_value (const char *name)
 {
   static char numbuf[32];
   char *ret;
@@ -2599,8 +2866,7 @@ _rl_get_string_variable_value (name)
 }
 
 void
-rl_variable_dumper (print_readably)
-     int print_readably;
+rl_variable_dumper (int print_readably)
 {
   int i;
   char *v;
@@ -2631,8 +2897,7 @@ rl_variable_dumper (print_readably)
    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_dump_variables (int count, int key)
 {
   if (rl_dispatching)
     fprintf (rl_outstream, "\r\n");
@@ -2643,9 +2908,7 @@ rl_dump_variables (count, key)
 
 /* Return non-zero if any members of ARRAY are a substring in STRING. */
 static int
-substring_member_of_array (string, array)
-     const char *string;
-     const char * const *array;
+substring_member_of_array (const char *string, const char * const *array)
 {
   while (*array)
     {
This page took 0.087189 seconds and 4 git commands to generate.