commit 5ba90b09ae8e08efa807cd4fc7b21772e7419bbc Author: Gavin Smith Date: Sun Mar 9 16:51:04 2014 +0000 * nodes.c (get_nodes_of_info_file): Set nodelen to -1 for all nodes. Initialize fields of NODE structure. (get_nodes_of_tag_table): Initialize fields of NODE structure. (info_node_of_file_buffer_tags): Call scan_node_contents on node contents before tags_expand. (info_get_node): Use strdup to allow calling info_parse_node in subsequent functions. (free_info_tag): Free tag.references if set. diff --git a/nodes.c b/nodes.c index 4c3344a..40674a9 100644 --- a/nodes.c +++ b/nodes.c @@ -82,24 +82,38 @@ extern void maybe_build_dir_node (char *dirname); If the node cannot be found, return NULL. */ NODE * -info_get_node (char *filename, char *nodename, int flag) +info_get_node (char *filename_in, char *nodename_in, int flag) { NODE *node; FILE_BUFFER *file_buffer = NULL; + char *filename = 0, *nodename = 0; + info_recent_file_error = NULL; - info_parse_node (nodename, flag); + info_parse_node (nodename_in, flag); nodename = NULL; + /* We need to duplicate info_parsed_filename because it can be rewritten + when info_get_node_of_file_buffer is called below (which eventually + calls scan_node_contents). */ + /* FIXME: Change info_parse_node to make all this easier */ + if (info_parsed_filename) - filename = info_parsed_filename; + filename = strdup(info_parsed_filename); + else if (filename_in) + filename = strdup(filename_in); if (info_parsed_nodename) - nodename = info_parsed_nodename; + nodename = strdup(info_parsed_nodename); + else if (nodename_in) + nodename = strdup(nodename_in); + /* See comment above for use of strdup() */ /* If FILENAME is not specified, it defaults to "dir". */ if (!filename) - filename = "dir"; + filename = strdup("dir"); + + /* Both filename and nodename are set by now. */ /* If the file to be looked up is "dir", build the contents from all of the "dir"s and "localdir"s found in INFOPATH. */ @@ -116,6 +130,7 @@ info_get_node (char *filename, char *nodename, int flag) if (filesys_error_number) info_recent_file_error = filesys_error_string (filename, filesys_error_number); + free(filename); free(nodename); return NULL; } } @@ -136,6 +151,7 @@ info_get_node (char *filename, char *nodename, int flag) node = info_get_node_of_file_buffer ("TOP", file_buffer); } + free(filename); free(nodename); return node; } @@ -568,18 +584,23 @@ get_nodes_of_info_file (FILE_BUFFER *file_buffer) entry->nodename = xmalloc (1 + (end - start)); strncpy (entry->nodename, nodeline + start, end - start); entry->nodename[end - start] = 0; - entry->nodestart = nodestart; + entry->nodestart = nodeline - binding.buffer; + entry->parent = 0; + entry->display_pos = 0; + entry->references = 0; + if (anchor) - entry->nodelen = 0; + { + entry->nodelen = 0; + entry->contents = 0; + } else { - SEARCH_BINDING node_body; - - node_body.buffer = binding.buffer + binding.start; - node_body.start = 0; - node_body.end = binding.end - binding.start; - node_body.flags = S_FoldCase; - entry->nodelen = get_node_length (&node_body); + /* Record that the node hasn't been parsed yet. */ + entry->nodelen = -1; + + entry->nodestart = nodeline - binding.buffer; + entry->contents = nodeline; } entry->filename = file_buffer->fullpath; @@ -669,7 +690,13 @@ get_nodes_of_tags_table (FILE_BUFFER *file_buffer, break; entry = xmalloc (sizeof (NODE)); + + /* Initialize sundry fields. */ entry->content_cache = NULL; + entry->references = 0; + entry->display_pos = 0; + entry->contents = 0; + entry->parent = 0; /* Find the beginning of the node definition. */ tmp_search->start += name_offset; @@ -961,6 +988,7 @@ info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer, char *nodename) if (strcmp (nodename, tag->nodename) == 0) { NODE *node; + /* If not a split file, subfile == file_buffer */ FILE_BUFFER *subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); if (!subfile) @@ -973,41 +1001,22 @@ info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer, char *nodename) return NULL; } + if (!tag->contents) + tag->contents = subfile->contents + tag->nodestart; + /* If we were able to find this file and load it, then return the node within it. */ - if (!(tag->nodestart >= 0 && tag->nodestart < subfile->filesize)) - return NULL; + if (!(tag->nodestart >= 0 && tag->nodestart < subfile->filesize)) + return NULL; - /* FIXME: why not just copy the NODE structure instead of - assigning the fields individually? */ node = xmalloc (sizeof (NODE)); - node->filename = subfile->fullpath; - node->parent = NULL; - node->nodename = tag->nodename; - - if (tag->content_cache) - node->contents = tag->content_cache; - else - node->contents = subfile->contents + tag->nodestart; - + /* FIXME: Why aren't these set already? */ + node->filename = subfile->fullpath; + node->parent = NULL; node->display_pos = 0; node->flags = 0; - node_set_body_start (node); - - if (file_buffer->flags & N_HasTagsTable) - { - node->flags |= N_HasTagsTable; - - if (file_buffer->flags & N_TagsIndirect) - { - node->flags |= N_TagsIndirect; - node->parent = file_buffer->fullpath; - } - } - - if (subfile->flags & N_IsCompressed) - node->flags |= N_IsCompressed; - + + /* If TAG->nodelen hasn't been calculated yet, then we aren't in a position to trust the entry pointer. Adjust things so that ENTRY->nodestart gets the exact address of the start of @@ -1040,10 +1049,9 @@ info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer, char *nodename) this node, or NULL if the node wasn't found. NODE->contents is side-effected to point to right after the separator. */ - node_sep = adjust_nodestart (node, min, max); + node_sep = adjust_nodestart (tag, min, max); if (node_sep == NULL) { - free (node); return NULL; } /* Readjust tag->nodestart. */ @@ -1052,33 +1060,80 @@ info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer, char *nodename) /* Calculate the length of the current node. */ buff_end = subfile->contents + subfile->filesize; - node_body.buffer = node->contents; + node_body.buffer = tag->contents; node_body.start = 0; node_body.end = buff_end - node_body.buffer; node_body.flags = 0; tag->nodelen = get_node_length (&node_body); - /* Expand eventual \b[...\b] constructs in the contents. - If found, update node->contents to point to the resulting - buffer. */ - if (tags_expand (node->contents, tag->nodelen, - &tag->content_cache, &tag->nodelen)) - node->contents = tag->content_cache; - node->nodelen = tag->nodelen; + + /* Initialize so we can know if parse_node or tags_expand + did anything. */ + tag->content_cache = 0; + + /* Read locations of references in node and similar. Rewrite + node from tag->contents to tag->content_cache if + preprocess_nodes=On. */ + /* TODO: Should we merge this with the previous step? */ + /* This has to be called before tags_expand because + tags_expand strips out the index markers, which we need + to alter the style of output indices. Also, tags_expand + does not output a terminating null, which breaks + scan_node_contents. */ + + scan_node_contents (tag); + if (tag->content_cache) + tag->contents = tag->content_cache; + + char *old_contents = tag->content_cache; + + /* Expand eventual \b[...\b] constructs in the contents. */ + + int new_nodelen; + if (tags_expand (tag->contents, tag->nodelen, + &tag->content_cache, &new_nodelen)) + { + tag->nodelen = new_nodelen; + + /* Free output of parse_node. */ + if (old_contents) + free (old_contents); + } + *node = *tag; } else if (tag->nodelen == 0) /* anchor, return containing node */ { - free (node); + free(node); node = find_node_of_anchor (file_buffer, tag); } else { + *node = *tag; + /* Since we know the length of this node, we have already adjusted tag->nodestart to point to the exact start of it. Simply skip the node separator. */ node->contents += skip_node_separator (node->contents); - node->nodelen = tag->nodelen; } + if (tag->content_cache) + node->contents = tag->content_cache; + + node_set_body_start (node); + + if (file_buffer->flags & N_HasTagsTable) + { + node->flags |= N_HasTagsTable; + + if (file_buffer->flags & N_TagsIndirect) + { + node->flags |= N_TagsIndirect; + node->parent = file_buffer->fullpath; + } + } + + if (subfile->flags & N_IsCompressed) + node->flags |= N_IsCompressed; + return node; } @@ -1186,6 +1241,7 @@ free_file_buffer_tags (FILE_BUFFER *file_buffer) static void free_info_tag (NODE *tag) { + if (tag->references) info_free_references (tag->references); free (tag->nodename); free (tag->content_cache);