--- embedaddon/readline/histsearch.c 2014/07/30 08:16:45 1.1.1.1 +++ embedaddon/readline/histsearch.c 2021/03/17 01:01:01 1.1.1.2 @@ -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. @@ -39,8 +39,13 @@ # include #endif +#if defined (HAVE_FNMATCH) +# include +#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 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;