Search global block from basic_lookup_symbol_nonlocal
[deliverable/binutils-gdb.git] / readline / complete.c
index a9c46dfc15ee9e9c7ffe5468d270eb2a6c3ba79d..adce0d69ac1d9bbf57a335c1fb0c6df36d9320c2 100644 (file)
@@ -1,6 +1,6 @@
 /* complete.c -- filename completion for readline. */
 
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2017 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,23 +100,35 @@ 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((const 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));
 static char *printable_part PARAMS((char *));
 static int fnwidth PARAMS((const char *));
-static int fnprint PARAMS((const char *, int));
+static int fnprint PARAMS((const char *, int, const char *));
 static int print_filename PARAMS((char *, char *, int));
 
 static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, 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;
@@ -180,14 +198,15 @@ int _rl_completion_prefix_display_length = 0;
    matches.  If < 0 or > _rl_screenwidth, it is ignored. */
 int _rl_completion_columns = -1;
 
-/* Global variables available to applications using readline. */
+#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;
 
-#if defined (VISIBLE_STATS)
-/* Non-zero means add an additional character to each filename displayed
-   during listing completion iff rl_filename_completion_desired which helps
-   to indicate the type of file being listed. */
-int rl_visible_stats = 0;
-#endif /* VISIBLE_STATS */
+/* Non-zero means to use a color (currently magenta) to indicate the common
+   prefix of a set of possible word completions. */
+int _rl_colored_completion_prefix = 0;
+#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
@@ -199,6 +218,15 @@ int _rl_skip_completed_text = 0;
    cycle of possible completions instead of the last. */
 int _rl_menu_complete_prefix_first = 0;
 
+/* Global variables available to applications using readline. */
+
+#if defined (VISIBLE_STATS)
+/* Non-zero means add an additional character to each filename displayed
+   during listing completion iff rl_filename_completion_desired which helps
+   to indicate the type of file being listed. */
+int rl_visible_stats = 0;
+#endif /* VISIBLE_STATS */
+
 /* If non-zero, then this is the address of a function to call when
    completing on a directory name.  The function is called with
    the address of a string (the current directory name) as an arg. */
@@ -206,6 +234,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 +410,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  */
@@ -390,8 +422,7 @@ static int completion_y_or_n;
    that does the initial simple matching selection algorithm (see
    rl_completion_matches ()).  The default is to do filename completion. */
 int
