Bash-5.3-alpha release

This commit is contained in:
Chet Ramey
2024-04-22 10:33:38 -04:00
parent f3b6bd1945
commit 622d318652
700 changed files with 136534 additions and 96420 deletions
+3
View File
@@ -282,6 +282,9 @@ parse-colors.o: ${BUILD_DIR}/config.h colors.h parse-colors.h
parse-colors.o: rldefs.h rlconf.h
parse-colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
input.o: posixselect.h posixtime.h
parens.o: posixselect.h posixtime.h
bind.o: rlshell.h
histfile.o: rlshell.h
nls.o: rlshell.h
+1 -7
View File
@@ -2,7 +2,7 @@
/* A minimal stdlib.h containing extern declarations for those functions
that bash uses. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
/* Copyright (C) 1993,2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -32,13 +32,7 @@ extern double strtod ();
/* Memory allocation functions. */
/* Generic pointer type. */
#ifndef PTR_T
#if defined (__STDC__)
# define PTR_T void *
#else
# define PTR_T char *
#endif
#endif /* PTR_T */
extern PTR_T malloc ();
+210 -197
View File
@@ -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,36 +697,23 @@ rl_untranslate_keyseq (int seq)
kseq[i++] = '-';
c = UNMETA (c);
}
else 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)
{
kseq[i++] = '\\';
kseq[i++] = 'C';
kseq[i++] = '-';
c = '?';
}
if (c == ESC)
{
kseq[i++] = '\\';
c = 'e';
}
else if (c == '\\' || c == '"')
else if (CTRL_CHAR (c) || c == RUBOUT)
{
kseq[i++] = '\\';
kseq[i++] = 'C';
kseq[i++] = '-';
c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
}
if (c == '\\' || c == '"')
kseq[i++] = '\\';
kseq[i++] = (unsigned char) c;
kseq[i] = '\0';
return kseq;
@@ -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,
@@ -1167,9 +1155,7 @@ _rl_init_file_error (va_alist)
/* **************************************************************** */
static int
parse_comparison_op (s, indp)
const char *s;
int *indp;
parse_comparison_op (const char *s, int *indp)
{
int i, peekc, op;
@@ -1247,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. */
@@ -1672,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. */
@@ -1850,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)
@@ -1917,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 },
@@ -2595,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)
@@ -2615,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
@@ -2678,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;
@@ -2714,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)
{
@@ -2768,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;
@@ -2788,6 +2742,56 @@ rl_invoking_keyseqs (rl_command_func_t *function)
return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
}
void
rl_print_keybinding (const char *name, Keymap kmap, int print_readably)
{
rl_command_func_t *function;
char **invokers;
function = rl_named_function (name);
invokers = rl_invoking_keyseqs_in_map (function, kmap ? kmap : _rl_keymap);
if (print_readably)
{
if (!invokers)
fprintf (rl_outstream, "# %s (not bound)\n", name);
else
{
register int j;
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
{
register int j;
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");
if (j == 5 && invokers[j])
fprintf (rl_outstream, "...\n");
for (j = 0; invokers[j]; j++)
xfree (invokers[j]);
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. */
@@ -2803,58 +2807,7 @@ rl_function_dumper (int print_readably)
fprintf (rl_outstream, "\n");
for (i = 0; name = names[i]; i++)
{
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
{
register int j;
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
{
register int j;
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");
}
if (j == 5 && invokers[j])
fprintf (rl_outstream, "...\n");
for (j = 0; invokers[j]; j++)
xfree (invokers[j]);
xfree (invokers);
}
}
}
rl_print_keybinding (name, _rl_keymap, print_readably);
xfree (names);
}
@@ -2875,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++)
{
@@ -2887,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,
@@ -2950,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)
{
@@ -2970,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)
@@ -3014,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)
+18 -3
View File
@@ -1,6 +1,6 @@
/* callback.c -- functions to use readline as an X `callback' mechanism. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -115,7 +115,10 @@ rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc)
#define CALLBACK_READ_RETURN() \
do { \
if (rl_persistent_signal_handlers == 0) \
rl_clear_signals (); \
{ \
rl_clear_signals (); \
if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
} \
return; \
} while (0)
#else
@@ -320,6 +323,15 @@ rl_callback_handler_remove (void)
rl_linefunc = NULL;
RL_UNSETSTATE (RL_STATE_CALLBACK);
RL_CHECK_SIGNALS ();
/* Do what we need to do to manage the undo list if we haven't already done
it in rl_callback_read_char(). If there's no undo list, we don't need to
do anything. It doesn't matter if we try to revert all previous lines a
second time; none of the history entries will have an undo list. */
if (rl_undo_list)
readline_common_teardown ();
/* At this point, rl_undo_list == NULL. */
if (in_handler)
{
in_handler = 0;
@@ -360,7 +372,7 @@ rl_callback_sigcleanup (void)
if (RL_ISSTATE (RL_STATE_ISEARCH))
_rl_isearch_cleanup (_rl_iscxt, 0);
else if (RL_ISSTATE (RL_STATE_NSEARCH))
_rl_nsearch_cleanup (_rl_nscxt, 0);
_rl_nsearch_sigcleanup (_rl_nscxt, 0);
else if (RL_ISSTATE (RL_STATE_VIMOTION))
RL_UNSETSTATE (RL_STATE_VIMOTION);
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
@@ -370,6 +382,9 @@ rl_callback_sigcleanup (void)
}
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
RL_UNSETSTATE (RL_STATE_MULTIKEY);
else if (RL_ISSTATE (RL_STATE_READSTR))
_rl_readstr_sigcleanup (_rl_rscxt, 0);
if (RL_ISSTATE (RL_STATE_CHARSEARCH))
RL_UNSETSTATE (RL_STATE_CHARSEARCH);
+1 -1
View File
@@ -55,7 +55,7 @@
#define largest_char 255 /* Largest character value. */
#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
#define META_CHAR(c) ((unsigned char)(c) > meta_character_threshold && (unsigned char)(c) <= largest_char)
#define CTRL(c) ((c) & control_character_mask)
#define META(c) ((c) | meta_character_bit)
+1 -1
View File
@@ -2,7 +2,7 @@
Modified by Chet Ramey for Readline.
Copyright (C) 1985, 1988, 1990-1991, 1995-2021
Copyright (C) 1985, 1988, 1990-1991, 1995-2021, 2023
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
+179 -170
View File
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -77,11 +77,7 @@ extern int errno;
# include "colors.h"
#endif
#ifdef __STDC__
typedef int QSFUNC (const void *, const void *);
#else
typedef int QSFUNC ();
#endif
#ifdef HAVE_LSTAT
# define LSTAT lstat
@@ -250,11 +246,24 @@ rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
either return its first argument (if no conversion takes place) or
newly-allocated memory. This can, for instance, convert filenames
between character sets for comparison against what's typed at the
keyboard. The returned value is what is added to the list of
matches. The second argument is the length of the filename to be
converted. */
keyboard (after its potential modification by rl_completion_rewrite_hook).
The returned value is what is added to the list of matches.
The second argument is the length of the filename to be converted. */
rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_t *)NULL;
/* If non-zero, this is the address of a function to call before
comparing the filename portion of a word to be completed with directory
entries from the filesystem. This takes the address of the partial word
to be completed, after any rl_filename_dequoting_function has been applied.
The function should either return its first argument (if no conversion
takes place) or newly-allocated memory. This can, for instance, convert
the filename portion of the completion word to a character set suitable
for comparison against directory entries read from the filesystem (after
their potential modification by rl_filename_rewrite_hook).
The returned value is what is added to the list of matches.
The second argument is the length of the filename to be converted. */
rl_dequote_func_t *rl_completion_rewrite_hook = (rl_dequote_func_t *)NULL;
/* Non-zero means readline completion functions perform tilde expansion. */
int rl_complete_with_tilde_expansion = 0;
@@ -340,6 +349,15 @@ int rl_filename_completion_desired = 0;
entry finder function. */
int rl_filename_quoting_desired = 1;
/* Non-zero means we should apply filename-type quoting to all completions
even if we are not otherwise treating the matches as filenames. This is
ALWAYS zero on entry, and can only be changed within a completion entry
finder function. */
int rl_full_quoting_desired = 0;
#define QUOTING_DESIRED() \
(rl_full_quoting_desired || (rl_filename_completion_desired && rl_filename_quoting_desired))
/* This function, if defined, is called by the completer when real
filename completion is done, after all the matching names have been
generated. It is passed a (char**) known as matches in the code below.
@@ -455,6 +473,7 @@ rl_complete (int ignore, int invoking_key)
int
rl_possible_completions (int ignore, int invoking_key)
{
last_completion_failed = 0;
rl_completion_invoking_key = invoking_key;
return (rl_complete_internal ('?'));
}
@@ -484,6 +503,32 @@ rl_completion_mode (rl_command_func_t *cfunc)
return TAB;
}
/********************************************/
/* */
/* Completion signal handling and cleanup */
/* */
/********************************************/
/* State to clean up and free if completion is interrupted by a signal. */
typedef struct {
char **matches;
char *saved_line;
} complete_sigcleanarg_t;
static void
_rl_complete_sigcleanup (int sig, void *ptr)
{
complete_sigcleanarg_t *arg;
if (sig == SIGINT) /* XXX - for now */
{
arg = ptr;
_rl_free_match_list (arg->matches);
FREE (arg->saved_line);
_rl_complete_display_matches_interrupt = 1;
}
}
/************************************/
/* */
/* Completion utility functions */
@@ -498,16 +543,6 @@ _rl_reset_completion_state (void)
rl_completion_quote_character = 0;
}
static void
_rl_complete_sigcleanup (int sig, void *ptr)
{
if (sig == SIGINT) /* XXX - for now */
{
_rl_free_match_list ((char **)ptr);
_rl_complete_display_matches_interrupt = 1;
}
}
/* Set default values for readline word completion. These are the variables
that application completion functions can change or inspect. */
static void
@@ -516,6 +551,7 @@ set_completion_defaults (int what_to_do)
/* Only the completion entry function can change these. */
rl_filename_completion_desired = 0;
rl_filename_quoting_desired = 1;
rl_full_quoting_desired = 0;
rl_completion_type = what_to_do;
rl_completion_suppress_append = rl_completion_suppress_quote = 0;
rl_completion_append_character = ' ';
@@ -1319,6 +1355,7 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
int low; /* Count of max-matched characters. */
int lx;
char *dtext; /* dequoted TEXT, if needed */
size_t len1, len2;
#if defined (HANDLE_MULTIBYTE)
int v;
size_t v1, v2;
@@ -1345,6 +1382,9 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
memset (&ps2, 0, sizeof (mbstate_t));
}
#endif
len1 = strlen (match_list[i]);
len2 = strlen (match_list[i + 1]);
for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++)
{
if (_rl_completion_case_fold)
@@ -1355,8 +1395,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
v1 = MBRTOWC (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
v2 = MBRTOWC (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
v1 = MBRTOWC (&wc1, match_list[i]+si, len1 - si, &ps1);
v2 = MBRTOWC (&wc2, match_list[i+1]+si, len2 - si, &ps2);
if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
{
if (c1 != c2) /* do byte comparison */
@@ -1412,10 +1452,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
check against the list of matches
FI */
dtext = (char *)NULL;
if (rl_filename_completion_desired &&
rl_filename_dequoting_function &&
rl_completion_found_quote &&
rl_filename_quoting_desired)
if (QUOTING_DESIRED() && rl_completion_found_quote &&
rl_filename_dequoting_function)
{
dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
text = dtext;
@@ -1630,7 +1668,7 @@ rl_display_match_list (char **matches, int len, int max)
if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
{
lines = _rl_internal_pager (lines);
if (lines < 0)
if (lines < 0 || _rl_complete_display_matches_interrupt)
return;
}
}
@@ -1658,7 +1696,7 @@ rl_display_match_list (char **matches, int len, int max)
if (_rl_page_completions && lines >= _rl_screenheight - 1)
{
lines = _rl_internal_pager (lines);
if (lines < 0)
if (lines < 0 || _rl_complete_display_matches_interrupt)
return;
}
}
@@ -1745,7 +1783,9 @@ display_matches (char **matches)
}
}
rl_display_match_list (matches, len, max);
/* We rely on the caller to set MATCHES to 0 when this returns. */
if (_rl_complete_display_matches_interrupt == 0)
rl_display_match_list (matches, len, max);
rl_forced_update_display ();
rl_display_fixed = 1;
@@ -1768,9 +1808,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
matches don't require a quoted substring. */
replacement = match;
should_quote = match && rl_completer_quote_characters &&
rl_filename_completion_desired &&
rl_filename_quoting_desired;
should_quote = match && rl_completer_quote_characters && QUOTING_DESIRED();
if (should_quote)
should_quote = should_quote && (!qc || !*qc ||
@@ -1784,6 +1822,11 @@ make_quoted_replacement (char *match, int mtype, char *qc)
should_quote = rl_filename_quote_characters
? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
: 0;
/* If we saw a quote in the original word, but readline thinks the
match doesn't need to be quoted, and the application has a filename
quoting function, give the application a chance to quote it if
needed so we don't second-guess the user. */
should_quote |= *qc == 0 && rl_completion_found_quote && mtype != NO_MATCH && rl_filename_quoting_function;
do_replace = should_quote ? mtype : NO_MATCH;
/* Quote the replacement, since we found an embedded
@@ -1791,6 +1834,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
if (do_replace != NO_MATCH && rl_filename_quoting_function)
replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
}
return (replacement);
}
@@ -1976,8 +2020,7 @@ compare_match (char *text, const char *match)
char *temp;
int r;
if (rl_filename_completion_desired && rl_filename_quoting_desired &&
rl_completion_found_quote && rl_filename_dequoting_function)
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
{
temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
r = strcmp (temp, match);
@@ -2001,10 +2044,11 @@ rl_complete_internal (int what_to_do)
{
char **matches;
rl_compentry_func_t *our_func;
int start, end, delimiter, found_quote, i, nontrivial_lcd;
int start, end, delimiter, found_quote, i, nontrivial_lcd, do_display;
char *text, *saved_line_buffer;
char quote_char;
int tlen, mlen, saved_last_completion_failed;
complete_sigcleanarg_t cleanarg; /* state to clean up on signal */
RL_SETSTATE(RL_STATE_COMPLETING);
@@ -2031,9 +2075,24 @@ rl_complete_internal (int what_to_do)
text = rl_copy_text (start, end);
matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
/* If TEXT contains quote characters, it will be dequoted as part of
generating the matches, and the matches will not contain any quote
characters. We need to dequote TEXT before performing the comparison.
Since compare_match performs the dequoting, and we only want to do it
once, we don't call compare_matches after dequoting TEXT; we call
strcmp directly. */
/* nontrivial_lcd is set if the common prefix adds something to the word
being completed. */
nontrivial_lcd = matches && compare_match (text, matches[0]) != 0;
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
{
char *t;
t = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
xfree (text);
text = t;
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
}
else
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
if (what_to_do == '!' || what_to_do == '@')
tlen = strlen (text);
xfree (text);
@@ -2068,6 +2127,8 @@ rl_complete_internal (int what_to_do)
if (matches && matches[0] && *matches[0])
last_completion_failed = 0;
do_display = 0;
switch (what_to_do)
{
case TAB:
@@ -2101,13 +2162,13 @@ rl_complete_internal (int what_to_do)
{
if (what_to_do == '!')
{
display_matches (matches);
do_display = 1;
break;
}
else if (what_to_do == '@')
{
if (nontrivial_lcd == 0)
display_matches (matches);
do_display = 1;
break;
}
else if (rl_editing_mode != vi_mode)
@@ -2131,23 +2192,11 @@ rl_complete_internal (int what_to_do)
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
break;
}
if (rl_completion_display_matches_hook == 0)
{
_rl_sigcleanup = _rl_complete_sigcleanup;
_rl_sigcleanarg = matches;
_rl_complete_display_matches_interrupt = 0;
}
display_matches (matches);
if (_rl_complete_display_matches_interrupt)
{
matches = 0; /* already freed by rl_complete_sigcleanup */
_rl_complete_display_matches_interrupt = 0;
if (rl_signal_event_hook)
(*rl_signal_event_hook) (); /* XXX */
}
_rl_sigcleanup = 0;
_rl_sigcleanarg = 0;
/*FALLTHROUGH*/
case '%': /* used by menu_complete */
case '|': /* add this for unconditional display */
do_display = 1;
break;
default:
@@ -2160,6 +2209,34 @@ rl_complete_internal (int what_to_do)
return 1;
}
/* If we need to display the match list, set up to clean it up on receipt of
a signal and do it here. If the application has registered a function to
display the matches, let it do the work. */
if (do_display)
{
if (rl_completion_display_matches_hook == 0)
{
_rl_sigcleanup = _rl_complete_sigcleanup;
cleanarg.matches = matches;
cleanarg.saved_line = saved_line_buffer;
_rl_sigcleanarg = &cleanarg;
_rl_complete_display_matches_interrupt = 0;
}
display_matches (matches);
if (_rl_complete_display_matches_interrupt)
{
matches = 0; /* Both already freed by _rl_complete_sigcleanup */
saved_line_buffer = 0;
_rl_complete_display_matches_interrupt = 0;
if (rl_signal_event_hook)
(*rl_signal_event_hook) ();
}
_rl_sigcleanup = 0;
_rl_sigcleanarg = 0;
}
_rl_free_match_list (matches);
/* Check to see if the line has changed through all of this manipulation. */
@@ -2200,7 +2277,7 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
register int i;
/* Number of slots in match_list. */
int match_list_size;
size_t match_list_size;
/* The list of matches. */
char **match_list;
@@ -2265,9 +2342,9 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
char *
rl_username_completion_function (const char *text, int state)
{
#if defined (__WIN32__) || defined (__OPENNT)
#if defined (_WIN32) || defined (__OPENNT) || !defined (HAVE_GETPWENT)
return (char *)NULL;
#else /* !__WIN32__ && !__OPENNT) */
#else /* !_WIN32 && !__OPENNT) && HAVE_GETPWENT */
static char *username = (char *)NULL;
static struct passwd *entry;
static int namelen, first_char, first_char_loc;
@@ -2282,25 +2359,19 @@ rl_username_completion_function (const char *text, int state)
username = savestring (&text[first_char_loc]);
namelen = strlen (username);
#if defined (HAVE_GETPWENT)
setpwent ();
#endif
}
#if defined (HAVE_GETPWENT)
while (entry = getpwent ())
{
/* Null usernames should result in all users as possible completions. */
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
break;
}
#endif
if (entry == 0)
{
#if defined (HAVE_GETPWENT)
endpwent ();
#endif
return ((char *)NULL);
}
else
@@ -2316,7 +2387,7 @@ rl_username_completion_function (const char *text, int state)
return (value);
}
#endif /* !__WIN32__ && !__OPENNT */
#endif /* !_WIN32 && !__OPENNT && HAVE_GETPWENT */
}
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
@@ -2327,18 +2398,7 @@ rl_username_completion_function (const char *text, int state)
static int
complete_fncmp (const char *convfn, int convlen, const char *filename, int filename_len)
{
register char *s1, *s2;
int d, len;
#if defined (HANDLE_MULTIBYTE)
size_t v1, v2;
mbstate_t ps1, ps2;
WCHAR_T wc1, wc2;
#endif
#if defined (HANDLE_MULTIBYTE)
memset (&ps1, 0, sizeof (mbstate_t));
memset (&ps2, 0, sizeof (mbstate_t));
#endif
size_t len;
if (filename_len == 0)
return 1;
@@ -2346,100 +2406,26 @@ complete_fncmp (const char *convfn, int convlen, const char *filename, int filen
return 0;
len = filename_len;
s1 = (char *)convfn;
s2 = (char *)filename;
/* Otherwise, if these match up to the length of filename, then
it is a match. */
if (_rl_completion_case_fold && _rl_completion_case_map)
if (_rl_completion_case_fold)
{
/* Case-insensitive comparison treating _ and - as equivalent */
/* Case-insensitive comparison treating _ and - as equivalent if
_rl_completion_case_map is non-zero */
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
do
{
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
if (v1 == 0 && v2 == 0)
return 1;
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
{
if (*s1 != *s2) /* do byte comparison */
return 0;
else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
return 0;
s1++; s2++; len--;
continue;
}
wc1 = towlower (wc1);
wc2 = towlower (wc2);
s1 += v1;
s2 += v1;
len -= v1;
if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
continue;
if (wc1 != wc2)
return 0;
}
while (len != 0);
}
else
#endif
{
do
{
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
/* *s1 == [-_] && *s2 == [-_] */
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
d = 0;
if (d != 0)
return 0;
s1++; s2++; /* already checked convlen >= filename_len */
}
while (--len != 0);
}
return 1;
}
else if (_rl_completion_case_fold)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
do
{
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
if (v1 == 0 && v2 == 0)
return 1;
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
{
if (*s1 != *s2) /* do byte comparison */
return 0;
s1++; s2++; len--;
continue;
}
wc1 = towlower (wc1);
wc2 = towlower (wc2);
if (wc1 != wc2)
return 0;
s1 += v1;
s2 += v1;
len -= v1;
}
while (len != 0);
return 1;
}
return (_rl_mb_strcaseeqn (convfn, convlen, filename, filename_len, len, _rl_completion_case_map));
else
#endif
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
(convlen >= filename_len) &&
(_rl_strnicmp (filename, convfn, filename_len) == 0))
return 1;
(convlen >= filename_len))
return (_rl_strcaseeqn (convfn, filename, len, _rl_completion_case_map));
}
else
{
/* XXX - add new _rl_mb_streqn function (like mbsncmp) instead of
relying on byte equivalence? */
if ((convfn[0] == filename[0]) &&
(convlen >= filename_len) &&
(strncmp (filename, convfn, filename_len) == 0))
@@ -2461,7 +2447,8 @@ rl_filename_completion_function (const char *text, int state)
static char *users_dirname = (char *)NULL;
static int filename_len;
char *temp, *dentry, *convfn;
int dirlen, dentlen, convlen;
size_t dirlen;
int dentlen, convlen;
int tilde_dirname;
struct dirent *entry;
@@ -2526,7 +2513,8 @@ rl_filename_completion_function (const char *text, int state)
temp = tilde_expand (dirname);
xfree (dirname);
dirname = temp;
tilde_dirname = 1;
if (*dirname != '~')
tilde_dirname = 1; /* indicate successful tilde expansion */
}
/* We have saved the possibly-dequoted version of the directory name
@@ -2545,11 +2533,16 @@ rl_filename_completion_function (const char *text, int state)
xfree (users_dirname);
users_dirname = savestring (dirname);
}
else if (tilde_dirname == 0 && rl_completion_found_quote && rl_filename_dequoting_function)
else if (rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
/* We already ran users_dirname through the dequoting function.
If tilde_dirname == 1, we successfully performed tilde expansion
on dirname. Now we need to reconcile those results. We either
just copy the already-dequoted users_dirname or tilde expand it
if we tilde-expanded dirname. */
temp = tilde_dirname ? tilde_expand (users_dirname) : savestring (users_dirname);
xfree (dirname);
dirname = savestring (users_dirname);
dirname = temp;
}
directory = opendir (dirname);
@@ -2564,6 +2557,18 @@ rl_filename_completion_function (const char *text, int state)
}
filename_len = strlen (filename);
/* Normalize the filename if the application has set a rewrite hook. */
if (*filename && rl_completion_rewrite_hook)
{
temp = (*rl_completion_rewrite_hook) (filename, filename_len);
if (temp != filename)
{
xfree (filename);
filename = temp;
filename_len = strlen (filename);
}
}
rl_filename_completion_desired = 1;
}
@@ -2576,6 +2581,7 @@ rl_filename_completion_function (const char *text, int state)
/* Now that we have some state, we can read the directory. */
entry = (struct dirent *)NULL;
convfn = dentry = 0;
while (directory && (entry = readdir (directory)))
{
convfn = dentry = entry->d_name;
@@ -2593,17 +2599,20 @@ rl_filename_completion_function (const char *text, int state)
if (filename_len == 0)
{
if (_rl_match_hidden_files == 0 && HIDDEN_FILE (convfn))
continue;
{
if (convfn != dentry)
xfree (convfn);
continue;
}
if (convfn[0] != '.' ||
(convfn[1] && (convfn[1] != '.' || convfn[2])))
break;
}
else
{
if (complete_fncmp (convfn, convlen, filename, filename_len))
break;
}
else if (complete_fncmp (convfn, convlen, filename, filename_len))
break;
else if (convfn != dentry)
xfree (convfn);
}
if (entry == 0)
@@ -2825,7 +2834,7 @@ rl_menu_complete (int count, int ignore)
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
static int orig_start, orig_end;
static char quote_char;
static int delimiter, cstate;
static int delimiter;
/* The first time through, we generate the list of matches and set things
up to insert them. */
@@ -2921,7 +2930,7 @@ rl_menu_complete (int count, int ignore)
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
{
rl_ding ();
FREE (matches);
_rl_free_match_list (matches);
matches = (char **)0;
full_completion = 1;
return (0);
+202 -115
View File
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
/* 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.
@@ -59,10 +59,6 @@
#include "rlprivate.h"
#include "xmalloc.h"
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
#endif /* !strchr && !__STDC__ */
static void putc_face (int, int, char *);
static void puts_face (const char *, const char *, int);
static void norm_face (char *, int);
@@ -282,6 +278,10 @@ static int prompt_physical_chars;
characters in the prompt or use heuristics about where they are. */
static int *local_prompt_newlines;
/* An array saying how many invisible characters are in each line of the
prompt. */
static int *local_prompt_invis_chars;
/* set to a non-zero value by rl_redisplay if we are marking modified history
lines and the current line is so marked. */
static int modmark;
@@ -295,6 +295,7 @@ static int line_totbytes;
static char *saved_local_prompt;
static char *saved_local_prefix;
static int *saved_local_prompt_newlines;
static int *saved_local_prompt_invis_chars;
static int saved_last_invisible;
static int saved_visible_length;
@@ -356,7 +357,7 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
{
char *r, *ret, *p, *igstart, *nprompt, *ms;
int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
int mlen, newlines, newlines_guess, bound, can_add_invis;
int mlen, newlines, newlines_guess, bound, can_add_invis, lastinvis;
int mb_cur_max;
/* We only expand the mode string for the last line of a multiline prompt
@@ -399,7 +400,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
*vlp = l;
local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
local_prompt_newlines[0] = 0;
local_prompt_invis_chars = (int *) xrealloc (local_prompt_invis_chars, sizeof (int) * 2);
local_prompt_newlines[0] = local_prompt_invis_chars[0] = 0;
local_prompt_newlines[1] = -1;
return r;
@@ -414,15 +416,20 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l, _rl_screenwidth) : APPROX_DIV(l, 80);
local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
local_prompt_newlines[newlines = 0] = 0;
local_prompt_invis_chars = (int *) xrealloc (local_prompt_invis_chars, sizeof (int) * (newlines_guess + 1));
local_prompt_invis_chars[0] = 0;
for (rl = 1; rl <= newlines_guess; rl++)
local_prompt_newlines[rl] = -1;
{
local_prompt_newlines[rl] = -1;
local_prompt_invis_chars[rl] = 0;
}
rl = physchars = 0; /* mode string now part of nprompt */
invfl = 0; /* invisible chars in first line of prompt */
invflset = 0; /* we only want to set invfl once */
igstart = 0; /* we're not ignoring any characters yet */
for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
for (ignoring = last = ninvis = lastinvis = 0, p = nprompt; p && *p; p++)
{
/* This code strips the invisible character string markers
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
@@ -447,6 +454,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
counter. */
if (invflset && newlines == 1)
invfl = ninvis;
local_prompt_invis_chars[newlines - 1] = ninvis - lastinvis;
lastinvis = ninvis;
}
if (p != (igstart + 1))
last = r - ret - 1;
@@ -511,6 +520,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
else
new = r - ret;
local_prompt_newlines[++newlines] = new;
local_prompt_invis_chars[newlines - 1] = ninvis - lastinvis;
lastinvis = ninvis;
}
/* What if a physical character of width >= 2 is split? There is
@@ -525,6 +536,9 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
if (rl <= _rl_screenwidth)
invfl = ninvis;
/* Make sure we account for invisible characters on the last line. */
local_prompt_invis_chars[newlines] = ninvis - lastinvis;
*r = '\0';
if (lp)
*lp = rl;
@@ -591,13 +605,22 @@ rl_expand_prompt (char *prompt)
FREE (local_prompt);
FREE (local_prompt_prefix);
/* Set default values for variables expand_prompt sets */
local_prompt = local_prompt_prefix = (char *)0;
local_prompt_len = 0;
prompt_last_invisible = prompt_invis_chars_first_line = 0;
prompt_visible_length = prompt_physical_chars = 0;
if (local_prompt_invis_chars == 0)
local_prompt_invis_chars = (int *)xmalloc (sizeof (int));
local_prompt_invis_chars[0] = 0;
if (prompt == 0 || *prompt == 0)
return (0);
{
local_prompt = xmalloc (sizeof (char));
local_prompt[0] = '\0';
return (0);
}
p = strrchr (prompt, '\n');
if (p == 0)
@@ -641,8 +664,8 @@ rl_expand_prompt (char *prompt)
static void
realloc_line (int minsize)
{
int minimum_size;
int newsize, delta;
size_t minimum_size;
size_t newsize, delta;
minimum_size = DEFAULT_LINE_BUFFER_SIZE;
if (minsize < minimum_size)
@@ -684,7 +707,7 @@ init_line_structures (int minsize)
if (line_size > minsize)
minsize = line_size;
}
realloc_line (minsize);
realloc_line (minsize);
if (vis_lbreaks == 0)
{
@@ -758,16 +781,39 @@ _rl_optimize_redisplay (void)
_rl_quick_redisplay = 1;
}
/* Useful shorthand used by rl_redisplay, update_line, rl_move_cursor_relative */
#define INVIS_FIRST() (local_prompt_invis_chars[0])
#define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line) ? local_prompt_invis_chars[line] : 0)
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
#define VIS_FACE(line) (vis_face + vis_lbreaks[line])
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
#define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
#define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
#define INV_CHARS_CURRENT_PROMPT_LINE(line) \
(local_prompt_invis_chars[line] > 0)
#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
_rl_last_c_pos != o_cpos && \
_rl_last_c_pos > wrap_offset && \
o_cpos < prompt_last_invisible)
/* Basic redisplay algorithm. See comments inline. */
void
rl_redisplay (void)
{
int in, out, c, linenum, cursor_linenum;
int inv_botlin, lb_botlin, lb_linenum, o_cpos;
int newlines, lpos, temp, n0, num, prompt_lines_estimate;
int newlines, lpos, temp, num, prompt_lines_estimate;
char *prompt_this_line;
char cur_face;
int hl_begin, hl_end;
int short_circuit;
int mb_cur_max = MB_CUR_MAX;
#if defined (HANDLE_MULTIBYTE)
WCHAR_T wc;
@@ -953,7 +999,7 @@ rl_redisplay (void)
the line breaks in the prompt string in expand_prompt, taking invisible
characters into account, and if lpos exceeds the screen width, we copy
the data in the loop below. */
lpos = prompt_physical_chars + modmark;
lpos = local_prompt ? prompt_physical_chars + modmark : 0;
#if defined (HANDLE_MULTIBYTE)
memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
@@ -964,6 +1010,9 @@ rl_redisplay (void)
in the first physical line of the prompt.
wrap_offset - prompt_invis_chars_first_line is usually the number of
invis chars on the second (or, more generally, last) line. */
/* XXX - There is code that assumes that all the invisible characters occur
on the first and last prompt lines; change that to use
local_prompt_invis_chars */
/* This is zero-based, used to set the newlines */
prompt_lines_estimate = lpos / _rl_screenwidth;
@@ -982,6 +1031,7 @@ rl_redisplay (void)
}
/* Now set lpos from the last newline */
/* XXX - change to use local_prompt_invis_chars[] */
if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
else
@@ -1044,6 +1094,8 @@ rl_redisplay (void)
wc_width = (temp >= 0) ? temp : 1;
}
}
else
wc_width = 1; /* make sure it's set for the META_CHAR check */
#endif
if (in == rl_point)
@@ -1053,31 +1105,32 @@ rl_redisplay (void)
}
#if defined (HANDLE_MULTIBYTE)
if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
if (META_CHAR (c) && wc_bytes == 1 && wc_width == 1)
#else
if (META_CHAR (c))
#endif
{
#if 0
/* TAG: readline-8.3 20230227 */
/* https://savannah.gnu.org/support/index.php?110830
asking for non-printing meta characters to be printed using an
escape sequence. */
/* isprint(c) handles bytes up to UCHAR_MAX */
if (_rl_output_meta_chars == 0 || isprint (c) == 0)
#else
if (_rl_output_meta_chars == 0)
#endif
{
char obuf[5];
int olen;
#if defined (HAVE_VSNPRINTF)
olen = snprintf (obuf, sizeof (obuf), "\\%o", c);
#else
olen = sprintf (obuf, "\\%o", c);
if (lpos + olen >= _rl_screenwidth)
{
temp = _rl_screenwidth - lpos;
CHECK_INV_LBREAKS ();
inv_lbreaks[++newlines] = out + temp;
#if defined (HANDLE_MULTIBYTE)
line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
#endif
lpos = olen - temp;
}
else
lpos += olen;
for (temp = 0; temp < olen; temp++)
{
invis_addc (&out, obuf[temp], cur_face);
@@ -1249,26 +1302,6 @@ rl_redisplay (void)
second and subsequent lines start at inv_lbreaks[N], offset by
OFFSET (which has already been calculated above). */
#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
#define WRAP_OFFSET(line, offset) ((line == 0) \
? (offset ? INVIS_FIRST() : 0) \
: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
#define VIS_FACE(line) (vis_face + vis_lbreaks[line])
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
#define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
#define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
_rl_last_c_pos != o_cpos && \
_rl_last_c_pos > wrap_offset && \
o_cpos < prompt_last_invisible)
/* We don't want to highlight anything that's going to be off the top
of the display; if the current line takes up more than an entire
screen, just mark the lines that won't be displayed as having a
@@ -1283,9 +1316,54 @@ rl_redisplay (void)
norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
}
/* XXX - experimental new code */
/* Now that _rl_last_v_pos is a logical count, not bounded by the
number of physical screen lines, this is a start at being able
to redisplay lines that consume more than the number of physical
screen lines in more than a simple `move-to-the-next-line' way.
If the new line has more lines than there are physical screen
lines, and the cursor would be off the top of the screen if we
displayed all the new lines, clear the screen without killing
the scrollback buffer, clear out the visible line so we do a
complete redraw, and make the loop break when we have displayed
a physical screen full of lines. Do the same if we are going to
move the cursor to a line that's greater than the number of
physical screen lines when we weren't before.
SHORT_CIRCUIT says where to break the loop. Pretty simple right now. */
short_circuit = -1;
if (inv_botlin >= _rl_screenheight)
{
int extra;
extra = inv_botlin - _rl_screenheight; /* lines off the top */
/* cursor in portion of line that would be off screen or in
the lines that exceed the number of physical screen lines. */
if (cursor_linenum <= extra ||
(cursor_linenum >= _rl_screenheight && _rl_vis_botlin <= _rl_screenheight))
{
if (cursor_linenum <= extra)
short_circuit = _rl_screenheight;
_rl_clear_screen (0);
if (visible_line)
memset (visible_line, 0, line_size);
rl_on_new_line ();
}
/* The cursor is beyond the number of lines that would be off
the top, but we still want to display only the first
_RL_SCREENHEIGHT lines starting at the beginning of the line. */
else if (cursor_linenum > extra && cursor_linenum <= _rl_screenheight &&
_rl_vis_botlin <= _rl_screenheight)
short_circuit = _rl_screenheight;
}
/* For each line in the buffer, do the updating display. */
for (linenum = 0; linenum <= inv_botlin; linenum++)
{
if (short_circuit >= 0 && linenum == short_circuit)
break;
/* This can lead us astray if we execute a program that changes
the locale from a non-multibyte to a multibyte one. */
o_cpos = _rl_last_c_pos;
@@ -1319,6 +1397,7 @@ rl_redisplay (void)
between the first and last lines of the prompt, if the
prompt consumes more than two lines. It's usually right */
/* XXX - not sure this is ever executed */
/* XXX - use local_prompt_invis_chars[linenum] */
_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
/* If this is the line with the prompt, we might need to
@@ -1388,7 +1467,7 @@ rl_redisplay (void)
((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
}
}
_rl_vis_botlin = inv_botlin;
_rl_vis_botlin = (short_circuit >= 0) ? short_circuit : inv_botlin;
/* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
different screen line during this redisplay. */
@@ -1413,6 +1492,7 @@ rl_redisplay (void)
only need to reprint it if the cursor is before the last
invisible character in the prompt string. */
/* XXX - why not use local_prompt_len? */
/* XXX - This is right only if the prompt is a single line. */
nleft = prompt_visible_length + wrap_offset;
if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
_rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
@@ -1895,6 +1975,8 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
/* See comments at dumb_update: for an explanation of this heuristic */
if (nmax < omax)
goto clear_rest_of_line;
/* XXX - need to use WRAP_OFFSET(current_line, wrap_offset) instead of
W_OFFSET - XXX */
else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
goto clear_rest_of_line;
else
@@ -1981,7 +2063,11 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
assume it's a combining character and back one up so the two base
characters no longer compare equivalently. */
t = MBRTOWC (&wc, ofd, mb_cur_max, &ps);
#if 0
if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
#else
if (t > 0 && IS_COMBINING_CHAR (wc))
#endif
{
old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
@@ -1998,6 +2084,8 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
#if defined (HANDLE_MULTIBYTE)
/* Find the last character that is the same between the two lines. This
bounds the region that needs to change. */
/* In this case, `last character' means the one farthest from the end of
the line. */
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
@@ -2014,7 +2102,7 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
*olsf != *nlsf)
break;
if (*ols == ' ')
if (*ols != ' ')
wsatend = 0;
ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
@@ -2076,14 +2164,30 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
}
/* count of invisible characters in the current invisible line. */
current_invis_chars = W_OFFSET (current_line, wrap_offset);
current_invis_chars = WRAP_OFFSET (current_line, wrap_offset);
if (_rl_last_v_pos != current_line)
{
_rl_move_vert (current_line);
/* We have moved up to a new screen line. This line may or may not have
invisible characters on it, but we do our best to recalculate
visible_wrap_offset based on what we know. */
if (current_line == 0)
/* This first clause handles the case where the prompt has been
recalculated (e.g., by rl_message) but the old prompt is still on
the visible line because we haven't overwritten it yet. We want
to somehow use the old prompt information, but we only want to do
this once. */
if (current_line == 0 && saved_local_prompt && old[0] == saved_local_prompt[0] && memcmp (old, saved_local_prompt, saved_local_length) == 0)
visible_wrap_offset = saved_invis_chars_first_line;
/* This clause handles the opposite: the prompt has been restored (e.g.,
by rl_clear_message) but the old saved_local_prompt (now NULL, so we
can't directly check it) is still on the visible line because we
haven't overwritten it yet. We guess that there aren't any invisible
characters in any of the prompts we put in with rl_message */
else if (current_line == 0 && local_prompt && new[0] == local_prompt[0] &&
(memcmp (new, local_prompt, local_prompt_len) == 0) &&
(memcmp (old, local_prompt, local_prompt_len) != 0))
visible_wrap_offset = 0;
else if (current_line == 0)
visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
#if 0 /* XXX - not yet */
else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
@@ -2140,6 +2244,7 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
else
/* We take wrap_offset into account here so we can pass correct
information to _rl_move_cursor_relative. */
/* XXX - can use local_prompt_invis_chars[0] instead of wrap_offset */
_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
cpos_adjusted = 1;
}
@@ -2183,6 +2288,7 @@ dumb_update:
wrap_offset-prompt_invis_chars_first_line
on the assumption that this is the number of invisible
characters in the last line of the prompt. */
/* XXX - CHANGE THIS USING local_prompt_invis_chars[current_line] */
if (wrap_offset > prompt_invis_chars_first_line &&
current_line == prompt_last_screen_line &&
prompt_physical_chars > _rl_screenwidth &&
@@ -2201,6 +2307,20 @@ dumb_update:
wrap_offset >= prompt_invis_chars_first_line &&
_rl_horizontal_scroll_mode == 0)
ADJUST_CPOS (prompt_invis_chars_first_line);
/* XXX - This is experimental. It's a start at supporting
prompts where a non-terminal line contains the last
invisible characters. We assume that we can use the
local_prompt_invis_chars array and that the current line
is completely filled with characters to _rl_screenwidth,
so we can either adjust by the number of bytes in the
current line or just go straight to _rl_screenwidth */
else if (current_line > 0 && current_line < prompt_last_screen_line &&
INV_CHARS_CURRENT_PROMPT_LINE(current_line) &&
_rl_horizontal_scroll_mode == 0)
{
_rl_last_c_pos = _rl_screenwidth;
cpos_adjusted = 1;
}
}
else
_rl_last_c_pos += temp;
@@ -2212,6 +2332,8 @@ dumb_update:
know for sure, so we use another heuristic calclulation below. */
if (nmax < omax)
goto clear_rest_of_line; /* XXX */
/* XXX - use WRAP_OFFSET(current_line, wrap_offset) here instead of
W_OFFSET since current_line == 0 */
else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
goto clear_rest_of_line;
else
@@ -2680,8 +2802,6 @@ rl_on_new_line_with_prompt (void)
int
rl_forced_update_display (void)
{
register char *temp;
if (visible_line)
memset (visible_line, 0, line_size);
@@ -2763,7 +2883,7 @@ _rl_move_cursor_relative (int new, const char *data, const char *dataf)
(prompt_last_invisible) in the last line. IN_INVISLINE is the
offset of DATA in invisible_line */
in_invisline = 0;
if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
if (data > invisible_line && _rl_inv_botlin < inv_lbsize && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
in_invisline = data - invisible_line;
/* Use NEW when comparing against the last invisible character in the
@@ -2866,9 +2986,25 @@ _rl_move_vert (int to)
{
register int delta, i;
if (_rl_last_v_pos == to || to > _rl_screenheight)
if (_rl_last_v_pos == to)
return;
#if 0
/* If we're being asked to move to a line beyond the screen height, and
we're currently at the last physical line, issue a newline and let the
terminal take care of scrolling the display. */
if (to >= _rl_screenheight)
{
if (_rl_last_v_pos == _rl_screenheight)
{
putc ('\n', rl_outstream);
_rl_cr ();
_rl_last_c_pos = 0;
}
return;
}
#endif
if ((delta = to - _rl_last_v_pos) > 0)
{
for (i = 0; i < delta; i++)
@@ -2952,29 +3088,15 @@ rl_character_len (int c, int pos)
mini-modeline. */
static int msg_saved_prompt = 0;
#if defined (USE_VARARGS)
int
#if defined (PREFER_STDARG)
rl_message (const char *format, ...)
#else
rl_message (va_alist)
va_dcl
#endif
{
va_list args;
#if defined (PREFER_VARARGS)
char *format;
#endif
#if defined (HAVE_VSNPRINTF)
int bneed;
#endif
#if defined (PREFER_STDARG)
va_start (args, format);
#else
va_start (args);
format = va_arg (args, char *);
#endif
if (msg_buf == 0)
msg_buf = xmalloc (msg_bufsiz = 128);
@@ -2987,12 +3109,7 @@ rl_message (va_alist)
msg_buf = xrealloc (msg_buf, msg_bufsiz);
va_end (args);
#if defined (PREFER_STDARG)
va_start (args, format);
#else
va_start (args);
format = va_arg (args, char *);
#endif
vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
}
#else
@@ -3023,40 +3140,6 @@ rl_message (va_alist)
return 0;
}
#else /* !USE_VARARGS */
int
rl_message (format, arg1, arg2)
char *format;
{
if (msg_buf == 0)
msg_buf = xmalloc (msg_bufsiz = 128);
sprintf (msg_buf, format, arg1, arg2);
msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
rl_display_prompt = msg_buf;
if (saved_local_prompt == 0)
{
rl_save_prompt ();
msg_saved_prompt = 1;
}
else if (local_prompt != saved_local_prompt)
{
FREE (local_prompt);
FREE (local_prompt_prefix);
local_prompt = (char *)NULL;
}
local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
&prompt_last_invisible,
&prompt_invis_chars_first_line,
&prompt_physical_chars);
local_prompt_prefix = (char *)NULL;
local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
(*rl_redisplay_function) ();
return 0;
}
#endif /* !USE_VARARGS */
/* How to clear things from the "echo-area". */
int
@@ -3098,10 +3181,12 @@ rl_save_prompt (void)
saved_invis_chars_first_line = prompt_invis_chars_first_line;
saved_physical_chars = prompt_physical_chars;
saved_local_prompt_newlines = local_prompt_newlines;
saved_local_prompt_invis_chars = local_prompt_invis_chars;
local_prompt = local_prompt_prefix = (char *)0;
local_prompt_len = 0;
local_prompt_newlines = (int *)0;
local_prompt_invis_chars = (int *)0;
prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
prompt_invis_chars_first_line = prompt_physical_chars = 0;
@@ -3113,11 +3198,13 @@ rl_restore_prompt (void)
FREE (local_prompt);
FREE (local_prompt_prefix);
FREE (local_prompt_newlines);
FREE (local_prompt_invis_chars);
local_prompt = saved_local_prompt;
local_prompt_prefix = saved_local_prefix;
local_prompt_len = saved_local_length;
local_prompt_newlines = saved_local_prompt_newlines;
local_prompt_invis_chars = saved_local_prompt_invis_chars;
prompt_prefix_length = saved_prefix_length;
prompt_last_invisible = saved_last_invisible;
@@ -3130,7 +3217,7 @@ rl_restore_prompt (void)
saved_local_length = 0;
saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
saved_invis_chars_first_line = saved_physical_chars = 0;
saved_local_prompt_newlines = 0;
saved_local_prompt_newlines = saved_local_prompt_invis_chars = 0;
}
char *
@@ -3318,7 +3405,7 @@ _rl_update_final (void)
full_lines = 1;
}
_rl_move_vert (_rl_vis_botlin);
woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
woff = W_OFFSET(_rl_vis_botlin, wrap_offset); /* XXX - WRAP_OFFSET? */
botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
/* If we've wrapped lines, remove the final xterm line-wrap flag. */
if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
@@ -3327,7 +3414,7 @@ _rl_update_final (void)
/* LAST_LINE includes invisible characters, so if you want to get the
last character of the first line, you have to take WOFF into account.
This needs to be done for both calls to _rl_move_cursor_relative,
This needs to be done both for calls to _rl_move_cursor_relative,
which takes a buffer position as the first argument, and any direct
subscripts of LAST_LINE. */
last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
@@ -3338,9 +3425,9 @@ _rl_update_final (void)
puts_face (&last_line[_rl_screenwidth - 1 + woff],
&last_face[_rl_screenwidth - 1 + woff], 1);
}
_rl_vis_botlin = 0;
if (botline_length > 0 || _rl_last_c_pos > 0)
if ((_rl_vis_botlin == 0 && botline_length == 0) || botline_length > 0 || _rl_last_c_pos > 0)
rl_crlf ();
_rl_vis_botlin = 0;
fflush (rl_outstream);
rl_display_fixed++;
}
+1 -1
View File
@@ -12,7 +12,7 @@ This document describes the GNU History library
a programming tool that provides a consistent user interface for
recalling lines of previously typed input.
Copyright @copyright{} 1988--2022 Free Software Foundation, Inc.
Copyright @copyright{} 1988--2023 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
+4 -5
View File
@@ -1,7 +1,7 @@
@ignore
This file documents the user interface to the GNU History library.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2023 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@@ -369,7 +369,7 @@ Returns 0 on success, or @code{errno} on failure.
These functions implement history expansion.
@deftypefun int history_expand (char *string, char **output)
@deftypefun int history_expand (const char *string, char **output)
Expand @var{string}, placing the result into @var{output}, a pointer
to a string (@pxref{History Interaction}). Returns:
@table @code
@@ -517,9 +517,8 @@ The following program demonstrates simple use of the @sc{gnu} History Library.
#include <stdio.h>
#include <readline/history.h>
main (argc, argv)
int argc;
char **argv;
int
main (int argc, char **argv)
@{
char line[1024], *t;
int len, done = 0;
+37 -12
View File
@@ -90,8 +90,8 @@ named by @env{$HISTFILE}.
If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
the lines are appended to the history file,
otherwise the history file is overwritten.
If @env{HISTFILE}
is unset, or if the history file is unwritable, the history is not saved.
If @env{HISTFILE} is unset or null,
or if the history file is unwritable, the history is not saved.
After saving the history, the history file is truncated
to contain no more than @env{$HISTFILESIZE} lines.
If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value, or
@@ -104,7 +104,7 @@ When the history file is read, lines beginning with the history
comment character followed immediately by a digit are interpreted
as timestamps for the following history entry.
The builtin command @code{fc} may be used to list or edit and re-execute
The @code{fc} builtin command may be used to list or edit and re-execute
a portion of the history list.
The @code{history} builtin may be used to display or modify the history
list and manipulate the history file.
@@ -113,8 +113,9 @@ are available in each editing mode that provide access to the
history list (@pxref{Commands For History}).
The shell allows control over which commands are saved on the history
list. The @env{HISTCONTROL} and @env{HISTIGNORE}
variables may be set to cause the shell to save only a subset of the
list.
The @env{HISTCONTROL} and @env{HISTIGNORE}
variables are used to cause the shell to save only a subset of the
commands entered.
The @code{cmdhist}
shell option, if enabled, causes the shell to attempt to save each
@@ -192,7 +193,7 @@ With no options, display the history list with line numbers.
Lines prefixed with a @samp{*} have been modified.
An argument of @var{n} lists only the last @var{n} lines.
If the shell variable @env{HISTTIMEFORMAT} is set and not null,
it is used as a format string for @var{strftime} to display
it is used as a format string for @code{strftime}(3) to display
the time stamp associated with each displayed history entry.
No intervening blank is printed between the formatted time stamp
and the history line.
@@ -250,6 +251,7 @@ If a @var{filename} argument is supplied
when any of the @option{-w}, @option{-r}, @option{-a}, or @option{-n} options
is used, Bash uses @var{filename} as the history file.
If not, then the value of the @env{HISTFILE} variable is used.
If @env{HISTFILE} is unset or null, these options have no effect.
The return value is 0 unless an invalid option is encountered, an
error occurs while reading or writing the history file, an invalid
@@ -282,14 +284,21 @@ expansion functions about quoting still in effect from previous lines.
History expansion takes place in two parts. The first is to determine
which line from the history list should be used during substitution.
The second is to select portions of that line for inclusion into the
current one. The line selected from the history is called the
@dfn{event}, and the portions of that line that are acted upon are
called @dfn{words}. Various @dfn{modifiers} are available to manipulate
the selected words. The line is broken into words in the same fashion
current one.
The line selected from the history is called the @dfn{event},
and the portions of that line that are acted upon are called @dfn{words}.
The line is broken into words in the same fashion
that Bash does, so that several words
surrounded by quotes are considered one word.
The @dfn{event designator} selects the event, the optional
@dfn{word designator} selects words from the event, and
various optional @dfn{modifiers} are available to manipulate the
selected words.
History expansions are introduced by the appearance of the
history expansion character, which is @samp{!} by default.
History expansions may appear anywhere in the input, but do not nest.
History expansion implements shell-like quoting conventions:
a backslash can be used to remove the special handling for the next character;
@@ -307,6 +316,16 @@ also treated as quoted if it immediately precedes the closing double quote
in a double-quoted string.
@end ifset
There is a special abbreviation for substitution, active when the
@var{quick substitution} character (default @samp{^})
is the first character on the line.
It selects the previous history list entry, using an event designator
equivalent to @code{!!},
and substitutes one string for another in that line.
It is described below (@pxref{Event Designators}).
This is the only history expansion that does not begin with the history
expansion character.
@ifset BashFeatures
Several shell options settable with the @code{shopt}
builtin (@pxref{The Shopt Builtin}) may be used to tailor
@@ -347,6 +366,9 @@ An event designator is a reference to a command line entry in the
history list.
Unless the reference is absolute, events are relative to the current
position in the history list.
The event designator consists of the portion of the word beginning
with the history expansion character, and ending with the word designator
if one is present, or the end of the word.
@cindex history events
@table @asis
@@ -354,8 +376,9 @@ position in the history list.
@item @code{!}
@ifset BashFeatures
Start a history substitution, except when followed by a space, tab,
the end of the line, @samp{=} or @samp{(} (when the
@code{extglob} shell option is enabled using the @code{shopt} builtin).
the end of the line, @samp{=},
or the rest of the shell metacharacters defined above
(@pxref{Definitions}).
@end ifset
@ifclear BashFeatures
Start a history substitution, except when followed by a space, tab,
@@ -400,6 +423,8 @@ The entire command line typed so far.
@subsection Word Designators
Word designators are used to select desired words from the event.
They are optional; if the word designator isn't supplied, the history
expansion uses the entire event.
A @samp{:} separates the event specification from the word designator. It
may be omitted if the word designator begins with a @samp{^}, @samp{$},
@samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning
+104 -52
View File
@@ -7,7 +7,7 @@ This document describes the GNU Readline Library, a utility for aiding
in the consistency of user interface across discrete programs that need
to provide a command line interface.
Copyright (C) 1988--2022 Free Software Foundation, Inc.
Copyright (C) 1988--2023 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -67,6 +67,9 @@ the simplest way possible, perhaps to replace calls in your code to
The function @code{readline()} prints a prompt @var{prompt}
and then reads and returns a single line of text from the user.
Since it's possible to enter characters into the line while quoting
them to disable any Readline editing function they might normally have,
this line may include embedded newlines and other special characters.
If @var{prompt} is @code{NULL} or the empty string, no prompt is displayed.
The line @code{readline} returns is allocated with @code{malloc()};
the caller should @code{free()} the line when it has finished with it.
@@ -476,6 +479,8 @@ The default hook checks @code{rl_instream}; if an application is using a
different input source, it should set the hook appropriately.
Readline queries for available input when implementing intra-key-sequence
timeouts during input and incremental searches.
This function must return zero if there is no input available, and non-zero
if input is available.
This may use an application-specific timeout before returning a value;
Readline uses the value passed to @code{rl_set_keyboard_input_timeout()}
or the value of the user-settable @var{keyseq-timeout} variable.
@@ -513,6 +518,15 @@ By default, this is set to @code{rl_deprep_terminal}
(@pxref{Terminal Management}).
@end deftypevar
@deftypevar {void} rl_macro_display_hook
If set, this points to a function that @code{rl_macro_dumper} will call to
display a key sequence bound to a macro.
It is called with the key sequence, the "untranslated" macro value (i.e.,
with backslash escapes included, as when passed to @code{rl_macro_bind}),
the @code{readable} argument passed to @code{rl_macro_dumper}, and any
prefix to display before the key sequence.
@end deftypevar
@deftypevar {Keymap} rl_executing_keymap
This variable is set to the keymap (@pxref{Keymaps}) in which the
currently executing Readline function was found.
@@ -915,9 +929,19 @@ Return an array of strings representing the key sequences used to
invoke @var{function} in the keymap @var{map}.
@end deftypefun
@deftypefun void rl_print_keybinding (const char *name, Keymap map, int readable)
Print key sequences bound to Readline function name @var{name} in
keymap @var{map}.
If @var{map} is NULL, this uses the current keymap.
If @var{readable} is non-zero,
the list is formatted in such a way that it can be made part of an
@code{inputrc} file and re-read.
@end deftypefun
@deftypefun void rl_function_dumper (int readable)
Print the Readline function names and the key sequences currently
bound to them to @code{rl_outstream}. If @var{readable} is non-zero,
bound to them to @code{rl_outstream}.
If @var{readable} is non-zero,
the list is formatted in such a way that it can be made part of an
@code{inputrc} file and re-read.
@end deftypefun
@@ -1346,13 +1370,15 @@ If @var{c} is a number, return the value it represents.
Bind the key sequence @var{keyseq} to invoke the macro @var{macro}.
The binding is performed in @var{map}. When @var{keyseq} is invoked, the
@var{macro} will be inserted into the line. This function is deprecated;
use @code{rl_generic_bind()} instead.
use @code{rl_generic_bind} instead.
@end deftypefun
@deftypefun void rl_macro_dumper (int readable)
Print the key sequences bound to macros and their values, using
the current keymap, to @code{rl_outstream}.
If @var{readable} is non-zero, the list is formatted in such a way
If the application has assigned a value to @code{rl_macro_display_hook},
@code{rl_macro_dumper} calls it instead of printing anything.
If @var{readable} is greater than zero, the list is formatted in such a way
that it can be made part of an @code{inputrc} file and re-read.
@end deftypefun
@@ -1389,6 +1415,10 @@ use all of a terminal's capabilities, and this function will return
values for only those capabilities Readline uses.
@end deftypefun
@deftypefun {void} rl_reparse_colors (void)
Read or re-read color definitions from @env{LS_COLORS}.
@end deftypefun
@deftypefun {void} rl_clear_history (void)
Clear the history list by deleting all of the entries, in the same manner
as the History library's @code{clear_history()} function.
@@ -2138,7 +2168,9 @@ The function should not modify the directory argument if it returns 0.
@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
If non-zero, this is the address of a function called when reading
directory entries from the filesystem for completion and comparing
them to the partial word to be completed. The function should
them to the filename portion of the partial word to be completed
(after its potential modification by @code{rl_completion_rewrite_hook}).
The function should
perform any necessary application or system-specific conversion on
the filename, such as converting between character sets or converting
from a filesystem format to a character input format.
@@ -2151,6 +2183,24 @@ matches, is added to the list of matches. Readline will free the
allocated string.
@end deftypevar
@deftypevar {rl_dequote_func_t *} rl_completion_rewrite_hook
If non-zero, this is the address of a function to call before
comparing the filename portion of a word to be completed with directory
entries from the filesystem.
The function takes two arguments: @var{fname}, the filename to be converted,
after any @code{rl_filename_dequoting_function} has been applied,
and @var{fnlen}, its length in bytes.
It must either return its first argument (if no conversion takes place)
or the converted filename in newly-allocated memory.
The function should perform any necessary application or system-specific
conversion on the filename, such as converting between character sets or
converting from a character input format to some other format.
Readline compares the converted form against directory entries, after
their potential modification by @code{rl_filename_rewrite_hook}, and adds
any matches to the list of matches.
Readline will free the allocated string.
@end deftypevar
@deftypevar {rl_compdisp_func_t *} rl_completion_display_matches_hook
If non-zero, then this is the address of a function to call when
completing a word would normally display the list of possible matches.
@@ -2298,6 +2348,17 @@ The quoting is effected via a call to the function pointed to
by @code{rl_filename_quoting_function}.
@end deftypevar
@deftypevar int rl_full_quoting_desired
Non-zero means that Readline should apply filename-style quoting,
including any application-specified quoting mechanism,
to all completion matches even if we are not otherwise treating the
matches as filenames.
This is @emph{always} zero when completion is attempted, and can only
be changed within an application-specific completion function.
The quoting is effected via a call to the function pointed to
by @code{rl_filename_quoting_function}.
@end deftypevar
@deftypevar int rl_attempted_completion_over
If an application-specific completion function assigned to
@code{rl_attempted_completion_function} sets this variable to a non-zero
@@ -2423,8 +2484,8 @@ COMMAND commands[] = @{
@};
/* Forward declarations. */
char *stripwhite ();
COMMAND *find_command ();
char *stripwhite (char *);
COMMAND *find_command (char *);
/* The name of this program, as taken from argv[0]. */
char *progname;
@@ -2433,8 +2494,7 @@ char *progname;
int done;
char *
dupstr (s)
char *s;
dupstr (char *s)
@{
char *r;
@@ -2443,9 +2503,8 @@ dupstr (s)
return (r);
@}
main (argc, argv)
int argc;
char **argv;
int
main (int argc, char **argv)
@{
char *line, *s;
@@ -2481,8 +2540,7 @@ main (argc, argv)
/* Execute a command line. */
int
execute_line (line)
char *line;
execute_line (char *line)
@{
register int i;
COMMAND *command;
@@ -2521,8 +2579,7 @@ execute_line (line)
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (name)
char *name;
find_command (char *name)
@{
register int i;
@@ -2536,8 +2593,7 @@ find_command (name)
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (string)
char *string;
stripwhite (char *string)
@{
register char *s, *t;
@@ -2561,13 +2617,14 @@ stripwhite (string)
/* */
/* **************************************************************** */
char *command_generator PARAMS((const char *, int));
char **fileman_completion PARAMS((const char *, int, int));
char *command_generator (const char *, int);
char **fileman_completion (const char *, int, int);
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
initialize_readline ()
void
initialize_readline (void)
@{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
@@ -2582,9 +2639,7 @@ initialize_readline ()
in case we want to do some simple parsing. Return the array of matches,
or NULL if there aren't any. */
char **
fileman_completion (text, start, end)
const char *text;
int start, end;
fileman_completion (const char *text, int start, int end)
@{
char **matches;
@@ -2603,9 +2658,7 @@ fileman_completion (text, start, end)
to start from scratch; without any state (i.e. STATE == 0), then we
start at the top of the list. */
char *
command_generator (text, state)
const char *text;
int state;
command_generator (const char *text, int state)
@{
static int list_index, len;
char *name;
@@ -2643,40 +2696,40 @@ command_generator (text, state)
static char syscom[1024];
/* List the file(s) named in arg. */
com_list (arg)
char *arg;
int
com_list (char *arg)
@{
if (!arg)
arg = "";
sprintf (syscom, "ls -FClg %s", arg);
snprintf (syscom, sizeof (syscom), "ls -FClg %s", arg);
return (system (syscom));
@}
com_view (arg)
char *arg;
int
com_view (char *arg)
@{
if (!valid_argument ("view", arg))
return 1;
#if defined (__MSDOS__)
/* more.com doesn't grok slashes in pathnames */
sprintf (syscom, "less %s", arg);
snprintf (syscom, sizeof (syscom), "less %s", arg);
#else
sprintf (syscom, "more %s", arg);
snprintf (syscom, sizeof (syscom), "more %s", arg);
#endif
return (system (syscom));
@}
com_rename (arg)
char *arg;
int
com_rename (char *arg)
@{
too_dangerous ("rename");
return (1);
@}
com_stat (arg)
char *arg;
int
com_stat (char *arg)
@{
struct stat finfo;
@@ -2703,8 +2756,8 @@ com_stat (arg)
return (0);
@}
com_delete (arg)
char *arg;
int
com_delete (char *arg)
@{
too_dangerous ("delete");
return (1);
@@ -2712,8 +2765,8 @@ com_delete (arg)
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
com_help (arg)
char *arg;
int
com_help (char *arg)
@{
register int i;
int printed = 0;
@@ -2751,8 +2804,8 @@ com_help (arg)
@}
/* Change to the directory ARG. */
com_cd (arg)
char *arg;
int
com_cd (char *arg)
@{
if (chdir (arg) == -1)
@{
@@ -2765,8 +2818,8 @@ com_cd (arg)
@}
/* Print out the current working directory. */
com_pwd (ignore)
char *ignore;
int
com_pwd (char *ignore)
@{
char dir[1024], *s;
@@ -2782,16 +2835,16 @@ com_pwd (ignore)
@}
/* The user wishes to quit using this program. Just set DONE non-zero. */
com_quit (arg)
char *arg;
int
com_quit (char *arg)
@{
done = 1;
return (0);
@}
/* Function which tells you that you can't do this. */
too_dangerous (caller)
char *caller;
void
too_dangerous (char *caller)
@{
fprintf (stderr,
"%s: Too dangerous for me to distribute. Write it yourself.\n",
@@ -2801,8 +2854,7 @@ too_dangerous (caller)
/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int
valid_argument (caller, arg)
char *caller, *arg;
valid_argument (char *caller, char *arg)
@{
if (!arg || !*arg)
@{
+92 -39
View File
@@ -1,5 +1,7 @@
@comment %**start of header (This is for running Texinfo on a region.)
@ifclear BashFeatures
@setfilename rluser.info
@end ifclear
@comment %**end of header (This is for running Texinfo on a region.)
@ignore
@@ -9,7 +11,7 @@ use these features. There is a document entitled "readline.texinfo"
which contains both end-user and programmer documentation for the
GNU Readline Library.
Copyright (C) 1988--2022 Free Software Foundation, Inc.
Copyright (C) 1988--2023 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
@@ -323,13 +325,14 @@ the line, thereby executing the command from the history list.
A movement command will terminate the search, make the last line found
the current line, and begin editing.
Readline remembers the last incremental search string. If two
@kbd{C-r}s are typed without any intervening characters defining a new
search string, any remembered search string is used.
Readline remembers the last incremental search string.
If two @kbd{C-r}s are typed without any intervening characters defining
a new search string, Readline uses any remembered search string.
Non-incremental searches read the entire search string before starting
to search for matching history lines. The search string may be
typed by the user or be part of the contents of the current line.
to search for matching history lines.
The search string may be typed by the user or be part of the contents of
the current line.
@node Readline Init File
@section Readline Init File
@@ -402,11 +405,12 @@ set editing-mode vi
@end example
Variable names and values, where appropriate, are recognized without regard
to case. Unrecognized variable names are ignored.
to case.
Unrecognized variable names are ignored.
Boolean variables (those that can be set to on or off) are set to on if
the value is null or empty, @var{on} (case-insensitive), or 1. Any other
value results in the variable being set to off.
the value is null or empty, @var{on} (case-insensitive), or 1.
Any other value results in the variable being set to off.
@ifset BashFeatures
The @w{@code{bind -V}} command lists the current Readline variable names
@@ -456,8 +460,12 @@ the terminal's bell.
@item bind-tty-special-chars
@vindex bind-tty-special-chars
If set to @samp{on} (the default), Readline attempts to bind the control
characters treated specially by the kernel's terminal driver to their
characters that are
treated specially by the kernel's terminal driver to their
Readline equivalents.
These override the default Readline bindings described here.
Type @samp{stty -a} at a Bash prompt to see your current terminal settings,
including the special control characters (usually @code{cchars}).
@item blink-matching-paren
@vindex blink-matching-paren
@@ -716,11 +724,11 @@ The default is @samp{off}.
@item match-hidden-files
@vindex match-hidden-files
This variable, when set to @samp{on}, causes Readline to match files whose
This variable, when set to @samp{on}, forces Readline to match files whose
names begin with a @samp{.} (hidden files) when performing filename
completion.
If set to @samp{off}, the leading @samp{.} must be
supplied by the user in the filename to be completed.
If set to @samp{off}, the user must include the leading @samp{.}
in the filename to be completed.
This variable is @samp{on} by default.
@item menu-complete-display-prefix
@@ -757,6 +765,12 @@ before returning when @code{accept-line} is executed. By default,
history lines may be modified and retain individual undo lists across
calls to @code{readline()}. The default is @samp{off}.
@item search-ignore-case
@vindex search-ignore-case
If set to @samp{on}, Readline performs incremental and non-incremental
history list searches in a case-insensitive fashion.
The default value is @samp{off}.
@item show-all-if-ambiguous
@vindex show-all-if-ambiguous
This alters the default behavior of the completion functions. If
@@ -1458,6 +1472,16 @@ moving point past that word as well.
If the insertion point is at the end of the line, this transposes
the last two words on the line.
@ifset BashFeatures
@item shell-transpose-words (M-C-t)
Drag the word before point past the word after point,
moving point past that word as well.
If the insertion point is at the end of the line, this transposes
the last two words on the line.
Word boundaries are the same as @code{shell-forward-word} and
@code{shell-backward-word}.
@end ifset
@item upcase-word (M-u)
Uppercase the current (or following) word. With a negative argument,
uppercase the previous word, but do not move the cursor.
@@ -1528,14 +1552,6 @@ Kill the word behind point.
Word boundaries are the same as @code{shell-backward-word}.
@end ifset
@item shell-transpose-words (M-C-t)
Drag the word before point past the word after point,
moving point past that word as well.
If the insertion point is at the end of the line, this transposes
the last two words on the line.
Word boundaries are the same as @code{shell-forward-word} and
@code{shell-backward-word}.
@item unix-word-rubout (C-w)
Kill the word behind point, using white space as a word boundary.
The killed text is saved on the kill-ring.
@@ -1858,9 +1874,13 @@ pathname expansion.
Display version information about the current instance of Bash.
@item shell-expand-line (M-C-e)
Expand the line as the shell does.
This performs alias and history expansion as well as all of the shell
word expansions (@pxref{Shell Expansions}).
Expand the line by performing shell word expansions.
This performs alias and history expansion,
$'@var{string}' and $"@var{string}" quoting,
tilde expansion, parameter and variable expansion, arithmetic expansion,
command and proces substitution,
word splitting, and quote removal.
An explicit argument suppresses command and process substitution.
@item history-expand-line (M-^)
Perform history expansion on the current line.
@@ -1898,6 +1918,13 @@ editing mode.
@end ifclear
@item execute-named-command (M-x)
Read a bindable readline command name from the input and execute the
function to which it's bound, as if the key sequence to which it was
bound appeared in the input.
If this function is supplied with a numeric argument, it passes that
argument to the function it executes.
@end ftable
@node Readline vi Mode
@@ -2098,14 +2125,25 @@ be completed, and two to modify the completion as it is happening.
@item compgen
@btindex compgen
@example
@code{compgen [@var{option}] [@var{word}]}
@code{compgen [-V @var{varname}] [@var{option}] [@var{word}]}
@end example
Generate possible completion matches for @var{word} according to
the @var{option}s, which may be any option accepted by the
@code{complete}
builtin with the exception of @option{-p} and @option{-r}, and write
the matches to the standard output.
builtin with the exceptions of
@option{-p},
@option{-r},
@option{-D},
@option{-E},
and
@option{-I},
and write the matches to the standard output.
If the @option{-V} option is supplied, @code{compgen} stores the generated
completions into the indexed array variable @var{varname} instead of writing
them to the standard output.
When using the @option{-F} or @option{-C} options, the various shell variables
set by the programmable completion facilities, while available, will not
have useful values.
@@ -2122,14 +2160,15 @@ matches were generated.
@item complete
@btindex complete
@example
@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}] [-G @var{globpat}]
[-W @var{wordlist}] [-F @var{function}] [-C @var{command}] [-X @var{filterpat}]
[-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]}
@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}]
[-G @var{globpat}] [-W @var{wordlist}] [-F @var{function}] [-C @var{command}]
[-X @var{filterpat}] [-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]}
@code{complete -pr [-DEI] [@var{name} @dots{}]}
@end example
Specify how arguments to each @var{name} should be completed.
If the @option{-p} option is supplied, or if no options are supplied, existing
If the @option{-p} option is supplied, or if no options or @var{name}s
are supplied, existing
completion specifications are printed in a way that allows them to be
reused as input.
The @option{-r} option removes a completion specification for
@@ -2187,6 +2226,10 @@ quoting special characters, or suppressing trailing spaces).
This option is intended to be used with shell functions specified
with @option{-F}.
@item fullquote
Tell Readline to quote all the completed words even if they are not
filenames.
@item noquote
Tell Readline not to quote the completed words if they are filenames
(quoting filenames is the default).
@@ -2330,7 +2373,14 @@ case, any completion not matching @var{filterpat} is removed.
@end table
The return value is true unless an invalid option is supplied, an option
other than @option{-p} or @option{-r} is supplied without a @var{name}
other than
@option{-p},
@option{-r},
@option{-D},
@option{-E},
or
@option{-I}
is supplied without a @var{name}
argument, an attempt is made to remove a completion specification for
a @var{name} for which no specification exists, or
an error occurs adding a completion specification.
@@ -2458,9 +2508,11 @@ complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
@noindent
Since we'd like Bash and Readline to take care of some
of the other details for us, we use several other options to tell Bash
and Readline what to do. The @option{-o filenames} option tells Readline
and Readline what to do.
The @option{-o filenames} option tells Readline
that the possible completions should be treated as filenames, and quoted
appropriately. That option will also cause Readline to append a slash to
appropriately.
That option will also cause Readline to append a slash to
filenames it can determine are directories (which is why we might want to
extend @code{_comp_cd} to append a slash if we're using directories found
via @var{CDPATH}: Readline can't tell those completions are directories).
@@ -2468,9 +2520,10 @@ The @option{-o nospace} option tells Readline to not append a space
character to the directory name, in case we want to append to it.
The @option{-o bashdefault} option brings in the rest of the "Bash default"
completions -- possible completions that Bash adds to the default Readline
set. These include things like command name completion, variable completion
for words beginning with @samp{$} or @samp{$@{}, completions containing pathname
expansion patterns (@pxref{Filename Expansion}), and so on.
set.
These include things like command name completion, variable completion
for words beginning with @samp{$} or @samp{$@{}, completions containing
pathname expansion patterns (@pxref{Filename Expansion}), and so on.
Once installed using @code{complete}, @code{_comp_cd} will be called every
time we attempt word completion for a @code{cd} command.
@@ -2479,8 +2532,8 @@ Many more examples -- an extensive collection of completions for most of
the common GNU, Unix, and Linux commands -- are available as part of the
bash_completion project. This is installed by default on many GNU/Linux
distributions. Originally written by Ian Macdonald, the project now lives
at @url{https://github.com/scop/bash-completion/}. There are ports for
other systems such as Solaris and Mac OS X.
at @url{https://github.com/scop/bash-completion/}.
There are ports for other systems such as Solaris and Mac OS X.
An older version of the bash_completion package is distributed with bash
in the @file{examples/complete} subdirectory.
+6 -6
View File
@@ -1,11 +1,11 @@
@ignore
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
@end ignore
@set EDITION 8.2
@set VERSION 8.2
@set EDITION 8.3
@set VERSION 8.3
@set UPDATED 19 September 2022
@set UPDATED-MONTH September 2022
@set UPDATED 19 January 2024
@set UPDATED-MONTH January 2024
@set LASTCHANGE Mon Sep 19 11:15:16 EDT 2022
@set LASTCHANGE Fri Jan 19 11:01:44 EST 2024
+1 -1
View File
@@ -448,7 +448,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_upcase_word }, /* Meta-u */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */
{ ISFUNC, rl_execute_named_command }, /* Meta-x */
{ ISFUNC, rl_yank_pop }, /* Meta-y */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */
+1 -1
View File
@@ -102,7 +102,7 @@ cc_t old_vtime;
struct termios term;
int
main()
main(int c, char **v)
{
fd_set fds;
+76 -94
View File
@@ -1,6 +1,6 @@
/* fileman.c - file manager example for readline library. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2009,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.
@@ -61,24 +61,24 @@
# include <readline/history.h>
#endif
extern char *xmalloc PARAMS((size_t));
extern char *xmalloc (size_t);
void initialize_readline PARAMS((void));
void too_dangerous PARAMS((char *));
void initialize_readline (void);
void too_dangerous (char *);
int execute_line PARAMS((char *));
int valid_argument PARAMS((char *, char *));
int execute_line (char *);
int valid_argument (char *, char *);
/* The names of functions that actually do the manipulation. */
int com_list PARAMS((char *));
int com_view PARAMS((char *));
int com_rename PARAMS((char *));
int com_stat PARAMS((char *));
int com_pwd PARAMS((char *));
int com_delete PARAMS((char *));
int com_help PARAMS((char *));
int com_cd PARAMS((char *));
int com_quit PARAMS((char *));
int com_list (char *);
int com_view (char *);
int com_rename (char *);
int com_stat (char *);
int com_pwd (char *);
int com_delete (char *);
int com_help (char *);
int com_cd (char *);
int com_quit (char *);
/* A structure which contains information on the commands this program
can understand. */
@@ -105,8 +105,11 @@ COMMAND commands[] = {
};
/* Forward declarations. */
char *stripwhite ();
COMMAND *find_command ();
char *dupstr (char *);
int execute_line (char *);
char *stripwhite (char *);
COMMAND *find_command (char *);
/* The name of this program, as taken from argv[0]. */
char *progname;
@@ -115,8 +118,7 @@ char *progname;
int done;
char *
dupstr (s)
char *s;
dupstr (char *s)
{
char *r;
@@ -125,45 +127,9 @@ dupstr (s)
return (r);
}
int
main (argc, argv)
int argc;
char **argv;
{
char *line, *s;
progname = argv[0];
initialize_readline (); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("FileMan: ");
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line);
if (*s)
{
add_history (s);
execute_line (s);
}
free (line);
}
exit (0);
}
/* Execute a command line. */
int
execute_line (line)
char *line;
execute_line (char *line)
{
register int i;
COMMAND *command;
@@ -202,8 +168,7 @@ execute_line (line)
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (name)
char *name;
find_command (char *name)
{
register int i;
@@ -217,8 +182,7 @@ find_command (name)
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (string)
char *string;
stripwhite (char *string)
{
register char *s, *t;
@@ -242,14 +206,14 @@ stripwhite (string)
/* */
/* **************************************************************** */
char *command_generator PARAMS((const char *, int));
char **fileman_completion PARAMS((const char *, int, int));
char *command_generator (const char *, int);
char **fileman_completion (const char *, int, int);
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
void
initialize_readline ()
initialize_readline (void)
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
@@ -264,9 +228,7 @@ initialize_readline ()
in case we want to do some simple parsing. Return the array of matches,
or NULL if there aren't any. */
char **
fileman_completion (text, start, end)
const char *text;
int start, end;
fileman_completion (const char *text, int start, int end)
{
char **matches;
@@ -285,9 +247,7 @@ fileman_completion (text, start, end)
to start from scratch; without any state (i.e. STATE == 0), then we
start at the top of the list. */
char *
command_generator (text, state)
const char *text;
int state;
command_generator (const char *text, int state)
{
static int list_index, len;
char *name;
@@ -326,43 +286,39 @@ static char syscom[1024];
/* List the file(s) named in arg. */
int
com_list (arg)
char *arg;
com_list (char *arg)
{
if (!arg)
arg = "";
sprintf (syscom, "ls -FClg %s", arg);
snprintf (syscom, sizeof (syscom), "ls -FClg %s", arg);
return (system (syscom));
}
int
com_view (arg)
char *arg;
com_view (char *arg)
{
if (!valid_argument ("view", arg))
return 1;
#if defined (__MSDOS__)
/* more.com doesn't grok slashes in pathnames */
sprintf (syscom, "less %s", arg);
snprintf (syscom, sizeof (syscom), "less %s", arg);
#else
sprintf (syscom, "more %s", arg);
snprintf (syscom, sizeof (syscom), "more %s", arg);
#endif
return (system (syscom));
}
int
com_rename (arg)
char *arg;
com_rename (char *arg)
{
too_dangerous ("rename");
return (1);
}
int
com_stat (arg)
char *arg;
com_stat (char *arg)
{
struct stat finfo;
@@ -390,8 +346,7 @@ com_stat (arg)
}
int
com_delete (arg)
char *arg;
com_delete (char *arg)
{
too_dangerous ("delete");
return (1);
@@ -400,8 +355,7 @@ com_delete (arg)
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
int
com_help (arg)
char *arg;
com_help (char *arg)
{
register int i;
int printed = 0;
@@ -440,8 +394,7 @@ com_help (arg)
/* Change to the directory ARG. */
int
com_cd (arg)
char *arg;
com_cd (char *arg)
{
if (chdir (arg) == -1)
{
@@ -455,8 +408,7 @@ com_cd (arg)
/* Print out the current working directory. */
int
com_pwd (ignore)
char *ignore;
com_pwd (char *ignore)
{
char dir[1024], *s;
@@ -473,8 +425,7 @@ com_pwd (ignore)
/* The user wishes to quit using this program. Just set DONE non-zero. */
int
com_quit (arg)
char *arg;
com_quit (char *arg)
{
done = 1;
return (0);
@@ -482,8 +433,7 @@ com_quit (arg)
/* Function which tells you that you can't do this. */
void
too_dangerous (caller)
char *caller;
too_dangerous (char *caller)
{
fprintf (stderr,
"%s: Too dangerous for me to distribute. Write it yourself.\n",
@@ -493,8 +443,7 @@ too_dangerous (caller)
/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int
valid_argument (caller, arg)
char *caller, *arg;
valid_argument (char *caller, char *arg)
{
if (!arg || !*arg)
{
@@ -504,3 +453,36 @@ valid_argument (caller, arg)
return (1);
}
int
main (int argc, char **argv)
{
char *line, *s;
progname = argv[0];
initialize_readline (); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("FileMan: ");
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line);
if (*s)
{
add_history (s);
execute_line (s);
}
free (line);
}
exit (0);
}
+5 -5
View File
@@ -32,9 +32,7 @@
#include <string.h>
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
char line[1024], *t;
int len, done;
@@ -91,6 +89,7 @@ main (argc, argv)
register HIST_ENTRY **the_list;
register int i;
time_t tt;
struct tm *tm;
char timestr[128];
the_list = history_list ();
@@ -98,8 +97,9 @@ main (argc, argv)
for (i = 0; the_list[i]; i++)
{
tt = history_get_time (the_list[i]);
if (tt)
strftime (timestr, sizeof (timestr), "%a %R", localtime(&tt));
tm = tt ? localtime (&tt) : 0;
if (tm)
strftime (timestr, sizeof (timestr), "%a %R", tm);
else
strcpy (timestr, "??");
printf ("%d: %s: %s\n", i + history_base, timestr, the_list[i]->line);
+35 -7
View File
@@ -1,6 +1,6 @@
/* manexamp.c -- The examples which appear in the documentation are here. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2009,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.
@@ -18,9 +18,35 @@
You should have received a copy of the GNU General Public License
along with Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <readline/readline.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#ifndef errno
extern int errno;
#endif
#if defined (READLINE_LIBRARY)
# include "readline.h"
# include "history.h"
#else
# include <readline/readline.h>
# include <readline/history.h>
#endif
/* **************************************************************** */
/* */
@@ -33,7 +59,7 @@ static char *line_read = (char *)NULL;
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
char *
rl_gets ()
rl_gets (void)
{
/* If the buffer has already been allocated, return the memory
to the free pool. */
@@ -60,10 +86,11 @@ rl_gets ()
/* **************************************************************** */
/* Invert the case of the COUNT following characters. */
invert_case_line (count, key)
int count, key;
int
invert_case_line (int count, int key)
{
register int start, end;
int start, end;
int direction;
start = rl_point;
@@ -92,7 +119,7 @@ invert_case_line (count, key)
}
if (start == end)
return;
return 0;
/* Tell readline that we are modifying the line, so save the undo
information. */
@@ -108,4 +135,5 @@ invert_case_line (count, key)
/* Move point to on top of the last character changed. */
rl_point = end - direction;
return 0;
}
+4 -10
View File
@@ -5,7 +5,7 @@
* usage: rl [-p prompt] [-u unit] [-d default] [-n nchars]
*/
/* Copyright (C) 1987-2009 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.
@@ -55,15 +55,11 @@ extern void exit();
extern int optind;
extern char *optarg;
#if !defined (strchr) && !defined (__STDC__)
extern char *strrchr();
#endif
static char *progname;
static char *deftext;
static int
set_deftext ()
set_deftext (void)
{
if (deftext)
{
@@ -75,16 +71,14 @@ set_deftext ()
}
static void
usage()
usage(void)
{
fprintf (stderr, "%s: usage: %s [-p prompt] [-u unit] [-d default] [-n nchars]\n",
progname, progname);
}
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
char *temp, *prompt;
struct stat sb;
+8 -12
View File
@@ -4,7 +4,7 @@
* usage: rlcat
*/
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2009,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.
@@ -64,27 +64,26 @@ extern int errno;
extern int optind;
extern char *optarg;
static int stdcat();
static int fcopy(FILE *);
static int stdcat(int, char **);
static char *progname;
static int vflag;
static void
usage()
usage(void)
{
fprintf (stderr, "%s: usage: %s [-vEVN] [filename]\n", progname, progname);
}
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
char *temp;
int opt, Vflag, Nflag;
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, ""):
setlocale (LC_ALL, "");
#endif
progname = strrchr(argv[0], '/');
@@ -134,8 +133,7 @@ main (argc, argv)
}
static int
fcopy(fp)
FILE *fp;
fcopy(FILE *fp)
{
int c;
char *x;
@@ -155,9 +153,7 @@ fcopy(fp)
}
int
stdcat (argc, argv)
int argc;
char **argv;
stdcat (int argc, char **argv)
{
int i, fd, r;
char *s;
+2 -4
View File
@@ -4,7 +4,7 @@
/* */
/* **************************************************************** */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2009,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.
@@ -48,10 +48,8 @@ extern void exit();
# include <readline/history.h>
#endif
extern HIST_ENTRY **history_list ();
int
main ()
main (int c, char **v)
{
char *temp, *prompt;
int done;
+3 -6
View File
@@ -40,16 +40,12 @@
#include "xmalloc.h"
#ifdef __STDC__
typedef int QSFUNC (const void *, const void *);
#else
typedef int QSFUNC ();
#endif
extern int _rl_qsort_string_compare (char **, char **);
FUNMAP **funmap;
static int funmap_size;
static size_t funmap_size;
static int funmap_entry;
/* After initializing the function map, this is the index of the first
@@ -93,6 +89,7 @@ static const FUNMAP default_funmap[] = {
{ "end-of-history", rl_end_of_history },
{ "end-of-line", rl_end_of_line },
{ "exchange-point-and-mark", rl_exchange_point_and_mark },
{ "execute-named-command", rl_execute_named_command },
{ "fetch-history", rl_fetch_history },
{ "forward-backward-delete-char", rl_rubout_or_delete },
{ "forward-byte", rl_forward_byte },
@@ -251,7 +248,7 @@ const char **
rl_funmap_names (void)
{
const char **result;
int result_size, result_index;
size_t result_size, result_index;
/* Make sure that the function map has been initialized. */
rl_initialize_funmap ();
+39 -26
View File
@@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
/* Copyright (C) 1989-2021,2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -70,12 +70,12 @@ static int subst_rhs_len;
specifications from word designators. Static for now */
static char *history_event_delimiter_chars = HISTORY_EVENT_DELIMITERS;
static char *get_history_word_specifier (char *, char *, int *);
static char *get_history_word_specifier (const char *, char *, int *);
static int history_tokenize_word (const char *, int);
static char **history_tokenize_internal (const char *, int, int *);
static char *history_substring (const char *, int, int);
static void freewords (char **, int);
static char *history_find_word (char *, int);
static char *history_find_word (const char *, int);
static char *quote_breaks (char *);
@@ -319,7 +319,7 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote)
to the closing single quote. FLAGS currently used to allow backslash
to escape a single quote (e.g., for bash $'...'). */
static void
hist_string_extract_single_quoted (char *string, int *sindex, int flags)
hist_string_extract_single_quoted (const char *string, int *sindex, int flags)
{
register int i;
@@ -374,7 +374,7 @@ quote_breaks (char *s)
}
static char *
hist_error(char *s, int start, int current, int errtype)
hist_error(const char *s, int start, int current, int errtype)
{
char *temp;
const char *emsg;
@@ -434,7 +434,7 @@ hist_error(char *s, int start, int current, int errtype)
subst_rhs is allowed to be set to the empty string. */
static char *
get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
get_subst_pattern (const char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
{
register int si, i, j, k;
char *s;
@@ -509,7 +509,7 @@ postproc_subst_rhs (void)
/* a single backslash protects the `&' from lhs interpolation */
if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
i++;
if (j >= new_size)
if (j + 1 >= new_size)
new = (char *)xrealloc (new, new_size *= 2);
new[j++] = subst_rhs[i];
}
@@ -527,12 +527,12 @@ postproc_subst_rhs (void)
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
/* need current line for !# */
static int
history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
history_expand_internal (const char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
{
int i, n, starting_index;
int substitute_globally, subst_bywords, want_quotes, print_only;
char *event, *temp, *result, *tstr, *t, c, *word_spec;
int result_len;
size_t result_len;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps;
@@ -730,7 +730,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
/* If `&' appears in the rhs, it's supposed to be replaced
with the lhs. */
if (member ('&', subst_rhs))
if (subst_lhs && member ('&', subst_rhs))
postproc_subst_rhs ();
}
else
@@ -881,7 +881,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
#define ADD_STRING(s) \
do \
{ \
int sl = strlen (s); \
size_t sl = strlen (s); \
j += sl; \
if (j >= result_len) \
{ \
@@ -896,7 +896,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
#define ADD_CHAR(c) \
do \
{ \
if (j >= result_len - 1) \
if ((j + 1) >= result_len) \
result = (char *)xrealloc (result, result_len += 64); \
result[j++] = c; \
result[j] = '\0'; \
@@ -904,14 +904,15 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
while (0)
int
history_expand (char *hstring, char **output)
history_expand (const char *hstring, char **output)
{
register int j;
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
int j;
int i, r, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
size_t l;
char *string;
/* The output string, and its length. */
int result_len;
size_t result_len;
char *result;
#if defined (HANDLE_MULTIBYTE)
@@ -949,7 +950,7 @@ history_expand (char *hstring, char **output)
/* The quick substitution character is a history expansion all right. That
is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
that is the substitution that we do. */
if (hstring[0] == history_subst_char)
if ((history_quoting_state != '\'' || history_quotes_inhibit_expansion == 0) && hstring[0] == history_subst_char)
{
string = (char *)xmalloc (l + 5);
@@ -965,7 +966,7 @@ history_expand (char *hstring, char **output)
memset (&ps, 0, sizeof (mbstate_t));
#endif
string = hstring;
string = (char *)hstring;
/* If not quick substitution, still maybe have to do expansion. */
/* `!' followed by one of the characters in history_no_expand_chars
@@ -983,6 +984,8 @@ history_expand (char *hstring, char **output)
squote = 0;
if (string[i])
i++;
if (i >= l)
i = l;
}
for ( ; string[i]; i++)
@@ -1053,6 +1056,11 @@ history_expand (char *hstring, char **output)
flag = (i > 0 && string[i - 1] == '$');
i++;
hist_string_extract_single_quoted (string, &i, flag);
if (i >= l)
{
i = l;
break;
}
}
else if (history_quotes_inhibit_expansion && string[i] == '\\')
{
@@ -1063,7 +1071,7 @@ history_expand (char *hstring, char **output)
}
}
if (string[i] != history_expansion_char)
{
xfree (result);
@@ -1113,7 +1121,7 @@ history_expand (char *hstring, char **output)
c = tchar;
memset (mb, 0, sizeof (mb));
for (k = 0; k < MB_LEN_MAX; k++)
for (k = 0; k < MB_LEN_MAX && i < l; k++)
{
mb[k] = (char)c;
memset (&ps, 0, sizeof (mbstate_t));
@@ -1303,7 +1311,7 @@ history_expand (char *hstring, char **output)
CALLER_INDEX is the offset in SPEC to start looking; it is updated
to point to just after the last character parsed. */
static char *
get_history_word_specifier (char *spec, char *from, int *caller_index)
get_history_word_specifier (const char *spec, char *from, int *caller_index)
{
register int i = *caller_index;
int first, last;
@@ -1418,7 +1426,7 @@ history_arg_extract (int first, int last, const char *string)
{
register int i, len;
char *result;
int size, offset;
size_t size, offset;
char **list;
/* XXX - think about making history_tokenize return a struct array,
@@ -1475,7 +1483,7 @@ history_arg_extract (int first, int last, const char *string)
static int
history_tokenize_word (const char *string, int ind)
{
register int i, j;
int i, j;
int delimiter, nestdelim, delimopen;
i = ind;
@@ -1562,6 +1570,8 @@ get_word:
(delimiter != '"' || member (string[i], slashify_in_quotes)))
{
i++;
if (string[i] == 0)
break;
continue;
}
@@ -1590,6 +1600,8 @@ get_word:
if (nestdelim == 0 && delimiter == 0 && member (string[i], "<>$!@?+*") && string[i+1] == '(') /*)*/
{
i += 2;
if (string[i] == 0)
break; /* could just return i here */
delimopen = '(';
delimiter = ')';
nestdelim = 1;
@@ -1627,7 +1639,8 @@ static char **
history_tokenize_internal (const char *string, int wind, int *indp)
{
char **result;
register int i, start, result_index, size;
int i, start, result_index;
size_t size;
/* If we're searching for a string that's not part of a word (e.g., " "),
make sure we set *INDP to a reasonable value. */
@@ -1636,7 +1649,7 @@ history_tokenize_internal (const char *string, int wind, int *indp)
/* Get a token, and stuff it into RESULT. The tokens are split
exactly where the shell would split them. */
for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
for (i = result_index = 0, size = 0, result = (char **)NULL; string[i]; )
{
/* Skip leading whitespace. */
for (; string[i] && fielddelim (string[i]); i++)
@@ -1696,7 +1709,7 @@ freewords (char **words, int start)
in the history line LINE. Used to save the word matched by the
last history !?string? search. */
static char *
history_find_word (char *line, int ind)
history_find_word (const char *line, int ind)
{
char **words, *s;
int i, wind;
+89 -25
View File
@@ -1,6 +1,6 @@
/* histfile.c - functions to manipulate the history file. */
/* Copyright (C) 1989-2019 Free Software Foundation, Inc.
/* Copyright (C) 1989-2019,2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -153,7 +153,7 @@ history_filename (const char *filename)
{
char *return_val;
const char *home;
int home_len;
size_t home_len;
return_val = filename ? savestring (filename) : (char *)NULL;
@@ -168,9 +168,8 @@ history_filename (const char *filename)
if (home == 0)
return (NULL);
else
home_len = strlen (home);
home_len = strlen (home);
return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
strcpy (return_val, home);
return_val[home_len] = '/';
@@ -190,7 +189,6 @@ history_backupfile (const char *filename)
char *ret, linkbuf[PATH_MAX+1];
size_t len;
ssize_t n;
struct stat fs;
fn = filename;
#if defined (HAVE_READLINK)
@@ -218,7 +216,6 @@ history_tempfile (const char *filename)
char *ret, linkbuf[PATH_MAX+1];
size_t len;
ssize_t n;
struct stat fs;
int pid;
fn = filename;
@@ -284,7 +281,10 @@ read_history_range (const char *filename, int from, int to)
buffer = last_ts = (char *)NULL;
input = history_filename (filename);
file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
if (input == 0)
return 0;
errno = 0;
file = open (input, O_RDONLY|O_BINARY, 0666);
if ((file < 0) || (fstat (file, &finfo) == -1))
goto error_and_exit;
@@ -526,10 +526,14 @@ history_truncate_file (const char *fname, int lines)
buffer = (char *)NULL;
filename = history_filename (fname);
if (filename == 0)
return 0;
tempname = 0;
file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
file = open (filename, O_RDONLY|O_BINARY, 0666);
rv = exists = 0;
orig_lines = lines;
/* Don't try to truncate non-regular files. */
if (file == -1 || fstat (file, &finfo) == -1)
{
@@ -578,6 +582,15 @@ history_truncate_file (const char *fname, int lines)
goto truncate_exit;
}
/* Don't bother with any of this if we're truncating to zero length. */
if (lines == 0)
{
close (file);
buffer[chars_read = 0] = '\0';
bp = buffer;
goto truncate_write;
}
chars_read = read (file, buffer, file_size);
close (file);
@@ -586,31 +599,38 @@ history_truncate_file (const char *fname, int lines)
rv = (chars_read < 0) ? errno : 0;
goto truncate_exit;
}
buffer[chars_read] = '\0'; /* for the initial check of bp1[1] */
orig_lines = lines;
/* Count backwards from the end of buffer until we have passed
LINES lines. bp1 is set funny initially. But since bp[1] can't
be a comment character (since it's off the end) and *bp can't be
both a newline and the history comment character, it should be OK. */
for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
both a newline and the history comment character, it should be OK.
If we are writing history timestamps, we need to add one to LINES
because we decrement it one extra time the first time through the loop
and we need the final timestamp line. */
lines += history_write_timestamps;
for (bp1 = bp = buffer + chars_read - 1; lines > 0 && bp > buffer; bp--)
{
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
lines--;
bp1 = bp;
}
/* If this is the first line, then the file contains exactly the
/* This is the right line, so move to its start. If we're writing history
timestamps, we want to go back until *bp == '\n' and bp1 starts a
history timestamp. If we're not, just move back to *bp == '\n'.
If this is the first line, then the file contains exactly the
number of lines we want to truncate to, so we don't need to do
anything. It's the first line if we don't find a newline between
the current value of i and 0. Otherwise, write from the start of
this line until the end of the buffer. */
anything, and we'll end up with bp == buffer.
Otherwise, write from the start of this line until the end of the
buffer. */
for ( ; bp > buffer; bp--)
{
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
{
if (*bp == '\n' && (history_write_timestamps == 0 || HIST_TIMESTAMP_START(bp1)))
{
bp++;
break;
}
}
bp1 = bp;
}
@@ -624,17 +644,24 @@ history_truncate_file (const char *fname, int lines)
goto truncate_exit;
}
truncate_write:
tempname = history_tempfile (filename);
if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
{
if (write (file, bp, chars_read - (bp - buffer)) < 0)
rv = errno;
{
rv = errno;
close (file);
}
if (fstat (file, &nfinfo) < 0 && rv == 0)
rv = errno;
if (rv == 0 && fstat (file, &nfinfo) < 0)
{
rv = errno;
close (file);
}
if (close (file) < 0 && rv == 0)
if (rv == 0 && close (file) < 0)
rv = errno;
}
else
@@ -671,6 +698,38 @@ history_truncate_file (const char *fname, int lines)
return rv;
}
/* Use stdio to write the history file after mmap or malloc fails, on the
assumption that the stdio library can allocate the smaller buffers it uses. */
static int
history_write_slow (int fd, HIST_ENTRY **the_history, int nelements, int overwrite)
{
FILE *fp;
int i, j, e;
fp = fdopen (fd, overwrite ? "w" : "a");
if (fp == 0)
return -1;
for (j = 0, i = history_length - nelements; i < history_length; i++)
{
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
fprintf (fp, "%s\n", the_history[i]->timestamp);
if (fprintf (fp, "%s\n", the_history[i]->line) < 0)
goto slow_write_error;
}
if (fflush (fp) < 0)
{
slow_write_error:
e = errno;
fclose (fp);
errno = e;
return -1;
}
if (fclose (fp) < 0)
return -1;
return 0;
}
/* Workhorse function for writing history. Writes the last NELEMENT entries
from the history list to FILENAME. OVERWRITE is non-zero if you
wish to replace FILENAME with the entries. */
@@ -680,7 +739,7 @@ history_do_write (const char *filename, int nelements, int overwrite)
register int i;
char *output, *tempname, *histname;
int file, mode, rv, exists;
struct stat finfo, nfinfo;
struct stat finfo;
#ifdef HISTORY_USE_MMAP
size_t cursize;
@@ -718,8 +777,8 @@ history_do_write (const char *filename, int nelements, int overwrite)
Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
{
HIST_ENTRY **the_history; /* local */
register int j;
int buffer_size;
size_t j;
size_t buffer_size;
char *buffer;
the_history = history_list ();
@@ -739,6 +798,8 @@ history_do_write (const char *filename, int nelements, int overwrite)
if ((void *)buffer == MAP_FAILED)
{
mmap_error:
if ((rv = history_write_slow (file, the_history, nelements, overwrite)) == 0)
goto write_success;
rv = errno;
close (file);
if (tempname)
@@ -751,6 +812,8 @@ mmap_error:
buffer = (char *)malloc (buffer_size);
if (buffer == 0)
{
if ((rv = history_write_slow (file, the_history, nelements, overwrite)) == 0)
goto write_success;
rv = errno;
close (file);
if (tempname)
@@ -789,6 +852,7 @@ mmap_error:
if (close (file) < 0 && rv == 0)
rv = errno;
write_success:
if (rv == 0 && histname && tempname)
rv = histfile_restore (tempname, histname);
+9 -4
View File
@@ -1,6 +1,6 @@
/* histlib.h -- internal definitions for the history library. */
/* Copyright (C) 1989-2009,2021-2022 Free Software Foundation, Inc.
/* Copyright (C) 1989-2009,2021-2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -34,6 +34,11 @@
: ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
#endif
#if !defined (HAVE_STRCASECMP)
#define strcasecmp(a,b) strcmp ((a), (b))
#define strncasecmp(a, b, n) strncmp ((a), (b), (n))
#endif
#ifndef savestring
#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
#endif
@@ -51,9 +56,6 @@
#endif
#ifndef member
# if !defined (strchr) && !defined (__STDC__)
extern char *strchr ();
# endif /* !strchr && !__STDC__ */
#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
#endif
@@ -72,6 +74,7 @@ extern char *strchr ();
#define NON_ANCHORED_SEARCH 0
#define ANCHORED_SEARCH 0x01
#define PATTERN_SEARCH 0x02
#define CASEFOLD_SEARCH 0x04
/* Possible definitions for what style of writing the history file we want. */
#define HISTORY_APPEND 0
@@ -81,9 +84,11 @@ extern char *strchr ();
/* histsearch.c */
extern int _hs_history_patsearch (const char *, int, int);
extern int _hs_history_search (const char *, int, int);
/* history.c */
extern void _hs_replace_history_data (int, histdata_t *, histdata_t *);
extern int _hs_search_history_data (histdata_t *);
extern int _hs_at_end_of_history (void);
/* histfile.c */
+140 -21
View File
@@ -1,6 +1,6 @@
/* history.c -- standalone history library */
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
/* Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -42,6 +42,7 @@
# endif
# include <unistd.h>
#endif
#include "posixtime.h"
#include <errno.h>
@@ -60,24 +61,39 @@ extern int errno;
#define MAX_HISTORY_INITIAL_SIZE 8192
/* The number of slots to increase the_history by. */
#define DEFAULT_HISTORY_GROW_SIZE 50
#define DEFAULT_HISTORY_GROW_SIZE 256
static char *hist_inittime (void);
static int history_list_grow_size (void);
static void history_list_resize (int); /* XXX - size_t? */
static void advance_history (void);
/* **************************************************************** */
/* */
/* History Functions */
/* */
/* **************************************************************** */
/* An array of HIST_ENTRY. This is where we store the history. */
/* An array of HIST_ENTRY. This is where we store the history. the_history is
a roving pointer somewhere into this, so the user-visible history list is
a window into real_history starting at the_history and extending
history_length entries. */
static HIST_ENTRY **real_history = (HIST_ENTRY **)NULL;
/* The current number of slots allocated to the input_history. */
static int real_history_size = 0;
/* A pointer to somewhere in real_history, where the user-visible history
starts. */
static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
/* Non-zero means that we have enforced a limit on the amount of
history that we save. */
static int history_stifled;
/* The current number of slots allocated to the input_history. */
/* The number of history entries available for user use, starting at the_history.
real_history_size - history_size == the_history - real_history */
static int history_size;
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
@@ -89,12 +105,59 @@ int max_input_history; /* backwards compatibility */
life easier for outside callers. */
int history_offset;
/* The number of strings currently stored in the history list. */
/* The number of strings currently stored in the history list. This is
always <= real_history_length */
int history_length;
/* The logical `base' of the history array. It defaults to 1. */
int history_base = 1;
/* Compute the number of bits required to store a given nonnegative integer.
NOTE: _bit_length(0) == 0 */
static inline unsigned
_bit_length(unsigned n)
{
/* This implementation is for simplicity, not for performance, but it is
fast enough for our purposes here. */
unsigned count = 0;
while (n)
{
n >>= 1;
count++;
}
return count;
}
/* Compute a grow size that adjusts to the size of the history.
We aim to grow by roughly sqrt(history_size) in order to amortize the cost of
realloc() and memmove(). This reduces the total cost of the memmoves from
O(N^2) to O(N*sqrt(N)). */
static int
history_list_grow_size (void)
{
int width, r;
/* Handle small positive values and guard against history_length accidentally
being negative. */
const int MIN_BITS = 10;
if (history_length < (1 << MIN_BITS))
return DEFAULT_HISTORY_GROW_SIZE;
/* For other values, we just want something easy to compute that grows roughly
as sqrt(N), where N=history_length. We use approximately 2^((k+1)/2),
where k is the bit length of N. This bounds the value between sqrt(2N) and
2*sqrt(N). */
width = MIN_BITS + _bit_length(history_length >> MIN_BITS);
/* If width is odd then this is 2^((width+1)/2). An even width gives a value
of 3*2^((width-2)/2) ~ 1.06*2^((width+1)/2). */
r = (1 << (width / 2)) + (1 << ((width - 1) / 2));
/* Make sure we always expand the list by at least DEFAULT_HISTORY_GROW_SIZE */
return ((r < DEFAULT_HISTORY_GROW_SIZE) ? DEFAULT_HISTORY_GROW_SIZE : r);
}
/* Return the current HISTORY_STATE of the history. */
HISTORY_STATE *
history_get_history_state (void)
@@ -261,7 +324,7 @@ hist_inittime (void)
time_t t;
char ts[64], *ret;
t = (time_t) time ((time_t *)0);
t = getnow ();
#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
#else
@@ -273,6 +336,48 @@ hist_inittime (void)
return ret;
}
/* Ensure space for new history entries by resetting the start pointer
(the_history) and resizing real_history if necessary. */
static void
history_list_resize (int new_size)
{
/* Do nothing there is already enough user space. history_length is always <=
real_history_size */
if (new_size < history_length)
return;
/* If we need to, reset the_history to the start of real_history and
start over. */
if (the_history != real_history)
memmove (real_history, the_history, history_length * sizeof (HIST_ENTRY *));
/* Don't bother if real_history_size is already big enough, since at this
point the_history == real_history and we will set history_size to
real_history_size. We don't shrink the history list. */
if (new_size > real_history_size)
{
real_history = (HIST_ENTRY **) xrealloc (real_history, new_size * sizeof (HIST_ENTRY *));
real_history_size = new_size;
}
the_history = real_history;
history_size = real_history_size;
if (history_size > history_length)
memset (real_history + history_length, 0, (history_size - history_length) * sizeof (HIST_ENTRY *));
}
static void
advance_history (void)
{
/* Advance 'the_history' pointer to simulate dropping the first entry. */
the_history++;
history_size--;
/* If full, move all the entries (and trailing NULL) to the beginning. */
if (history_length == history_size)
history_list_resize (history_length + history_list_grow_size ());
}
/* Place STRING at the end of the history list. The data field
is set to NULL. */
void
@@ -283,8 +388,6 @@ add_history (const char *string)
if (history_stifled && (history_length == history_max_entries))
{
register int i;
/* If the history is stifled, and history_length is zero,
and it equals history_max_entries, we don't save items. */
if (history_length == 0)
@@ -294,9 +397,8 @@ add_history (const char *string)
if (the_history[0])
(void) free_history_entry (the_history[0]);
/* Copy the rest of the entries, moving down one slot. Copy includes
trailing NULL. */
memmove (the_history, the_history + 1, history_length * sizeof (HIST_ENTRY *));
/* Advance the pointer into real_history, resizing if necessary. */
advance_history ();
new_length = history_length;
history_base++;
@@ -305,23 +407,20 @@ add_history (const char *string)
{
if (history_size == 0)
{
int initial_size;
if (history_stifled && history_max_entries > 0)
history_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
initial_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
? MAX_HISTORY_INITIAL_SIZE
: history_max_entries + 2;
else
history_size = DEFAULT_HISTORY_INITIAL_SIZE;
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
initial_size = DEFAULT_HISTORY_INITIAL_SIZE;
history_list_resize (initial_size);
new_length = 1;
}
else
{
if (history_length == (history_size - 1))
{
history_size += DEFAULT_HISTORY_GROW_SIZE;
the_history = (HIST_ENTRY **)
xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
}
history_list_resize (real_history_size + history_list_grow_size ());
new_length = history_length + 1;
}
}
@@ -460,7 +559,7 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
}
last = -1;
for (i = 0; i < history_length; i++)
for (i = history_length - 1; i >= 0; i--)
{
entry = the_history[i];
if (entry == 0)
@@ -477,7 +576,27 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
entry = the_history[last];
entry->data = new; /* XXX - we don't check entry->old */
}
}
}
int
_hs_search_history_data (histdata_t *needle)
{
register int i;
HIST_ENTRY *entry;
if (history_length == 0 || the_history == 0)
return -1;
for (i = history_length - 1; i >= 0; i--)
{
entry = the_history[i];
if (entry == 0)
continue;
if (entry->data == needle)
return i;
}
return -1;
}
/* Remove history element WHICH from the history. The removed
element is returned to you so you can free the line, data,
+6 -6
View File
@@ -1,6 +1,6 @@
/* history.h -- the names of functions that you can call in history. */
/* Copyright (C) 1989-2022 Free Software Foundation, Inc.
/* Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -36,11 +36,7 @@ extern "C" {
# include <readline/rltypedefs.h>
#endif
#ifdef __STDC__
typedef void *histdata_t;
#else
typedef char *histdata_t;
#endif
/* Let's not step on anyone else's define for now, since we don't use this yet. */
#ifndef HS_HISTORY_VERSION
@@ -54,6 +50,10 @@ typedef struct _hist_entry {
histdata_t data;
} HIST_ENTRY;
#ifndef HIST_ENTRY_DEFINED
# define HIST_ENTRY_DEFINED
#endif
/* Size of the history-library-managed space in history entry HS. */
#define HISTENT_BYTES(hs) (strlen ((hs)->line) + strlen ((hs)->timestamp))
@@ -232,7 +232,7 @@ extern int history_truncate_file (const char *, int);
If an error occurred in expansion, then OUTPUT contains a descriptive
error message. */
extern int history_expand (char *, char **);
extern int history_expand (const char *, char **);
/* Extract a string segment consisting of the FIRST through LAST
arguments present in STRING. Arguments are broken up as in
+83 -32
View File
@@ -1,6 +1,6 @@
/* histsearch.c -- searching the history list. */
/* Copyright (C) 1989, 1992-2009,2017,2021 Free Software Foundation, Inc.
/* Copyright (C) 1989, 1992-2009,2017,2021,2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -47,6 +47,8 @@
#include "histlib.h"
#include "xmalloc.h"
#include "rlmbutil.h"
/* The list of alternate characters that can delimit a history search
string. */
char *history_search_delimiter_chars = (char *)NULL;
@@ -57,7 +59,10 @@ static int history_search_internal (const char *, int, int);
If DIRECTION < 0, then the search is through previous entries, else
through subsequent. If ANCHORED is non-zero, the string must
appear at the beginning of a history line, otherwise, the string
may appear anywhere in the line. If the string is found, then
may appear anywhere in the line. If PATSEARCH is non-zero, and fnmatch(3)
is available, fnmatch is used to match the string instead of a simple
string comparison. If IGNORECASE is set, the string comparison is
performed case-insensitively. If the string is found, then
current_history () is the history entry, and the value of this
function is the offset in the line of that history entry that the
string was found in. Otherwise, nothing is changed, and a -1 is
@@ -66,10 +71,12 @@ static int history_search_internal (const char *, int, int);
static int
history_search_internal (const char *string, int direction, int flags)
{
register int i, reverse;
register char *line;
register int line_index;
int string_len, anchored, patsearch;
int i, reverse;
char *line;
size_t string_len, line_len;
int line_index; /* can't be unsigned */
int anchored, patsearch, igncase;
int found, mb_cur_max;
HIST_ENTRY **the_history; /* local */
i = history_offset;
@@ -80,6 +87,7 @@ history_search_internal (const char *string, int direction, int flags)
#else
patsearch = 0;
#endif
igncase = (flags & CASEFOLD_SEARCH);
/* Take care of trivial cases first. */
if (string == 0 || *string == '\0')
@@ -91,6 +99,8 @@ history_search_internal (const char *string, int direction, int flags)
if (reverse && (i >= history_length))
i = history_length - 1;
mb_cur_max = MB_CUR_MAX;
#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
the_history = history_list ();
@@ -104,7 +114,7 @@ history_search_internal (const char *string, int direction, int flags)
return (-1);
line = the_history[i]->line;
line_index = strlen (line);
line_len = line_index = strlen (line);
/* If STRING is longer than line, no match. */
if (patsearch == 0 && (string_len > line_index))
@@ -116,18 +126,27 @@ history_search_internal (const char *string, int direction, int flags)
/* Handle anchored searches first. */
if (anchored == ANCHORED_SEARCH)
{
found = 0;
#if defined (HAVE_FNMATCH)
if (patsearch)
{
if (fnmatch (string, line, 0) == 0)
{
history_offset = i;
return (0);
}
}
found = fnmatch (string, line, 0) == 0;
else
#endif
if (STREQN (string, line, string_len))
if (igncase)
{
#if defined (HANDLE_MULTIBYTE)
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
found = _rl_mb_strcaseeqn (string, string_len,
line, line_len,
string_len, 0);
else
#endif
found = strncasecmp (string, line, string_len) == 0;
}
else
found = STREQN (string, line, string_len);
if (found)
{
history_offset = i;
return (0);
@@ -140,55 +159,80 @@ history_search_internal (const char *string, int direction, int flags)
/* Do substring search. */
if (reverse)
{
line_index -= (patsearch == 0) ? string_len : 1;
size_t ll;
ll = (patsearch == 0) ? string_len : 1;
line_index -= ll;
found = 0;
while (line_index >= 0)
{
#if defined (HAVE_FNMATCH)
if (patsearch)
{
if (fnmatch (string, line + line_index, 0) == 0)
{
history_offset = i;
return (line_index);
}
}
found = fnmatch (string, line + line_index, 0) == 0;
else
#endif
if (STREQN (string, line + line_index, string_len))
if (igncase)
{
#if defined (HANDLE_MULTIBYTE)
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
found = _rl_mb_strcaseeqn (string, string_len,
line + line_index, ll,
string_len, 0);
else
#endif
found = strncasecmp (string, line + line_index, string_len) == 0;
}
else
found = STREQN (string, line + line_index, string_len);
if (found)
{
history_offset = i;
return (line_index);
}
line_index--;
ll++;
}
}
else
{
register int limit;
size_t ll;
ll = line_len;
limit = line_index - string_len + 1;
line_index = 0;
found = 0;
while (line_index < limit)
{
#if defined (HAVE_FNMATCH)
if (patsearch)
{
if (fnmatch (string, line + line_index, 0) == 0)
{
history_offset = i;
return (line_index);
}
}
found = fnmatch (string, line + line_index, 0) == 0;
else
#endif
if (STREQN (string, line + line_index, string_len))
if (igncase)
{
#if defined (HANDLE_MULTIBYTE)
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
found = _rl_mb_strcaseeqn (string, string_len,
line + line_index, ll,
string_len, 0);
else
#endif
found = strncasecmp (string, line + line_index, string_len) == 0;
}
else
found = STREQN (string, line + line_index, string_len);
if (found)
{
history_offset = i;
return (line_index);
}
line_index++;
ll--;
}
}
NEXT_LINE ();
@@ -266,6 +310,13 @@ history_search_prefix (const char *string, int direction)
return (history_search_internal (string, direction, ANCHORED_SEARCH));
}
/* At some point, make this public for users of the history library. */
int
_hs_history_search (const char *string, int direction, int flags)
{
return (history_search_internal (string, direction, flags));
}
/* Search for STRING in the history list. DIR is < 0 for searching
backwards. POS is an absolute index into the history list at
which point to begin searching. */
+71 -31
View File
@@ -1,6 +1,6 @@
/* input.c -- character input functions for readline. */
/* Copyright (C) 1994-2021 Free Software Foundation, Inc.
/* Copyright (C) 1994-2022 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.
@@ -138,20 +138,16 @@ win32_isatty (int fd)
/* Readline timeouts */
/* I don't know how to set a timeout for _getch() in MinGW32, so we use
SIGALRM. */
#if (defined (HAVE_PSELECT) || defined (HAVE_SELECT)) && !defined (__MINGW32__)
# define RL_TIMEOUT_USE_SELECT
#else
# define RL_TIMEOUT_USE_SIGALRM
#endif
/* We now define RL_TIMEOUT_USE_SELECT or RL_TIMEOUT_USE_SIGALRM in rlprivate.h */
int rl_set_timeout (unsigned int, unsigned int);
int rl_timeout_remaining (unsigned int *, unsigned int *);
int _rl_timeout_init (void);
int _rl_timeout_sigalrm_handler (void);
int _rl_timeout_handle_sigalrm (void);
#if defined (RL_TIMEOUT_USE_SELECT)
int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *);
#endif
static void _rl_timeout_handle (void);
#if defined (RL_TIMEOUT_USE_SIGALRM)
@@ -248,38 +244,53 @@ rl_gather_tyi (void)
register int tem, result;
int chars_avail, k;
char input;
#if defined(HAVE_SELECT)
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
fd_set readfds, exceptfds;
struct timeval timeout;
#endif
result = -1;
chars_avail = 0;
input = 0;
tty = fileno (rl_instream);
/* Move this up here to give it first shot, but it can't set chars_avail */
/* XXX - need rl_chars_available_hook? */
if (rl_input_available_hook)
{
result = (*rl_input_available_hook) ();
if (result == 0)
result = -1;
}
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (tty, &readfds);
FD_SET (tty, &exceptfds);
USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
if (result == -1)
{
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (tty, &readfds);
FD_SET (tty, &exceptfds);
USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
#if defined (RL_TIMEOUT_USE_SELECT)
result = _rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL);
result = _rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL);
#else
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
#endif
if (result <= 0)
return 0; /* Nothing to read. */
if (result <= 0)
return 0; /* Nothing to read. */
}
#endif
result = -1;
errno = 0;
#if defined (FIONREAD)
result = ioctl (tty, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
if (result == -1)
chars_avail = 0;
{
errno = 0;
result = ioctl (tty, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
if (result == -1)
chars_avail = 0;
}
#endif
#if defined (O_NDELAY)
@@ -306,8 +317,11 @@ rl_gather_tyi (void)
#if defined (__MINGW32__)
/* Use getch/_kbhit to check for available console input, in the same way
that we read it normally. */
chars_avail = isatty (tty) ? _kbhit () : 0;
result = 0;
if (result == -1)
{
chars_avail = isatty (tty) ? _kbhit () : 0;
result = 0;
}
#endif
/* If there's nothing available, don't waste time trying to read
@@ -649,7 +663,7 @@ rl_timeout_remaining (unsigned int *secs, unsigned int *usecs)
/* This should only be called if RL_TIMEOUT_USE_SELECT is defined. */
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
#if defined (RL_TIMEOUT_USE_SELECT)
int
_rl_timeout_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout, const sigset_t *sigmask)
{
@@ -802,10 +816,10 @@ rl_read_key (void)
int
rl_getc (FILE *stream)
{
int result;
int result, ostate, osig;
unsigned char c;
int fd;
#if defined (HAVE_PSELECT)
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
sigset_t empty_set;
fd_set readfds;
#endif
@@ -813,12 +827,26 @@ rl_getc (FILE *stream)
fd = fileno (stream);
while (1)
{
osig = _rl_caught_signal;
ostate = rl_readline_state;
RL_CHECK_SIGNALS ();
#if defined (READLINE_CALLBACKS)
/* Do signal handling post-processing here, but just in callback mode
for right now because the signal cleanup can change some of the
callback state, and we need to either let the application have a
chance to react or abort some current operation that gets cleaned
up by rl_callback_sigcleanup(). If not, we'll just run through the
loop again. */
if (osig != 0 && (ostate & RL_STATE_CALLBACK))
goto postproc_signal;
#endif
/* We know at this point that _rl_caught_signal == 0 */
#if defined (__MINGW32__)
if (isatty (fd)
if (isatty (fd))
return (_getch ()); /* "There is no error return." */
#endif
result = 0;
@@ -878,6 +906,9 @@ rl_getc (FILE *stream)
/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
handle_error:
osig = _rl_caught_signal;
ostate = rl_readline_state;
/* If the error that we received was EINTR, then try again,
this is simply an interrupted system call to read (). We allow
the read to be interrupted if we caught SIGHUP, SIGTERM, or any
@@ -918,8 +949,17 @@ handle_error:
RL_CHECK_SIGNALS ();
#endif /* SIGALRM */
postproc_signal:
/* POSIX says read(2)/pselect(2)/select(2) don't return EINTR for any
reason other than being interrupted by a signal, so we can safely
call the application's signal event hook. */
if (rl_signal_event_hook)
(*rl_signal_event_hook) ();
#if defined (READLINE_CALLBACKS)
else if (osig == SIGINT && (ostate & RL_STATE_CALLBACK) && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG)))
/* just these cases for now */
_rl_abort_internal ();
#endif
}
}
+80 -12
View File
@@ -6,7 +6,7 @@
/* */
/* **************************************************************** */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2021,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.
@@ -59,6 +59,8 @@ char *_rl_isearch_terminators = (char *)NULL;
_rl_search_cxt *_rl_iscxt = 0;
int _rl_search_case_fold = 0;
static int rl_search_history (int, int);
static _rl_search_cxt *_rl_isearch_init (int);
@@ -150,7 +152,7 @@ static void
rl_display_search (char *search_string, int flags, int where)
{
char *message;
int msglen, searchlen;
size_t msglen, searchlen;
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
@@ -340,7 +342,7 @@ _rl_search_getchar (_rl_search_cxt *cxt)
int
_rl_isearch_dispatch (_rl_search_cxt *cxt, int c)
{
int n, wstart, wlen, limit, cval, incr;
int n, wstart, wlen, limit, cval;
char *paste;
size_t pastelen;
int j;
@@ -428,7 +430,11 @@ add_character:
{
f = cxt->keymap[c].function;
if (f == rl_do_lowercase_version)
f = cxt->keymap[_rl_to_lower (c)].function;
{
f = cxt->keymap[_rl_to_lower (c)].function;
if (f == rl_do_lowercase_version)
f = rl_insert;
}
}
if (f == rl_reverse_search_history)
@@ -445,6 +451,8 @@ add_character:
cxt->lastc = -6;
else if (f == rl_bracketed_paste_begin)
cxt->lastc = -7;
else if (c == CTRL('V') || f == rl_quoted_insert)
cxt->lastc = -8;
}
/* If we changed the keymap earlier while translating a key sequence into
@@ -463,6 +471,11 @@ add_character:
{
rl_stuff_char (cxt->lastc);
rl_execute_next (cxt->prevc);
/* We're going to read the last two characters again. */
_rl_del_executing_keyseq ();
_rl_del_executing_keyseq ();
/* XXX - do we insert everything in cxt->pmb? */
return (0);
}
@@ -477,6 +490,8 @@ add_character:
/* Make lastc be the next character read */
/* XXX - do we insert everything in cxt->mb? */
rl_execute_next (cxt->lastc);
_rl_del_executing_keyseq ();
/* Dispatch on the previous character (insert into search string) */
cxt->lastc = cxt->prevc;
#if defined (HANDLE_MULTIBYTE)
@@ -524,7 +539,10 @@ add_character:
settable keyboard timeout value, this could alternatively
use _rl_input_queued(100000) */
if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
rl_execute_next (ESC);
{
rl_execute_next (ESC);
_rl_del_executing_keyseq ();
}
return (0);
}
@@ -536,6 +554,7 @@ add_character:
/* This sets rl_pending_input to LASTC; it will be picked up the next
time rl_read_key is called. */
rl_execute_next (cxt->lastc);
_rl_del_executing_keyseq ();
return (0);
}
}
@@ -546,6 +565,7 @@ add_character:
/* This sets rl_pending_input to LASTC; it will be picked up the next
time rl_read_key is called. */
rl_execute_next (cxt->lastc);
_rl_del_executing_keyseq ();
return (0);
}
@@ -698,6 +718,27 @@ opcode_dispatch:
xfree (paste);
break;
case -8: /* quoted insert */
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_disable_tty_signals ();
#endif
c = _rl_search_getchar (cxt);
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_restore_tty_signals ();
#endif
if (c < 0)
{
cxt->sflags |= SF_FAILED;
cxt->history_pos = cxt->last_found_line;
return -1;
}
_rl_add_executing_keyseq (c);
/*FALLTHROUGH*/
/* Add character to search string and continue search. */
default:
#if defined (HANDLE_MULTIBYTE)
@@ -713,13 +754,13 @@ opcode_dispatch:
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
int j;
int w;
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
else
for (j = 0; j < wlen; )
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
for (w = 0; w < wlen; )
cxt->search_string[cxt->search_string_index++] = cxt->mb[w++];
}
else
#endif
@@ -741,7 +782,27 @@ opcode_dispatch:
/* Search the current line. */
while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
{
if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
int found;
if (_rl_search_case_fold)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
found = _rl_mb_strcaseeqn (cxt->search_string,
cxt->search_string_index,
cxt->sline + cxt->sline_index,
limit,
cxt->search_string_index, 0);
else
found = _rl_strnicmp (cxt->search_string,
cxt->sline + cxt->sline_index,
cxt->search_string_index) == 0;
#endif
}
else
found = STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index);
if (found)
{
cxt->sflags |= SF_FOUND;
break;
@@ -749,7 +810,7 @@ opcode_dispatch:
else
cxt->sline_index += cxt->direction;
if (cxt->sline_index < 0)
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
{
cxt->sline_index = 0;
break;
@@ -782,8 +843,8 @@ opcode_dispatch:
if (cxt->sflags & SF_FAILED)
{
/* XXX - reset sline_index if < 0 */
if (cxt->sline_index < 0)
/* XXX - reset sline_index if < 0 or longer than the history line */
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
cxt->sline_index = 0;
break;
}
@@ -885,6 +946,13 @@ _rl_isearch_callback (_rl_search_cxt *cxt)
int c, r;
c = _rl_search_getchar (cxt);
if (c < 0) /* EOF */
return 1;
if (RL_ISSTATE (RL_STATE_ISEARCH) == 0) /* signal could turn it off */
return 1;
/* We might want to handle EOF here */
r = _rl_isearch_dispatch (cxt, cxt->lastc);
+17 -15
View File
@@ -1,6 +1,6 @@
/* kill.c -- kill ring management. */
/* Copyright (C) 1994-2021 Free Software Foundation, Inc.
/* Copyright (C) 1994-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.
@@ -348,15 +348,15 @@ rl_unix_filename_rubout (int count, int key)
if (count <= 0)
count = 1;
while (count--)
while (rl_point > 0 && count--)
{
c = rl_line_buffer[rl_point - 1];
/* First move backwards through whitespace */
while (rl_point && whitespace (c))
{
rl_point--;
c = rl_line_buffer[rl_point - 1];
if (--rl_point)
c = rl_line_buffer[rl_point - 1];
}
/* Consume one or more slashes. */
@@ -377,14 +377,14 @@ rl_unix_filename_rubout (int count, int key)
while (rl_point && (whitespace (c) || c == '/'))
{
rl_point--;
c = rl_line_buffer[rl_point - 1];
if (--rl_point)
c = rl_line_buffer[rl_point - 1];
}
while (rl_point && (whitespace (c) == 0) && c != '/')
{
rl_point--; /* XXX - multibyte? */
c = rl_line_buffer[rl_point - 1];
if (--rl_point) /* XXX - multibyte? */
c = rl_line_buffer[rl_point - 1];
}
}
@@ -569,7 +569,7 @@ rl_vi_yank_pop (int count, int key)
}
l = strlen (rl_kill_ring[rl_kill_index]);
#if 0 /* TAG:readline-8.3 8/29/2022 matteopaolini1995@gmail.com */
#if 1
origpoint = rl_point;
n = rl_point - l + 1;
#else
@@ -577,7 +577,7 @@ rl_vi_yank_pop (int count, int key)
#endif
if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
{
#if 0 /* TAG:readline-8.3 */
#if 1
rl_delete_text (n, n + l); /* remember vi cursor positioning */
rl_point = origpoint - l;
#else
@@ -756,8 +756,8 @@ _rl_bracketed_text (size_t *lenp)
int
rl_bracketed_paste_begin (int count, int key)
{
int retval, c;
size_t len, cap;
int retval;
size_t len;
char *buf;
buf = _rl_bracketed_text (&len);
@@ -774,12 +774,12 @@ int
_rl_read_bracketed_paste_prefix (int c)
{
char pbuf[BRACK_PASTE_SLEN+1], *pbpref;
int key, ind, j;
int key, ind;
pbpref = BRACK_PASTE_PREF; /* XXX - debugging */
if (c != pbpref[0])
return (0);
pbuf[ind = 0] = c;
pbuf[ind = 0] = key = c;
while (ind < BRACK_PASTE_SLEN-1 &&
(RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
_rl_pushed_input_available () == 0 &&
@@ -846,7 +846,7 @@ _rl_bracketed_read_key ()
int
_rl_bracketed_read_mbstring (char *mb, int mlen)
{
int c, r;
int c;
c = _rl_bracketed_read_key ();
if (c < 0)
@@ -865,6 +865,8 @@ _rl_bracketed_read_mbstring (char *mb, int mlen)
/* A special paste command for Windows users. */
#if defined (_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int
+1 -1
View File
@@ -69,7 +69,7 @@ static int executing_macro_index;
static char *current_macro = (char *)NULL;
/* The size of the buffer allocated to current_macro. */
static int current_macro_size;
static size_t current_macro_size;
/* The index at which characters are being added to current_macro. */
static int current_macro_index;
+101 -20
View File
@@ -1,6 +1,6 @@
/* mbutil.c -- readline multibyte character utility functions */
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
/* Copyright (C) 2001-2021,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.
@@ -148,7 +148,7 @@ _rl_utf8_mblen (const char *s, size_t n)
}
static int
_rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_zero)
_rl_find_next_mbchar_internal (const char *string, int seed, int count, int find_non_zero)
{
size_t tmp, len;
mbstate_t ps;
@@ -216,11 +216,13 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
if (find_non_zero)
{
tmp = MBRTOWC (&wc, string + point, strlen (string + point), &ps);
len = strlen (string + point);
tmp = MBRTOWC (&wc, string + point, len, &ps);
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && WCWIDTH (wc) == 0)
{
point += tmp;
tmp = MBRTOWC (&wc, string + point, strlen (string + point), &ps);
len -= tmp;
tmp = MBRTOWC (&wc, string + point, len, &ps);
}
}
@@ -228,7 +230,7 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
}
static inline int
_rl_test_nonzero (char *string, int ind, int len)
_rl_test_nonzero (const char *string, int ind, int len)
{
size_t tmp;
WCHAR_T wc;
@@ -242,9 +244,8 @@ _rl_test_nonzero (char *string, int ind, int len)
/* experimental -- needs to handle zero-width characters better */
static int
_rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
_rl_find_prev_utf8char (const char *string, int seed, int find_non_zero)
{
char *s;
unsigned char b;
int save, prev;
size_t len;
@@ -262,11 +263,16 @@ _rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
save = prev;
/* Move back until we're not in the middle of a multibyte char */
#if 0
if (UTF8_MBCHAR (b))
{
while (prev > 0 && (b = (unsigned char)string[--prev]) && UTF8_MBCHAR (b))
;
}
#else
while (prev > 0 && (b = (unsigned char)string[--prev]) && UTF8_MBFIRSTCHAR (b) == 0)
;
#endif
if (UTF8_MBFIRSTCHAR (b))
{
@@ -288,7 +294,7 @@ _rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
}
/*static*/ int
_rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
_rl_find_prev_mbchar_internal (const char *string, int seed, int find_non_zero)
{
mbstate_t ps;
int prev, non_zero_prev, point, length;
@@ -356,19 +362,19 @@ _rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
if it couldn't parse a complete multibyte character. */
int
_rl_get_char_len (char *src, mbstate_t *ps)
_rl_get_char_len (const char *src, mbstate_t *ps)
{
size_t tmp, l;
int mb_cur_max;
/* Look at no more than MB_CUR_MAX characters */
l = (size_t)strlen (src);
if (_rl_utf8locale && l > 0 && UTF8_SINGLEBYTE(*src))
l = strlen (src);
if (_rl_utf8locale && l >= 0 && UTF8_SINGLEBYTE(*src))
tmp = (*src != 0) ? 1 : 0;
else
{
mb_cur_max = MB_CUR_MAX;
tmp = mbrlen((const char *)src, (l < mb_cur_max) ? l : mb_cur_max, ps);
tmp = mbrlen(src, (l < mb_cur_max) ? l : mb_cur_max, ps);
}
if (tmp == (size_t)(-2))
{
@@ -394,7 +400,7 @@ _rl_get_char_len (char *src, mbstate_t *ps)
/* compare the specified two characters. If the characters matched,
return 1. Otherwise return 0. */
int
_rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, mbstate_t *ps2)
_rl_compare_chars (const char *buf1, int pos1, mbstate_t *ps1, const char *buf2, int pos2, mbstate_t *ps2)
{
int i, w1, w2;
@@ -417,7 +423,7 @@ _rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, m
if point is invalid (point < 0 || more than string length),
it returns -1 */
int
_rl_adjust_point (char *string, int point, mbstate_t *ps)
_rl_adjust_point (const char *string, int point, mbstate_t *ps)
{
size_t tmp;
int length, pos;
@@ -457,7 +463,7 @@ _rl_adjust_point (char *string, int point, mbstate_t *ps)
}
int
_rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length)
_rl_is_mbchar_matched (const char *string, int seed, int end, char *mbchar, int length)
{
int i;
@@ -471,19 +477,19 @@ _rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length
}
WCHAR_T
_rl_char_value (char *buf, int ind)
_rl_char_value (const char *buf, int ind)
{
size_t tmp;
WCHAR_T wc;
mbstate_t ps;
int l;
size_t l;
if (MB_LEN_MAX == 1 || rl_byte_oriented)
return ((WCHAR_T) buf[ind]);
if (_rl_utf8locale && UTF8_SINGLEBYTE(buf[ind]))
return ((WCHAR_T) buf[ind]);
l = strlen (buf);
if (ind >= l - 1)
if (ind + 1 >= l)
return ((WCHAR_T) buf[ind]);
if (l < ind) /* Sanity check */
l = strlen (buf+ind);
@@ -500,7 +506,7 @@ _rl_char_value (char *buf, int ind)
characters. */
#undef _rl_find_next_mbchar
int
_rl_find_next_mbchar (char *string, int seed, int count, int flags)
_rl_find_next_mbchar (const char *string, int seed, int count, int flags)
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_next_mbchar_internal (string, seed, count, flags);
@@ -514,7 +520,7 @@ _rl_find_next_mbchar (char *string, int seed, int count, int flags)
we look for non-zero-width multibyte characters. */
#undef _rl_find_prev_mbchar
int
_rl_find_prev_mbchar (char *string, int seed, int flags)
_rl_find_prev_mbchar (const char *string, int seed, int flags)
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_prev_mbchar_internal (string, seed, flags);
@@ -522,3 +528,78 @@ _rl_find_prev_mbchar (char *string, int seed, int flags)
return ((seed == 0) ? seed : seed - 1);
#endif
}
/* Compare the first N characters of S1 and S2 without regard to case. If
FLAGS&1, apply the mapping specified by completion-map-case and make
`-' and `_' equivalent. Returns 1 if the strings are equal. */
int
_rl_mb_strcaseeqn (const char *s1, size_t l1, const char *s2, size_t l2, size_t n, int flags)
{
size_t v1, v2;
mbstate_t ps1, ps2;
WCHAR_T wc1, wc2;
memset (&ps1, 0, sizeof (mbstate_t));
memset (&ps2, 0, sizeof (mbstate_t));
do
{
v1 = MBRTOWC(&wc1, s1, l1, &ps1);
v2 = MBRTOWC(&wc2, s2, l2, &ps2);
if (v1 == 0 && v2 == 0)
return 1;
else if (MB_INVALIDCH(v1) || MB_INVALIDCH(v2))
{
int d;
d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* do byte comparison */
if ((flags & 1) && (*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
d = 0; /* case insensitive character mapping */
if (d != 0)
return 0;
s1++;
s2++;
n--;
continue;
}
wc1 = towlower(wc1);
wc2 = towlower(wc2);
s1 += v1;
s2 += v1;
n -= v1;
if ((flags & 1) && (wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
continue;
if (wc1 != wc2)
return 0;
}
while (n != 0);
return 1;
}
/* Return 1 if the multibyte characters pointed to by S1 and S2 are equal
without regard to case. If FLAGS&1, apply the mapping specified by
completion-map-case and make `-' and `_' equivalent. */
int
_rl_mb_charcasecmp (const char *s1, mbstate_t *ps1, const char *s2, mbstate_t *ps2, int flags)
{
int d;
size_t v1, v2;
wchar_t wc1, wc2;
d = MB_CUR_MAX;
v1 = MBRTOWC(&wc1, s1, d, ps1);
v2 = MBRTOWC(&wc2, s2, d, ps2);
if (v1 == 0 && v2 == 0)
return 1;
else if (MB_INVALIDCH(v1) || MB_INVALIDCH(v2))
{
if ((flags & 1) && (*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
return 1;
return (_rl_to_lower (*s1) == _rl_to_lower (*s2));
}
wc1 = towlower(wc1);
wc2 = towlower(wc2);
if ((flags & 1) && (wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
return 1;
return (wc1 == wc2);
}
+114 -63
View File
@@ -1,6 +1,6 @@
/* misc.c -- miscellaneous bindable readline functions. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -150,6 +150,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
if (_rl_digit_p (c))
{
_rl_add_executing_keyseq (key);
r = _rl_digit_value (c);
rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
rl_explicit_arg = 1;
@@ -157,6 +158,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
}
else if (c == '-' && rl_explicit_arg == 0)
{
_rl_add_executing_keyseq (key);
rl_numeric_arg = 1;
_rl_argcxt |= NUM_SAWMINUS;
rl_arg_sign = -1;
@@ -235,6 +237,7 @@ rl_digit_argument (int ignore, int key)
else
{
rl_execute_next (key);
_rl_del_executing_keyseq ();
return (rl_digit_loop ());
}
}
@@ -306,9 +309,11 @@ void
_rl_start_using_history (void)
{
using_history ();
if (_rl_saved_line_for_history)
_rl_free_saved_history_line ();
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
#if 1
if (_rl_saved_line_for_history && _rl_saved_line_for_history->data)
_rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
#endif
_rl_free_saved_history_line ();
_rl_history_search_pos = -99; /* some random invalid history position */
}
@@ -339,64 +344,83 @@ rl_maybe_replace_line (void)
xfree (temp->line);
FREE (temp->timestamp);
xfree (temp);
/* What about _rl_saved_line_for_history? if the saved undo list is
rl_undo_list, and we just put that into a history entry, should
we set the saved undo list to NULL? */
if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == rl_undo_list)
_rl_saved_line_for_history->data = 0;
/* Do we want to set rl_undo_list = 0 here since we just saved it into
a history entry? */
rl_undo_list = 0;
}
return 0;
}
void
_rl_unsave_line (HIST_ENTRY *entry)
{
/* Can't call with `1' because rl_undo_list might point to an undo
list from a history entry, as in rl_replace_from_history() below. */
rl_replace_line (entry->line, 0);
rl_undo_list = (UNDO_LIST *)entry->data;
/* Doesn't free `data'. */
_rl_free_history_entry (entry);
rl_point = rl_end; /* rl_replace_line sets rl_end */
}
/* Restore the _rl_saved_line_for_history if there is one. */
int
rl_maybe_unsave_line (void)
{
if (_rl_saved_line_for_history)
{
/* Can't call with `1' because rl_undo_list might point to an undo
list from a history entry, as in rl_replace_from_history() below. */
rl_replace_line (_rl_saved_line_for_history->line, 0);
rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
/* Doesn't free `data'. */
_rl_free_history_entry (_rl_saved_line_for_history);
_rl_unsave_line (_rl_saved_line_for_history);
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
rl_point = rl_end; /* rl_replace_line sets rl_end */
}
else
rl_ding ();
return 0;
}
HIST_ENTRY *
_rl_alloc_saved_line (void)
{
HIST_ENTRY *ret;
ret = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
ret->line = savestring (rl_line_buffer);
ret->timestamp = (char *)NULL;
ret->data = (char *)rl_undo_list;
return ret;
}
/* Save the current line in _rl_saved_line_for_history. */
int
rl_maybe_save_line (void)
{
if (_rl_saved_line_for_history == 0)
{
_rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
_rl_saved_line_for_history->line = savestring (rl_line_buffer);
_rl_saved_line_for_history->timestamp = (char *)NULL;
_rl_saved_line_for_history->data = (char *)rl_undo_list;
}
_rl_saved_line_for_history = _rl_alloc_saved_line ();
return 0;
}
/* Just a wrapper, any self-respecting compiler will inline it. */
void
_rl_free_saved_line (HIST_ENTRY *entry)
{
_rl_free_history_entry (entry);
}
int
_rl_free_saved_history_line (void)
{
UNDO_LIST *orig;
_rl_free_saved_line (_rl_saved_line_for_history);
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
if (_rl_saved_line_for_history)
{
if (rl_undo_list && rl_undo_list == (UNDO_LIST *)_rl_saved_line_for_history->data)
rl_undo_list = 0;
/* Have to free this separately because _rl_free_history entry can't:
it doesn't know whether or not this has application data. Only the
callers that know this is _rl_saved_line_for_history can know that
it's an undo list. */
if (_rl_saved_line_for_history->data)
_rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
_rl_free_history_entry (_rl_saved_line_for_history);
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
}
return 0;
}
@@ -554,20 +578,11 @@ rl_end_of_history (int count, int key)
return 0;
}
/* Move down to the next history line. */
int
rl_get_next_history (int count, int key)
_rl_next_history_internal (int count)
{
HIST_ENTRY *temp;
if (count < 0)
return (rl_get_previous_history (-count, key));
if (count == 0)
return 0;
rl_maybe_replace_line ();
/* either not saved by rl_newline or at end of line, so set appropriately. */
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
@@ -582,41 +597,48 @@ rl_get_next_history (int count, int key)
}
if (temp == 0)
rl_maybe_unsave_line ();
return 0;
else
{
rl_replace_from_history (temp, 0);
_rl_history_set_point ();
return 1;
}
}
/* Move down to the next history line. */
int
rl_get_next_history (int count, int key)
{
int r;
if (count < 0)
return (rl_get_previous_history (-count, key));
if (count == 0)
return 0;
rl_maybe_replace_line ();
r = _rl_next_history_internal (count);
if (r == 0)
rl_maybe_unsave_line ();
return 0;
}
/* Get the previous item out of our interactive history, making it the current
line. If there is no previous history, just ding. */
int
rl_get_previous_history (int count, int key)
_rl_previous_history_internal (int count)
{
HIST_ENTRY *old_temp, *temp;
int had_saved_line;
if (count < 0)
return (rl_get_next_history (-count, key));
if (count == 0 || history_list () == 0)
return 0;
temp = old_temp = (HIST_ENTRY *)NULL;
/* either not saved by rl_newline or at end of line, so set appropriately. */
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
/* If we don't have a line saved, then save this one. */
had_saved_line = _rl_saved_line_for_history != 0;
rl_maybe_save_line ();
/* If the current line has changed, save the changes. */
rl_maybe_replace_line ();
temp = old_temp = (HIST_ENTRY *)NULL;
while (count)
{
temp = previous_history ();
@@ -634,15 +656,41 @@ rl_get_previous_history (int count, int key)
if (temp == 0)
{
if (had_saved_line == 0)
_rl_free_saved_history_line ();
rl_ding ();
return 0;
}
else
{
rl_replace_from_history (temp, 0);
_rl_history_set_point ();
return 1;
}
}
/* Get the previous item out of our interactive history, making it the current
line. If there is no previous history, just ding. */
int
rl_get_previous_history (int count, int key)
{
int had_saved_line, r;
if (count < 0)
return (rl_get_next_history (-count, key));
if (count == 0 || history_list () == 0)
return 0;
/* If we don't have a line saved, then save this one. */
had_saved_line = _rl_saved_line_for_history != 0;
rl_maybe_save_line ();
/* If the current line has changed, save the changes. */
rl_maybe_replace_line ();
r = _rl_previous_history_internal (count);
if (r == 0 && had_saved_line == 0) /* failed to find previous history */
_rl_free_saved_history_line ();
return 0;
}
@@ -693,7 +741,7 @@ static int saved_history_logical_offset = -1;
#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
static int
set_saved_history ()
set_saved_history (void)
{
int absolute_offset, count;
@@ -762,7 +810,10 @@ _rl_set_insert_mode (int im, int force)
_rl_set_cursor (im, force);
#endif
RL_UNSETSTATE (RL_STATE_OVERWRITE);
rl_insert_mode = im;
if (rl_insert_mode == RL_IM_OVERWRITE)
RL_SETSTATE (RL_STATE_OVERWRITE);
}
/* Toggle overwrite mode. A positive explicit argument selects overwrite
+1 -4
View File
@@ -38,6 +38,7 @@
# include <unistd.h>
#endif
#include "rlstdc.h"
#include "posixselect.h"
#if defined (HAVE_STRING_H)
@@ -46,10 +47,6 @@
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
#endif /* !strchr && !__STDC__ */
#include "readline.h"
#include "rlprivate.h"
+36 -9
View File
@@ -297,6 +297,22 @@ get_funky_string (char **dest, const char **src, bool equals_end, size_t *output
}
#endif /* COLOR_SUPPORT */
static void
free_color_ext_list (void)
{
COLOR_EXT_TYPE *e;
COLOR_EXT_TYPE *e2;
for (e = _rl_color_ext_list; e != NULL; /* empty */)
{
e2 = e;
e = e->next;
free (e2);
}
_rl_color_ext_list = 0;
}
void _rl_parse_colors(void)
{
#if defined (COLOR_SUPPORT)
@@ -420,21 +436,32 @@ void _rl_parse_colors(void)
if (state < 0)
{
COLOR_EXT_TYPE *e;
COLOR_EXT_TYPE *e2;
_rl_errmsg ("unparsable value for LS_COLORS environment variable");
free (color_buf);
for (e = _rl_color_ext_list; e != NULL; /* empty */)
{
e2 = e;
e = e->next;
free (e2);
}
_rl_color_ext_list = NULL;
free_color_ext_list ();
_rl_colored_stats = 0; /* can't have colored stats without colors */
_rl_colored_completion_prefix = 0; /* or colored prefixes */
}
#else /* !COLOR_SUPPORT */
;
#endif /* !COLOR_SUPPORT */
}
void
rl_reparse_colors (void)
{
char *v;
v = sh_get_env_value ("LS_COLORS");
if (v == 0 && color_buf == 0)
return; /* no change */
if (v && color_buf && STREQ (v, color_buf))
return; /* no change */
free (color_buf);
free_color_ext_list ();
_rl_parse_colors ();
}
+2 -2
View File
@@ -21,13 +21,13 @@
#ifndef _POSIXSELECT_H_
#define _POSIXSELECT_H_
#if defined (FD_SET) && !defined (HAVE_SELECT)
#if defined (FD_SET) && !defined (HAVE_SELECT) && !defined (_WIN32)
# define HAVE_SELECT 1
#endif
#if defined (HAVE_SELECT)
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
# include <sys/time.h>
# include "posixtime.h"
# endif
#endif /* HAVE_SELECT */
#if defined (HAVE_SYS_SELECT_H)
+11 -2
View File
@@ -1,6 +1,6 @@
/* posixtime.h -- wrapper for time.h, sys/times.h mess. */
/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -49,9 +49,18 @@ struct timeval
#endif
#if !HAVE_GETTIMEOFDAY
extern int gettimeofday PARAMS((struct timeval *, void *));
extern int gettimeofday (struct timeval * restrict, void * restrict);
#endif
/* consistently use gettimeofday for time information */
static inline time_t
getnow(void)
{
struct timeval now;
gettimeofday (&now, 0);
return now.tv_sec;
}
/* These exist on BSD systems, at least. */
#if !defined (timerclear)
# define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0)
+42 -18
View File
@@ -1,7 +1,7 @@
/* readline.c -- a general facility for reading lines of input
with emacs style editing and completion. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -262,7 +262,7 @@ _rl_keyseq_cxt *_rl_kscxt = 0;
int rl_executing_key;
char *rl_executing_keyseq = 0;
int _rl_executing_keyseq_size = 0;
size_t _rl_executing_keyseq_size = 0;
struct _rl_cmd _rl_pending_command;
struct _rl_cmd *_rl_command_to_execute = (struct _rl_cmd *)NULL;
@@ -474,17 +474,12 @@ readline_internal_setup (void)
RL_CHECK_SIGNALS ();
}
STATIC_CALLBACK char *
readline_internal_teardown (int eof)
STATIC_CALLBACK void
readline_common_teardown (void)
{
char *temp;
HIST_ENTRY *entry;
RL_CHECK_SIGNALS ();
if (eof)
RL_SETSTATE (RL_STATE_EOF); /* XXX */
/* Restore the original of this history line, iff the line that we
are editing was originally in the history, AND the line has changed. */
entry = current_history ();
@@ -510,6 +505,17 @@ readline_internal_teardown (int eof)
rid of it now. */
if (rl_undo_list)
rl_free_undo_list ();
}
STATIC_CALLBACK char *
readline_internal_teardown (int eof)
{
RL_CHECK_SIGNALS ();
if (eof)
RL_SETSTATE (RL_STATE_EOF); /* XXX */
readline_common_teardown ();
/* Disable the meta key, if this terminal has one and we were told to use it.
The check whether or not we sent the enable string is in
@@ -566,6 +572,7 @@ readline_internal_charloop (void)
{
static int lastc, eof_found;
int c, code, lk, r;
static procenv_t olevel;
lastc = EOF;
@@ -576,6 +583,9 @@ readline_internal_charloop (void)
#endif
lk = _rl_last_command_was_kill;
/* Save and restore _rl_top_level even though most of the time it
doesn't matter. */
memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
#if defined (HAVE_POSIX_SIGSETJMP)
code = sigsetjmp (_rl_top_level, 0);
#else
@@ -586,13 +596,14 @@ readline_internal_charloop (void)
{
(*rl_redisplay_function) ();
_rl_want_redisplay = 0;
if (RL_ISSTATE (RL_STATE_CALLBACK))
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
/* If we longjmped because of a timeout, handle it here. */
if (RL_ISSTATE (RL_STATE_TIMEOUT))
{
RL_SETSTATE (RL_STATE_DONE);
rl_done = 1;
return 1;
return (rl_done = 1);
}
/* If we get here, we're not being called from something dispatched
@@ -703,6 +714,7 @@ readline_internal_charloop (void)
_rl_internal_char_cleanup ();
#if defined (READLINE_CALLBACKS)
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
return 0;
#else
}
@@ -899,8 +911,17 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
{
/* Special case rl_do_lowercase_version (). */
if (func == rl_do_lowercase_version)
/* Should we do anything special if key == ANYOTHERKEY? */
return (_rl_dispatch (_rl_to_lower ((unsigned char)key), map));
{
/* Should we do anything special if key == ANYOTHERKEY? */
newkey = _rl_to_lower ((unsigned char)key);
if (newkey != key)
return (_rl_dispatch (newkey, map));
else
{
rl_ding (); /* gentle failure */
return 0;
}
}
rl_executing_keymap = map;
rl_executing_key = key;
@@ -1109,7 +1130,11 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq)
type = m[ANYOTHERKEY].type;
func = m[ANYOTHERKEY].function;
if (type == ISFUNC && func == rl_do_lowercase_version)
r = _rl_dispatch (_rl_to_lower ((unsigned char)key), map);
{
int newkey = _rl_to_lower ((unsigned char)key);
/* check that there is actually a lowercase version to avoid infinite recursion */
r = (newkey != key) ? _rl_dispatch (newkey, map) : 1;
}
else if (type == ISFUNC)
{
/* If we shadowed a function, whatever it is, we somehow need a
@@ -1322,9 +1347,8 @@ readline_initialize_everything (void)
_rl_parse_colors ();
#endif
rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
if (rl_executing_keyseq)
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
rl_executing_keyseq = xmalloc (_rl_executing_keyseq_size = 16);
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
}
/* If this system allows us to look at the values of the regular
@@ -1562,7 +1586,7 @@ void
_rl_add_executing_keyseq (int key)
{
RESIZE_KEYSEQ_BUFFER ();
rl_executing_keyseq[rl_key_sequence_length++] = key;
rl_executing_keyseq[rl_key_sequence_length++] = key;
}
/* `delete' the last character added to the executing key sequence. Use this
+63 -38
View File
@@ -1,6 +1,6 @@
/* Readline.h -- the names of functions callable from within readline. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -39,9 +39,9 @@ extern "C" {
#endif
/* Hex-encoded Readline version number. */
#define RL_READLINE_VERSION 0x0802 /* Readline 8.2 */
#define RL_READLINE_VERSION 0x0803 /* Readline 8.3 */
#define RL_VERSION_MAJOR 8
#define RL_VERSION_MINOR 2
#define RL_VERSION_MINOR 3
/* Readline data structures. */
@@ -209,6 +209,8 @@ extern int rl_stop_output (int, int);
extern int rl_abort (int, int);
extern int rl_tty_status (int, int);
extern int rl_execute_named_command (int, int);
/* Bindable commands for incremental and non-incremental history searching. */
extern int rl_history_search_forward (int, int);
extern int rl_history_search_backward (int, int);
@@ -341,7 +343,9 @@ extern int rl_trim_arg_from_keyseq (const char *, size_t, Keymap);
extern void rl_list_funmap_names (void);
extern char **rl_invoking_keyseqs_in_map (rl_command_func_t *, Keymap);
extern char **rl_invoking_keyseqs (rl_command_func_t *);
extern void rl_print_keybinding (const char *, Keymap, int);
extern void rl_function_dumper (int);
extern void rl_macro_dumper (int);
extern void rl_variable_dumper (int);
@@ -404,11 +408,7 @@ extern void rl_activate_mark (void);
extern void rl_deactivate_mark (void);
extern int rl_mark_active_p (void);
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
#else
extern int rl_message ();
#endif
extern int rl_show_char (int);
@@ -441,6 +441,7 @@ extern void rl_get_screen_size (int *, int *);
extern void rl_reset_screen_size (void);
extern char *rl_get_termcap (const char *);
extern void rl_reparse_colors (void);
/* Functions for character input. */
extern int rl_stuff_char (int);
@@ -627,6 +628,8 @@ extern rl_voidfunc_t *rl_redisplay_function;
extern rl_vintfunc_t *rl_prep_term_function;
extern rl_voidfunc_t *rl_deprep_term_function;
extern rl_macro_print_func_t *rl_macro_display_hook;
/* Dispatch variables. */
extern Keymap rl_executing_keymap;
extern Keymap rl_binding_keymap;
@@ -770,6 +773,19 @@ extern rl_icppfunc_t *rl_filename_stat_hook;
converted. */
extern rl_dequote_func_t *rl_filename_rewrite_hook;
/* If non-zero, this is the address of a function to call before
comparing the filename portion of a word to be completed with directory
entries from the filesystem. This takes the address of the partial word
to be completed, after any rl_filename_dequoting_function has been applied.
The function should either return its first argument (if no conversion
takes place) or newly-allocated memory. This can, for instance, convert
the filename portion of the completion word to a character set suitable
for comparison against directory entries read from the filesystem (after
their potential modification by rl_filename_rewrite_hook).
The returned value is what is added to the list of matches.
The second argument is the length of the filename to be converted. */
extern rl_dequote_func_t *rl_completion_rewrite_hook;
/* Backwards compatibility with previous versions of readline. */
#define rl_symbolic_link_hook rl_directory_completion_hook
@@ -794,6 +810,12 @@ extern int rl_filename_completion_desired;
entry finder function. */
extern int rl_filename_quoting_desired;
/* Non-zero means we should apply filename-type quoting to all completions
even if we are not otherwise treating the matches as filenames. This is
ALWAYS zero on entry, and can only be changed within a completion entry
finder function. */
extern int rl_full_quoting_desired;
/* Set to a function to quote a filename in an application-specific fashion.
Called with the text to quote, the type of match found (single or multiple)
and a pointer to the quoting character to be used, which the function can
@@ -892,37 +914,40 @@ extern int rl_persistent_signal_handlers;
#define MULT_MATCH 2
/* Possible state values for rl_readline_state */
#define RL_STATE_NONE 0x000000 /* no state; before first call */
#define RL_STATE_NONE 0x0000000 /* no state; before first call */
#define RL_STATE_INITIALIZING 0x0000001 /* initializing */
#define RL_STATE_INITIALIZED 0x0000002 /* initialization done */
#define RL_STATE_TERMPREPPED 0x0000004 /* terminal is prepped */
#define RL_STATE_READCMD 0x0000008 /* reading a command key */
#define RL_STATE_METANEXT 0x0000010 /* reading input after ESC */
#define RL_STATE_DISPATCHING 0x0000020 /* dispatching to a command */
#define RL_STATE_MOREINPUT 0x0000040 /* reading more input in a command function */
#define RL_STATE_ISEARCH 0x0000080 /* doing incremental search */
#define RL_STATE_NSEARCH 0x0000100 /* doing non-inc search */
#define RL_STATE_SEARCH 0x0000200 /* doing a history search */
#define RL_STATE_NUMERICARG 0x0000400 /* reading numeric argument */
#define RL_STATE_MACROINPUT 0x0000800 /* getting input from a macro */
#define RL_STATE_MACRODEF 0x0001000 /* defining keyboard macro */
#define RL_STATE_OVERWRITE 0x0002000 /* overwrite mode */
#define RL_STATE_COMPLETING 0x0004000 /* doing completion */
#define RL_STATE_SIGHANDLER 0x0008000 /* in readline sighandler */
#define RL_STATE_UNDOING 0x0010000 /* doing an undo */
#define RL_STATE_INPUTPENDING 0x0020000 /* rl_execute_next called */
#define RL_STATE_TTYCSAVED 0x0040000 /* tty special chars saved */
#define RL_STATE_CALLBACK 0x0080000 /* using the callback interface */
#define RL_STATE_VIMOTION 0x0100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x0200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x0400000 /* entered vi command mode at least once */
#define RL_STATE_CHARSEARCH 0x0800000 /* vi mode char search */
#define RL_STATE_REDISPLAYING 0x1000000 /* updating terminal display */
#define RL_STATE_INITIALIZING 0x00000001 /* initializing */
#define RL_STATE_INITIALIZED 0x00000002 /* initialization done */
#define RL_STATE_TERMPREPPED 0x00000004 /* terminal is prepped */
#define RL_STATE_READCMD 0x00000008 /* reading a command key */
#define RL_STATE_METANEXT 0x00000010 /* reading input after ESC */
#define RL_STATE_DISPATCHING 0x00000020 /* dispatching to a command */
#define RL_STATE_MOREINPUT 0x00000040 /* reading more input in a command function */
#define RL_STATE_ISEARCH 0x00000080 /* doing incremental search */
#define RL_STATE_NSEARCH 0x00000100 /* doing non-inc search */
#define RL_STATE_SEARCH 0x00000200 /* doing a history search */
#define RL_STATE_NUMERICARG 0x00000400 /* reading numeric argument */
#define RL_STATE_MACROINPUT 0x00000800 /* getting input from a macro */
#define RL_STATE_MACRODEF 0x00001000 /* defining keyboard macro */
#define RL_STATE_OVERWRITE 0x00002000 /* overwrite mode */
#define RL_STATE_COMPLETING 0x00004000 /* doing completion */
#define RL_STATE_SIGHANDLER 0x00008000 /* in readline sighandler */
#define RL_STATE_UNDOING 0x00010000 /* doing an undo */
#define RL_STATE_INPUTPENDING 0x00020000 /* rl_execute_next called */
#define RL_STATE_TTYCSAVED 0x00040000 /* tty special chars saved */
#define RL_STATE_CALLBACK 0x00080000 /* using the callback interface */
#define RL_STATE_VIMOTION 0x00100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x00200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x00400000 /* entered vi command mode at least once */
#define RL_STATE_CHARSEARCH 0x00800000 /* vi mode char search */
#define RL_STATE_REDISPLAYING 0x01000000 /* updating terminal display */
#define RL_STATE_DONE 0x2000000 /* done; accepted line */
#define RL_STATE_TIMEOUT 0x4000000 /* done; timed out */
#define RL_STATE_EOF 0x8000000 /* done; got eof on read */
#define RL_STATE_DONE 0x02000000 /* done; accepted line */
#define RL_STATE_TIMEOUT 0x04000000 /* done; timed out */
#define RL_STATE_EOF 0x08000000 /* done; got eof on read */
/* Rearrange these for next major version */
#define RL_STATE_READSTR 0x10000000 /* reading a string for M-x */
#define RL_SETSTATE(x) (rl_readline_state |= (x))
#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
@@ -939,7 +964,7 @@ struct readline_state {
char *prompt;
/* global state */
int rlstate;
int rlstate; /* XXX -- needs to be unsigned long */
int done;
Keymap kmap;
+5
View File
@@ -76,4 +76,9 @@
#define RL_VI_CMD_MODESTR_DEFAULT "(cmd)"
#define RL_VI_CMD_MODESTR_DEFLEN 5
/* Do you want readline to assume it's running in an ANSI-compatible terminal
by default? If set to 0, readline tries to check and verify whether or not
it is. */
#define RL_ANSI_TERM_DEFAULT 1 /* for now */
#endif /* _RLCONF_H_ */
+3 -13
View File
@@ -40,7 +40,7 @@
# if defined (HAVE_TERMIO_H)
# define TERMIO_TTY_DRIVER
# else
# if !defined (__MINGW32__)
# if !defined (__MINGW32__) && !defined (_MSC_VER)
# define NEW_TTY_DRIVER
# else
# define NO_TTY_DRIVER
@@ -63,17 +63,7 @@
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
#endif /* !strchr && !__STDC__ */
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# if defined (PREFER_VARARGS)
# include <varargs.h>
# endif
#endif
#include <stdarg.h>
#if defined (HAVE_STRCASECMP)
#define _rl_stricmp strcasecmp
@@ -83,7 +73,7 @@ extern int _rl_stricmp (const char *, const char *);
extern int _rl_strnicmp (const char *, const char *, int);
#endif
#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
#if defined (HAVE_STRPBRK) && !defined (HANDLE_MULTIBYTE)
# define _rl_strpbrk(a,b) strpbrk((a),(b))
#else
extern char *_rl_strpbrk (const char *, const char *);
+21 -11
View File
@@ -1,6 +1,6 @@
/* rlmbutil.h -- utility functions for multibyte characters. */
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
/* Copyright (C) 2001-2021,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.
@@ -104,23 +104,26 @@
#define MB_FIND_ANY 0x00
#define MB_FIND_NONZERO 0x01
extern int _rl_find_prev_mbchar (char *, int, int);
extern int _rl_find_next_mbchar (char *, int, int, int);
extern int _rl_find_prev_mbchar (const char *, int, int);
extern int _rl_find_next_mbchar (const char *, int, int, int);
#ifdef HANDLE_MULTIBYTE
extern int _rl_compare_chars (char *, int, mbstate_t *, char *, int, mbstate_t *);
extern int _rl_get_char_len (char *, mbstate_t *);
extern int _rl_adjust_point (char *, int, mbstate_t *);
extern int _rl_compare_chars (const char *, int, mbstate_t *, const char *, int, mbstate_t *);
extern int _rl_get_char_len (const char *, mbstate_t *);
extern int _rl_adjust_point (const char *, int, mbstate_t *);
extern int _rl_read_mbchar (char *, int);
extern int _rl_read_mbstring (int, char *, int);
extern int _rl_is_mbchar_matched (char *, int, int, char *, int);
extern int _rl_is_mbchar_matched (const char *, int, int, char *, int);
extern WCHAR_T _rl_char_value (char *, int);
extern WCHAR_T _rl_char_value (const char *, int);
extern int _rl_walphabetic (WCHAR_T);
extern int _rl_mb_strcaseeqn (const char *, size_t, const char *, size_t, size_t, int);
extern int _rl_mb_charcasecmp (const char *, mbstate_t *, const char *, mbstate_t *, int);
#define _rl_to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc))
#define _rl_to_wlower(wc) (iswupper (wc) ? towlower (wc) : (wc))
@@ -169,11 +172,16 @@ _rl_wcwidth (WCHAR_T wc)
}
}
/* Unicode combining characters range from U+0300 to U+036F */
#define UNICODE_COMBINING_CHAR(x) ((x) >= 768 && (x) <= 879)
/* Unicode combining characters as of version 15.1 */
#define UNICODE_COMBINING_CHAR(x) \
(((x) >= 0x0300 && (x) <= 0x036F) || \
((x) >= 0x1AB0 && (x) <= 0x1AFF) || \
((x) >= 0x1DC0 && (x) <= 0x1DFF) || \
((x) >= 0x20D0 && (x) <= 0x20FF) || \
((x) >= 0xFE20 && (x) <= 0xFE2F))
#if defined (WCWIDTH_BROKEN)
# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR(wc)) ? 0 : _rl_wcwidth(wc))
# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR((int)wc)) ? 0 : _rl_wcwidth(wc))
#else
# define WCWIDTH(wc) _rl_wcwidth(wc)
#endif
@@ -184,6 +192,8 @@ _rl_wcwidth (WCHAR_T wc)
# define IS_COMBINING_CHAR(x) (WCWIDTH(x) == 0)
#endif
#define IS_BASE_CHAR(x) (iswgraph(x) && WCWIDTH(x) > 0)
#define UTF8_SINGLEBYTE(c) (((c) & 0x80) == 0)
#define UTF8_MBFIRSTCHAR(c) (((c) & 0xc0) == 0xc0)
#define UTF8_MBCHAR(c) (((c) & 0xc0) == 0x80)
+69 -9
View File
@@ -1,7 +1,7 @@
/* rlprivate.h -- functions and variables global to the readline library,
but not intended for use by applications. */
/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
/* Copyright (C) 1999-2024 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.
@@ -67,6 +67,7 @@
#define SF_CHGKMAP 0x08
#define SF_PATTERN 0x10
#define SF_NOCASE 0x20 /* unused so far */
#define SF_FREEPMT 0x40 /* saved prompt separately, need to free it */
typedef struct __rl_search_context
{
@@ -110,6 +111,28 @@ typedef struct __rl_search_context
char *search_terminators;
} _rl_search_cxt;
/* readstr flags */
#define READSTR_NOSPACE 0x01 /* don't insert space, use for completion */
#define READSTR_FREEPMT 0x02 /* called rl_save_prompt, need to free it ourselves */
typedef struct __rl_readstr_context
{
int flags;
int prevc;
int lastc;
#if defined (HANDLE_MULTIBYTE)
char mb[MB_LEN_MAX];
char pmb[MB_LEN_MAX];
#endif
int save_point;
int save_mark;
int save_line;
int (*compfunc) (struct __rl_readstr_context *, int);
} _rl_readstr_cxt;
struct _rl_cmd {
Keymap map;
int count;
@@ -247,10 +270,11 @@ extern char *_rl_savestring (const char *);
* Undocumented private functions *
*************************************************************************/
#if defined(READLINE_CALLBACKS)
#if defined (READLINE_CALLBACKS)
/* readline.c */
extern void readline_internal_setup (void);
extern void readline_common_teardown (void);
extern char *readline_internal_teardown (int);
extern int readline_internal_char (void);
@@ -303,8 +327,22 @@ extern int _rl_pushed_input_available (void);
extern int _rl_timeout_init (void);
extern int _rl_timeout_handle_sigalrm (void);
#if defined (_POSIXSELECT_H_)
/* use as a sentinel for fd_set, struct timeval, and sigset_t definitions */
#if defined (__MINGW32__)
# define RL_TIMEOUT_USE_SIGALRM
#elif defined (HAVE_SELECT) || defined (HAVE_PSELECT)
# define RL_TIMEOUT_USE_SELECT
#elif defined (_MSC_VER)
/* can't use select/pselect or SIGALRM, so no timeouts */
#else
# define RL_TIMEOUT_USE_SIGALRM
#endif
#endif
#if defined (RL_TIMEOUT_USE_SELECT)
extern int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *);
#endif
@@ -355,7 +393,13 @@ extern int _rl_arg_callback (_rl_arg_cxt);
extern void _rl_reset_argument (void);
extern void _rl_start_using_history (void);
#if defined (HIST_ENTRY_DEFINED)
extern HIST_ENTRY *_rl_alloc_saved_line (void);
extern void _rl_free_saved_line (HIST_ENTRY *);
extern void _rl_unsave_line (HIST_ENTRY *);
#endif
extern int _rl_free_saved_history_line (void);
extern void _rl_set_insert_mode (int, int);
extern void _rl_revert_previous_lines (void);
@@ -391,6 +435,9 @@ extern int _rl_restore_tty_signals (void);
/* search.c */
extern int _rl_nsearch_callback (_rl_search_cxt *);
extern int _rl_nsearch_cleanup (_rl_search_cxt *, int);
extern int _rl_nsearch_sigcleanup (_rl_search_cxt *, int);
extern void _rl_free_saved_search_line (void);
/* signals.c */
extern void _rl_signal_handler (int);
@@ -400,6 +447,8 @@ extern void _rl_release_sigint (void);
extern void _rl_block_sigwinch (void);
extern void _rl_release_sigwinch (void);
extern void _rl_state_sigcleanup (void);
/* terminal.c */
extern void _rl_get_screen_size (int, int);
extern void _rl_sigwinch_resize_terminal (void);
@@ -439,21 +488,26 @@ extern int _rl_char_search_internal (int, int, int);
#endif
extern int _rl_set_mark_at_pos (int);
extern _rl_readstr_cxt *_rl_rscxt_alloc (int);
extern void _rl_rscxt_dispose (_rl_readstr_cxt *, int);
extern void _rl_free_saved_readstr_line (void);
extern void _rl_unsave_saved_readstr_line (void);
extern _rl_readstr_cxt *_rl_readstr_init (int, int);
extern int _rl_readstr_cleanup (_rl_readstr_cxt *, int);
extern int _rl_readstr_sigcleanup (_rl_readstr_cxt *, int);
extern void _rl_readstr_restore (_rl_readstr_cxt *);
extern int _rl_readstr_getchar (_rl_readstr_cxt *);
extern int _rl_readstr_dispatch (_rl_readstr_cxt *, int);
/* undo.c */
extern UNDO_LIST *_rl_copy_undo_entry (UNDO_LIST *);
extern UNDO_LIST *_rl_copy_undo_list (UNDO_LIST *);
extern void _rl_free_undo_list (UNDO_LIST *);
/* util.c */
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
extern void _rl_ttymsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
extern void _rl_errmsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
extern void _rl_trace (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
#else
extern void _rl_ttymsg ();
extern void _rl_errmsg ();
extern void _rl_trace ();
#endif
extern void _rl_audit_tty (char *);
extern int _rl_tropen (void);
@@ -461,6 +515,8 @@ extern int _rl_tropen (void);
extern int _rl_abort_internal (void);
extern int _rl_null_function (int, int);
extern char *_rl_strindex (const char *, const char *);
extern int _rl_strcaseeqn (const char *, const char *, size_t, int);
extern int _rl_charcasecmp (int, int, int);
extern int _rl_qsort_string_compare (char **, char **);
extern int (_rl_uppercase_p) (int);
extern int (_rl_lowercase_p) (int);
@@ -516,6 +572,7 @@ extern int _rl_menu_complete_prefix_first;
/* display.c */
extern int _rl_vis_botlin;
extern int _rl_last_c_pos;
extern int _rl_last_v_pos;
extern int _rl_suppress_redisplay;
extern int _rl_want_redisplay;
@@ -530,6 +587,7 @@ extern int _rl_vi_cmd_modestr_len;
extern char *_rl_isearch_terminators;
extern _rl_search_cxt *_rl_iscxt;
extern int _rl_search_case_fold;
/* macro.c */
extern char *_rl_executing_macro;
@@ -570,7 +628,7 @@ extern procenv_t _rl_top_level;
extern _rl_keyseq_cxt *_rl_kscxt;
extern int _rl_keyseq_timeout;
extern int _rl_executing_keyseq_size;
extern size_t _rl_executing_keyseq_size;
extern rl_hook_func_t *_rl_internal_startup_hook;
@@ -615,6 +673,8 @@ extern int _rl_term_autowrap;
extern int _rl_optimize_typeahead;
extern int _rl_keep_mark_active;
extern _rl_readstr_cxt *_rl_rscxt;
/* undo.c */
extern int _rl_doing_an_undo;
extern int _rl_undo_group_level;
+1 -13
View File
@@ -1,6 +1,6 @@
/* stdc.h -- macros to make source compile on both ANSI C and K&R C compilers. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
/* Copyright (C) 1993-2009,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.
@@ -42,16 +42,4 @@
# endif
#endif
/* Moved from config.h.in because readline.h:rl_message depends on these
defines. */
#if defined (__STDC__) && defined (HAVE_STDARG_H)
# define PREFER_STDARG
# define USE_VARARGS
#else
# if defined (HAVE_VARARGS_H)
# define PREFER_VARARGS
# define USE_VARARGS
# endif
#endif
#endif /* !_RL_STDC_H_ */
+18 -17
View File
@@ -1,7 +1,7 @@
/* rltty.c -- functions to prepare and restore the terminal for readline's
use. */
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
/* Copyright (C) 1992-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.
@@ -49,6 +49,8 @@
extern int errno;
#endif /* !errno */
int _rl_use_tty_xon_xoff = 1;
rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
@@ -80,8 +82,7 @@ static int ksrflow;
/* Dummy call to force a backgrounded readline to stop before it tries
to get the tty settings. */
static void
set_winsize (tty)
int tty;
set_winsize (int tty)
{
#if defined (TIOCGWINSZ)
struct winsize w;
@@ -276,15 +277,16 @@ prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop)
}
#if defined (TIOCGETC)
# if defined (USE_XON_XOFF)
/* Get rid of terminal output start and stop characters. */
tiop->tchars.t_stopc = -1; /* C-s */
tiop->tchars.t_startc = -1; /* C-q */
if (_rl_use_tty_xon_xoff == 0)
{
/* Get rid of terminal output start and stop characters. */
tiop->tchars.t_stopc = -1; /* C-s */
tiop->tchars.t_startc = -1; /* C-q */
/* If there is an XON character, bind it to restart the output. */
if (oldtio.tchars.t_startc != -1)
rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
# endif /* USE_XON_XOFF */
/* If there is an XON character, bind it to restart the output. */
if (oldtio.tchars.t_startc != -1)
rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
}
/* If there is an EOF char, bind _rl_eof_char to it. */
if (oldtio.tchars.t_eofc != -1)
@@ -515,14 +517,13 @@ prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop)
if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
_rl_eof_char = oldtio.c_cc[VEOF];
#if defined (USE_XON_XOFF)
if (_rl_use_tty_xon_xoff == 0)
#if defined (IXANY)
tiop->c_iflag &= ~(IXON | IXANY);
tiop->c_iflag &= ~(IXON | IXANY);
#else
/* `strict' Posix systems do not define IXANY. */
tiop->c_iflag &= ~IXON;
/* `strict' Posix systems do not define IXANY. */
tiop->c_iflag &= ~IXON;
#endif /* IXANY */
#endif /* USE_XON_XOFF */
/* Only turn this off if we are using all 8 bits. */
if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
@@ -729,7 +730,7 @@ rl_tty_set_echoing (int u)
_rl_echoing_p = u;
return o;
}
/* **************************************************************** */
/* */
/* Bogus Flow Control */
+6 -10
View File
@@ -1,6 +1,6 @@
/* rltypedefs.h -- Type declarations for readline functions. */
/* Copyright (C) 2000-2021 Free Software Foundation, Inc.
/* Copyright (C) 2000-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.
@@ -28,22 +28,15 @@ extern "C" {
/* Old-style, attempt to mark as deprecated in some way people will notice. */
#if !defined (_FUNCTION_DEF)
#if !defined (_FUNCTION_DEF) && defined (WANT_OBSOLETE_TYPEDEFS)
# define _FUNCTION_DEF
#if defined(__GNUC__) || defined(__clang__)
typedef int Function () __attribute__((deprecated));
typedef void VFunction () __attribute__((deprecated));
typedef char *CPFunction () __attribute__((deprecated));
typedef char **CPPFunction () __attribute__((deprecated));
#else
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction ();
typedef char **CPPFunction ();
#endif
#endif /* _FUNCTION_DEF */
#endif /* _FUNCTION_DEF && WANT_OBSOLETE_TYPEDEFS */
/* New style. */
@@ -64,6 +57,9 @@ typedef int rl_compignore_func_t (char **);
typedef void rl_compdisp_func_t (char **, int, int);
/* Functions for displaying key bindings. Currently only one. */
typedef void rl_macro_print_func_t (const char *, const char *, int, const char *);
/* Type for input and pre-read hook functions like rl_event_hook */
typedef int rl_hook_func_t (void);
+124 -49
View File
@@ -1,6 +1,6 @@
/* search.c - code for non-incremental searching in emacs and vi modes. */
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
/* Copyright (C) 1992-2024 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.
@@ -55,6 +55,8 @@
_rl_search_cxt *_rl_nscxt = 0;
static HIST_ENTRY *_rl_saved_line_for_search;
static char *noninc_search_string = (char *) NULL;
static int noninc_history_pos;
@@ -65,7 +67,7 @@ static int _rl_history_search_len;
static int _rl_history_search_flags;
static char *history_search_string;
static int history_string_size;
static size_t history_string_size;
static void make_history_line_current (HIST_ENTRY *);
static int noninc_search_from_pos (char *, int, int, int, int *);
@@ -78,21 +80,57 @@ static _rl_search_cxt *_rl_nsearch_init (int, int);
static void _rl_nsearch_abort (_rl_search_cxt *);
static int _rl_nsearch_dispatch (_rl_search_cxt *, int);
void
_rl_free_saved_search_line (void)
{
if (_rl_saved_line_for_search)
_rl_free_saved_line (_rl_saved_line_for_search);
_rl_saved_line_for_search = (HIST_ENTRY *)NULL;
}
static inline void
_rl_unsave_saved_search_line (void)
{
if (_rl_saved_line_for_search)
_rl_unsave_line (_rl_saved_line_for_search);
_rl_saved_line_for_search = (HIST_ENTRY *)NULL;
}
/* We're going to replace the undo list with the one created by inserting
the matching line we found, so we want to free rl_undo_list if it's not
from a history entry. We assume the undo list does not come from a
history entry if we are at the end of the history, entering a new line.
The call to rl_maybe_replace_line() has already ensured that any undo
list pointing to a history entry has already been saved back to the
history and set rl_undo_list to NULL. */
static void
dispose_saved_search_line (void)
{
UNDO_LIST *xlist;
if (_hs_at_end_of_history () == 0)
_rl_unsave_saved_search_line ();
else if (_rl_saved_line_for_search)
{
xlist = _rl_saved_line_for_search ? (UNDO_LIST *)_rl_saved_line_for_search->data : 0;
if (xlist)
_rl_free_undo_list (xlist);
_rl_saved_line_for_search->data = 0;
_rl_free_saved_search_line ();
}
}
/* Make the data from the history entry ENTRY be the contents of the
current line. This doesn't do anything with rl_point; the caller
must set it. */
static void
make_history_line_current (HIST_ENTRY *entry)
{
UNDO_LIST *xlist;
xlist = _rl_saved_line_for_history ? (UNDO_LIST *)_rl_saved_line_for_history->data : 0;
/* At this point, rl_undo_list points to a private search string list. */
if (rl_undo_list && rl_undo_list != (UNDO_LIST *)entry->data && rl_undo_list != xlist)
rl_free_undo_list ();
/* Now we create a new undo list with a single insert for this text.
WE DON'T CHANGE THE ORIGINAL HISTORY ENTRY UNDO LIST */
rl_undo_list = 0; /* XXX */
_rl_replace_text (entry->line, 0, rl_end);
_rl_fix_point (1);
#if defined (VI_MODE)
@@ -103,15 +141,6 @@ make_history_line_current (HIST_ENTRY *entry)
current editing buffer. */
rl_free_undo_list ();
#endif
/* This will need to free the saved undo list associated with the original
(pre-search) line buffer.
XXX - look at _rl_free_saved_history_line and consider calling it if
rl_undo_list != xlist (or calling rl_free_undo list directly on
_rl_saved_line_for_history->data) */
if (_rl_saved_line_for_history)
_rl_free_history_entry (_rl_saved_line_for_history);
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
}
/* Search the history list for STRING starting at absolute history position
@@ -135,21 +164,23 @@ noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
RL_SETSTATE(RL_STATE_SEARCH);
/* These functions return the match offset in the line; history_offset gives
the matching line in the history list */
if (flags & SF_PATTERN)
sflags = 0; /* Non-anchored search */
s = string;
if (*s == '^')
{
s = string;
sflags = 0; /* Non-anchored search */
if (*s == '^')
{
sflags |= ANCHORED_SEARCH;
s++;
}
ret = _hs_history_patsearch (s, dir, sflags);
sflags |= ANCHORED_SEARCH;
s++;
}
else if (*string == '^')
ret = history_search_prefix (string + 1, dir);
if (flags & SF_PATTERN)
ret = _hs_history_patsearch (s, dir, sflags);
else
ret = history_search (string, dir);
{
if (_rl_search_case_fold)
sflags |= CASEFOLD_SEARCH;
ret = _hs_history_search (s, dir, sflags);
}
RL_UNSETSTATE(RL_STATE_SEARCH);
if (ncp)
@@ -181,7 +212,7 @@ noninc_dosearch (char *string, int dir, int flags)
if (pos == -1)
{
/* Search failed, current history position unchanged. */
rl_maybe_unsave_line ();
_rl_unsave_saved_search_line ();
rl_clear_message ();
rl_point = 0;
rl_ding ();
@@ -190,6 +221,10 @@ noninc_dosearch (char *string, int dir, int flags)
noninc_history_pos = pos;
/* We're committed to making the line we found the current contents of
rl_line_buffer. We can dispose of _rl_saved_line_for_search. */
dispose_saved_search_line ();
oldpos = where_history ();
history_set_pos (noninc_history_pos);
entry = current_history (); /* will never be NULL after successful search */
@@ -201,7 +236,7 @@ noninc_dosearch (char *string, int dir, int flags)
make_history_line_current (entry);
if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end)
if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind >= 0 && ind < rl_end)
{
rl_point = ind;
rl_mark = ind + strlen (string);
@@ -236,7 +271,10 @@ _rl_nsearch_init (int dir, int pchar)
cxt->direction = dir;
cxt->history_pos = cxt->save_line;
rl_maybe_save_line ();
/* If the current line has changed, put it back into the history if necessary. */
rl_maybe_replace_line ();
_rl_saved_line_for_search = _rl_alloc_saved_line ();
/* Clear the undo list, since reading the search string should create its
own undo list, and the whole list will end up being freed when we
@@ -248,6 +286,7 @@ _rl_nsearch_init (int dir, int pchar)
rl_end = rl_point = 0;
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
cxt->sflags |= SF_FREEPMT;
rl_message ("%s", p);
xfree (p);
@@ -272,16 +311,27 @@ _rl_nsearch_cleanup (_rl_search_cxt *cxt, int r)
static void
_rl_nsearch_abort (_rl_search_cxt *cxt)
{
rl_maybe_unsave_line ();
_rl_unsave_saved_search_line ();
rl_point = cxt->save_point;
rl_mark = cxt->save_mark;
rl_restore_prompt ();
if (cxt->sflags & SF_FREEPMT)
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
cxt->sflags &= ~SF_FREEPMT;
rl_clear_message ();
_rl_fix_point (1);
RL_UNSETSTATE (RL_STATE_NSEARCH);
}
int
_rl_nsearch_sigcleanup (_rl_search_cxt *cxt, int r)
{
if (cxt->sflags & SF_FREEPMT)
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
cxt->sflags &= ~SF_FREEPMT;
return (_rl_nsearch_cleanup (cxt, r));
}
/* Process just-read character C according to search context CXT. Return -1
if the caller should abort the search, 0 if we should break out of the
loop, and 1 if we should continue to read characters. */
@@ -303,6 +353,17 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
rl_unix_line_discard (1, c);
break;
case CTRL('Q'):
case CTRL('V'):
n = rl_quoted_insert (1, c);
if (n < 0)
{
_rl_nsearch_abort (cxt);
return -1;
}
cxt->lastc = (rl_point > 0) ? rl_line_buffer[rl_point - 1] : rl_line_buffer[0];
break;
case RETURN:
case NEWLINE:
return 0;
@@ -376,8 +437,11 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
{
if (noninc_search_string == 0)
{
_rl_free_saved_search_line ();
rl_ding ();
rl_restore_prompt ();
if (cxt->sflags & SF_FREEPMT)
rl_restore_prompt ();
cxt->sflags &= ~SF_FREEPMT;
RL_UNSETSTATE (RL_STATE_NSEARCH);
return -1;
}
@@ -389,15 +453,22 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
FREE (noninc_search_string);
noninc_search_string = savestring (rl_line_buffer);
/* If we don't want the subsequent undo list generated by the search
/* We don't want the subsequent undo list generated by the search
matching a history line to include the contents of the search string,
we need to clear rl_line_buffer here. For now, we just clear the
undo list generated by reading the search string. (If the search
fails, the old undo list will be restored by rl_maybe_unsave_line.) */
so we need to clear rl_line_buffer here. If we don't want that,
change the #if 1 to an #if 0 below. We clear the undo list
generated by reading the search string. (If the search fails, the
old undo list will be restored by _rl_unsave_line.) */
rl_free_undo_list ();
#if 1
rl_line_buffer[rl_point = rl_end = 0] = '\0';
#endif
}
rl_restore_prompt ();
if (cxt->sflags & SF_FREEPMT)
rl_restore_prompt ();
cxt->sflags &= ~SF_FREEPMT;
return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
}
@@ -530,11 +601,12 @@ rl_history_search_internal (int count, int dir)
{
HIST_ENTRY *temp;
int ret, oldpos, newcol;
int had_saved_line;
char *t;
had_saved_line = _rl_saved_line_for_history != 0;
rl_maybe_save_line ();
/* If the current line has changed, put it back into the history if necessary. */
rl_maybe_replace_line ();
_rl_saved_line_for_search = _rl_alloc_saved_line ();
temp = (HIST_ENTRY *)NULL;
/* Search COUNT times through the history for a line matching
@@ -566,8 +638,7 @@ rl_history_search_internal (int count, int dir)
/* If we didn't find anything at all, return. */
if (temp == 0)
{
/* XXX - check had_saved_line here? */
rl_maybe_unsave_line ();
_rl_unsave_saved_search_line ();
rl_ding ();
/* If you don't want the saved history line (last match) to show up
in the line buffer after the search fails, change the #if 0 to
@@ -580,12 +651,16 @@ rl_history_search_internal (int count, int dir)
rl_mark = 0;
}
#else
rl_point = _rl_history_search_len; /* rl_maybe_unsave_line changes it */
rl_point = _rl_history_search_len; /* _rl_unsave_line changes it */
rl_mark = rl_end;
#endif
return 1;
}
/* We're committed to making the line we found the current contents of
rl_line_buffer. We can dispose of _rl_saved_line_for_search. */
dispose_saved_search_line ();
/* Copy the line we found into the current line buffer. */
make_history_line_current (temp);
@@ -619,7 +694,7 @@ rl_history_search_reinit (int flags)
if (rl_point)
{
/* Allocate enough space for anchored and non-anchored searches */
if (_rl_history_search_len >= history_string_size - 2)
if (_rl_history_search_len + 2 >= history_string_size)
{
history_string_size = _rl_history_search_len + 2;
history_search_string = (char *)xrealloc (history_search_string, history_string_size);
@@ -630,7 +705,7 @@ rl_history_search_reinit (int flags)
strncpy (history_search_string + sind, rl_line_buffer, rl_point);
history_search_string[rl_point + sind] = '\0';
}
_rl_free_saved_history_line (); /* XXX rl_undo_list? */
_rl_free_saved_search_line ();
}
/* Search forward in the history for the string of characters
-4
View File
@@ -67,10 +67,6 @@
extern struct passwd *getpwuid (uid_t);
#endif /* HAVE_GETPWUID && !HAVE_GETPW_DECLS */
#ifndef NULL
# define NULL 0
#endif
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
+20 -2
View File
@@ -1,6 +1,6 @@
/* signals.c -- signal handling support for readline. */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2024 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.
@@ -267,6 +267,9 @@ _rl_handle_signal (int sig)
sigprocmask (SIG_BLOCK, &set, &oset);
#endif
#if defined (READLINE_CALLBACKS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0 || rl_persistent_signal_handlers)
#endif
rl_echo_signal_char (sig);
rl_cleanup_after_signal ();
@@ -582,6 +585,19 @@ rl_reset_after_signal (void)
rl_set_signals ();
}
/* Similar to rl_callback_sigcleanup, but cleans up operations that allocate
state even when not in callback mode. */
void
_rl_state_sigcleanup (void)
{
if (RL_ISSTATE (RL_STATE_ISEARCH)) /* incremental search */
_rl_isearch_cleanup (_rl_iscxt, 0);
else if (RL_ISSTATE (RL_STATE_NSEARCH)) /* non-incremental search */
_rl_nsearch_sigcleanup (_rl_nscxt, 0);
else if (RL_ISSTATE (RL_STATE_READSTR)) /* reading a string */
_rl_readstr_sigcleanup (_rl_rscxt, 0);
}
/* Free up the readline variable line state for the current line (undo list,
any partial history entry, any keyboard macros in progress, and any
numeric arguments in process) after catching a signal, before calling
@@ -591,6 +607,9 @@ rl_free_line_state (void)
{
register HIST_ENTRY *entry;
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_state_sigcleanup ();
rl_free_undo_list ();
entry = current_history ();
@@ -622,7 +641,6 @@ rl_check_signals (void)
/* **************************************************************** */
#if defined (HAVE_POSIX_SIGNALS)
static sigset_t sigint_set, sigint_oset;
static sigset_t sigwinch_set, sigwinch_oset;
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
+7 -7
View File
@@ -1,6 +1,6 @@
/* tcap.h -- termcap library functions and variables. */
/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
/* Copyright (C) 1996-2015,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.
@@ -46,14 +46,14 @@ extern char *UP, *BC;
extern short ospeed;
extern int tgetent ();
extern int tgetflag ();
extern int tgetnum ();
extern char *tgetstr ();
extern int tgetent (char *, const char *);
extern int tgetflag (const char *);
extern int tgetnum (const char *);
extern char *tgetstr (const char *, char **);
extern int tputs ();
extern int tputs (const char *, int, int (*)(int));
extern char *tgoto ();
extern char *tgoto (const char *, int, int);
#endif /* HAVE_TERMCAP_H */
+92 -7
View File
@@ -1,6 +1,6 @@
/* terminal.c -- controlling the terminal with termcap. */
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
/* Copyright (C) 1996-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.
@@ -69,7 +69,7 @@
#include "rlshell.h"
#include "xmalloc.h"
#if defined (__MINGW32__)
#if defined (_WIN32)
# include <windows.h>
# include <wincon.h>
@@ -113,6 +113,7 @@ char PC, *BC, *UP;
char *_rl_term_clreol;
char *_rl_term_clrpag;
char *_rl_term_clrscroll;
char *_rl_term_ho;
char *_rl_term_cr;
char *_rl_term_backspace;
char *_rl_term_goto;
@@ -185,6 +186,12 @@ static char *_rl_term_kN;
static char *_rl_term_vs; /* very visible */
static char *_rl_term_ve; /* normal */
/* Bracketed paste */
static char *_rl_term_BE; /* enable */
static char *_rl_term_BD; /* disable */
static char *_rl_term_PS; /* paste start */
static char *_rl_term_PE; /* paste end */
/* User-settable color sequences to begin and end the active region. Defaults
are rl_term_so and rl_term_se on non-dumb terminals. */
char *_rl_active_region_start_color = NULL;
@@ -214,6 +221,9 @@ int _rl_enable_keypad;
/* Non-zero means the user wants to enable a meta key. */
int _rl_enable_meta = 1;
/* Non-zero means this is an ANSI-compatible terminal; assume it is. */
int _rl_term_isansi = RL_ANSI_TERM_DEFAULT;
#if defined (__EMX__)
static void
_emx_get_screensize (int *swp, int *shp)
@@ -229,7 +239,7 @@ _emx_get_screensize (int *swp, int *shp)
}
#endif
#if defined (__MINGW32__)
#if defined (_WIN32)
static void
_win_get_screensize (int *swp, int *shp)
{
@@ -272,7 +282,7 @@ _rl_get_screen_size (int tty, int ignore_env)
#if defined (__EMX__)
_emx_get_screensize (&wc, &wr);
#elif defined (__MINGW32__)
#elif defined (_WIN32) && !defined (__CYGWIN__)
_win_get_screensize (&wc, &wr);
#endif
@@ -415,14 +425,19 @@ struct _tc_string {
static const struct _tc_string tc_strings[] =
{
{ "@7", &_rl_term_at7 },
{ "BD", &_rl_term_BD },
{ "BE", &_rl_term_BE },
{ "DC", &_rl_term_DC },
{ "E3", &_rl_term_clrscroll },
{ "IC", &_rl_term_IC },
{ "PE", &_rl_term_PE },
{ "PS", &_rl_term_PS },
{ "ce", &_rl_term_clreol },
{ "cl", &_rl_term_clrpag },
{ "cr", &_rl_term_cr },
{ "dc", &_rl_term_dc },
{ "ei", &_rl_term_ei },
{ "ho", &_rl_term_ho },
{ "ic", &_rl_term_ic },
{ "im", &_rl_term_im },
{ "kD", &_rl_term_kD }, /* delete */
@@ -466,6 +481,63 @@ get_term_capabilities (char **bp)
tcap_initialized = 1;
}
struct _term_name {
const char * const name;
size_t len;
};
/* Non-exhaustive list of ANSI/ECMA terminals. */
static const struct _term_name ansiterms[] =
{
{ "xterm", 5 },
{ "rxvt", 4 },
{ "eterm", 5 },
{ "screen", 6 },
{ "tmux", 4 },
{ "vt100", 5 },
{ "vt102", 5 },
{ "vt220", 5 },
{ "vt320", 5 },
{ "ansi", 4 },
{ "scoansi", 7 },
{ "cygwin", 6 },
{ "linux", 5 },
{ "konsole", 7 },
{ "bvterm", 6 },
{ 0, 0 }
};
static inline int
iscsi (const char *s)
{
return ((s[0] == ESC && s[1] == '[') ? 2
: ((unsigned char)s[0] == 0x9b) ? 1 : 0);
}
static int
_rl_check_ansi_terminal (const char *terminal_name)
{
int i;
size_t len;
for (i = 0; ansiterms[i].name; i++)
if (STREQN (terminal_name, ansiterms[i].name, ansiterms[i].len))
return 1;
if (_rl_term_clreol == 0 || _rl_term_forward_char == 0 ||
_rl_term_ho == 0 || _rl_term_up == 0)
return 0;
/* check some common capabilities */
if (((len = iscsi (_rl_term_clreol)) && _rl_term_clreol[len] == 'K') && /* ce */
((len = iscsi (_rl_term_forward_char)) && _rl_term_forward_char[len] == 'C') && /* nd */
((len = iscsi (_rl_term_ho)) && _rl_term_ho[len] == 'H') && /* ho */
((len = iscsi (_rl_term_up)) && _rl_term_up[len] == 'A')) /* up */
return 1;
return 0;
}
int
_rl_init_terminal_io (const char *terminal_name)
{
@@ -480,7 +552,10 @@ _rl_init_terminal_io (const char *terminal_name)
if (term == 0)
term = "dumb";
dumbterm = STREQ (term, "dumb");
_rl_term_isansi = RL_ANSI_TERM_DEFAULT;
dumbterm = STREQ (term, "dumb") || STREQ (term, "vt52") || STREQ (term, "adm3a");
if (dumbterm)
_rl_term_isansi = 0;
reset_region_colors = 1;
@@ -492,11 +567,13 @@ _rl_init_terminal_io (const char *terminal_name)
_rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
_rl_term_cr = "\r";
_rl_term_backspace = (char *)NULL;
_rl_term_ho = (char *)NULL;
_rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL;
_rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL;
_rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL;
_rl_term_kN = _rl_term_kP = (char *)NULL;
_rl_term_so = _rl_term_se = (char *)NULL;
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
#if defined(HACK_TERMCAP_MOTION)
_rl_term_forward_char = (char *)NULL;
#endif
@@ -553,6 +630,7 @@ _rl_init_terminal_io (const char *terminal_name)
/* Everything below here is used by the redisplay code (tputs). */
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
_rl_term_cr = "\r";
_rl_term_ho = (char *)NULL;
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
@@ -565,8 +643,11 @@ _rl_init_terminal_io (const char *terminal_name)
_rl_term_so = _rl_term_se = (char *)NULL;
_rl_terminal_can_insert = term_has_meta = 0;
_rl_term_isansi = 0; /* not an ANSI terminal */
/* Assume generic unknown terminal can't handle the enable/disable
escape sequences */
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
_rl_enable_bracketed_paste = 0;
/* No terminal so/se capabilities. */
@@ -625,9 +706,13 @@ _rl_init_terminal_io (const char *terminal_name)
bind_termcap_arrow_keys (vi_insertion_keymap);
#endif /* VI_MODE */
if (dumbterm == 0 && _rl_term_isansi == 0)
_rl_term_isansi = _rl_check_ansi_terminal (terminal_name);
/* There's no way to determine whether or not a given terminal supports
bracketed paste mode, so we assume a terminal named "dumb" does not. */
if (dumbterm)
bracketed paste mode, so we assume a non-ANSI terminal (as best as we
can determine) does not. */
if (_rl_term_isansi == 0)
_rl_enable_bracketed_paste = _rl_enable_active_region = 0;
if (reset_region_colors)
+510 -18
View File
@@ -1,6 +1,6 @@
/* text.c -- text handling commands for readline. */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2021,2023-2024 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.
@@ -85,7 +85,8 @@ int _rl_optimize_typeahead = 1; /* rl_insert tries to read typeahead */
int
rl_insert_text (const char *string)
{
register int i, l;
register int i;
size_t l;
l = (string && *string) ? strlen (string) : 0;
if (l == 0)
@@ -704,7 +705,11 @@ static mbstate_t ps = {0};
/* Insert the character C at the current location, moving point forward.
If C introduces a multibyte sequence, we read the whole sequence and
then insert the multibyte char into the line buffer. */
then insert the multibyte char into the line buffer.
If C == 0, we immediately insert any pending partial multibyte character,
assuming that we have read a character that doesn't map to self-insert.
This doesn't completely handle characters that are part of a multibyte
character but map to editing functions. */
int
_rl_insert_char (int count, int c)
{
@@ -718,11 +723,28 @@ _rl_insert_char (int count, int c)
static int stored_count = 0;
#endif
#if !defined (HANDLE_MULTIBYTE)
if (count <= 0)
return 0;
#else
if (count < 0)
return 0;
if (count == 0)
{
if (pending_bytes_length == 0)
return 0;
if (stored_count <= 0)
stored_count = count;
else
count = stored_count;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX == 1 || rl_byte_oriented)
memcpy (incoming, pending_bytes, pending_bytes_length);
incoming[pending_bytes_length] = '\0';
incoming_length = pending_bytes_length;
pending_bytes_length = 0;
memset (&ps, 0, sizeof (mbstate_t));
}
else if (MB_CUR_MAX == 1 || rl_byte_oriented)
{
incoming[0] = c;
incoming[1] = '\0';
@@ -730,6 +752,9 @@ _rl_insert_char (int count, int c)
}
else if (_rl_utf8locale && (c & 0x80) == 0)
{
if (pending_bytes_length)
_rl_insert_char (0, 0);
incoming[0] = c;
incoming[1] = '\0';
incoming_length = 1;
@@ -764,7 +789,8 @@ _rl_insert_char (int count, int c)
incoming[1] = '\0';
incoming_length = 1;
pending_bytes_length--;
memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
if (pending_bytes_length)
memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
/* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
@@ -827,7 +853,11 @@ _rl_insert_char (int count, int c)
rl_insert_text (string);
xfree (string);
#if defined (HANDLE_MULTIBYTE)
return (pending_bytes_length != 0);
#else
return 0;
#endif
}
if (count > TEXT_COUNT_MAX)
@@ -860,6 +890,8 @@ _rl_insert_char (int count, int c)
xfree (string);
incoming_length = 0;
stored_count = 0;
return (pending_bytes_length != 0);
#else /* !HANDLE_MULTIBYTE */
char str[TEXT_COUNT_MAX+1];
@@ -873,9 +905,9 @@ _rl_insert_char (int count, int c)
rl_insert_text (str);
count -= decreaser;
}
#endif /* !HANDLE_MULTIBYTE */
return 0;
#endif /* !HANDLE_MULTIBYTE */
}
if (MB_CUR_MAX == 1 || rl_byte_oriented)
@@ -903,9 +935,11 @@ _rl_insert_char (int count, int c)
rl_insert_text (incoming);
stored_count = 0;
}
#endif
return (pending_bytes_length != 0);
#else
return 0;
#endif
}
/* Overwrite the character at point (or next COUNT characters) with C.
@@ -983,6 +1017,11 @@ rl_insert (int count, int c)
break;
}
/* If we didn't insert n and there are pending bytes, we need to insert
them if _rl_insert_char didn't do that on its own. */
if (r == 1 && rl_insert_mode == RL_IM_INSERT)
r = _rl_insert_char (0, 0); /* flush partial multibyte char */
if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
{
/* setting rl_pending_input inhibits setting rl_last_func so we do it
@@ -992,7 +1031,6 @@ rl_insert (int count, int c)
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
r = rl_execute_next (n);
}
return r;
}
@@ -1054,6 +1092,8 @@ _rl_insert_next_callback (_rl_callback_generic_arg *data)
int
rl_quoted_insert (int count, int key)
{
int r;
/* Let's see...should the callback interface futz with signal handling? */
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
@@ -1072,15 +1112,17 @@ rl_quoted_insert (int count, int key)
/* A negative count means to quote the next -COUNT characters. */
if (count < 0)
{
int r;
do
r = _rl_insert_next (1);
while (r == 0 && ++count < 0);
return r;
}
else
r = _rl_insert_next (count);
return _rl_insert_next (count);
if (r == 1)
_rl_insert_char (0, 0); /* insert partial multibyte character */
return r;
}
/* Insert a tab character. */
@@ -1229,11 +1271,12 @@ _rl_rubout_char (int count, int key)
c = rl_line_buffer[--rl_point];
rl_delete_text (rl_point, orig_point);
/* The erase-at-end-of-line hack is of questionable merit now. */
if (rl_point == rl_end && ISPRINT ((unsigned char)c) && _rl_last_c_pos)
if (rl_point == rl_end && ISPRINT ((unsigned char)c) && _rl_last_c_pos && _rl_last_v_pos == 0)
{
int l;
l = rl_character_len (c, rl_point);
_rl_erase_at_end_of_line (l);
if (_rl_last_c_pos >= l)
_rl_erase_at_end_of_line (l);
}
}
else
@@ -1764,8 +1807,7 @@ _rl_char_search (int count, int fdir, int bdir)
#if defined (READLINE_CALLBACKS)
static int
_rl_char_search_callback (data)
_rl_callback_generic_arg *data;
_rl_char_search_callback (_rl_callback_generic_arg *data)
{
_rl_callback_func = 0;
_rl_want_redisplay = 1;
@@ -1886,3 +1928,453 @@ rl_mark_active_p (void)
{
return (mark_active);
}
/* **************************************************************** */
/* */
/* Reading a string entered from the keyboard */
/* */
/* **************************************************************** */
/* A very simple set of functions to read a string from the keyboard using
the line buffer as temporary storage. The caller can set a completion
function to perform completion on TAB and SPACE. */
/* XXX - this is all very similar to the search stuff but with a different
CXT. */
static HIST_ENTRY *_rl_saved_line_for_readstr;
_rl_readstr_cxt *_rl_rscxt;
_rl_readstr_cxt *
_rl_rscxt_alloc (int flags)
{
_rl_readstr_cxt *cxt;
cxt = (_rl_readstr_cxt *)xmalloc (sizeof (_rl_readstr_cxt));
cxt->flags = flags;
cxt->save_point = rl_point;
cxt->save_mark = rl_mark;
cxt->save_line = where_history ();
cxt->prevc = cxt->lastc = 0;
cxt->compfunc = NULL;
return cxt;
}
void
_rl_rscxt_dispose (_rl_readstr_cxt *cxt, int flags)
{
xfree (cxt);
}
/* This isn't used yet */
void
_rl_free_saved_readstr_line ()
{
if (_rl_saved_line_for_readstr)
/* This doesn't free any saved undo list, if it needs to,
rl_clear_history shows how to do it. */
_rl_free_saved_line (_rl_saved_line_for_readstr);
_rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
}
void
_rl_unsave_saved_readstr_line ()
{
if (_rl_saved_line_for_readstr)
{
_rl_free_undo_list (rl_undo_list);
_rl_unsave_line (_rl_saved_line_for_readstr); /* restores rl_undo_list */
}
_rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
}
_rl_readstr_cxt *
_rl_readstr_init (int pchar, int flags)
{
_rl_readstr_cxt *cxt;
char *p;
cxt = _rl_rscxt_alloc (flags);
rl_maybe_replace_line ();
_rl_saved_line_for_readstr = _rl_alloc_saved_line ();
rl_undo_list = 0;
rl_line_buffer[0] = 0;
rl_end = rl_point = 0;
p = _rl_make_prompt_for_search (pchar ? pchar : '@');
cxt->flags |= READSTR_FREEPMT;
rl_message ("%s", p);
xfree (p);
RL_SETSTATE (RL_STATE_READSTR);
_rl_rscxt = cxt;
return cxt;
}
int
_rl_readstr_cleanup (_rl_readstr_cxt *cxt, int r)
{
_rl_rscxt_dispose (cxt, 0);
_rl_rscxt = 0;
RL_UNSETSTATE (RL_STATE_READSTR);
return (r != 1);
}
void
_rl_readstr_restore (_rl_readstr_cxt *cxt)
{
_rl_unsave_saved_readstr_line (); /* restores rl_undo_list */
rl_point = cxt->save_point;
rl_mark = cxt->save_mark;
if (cxt->flags & READSTR_FREEPMT)
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
cxt->flags &= ~READSTR_FREEPMT;
rl_clear_message ();
_rl_fix_point (1);
}
int
_rl_readstr_sigcleanup (_rl_readstr_cxt *cxt, int r)
{
if (cxt->flags & READSTR_FREEPMT)
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
cxt->flags &= ~READSTR_FREEPMT;
return (_rl_readstr_cleanup (cxt, r));
}
int
_rl_readstr_getchar (_rl_readstr_cxt *cxt)
{
int c;
cxt->prevc = cxt->lastc;
/* Read a key and decide how to proceed. */
RL_SETSTATE(RL_STATE_MOREINPUT);
c = cxt->lastc = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#if defined (HANDLE_MULTIBYTE)
/* This ends up with C (and LASTC) being set to the last byte of the
multibyte character. In most cases c == lastc == mb[0] */
if (c >= 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
#endif
RL_CHECK_SIGNALS ();
return c;
}
/* Process just-read character C according to readstr context CXT. Return -1
if the caller should abort the read, 0 if we should break out of the
loop, and 1 if we should continue to read characters. This can perform
completion on the string read so far (stored in rl_line_buffer) if the
caller has set up a completion function. The completion function can
return -1 to indicate that we should abort the read. If we return -1
we will call _rl_readstr_restore to clean up the state, leaving the caller
to free the context. */
int
_rl_readstr_dispatch (_rl_readstr_cxt *cxt, int c)
{
int n;
if (c < 0)
c = CTRL ('C');
/* could consider looking up the function bound to they key and dispatching
off that, but you want most characters inserted by default without having
to quote. */
switch (c)
{
case CTRL('W'):
rl_unix_word_rubout (1, c);
break;
case CTRL('U'):
rl_unix_line_discard (1, c);
break;
case CTRL('Q'):
case CTRL('V'):
n = rl_quoted_insert (1, c);
if (n < 0)
{
_rl_readstr_restore (cxt);
return -1;
}
cxt->lastc = (rl_point > 0) ? rl_line_buffer[rl_point - 1] : rl_line_buffer[0]; /* preserve prevc */
break;
case RETURN:
case NEWLINE:
return 0;
case CTRL('H'):
case RUBOUT:
if (rl_point == 0)
{
_rl_readstr_restore (cxt);
return -1;
}
_rl_rubout_char (1, c);
break;
case CTRL('C'):
case CTRL('G'):
rl_ding ();
_rl_readstr_restore (cxt);
return -1;
case ESC:
/* Allow users to bracketed-paste text into the string.
Similar code is in search.c:_rl_nsearch_dispatch(). */
if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
{
if (_rl_read_bracketed_paste_prefix (c) == 1)
rl_bracketed_paste_begin (1, c);
else
{
c = rl_read_key (); /* get the ESC that got pushed back */
_rl_insert_char (1, c);
}
}
else
_rl_insert_char (1, c);
break;
case ' ':
if ((cxt->flags & READSTR_NOSPACE) == 0)
{
_rl_insert_char (1, c);
break;
}
/* FALLTHROUGH */
case TAB:
/* Perform completion if the caller has set a completion function. */
n = (cxt->compfunc) ? (*cxt->compfunc) (cxt, c) : _rl_insert_char (1, c);
if (n < 0)
{
_rl_readstr_restore (cxt);
return -1;
}
break;
#if 0
case CTRL('_'):
rl_do_undo ();
break;
#endif
default:
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
rl_insert_text (cxt->mb);
else
#endif
_rl_insert_char (1, c);
break;
}
(*rl_redisplay_function) ();
rl_deactivate_mark ();
return 1;
}
/* **************************************************************** */
/* */
/* Reading and Executing named commands */
/* */
/* **************************************************************** */
/* A completion generator for bindable readline command names. */
static char *
readcmd_completion_function (const char *text, int state)
{
static const char **cmdlist = NULL;
static size_t lind, nlen;
const char *cmdname;
if (state == 0)
{
if (cmdlist)
free (cmdlist);
cmdlist = rl_funmap_names ();
lind = 0;
nlen = RL_STRLEN (text);
}
if (cmdlist == 0 || cmdlist[lind] == 0)
return (char *)NULL;
while (cmdlist[lind])
{
cmdname = cmdlist[lind++];
if (STREQN (text, cmdname, nlen))
return (savestring (cmdname));
}
return ((char *)NULL);
}
static void
_rl_display_cmdname_matches (char **matches)
{
size_t len, max, i;
int old;
old = rl_filename_completion_desired;
rl_filename_completion_desired = 0;
/* There is more than one match. Find out how many there are,
and find the maximum printed length of a single entry. */
for (max = 0, i = 1; matches[i]; i++)
{
len = strlen (matches[i]);
if (len > max)
max = len;
}
len = i - 1;
rl_display_match_list (matches, len, max);
rl_filename_completion_desired = old;
rl_forced_update_display ();
rl_display_fixed = 1;
}
static int
_rl_readcmd_complete (_rl_readstr_cxt *cxt, int c)
{
char **matches;
char *prefix;
size_t plen;
matches = rl_completion_matches (rl_line_buffer, readcmd_completion_function);
if (RL_SIG_RECEIVED())
{
_rl_free_match_list (matches);
matches = 0;
RL_CHECK_SIGNALS ();
return -1;
}
else if (matches == 0)
rl_ding ();
/* Whether or not there are multiple matches, we just want to append the
new characters in matches[0]. We display possible matches if we didn't
append anything. */
if (matches)
{
prefix = matches[0];
plen = strlen (prefix);
if (plen > rl_end)
{
size_t n;
for (n = rl_end; n < plen && prefix[n]; n++)
_rl_insert_char (1, prefix[n]);
}
else if (matches[1])
_rl_display_cmdname_matches (matches);
_rl_free_match_list (matches);
}
return 0;
}
/* Use the readstr functions to read a bindable command name using the
line buffer, with completion. */
static char *
_rl_read_command_name ()
{
_rl_readstr_cxt *cxt;
char *ret;
int c, r;
cxt = _rl_readstr_init ('!', READSTR_NOSPACE);
cxt->compfunc = _rl_readcmd_complete;
/* skip callback stuff for now */
r = 0;
while (1)
{
c = _rl_readstr_getchar (cxt);
if (c < 0)
{
_rl_readstr_restore (cxt);
_rl_readstr_cleanup (cxt, r);
return NULL;
}
if (c == 0)
break;
r = _rl_readstr_dispatch (cxt, c);
if (r < 0)
{
_rl_readstr_cleanup (cxt, r);
return NULL; /* dispatch function cleans up */
}
else if (r == 0)
break;
}
ret = savestring (rl_line_buffer);
/* Now restore the original line and perform one final redisplay. */
_rl_readstr_restore (cxt);
(*rl_redisplay_function) ();
/* And free up the context. */
_rl_readstr_cleanup (cxt, r);
return ret;
}
/* Read a command name from the keyboard and execute it as if the bound key
sequence had been entered. */
int
rl_execute_named_command (int count, int key)
{
char *command;
rl_command_func_t *func;
int r;
command = _rl_read_command_name ();
if (command == 0 || *command == '\0')
return 1;
if (func = rl_named_function (command))
{
int prev, ostate;
prev = rl_dispatching;
ostate = RL_ISSTATE (RL_STATE_DISPATCHING);
rl_dispatching = 1;
RL_SETSTATE (RL_STATE_DISPATCHING); /* make sure it's set */
r = (*func) (count, key);
if (ostate == 0)
RL_UNSETSTATE (RL_STATE_DISPATCHING); /* unset it if it wasn't set */
rl_dispatching = prev;
}
else
{
rl_ding ();
r = 1;
}
free (command);
return r;
}
+7 -14
View File
@@ -1,6 +1,6 @@
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
/* Copyright (C) 1988-2020 Free Software Foundation, Inc.
/* Copyright (C) 1988-2020,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.
@@ -68,14 +68,6 @@ extern struct passwd *getpwnam (const char *);
#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
#endif /* !savestring */
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *) 0)
# else
# define NULL 0x0
# endif /* !__STDC__ */
#endif /* !NULL */
/* If being compiled as part of bash, these will be satisfied from
variables.o. If being compiled as part of readline, they will
be satisfied from shell.o. */
@@ -160,8 +152,9 @@ tilde_find_prefix (const char *string, int *len)
static int
tilde_find_suffix (const char *string)
{
register int i, j, string_len;
register char **suffixes;
int i, j;
size_t string_len;
char **suffixes;
suffixes = tilde_additional_suffixes;
string_len = strlen (string);
@@ -189,7 +182,7 @@ char *
tilde_expand (const char *string)
{
char *result;
int result_size, result_index;
size_t result_size, result_index;
result_index = result_size = 0;
if (result = strchr (string, '~'))
@@ -200,7 +193,7 @@ tilde_expand (const char *string)
/* Scan through STRING expanding tildes as we come to them. */
while (1)
{
register int start, end;
int start, end;
char *tilde_word, *expansion;
int len;
@@ -318,7 +311,7 @@ static char *
glue_prefix_and_suffix (char *prefix, const char *suffix, int suffind)
{
char *ret;
int plen, slen;
size_t plen, slen;
plen = (prefix && *prefix) ? strlen (prefix) : 0;
slen = strlen (suffix + suffind);
+3 -1
View File
@@ -116,12 +116,14 @@ _rl_free_undo_list (UNDO_LIST *ul)
void
rl_free_undo_list (void)
{
UNDO_LIST *release, *orig_list;
UNDO_LIST *orig_list;
orig_list = rl_undo_list;
_rl_free_undo_list (rl_undo_list);
rl_undo_list = (UNDO_LIST *)NULL;
_hs_replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == orig_list)
_rl_saved_line_for_history->data = 0;
}
UNDO_LIST *
+48 -68
View File
@@ -43,8 +43,8 @@
#include <ctype.h>
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#include "rlmbutil.h"
#include "rldefs.h"
#if defined (TIOCSTAT_IN_SYS_IOCTL)
# include <sys/ioctl.h>
@@ -229,26 +229,12 @@ rl_tilde_expand (int ignore, int key)
return (0);
}
#if defined (USE_VARARGS)
void
#if defined (PREFER_STDARG)
_rl_ttymsg (const char *format, ...)
#else
_rl_ttymsg (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: ");
vfprintf (stderr, format, args);
@@ -261,24 +247,11 @@ _rl_ttymsg (va_alist)
}
void
#if defined (PREFER_STDARG)
_rl_errmsg (const char *format, ...)
#else
_rl_errmsg (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: ");
vfprintf (stderr, format, args);
@@ -288,28 +261,6 @@ _rl_errmsg (va_alist)
va_end (args);
}
#else /* !USE_VARARGS */
void
_rl_ttymsg (format, arg1, arg2)
char *format;
{
fprintf (stderr, "readline: ");
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
rl_forced_update_display ();
}
void
_rl_errmsg (format, arg1, arg2)
char *format;
{
fprintf (stderr, "readline: ");
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
}
#endif /* !USE_VARARGS */
/* **************************************************************** */
/* */
/* String Utility Functions */
@@ -321,7 +272,8 @@ _rl_errmsg (format, arg1, arg2)
char *
_rl_strindex (const char *s1, const char *s2)
{
register int i, l, len;
int i;
size_t l, len;
for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
if (_rl_strnicmp (s1 + i, s2, l) == 0)
@@ -329,9 +281,10 @@ _rl_strindex (const char *s1, const char *s2)
return ((char *)NULL);
}
#ifndef HAVE_STRPBRK
#if !defined (HAVE_STRPBRK) || defined (HANDLE_MULTIBYTE)
/* Find the first occurrence in STRING1 of any character from STRING2.
Return a pointer to the character in STRING1. */
Return a pointer to the character in STRING1. Understands multibyte
characters. */
char *
_rl_strpbrk (const char *string1, const char *string2)
{
@@ -417,6 +370,48 @@ _rl_stricmp (const char *string1, const char *string2)
}
#endif /* !HAVE_STRCASECMP */
/* Compare the first N characters of S1 and S2 without regard to case. If
FLAGS&1, apply the mapping specified by completion-map-case and make
`-' and `_' equivalent. Returns 1 if the strings are equal. */
int
_rl_strcaseeqn(const char *s1, const char *s2, size_t n, int flags)
{
int c1, c2;
int d;
if ((flags & 1) == 0)
return (_rl_strnicmp (s1, s2, n) == 0);
do
{
c1 = _rl_to_lower (*s1);
c2 = _rl_to_lower (*s2);
d = c1 - c2;
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
d = 0; /* case insensitive character mapping */
if (d != 0)
return 0;
s1++;
s2++;
n--;
}
while (n != 0);
return 1;
}
/* Return 1 if the characters C1 and C2 are equal without regard to case.
If FLAGS&1, apply the mapping specified by completion-map-case and make
`-' and `_' equivalent. */
int
_rl_charcasecmp (int c1, int c2, int flags)
{
if ((flags & 1) && (c1 == '-' || c1 == '_') && (c2 == '-' || c2 == '_'))
return 1;
return ( _rl_to_lower (c1) == _rl_to_lower (c2));
}
/* Stupid comparison routine for qsort () ing strings. */
int
_rl_qsort_string_compare (char **s1, char **s2)
@@ -464,28 +459,14 @@ _rl_savestring (const char *s)
}
#if defined (DEBUG)
#if defined (USE_VARARGS)
static FILE *_rl_tracefp;
void
#if defined (PREFER_STDARG)
_rl_trace (const char *format, ...)
#else
_rl_trace (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
if (_rl_tracefp == 0)
_rl_tropen ();
@@ -531,7 +512,6 @@ _rl_settracefp (FILE *fp)
{
_rl_tracefp = fp;
}
#endif
#endif /* DEBUG */
+69 -14
View File
@@ -1,7 +1,7 @@
/* vi_mode.c -- A vi emulation mode for Bash.
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2021,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.
@@ -76,6 +76,10 @@
#define INCREMENT_POS(start) (start)++
#endif /* !HANDLE_MULTIBYTE */
/* Flags for the motion context */
#define MOVE_SUCCESS 0
#define MOVE_FAILED 0x01
/* This is global so other parts of the code can check whether the last
command was a text modification command. */
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
@@ -101,9 +105,8 @@ static int vi_replace_count;
/* If non-zero, we have text inserted after a c[motion] command that put
us implicitly into insert mode. Some people want this text to be
attached to the command so that it is `redoable' with `.'. */
static int vi_continued_command;
static char *vi_insert_buffer;
static int vi_insert_buffer_size;
static size_t vi_insert_buffer_size;
static int _rl_vi_last_repeat = 1;
static int _rl_vi_last_arg_sign = 1;
@@ -364,12 +367,12 @@ rl_vi_search (int count, int key)
switch (key)
{
case '?':
_rl_free_saved_history_line ();
_rl_free_saved_search_line (); /* just in case */
rl_noninc_forward_search (count, key);
break;
case '/':
_rl_free_saved_history_line ();
_rl_free_saved_search_line ();
rl_noninc_reverse_search (count, key);
break;
@@ -1087,6 +1090,7 @@ _rl_vi_arg_dispatch (int c)
}
else
{
rl_restore_prompt ();
rl_clear_message ();
rl_stuff_char (key);
return 0; /* done */
@@ -1150,10 +1154,27 @@ _rl_mvcxt_dispose (_rl_vimotion_cxt *m)
xfree (m);
}
static inline int
vi_charsearch_command (int c)
{
switch (c)
{
case 'f':
case 'F':
case 't':
case 'T':
case ';':
case ',':
return 1;
default:
return 0;
}
}
static int
rl_domove_motion_callback (_rl_vimotion_cxt *m)
{
int c;
int c, r, opoint;
_rl_vi_last_motion = c = m->motion;
@@ -1163,8 +1184,15 @@ rl_domove_motion_callback (_rl_vimotion_cxt *m)
rl_extend_line_buffer (rl_end + 1);
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
opoint = rl_point;
_rl_dispatch (c, _rl_keymap);
r = _rl_dispatch (c, _rl_keymap);
/* Note in the context that the motion command failed. Right now we only do
this for unsuccessful searches (ones where _rl_dispatch returns non-zero
and point doesn't move). */
if (r != 0 && rl_point == opoint && vi_charsearch_command (c))
m->flags |= MOVE_FAILED;
#if defined (READLINE_CALLBACKS)
if (RL_ISSTATE (RL_STATE_CALLBACK))
@@ -1199,7 +1227,15 @@ _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
{
/* 'c' and 'C' enter insert mode after the delete even if the motion
didn't delete anything, as long as the motion command is valid. */
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c))
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
return (vidomove_dispatch (m));
/* 'd' and 'D' must delete at least one character even if the motion
command doesn't move the cursor. */
if (_rl_to_upper (m->key) == 'D' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
return (vidomove_dispatch (m));
/* 'y' and 'Y' must yank at least one character even if the motion
command doean't move the cursor. */
if (_rl_to_upper (m->key) == 'Y' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
return (vidomove_dispatch (m));
RL_UNSETSTATE (RL_STATE_VIMOTION);
return (-1);
@@ -1285,7 +1321,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
/* Readine vi motion char starting numeric argument */
else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
{
RL_SETSTATE (RL_STATE_NUMERICARG);
_rl_arg_init ();
return (_rl_vi_arg_dispatch (c));
}
#endif
@@ -1295,7 +1331,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
save = rl_numeric_arg;
rl_numeric_arg = _rl_digit_value (c);
rl_explicit_arg = 1;
RL_SETSTATE (RL_STATE_NUMERICARG);
_rl_arg_init ();
rl_digit_loop1 ();
rl_numeric_arg *= save;
c = rl_vi_domove_getchar (m);
@@ -1304,6 +1340,13 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
m->motion = 0;
return -1;
}
else if (member (c, vi_motion) == 0)
{
m->motion = 0;
RL_UNSETSTATE (RL_STATE_VIMOTION);
RL_UNSETSTATE (RL_STATE_NUMERICARG);
return (1);
}
m->motion = c;
return (rl_domove_motion_callback (m));
}
@@ -1328,6 +1371,7 @@ _rl_vi_domove_callback (_rl_vimotion_cxt *m)
int c, r;
m->motion = c = rl_vi_domove_getchar (m);
if (c < 0)
return 1; /* EOF */
r = rl_domove_read_callback (m);
@@ -1340,7 +1384,6 @@ _rl_vi_domove_callback (_rl_vimotion_cxt *m)
int
rl_vi_domove (int x, int *ignore)
{
int r;
_rl_vimotion_cxt *m;
m = _rl_vimvcxt;
@@ -1381,7 +1424,11 @@ rl_vi_delete_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_DELETE, key);
{
/* are we being called recursively or by `y' or `c'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
@@ -1480,7 +1527,11 @@ rl_vi_change_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_CHANGE, key);
{
/* are we being called recursively or by `y' or `d'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
_rl_vimvcxt->start = rl_point;
@@ -1559,7 +1610,11 @@ rl_vi_yank_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_YANK, key);
{
/* are we being called recursively or by `c' or `d'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
_rl_vimvcxt->start = rl_point;
+1 -1
View File
@@ -42,7 +42,7 @@
/* **************************************************************** */
static void
memory_error_and_abort (char *fname)
memory_error_and_abort (const char * const fname)
{
fprintf (stderr, "%s: out of virtual memory\n", fname);
exit (2);
+2 -8
View File
@@ -1,6 +1,6 @@
/* xmalloc.h -- memory allocation that aborts on errors. */
/* Copyright (C) 1999-2009,2010-2021 Free Software Foundation, Inc.
/* Copyright (C) 1999-2009,2010-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.
@@ -29,13 +29,7 @@
#endif
#ifndef PTR_T
#ifdef __STDC__
# define PTR_T void *
#else
# define PTR_T char *
#endif
# define PTR_T void *
#endif /* !PTR_T */
extern PTR_T xmalloc (size_t);