aboutsummaryrefslogtreecommitdiff
path: root/readline/bind.c
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-10-07 12:52:13 -0600
committerTom Tromey <tom@tromey.com>2019-08-12 10:57:56 -0600
commit775e241e9c5f2b2ff2b59972ab70e5f20763fae6 (patch)
tree597ab643dce69ee6e98e46ecac00ee85f447bb4b /readline/bind.c
parent08132bdd876fa1825810f90ecc25390dd4ded457 (diff)
downloadgdb-775e241e9c5f2b2ff2b59972ab70e5f20763fae6.zip
gdb-775e241e9c5f2b2ff2b59972ab70e5f20763fae6.tar.gz
gdb-775e241e9c5f2b2ff2b59972ab70e5f20763fae6.tar.bz2
Import readline 7.0 (patch 5)
This imports readline 7.0 (up to patch 5) while preserving all gdb-local changes. This was done by checking out the readline git repository, making a branch based on the gdb baseline revision, applying the gdb changes to that branch, and then merging from readline 7. readline/ChangeLog.gdb 2019-08-12 Tom Tromey <tom@tromey.com> * Imported readline 7.0 patch 5.
Diffstat (limited to 'readline/bind.c')
-rw-r--r--readline/bind.c424
1 files changed, 344 insertions, 80 deletions
diff --git a/readline/bind.c b/readline/bind.c
index a939528..f1098c4 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-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2016 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.
@@ -72,11 +72,20 @@ extern char *strchr (), *strrchr ();
/* Variables exported by this file. */
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 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 char *_rl_get_string_variable_value PARAMS((const char *));
static int substring_member_of_array PARAMS((const char *, const char * const *));
@@ -113,6 +122,9 @@ rl_bind_key (key, function)
int key;
rl_command_func_t *function;
{
+ char keyseq[3];
+ int l;
+
if (key < 0)
return (key);
@@ -131,8 +143,24 @@ rl_bind_key (key, function)
return (key);
}
- _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 '\' make sure to escape it so it makes it
+ through the call to rl_translate_keyseq. */
+ if (_rl_keymap[key].type != ISKMAP)
+ {
+ _rl_keymap[key].type = ISFUNC;
+ _rl_keymap[key].function = function;
+ }
+ else
+ {
+ l = 0;
+ if (key == '\\')
+ keyseq[l++] = '\\';
+ keyseq[l++] = key;
+ keyseq[l] = '\0';
+ rl_bind_keyseq (keyseq, function);
+ }
rl_binding_keymap = _rl_keymap;
return (0);
}
@@ -538,7 +566,7 @@ rl_translate_keyseq (seq, array, len)
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;
@@ -567,6 +595,40 @@ rl_translate_keyseq (seq, array, len)
return (0);
}
+static int
+_rl_isescape (c)
+ int c;
+{
+ switch (c)
+ {
+ case '\007':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case TAB:
+ case 0x0b: return (1);
+ default: return (0);
+ }
+}
+
+static int
+_rl_escchar (c)
+ int c;
+{
+ switch (c)
+ {
+ case '\007': return ('a');
+ case '\b': return ('b');
+ case '\f': return ('f');
+ case '\n': return ('n');
+ case '\r': return ('r');
+ case TAB: return ('t');
+ case 0x0b: return ('v');
+ default: return (c);
+ }
+}
+
char *
rl_untranslate_keyseq (seq)
int seq;
@@ -618,9 +680,10 @@ rl_untranslate_keyseq (seq)
return kseq;
}
-static char *
-_rl_untranslate_macro_value (seq)
+char *
+_rl_untranslate_macro_value (seq, use_escapes)
char *seq;
+ int use_escapes;
{
char *ret, *r, *s;
int c;
@@ -644,9 +707,14 @@ _rl_untranslate_macro_value (seq)
else if (CTRL_CHAR (c))
{
*r++ = '\\';
- *r++ = 'C';
- *r++ = '-';
- c = _rl_to_lower (UNCTRL (c));
+ if (use_escapes && _rl_isescape (c))
+ c = _rl_escchar (c);
+ else
+ {
+ *r++ = 'C';
+ *r++ = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
}
else if (c == RUBOUT)
{
@@ -926,14 +994,35 @@ _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);
}
/* **************************************************************** */
@@ -1153,10 +1242,42 @@ 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;
+{
+ int i, c, passc;
+
+ for (i = start,passc = 0; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ if (c == 0)
+ break;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc = 1;
+ continue;
+ }
+
+ if (c == delim)
+ break;
+ }
+
+ return i;
+}
+
/* Read the binding command from STRING and perform it.
A key binding command looks like: Keyname: function-name\0,
a variable binding command looks like: set variable value.
@@ -1167,12 +1288,12 @@ rl_parse_and_bind (string)
{
char *funname, *kname;
register int c, i;
- int key, equivalency;
+ int key, equivalency, foundmod, foundsep;
while (string && whitespace (*string))
string++;
- if (!string || !*string || *string == '#')
+ if (string == 0 || *string == 0 || *string == '#')
return 0;
/* If this is a parser directive, act on it. */
@@ -1192,31 +1313,16 @@ rl_parse_and_bind (string)
backslash to quote characters in the key expression. */
if (*string == '"')
{
- int passc = 0;
-
- for (i = 1; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc++;
- continue;
- }
+ i = _rl_skip_to_delim (string, 1, '"');
- if (c == '"')
- break;
- }
/* 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
+ i++; /* skip past closing double quote */
}
/* Advance to the colon (:) or whitespace which separates the two objects. */
@@ -1224,6 +1330,8 @@ rl_parse_and_bind (string)
equivalency = (c == ':' && string[i + 1] == '=');
+ foundsep = c != 0;
+
/* Mark the end of the command (or keyname). */
if (string[i])
string[i++] = '\0';
@@ -1236,6 +1344,7 @@ rl_parse_and_bind (string)
if (_rl_stricmp (string, "set") == 0)
{
char *var, *value, *e;
+ int s;
var = string + i;
/* Make VAR point to start of variable name. */
@@ -1243,25 +1352,37 @@ rl_parse_and_bind (string)
/* Make VALUE point to start of value string. */
value = var;
- while (*value && !whitespace (*value)) value++;
+ while (*value && whitespace (*value) == 0) value++;
if (*value)
*value++ = '\0';
while (*value && whitespace (*value)) value++;
- /* Strip trailing whitespace from values to boolean variables. Temp
- fix until I get a real quoted-string parser here. */
- i = find_boolean_var (var);
- if (i >= 0)
+ /* 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';
}
-
+ else if ((i = find_string_var (var)) >= 0)
+ {
+ /* Allow quoted strings in variable values */
+ if (*value == '"')
+ {
+ i = _rl_skip_to_delim (value, 1, *value);
+ value[i] = '\0';
+ value++; /* skip past the quote */
+ }
+ else
+ goto remove_trailing;
+ }
+
rl_variable_bind (var, value);
return 0;
}
@@ -1282,32 +1403,13 @@ rl_parse_and_bind (string)
the quoted string delimiter, like the shell. */
if (*funname == '\'' || *funname == '"')
{
- int delimiter, passc;
-
- delimiter = string[i++];
- for (passc = 0; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc = 1;
- continue;
- }
-
- if (c == delimiter)
- break;
- }
- if (c)
+ i = _rl_skip_to_delim (string, i+1, *funname);
+ if (string[i])
i++;
}
/* Advance to the end of the string. */
- for (; string[i] && !whitespace (string[i]); i++);
+ for (; string[i] && whitespace (string[i]) == 0; i++);
/* No extra whitespace at the end of the string. */
string[i] = '\0';
@@ -1319,6 +1421,12 @@ rl_parse_and_bind (string)
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 == '"')
@@ -1367,7 +1475,7 @@ rl_parse_and_bind (string)
/* Get the actual character we want to deal with. */
kname = strrchr (string, '-');
- if (!kname)
+ if (kname == 0)
kname = string;
else
kname++;
@@ -1375,11 +1483,24 @@ rl_parse_and_bind (string)
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 == '"')
@@ -1406,6 +1527,7 @@ rl_parse_and_bind (string)
#endif /* PREFIX_META_HACK */
else
rl_bind_key (key, rl_named_function (funname));
+
return 0;
}
@@ -1423,11 +1545,16 @@ static const struct {
{ "bind-tty-special-chars", &_rl_bind_stty_chars, 0 },
{ "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 },
{ "completion-map-case", &_rl_completion_case_map, 0 },
{ "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, 0 },
{ "enable-keypad", &_rl_enable_keypad, 0 },
{ "enable-meta-key", &_rl_enable_meta, 0 },
{ "expand-tilde", &rl_complete_with_tilde_expansion, 0 },
@@ -1447,6 +1574,7 @@ static const struct {
{ "revert-all-at-newline", &_rl_revert_all_at_newline, 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 },
{ "skip-completed-text", &_rl_skip_completed_text, 0 },
#if defined (VISIBLE_STATS)
{ "visible-stats", &rl_visible_stats, 0 },
@@ -1486,6 +1614,8 @@ hack_special_boolean_var (i)
else
_rl_bell_preference = AUDIBLE_BELL;
}
+ else if (_rl_stricmp (name, "show-mode-in-prompt") == 0)
+ _rl_reset_prompt ();
}
typedef int _rl_sv_func_t PARAMS((const char *));
@@ -1508,9 +1638,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;
@@ -1523,9 +1657,13 @@ 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 }
};
@@ -1542,7 +1680,7 @@ find_string_var (name)
}
/* 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". Any other
values result in 0 (false). */
static int
bool_to_int (value)
@@ -1591,10 +1729,14 @@ 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);
return v;
@@ -1683,13 +1825,17 @@ static int
sv_histsize (value)
const char *value;
{
- int nval = 500;
+ int nval;
+ nval = 500;
if (value && *value)
{
nval = atoi (value);
if (nval < 0)
- return 1;
+ {
+ unstifle_history ();
+ return 0;
+ }
}
stifle_history (nval);
return 0;
@@ -1711,6 +1857,23 @@ sv_keymap (value)
}
static int
+sv_seqtimeout (value)
+ const char *value;
+{
+ int nval;
+
+ nval = 0;
+ if (value && *value)
+ {
+ nval = atoi (value);
+ if (nval < 0)
+ nval = 0;
+ }
+ _rl_keyseq_timeout = nval;
+ return 0;
+}
+
+static int
sv_bell_style (value)
const char *value;
{
@@ -1748,7 +1911,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++)
;
}
@@ -1762,7 +1925,96 @@ sv_isrchterm (value)
xfree (v);
return 0;
}
-
+
+extern char *_rl_emacs_mode_str;
+
+static int
+sv_emacs_modestr (value)
+ 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 (value)
+ 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 (value)
+ 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 ' '. */
@@ -2167,7 +2419,8 @@ rl_function_dumper (print_readably)
}
}
}
- free (names);
+
+ xfree (names);
}
/* Print all of the current functions and their bindings to
@@ -2200,7 +2453,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
{
case ISMACR:
keyname = _rl_get_keyname (key);
- out = _rl_untranslate_macro_value ((char *)map[key].function);
+ out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
if (print_readably)
fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
@@ -2312,7 +2565,7 @@ _rl_get_string_variable_value (name)
{
if (_rl_isearch_terminators == 0)
return 0;
- ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
+ ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
if (ret)
{
strncpy (numbuf, ret, sizeof (numbuf) - 1);
@@ -2330,6 +2583,17 @@ _rl_get_string_variable_value (name)
ret = rl_get_keymap_name_from_edit_mode ();
return (ret ? ret : "none");
}
+ else if (_rl_stricmp (name, "keyseq-timeout") == 0)
+ {
+ 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);
}