--- embedaddon/readline/bind.c 2014/07/30 08:16:45 1.1.1.1 +++ embedaddon/readline/bind.c 2021/03/17 01:01:01 1.1.1.2 @@ -1,6 +1,6 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987-2012 Free Software Foundation, Inc. +/* Copyright (C) 1987-2020 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. @@ -74,22 +74,45 @@ Keymap rl_binding_keymap; static int _rl_skip_to_delim PARAMS((char *, int, int)); +#if defined (USE_VARARGS) && defined (PREFER_STDARG) +static void _rl_init_file_error (const char *, ...) __attribute__((__format__ (printf, 1, 2))); +#else +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 void _rl_init_file_error PARAMS((const char *)); static int _rl_read_init_file PARAMS((const char *, int)); 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 */ @@ -100,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); @@ -113,13 +133,15 @@ 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) { - if (key < 0) + char keyseq[4]; + int l; + + if (key < 0 || key > largest_char) return (key); + /* Want to make this a multi-character key sequence with an ESC prefix */ if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { if (_rl_keymap[ESC].type == ISKMAP) @@ -132,11 +154,46 @@ rl_bind_key (key, function) escmap[key].function = function; return (0); } - return (key); + + /* Otherwise, let's just let rl_generic_bind handle the key sequence. + We start it off with ESC here and let the code below add the rest + of the sequence. */ + keyseq[0] = ESC; + l = 1; + key = UNMETA(key); + goto bind_keyseq; } - _rl_keymap[key].type = ISFUNC; - _rl_keymap[key].function = function; + /* If it's bound to a function or macro, just overwrite. Otherwise we have + to treat it as a key sequence so rl_generic_bind handles shadow keymaps + for us. If we are binding '\' or \C-@ (NUL) make sure to escape it so + it makes it through the call to rl_translate_keyseq. */ + if (_rl_keymap[key].type != ISKMAP) + { + if (_rl_keymap[key].type == ISMACR) + xfree ((char *)_rl_keymap[key].function); + _rl_keymap[key].type = ISFUNC; + _rl_keymap[key].function = function; + } + else + { + l = 0; +bind_keyseq: + if (key == '\\') + { + keyseq[l++] = '\\'; + keyseq[l++] = '\\'; + } + else if (key == '\0') + { + keyseq[l++] = '\\'; + keyseq[l++] = '0'; + } + else + keyseq[l++] = key; + keyseq[l] = '\0'; + rl_bind_keyseq (keyseq, function); + } rl_binding_keymap = _rl_keymap; return (0); } @@ -144,10 +201,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; @@ -160,57 +214,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; @@ -221,14 +262,20 @@ rl_unbind_function_in_map (func, map) map[i].function = (rl_command_func_t *)NULL; rval = 1; } + else if (map[i].type == ISKMAP) /* TAG:readline-8.1 */ + { + int r; + r = rl_unbind_function_in_map (func, FUNCTION_TO_KEYMAP (map, i)); + if (r == 1) + rval = 1; + } } 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; @@ -242,9 +289,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)); } @@ -253,20 +298,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)); } @@ -275,16 +314,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 @@ -298,9 +345,7 @@ rl_bind_keyseq_if_unbound_in_map (keyseq, default_func } 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)); } @@ -309,9 +354,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; @@ -333,16 +376,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, ic; register int i; KEYMAP_ENTRY k; + Keymap prevmap; k.function = 0; @@ -365,12 +405,17 @@ 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) { @@ -378,12 +423,19 @@ rl_generic_bind (type, keyseq, data, map) return -1; } + /* We now rely on rl_translate_keyseq to do this conversion, so this + check is superfluous. */ +#if 0 if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { ic = UNMETA (ic); if (map[ESC].type == ISKMAP) - map = FUNCTION_TO_KEYMAP (map, ESC); + { + prevmap = map; + map = FUNCTION_TO_KEYMAP (map, ESC); + } } +#endif if ((i + 1) < keys_len) { @@ -401,6 +453,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 @@ -416,10 +469,9 @@ rl_generic_bind (type, keyseq, data, map) } else { - if (map[ic].type == ISMACR) - xfree ((char *)map[ic].function); - else if (map[ic].type == ISKMAP) + 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 @@ -430,13 +482,36 @@ rl_generic_bind (type, keyseq, data, map) if (type == ISFUNC && data == 0) data = (char *)_rl_null_function; } + if (map[ic].type == ISMACR) + xfree ((char *)map[ic].function); map[ic].function = KEYMAP_TO_FUNCTION (data); map[ic].type = type; } 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; } @@ -445,62 +520,41 @@ 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; + register int i, l, temp; + int has_control, has_meta; + unsigned char c; - for (i = l = 0; c = seq[i]; i++) + has_control = 0; + has_meta = 0; + + /* When there are incomplete prefixes \C- or \M- (has_control || has_meta) + without base character at the end of SEQ, they are processed as the + prefixes for '\0'. + */ + for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++) { - if (c == '\\') + /* Only backslashes followed by a non-null character are handled + specially. Trailing backslash (backslash followed by '\0') is + processed as a normal character. + */ + if (c == '\\' && seq[i + 1] != '\0') { c = seq[++i]; - if (c == 0) - break; - /* Handle \C- and \M- prefixes. */ - if ((c == 'C' || c == 'M') && seq[i + 1] == '-') + if (c == 'C' && seq[i + 1] == '-') { - /* Handle special case of backwards define. */ - if (strncmp (&seq[i], "C-\\M-", 5) == 0) - { - 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') - { - i++; /* seq[i] == '-' */ - /* XXX - obey convert-meta setting */ - if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP) - array[l++] = ESC; /* ESC is meta-prefix */ - else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-') - { - i += 4; - temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); - array[l++] = META (temp); - } - else - { - /* This doesn't yet handle things like \M-\a, which may - or may not have any reasonable meaning. You're - probably better off using straight octal or hex. */ - i++; - array[l++] = META (seq[i]); - } - } - else if (c == 'C') - { - i += 2; - /* Special hack for C-?... */ - array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); - } + i++; + has_control = 1; continue; + } + else if (c == 'M' && seq[i + 1] == '-') + { + i++; + has_meta = 1; + continue; } /* Translate other backslash-escaped characters. These are the @@ -510,42 +564,42 @@ rl_translate_keyseq (seq, array, len) switch (c) { case 'a': - array[l++] = '\007'; + c = '\007'; break; case 'b': - array[l++] = '\b'; + c = '\b'; break; case 'd': - array[l++] = RUBOUT; /* readline-specific */ + c = RUBOUT; /* readline-specific */ break; case 'e': - array[l++] = ESC; + c = ESC; break; case 'f': - array[l++] = '\f'; + c = '\f'; break; case 'n': - array[l++] = NEWLINE; + c = NEWLINE; break; case 'r': - array[l++] = RETURN; + c = RETURN; break; case 't': - array[l++] = TAB; + c = TAB; break; case 'v': - array[l++] = 0x0B; + c = 0x0B; break; case '\\': - array[l++] = '\\'; + c = '\\'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': i++; - for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++) + for (temp = 2, c -= '0'; ISOCTAL ((unsigned char)seq[i]) && temp--; i++) c = (c * 8) + OCTVALUE (seq[i]); i--; /* auto-increment in for loop */ - array[l++] = c & largest_char; + c &= largest_char; break; case 'x': i++; @@ -554,16 +608,40 @@ rl_translate_keyseq (seq, array, len) if (temp == 2) c = 'x'; i--; /* auto-increment in for loop */ - array[l++] = c & largest_char; + c &= largest_char; break; default: /* backslashes before non-special chars just add the char */ - array[l++] = c; + c &= largest_char; break; /* the backslash is stripped */ } - continue; } - array[l++] = c; + /* Process \C- and \M- flags */ + if (has_control) + { + /* Special treatment for C-? */ + c = (c == '?') ? RUBOUT : CTRL (_rl_to_upper (c)); + has_control = 0; + } + if (has_meta) + { + c = META (c); + has_meta = 0; + } + + /* If convert-meta is turned on, convert a meta char to a key sequence */ + if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii) + { + array[l++] = ESC; /* ESC is meta-prefix */ + array[l++] = UNMETA (c); + } + else + array[l++] = (c); + + /* Null characters may be processed for incomplete prefixes at the end of + sequence */ + if (seq[i] == '\0') + break; } *len = l; @@ -572,8 +650,7 @@ rl_translate_keyseq (seq, array, len) } static int -_rl_isescape (c) - int c; +_rl_isescape (int c) { switch (c) { @@ -589,8 +666,7 @@ _rl_isescape (c) } static int -_rl_escchar (c) - int c; +_rl_escchar (int c) { switch (c) { @@ -606,8 +682,7 @@ _rl_escchar (c) } char * -rl_untranslate_keyseq (seq) - int seq; +rl_untranslate_keyseq (int seq) { static char kseq[16]; int i, c; @@ -657,9 +732,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; @@ -716,10 +789,9 @@ _rl_untranslate_macro_value (seq, use_escapes) /* Return a pointer to the function that STRING represents. If STRING doesn't have a matching function, then a NULL pointer - is returned. */ + is returned. The string match is case-insensitive. */ rl_command_func_t * -rl_named_function (string) - const char *string; +rl_named_function (const char *string) { register int i; @@ -736,18 +808,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]; @@ -773,7 +842,7 @@ rl_function_of_keyseq (keyseq, map, type) { /* If this is the last key in the key sequence, return the map. */ - if (keyseq[i + 1] == '\0') + if (i + 1 == len) { if (type) *type = ISKMAP; @@ -786,9 +855,9 @@ rl_function_of_keyseq (keyseq, map, type) /* If we're not at the end of the key sequence, and the current key is bound to something other than a keymap, then the entire key sequence is not bound. */ - else if (map[ic].type != ISKMAP && keyseq[i+1]) + else if (map[ic].type != ISKMAP && i+1 < len) return ((rl_command_func_t *)NULL); - else /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */ + else /* map[ic].type != ISKMAP && i+1 == len */ { if (type) *type = map[ic].type; @@ -799,6 +868,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; @@ -811,17 +892,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; @@ -858,8 +942,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); @@ -876,8 +959,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) @@ -902,9 +984,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; @@ -970,18 +1050,95 @@ _rl_read_init_file (filename, include_level) } static void -_rl_init_file_error (msg) - const char *msg; +#if defined (PREFER_STDARG) +_rl_init_file_error (const char *format, ...) +#else +_rl_init_file_error (va_alist) + va_dcl +#endif { + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + fprintf (stderr, "readline: "); if (currently_reading_init_file) - _rl_errmsg ("%s: line %d: %s\n", current_readline_init_file, - current_readline_init_lineno, msg); - else - _rl_errmsg ("%s", msg); + fprintf (stderr, "%s: line %d: ", current_readline_init_file, + current_readline_init_lineno); + + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); + + 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 */ /* */ /* **************************************************************** */ @@ -1010,11 +1167,12 @@ 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) { @@ -1030,6 +1188,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++); @@ -1072,10 +1232,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; @@ -1083,8 +1371,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; @@ -1114,8 +1401,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]; @@ -1125,8 +1411,7 @@ parser_endif (args) } static int -parser_include (args) - char *args; +parser_include (char *args) { const char *old_init_file; char *e; @@ -1166,8 +1451,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; @@ -1197,16 +1481,14 @@ handle_parser_directive (statement) } /* display an error message about the unknown parser directive */ - _rl_init_file_error ("unknown parser directive"); + _rl_init_file_error ("%s: unknown parser directive", directive); return (1); } /* 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; @@ -1238,12 +1520,11 @@ _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; - int key, equivalency; + int key, equivalency, foundmod, foundsep; while (string && whitespace (*string)) string++; @@ -1273,7 +1554,7 @@ rl_parse_and_bind (string) /* If we didn't find a closing quote, abort the line. */ if (string[i] == '\0') { - _rl_init_file_error ("no closing `\"' in key binding"); + _rl_init_file_error ("%s: no closing `\"' in key binding", string); return 1; } else @@ -1283,8 +1564,16 @@ 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; + /* Mark the end of the command (or keyname). */ if (string[i]) string[i++] = '\0'; @@ -1313,15 +1602,11 @@ rl_parse_and_bind (string) /* Strip trailing whitespace from values of boolean variables. */ if (find_boolean_var (var) >= 0) { - /* remove trailing whitespace */ -remove_trailing: - e = value + strlen (value) - 1; - while (e >= value && whitespace (*e)) - e--; - e++; /* skip back to whitespace or EOS */ - - if (*e && e >= value) - *e = '\0'; + /* just read a whitespace-delimited word or empty string */ + for (e = value; *e && whitespace (*e) == 0; e++) + ; + if (e > value) + *e = '\0'; /* cut off everything trailing */ } else if ((i = find_string_var (var)) >= 0) { @@ -1333,9 +1618,24 @@ remove_trailing: value++; /* skip past the quote */ } else - goto remove_trailing; + { + /* remove trailing whitespace */ + e = value + strlen (value) - 1; + while (e >= value && whitespace (*e)) + e--; + e++; /* skip back to whitespace or EOS */ + + if (*e && e >= value) + *e = '\0'; + } } - + else + { + /* avoid calling rl_variable_bind just to find this out */ + _rl_init_file_error ("%s: unknown variable name", var); + return 1; + } + rl_variable_bind (var, value); return 0; } @@ -1359,6 +1659,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. */ @@ -1374,6 +1679,12 @@ remove_trailing: return 0; } + if (foundsep == 0) + { + _rl_init_file_error ("%s: no key sequence terminator", string); + return 1; + } + /* If this is a new-style key-binding, then do the binding with rl_bind_keyseq (). Otherwise, let the older code deal with it. */ if (*string == '"') @@ -1430,12 +1741,25 @@ remove_trailing: key = glean_key_from_name (kname); /* Add in control and meta bits. */ + foundmod = 0; if (substring_member_of_array (string, _rl_possible_control_prefixes)) - key = CTRL (_rl_to_upper (key)); + { + key = CTRL (_rl_to_upper (key)); + foundmod = 1; + } if (substring_member_of_array (string, _rl_possible_meta_prefixes)) - key = META (key); + { + key = META (key); + foundmod = 1; + } + if (foundmod == 0 && kname != string) + { + _rl_init_file_error ("%s: unknown key modifier", string); + return 1; + } + /* Temporary. Handle old-style keyname with macro-binding. */ if (*funname == '\'' || *funname == '"') { @@ -1461,6 +1785,7 @@ remove_trailing: #endif /* PREFIX_META_HACK */ else rl_bind_key (key, rl_named_function (funname)); + return 0; } @@ -1479,6 +1804,7 @@ static const struct { { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL }, { "byte-oriented", &rl_byte_oriented, 0 }, #if defined (COLOR_SUPPORT) + { "colored-completion-prefix",&_rl_colored_completion_prefix, 0 }, { "colored-stats", &_rl_colored_stats, 0 }, #endif { "completion-ignore-case", &_rl_completion_case_fold, 0 }, @@ -1486,6 +1812,7 @@ static const struct { { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 }, { "disable-completion", &rl_inhibit_completion, 0 }, { "echo-control-characters", &_rl_echo_control_chars, 0 }, + { "enable-bracketed-paste", &_rl_enable_bracketed_paste, V_SPECIAL }, { "enable-keypad", &_rl_enable_keypad, 0 }, { "enable-meta-key", &_rl_enable_meta, 0 }, { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, @@ -1514,8 +1841,7 @@ static const struct { }; static int -find_boolean_var (name) - const char *name; +find_boolean_var (const char *name) { register int i; @@ -1525,12 +1851,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; @@ -1547,6 +1878,8 @@ hack_special_boolean_var (i) } else if (_rl_stricmp (name, "show-mode-in-prompt") == 0) _rl_reset_prompt (); + else if (_rl_stricmp (name, "enable-bracketed-paste") == 0) + _rl_enable_active_region = _rl_enable_bracketed_paste; } typedef int _rl_sv_func_t PARAMS((const char *)); @@ -1569,10 +1902,13 @@ static int sv_dispprefix PARAMS((const char *)); static int sv_compquery PARAMS((const char *)); static int sv_compwidth PARAMS((const char *)); static int sv_editmode PARAMS((const char *)); +static int sv_emacs_modestr PARAMS((const char *)); static int sv_histsize PARAMS((const char *)); static int sv_isrchterm PARAMS((const char *)); static int sv_keymap PARAMS((const char *)); static int sv_seqtimeout PARAMS((const char *)); +static int sv_viins_modestr PARAMS((const char *)); +static int sv_vicmd_modestr PARAMS((const char *)); static const struct { const char * const name; @@ -1585,16 +1921,18 @@ static const struct { { "completion-prefix-display-length", V_INT, sv_dispprefix }, { "completion-query-items", V_INT, sv_compquery }, { "editing-mode", V_STRING, sv_editmode }, + { "emacs-mode-string", V_STRING, sv_emacs_modestr }, { "history-size", V_INT, sv_histsize }, { "isearch-terminators", V_STRING, sv_isrchterm }, { "keymap", V_STRING, sv_keymap }, { "keyseq-timeout", V_INT, sv_seqtimeout }, + { "vi-cmd-mode-string", V_STRING, sv_vicmd_modestr }, + { "vi-ins-mode-string", V_STRING, sv_viins_modestr }, { (char *)NULL, 0, (_rl_sv_func_t *)0 } }; static int -find_string_var (name) - const char *name; +find_string_var (const char *name) { register int i; @@ -1604,12 +1942,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-insenstive), or "1". Any other + the value is null or empty, `on' (case-insensitive), or "1". All 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) || @@ -1617,8 +1960,7 @@ bool_to_int (value) } char * -rl_variable_value (name) - const char *name; +rl_variable_value (const char *name) { register int i; @@ -1632,12 +1974,11 @@ rl_variable_value (name) return (_rl_get_string_variable_value (string_varlist[i].name)); /* Unknown variable names return NULL. */ - return 0; + return (char *)NULL; } int -rl_variable_bind (name, value) - const char *name, *value; +rl_variable_bind (const char *name, const char *value) { register int i; int v; @@ -1654,18 +1995,23 @@ rl_variable_bind (name, value) i = find_string_var (name); - /* For the time being, unknown variable names or string names without a - handler function are simply ignored. */ + /* For the time being, string names without a handler function are simply + ignored. */ if (i < 0 || string_varlist[i].set_func == 0) - return 0; + { + if (i < 0) + _rl_init_file_error ("%s: unknown variable name", name); + return 0; + } v = (*string_varlist[i].set_func) (value); + if (v != 0) + _rl_init_file_error ("%s: could not set value to `%s'", name, value); return v; } static int -sv_editmode (value) - const char *value; +sv_editmode (const char *value) { if (_rl_strnicmp (value, "vi", 2) == 0) { @@ -1685,8 +2031,7 @@ sv_editmode (value) } static int -sv_combegin (value) - const char *value; +sv_combegin (const char *value) { if (value && *value) { @@ -1698,8 +2043,7 @@ sv_combegin (value) } static int -sv_dispprefix (value) - const char *value; +sv_dispprefix (const char *value) { int nval = 0; @@ -1714,8 +2058,7 @@ sv_dispprefix (value) } static int -sv_compquery (value) - const char *value; +sv_compquery (const char *value) { int nval = 100; @@ -1730,8 +2073,7 @@ sv_compquery (value) } static int -sv_compwidth (value) - const char *value; +sv_compwidth (const char *value) { int nval = -1; @@ -1743,8 +2085,7 @@ sv_compwidth (value) } static int -sv_histsize (value) - const char *value; +sv_histsize (const char *value) { int nval; @@ -1763,8 +2104,7 @@ sv_histsize (value) } static int -sv_keymap (value) - const char *value; +sv_keymap (const char *value) { Keymap kmap; @@ -1778,8 +2118,7 @@ sv_keymap (value) } static int -sv_seqtimeout (value) - const char *value; +sv_seqtimeout (const char *value) { int nval; @@ -1795,8 +2134,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; @@ -1812,8 +2150,7 @@ sv_bell_style (value) } static int -sv_isrchterm (value) - const char *value; +sv_isrchterm (const char *value) { int beg, end, delim; char *v; @@ -1832,7 +2169,7 @@ sv_isrchterm (value) } else { - for (beg = end = 0; whitespace (v[end]) == 0; end++) + for (beg = end = 0; v[end] && whitespace (v[end]) == 0; end++) ; } @@ -1846,7 +2183,93 @@ sv_isrchterm (value) xfree (v); return 0; } - + +extern char *_rl_emacs_mode_str; + +static int +sv_emacs_modestr (const char *value) +{ + if (value && *value) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_emacs_mode_str, &_rl_emacs_modestr_len); + _rl_emacs_mode_str[_rl_emacs_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = (char *)xmalloc (1); + _rl_emacs_mode_str[_rl_emacs_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_emacs_modestr_len = 0; + return 0; + } + return 1; +} + +static int +sv_viins_modestr (const char *value) +{ + if (value && *value) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_vi_ins_mode_str, &_rl_vi_ins_modestr_len); + _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = (char *)xmalloc (1); + _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_vi_ins_modestr_len = 0; + return 0; + } + return 1; +} + +static int +sv_vicmd_modestr (const char *value) +{ + if (value && *value) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_vi_cmd_mode_str, &_rl_vi_cmd_modestr_len); + _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = (char *)xmalloc (1); + _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_vi_cmd_modestr_len = 0; + return 0; + } + return 1; +} + /* Return the character which matches NAME. For example, `Space' returns ' '. */ @@ -1871,8 +2294,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; @@ -1884,10 +2306,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 }, @@ -1901,45 +2325,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; @@ -1950,7 +2445,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"; @@ -1975,7 +2470,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; @@ -1992,8 +2487,7 @@ rl_list_funmap_names () } static char * -_rl_get_keyname (key) - int key; +_rl_get_keyname (int key) { char *keyname; int i, c; @@ -2068,9 +2562,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; @@ -2137,20 +2629,22 @@ rl_invoking_keyseqs_in_map (function, map) else sprintf (keyname, "\\e"); } - else if (CTRL_CHAR (key)) - sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key))); - else if (key == RUBOUT) - sprintf (keyname, "\\C-?"); - else if (key == '\\' || key == '"') - { - keyname[0] = '\\'; - keyname[1] = (char) key; - keyname[2] = '\0'; - } else { - keyname[0] = (char) key; - keyname[1] = '\0'; + int c = key, l = 0; + if (CTRL_CHAR (c) || c == RUBOUT) + { + keyname[l++] = '\\'; + keyname[l++] = 'C'; + keyname[l++] = '-'; + c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c)); + } + + if (c == '\\' || c == '"') + keyname[l++] = '\\'; + + keyname[l++] = (char) c; + keyname[l++] = '\0'; } strcat (keyname, seqs[i]); @@ -2177,8 +2671,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)); } @@ -2187,8 +2680,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; @@ -2259,8 +2751,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"); @@ -2270,10 +2761,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; @@ -2332,15 +2820,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"); @@ -2350,8 +2836,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; @@ -2420,13 +2905,18 @@ _rl_get_string_variable_value (name) sprintf (numbuf, "%d", _rl_keyseq_timeout); return (numbuf); } + else if (_rl_stricmp (name, "emacs-mode-string") == 0) + return (_rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT); + else if (_rl_stricmp (name, "vi-cmd-mode-string") == 0) + return (_rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT); + else if (_rl_stricmp (name, "vi-ins-mode-string") == 0) + return (_rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT); else return (0); } void -rl_variable_dumper (print_readably) - int print_readably; +rl_variable_dumper (int print_readably) { int i; char *v; @@ -2457,8 +2947,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"); @@ -2469,9 +2958,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) {