diff -up -x 'Makefile*' -x '*.o' -x '*~' info/info-utils.c info-adjust-anchors/info-utils.c --- info/info-utils.c 2014-03-07 22:13:27.000000000 +0000 +++ info-adjust-anchors/info-utils.c 2014-03-09 15:03:48.000000000 +0000 @@ -446,42 +446,99 @@ printed_representation (const char *char /* Whether to strip syntax from the text of nodes. */ int preprocess_nodes_p; +static char *input_start; + static size_t output_allocated; static size_t output_length; static char **output_start; +static NODE **anchor_to_adjust; +static int nodestart; + +/* Difference between the number of bytes input in the file and + bytes output. */ +static long int output_bytes_difference; + static void init_output_stream (char **o_s) { output_allocated = 0; output_length = 0; output_start = o_s; + output_bytes_difference = 0; } static void -write_and_advance (char **output, char *input, size_t n) +reallocate_output (char **output, size_t n) { - if (preprocess_nodes_p) + output_length += n; + while (output_allocated < output_length) { - output_length += n; - while (output_allocated < output_length) + size_t offset; + if (output_allocated == 0) { - size_t offset; - if (output_allocated == 0) - { - output_allocated = 8; /* Initial allocation */ - offset = 0; - } - else - { - offset = *output - *output_start; - } + output_allocated = 8; /* Initial allocation */ + offset = 0; + } + else + { + offset = *output - *output_start; + } - *output_start = x2realloc (*output_start, &output_allocated); - *output = *output_start + offset; - } + *output_start = x2realloc (*output_start, &output_allocated); + *output = *output_start + offset; + } +} + +static void +skip_input (char **input, size_t n) +{ + *input += n; + output_bytes_difference += n; +} + +static void +write_extra_bytes_to_output (char **output, char *input, size_t n) +{ + if (preprocess_nodes_p) + { + reallocate_output (output, n); memmove (*output, input, n); *output += n; + output_bytes_difference -= n; + } +} + +static void +copy_input_to_output (char **output, char **input, size_t n) +{ + if (preprocess_nodes_p) + { + reallocate_output (output, n); + memmove (*output, *input, n); + *input += n; + *output += n; + + /* Check if we have gone past any anchors and + adjust with output_bytes_difference. */ + if (anchor_to_adjust) + { + while ((*anchor_to_adjust)->nodestart - nodestart + <= *input - input_start) + { + (*anchor_to_adjust)->nodestart -= output_bytes_difference; + anchor_to_adjust++; + if (!*anchor_to_adjust || (*anchor_to_adjust)->nodelen != 0) + { + anchor_to_adjust = 0; + break; + } + } + } + } + else + { + *input += n; } } @@ -489,21 +546,20 @@ write_and_advance (char **output, char * static void underlining_off (char **output) { - write_and_advance (output, "\033[24m", 5); + write_extra_bytes_to_output (output, "\033[24m", 5); } static void underlining_on (char **output) { - write_and_advance (output, "\033[4m", 4); + write_extra_bytes_to_output (output, "\033[4m", 4); } -/* Read first line of node and set next, prev and up. Advance INPTR past +/* Read first line of node and set next, prev and up. Advance NODEPTR past the first line. */ static void -parse_top_node_line (NODE *node, char **inptr) +parse_top_node_line (NODE *node, char **nodeptr) { - char *nodeptr = *inptr; char **store_in; int value_length; @@ -513,30 +569,30 @@ parse_top_node_line (NODE *node, char ** { store_in = 0; - nodeptr += skip_whitespace (nodeptr); + skip_input (nodeptr, skip_whitespace (*nodeptr)); /* Check what field we are looking at */ - if (!strncmp (nodeptr, INFO_FILE_LABEL, strlen(INFO_FILE_LABEL))) + if (!strncmp (*nodeptr, INFO_FILE_LABEL, strlen(INFO_FILE_LABEL))) { - nodeptr += strlen(INFO_FILE_LABEL); + skip_input (nodeptr, strlen(INFO_FILE_LABEL)); } - else if (!strncmp (nodeptr, INFO_NODE_LABEL, strlen(INFO_NODE_LABEL))) + else if (!strncmp (*nodeptr, INFO_NODE_LABEL, strlen(INFO_NODE_LABEL))) { - nodeptr += strlen(INFO_NODE_LABEL); + skip_input (nodeptr, strlen(INFO_NODE_LABEL)); } - else if (!strncmp (nodeptr, INFO_PREV_LABEL, strlen(INFO_PREV_LABEL))) + else if (!strncmp (*nodeptr, INFO_PREV_LABEL, strlen(INFO_PREV_LABEL))) { - nodeptr += strlen(INFO_PREV_LABEL); + skip_input (nodeptr, strlen(INFO_PREV_LABEL)); store_in = &(node->prev); } - else if (!strncmp (nodeptr, INFO_NEXT_LABEL, strlen(INFO_NEXT_LABEL))) + else if (!strncmp (*nodeptr, INFO_NEXT_LABEL, strlen(INFO_NEXT_LABEL))) { - nodeptr += strlen(INFO_NEXT_LABEL); + skip_input (nodeptr, strlen(INFO_NEXT_LABEL)); store_in = &(node->next); } - else if (!strncmp (nodeptr, INFO_UP_LABEL, strlen(INFO_UP_LABEL))) + else if (!strncmp (*nodeptr, INFO_UP_LABEL, strlen(INFO_UP_LABEL))) { - nodeptr += strlen(INFO_UP_LABEL); + skip_input (nodeptr, strlen(INFO_UP_LABEL)); store_in = &(node->up); } else @@ -544,28 +600,27 @@ parse_top_node_line (NODE *node, char ** /* Not recognized - code below will skip to next comma */ } - nodeptr += skip_whitespace (nodeptr); + skip_input(nodeptr, skip_whitespace (*nodeptr)); /* PARSE_NODE_START separates at commas or newlines, so it will work for filenames including full stops. */ - value_length = skip_node_characters (nodeptr, PARSE_NODE_START); + value_length = skip_node_characters (*nodeptr, PARSE_NODE_START); if (store_in) { (*store_in) = xmalloc (value_length + 1); - memmove (*store_in, nodeptr, value_length); + memmove (*store_in, *nodeptr, value_length); (*store_in) [value_length] = '\0'; } - nodeptr += value_length; - if ((*nodeptr) == '\n') + skip_input (nodeptr, value_length); + if ((**nodeptr) == '\n') { - nodeptr++; + skip_input (nodeptr, 1); break; } - nodeptr++; /* Point after field terminator */ + skip_input (nodeptr, 1); /* Point after field terminator */ } - *inptr = nodeptr; } static int @@ -585,7 +640,7 @@ colon_after_newline (char *nodeptr) /* Remove syntax from node->contents and build list of references in node. */ void -scan_node_contents (NODE *node) +scan_node_contents (NODE **tag) { SEARCH_BINDING s; char *search_string; @@ -594,6 +649,7 @@ scan_node_contents (NODE *node) char *new_contents = 0, *outptr = 0; int found_menu_entry, in_index = 0; + NODE *node = *tag; REFERENCE **refs = NULL; size_t refs_index = 0, refs_slots = 0; @@ -605,6 +661,13 @@ scan_node_contents (NODE *node) init_output_stream (&new_contents); + /* Set anchor_to_adjust to first anchor in node, if any. */ + anchor_to_adjust = tag + 1; + if (!*anchor_to_adjust) + anchor_to_adjust = 0; + else if (*anchor_to_adjust && (*anchor_to_adjust)->nodelen != 0) + anchor_to_adjust = 0; + /* Initialize refs to point to array of one null pointer in case * there are no results. This way we know if refs has been initialized * even if it is empty. */ @@ -612,7 +675,11 @@ scan_node_contents (NODE *node) refs_slots = 1; + /* This should be the only time we assign to nodeptr in this function - + all other assignment should be done with the helper functions above. */ nodeptr = node->contents; + input_start = node->contents; + nodestart = node->nodestart; parse_top_node_line (node, &nodeptr); deleted_lines++; @@ -663,9 +730,9 @@ search_again: /* Write out up to Menu label, and skip it */ copy_to -= 8; - write_and_advance (&outptr, nodeptr, copy_to - nodeptr); + copy_input_to_output (&outptr, &nodeptr, copy_to - nodeptr); + skip_input (&nodeptr, 8); - nodeptr = copy_to + 8; deleted_lines++; s.start = nodeptr - s.buffer; continue; @@ -687,16 +754,14 @@ search_again: } /* Write out up to current reference */ - write_and_advance (&outptr, nodeptr, copy_to - nodeptr); + copy_input_to_output (&outptr, &nodeptr, copy_to - nodeptr); - /* Skip notation */ - if (found_menu_entry) - nodeptr = copy_to; - else - nodeptr = copy_to + 5; + /* Skip "*Note" */ + if (!found_menu_entry) + skip_input (&nodeptr, 5); /* Search forward to ":" to get label name */ - nodeptr += skip_whitespace (nodeptr); + skip_input (&nodeptr, skip_whitespace (nodeptr)); colon_offset = string_in_line (":", nodeptr); /* Cross-references may have a newline in the middle. */ @@ -707,10 +772,7 @@ search_again: else if (colon_offset == -1) { /* This is not a menu entry or reference. */ - /* See mysql manual (mysql-nutshell) */ - /* FIXME: set nodeptr for both xrefs and mitems, making - sure we output everything we should */ - nodeptr++; + skip_input (&nodeptr, 1); s.start = nodeptr - s.buffer; continue; @@ -733,20 +795,21 @@ search_again: entry->label = xmalloc(colon_offset + 1); strncpy (entry->label, nodeptr, colon_offset); entry->label[colon_offset] = '\0'; + skip_input (&nodeptr, colon_offset + 1); /* Output reference text and set location of reference */ if (!found_menu_entry) { if (capital_s) - write_and_advance (&outptr, "See ", 4); + write_extra_bytes_to_output (&outptr, "See ", 4); else - write_and_advance (&outptr, "see ", 4); + write_extra_bytes_to_output (&outptr, "see ", 4); } /* Output any whitespace or newlines before reference label */ leading_whitespace = skip_whitespace_and_newlines (entry->label); - write_and_advance (&outptr, entry->label, leading_whitespace); + write_extra_bytes_to_output (&outptr, entry->label, leading_whitespace); underlining_on (&outptr); @@ -770,7 +833,7 @@ search_again: while (*labelptr != '\n' && *labelptr) labelptr++; newline_offset = labelptr - (entry->label + leading_whitespace); - write_and_advance(&outptr, entry->label + leading_whitespace, + write_extra_bytes_to_output (&outptr, entry->label + leading_whitespace, (*labelptr ? newline_offset : strlen(entry->label) - leading_whitespace)); @@ -786,13 +849,14 @@ search_again: underlining_off (&outptr); /* Output newline and any whitespace at start of line */ - write_and_advance (&outptr, labelptr, space_at_start_of_line); + write_extra_bytes_to_output (&outptr, labelptr, + space_at_start_of_line); labelptr += space_at_start_of_line; underlining_on (&outptr); /* Output rest of label */ - write_and_advance (&outptr, labelptr, + write_extra_bytes_to_output (&outptr, labelptr, entry->label + strlen(entry->label) - labelptr); /* Text of reference ends later in node because of terminal @@ -809,20 +873,17 @@ search_again: /* We've output the label, so now we can canonicalize it. */ canonicalize_whitespace (entry->label); - /* Read from after ':' to get target of reference. */ - nodeptr += colon_offset; nodeptr++; - /* If this reference entry continues with another ':' then the * nodename is the same as the label. */ if (*nodeptr == ':') { entry->nodename = xstrdup (entry->label); - nodeptr++; + skip_input (&nodeptr, 1); if (found_menu_entry) { /* Output two spaces to match the length of "::" */ - write_and_advance (&outptr, " ", 2); + write_extra_bytes_to_output (&outptr, " ", 2); } } else @@ -854,20 +915,18 @@ search_again: entry->line_number = info_parsed_line_number - deleted_lines; if (in_index) - { - /* For index nodes, output the destination as well, - which will be the name of the node the index entry - refers to. */ - write_and_advance (&outptr, nodeptr, length); - } - - nodeptr += length; + /* For index nodes, output the destination as well, + which will be the name of the node the index entry + refers to. */ + copy_input_to_output (&outptr, &nodeptr, length); + else + skip_input (&nodeptr, length); if (found_menu_entry && !in_index) /* Output spaces the length of the node specifier to avoid messing up left edge of second column of menu. */ for (i = 0; i < length; i++) - write_and_advance (&outptr, " ", 1); + write_extra_bytes_to_output (&outptr, " ", 1); } add_pointer_to_array (entry, refs_index, refs, refs_slots, 50); @@ -899,12 +958,10 @@ search_again: if (ptr_to_null_byte <= node->contents + node->nodelen - 3) { /* Write out up to tag. */ - write_and_advance (&outptr, nodeptr, + copy_input_to_output (&outptr, &nodeptr, ptr_to_null_byte + 3 - nodeptr); - /* Point to first character after ']' */ - nodeptr = ptr_to_null_byte + 3; - + /* Update search to start after tag. */ s.buffer = nodeptr; s.start = 0; s.end = node->nodelen - (nodeptr - node->contents); @@ -915,7 +972,7 @@ search_again: /* If we haven't accidentally gone past the end of the node, write out the rest of it. */ if (nodeptr < node->contents + node->nodelen) - write_and_advance (&outptr, nodeptr, + copy_input_to_output (&outptr, &nodeptr, (node->contents + node->nodelen) - nodeptr); node->references = refs; diff -up -x 'Makefile*' -x '*.o' -x '*~' info/info-utils.h info-adjust-anchors/info-utils.h --- info/info-utils.h 2014-03-06 00:57:30.000000000 +0000 +++ info-adjust-anchors/info-utils.h 2014-03-09 19:28:07.000000000 +0000 @@ -56,9 +56,11 @@ extern char *info_parsed_nodename; */ int info_parse_node (char *string, int flag); -/* If preprocess_nodes_p=On, remove syntax from NODE->contents and - place in NODE->content_cache. Set other fields of NODE. */ -void scan_node_contents (NODE *node); +/* NODE points to a tag table entry for a file. If preprocess_nodes_p=On, + remove syntax from (*NODE)->contents and place in NODE->content_cache, + and adjust offsets of anchors following node in tag table. Set other + fields of NODE. */ +void scan_node_contents (NODE **node); /* Get the entry associated with LABEL in REFERENCES. Return a pointer to the reference if found, or NULL. */ diff -up -x 'Makefile*' -x '*.o' -x '*~' info/nodes.c info-adjust-anchors/nodes.c --- info/nodes.c 2014-03-06 02:40:53.000000000 +0000 +++ info-adjust-anchors/nodes.c 2014-03-07 23:23:25.000000000 +0000 @@ -1077,12 +1077,13 @@ info_node_of_file_buffer_tags (FILE_BUFF does not output a terminating null, which breaks scan_node_contents. */ - scan_node_contents (tag); + scan_node_contents (&file_buffer->tags[i]); if (tag->content_cache) tag->contents = tag->content_cache; char *old_contents = tag->content_cache; +#if 0 /* Expand eventual \b[...\b] constructs in the contents. */ int new_nodelen; @@ -1095,6 +1096,8 @@ info_node_of_file_buffer_tags (FILE_BUFF if (old_contents) free (old_contents); } +#endif + *node = *tag; } else if (tag->nodelen == 0) /* anchor, return containing node */