-rl_complete (ignore, invoking_key)
-     int ignore, invoking_key;
+rl_complete (int ignore, int invoking_key)
 {
   rl_completion_invoking_key = invoking_key;
 
@@ -409,16 +440,14 @@ rl_complete (ignore, invoking_key)
 
 /* List the possible completions.  See description of rl_complete (). */
 int
-rl_possible_completions (ignore, invoking_key)
-     int ignore, invoking_key;
+rl_possible_completions (int ignore, int invoking_key)
 {
   rl_completion_invoking_key = invoking_key;
   return (rl_complete_internal ('?'));
 }
 
 int
-rl_insert_completions (ignore, invoking_key)
-     int ignore, invoking_key;
+rl_insert_completions (int ignore, int invoking_key)
 {
   rl_completion_invoking_key = invoking_key;
   return (rl_complete_internal ('*'));
@@ -430,8 +459,7 @@ rl_insert_completions (ignore, invoking_key)
    an application-specific completion function to honor the
    show-all-if-ambiguous readline variable. */
 int
-rl_completion_mode (cfunc)
-     rl_command_func_t *cfunc;
+rl_completion_mode (rl_command_func_t *cfunc)
 {
   if (rl_last_func == cfunc && !completion_changed_buffer)
     return '?';
@@ -451,17 +479,26 @@ rl_completion_mode (cfunc)
 
 /* Reset readline state on a signal or other event. */
 void
-_rl_reset_completion_state ()
+_rl_reset_completion_state (void)
 {
   rl_completion_found_quote = 0;
   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
-set_completion_defaults (what_to_do)
-     int what_to_do;
+set_completion_defaults (int what_to_do)
 {
   /* Only the completion entry function can change these. */
   rl_filename_completion_desired = 0;
@@ -472,26 +509,23 @@ 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. */
 static int
-get_y_or_n (for_pager)
-     int for_pager;
+get_y_or_n (int 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. */
 #if defined (READLINE_CALLBACKS)
   if (RL_ISSTATE (RL_STATE_CALLBACK))
     return 1;
-#endif
 #endif
 
   for (;;)
@@ -515,8 +549,7 @@ get_y_or_n (for_pager)
 }
 
 static int
-_rl_internal_pager (lines)
-     int lines;
+_rl_internal_pager (int lines)
 {
   int i;
 
@@ -533,8 +566,7 @@ _rl_internal_pager (lines)
 }
 
 static int
-path_isdir (filename)
-     const char *filename;
+path_isdir (const char *filename)
 {
   struct stat finfo;
 
@@ -551,11 +583,12 @@ path_isdir (filename)
      `%' for character special devices
      `#' for block special devices */
 static int
-stat_char (filename)
-     char *filename;
+stat_char (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,14 +597,27 @@ 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)
-    return (0);
+    {
+      xfree (f);
+      return (0);
+    }
 
   character = 0;
   if (S_ISDIR (finfo.st_mode))
@@ -598,13 +644,56 @@ stat_char (filename)
 #endif
   else if (S_ISREG (finfo.st_mode))
     {
+#if defined (_WIN32) && !defined (__CYGWIN__)
+      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 (const char *filename)
+{
+  _rl_set_normal_color ();
+  return (_rl_print_color_indicator (filename));
+}
+
+static void
+colored_stat_end (void)
+{
+  _rl_prep_non_filename_text ();
+  _rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]);
+}
+
+static int
+colored_prefix_start (void)
+{
+  _rl_set_normal_color ();
+  return (_rl_print_prefix_color ());
+}
+
+static void
+colored_prefix_end (void)
+{
+  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
@@ -614,8 +703,7 @@ stat_char (filename)
    for the previous slash and return the portion following that.  If
    there's no previous slash, we just return what we were passed. */
 static char *
-printable_part (pathname)
-      char *pathname;
+printable_part (char *pathname)
 {
   char *temp, *x;
 
@@ -623,13 +711,15 @@ 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
 
   if (temp == 0 || *temp == '\0')
     return (pathname);
+  else if (temp[1] == 0 && temp == pathname)
+    return (pathname);
   /* If the basename is NULL, we might have a pathname like '/usr/src/'.
      Look for a previous slash and, if one is found, return the portion
      following that slash.  If there's no previous slash, just return the
@@ -647,8 +737,7 @@ printable_part (pathname)
 
 /* Compute width of STRING when displayed on screen by print_filename */
 static int
-fnwidth (string)
-     const char *string;
+fnwidth (const char *string)
 {
   int width, pos;
 #if defined (HANDLE_MULTIBYTE)
@@ -684,7 +773,7 @@ fnwidth (string)
          else
            {
              pos += clen;
-             w = wcwidth (wc);
+             w = WCWIDTH (wc);
              width += (w >= 0) ? w : 1;
            }
 #else
@@ -700,12 +789,11 @@ fnwidth (string)
 #define ELLIPSIS_LEN   3
 
 static int
-fnprint (to_print, prefix_bytes)
-     const char *to_print;
-     int prefix_bytes;
+fnprint (const char *to_print, int prefix_bytes, const char *real_pathname)
 {
   int printed_len, w;
   const char *s;
+  int common_prefix_len, print_len;
 #if defined (HANDLE_MULTIBYTE)
   mbstate_t ps;
   const char *end;
@@ -713,18 +801,28 @@ fnprint (to_print, prefix_bytes)
   int width;
   wchar_t wc;
 
-  end = to_print + strlen (to_print) + 1;
+  print_len = strlen (to_print);
+  end = to_print + print_len + 1;
   memset (&ps, 0, sizeof (mbstate_t));
+#else
+  print_len = strlen (to_print);
 #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')
+     possible completions.  Only cut off prefix_bytes if we're going to be
+     printing the ellipsis, which takes precedence over coloring the
+     completion prefix (see print_filename() below). */
+  if (_rl_completion_prefix_display_length > 0 && prefix_bytes >= print_len)
     prefix_bytes = 0;
 
-  if (prefix_bytes)
+#if defined (COLOR_SUPPORT)
+  if (_rl_colored_stats && (prefix_bytes == 0 || _rl_colored_completion_prefix <= 0))
+    colored_stat_start (real_pathname);
+#endif
+
+  if (prefix_bytes && _rl_completion_prefix_display_length > 0)
     {
       char ellipsis;
 
@@ -733,6 +831,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)
@@ -771,7 +878,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);
@@ -783,8 +890,25 @@ fnprint (to_print, prefix_bytes)
          printed_len++;
 #endif
        }
+      if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len)
+       {
+#if defined (COLOR_SUPPORT)
+         /* printed bytes = s - to_print */
+         /* printed bytes should never be > but check for paranoia's sake */
+         colored_prefix_end ();
+         if (_rl_colored_stats)
+           colored_stat_start (real_pathname);         /* XXX - experiment */
+#endif
+         common_prefix_len = 0;
+       }
     }
 
+#if defined (COLOR_SUPPORT)
+  /* XXX - unconditional for now */
+  if (_rl_colored_stats)
+    colored_stat_end ();
+#endif
+
   return printed_len;
 }
 
@@ -793,21 +917,26 @@ fnprint (to_print, prefix_bytes)
    filenames.  Return the number of characters we output. */
 
 static int
-print_filename (to_print, full_pathname, prefix_bytes)
-     char *to_print, *full_pathname;
-     int prefix_bytes;
+print_filename (char *to_print, char *full_pathname, int prefix_bytes)
 {
   int printed_len, extension_char, slen, tlen;
   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, to_print);
 
+  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
@@ -845,7 +974,6 @@ print_filename (to_print, full_pathname, prefix_bytes)
            slen--;
          else
            new_full_pathname[slen] = '/';
-         new_full_pathname[slen] = '/';
          strcpy (new_full_pathname + slen + 1, to_print);
 
 #if defined (VISIBLE_STATS)
@@ -853,8 +981,25 @@ 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 = '/';
+           }
+
+         /* Move colored-stats code inside fnprint() */
+#if defined (COLOR_SUPPORT)
+         if (_rl_colored_stats)
+           printed_len = fnprint (to_print, prefix_bytes, new_full_pathname);
+#endif
 
          xfree (new_full_pathname);
          to_print[-1] = c;
@@ -867,8 +1012,14 @@ 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 = '/';
+
+         /* Move colored-stats code inside fnprint() */
+#if defined (COLOR_SUPPORT)
+         if (_rl_colored_stats)
+           printed_len = fnprint (to_print, prefix_bytes, s);
+#endif
        }
 
       xfree (s);
@@ -883,10 +1034,7 @@ print_filename (to_print, full_pathname, prefix_bytes)
 }
 
 static char *
-rl_quote_filename (s, rtype, qcp)
-     char *s;
-     int rtype;
-     char *qcp;
+rl_quote_filename (char *s, int rtype, char *qcp)
 {
   char *r;
 
@@ -914,8 +1062,7 @@ rl_quote_filename (s, rtype, qcp)
    the value of the delimiter character that caused a word break. */
 
 char
-_rl_find_completion_word (fp, dp)
-     int *fp, *dp;
+_rl_find_completion_word (int *fp, int *dp)
 {
   int scan, end, found_quote, delimiter, pass_next, isbrk;
   char quote_char, *brkchars;
@@ -1047,11 +1194,7 @@ _rl_find_completion_word (fp, dp)
 }
 
 static char **
-gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
-     char *text;
-     int start, end;
-     rl_compentry_func_t *our_func;
-     int found_quote, quote_char;
+gen_completion_matches (char *text, int start, int end, rl_compentry_func_t *our_func, int found_quote, int quote_char)
 {
   char **matches;
 
@@ -1063,10 +1206,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)
        {
@@ -1077,15 +1223,22 @@ 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;  
 }
 
 /* Filter out duplicates in MATCHES.  This frees up the strings in
    MATCHES. */
 static char **
-remove_duplicate_matches (matches)
-     char **matches;
+remove_duplicate_matches (char **matches)
 {
   char *lowest_common;
   int i, j, newlen;
@@ -1145,16 +1298,15 @@ remove_duplicate_matches (matches)
 /* Find the common prefix of the list of matches, and put it into
    matches[0]. */
 static int
-compute_lcd_of_matches (match_list, matches, text)
-     char **match_list;
-     int matches;
-     const char *text;
+compute_lcd_of_matches (char **match_list, int matches, const char *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
@@ -1187,14 +1339,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
@@ -1266,24 +1424,24 @@ compute_lcd_of_matches (match_list, matches, text)
            }
 
          /* sort the list to get consistent answers. */
-         qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
+         if (rl_sort_completion_matches)
+           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);
        }
@@ -1297,9 +1455,7 @@ compute_lcd_of_matches (match_list, matches, text)
 }
 
 static int
