X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=readline%2Fbind.c;h=57ae10f7318e521797fb4b8f7e426c7ab1324a49;hb=cb41b9e70e6fbd1cb603bb9ba4372fbb8ae87b20;hp=f1098c48b17ef910b18edea72c4d36926bb362c4;hpb=ca2589f3bbad1e151abbb293d4c43a87b7a4d5ec;p=deliverable%2Fbinutils-gdb.git diff --git a/readline/bind.c b/readline/bind.c index f1098c48b1..57ae10f731 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; @@ -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) {