aboutsummaryrefslogtreecommitdiff
path: root/readline/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'readline/bind.c')
-rw-r--r--readline/bind.c683
1 files changed, 473 insertions, 210 deletions
diff --git a/readline/bind.c b/readline/bind.c
index f1098c4..57ae10f 100644
--- a/readline/bind.c
+++ b/readline/bind.c
@@ -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;
@@ -1027,6 +1050,62 @@ _rl_init_file_error (va_alist)
/* **************************************************************** */
/* */
+/* 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)
{