-postprocess_matches (matchesp, matching_filenames)
-     char ***matchesp;
-     int matching_filenames;
+postprocess_matches (char ***matchesp, int matching_filenames)
 {
   char *t, **matches, **temp_matches;
   int nmatch, i;
@@ -1310,7 +1466,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)
     {
@@ -1353,7 +1509,7 @@ postprocess_matches (matchesp, matching_filenames)
 }
 
 static int
-complete_get_screenwidth ()
+complete_get_screenwidth (void)
 {
   int cols;
   char *envcols;
@@ -1374,9 +1530,7 @@ complete_get_screenwidth ()
    of strings, in argv format, LEN is the number of strings in MATCHES,
    and MAX is the length of the longest string in MATCHES. */
 void
-rl_display_match_list (matches, len, max)
-     char **matches;
-     int len, max;
+rl_display_match_list (char **matches, int len, int max)
 {
   int count, limit, printed_len, lines, cols;
   int i, j, k, l, common_length, sind;
@@ -1388,15 +1542,29 @@ rl_display_match_list (matches, len, max)
   if (_rl_completion_prefix_display_length > 0)
     {
       t = printable_part (matches[0]);
-      temp = strrchr (t, '/');
+      /* check again in case of /usr/src/ */
+      temp = rl_filename_completion_desired ? strrchr (t, '/') : 0;
       common_length = temp ? fnwidth (temp) : fnwidth (t);
       sind = temp ? strlen (temp) : strlen (t);
+      if (common_length > max || sind > max)
+       common_length = sind = 0;
 
       if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN)
        max -= common_length - ELLIPSIS_LEN;
       else
        common_length = sind = 0;
     }
+#if defined (COLOR_SUPPORT)
+  else if (_rl_colored_completion_prefix > 0)
+    {
+      t = printable_part (matches[0]);
+      temp = rl_filename_completion_desired ? strrchr (t, '/') : 0;
+      common_length = temp ? fnwidth (temp) : fnwidth (t);
+      sind = temp ? RL_STRLEN (temp+1) : RL_STRLEN (t);                /* want portion after final slash */
+      if (common_length > max || sind > max)
+       common_length = sind = 0;
+    }
+#endif
 
   /* How many items of MAX length can we fit in the screen window? */
   cols = complete_get_screenwidth ();
@@ -1443,12 +1611,23 @@ rl_display_match_list (matches, len, max)
                  printed_len = print_filename (temp, matches[l], sind);
 
                  if (j + 1 < limit)
-                   for (k = 0; k < max - printed_len; k++)
-                     putc (' ', rl_outstream);
+                   {
+                     if (max <= printed_len)
+                       putc (' ', rl_outstream);
+                     else
+                       for (k = 0; k < max - printed_len; k++)
+                         putc (' ', rl_outstream);
+                   }
                }
              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)
            {
@@ -1466,9 +1645,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++;
@@ -1479,6 +1664,8 @@ rl_display_match_list (matches, len, max)
                        return;
                    }
                }
