Import readline 8.0
[deliverable/binutils-gdb.git] / readline / histsearch.c
index 1ad55d22d3010d1a74c963addd46d5d9de0b0c78..7a426c96781429785f1b44ad3241da43e63df545 100644 (file)
@@ -1,6 +1,6 @@
 /* histsearch.c -- searching the history list. */
 
-/* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1992-2009,2017 Free Software Foundation, Inc.
 
    This file contains the GNU History Library (History), a set of
    routines for managing the text of previously typed lines.
 #  include <unistd.h>
 #endif
 
+#if defined (HAVE_FNMATCH)
+#  include <fnmatch.h>
+#endif
+
 #include "history.h"
 #include "histlib.h"
+#include "xmalloc.h"
 
 /* The list of alternate characters that can delimit a history search
    string. */
@@ -59,18 +64,22 @@ static int history_search_internal PARAMS((const char *, int, int));
    returned. */
 
 static int
-history_search_internal (string, direction, anchored)
-     const char *string;
-     int direction, anchored;
+history_search_internal (const char *string, int direction, int flags)
 {
   register int i, reverse;
   register char *line;
   register int line_index;
-  int string_len;
+  int string_len, anchored, patsearch;
   HIST_ENTRY **the_history;    /* local */
 
   i = history_offset;
   reverse = (direction < 0);
+  anchored = (flags & ANCHORED_SEARCH);
+#if defined (HAVE_FNMATCH)
+  patsearch = (flags & PATTERN_SEARCH);
+#else
+  patsearch = 0;
+#endif
 
   /* Take care of trivial cases first. */
   if (string == 0 || *string == '\0')
@@ -98,7 +107,7 @@ history_search_internal (string, direction, anchored)
       line_index = strlen (line);
 
       /* If STRING is longer than line, no match. */
-      if (string_len > line_index)
+      if (patsearch == 0 && (string_len > line_index))
        {
          NEXT_LINE ();
          continue;
@@ -107,6 +116,17 @@ history_search_internal (string, direction, anchored)
       /* Handle anchored searches first. */
       if (anchored == ANCHORED_SEARCH)
        {
+#if defined (HAVE_FNMATCH)
+         if (patsearch)
+           {
+             if (fnmatch (string, line, 0) == 0)
+               {
+                 history_offset = i;
+                 return (0);
+               }
+           }
+         else
+#endif
          if (STREQN (string, line, string_len))
            {
              history_offset = i;
@@ -120,10 +140,21 @@ history_search_internal (string, direction, anchored)
       /* Do substring search. */
       if (reverse)
        {
-         line_index -= string_len;
+         line_index -= (patsearch == 0) ? string_len : 1;
 
          while (line_index >= 0)
            {
+#if defined (HAVE_FNMATCH)
+             if (patsearch)
+               {
+                 if (fnmatch (string, line + line_index, 0) == 0)
+                   {
+                     history_offset = i;
+                     return (line_index);
+                   }
+               }
+             else
+#endif
              if (STREQN (string, line + line_index, string_len))
                {
                  history_offset = i;
@@ -141,6 +172,17 @@ history_search_internal (string, direction, anchored)
 
          while (line_index < limit)
            {
+#if defined (HAVE_FNMATCH)
+             if (patsearch)
+               {
+                 if (fnmatch (string, line + line_index, 0) == 0)
+                   {
+                     history_offset = i;
+                     return (line_index);
+                   }
+               }
+             else
+#endif
              if (STREQN (string, line + line_index, string_len))
                {
                  history_offset = i;
@@ -153,20 +195,73 @@ history_search_internal (string, direction, anchored)
     }
 }
 
+int
+_hs_history_patsearch (const char *string, int direction, int flags)
+{
+  char *pat;
+  size_t len, start;
+  int ret, unescaped_backslash;
+
+#if defined (HAVE_FNMATCH)
+  /* Assume that the string passed does not have a leading `^' and any
+     anchored search request is captured in FLAGS */
+  len = strlen (string);
+  ret = len - 1;
+  /* fnmatch is required to reject a pattern that ends with an unescaped
+     backslash */
+  if (unescaped_backslash = (string[ret] == '\\'))
+    {
+      while (ret > 0 && string[--ret] == '\\')
+       unescaped_backslash = 1 - unescaped_backslash;
+    }
+  if (unescaped_backslash)
+    return -1;
+  pat = (char *)xmalloc (len + 3);
+  /* If the search string is not anchored, we'll be calling fnmatch (assuming
+     we have it). Prefix a `*' to the front of the search string so we search
+     anywhere in the line. */
+  if ((flags & ANCHORED_SEARCH) == 0 && string[0] != '*')
+    {
+      pat[0] = '*';
+      start = 1;
+      len++;
+    }
+  else
+    {
+      start = 0;
+    }
+
+  /* Attempt to reduce the number of searches by tacking a `*' onto the end
+     of a pattern that doesn't have one.  Assume a pattern that ends in a
+     backslash contains an even number of trailing backslashes; we check
+     above */
+  strcpy (pat + start, string);
+  if (pat[len - 1] != '*')
+    {
+      pat[len] = '*';          /* XXX */
+      pat[len+1] = '\0';
+    }
+#else
+  pat = string;
+#endif
+
+  ret = history_search_internal (pat, direction, flags|PATTERN_SEARCH);
+
+  if (pat != string)
+    free (pat);
+  return ret;
+}
+       
 /* Do a non-anchored search for STRING through the history in DIRECTION. */
 int
-history_search (string, direction)
-     const char *string;
-     int direction;
+history_search (const char *string, int direction)
 {
   return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
 }
 
 /* Do an anchored search for string through the history in DIRECTION. */
 int
-history_search_prefix (string, direction)
-     const char *string;
-     int direction;
+history_search_prefix (const char *string, int direction)
 {
   return (history_search_internal (string, direction, ANCHORED_SEARCH));
 }
@@ -175,9 +270,7 @@ history_search_prefix (string, direction)
    backwards.  POS is an absolute index into the history list at
    which point to begin searching. */
 int
-history_search_pos (string, dir, pos)
-     const char *string;
-     int dir, pos;
+history_search_pos (const char *string, int dir, int pos)
 {
   int ret, old;
 
This page took 0.028449 seconds and 4 git commands to generate.