[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[5732] always search entire body of node for search results
From: |
Gavin D. Smith |
Subject: |
[5732] always search entire body of node for search results |
Date: |
Thu, 07 Aug 2014 15:08:49 +0000 |
Revision: 5732
http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5732
Author: gavin
Date: 2014-08-07 15:08:46 +0000 (Thu, 07 Aug 2014)
Log Message:
-----------
always search entire body of node for search results
Modified Paths:
--------------
trunk/ChangeLog
trunk/info/Makefile.am
trunk/info/filesys.c
trunk/info/info-utils.c
trunk/info/nodes.h
trunk/info/search.c
trunk/info/session.c
trunk/info/t/search-after-tag.sh
trunk/info/tag.c
trunk/info/window.c
trunk/info/window.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/ChangeLog 2014-08-07 15:08:46 UTC (rev 5732)
@@ -1,3 +1,35 @@
+2014-08-07 Gavin Smith <address@hidden>
+
+ * info/window.h (WINDOW): New fields 'search_string',
+ 'search_is_case_sensitive'.
+ * info/search.c (regexp_search): Always search entire body of node.
+ Don't save information about searches in static variables; save and
+ retrieve it in passed WINDOW instead. Always free regex_t object.
+ * info/session.c (info_search_in_node_internal): Set node of window
+ before calling regexp_search.
+ (info_set_node_of_window): Free matches for old node.
+
+ * info/filesys.c (convert_eols): Convert null bytes in Info tags to
+ spaces.
+ * info/session.c (allfiles_create_node): Add index tag with spaces
+ instead of nulls.
+ * info/nodes.h (INFO_TAG_REGEXP): New preprocessor definition.
+ * info/info-utils.c (scan_info_tag): Function separated out from
+ scan_node_contents.
+ (scan_node_contents): Include INFO_TAG_REGEXP in regexp search. Don't
+ change start of search.
+ * info/tag.c (tag_expand): Process tags with spaces instead of null
+ bytes.
+
+ * info/window.c (info_tag): Expect Info tag with space instead of null
+ byte.
+ * info/info-utils.c (printed_representation): Call info_tag in right
+ place.
+
+ * info/Makefile.am: search-after-tag.sh removed from XFAIL_TESTS.
+ * info/t/search-after-tag.sh: Source info/t/Init-inter.inc as
+ intended.
+
2014-08-06 Gavin Smith <address@hidden>
* info/display.c (display_update_window_1): Output sequence turning on
Modified: trunk/info/Makefile.am
===================================================================
--- trunk/info/Makefile.am 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/Makefile.am 2014-08-07 15:08:46 UTC (rev 5732)
@@ -129,7 +129,6 @@
t/help.sh
XFAIL_TESTS = \
- t/search-after-tag.sh \
t/quoted-label-as-target.sh \
t/quoted-target.sh \
t/quoted-label-and-target.sh \
Modified: trunk/info/filesys.c
===================================================================
--- trunk/info/filesys.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/filesys.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -289,7 +289,10 @@
we afford converting them into newlines as well? Maybe implement some
heuristics here, like in Emacs 20.
- FIXME: is it a good idea to show the EOL type on the modeline? */
+ FIXME: is it a good idea to show the EOL type on the modeline?
+
+ Additionally, convert null bytes in "Info tags" to spaces. This simplifies
+ processing of node contents. */
static long
convert_eols (char *text, long int textlen)
{
@@ -303,7 +306,13 @@
s++;
textlen--;
}
- *d++ = *s++;
+ *d = *s++;
+
+ if (d[0] == '\0' && d[1] == '\010'
+ && (d[2] == '[' || d[2] == ']'))
+ d[0] = ' ';
+
+ d++;
}
return d - text;
Modified: trunk/info/info-utils.c
===================================================================
--- trunk/info/info-utils.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/info-utils.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -504,11 +504,21 @@
if (mb_isprint (mbi_cur (*iter)))
{
- /* cur.wc gives a wchar_t object. See mbiter.h in the
- gnulib/lib directory. */
- *pchars = wcwidth ((*iter).cur.wc);
- *pbytes = cur_len;
- return cur_ptr;
+ if (info_tag (*iter, &cur_len))
+ {
+ *pchars = 0;
+ *pbytes = cur_len;
+ ITER_SETBYTES (*iter, cur_len);
+ return cur_ptr;
+ }
+ else
+ {
+ /* cur.wc gives a wchar_t object. See mbiter.h in the
+ gnulib/lib directory. */
+ *pchars = wcwidth ((*iter).cur.wc);
+ *pbytes = cur_len;
+ return cur_ptr;
+ }
}
else if (cur_len == 1)
{
@@ -528,13 +538,6 @@
return cur_ptr;
}
- else if (info_tag (*iter, &cur_len))
- {
- *pchars = 0;
- *pbytes = cur_len;
- ITER_SETBYTES (*iter, cur_len);
- return cur_ptr;
- }
else if (*cur_ptr == '\t')
{
int i = 0;
@@ -1529,6 +1532,54 @@
return ptr[index];
}
+/* Process an in index marker ("address@hidden@^H]") or an image marker
+ ("address@hidden address@hidden"). The null bytes here were converted into
spaces in
+ the convert_eols function in filesys.c. */
+static void
+scan_info_tag (NODE *node, int *in_index, FILE_BUFFER *fb)
+{
+ char *p, *p1;
+ struct text_buffer *expansion = xmalloc (sizeof (struct text_buffer));
+
+ p = inptr;
+ p1 = p;
+
+ text_buffer_init (expansion);
+
+ if (tag_expand (&p1, expansion, in_index))
+ {
+ if (*in_index)
+ node->flags |= N_IsIndex;
+
+ if (!rewrite_p)
+ {
+ rewrite_p = 1;
+ init_output_stream (fb);
+
+ /* Put inptr back to start so that
+ copy_input_to_output below gets all
+ preceding contents. */
+ inptr = node->contents;
+ }
+
+ /* Write out up to tag. */
+ copy_input_to_output (p - inptr);
+
+ write_tag_contents (text_buffer_base (expansion),
+ text_buffer_off (expansion));
+ /* Skip past body of tag. */
+ skip_input (p1 - inptr);
+ }
+ else
+ {
+ /* It was not a valid tag. */
+ copy_input_to_output (p - inptr + 1);
+ }
+
+ text_buffer_free (expansion);
+ free (expansion);
+}
+
/* Scan (*NODE_PTR)->contents and record location and contents of
cross-references and menu items. Convert character encoding of
node contents to that of the user if the two are known to be
@@ -1542,6 +1593,7 @@
SEARCH_BINDING s;
char *search_string;
long position;
+ WINDOW save_search = {};
int in_menu = 0;
NODE *node = *node_ptr;
@@ -1549,6 +1601,9 @@
REFERENCE **refs = NULL;
size_t refs_index = 0, refs_slots = 0;
+ /* Whether an index tag was seen. */
+ int in_index = 0;
+
/* Check that contents haven't already been processed. This shouldn't
happen. */
if (node->flags & N_WasRewritten)
@@ -1598,15 +1653,18 @@
parse_top_node_line (node);
- search_string = INFO_MENU_REGEXP "|" INFO_XREF_REGEXP;
+ search_string = INFO_MENU_REGEXP "|" INFO_XREF_REGEXP
+ "|" INFO_TAG_REGEXP;
s.buffer = node->contents;
s.start = inptr - node->contents;
s.end = node->nodelen;
s.flags = S_FoldCase;
-search_again:
- while (regexp_search (search_string, &s, &position, 0, 0) == search_success)
+ save_search.node = node;
+
+ while (regexp_search (search_string, &s, &position, 0, &save_search)
+ == search_success)
{
int in_parentheses = 0;
REFERENCE *entry;
@@ -1623,102 +1681,45 @@
if (*inptr == '\n')
skip_input (strspn (inptr, "\n") - 1); /* Keep one newline. */
- search_string = INFO_MENU_ENTRY_REGEXP "|" INFO_XREF_REGEXP;
- s.start = inptr - s.buffer;
- continue;
+ search_string = INFO_MENU_ENTRY_REGEXP "|" INFO_XREF_REGEXP
+ "|" INFO_TAG_REGEXP;
}
+ else if (match[0] == ' ') /* Info tag */
+ {
+ scan_info_tag (node, &in_index, fb);
+ }
+ else
+ {
+ /* Create REFERENCE entity. */
+ entry = info_new_reference (0, 0);
- /* Create REFERENCE entity. */
- entry = info_new_reference (0, 0);
+ if (safe_string_index (inptr, -1, s.buffer, s.end) == '('
+ && safe_string_index (inptr, 1, s.buffer, s.end) == 'n')
+ in_parentheses = 1;
- if (safe_string_index (inptr, -1, s.buffer, s.end) == '('
- && safe_string_index (inptr, 1, s.buffer, s.end) == 'n')
- in_parentheses = 1;
+ save_conversion_state ();
+ scan_reference_marker (entry);
- save_conversion_state ();
- scan_reference_marker (entry);
+ if (!scan_reference_label (entry)
+ || !scan_reference_target (entry, node, in_parentheses))
+ {
+ /* This is not a menu entry or reference. Do not add to our
list. */
+ char *cur_inptr = inptr;
+ reset_conversion ();
+ copy_input_to_output (cur_inptr - inptr);
- if (!scan_reference_label (entry)
- || !scan_reference_target (entry, node, in_parentheses))
- {
- /* This is not a menu entry or reference. Do not add to our list. */
- char *cur_inptr = inptr;
- reset_conversion ();
- copy_input_to_output (cur_inptr - inptr);
+ info_reference_free (entry);
+ s.start = inptr - s.buffer;
+ continue;
+ }
- info_reference_free (entry);
- s.start = inptr - s.buffer;
- continue;
+ add_pointer_to_array (entry, refs_index, refs, refs_slots, 50);
}
- add_pointer_to_array (entry, refs_index, refs, refs_slots, 50);
-
s.start = inptr - s.buffer;
if (s.start >= s.end) break;
}
- /* Search may have stopped too early because of null byte
- in index marker ("address@hidden@^H]") or in image marker
- ("address@hidden address@hidden"). Process these and try again. */
- {
- char *p, *p1;
- int in_index = 0;
-
- p = strchr (inptr, '\0');
- p1 = p;
-
- /* If null byte is in text of node: */
- if (p < node->contents + node->nodelen)
- {
- struct text_buffer *expansion = xmalloc (sizeof (struct text_buffer));
- text_buffer_init (expansion);
-
- /* FIXME: bounds checking in tag_expand? */
- if (tag_expand (&p1, expansion, &in_index))
- {
- if (in_index)
- node->flags |= N_IsIndex;
-
- if (!rewrite_p)
- {
- rewrite_p = 1;
- init_output_stream (fb);
-
- /* Put inptr back to start so that
- copy_input_to_output below gets all
- preceding contents. */
- inptr = node->contents;
- }
-
- /* Write out up to null byte. */
- copy_input_to_output (p - inptr);
-
- write_tag_contents (text_buffer_base (expansion),
- text_buffer_off (expansion));
- /* Skip past body of tag. */
- skip_input (p1 - inptr);
- }
- else
- {
- /* We encountered a null byte before the end of the node
- contents, but it did not introduce a valid tag (image,
- index, or otherwise). Write up to and including null
- and continue searching. */
- copy_input_to_output (p - inptr + 1);
- }
-
- text_buffer_free (expansion);
- free (expansion);
-
- /* Update search. */
- s.buffer = inptr;
- s.start = 0;
- s.end = node->nodelen - (inptr - node->contents);
-
- goto search_again;
- }
- }
-
/* If we haven't accidentally gone past the end of the node, write
out the rest of it. */
if (inptr < node->contents + node->nodelen)
Modified: trunk/info/nodes.h
===================================================================
--- trunk/info/nodes.h 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/nodes.h 2014-08-07 15:08:46 UTC (rev 5732)
@@ -95,7 +95,8 @@
#define INFO_XREF_LABEL "*Note"
/* Only match "*Note" if it is followed by a whitespace character so that it
will not be recognized if, e.g., it is surrounded in inverted commas. */
-#define INFO_XREF_REGEXP "\\*Note[ \\t\\n]";
+#define INFO_XREF_REGEXP "\\*Note[ \\t\\n]"
+#define INFO_TAG_REGEXP " \010\\["
#define TAGS_TABLE_END_LABEL "\nEnd Tag Table"
#define TAGS_TABLE_BEG_LABEL "Tag Table:\n"
#define INDIRECT_TAGS_TABLE_LABEL "Indirect:\n"
Modified: trunk/info/search.c
===================================================================
--- trunk/info/search.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/search.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -98,43 +98,33 @@
regexp_search (char *regexp, SEARCH_BINDING *binding,
long *poff, SEARCH_BINDING *pend, WINDOW *window)
{
- static regex_t preg; /* Compiled pattern buffer for regexp. */
+ int is_insensitive = 0;
- /* Store the last regular expression to avoid recompiling. */
- static char *previous_regexp = NULL;
- static int was_insensitive = 0;
-
regoff_t start = 0, end;
- /* Remember the last buffer the search was over. We can optimize by reusing
- the results from last time. */
- static char *previous_content = NULL;
- static long previous_start = 0, previous_end = 0;
+ char *buffer; /* Buffer to search in. */
- static regmatch_t *matches; /* List of matches. */
- static size_t match_alloc = 0;
- static size_t match_count = 0;
+ regmatch_t *matches; /* List of matches. */
+ size_t match_count;
- /* Check if we need to compile a new regexp. */
- if (previous_regexp == NULL
- || (binding->flags & S_FoldCase) != was_insensitive
- || strcmp (previous_regexp, regexp) != 0)
+ regmatch_t *new_matches = 0; /* List of matches if they have to be
+ recalculated. */
+ size_t match_alloc = 0;
+ size_t new_match_count = 0;
+
+ /* Check if we need to calculate new results. */
+ if (!window->matches || strcmp (window->search_string, regexp)
+ || window->search_is_case_sensitive != binding->flags & S_FoldCase)
{
+ regex_t preg; /* Compiled pattern buffer for regexp. */
int result;
char *unescaped_regexp;
char *p, *q;
+ char saved_char;
+ regoff_t offset = 0;
- previous_content = NULL;
+ is_insensitive = binding->flags & S_FoldCase;
- if (previous_regexp != NULL)
- {
- free (previous_regexp);
- previous_regexp = NULL;
- regfree (&preg);
- }
-
- was_insensitive = binding->flags & S_FoldCase;
-
/* expand the \n and \t in regexp */
unescaped_regexp = xmalloc (1 + strlen (regexp));
for (p = regexp, q = unescaped_regexp; *p != '\0'; p++, q++)
@@ -165,7 +155,7 @@
result = regcomp (&preg, unescaped_regexp,
REG_EXTENDED|
REG_NEWLINE|
- (was_insensitive ? REG_ICASE : 0));
+ (is_insensitive ? REG_ICASE : 0));
free (unescaped_regexp);
if (result != 0)
@@ -177,77 +167,70 @@
return search_failure;
}
- previous_regexp = xstrdup (regexp);
- }
+ buffer = window->node->contents;
+ saved_char = buffer[window->node->nodelen];
+ buffer[window->node->nodelen] = '\0';
- if (binding->start < binding->end)
- {
- start = binding->start;
- end = binding->end;
- }
- else
- {
- start = binding->end;
- end = binding->start;
- }
-
- /* Check if we need to calculate new results. */
- if (binding->buffer != previous_content
- || start < previous_start
- || end > previous_end)
- {
- char saved_char;
- regoff_t offset = start;
-
- /* Save for next time. */
- previous_content = binding->buffer;
- previous_start = start;
- previous_end = end;
-
- saved_char = previous_content[end];
- previous_content[end] = '\0';
-
- for (match_count = 0; offset < end; )
+ for (new_match_count = 0; offset < window->node->nodelen; )
{
int result = 0;
- if (match_count == match_alloc)
+ if (new_match_count == match_alloc)
{
/* The match list is full. Initially allocate 256 entries,
then double every time we fill it. */
if (match_alloc == 0)
match_alloc = 256;
- matches = x2nrealloc (matches, &match_alloc, sizeof matches[0]);
+ new_matches = x2nrealloc (new_matches, &match_alloc, sizeof
new_matches[0]);
}
- result = regexec (&preg, &previous_content[offset],
- 1, &matches[match_count], 0);
+ result = regexec (&preg, &buffer[offset],
+ 1, &new_matches[new_match_count], 0);
if (result == 0)
{
- if (matches[match_count].rm_eo == 0)
+ if (new_matches[new_match_count].rm_eo == 0)
{
/* ignore empty matches */
offset++;
}
else
{
- matches[match_count].rm_so += offset;
- matches[match_count].rm_eo += offset;
- offset = matches[match_count++].rm_eo;
+ new_matches[new_match_count].rm_so += offset;
+ new_matches[new_match_count].rm_eo += offset;
+ offset = new_matches[new_match_count++].rm_eo;
}
}
else
break;
}
- previous_content[end] = saved_char;
+ buffer[window->node->nodelen] = saved_char;
+ regfree (&preg);
}
/* Pass back the full list of results. */
- if (window)
+ if (window && new_matches)
{
- window->matches = matches;
- window->match_count = match_count;
+ window->search_string = xstrdup (regexp);
+ window->search_is_case_sensitive = binding->flags & S_FoldCase;
+ window->matches = new_matches;
+ window->match_count = new_match_count;
}
+ /* Extract the matches we are looking for. */
+
+ matches = window->matches;
+ match_count = window->match_count;
+
+ if (binding->start < binding->end)
+ {
+ start = binding->start;
+ end = binding->end;
+ }
+ else
+ {
+ start = binding->end;
+ end = binding->start;
+ }
+
if (binding->start > binding->end)
{
/* searching backward */
@@ -261,7 +244,7 @@
{
if (pend)
{
- pend->buffer = binding->buffer;
+ pend->buffer = buffer;
pend->flags = binding->flags;
pend->start = matches[i].rm_so;
pend->end = matches[i].rm_eo;
@@ -284,7 +267,7 @@
{
if (pend)
{
- pend->buffer = binding->buffer;
+ pend->buffer = buffer;
pend->flags = binding->flags;
pend->start = matches[i].rm_so;
pend->end = matches[i].rm_eo;
Modified: trunk/info/session.c
===================================================================
--- trunk/info/session.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/session.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -82,7 +82,7 @@
term, term);
/* Mark as an index so that destinations are never hidden. */
- text_buffer_add_string (&text, "\000\010[index\000\010]", 11);
+ text_buffer_add_string (&text, "\040\010[index\040\010]", 11);
text_buffer_printf (&text, "\n* Menu:\n\n");
for (i = 0; fref[i]; i++)
@@ -804,6 +804,7 @@
/* Clear displayed search matches if any. TODO: do search again in new
node? */
+ free (win->matches);
win->matches = 0;
/* Put this node into the window. */
@@ -3496,6 +3497,16 @@
if (result != search_success)
{
+ /* regexp_search uses window->node now, not binding.buffer. */
+ NODE *saved_node = 0;
+ if (window)
+ {
+ saved_node = window->node;
+ window->node = node;
+ free (window->matches);
+ window->matches = 0;
+ }
+
binding.buffer = node->contents;
binding.start = start;
binding.end = node->nodelen;
@@ -3514,6 +3525,8 @@
result = (match_regexp ?
regexp_search (string, &binding, poff, resbnd, window):
search (string, &binding, poff));
+ if (saved_node)
+ window->node = saved_node;
}
if (result == search_success && window)
@@ -3521,7 +3534,11 @@
window->flags |= W_UpdateWindow;
if (window->node != node)
{
+ /* window->matches is already the match list for the new node,
+ so prevent info_set_node_of_window freeing it. */
regmatch_t *saved_matches = window->matches;
+ window->matches = 0;
+
info_set_node_of_window (window, node);
window->matches = saved_matches;
}
Modified: trunk/info/t/search-after-tag.sh
===================================================================
--- trunk/info/t/search-after-tag.sh 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/t/search-after-tag.sh 2014-08-07 15:08:46 UTC (rev 5732)
@@ -16,7 +16,7 @@
srcdir=${srcdir:-.}
. $srcdir/t/Init-test.inc
-. $t/Init-intera.inc
+. $t/Init-inter.inc
run_ginfo -f intera -n Searching
# Search for text in a node that appears after an Info tag
Modified: trunk/info/tag.c
===================================================================
--- trunk/info/tag.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/tag.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -213,16 +213,16 @@
size_t len;
struct tag_handler *tp;
- if (memcmp(p, "\0\b[", 3) != 0) /* opening magic? */
+ if (memcmp(p, " \b[", 3) != 0) /* opening magic? */
return 0;
p += 3;
- q = p + strlen (p); /* forward to next null */
- if (memcmp (q + 1, "\b]", 2) != 0) /* closing magic? */
+ q = strstr (p, " \b]"); /* closing magic? */
+ if (!q)
return 0;
/* Output is different for index nodes */
- if (!strcmp ("index", p))
+ if (!strncmp ("index", p, strlen ("index")))
*is_index = 1;
len = strcspn (p, " \t"); /* tag name */
@@ -232,11 +232,16 @@
while (p[len] == ' ' || p[len] == '\t')
++len; /* move past whitespace */
+ q[0] = '\0';
+
if (!tp->handler || tp->handler (p + len, outbuf) == 0)
{
*input = q + 3;
+ q[0] = ' ';
+
return 1;
}
+ q[0] = ' ';
}
return 0;
}
Modified: trunk/info/window.c
===================================================================
--- trunk/info/window.c 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/window.c 2014-08-07 15:08:46 UTC (rev 5732)
@@ -1181,7 +1181,7 @@
int
info_tag (mbi_iterator_t iter, size_t *plen)
{
- if (*mbi_cur_ptr (iter) == '\0' && mbi_avail (iter))
+ if (*mbi_cur_ptr (iter) == ' ' && mbi_avail (iter))
{
mbi_advance (iter);
if (*mbi_cur_ptr (iter) == '\b' && mbi_avail (iter))
@@ -1192,7 +1192,7 @@
const char *ptr, *end;
mbi_advance (iter);
ptr = mbi_cur_ptr (iter);
- end = memmem (ptr, ITER_LIMIT (iter), "\0\b]", 3);
+ end = memmem (ptr, ITER_LIMIT (iter), " \b]", 3);
if (end)
{
*plen = end - ptr + 6;
Modified: trunk/info/window.h
===================================================================
--- trunk/info/window.h 2014-08-06 14:28:28 UTC (rev 5731)
+++ trunk/info/window.h 2014-08-07 15:08:46 UTC (rev 5732)
@@ -89,6 +89,8 @@
int flags; /* See below for details. */
/* Used for highlighting search matches. */
+ char *search_string;
+ int search_is_case_sensitive;
regmatch_t *matches;
size_t match_count;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [5732] always search entire body of node for search results,
Gavin D. Smith <=