+             else if (max <= printed_len)
+               putc (' ', rl_outstream);
              else
                for (k = 0; k < max - printed_len; k++)
                  putc (' ', rl_outstream);
@@ -1500,8 +1687,7 @@ rl_display_match_list (matches, len, max)
    and ask the user if he wants to see the list if there are more matches
    than RL_COMPLETION_QUERY_ITEMS. */
 static void
-display_matches (matches)
-     char **matches;
+display_matches (char **matches)
 {
   int len, max, i;
   char *temp;
@@ -1567,11 +1753,9 @@ display_matches (matches)
   rl_display_fixed = 1;
 }
 
+/* qc == pointer to quoting character, if any */
 static char *
-make_quoted_replacement (match, mtype, qc)
-     char *match;
-     int mtype;
-     char *qc; /* Pointer to quoting character, if any */
+make_quoted_replacement (char *match, int mtype, char *qc)
 {
   int should_quote, do_replace;
   char *replacement;
@@ -1613,10 +1797,7 @@ make_quoted_replacement (match, mtype, qc)
 }
 
 static void
-insert_match (match, start, mtype, qc)
-     char *match;
-     int start, mtype;
-     char *qc;
+insert_match (char *match, int start, int mtype, char *qc)
 {
   char *replacement, *r;
   char oqc;
@@ -1673,11 +1854,9 @@ insert_match (match, start, mtype, qc)
    value of _rl_complete_mark_symlink_dirs, but may be modified by an
    application's completion function). */
 static int
-append_to_match (text, delimiter, quote_char, nontrivial_match)
-     char *text;
-     int delimiter, quote_char, nontrivial_match;
+append_to_match (char *text, int delimiter, int quote_char, int nontrivial_match)
 {
-  char temp_string[4], *filename;
+  char temp_string[4], *filename, *fn;
   int temp_string_index, s;
   struct stat finfo;
 
@@ -1696,6 +1875,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);
@@ -1715,8 +1901,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
@@ -1736,10 +1921,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
 }
 
 static void
