version 1.1.1.1, 2014/07/30 08:16:45
|
version 1.1.1.2, 2021/03/17 01:01:01
|
Line 1
|
Line 1
|
/* histsearch.c -- searching the history list. */ |
/* 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 |
This file contains the GNU History Library (History), a set of |
routines for managing the text of previously typed lines. |
routines for managing the text of previously typed lines. |
Line 39
|
Line 39
|
# include <unistd.h> |
# include <unistd.h> |
#endif |
#endif |
|
|
|
#if defined (HAVE_FNMATCH) |
|
# include <fnmatch.h> |
|
#endif |
|
|
#include "history.h" |
#include "history.h" |
#include "histlib.h" |
#include "histlib.h" |
|
#include "xmalloc.h" |
|
|
/* The list of alternate characters that can delimit a history search |
/* The list of alternate characters that can delimit a history search |
string. */ |
string. */ |
Line 59 static int history_search_internal PARAMS((const char
|
Line 64 static int history_search_internal PARAMS((const char
|
returned. */ |
returned. */ |
|
|
static int |
static int |
history_search_internal (string, direction, anchored) | history_search_internal (const char *string, int direction, int flags) |
const char *string; | |
int direction, anchored; | |
{ |
{ |
register int i, reverse; |
register int i, reverse; |
register char *line; |
register char *line; |
register int line_index; |
register int line_index; |
int string_len; | int string_len, anchored, patsearch; |
HIST_ENTRY **the_history; /* local */ |
HIST_ENTRY **the_history; /* local */ |
|
|
i = history_offset; |
i = history_offset; |
reverse = (direction < 0); |
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. */ |
/* Take care of trivial cases first. */ |
if (string == 0 || *string == '\0') |
if (string == 0 || *string == '\0') |
Line 98 history_search_internal (string, direction, anchored)
|
Line 107 history_search_internal (string, direction, anchored)
|
line_index = strlen (line); |
line_index = strlen (line); |
|
|
/* If STRING is longer than line, no match. */ |
/* If STRING is longer than line, no match. */ |
if (string_len > line_index) | if (patsearch == 0 && (string_len > line_index)) |
{ |
{ |
NEXT_LINE (); |
NEXT_LINE (); |
continue; |
continue; |
Line 107 history_search_internal (string, direction, anchored)
|
Line 116 history_search_internal (string, direction, anchored)
|
/* Handle anchored searches first. */ |
/* Handle anchored searches first. */ |
if (anchored == ANCHORED_SEARCH) |
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)) |
if (STREQN (string, line, string_len)) |
{ |
{ |
history_offset = i; |
history_offset = i; |
Line 120 history_search_internal (string, direction, anchored)
|
Line 140 history_search_internal (string, direction, anchored)
|
/* Do substring search. */ |
/* Do substring search. */ |
if (reverse) |
if (reverse) |
{ |
{ |
line_index -= string_len; | line_index -= (patsearch == 0) ? string_len : 1; |
|
|
while (line_index >= 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); |
|
} |
|
} |
|
else |
|
#endif |
if (STREQN (string, line + line_index, string_len)) |
if (STREQN (string, line + line_index, string_len)) |
{ |
{ |
history_offset = i; |
history_offset = i; |
Line 141 history_search_internal (string, direction, anchored)
|
Line 172 history_search_internal (string, direction, anchored)
|
|
|
while (line_index < limit) |
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)) |
if (STREQN (string, line + line_index, string_len)) |
{ |
{ |
history_offset = i; |
history_offset = i; |
Line 153 history_search_internal (string, direction, anchored)
|
Line 195 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. */ |
/* Do a non-anchored search for STRING through the history in DIRECTION. */ |
int |
int |
history_search (string, direction) | history_search (const char *string, int direction) |
const char *string; | |
int direction; | |
{ |
{ |
return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); |
return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); |
} |
} |
|
|
/* Do an anchored search for string through the history in DIRECTION. */ |
/* Do an anchored search for string through the history in DIRECTION. */ |
int |
int |
history_search_prefix (string, direction) | history_search_prefix (const char *string, int direction) |
const char *string; | |
int direction; | |
{ |
{ |
return (history_search_internal (string, direction, ANCHORED_SEARCH)); |
return (history_search_internal (string, direction, ANCHORED_SEARCH)); |
} |
} |
Line 175 history_search_prefix (string, direction)
|
Line 270 history_search_prefix (string, direction)
|
backwards. POS is an absolute index into the history list at |
backwards. POS is an absolute index into the history list at |
which point to begin searching. */ |
which point to begin searching. */ |
int |
int |
history_search_pos (string, dir, pos) | history_search_pos (const char *string, int dir, int pos) |
const char *string; | |
int dir, pos; | |
{ |
{ |
int ret, old; |
int ret, old; |
|
|