diff options
Diffstat (limited to 'bind.c')
-rw-r--r-- | bind.c | 395 |
1 files changed, 205 insertions, 190 deletions
@@ -1,6 +1,6 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987-2022 Free Software Foundation, Inc. +/* Copyright (C) 1987-2023 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. @@ -65,20 +65,15 @@ extern int errno; #include "rlshell.h" #include "xmalloc.h" -#if !defined (strchr) && !defined (__STDC__) -extern char *strchr (), *strrchr (); -#endif /* !strchr && !__STDC__ */ - /* Variables exported by this file. */ Keymap rl_binding_keymap; +/* Functions exported by this file. */ +rl_macro_print_func_t *rl_macro_display_hook = (rl_macro_print_func_t *)NULL; + static int _rl_skip_to_delim (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 (const char *, size_t, Keymap, int *); @@ -531,8 +526,7 @@ rl_translate_keyseq (const char *seq, char *array, int *len) /* 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'. - */ + prefixes for '\0'. */ for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++) { /* Only backslashes followed by a non-null character are handled @@ -629,11 +623,17 @@ rl_translate_keyseq (const char *seq, char *array, int *len) has_meta = 0; } - /* If convert-meta is turned on, convert a meta char to a key sequence */ + /* 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); + int x = UNMETA (c); + if (x) + { + array[l++] = ESC; /* ESC is meta-prefix */ + array[l++] = x; + } + else + array[l++] = c; /* just do the best we can without sticking a NUL in there. */ } else array[l++] = (c); @@ -685,7 +685,8 @@ char * rl_untranslate_keyseq (int seq) { static char kseq[16]; - int i, c; + int i; + unsigned char c; i = 0; c = seq; @@ -696,35 +697,22 @@ rl_untranslate_keyseq (int seq) kseq[i++] = '-'; c = UNMETA (c); } - else if (c == ESC) + + if (c == ESC) { kseq[i++] = '\\'; c = 'e'; } - else if (CTRL_CHAR (c)) - { - kseq[i++] = '\\'; - kseq[i++] = 'C'; - kseq[i++] = '-'; - c = _rl_to_lower (UNCTRL (c)); - } - else if (c == RUBOUT) + else if (CTRL_CHAR (c) || c == RUBOUT) { kseq[i++] = '\\'; kseq[i++] = 'C'; kseq[i++] = '-'; - c = '?'; + c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c)); } - if (c == ESC) - { - kseq[i++] = '\\'; - c = 'e'; - } - else if (c == '\\' || c == '"') - { - kseq[i++] = '\\'; - } + if (c == '\\' || c == '"') + kseq[i++] = '\\'; kseq[i++] = (unsigned char) c; kseq[i] = '\0'; @@ -735,9 +723,9 @@ char * _rl_untranslate_macro_value (char *seq, int use_escapes) { char *ret, *r, *s; - int c; + unsigned char c; - r = ret = (char *)xmalloc (7 * strlen (seq) + 1); + r = ret = (char *)xmalloc (8 * strlen (seq) + 1); for (s = seq; *s; s++) { c = *s; @@ -748,7 +736,9 @@ _rl_untranslate_macro_value (char *seq, int use_escapes) *r++ = '-'; c = UNMETA (c); } - else if (c == ESC) + + /* We want to keep from printing literal control chars */ + if (c == ESC) { *r++ = '\\'; c = 'e'; @@ -773,15 +763,10 @@ _rl_untranslate_macro_value (char *seq, int use_escapes) c = '?'; } - if (c == ESC) - { - *r++ = '\\'; - c = 'e'; - } - else if (c == '\\' || c == '"') + if (c == '\\' || c == '"') *r++ = '\\'; - *r++ = (unsigned char)c; + *r++ = c; } *r = '\0'; return ret; @@ -889,21 +874,30 @@ int rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map) { register int i, j, parsing_digits; - unsigned char ic; + unsigned int ic; /* int to handle ANYOTHERKEY */ Keymap map0; if (map == 0) map = _rl_keymap; map0 = map; - /* The digits following the initial one (e.g., the binding to digit-argument) - or the optional `-' in a binding to digit-argument or universal-argument - are not added to rl_executing_keyseq. This is basically everything read by - rl_digit_loop. The parsing_digits logic is here in case they ever are. */ + /* Make sure to add the digits following the initial one (e.g., the binding + to digit-argument) and the optional `-' in a binding to digit-argument + or universal-argument to rl_executing_keyseq. This is basically + everything read by rl_digit_loop. */ for (i = j = parsing_digits = 0; keyseq && i < len; i++) { ic = keyseq[i]; + if (parsing_digits == 2) + { + if (ic == '-') /* skip over runs of minus chars */ + { + j = i + 1; + continue; + } + parsing_digits = 1; + } if (parsing_digits) { if (_rl_digit_p (ic)) @@ -916,10 +910,11 @@ rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map) if (map[ic].type == ISKMAP) { - if (i + 1 == len) - return -1; map = FUNCTION_TO_KEYMAP (map, ic); - continue; + if (i + 1 == len) + ic = ANYOTHERKEY; + else + continue; } if (map[ic].type == ISFUNC) { @@ -938,16 +933,11 @@ rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map) /* This logic should be identical to rl_digit_loop */ /* We accept M-- as equivalent to M--1, C-u- as equivalent to C-u-1 - but set parsing_digits to 2 to note that we saw `-' */ - if (map[ic].function == rl_universal_argument && (i + 1 == '-')) - { - i++; - parsing_digits = 2; - } - if (map[ic].function == rl_digit_argument && ic == '-') - { - parsing_digits = 2; - } + but set parsing_digits to 2 to note that we saw `-'. See above + for the check that skips over one or more `-' characters. */ + if (map[ic].function == rl_universal_argument || + (map[ic].function == rl_digit_argument && ic == '-')) + parsing_digits = 2; map = map0; j = i + 1; @@ -978,11 +968,20 @@ _rl_read_file (char *filename, size_t *sizep) char *buffer; int i, file; - file = -1; - if (((file = open (filename, O_RDONLY, 0666)) < 0) || (fstat (file, &finfo) < 0)) + file = open (filename, O_RDONLY, 0666); + /* If the open is interrupted, retry once */ + if (file < 0 && errno == EINTR) { + RL_CHECK_SIGNALS (); + file = open (filename, O_RDONLY, 0666); + } + + if ((file < 0) || (fstat (file, &finfo) < 0)) + { + i = errno; if (file >= 0) close (file); + errno = i; return ((char *)NULL); } @@ -991,10 +990,13 @@ _rl_read_file (char *filename, size_t *sizep) /* check for overflow on very large files */ if (file_size != finfo.st_size || file_size + 1 < file_size) { + i = errno; if (file >= 0) close (file); #if defined (EFBIG) errno = EFBIG; +#else + errno = i; #endif return ((char *)NULL); } @@ -1129,25 +1131,11 @@ _rl_read_init_file (const char *filename, int include_level) } static void -#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) fprintf (stderr, "%s: line %d: ", current_readline_init_file, @@ -1245,7 +1233,7 @@ const char *rl_readline_name = "other"; /* Stack of previous values of parsing_conditionalized_out. */ static unsigned char *if_stack = (unsigned char *)NULL; static int if_stack_depth; -static int if_stack_size; +static size_t if_stack_size; /* Push _rl_parsing_conditionalized_out, and set parser state based on ARGS. */ @@ -1670,7 +1658,6 @@ rl_parse_and_bind (char *string) if (_rl_stricmp (string, "set") == 0) { char *var, *value, *e; - int s; var = string + i; /* Make VAR point to start of variable name. */ @@ -1848,7 +1835,7 @@ rl_parse_and_bind (char *string) if (*funname == '\'' || *funname == '"') { char useq[2]; - int fl = strlen (funname); + size_t fl = strlen (funname); useq[0] = key; useq[1] = '\0'; if (fl && funname[fl - 1] == *funname) @@ -1915,6 +1902,7 @@ static const struct { { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL }, { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 }, { "revert-all-at-newline", &_rl_revert_all_at_newline, 0 }, + { "search-ignore-case", &_rl_search_case_fold, 0 }, { "show-all-if-ambiguous", &_rl_complete_show_all, 0 }, { "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 }, { "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 }, @@ -2593,17 +2581,13 @@ _rl_get_keyname (int key) char *keyname; int i, c; - keyname = (char *)xmalloc (8); + keyname = (char *)xmalloc (9); c = key; /* Since this is going to be used to write out keysequence-function pairs for possible inclusion in an inputrc file, we don't want to do any special meta processing on KEY. */ -#if 1 - /* XXX - Experimental */ - /* We might want to do this, but the old version of the code did not. */ - /* If this is an escape character, we don't want to do any more processing. Just add the special ESC key sequence and return. */ if (c == ESC) @@ -2613,28 +2597,23 @@ _rl_get_keyname (int key) keyname[2] = '\0'; return keyname; } -#endif - /* RUBOUT is translated directly into \C-? */ - if (key == RUBOUT) + if (key == ANYOTHERKEY) { - keyname[0] = '\\'; - keyname[1] = 'C'; - keyname[2] = '-'; - keyname[3] = '?'; - keyname[4] = '\0'; + keyname[0] = '\0'; return keyname; } i = 0; + /* Now add special prefixes needed for control characters. This can potentially change C. */ - if (CTRL_CHAR (c)) + if (CTRL_CHAR (c) || c == RUBOUT) { keyname[i++] = '\\'; keyname[i++] = 'C'; keyname[i++] = '-'; - c = _rl_to_lower (UNCTRL (c)); + c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c)); } /* XXX experimental code. Turn the characters that are not ASCII or @@ -2676,7 +2655,7 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map) { register int key; char **result; - int result_index, result_size; + size_t result_index, result_size; result = (char **)NULL; result_index = result_size = 0; @@ -2712,53 +2691,24 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map) { char **seqs; register int i; + char *keyname; + size_t knlen; /* Find the list of keyseqs in this map which have FUNCTION as their target. Add the key sequences found to RESULT. */ - if (map[key].function) - seqs = - rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key)); - else + if (map[key].function == 0) break; + seqs = rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key)); if (seqs == 0) break; + keyname = _rl_get_keyname (key); + knlen = RL_STRLEN (keyname); + for (i = 0; seqs[i]; i++) { - char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); - - if (key == ESC) - { - /* If ESC is the meta prefix and we're converting chars - with the eighth bit set to ESC-prefixed sequences, then - we can use \M-. Otherwise we need to use the sequence - for ESC. */ - if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP) - sprintf (keyname, "\\M-"); - else - sprintf (keyname, "\\e"); - } - else - { - 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]); - xfree (seqs[i]); + char *x; if (result_index + 2 > result_size) { @@ -2766,10 +2716,16 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map) result = (char **)xrealloc (result, result_size * sizeof (char *)); } - result[result_index++] = keyname; + x = xmalloc (knlen + RL_STRLEN (seqs[i]) + 1); + strcpy (x, keyname); + strcpy (x + knlen, seqs[i]); + xfree (seqs[i]); + + result[result_index++] = x; result[result_index] = (char *)NULL; } + xfree (keyname); xfree (seqs); } break; @@ -2786,73 +2742,72 @@ rl_invoking_keyseqs (rl_command_func_t *function) return (rl_invoking_keyseqs_in_map (function, _rl_keymap)); } -/* Print all of the functions and their bindings to rl_outstream. If - PRINT_READABLY is non-zero, then print the output in such a way - that it can be read back in. */ void -rl_function_dumper (int print_readably) +rl_print_keybinding (const char *name, Keymap kmap, int print_readably) { - register int i; - const char **names; - const char *name; + rl_command_func_t *function; + char **invokers; - names = rl_funmap_names (); + function = rl_named_function (name); + invokers = rl_invoking_keyseqs_in_map (function, kmap ? kmap : _rl_keymap); - fprintf (rl_outstream, "\n"); - - for (i = 0; name = names[i]; i++) + if (print_readably) { - rl_command_func_t *function; - char **invokers; - - function = rl_named_function (name); - invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap); - - if (print_readably) + if (!invokers) + fprintf (rl_outstream, "# %s (not bound)\n", name); + else { - if (!invokers) - fprintf (rl_outstream, "# %s (not bound)\n", name); - else - { - register int j; + register int j; - for (j = 0; invokers[j]; j++) - { - fprintf (rl_outstream, "\"%s\": %s\n", - invokers[j], name); - xfree (invokers[j]); - } - - xfree (invokers); + for (j = 0; invokers[j]; j++) + { + fprintf (rl_outstream, "\"%s\": %s\n", invokers[j], name); + xfree (invokers[j]); } + + xfree (invokers); } + } + else + { + if (!invokers) + fprintf (rl_outstream, "%s is not bound to any keys\n", name); else { - if (!invokers) - fprintf (rl_outstream, "%s is not bound to any keys\n", - name); - else - { - register int j; + register int j; - fprintf (rl_outstream, "%s can be found on ", name); + fprintf (rl_outstream, "%s can be found on ", name); - for (j = 0; invokers[j] && j < 5; j++) - { - fprintf (rl_outstream, "\"%s\"%s", invokers[j], - invokers[j + 1] ? ", " : ".\n"); - } + for (j = 0; invokers[j] && j < 5; j++) + fprintf (rl_outstream, "\"%s\"%s", invokers[j], invokers[j + 1] ? ", " : ".\n"); - if (j == 5 && invokers[j]) - fprintf (rl_outstream, "...\n"); + if (j == 5 && invokers[j]) + fprintf (rl_outstream, "...\n"); - for (j = 0; invokers[j]; j++) - xfree (invokers[j]); + for (j = 0; invokers[j]; j++) + xfree (invokers[j]); - xfree (invokers); - } + xfree (invokers); } } +} + +/* Print all of the functions and their bindings to rl_outstream. If + PRINT_READABLY is non-zero, then print the output in such a way + that it can be read back in. */ +void +rl_function_dumper (int print_readably) +{ + register int i; + const char **names; + const char *name; + + names = rl_funmap_names (); + + fprintf (rl_outstream, "\n"); + + for (i = 0; name = names[i]; i++) + rl_print_keybinding (name, _rl_keymap, print_readably); xfree (names); } @@ -2873,9 +2828,9 @@ rl_dump_functions (int count, int key) static void _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix) { - register int key; + int key; char *keyname, *out; - int prefix_len; + size_t prefix_len; for (key = 0; key < KEYMAP_SIZE; key++) { @@ -2885,6 +2840,16 @@ _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix) keyname = _rl_get_keyname (key); out = _rl_untranslate_macro_value ((char *)map[key].function, 0); + /* If the application wants to print macros, let it. Give it the + ascii-fied value with backslash escapes, so it will have to use + rl_macro_bind (with its call to rl_translate_keyseq) to get the + same value back. */ + if (rl_macro_display_hook) + { + (*rl_macro_display_hook) (keyname, out, print_readably, prefix); + break; + } + if (print_readably) fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "", keyname, @@ -2948,10 +2913,40 @@ rl_dump_macros (int count, int key) static char * _rl_get_string_variable_value (const char *name) { - static char numbuf[32]; + static char numbuf[64]; /* more than enough for INTMAX_MAX */ char *ret; - if (_rl_stricmp (name, "bell-style") == 0) + if (_rl_stricmp (name, "active-region-start-color") == 0) + { + if (_rl_active_region_start_color == 0) + return 0; + ret = _rl_untranslate_macro_value (_rl_active_region_start_color, 0); + if (ret) + { + strncpy (numbuf, ret, sizeof (numbuf) - 1); + xfree (ret); + numbuf[sizeof(numbuf) - 1] = '\0'; + } + else + numbuf[0] = '\0'; + return numbuf; + } + else if (_rl_stricmp (name, "active-region-end-color") == 0) + { + if (_rl_active_region_end_color == 0) + return 0; + ret = _rl_untranslate_macro_value (_rl_active_region_end_color, 0); + if (ret) + { + strncpy (numbuf, ret, sizeof (numbuf) - 1); + xfree (ret); + numbuf[sizeof(numbuf) - 1] = '\0'; + } + else + numbuf[0] = '\0'; + return numbuf; + } + else if (_rl_stricmp (name, "bell-style") == 0) { switch (_rl_bell_preference) { @@ -2968,24 +2963,40 @@ _rl_get_string_variable_value (const char *name) return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); else if (_rl_stricmp (name, "completion-display-width") == 0) { +#if defined (HAVE_VSNPRINTF) + snprintf (numbuf, sizeof (numbuf), "%d", _rl_completion_columns); +#else sprintf (numbuf, "%d", _rl_completion_columns); +#endif return (numbuf); } else if (_rl_stricmp (name, "completion-prefix-display-length") == 0) { +#if defined (HAVE_VSNPRINTF) + snprintf (numbuf, sizeof (numbuf), "%d", _rl_completion_prefix_display_length); +#else sprintf (numbuf, "%d", _rl_completion_prefix_display_length); +#endif return (numbuf); } else if (_rl_stricmp (name, "completion-query-items") == 0) { +#if defined (HAVE_VSNPRINTF) + snprintf (numbuf, sizeof (numbuf), "%d", rl_completion_query_items); +#else sprintf (numbuf, "%d", rl_completion_query_items); +#endif return (numbuf); } else if (_rl_stricmp (name, "editing-mode") == 0) return (rl_get_keymap_name_from_edit_mode ()); else if (_rl_stricmp (name, "history-size") == 0) { - sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0); +#if defined (HAVE_VSNPRINTF) + snprintf (numbuf, sizeof (numbuf), "%d", history_is_stifled() ? history_max_entries : -1); +#else + sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : -1); +#endif return (numbuf); } else if (_rl_stricmp (name, "isearch-terminators") == 0) @@ -3012,7 +3023,11 @@ _rl_get_string_variable_value (const char *name) } else if (_rl_stricmp (name, "keyseq-timeout") == 0) { - sprintf (numbuf, "%d", _rl_keyseq_timeout); +#if defined (HAVE_VSNPRINTF) + snprintf (numbuf, sizeof (numbuf), "%d", _rl_keyseq_timeout); +#else + sprintf (numbuf, "%d", _rl_keyseq_timeout); +#endif return (numbuf); } else if (_rl_stricmp (name, "emacs-mode-string") == 0) |