aboutsummaryrefslogtreecommitdiff
path: root/readline/complete.c
diff options
context:
space:
mode:
authorPatrick Palka <patrick@parcs.ath.cx>2015-07-14 20:29:21 -0400
committerPatrick Palka <patrick@parcs.ath.cx>2015-07-25 09:53:01 -0400
commit4a11f2065906976675808364ddbd1c0f77eea41f (patch)
tree8b25495190b4d41b1785910c4cc4fd709d0a628a /readline/complete.c
parenta496fbc8802f0a5719db6347a43cc869e03d83c9 (diff)
downloadgdb-4a11f2065906976675808364ddbd1c0f77eea41f.zip
gdb-4a11f2065906976675808364ddbd1c0f77eea41f.tar.gz
gdb-4a11f2065906976675808364ddbd1c0f77eea41f.tar.bz2
Sync readline/ to version 7.0 alpha
This patch syncs our upstream copy of readline from version 6.2 to the latest version, 7.0 alpha (released July 10 2015). I essentially copied what was done the last time readline was synced, when Jan updated to readline 6.2 in 2011: http://sourceware.org/ml/gdb-patches/2011-05/msg00003.html Procedure: 1. I extracted the readline-7.0-alpha tarball on top of readline/. 2. I deleted all the new files under doc/ that were deliberately omitted before. 3. I regenerated readline/configure and readline/examples/rlfe/configure using autoconf 2.64. No other configure files need regenerating. 4. I updated the function gdb_printable_part in completer.c with a trivial change made to the readline function it is based off of, printable_part in readline/complete.c. There is more work to be done in completer.c to sync it with readline/complete.c, but it is non-trivial and should probably be done separately anyway. Local patches that had to be reapplied: None. readline 7.0 alpha contains all of our local readline patches. New files in readline/: colors.{c,h} examples/{hist_erasedups,hist_purgecmd,rl-callbacktest,rlbasic}.c parse-colors.{c,h} readline.pc.in configure.ac Deleted files in readline/: configure.in Regressions: After the sync there is one testsuite regression, the test "signal SIGINT" in gdb.gdb/selftest.exp which now FAILs. Previously, the readline 6.2 SIGINT handler would temporarily reinstall the underlying application's SIGINT handler and immediately re-raise SIGINT so that the orginal handler gets invoked. But now (since readline 6.3) its SIGINT handler does not re-raise SIGINT or directly invoke the original handler; it now sets a flag marking that SIGINT was raised, and waits until readline explicitly has control to call the application's SIGINT handler. Anyway, because SIGINT is no longer re-raised from within readline's SIGINT handler, doing "signal SIGINT" with a stopped inferior gdb process will no longer resume and then immediately stop the process (since there is no 2nd SIGINT to immediately catch). Instead, the inferior gdb process will now just print "Quit" and continue to run. So with this commit, this particular test case is adjusted to reflect this change in behavior (we now have to send a 2nd SIGINT manually to stop it). Aside from this one testsuite regression, I personally noticed no regression in user-visible behavior. Though I only tested on x86_64 and on i686 Debian Stretch. Getting this kind of change in at the start of the GDB 7.11 development cycle will allow us to get a lot of passive testing from developers and from bleeding-edge users. readline/ChangeLog.gdb: Import readline 7.0 alpha * configure: Regenerate. * examples/rlfe/configure: Regenerate. gdb/ChangeLog: * completer.c (gdb_printable_part): Sync with readline function it is based off of. gdb/testsuite/ChangeLog: * gdb.gdb/selftest.exp (test_with_self): Update test to now expect the GDB inferior to no longer immediately stop after being resumed with "signal SIGINT".
Diffstat (limited to 'readline/complete.c')
-rw-r--r--readline/complete.c487
1 files changed, 394 insertions, 93 deletions
diff --git a/readline/complete.c b/readline/complete.c
index a5ce803..302ea1d 100644
--- a/readline/complete.c
+++ b/readline/complete.c
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2015 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.
@@ -31,6 +31,8 @@
# include <sys/file.h>
#endif
+#include <signal.h>
+
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
@@ -64,6 +66,10 @@ extern int errno;
#include "xmalloc.h"
#include "rlprivate.h"
+#if defined (COLOR_SUPPORT)
+# include "colors.h"
+#endif
+
#ifdef __STDC__
typedef int QSFUNC (const void *, const void *);
#else
@@ -94,17 +100,29 @@ extern struct passwd *getpwent PARAMS((void));
longest string in that array. */
rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
-#if defined (VISIBLE_STATS)
+#if defined (VISIBLE_STATS) || defined (COLOR_SUPPORT)
# if !defined (X_OK)
# define X_OK 1
# endif
+#endif
+
+#if defined (VISIBLE_STATS)
static int stat_char PARAMS((char *));
#endif
+#if defined (COLOR_SUPPORT)
+static int colored_stat_start PARAMS((char *));
+static void colored_stat_end PARAMS((void));
+static int colored_prefix_start PARAMS((void));
+static void colored_prefix_end PARAMS((void));
+#endif
+
static int path_isdir PARAMS((const char *));
static char *rl_quote_filename PARAMS((char *, int, char *));
+static void _rl_complete_sigcleanup PARAMS((int, void *));
+
static void set_completion_defaults PARAMS((int));
static int get_y_or_n PARAMS((int));
static int _rl_internal_pager PARAMS((int));
@@ -156,7 +174,7 @@ int _rl_complete_mark_symlink_dirs = 0;
int _rl_print_completions_horizontally;
/* Non-zero means that case is not significant in filename completion. */
-#if defined (__MSDOS__) && !defined (__DJGPP__)
+#if (defined (__MSDOS__) && !defined (__DJGPP__)) || (defined (_WIN32) && !defined (__CYGWIN__))
int _rl_completion_case_fold = 1;
#else
int _rl_completion_case_fold = 0;
@@ -189,6 +207,14 @@ int _rl_completion_columns = -1;
int rl_visible_stats = 0;
#endif /* VISIBLE_STATS */
+#if defined (COLOR_SUPPORT)
+/* Non-zero means to use colors to indicate file type when listing possible
+ completions. The colors used are taken from $LS_COLORS, if set. */
+int _rl_colored_stats = 0;
+
+int _rl_colored_completion_prefix = 1;
+#endif
+
/* If non-zero, when completing in the middle of a word, don't insert
characters from the match that match characters following point in
the word. This means, for instance, completing when the cursor is
@@ -206,6 +232,8 @@ rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
+
/* If non-zero, this is the address of a function to call when reading
directory entries from the filesystem for completion and comparing
them to the partial word to be completed. The function should
@@ -380,6 +408,8 @@ static int completion_changed_buffer;
/* The result of the query to the user about displaying completion matches */
static int completion_y_or_n;
+static int _rl_complete_display_matches_interrupt = 0;
+
/*************************************/
/* */
/* Bindable completion functions */
@@ -457,6 +487,18 @@ _rl_reset_completion_state ()
rl_completion_quote_character = 0;
}
+static void
+_rl_complete_sigcleanup (sig, ptr)
+ 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
@@ -472,6 +514,9 @@ set_completion_defaults (what_to_do)
/* The completion entry function may optionally change this. */
rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
+
+ /* Reset private state. */
+ _rl_complete_display_matches_interrupt = 0;
}
/* The user must press "y" or "n". Non-zero return means "y" pressed. */
@@ -481,10 +526,6 @@ get_y_or_n (for_pager)
{
int c;
-/* Disabled for GDB due to the gdb.base/readline-ask.exp regression.
- [patch] testsuite: Test readline-6.2 "ask" regression
- http://sourceware.org/ml/gdb-patches/2011-05/msg00002.html */
-#if 0
/* For now, disable pager in callback mode, until we later convert to state
driven functions. Have to wait until next major version to add new
state definition, since it will change value of RL_STATE_DONE. */
@@ -492,7 +533,6 @@ get_y_or_n (for_pager)
if (RL_ISSTATE (RL_STATE_CALLBACK))
return 1;
#endif
-#endif
for (;;)
{
@@ -556,6 +596,8 @@ stat_char (filename)
{
struct stat finfo;
int character, r;
+ char *f;
+ const char *fn;
/* Short-circuit a //server on cygwin, since that will always behave as
a directory. */
@@ -564,10 +606,20 @@ stat_char (filename)
return '/';
#endif
+ f = 0;
+ if (rl_filename_stat_hook)
+ {
+ f = savestring (filename);
+ (*rl_filename_stat_hook) (&f);
+ fn = f;
+ }
+ else
+ fn = filename;
+
#if defined (HAVE_LSTAT) && defined (S_ISLNK)
- r = lstat (filename, &finfo);
+ r = lstat (fn, &finfo);
#else
- r = stat (filename, &finfo);
+ r = stat (fn, &finfo);
#endif
if (r == -1)
@@ -599,25 +651,56 @@ stat_char (filename)
else if (S_ISREG (finfo.st_mode))
{
#if defined (_WIN32) && !defined (__CYGWIN__)
- /* Windows 'access' doesn't support X_OK and on latest Windows
- versions even invokes an invalid parameter exception. */
- char *ext = strrchr (filename, '.');
-
- if (ext
- && (_rl_stricmp (ext, ".exe") == 0
- || _rl_stricmp (ext, ".cmd") == 0
- || _rl_stricmp (ext, ".bat") == 0
- || _rl_stricmp (ext, ".com") == 0))
+ char *ext;
+
+ /* Windows doesn't do access and X_OK; check file extension instead */
+ ext = strrchr (fn, '.');
+ if (ext && (_rl_stricmp (ext, ".exe") == 0 ||
+ _rl_stricmp (ext, ".cmd") == 0 ||
+ _rl_stricmp (ext, ".bat") == 0 ||
+ _rl_stricmp (ext, ".com") == 0))
character = '*';
#else
if (access (filename, X_OK) == 0)
character = '*';
#endif
}
+
+ xfree (f);
return (character);
}
#endif /* VISIBLE_STATS */
+#if defined (COLOR_SUPPORT)
+static int
+colored_stat_start (filename)
+ char *filename;
+{
+ _rl_set_normal_color ();
+ return (_rl_print_color_indicator (filename));
+}
+
+static void
+colored_stat_end ()
+{
+ _rl_prep_non_filename_text ();
+ _rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]);
+}
+
+static int
+colored_prefix_start ()
+{
+ _rl_set_normal_color ();
+ return (_rl_print_prefix_color ());
+}
+
+static void
+colored_prefix_end ()
+{
+ colored_stat_end (); /* for now */
+}
+#endif
+
/* Return the portion of PATHNAME that should be output when listing
possible completions. If we are hacking filename completion, we
are only interested in the basename, the portion following the
@@ -636,7 +719,7 @@ printable_part (pathname)
return (pathname);
temp = strrchr (pathname, '/');
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) || defined (_WIN32)
if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
temp = pathname + 1;
#endif
@@ -697,7 +780,7 @@ fnwidth (string)
else
{
pos += clen;
- w = wcwidth (wc);
+ w = WCWIDTH (wc);
width += (w >= 0) ? w : 1;
}
#else
@@ -719,6 +802,7 @@ fnprint (to_print, prefix_bytes)
{
int printed_len, w;
const char *s;
+ int common_prefix_len;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps;
const char *end;
@@ -730,14 +814,14 @@ fnprint (to_print, prefix_bytes)
memset (&ps, 0, sizeof (mbstate_t));
#endif
- printed_len = 0;
+ printed_len = common_prefix_len = 0;
/* Don't print only the ellipsis if the common prefix is one of the
possible completions */
if (to_print[prefix_bytes] == '\0')
prefix_bytes = 0;
- if (prefix_bytes)
+ if (prefix_bytes && _rl_completion_prefix_display_length > 0)
{
char ellipsis;
@@ -746,6 +830,15 @@ fnprint (to_print, prefix_bytes)
putc (ellipsis, rl_outstream);
printed_len = ELLIPSIS_LEN;
}
+#if defined (COLOR_SUPPORT)
+ else if (prefix_bytes && _rl_colored_completion_prefix > 0)
+ {
+ common_prefix_len = prefix_bytes;
+ prefix_bytes = 0;
+ /* XXX - print color indicator start here */
+ colored_prefix_start ();
+ }
+#endif
s = to_print + prefix_bytes;
while (*s)
@@ -784,7 +877,7 @@ fnprint (to_print, prefix_bytes)
break;
else
{
- w = wcwidth (wc);
+ w = WCWIDTH (wc);
width = (w >= 0) ? w : 1;
}
fwrite (s, 1, tlen, rl_outstream);
@@ -796,6 +889,13 @@ fnprint (to_print, prefix_bytes)
printed_len++;
#endif
}
+ if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len)
+ {
+ /* printed bytes = s - to_print */
+ /* printed bytes should never be > but check for paranoia's sake */
+ colored_prefix_end ();
+ common_prefix_len = 0;
+ }
}
return printed_len;
@@ -814,13 +914,20 @@ print_filename (to_print, full_pathname, prefix_bytes)
char *s, c, *new_full_pathname, *dn;
extension_char = 0;
- printed_len = fnprint (to_print, prefix_bytes);
+#if defined (COLOR_SUPPORT)
+ /* Defer printing if we want to prefix with a color indicator */
+ if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0)
+#endif
+ printed_len = fnprint (to_print, prefix_bytes);
+ if (rl_filename_completion_desired && (
#if defined (VISIBLE_STATS)
- if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
-#else
- if (rl_filename_completion_desired && _rl_complete_mark_directories)
+ rl_visible_stats ||
#endif
+#if defined (COLOR_SUPPORT)
+ _rl_colored_stats ||
+#endif
+ _rl_complete_mark_directories))
{
/* If to_print != full_pathname, to_print is the basename of the
path passed. In this case, we try to expand the directory
@@ -866,8 +973,28 @@ print_filename (to_print, full_pathname, prefix_bytes)
extension_char = stat_char (new_full_pathname);
else
#endif
- if (path_isdir (new_full_pathname))
- extension_char = '/';
+ if (_rl_complete_mark_directories)
+ {
+ dn = 0;
+ if (rl_directory_completion_hook == 0 && rl_filename_stat_hook)
+ {
+ dn = savestring (new_full_pathname);
+ (*rl_filename_stat_hook) (&dn);
+ xfree (new_full_pathname);
+ new_full_pathname = dn;
+ }
+ if (path_isdir (new_full_pathname))
+ extension_char = '/';
+ }
+
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats)
+ {
+ colored_stat_start (new_full_pathname);
+ printed_len = fnprint (to_print, prefix_bytes);
+ colored_stat_end ();
+ }
+#endif
xfree (new_full_pathname);
to_print[-1] = c;
@@ -880,8 +1007,18 @@ print_filename (to_print, full_pathname, prefix_bytes)
extension_char = stat_char (s);
else
#endif
- if (path_isdir (s))
+ if (_rl_complete_mark_directories && path_isdir (s))
extension_char = '/';
+
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats)
+ {
+ colored_stat_start (s);
+ printed_len = fnprint (to_print, prefix_bytes);
+ colored_stat_end ();
+ }
+#endif
+
}
xfree (s);
@@ -1076,10 +1213,13 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
variable rl_attempted_completion_function. */
if (rl_attempted_completion_function)
{
- _rl_interrupt_immediately++;
matches = (*rl_attempted_completion_function) (text, start, end);
- if (_rl_interrupt_immediately > 0)
- _rl_interrupt_immediately--;
+ if (RL_SIG_RECEIVED())
+ {
+ _rl_free_match_list (matches);
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
if (matches || rl_attempted_completion_over)
{
@@ -1090,7 +1230,15 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
/* XXX -- filename dequoting moved into rl_filename_completion_function */
+ /* rl_completion_matches will check for signals as well to avoid a long
+ delay while reading a directory. */
matches = rl_completion_matches (text, our_func);
+ if (RL_SIG_RECEIVED())
+ {
+ _rl_free_match_list (matches);
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
return matches;
}
@@ -1165,9 +1313,11 @@ compute_lcd_of_matches (match_list, matches, text)
{
register int i, c1, c2, si;
int low; /* Count of max-matched characters. */
+ int lx;
char *dtext; /* dequoted TEXT, if needed */
#if defined (HANDLE_MULTIBYTE)
int v;
+ size_t v1, v2;
mbstate_t ps1, ps2;
wchar_t wc1, wc2;
#endif
@@ -1200,14 +1350,20 @@ compute_lcd_of_matches (match_list, matches, text)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
- mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
+ 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);
+ if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
+ {
+ if (c1 != c2) /* do byte comparison */
+ break;
+ continue;
+ }
wc1 = towlower (wc1);
wc2 = towlower (wc2);
if (wc1 != wc2)
break;
- else if (v > 1)
- si += v - 1;
+ else if (v1 > 1)
+ si += v1 - 1;
}
else
#endif
@@ -1282,21 +1438,20 @@ compute_lcd_of_matches (match_list, matches, text)
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
si = strlen (text);
- if (si <= low)
- {
- for (i = 1; i <= matches; i++)
- if (strncmp (match_list[i], text, si) == 0)
- {
- strncpy (match_list[0], match_list[i], low);
- break;
- }
- /* no casematch, use first entry */
- if (i > matches)
- strncpy (match_list[0], match_list[1], low);
- }
- else
- /* otherwise, just use the text the user typed. */
- strncpy (match_list[0], text, low);
+ lx = (si <= low) ? si : low; /* check shorter of text and matches */
+ /* Try to preserve the case of what the user typed in the presence of
+ multiple matches: check each match for something that matches
+ what the user typed taking case into account; use it up to common
+ length of matches if one is found. If not, just use first match. */
+ for (i = 1; i <= matches; i++)
+ if (strncmp (match_list[i], text, lx) == 0)
+ {
+ strncpy (match_list[0], match_list[i], low);
+ break;
+ }
+ /* no casematch, use first entry */
+ if (i > matches)
+ strncpy (match_list[0], match_list[1], low);
FREE (dtext);
}
@@ -1323,7 +1478,7 @@ postprocess_matches (matchesp, matching_filenames)
return 0;
/* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
+ to ignore duplicate possibilities. Scan for the text to
insert being identical to the other completions. */
if (rl_ignore_completion_duplicates)
{
@@ -1401,7 +1556,7 @@ rl_display_match_list (matches, len, max)
if (_rl_completion_prefix_display_length > 0)
{
t = printable_part (matches[0]);
- temp = strrchr (t, '/');
+ temp = strrchr (t, '/'); /* check again in case of /usr/src/ */
common_length = temp ? fnwidth (temp) : fnwidth (t);
sind = temp ? strlen (temp) : strlen (t);
@@ -1410,6 +1565,15 @@ rl_display_match_list (matches, len, max)
else
common_length = sind = 0;
}
+#if defined (COLOR_SUPPORT)
+ else if (_rl_colored_completion_prefix > 0)
+ {
+ t = printable_part (matches[0]);
+ temp = strrchr (t, '/');
+ common_length = temp ? fnwidth (temp) : fnwidth (t);
+ sind = temp ? RL_STRLEN (temp+1) : RL_STRLEN (t); /* want portion after final slash */
+ }
+#endif
/* How many items of MAX length can we fit in the screen window? */
cols = complete_get_screenwidth ();
@@ -1462,6 +1626,12 @@ rl_display_match_list (matches, len, max)
l += count;
}
rl_crlf ();
+#if defined (SIGWINCH)
+ if (RL_SIG_RECEIVED () && RL_SIGWINCH_RECEIVED() == 0)
+#else
+ if (RL_SIG_RECEIVED ())
+#endif
+ return;
lines++;
if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
{
@@ -1479,9 +1649,15 @@ rl_display_match_list (matches, len, max)
temp = printable_part (matches[i]);
printed_len = print_filename (temp, matches[i], sind);
/* Have we reached the end of this line? */
+#if defined (SIGWINCH)
+ if (RL_SIG_RECEIVED () && RL_SIGWINCH_RECEIVED() == 0)
+#else
+ if (RL_SIG_RECEIVED ())
+#endif
+ return;
if (matches[i+1])
{
- if (i && (limit > 1) && (i % limit) == 0)
+ if (limit == 1 || (i && (limit > 1) && (i % limit) == 0))
{
rl_crlf ();
lines++;
@@ -1690,7 +1866,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
char *text;
int delimiter, quote_char, nontrivial_match;
{
- char temp_string[4], *filename;
+ char temp_string[4], *filename, *fn;
int temp_string_index, s;
struct stat finfo;
@@ -1709,6 +1885,13 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
if (rl_filename_completion_desired)
{
filename = tilde_expand (text);
+ if (rl_filename_stat_hook)
+ {
+ fn = savestring (filename);
+ (*rl_filename_stat_hook) (&fn);
+ xfree (filename);
+ filename = fn;
+ }
s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
? LSTAT (filename, &finfo)
: stat (filename, &finfo);
@@ -1728,8 +1911,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
#ifdef S_ISLNK
/* Don't add anything if the filename is a symlink and resolves to a
directory. */
- else if (s == 0 && S_ISLNK (finfo.st_mode) &&
- stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
+ else if (s == 0 && S_ISLNK (finfo.st_mode) && path_isdir (filename))
;
#endif
else
@@ -1849,10 +2031,8 @@ rl_complete_internal (what_to_do)
/* nontrivial_lcd is set if the common prefix adds something to the word
being completed. */
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
-#if 1
if (what_to_do == '!' || what_to_do == '@')
tlen = strlen (text);
-#endif
xfree (text);
if (matches == 0)
@@ -1886,10 +2066,6 @@ rl_complete_internal (what_to_do)
case '!':
case '@':
/* Insert the first match with proper quoting. */
-#if 0
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
-#else
if (what_to_do == TAB)
{
if (*matches[0])
@@ -1904,7 +2080,6 @@ rl_complete_internal (what_to_do)
if (mlen >= tlen)
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
}
-#endif
/* If there are more matches, ring the bell to indicate.
If we are in vi mode, Posix.2 says to not ring the bell.
@@ -1940,7 +2115,22 @@ rl_complete_internal (what_to_do)
break;
case '?':
+ 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;
break;
default:
@@ -1948,6 +2138,7 @@ rl_complete_internal (what_to_do)
rl_ding ();
FREE (saved_line_buffer);
RL_UNSETSTATE(RL_STATE_COMPLETING);
+ _rl_free_match_list (matches);
_rl_reset_completion_state ();
return 1;
}
@@ -1963,6 +2154,8 @@ rl_complete_internal (what_to_do)
RL_UNSETSTATE(RL_STATE_COMPLETING);
_rl_reset_completion_state ();
+
+ RL_CHECK_SIGNALS ();
return 0;
}
@@ -1989,6 +2182,8 @@ rl_completion_matches (text, entry_function)
const char *text;
rl_compentry_func_t *entry_function;
{
+ register int i;
+
/* Number of slots in match_list. */
int match_list_size;
@@ -2006,18 +2201,36 @@ rl_completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL;
- _rl_interrupt_immediately++;
while (string = (*entry_function) (text, matches))
{
- if (matches + 1 == match_list_size)
+ if (RL_SIG_RECEIVED ())
+ {
+ /* Start at 1 because we don't set matches[0] in this function.
+ Only free the list members if we're building match list from
+ rl_filename_completion_function, since we know that doesn't
+ free the strings it returns. */
+ if (entry_function == rl_filename_completion_function)
+ {
+ for (i = 1; match_list[i]; i++)
+ xfree (match_list[i]);
+ }
+ xfree (match_list);
+ match_list = 0;
+ match_list_size = 0;
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
+
+ if (matches + 1 >= match_list_size)
match_list = (char **)xrealloc
(match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+ if (match_list == 0)
+ return (match_list);
+
match_list[++matches] = string;
match_list[matches + 1] = (char *)NULL;
}
- if (_rl_interrupt_immediately > 0)
- _rl_interrupt_immediately--;
/* If there were any matches, then look through them finding out the
lowest common denominator. That then becomes match_list[0]. */
@@ -2056,7 +2269,9 @@ rl_username_completion_function (text, state)
username = savestring (&text[first_char_loc]);
namelen = strlen (username);
+#if defined (HAVE_GETPWENT)
setpwent ();
+#endif
}
#if defined (HAVE_GETPWENT)
@@ -2093,8 +2308,9 @@ rl_username_completion_function (text, state)
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
- regard to the alphabetic case of characters. CONVFN is the possibly-
- converted directory entry; FILENAME is what the user typed. */
+ regard to the alphabetic case of characters. If
+ _rl_completion_case_map is set, make `-' and `_' equivalent. CONVFN is
+ the possibly-converted directory entry; FILENAME is what the user typed. */
static int
complete_fncmp (convfn, convlen, filename, filename_len)
const char *convfn;
@@ -2104,34 +2320,110 @@ complete_fncmp (convfn, convlen, filename, 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
+
+ if (filename_len == 0)
+ return 1;
+ if (convlen < filename_len)
+ 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)
{
/* Case-insensitive comparison treating _ and - as equivalent */
- if (filename_len == 0)
- return 1;
- if (convlen < filename_len)
- return 0;
- s1 = (char *)convfn;
- s2 = (char *)filename;
- len = filename_len;
- do
+#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
{
- 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 */
+ 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);
}
- 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;
+ }
+ else
+#endif
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
(convlen >= filename_len) &&
(_rl_strnicmp (filename, convfn, filename_len) == 0))
@@ -2163,6 +2455,7 @@ rl_filename_completion_function (text, state)
static int filename_len;
char *temp, *dentry, *convfn;
int dirlen, dentlen, convlen;
+ int tilde_dirname;
struct dirent *entry;
/* If we don't have any state, then do some initialization. */
@@ -2186,7 +2479,7 @@ rl_filename_completion_function (text, state)
temp = strrchr (dirname, '/');
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) || defined (_WIN32)
/* special hack for //X/... */
if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
temp = strrchr (dirname + 3, '/');
@@ -2197,7 +2490,7 @@ rl_filename_completion_function (text, state)
strcpy (filename, ++temp);
*temp = '\0';
}
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN__))
/* searches from current directory on the drive */
else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
{
@@ -2220,11 +2513,13 @@ rl_filename_completion_function (text, state)
else
users_dirname = savestring (dirname);
+ tilde_dirname = 0;
if (*dirname == '~')
{
temp = tilde_expand (dirname);
xfree (dirname);
dirname = temp;
+ tilde_dirname = 1;
}
/* We have saved the possibly-dequoted version of the directory name
@@ -2243,7 +2538,7 @@ rl_filename_completion_function (text, state)
xfree (users_dirname);
users_dirname = savestring (dirname);
}
- else if (rl_completion_found_quote && rl_filename_dequoting_function)
+ else if (tilde_dirname == 0 && rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
xfree (dirname);
@@ -2251,8 +2546,9 @@ rl_filename_completion_function (text, state)
}
directory = opendir (dirname);
- /* Now dequote a non-null filename. */
- if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function)
+ /* Now dequote a non-null filename. FILENAME will not be NULL, but may
+ be empty. */
+ if (*filename && rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
@@ -2616,6 +2912,11 @@ rl_menu_complete (count, ignore)
full_completion = 1;
return (0);
}
+ else if (_rl_menu_complete_prefix_first)
+ {
+ rl_ding ();
+ return (0);
+ }
}
else if (match_list_size <= 1)
{