-insert_all_matches (matches, point, qc)
-     char **matches;
-     int point;
-     char *qc;
+insert_all_matches (char **matches, int point, char *qc)
 {
   int i;
   char *rp;
@@ -1775,8 +1957,7 @@ insert_all_matches (matches, point, qc)
 }
 
 void
-_rl_free_match_list (matches)
-     char **matches;
+_rl_free_match_list (char **matches)
 {
   register int i;
 
@@ -1798,17 +1979,14 @@ _rl_free_match_list (matches)
    `@' means to do standard completion, and list all possible completions if
    there is more than one and partial completion is not possible. */
 int
-rl_complete_internal (what_to_do)
-     int what_to_do;
+rl_complete_internal (int what_to_do)
 {
   char **matches;
   rl_compentry_func_t *our_func;
   int start, end, delimiter, found_quote, i, nontrivial_lcd;
   char *text, *saved_line_buffer;
   char quote_char;
-#if 1
   int tlen, mlen;
-#endif
 
   RL_SETSTATE(RL_STATE_COMPLETING);
 
@@ -1836,10 +2014,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)
@@ -1873,10 +2049,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])
@@ -1891,7 +2063,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.
@@ -1927,7 +2098,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:
@@ -1935,6 +2121,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;
     }
@@ -1950,6 +2137,8 @@ rl_complete_internal (what_to_do)
 
   RL_UNSETSTATE(RL_STATE_COMPLETING);
   _rl_reset_completion_state ();
+
+  RL_CHECK_SIGNALS ();
   return 0;
 }
 
@@ -1972,10 +2161,10 @@ rl_complete_internal (what_to_do)
      when there are no more matches.
  */
 char **
-rl_completion_matches (text, entry_function)
-     const char *text;
-     rl_compentry_func_t *entry_function;
+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;
 
@@ -1993,18 +2182,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]. */
@@ -2022,9 +2229,7 @@ rl_completion_matches (text, entry_function)
    TEXT contains a partial username preceded by a random
    character (usually `~').  */
 char *
-rl_username_completion_function (text, state)
-     const char *text;
-     int state;
+rl_username_completion_function (const char *text, int state)
 {
 #if defined (__WIN32__) || defined (__OPENNT)
   return (char *)NULL;
@@ -2043,7 +2248,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)
@@ -2080,45 +2287,118 @@ 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;
-     int convlen;
-     const char *filename;
-     int filename_len;
+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
+
+  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))
@@ -2139,9 +2419,7 @@ complete_fncmp (convfn, convlen, filename, filename_len)
    because of all the pathnames that must be followed when looking up the
    completion for a command. */
 char *
-rl_filename_completion_function (text, state)
-     const char *text;
-     int state;
+rl_filename_completion_function (const char *text, int state)
 {
   static DIR *directory = (DIR *)NULL;
   static char *filename = (char *)NULL;
@@ -2150,6 +2428,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. */
@@ -2173,7 +2452,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, '/');
@@ -2184,7 +2463,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] == ':')
         {
@@ -2207,11 +2486,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
@@ -2230,7 +2511,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);
@@ -2238,8 +2519,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);
@@ -2365,8 +2647,7 @@ rl_filename_completion_function (text, state)
    hit the end of the match list, we restore the original unmatched text,
    ring the bell, and reset the counter to zero. */
 int
-rl_old_menu_complete (count, invoking_key)
-     int count, invoking_key;
+rl_old_menu_complete (int count, int invoking_key)
 {
   rl_compentry_func_t *our_func;
   int matching_filenames, found_quote;
@@ -2487,9 +2768,17 @@ rl_old_menu_complete (count, invoking_key)
   return (0);
 }
 
+/* The current version of menu completion.
+   The differences between this function and the original are:
+
+1. It honors the maximum number of completions variable (completion-query-items)
+2. It appends to the word as usual if there is only one match
+3. It displays the common prefix if there is one, and makes it the first menu
+   choice if the menu-complete-display-prefix option is enabled
+*/
 int
-rl_menu_complete (count, ignore)
-     int count, ignore;
+rl_menu_complete (int count, int ignore)
 {
   rl_compentry_func_t *our_func;
   int matching_filenames, found_quote;
@@ -2603,6 +2892,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)
        {
@@ -2656,8 +2950,7 @@ rl_menu_complete (count, ignore)
 }
 
 int
-rl_backward_menu_complete (count, key)
-     int count, key;
+rl_backward_menu_complete (int count, int key)
 {
   /* Positive arguments to backward-menu-complete translate into negative
      arguments for menu-complete, and vice versa. */
This page took 0.039471 seconds and 4 git commands to generate.