diff options
Diffstat (limited to 'texinfo/info/nodes.c')
-rw-r--r-- | texinfo/info/nodes.c | 796 |
1 files changed, 387 insertions, 409 deletions
diff --git a/texinfo/info/nodes.c b/texinfo/info/nodes.c index 8995c78195f..f2737e7b354 100644 --- a/texinfo/info/nodes.c +++ b/texinfo/info/nodes.c @@ -21,17 +21,8 @@ Written by Brian Fox (bfox@ai.mit.edu). */ -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#if defined (HAVE_SYS_FILE_H) -#include <sys/file.h> -#endif /* HAVE_SYS_FILE_H */ -#include <sys/errno.h> -#include <sys/stat.h> -#if defined (HAVE_STRING_H) -#include <string.h> -#endif /* HAVE_STRING_H */ +#include "info.h" + #include "nodes.h" #include "search.h" #include "filesys.h" @@ -41,22 +32,10 @@ # include "man.h" #endif /* HANDLE_MAN_PAGES */ -#if !defined (O_RDONLY) -#if defined (HAVE_SYS_FCNTL_H) -#include <sys/fcntl.h> -#else /* !HAVE_SYS_FCNTL_H */ -#include <fcntl.h> -#endif /* !HAVE_SYS_FCNTL_H */ -#endif /* !O_RDONLY */ - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - /* **************************************************************** */ -/* */ -/* Functions Static to this File */ -/* */ +/* */ +/* Functions Static to this File */ +/* */ /* **************************************************************** */ static void forget_info_file (), remember_info_file (); @@ -81,9 +60,9 @@ static long get_node_length (); #define INFO_GET_TAGS 1 /* **************************************************************** */ -/* */ -/* Global Variables */ -/* */ +/* */ +/* Global Variables */ +/* */ /* **************************************************************** */ /* When non-zero, this is a string describing the recent file error. */ @@ -96,9 +75,9 @@ FILE_BUFFER **info_loaded_files = (FILE_BUFFER **)NULL; int info_loaded_files_slots = 0; /* **************************************************************** */ -/* */ -/* Public Functions for Node Manipulation */ -/* */ +/* */ +/* Public Functions for Node Manipulation */ +/* */ /* **************************************************************** */ /* Used to build "dir" menu from "localdir" files found in INFOPATH. */ @@ -142,8 +121,8 @@ info_get_node (filename, nodename) if (!file_buffer) { if (filesys_error_number) - info_recent_file_error = - filesys_error_string (filename, filesys_error_number); + info_recent_file_error = + filesys_error_string (filename, filesys_error_number); return ((NODE *)NULL); } @@ -154,9 +133,9 @@ info_get_node (filename, nodename) { node = info_get_node_of_file_buffer ("Top", file_buffer); if (!node) - node = info_get_node_of_file_buffer ("top", file_buffer); + node = info_get_node_of_file_buffer ("top", file_buffer); if (!node) - node = info_get_node_of_file_buffer ("TOP", file_buffer); + node = info_get_node_of_file_buffer ("TOP", file_buffer); } return (node); } @@ -193,7 +172,7 @@ info_get_node_of_file_buffer (nodename, file_buffer) node = (NODE *)xmalloc (sizeof (NODE)); node->filename = file_buffer->fullpath; node->parent = (char *)NULL; - node->nodename = strdup ("*"); + node->nodename = xstrdup ("*"); node->contents = file_buffer->contents; node->nodelen = file_buffer->filesize; node->flags = 0; @@ -203,7 +182,7 @@ info_get_node_of_file_buffer (nodename, file_buffer) the manpage node finding function instead. */ else if (file_buffer->flags & N_IsManPage) { - node = get_manpage_node (file_buffer, nodename); + node = get_manpage_node (file_buffer, nodename); } #endif /* HANDLE_MAN_PAGES */ /* If this is the "main" info file, it might contain a tags table. Search @@ -242,9 +221,9 @@ info_load_file (filename) /* **************************************************************** */ -/* */ -/* Private Functions Implementation */ -/* */ +/* */ +/* Private Functions Implementation */ +/* */ /* **************************************************************** */ /* The workhorse for info_find_file (). Non-zero 2nd argument says to @@ -263,58 +242,58 @@ info_find_file_internal (filename, get_tags) /* First try to find the file in our list of already loaded files. */ if (info_loaded_files) { - for (i = 0; file_buffer = info_loaded_files[i]; i++) - if ((strcmp (filename, file_buffer->filename) == 0) || - (strcmp (filename, file_buffer->fullpath) == 0) || - ((*filename != '/') && - strcmp (filename, - filename_non_directory (file_buffer->fullpath)) == 0)) - { - struct stat new_info, *old_info; - - /* This file is loaded. If the filename that we want is - specifically "dir", then simply return the file buffer. */ - if (strcasecmp (filename_non_directory (filename), "dir") == 0) - return (file_buffer); + for (i = 0; (file_buffer = info_loaded_files[i]); i++) + if ((strcmp (filename, file_buffer->filename) == 0) || + (strcmp (filename, file_buffer->fullpath) == 0) || + ((*filename != '/') && + strcmp (filename, + filename_non_directory (file_buffer->fullpath)) == 0)) + { + struct stat new_info, *old_info; + + /* This file is loaded. If the filename that we want is + specifically "dir", then simply return the file buffer. */ + if (strcasecmp (filename_non_directory (filename), "dir") == 0) + return (file_buffer); #if defined (HANDLE_MAN_PAGES) - /* Do the same for the magic MANPAGE file. */ - if (file_buffer->flags & N_IsManPage) - return (file_buffer); + /* Do the same for the magic MANPAGE file. */ + if (file_buffer->flags & N_IsManPage) + return (file_buffer); #endif /* HANDLE_MAN_PAGES */ - /* The file appears to be already loaded, and it is not "dir". - Check to see if it has changed since the last time it was - loaded. */ - if (stat (file_buffer->fullpath, &new_info) == -1) - { - filesys_error_number = errno; - return ((FILE_BUFFER *)NULL); - } - - old_info = &file_buffer->finfo; - - if ((new_info.st_size != old_info->st_size) || - (new_info.st_mtime != old_info->st_mtime)) - { - /* The file has changed. Forget that we ever had loaded it - in the first place. */ - forget_info_file (filename); - break; - } - else - { - /* The info file exists, and has not changed since the last - time it was loaded. If the caller requested a nodes list - for this file, and there isn't one here, build the nodes - for this file_buffer. In any case, return the file_buffer - object. */ - if (get_tags && !file_buffer->tags) - build_tags_and_nodes (file_buffer); - - return (file_buffer); - } - } + /* The file appears to be already loaded, and it is not "dir". + Check to see if it has changed since the last time it was + loaded. */ + if (stat (file_buffer->fullpath, &new_info) == -1) + { + filesys_error_number = errno; + return ((FILE_BUFFER *)NULL); + } + + old_info = &file_buffer->finfo; + + if ((new_info.st_size != old_info->st_size) || + (new_info.st_mtime != old_info->st_mtime)) + { + /* The file has changed. Forget that we ever had loaded it + in the first place. */ + forget_info_file (filename); + break; + } + else + { + /* The info file exists, and has not changed since the last + time it was loaded. If the caller requested a nodes list + for this file, and there isn't one here, build the nodes + for this file_buffer. In any case, return the file_buffer + object. */ + if (get_tags && !file_buffer->tags) + build_tags_and_nodes (file_buffer); + + return (file_buffer); + } + } } /* The file wasn't loaded. Try to load it now. */ @@ -364,21 +343,21 @@ info_load_file_internal (filename, get_tags) char *lowered_name; char *basename; - lowered_name = strdup (filename); + lowered_name = xstrdup (filename); basename = (char *) strrchr (lowered_name, '/'); if (basename) - basename++; + basename++; else - basename = lowered_name; + basename = lowered_name; while (*basename) - { - if (isupper (*basename)) - *basename = tolower (*basename); + { + if (isupper (*basename)) + *basename = tolower (*basename); - basename++; - } + basename++; + } fullpath = info_find_fullpath (lowered_name); free (lowered_name); @@ -402,8 +381,8 @@ info_load_file_internal (filename, get_tags) /* The file was found, and can be read. Allocate FILE_BUFFER and fill in the various members. */ file_buffer = make_file_buffer (); - file_buffer->filename = strdup (filename); - file_buffer->fullpath = strdup (fullpath); + file_buffer->filename = xstrdup (filename); + file_buffer->fullpath = xstrdup (fullpath); file_buffer->finfo = finfo; file_buffer->filesize = filesize; file_buffer->contents = contents; @@ -444,81 +423,81 @@ build_tags_and_nodes (file_buffer) if (position != -1) while (1) { - long tags_table_begin, tags_table_end; - - binding.end = position; - binding.start = binding.end - 5 - strlen (TAGS_TABLE_END_LABEL); - if (binding.start < 0) - binding.start = 0; - - position = find_node_separator (&binding); - - /* For this test, (and all others here) failure indicates a bogus - tags table. Grovel the file. */ - if (position == -1) - break; - - /* Remember the end of the tags table. */ - binding.start = position; - tags_table_end = binding.start; - binding.end = 0; - - /* Locate the start of the tags table. */ - position = search_backward (TAGS_TABLE_BEG_LABEL, &binding); - - if (position == -1) - break; - - binding.end = position; - binding.start = binding.end - 5 - strlen (TAGS_TABLE_BEG_LABEL); - position = find_node_separator (&binding); - - if (position == -1) - break; - - /* The file contains a valid tags table. Fill the FILE_BUFFER's - tags member. */ - file_buffer->flags |= N_HasTagsTable; - tags_table_begin = position; - - /* If this isn't an indirect tags table, just remember the nodes - described locally in this tags table. Note that binding.end - is pointing to just after the beginning label. */ - binding.start = binding.end; - binding.end = file_buffer->filesize; - - if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding)) - { - binding.start = tags_table_begin; - binding.end = tags_table_end; - get_nodes_of_tags_table (file_buffer, &binding); - return; - } - else - { - /* This is an indirect tags table. Build TAGS member. */ - SEARCH_BINDING indirect; - - indirect.start = tags_table_begin; - indirect.end = 0; - indirect.buffer = binding.buffer; - indirect.flags = S_FoldCase; - - position = search_backward (INDIRECT_TAGS_TABLE_LABEL, &indirect); - - if (position == -1) - { - /* This file is malformed. Give up. */ - return; - } - - indirect.start = position; - indirect.end = tags_table_begin; - binding.start = tags_table_begin; - binding.end = tags_table_end; - get_tags_of_indirect_tags_table (file_buffer, &indirect, &binding); - return; - } + long tags_table_begin, tags_table_end; + + binding.end = position; + binding.start = binding.end - 5 - strlen (TAGS_TABLE_END_LABEL); + if (binding.start < 0) + binding.start = 0; + + position = find_node_separator (&binding); + + /* For this test, (and all others here) failure indicates a bogus + tags table. Grovel the file. */ + if (position == -1) + break; + + /* Remember the end of the tags table. */ + binding.start = position; + tags_table_end = binding.start; + binding.end = 0; + + /* Locate the start of the tags table. */ + position = search_backward (TAGS_TABLE_BEG_LABEL, &binding); + + if (position == -1) + break; + + binding.end = position; + binding.start = binding.end - 5 - strlen (TAGS_TABLE_BEG_LABEL); + position = find_node_separator (&binding); + + if (position == -1) + break; + + /* The file contains a valid tags table. Fill the FILE_BUFFER's + tags member. */ + file_buffer->flags |= N_HasTagsTable; + tags_table_begin = position; + + /* If this isn't an indirect tags table, just remember the nodes + described locally in this tags table. Note that binding.end + is pointing to just after the beginning label. */ + binding.start = binding.end; + binding.end = file_buffer->filesize; + + if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding)) + { + binding.start = tags_table_begin; + binding.end = tags_table_end; + get_nodes_of_tags_table (file_buffer, &binding); + return; + } + else + { + /* This is an indirect tags table. Build TAGS member. */ + SEARCH_BINDING indirect; + + indirect.start = tags_table_begin; + indirect.end = 0; + indirect.buffer = binding.buffer; + indirect.flags = S_FoldCase; + + position = search_backward (INDIRECT_TAGS_TABLE_LABEL, &indirect); + + if (position == -1) + { + /* This file is malformed. Give up. */ + return; + } + + indirect.start = position; + indirect.end = tags_table_begin; + binding.start = tags_table_begin; + binding.end = tags_table_end; + get_tags_of_indirect_tags_table (file_buffer, &indirect, &binding); + return; + } } /* This file doesn't contain any kind of tags table. Grovel the @@ -561,37 +540,37 @@ get_nodes_of_info_file (file_buffer) /* If not there, this is not the start of a node. */ if (start == -1) - continue; + continue; /* Find the start of the nodename. */ start += skip_whitespace (nodeline + start); /* Find the end of the nodename. */ end = start + - skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES); + skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES); /* Okay, we have isolated the node name, and we know where the - node starts. Remember this information in a NODE structure. */ + node starts. Remember this information in a NODE structure. */ entry = (TAG *)xmalloc (sizeof (TAG)); entry->nodename = (char *)xmalloc (1 + (end - start)); strncpy (entry->nodename, nodeline + start, end - start); entry->nodename[end - start] = '\0'; entry->nodestart = nodestart; { - SEARCH_BINDING node_body; + 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); + 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); } entry->filename = file_buffer->fullpath; /* Add this tag to the array of tag structures in this FILE_BUFFER. */ add_pointer_to_array (entry, tags_index, file_buffer->tags, - file_buffer->tags_slots, 100, TAG *); + file_buffer->tags_slots, 100, TAG *); } } @@ -608,7 +587,7 @@ get_node_length (binding) for (i = binding->start, body = binding->buffer; i < binding->end; i++) { if (body[i] == INFO_FF || body[i] == INFO_COOKIE) - break; + break; } return ((long) i - binding->start); } @@ -652,16 +631,16 @@ get_nodes_of_tags_table (file_buffer, buffer_binding) /* Skip past informative "(Indirect)" tags table line. */ if (!tags_index && looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, search)) - continue; + continue; /* Find the label preceding the node name. */ offset = - string_in_line (INFO_NODE_LABEL, search->buffer + search->start); + string_in_line (INFO_NODE_LABEL, search->buffer + search->start); /* If not there, not a defining line, so we must be out of the - tags table. */ + tags table. */ if (offset == -1) - break; + break; /* Point to the beginning of the node definition. */ search->start += offset; @@ -670,11 +649,11 @@ get_nodes_of_tags_table (file_buffer, buffer_binding) /* Move past the node's name. */ for (offset = 0; - (nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP); - offset++); + (nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP); + offset++); if (nodedef[offset] != INFO_TAGSEP) - continue; + continue; entry = (TAG *)xmalloc (sizeof (TAG)); entry->nodename = (char *)xmalloc (1 + offset); @@ -687,13 +666,13 @@ get_nodes_of_tags_table (file_buffer, buffer_binding) entry->nodelen = -1; /* The filename of this node is currently known as the same as the - name of this file. */ + name of this file. */ entry->filename = file_buffer->fullpath; /* Add this node structure to the array of node structures in this - FILE_BUFFER. */ + FILE_BUFFER. */ add_pointer_to_array (entry, tags_index, file_buffer->tags, - file_buffer->tags_slots, 100, TAG *); + file_buffer->tags_slots, 100, TAG *); } free (search); } @@ -734,23 +713,23 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding) while (line < end) { - int colon; + int colon; - colon = string_in_line (":", line); + colon = string_in_line (":", line); - if (colon == -1) - break; + if (colon == -1) + break; - subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE)); - subfile->filename = (char *)xmalloc (colon); - strncpy (subfile->filename, line, colon - 1); - subfile->filename[colon - 1] = '\0'; - subfile->first_byte = (long) atol (line + colon); + subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE)); + subfile->filename = (char *)xmalloc (colon); + strncpy (subfile->filename, line, colon - 1); + subfile->filename[colon - 1] = '\0'; + subfile->first_byte = (long) atol (line + colon); - add_pointer_to_array - (subfile, subfiles_index, subfiles, subfiles_slots, 10, SUBFILE *); + add_pointer_to_array + (subfile, subfiles_index, subfiles, subfiles_slots, 10, SUBFILE *); - while (*line++ != '\n'); + while (*line++ != '\n'); } } @@ -768,10 +747,10 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding) SEARCH_BINDING binding; /* Find the length of the header of the file containing the indirect - tags table. This header appears at the start of every file. We - want the absolute position of each node within each subfile, so - we subtract the start of the containing subfile from the logical - position of the node, and then add the length of the header in. */ + tags table. This header appears at the start of every file. We + want the absolute position of each node within each subfile, so + we subtract the start of the containing subfile from the logical + position of the node, and then add the length of the header in. */ binding.buffer = file_buffer->contents; binding.start = 0; binding.end = file_buffer->filesize; @@ -779,81 +758,80 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding) header_length = find_node_separator (&binding); if (header_length == -1) - header_length = 0; + header_length = 0; /* Build the file buffer's list of subfiles. */ { - char *containing_dir, *temp; - int len_containing_dir; + char *containing_dir, *temp; + int len_containing_dir; - containing_dir = strdup (file_buffer->fullpath); - temp = (char *) strrchr (containing_dir, '/'); + containing_dir = xstrdup (file_buffer->fullpath); + temp = (char *) strrchr (containing_dir, '/'); - if (temp) - *temp = '\0'; + if (temp) + *temp = '\0'; - len_containing_dir = strlen (containing_dir); + len_containing_dir = strlen (containing_dir); - for (i = 0; subfiles[i]; i++); + for (i = 0; subfiles[i]; i++); - file_buffer->subfiles = (char **) xmalloc ((1 + i) * sizeof (char *)); + file_buffer->subfiles = (char **) xmalloc ((1 + i) * sizeof (char *)); - for (i = 0; subfiles[i]; i++) - { - char *fullpath; + for (i = 0; subfiles[i]; i++) + { + char *fullpath; - fullpath = (char *) xmalloc - (2 + strlen (subfiles[i]->filename) + len_containing_dir); + fullpath = (char *) xmalloc + (2 + strlen (subfiles[i]->filename) + len_containing_dir); - sprintf (fullpath, "%s/%s", - containing_dir, subfiles[i]->filename); + sprintf (fullpath, "%s/%s", + containing_dir, subfiles[i]->filename); - file_buffer->subfiles[i] = fullpath; - } - file_buffer->subfiles[i] = (char *)NULL; - free (containing_dir); + file_buffer->subfiles[i] = fullpath; + } + file_buffer->subfiles[i] = (char *)NULL; + free (containing_dir); } /* For each node in the file's tags table, remember the starting - position. */ - for (tags_index = 0; - entry = file_buffer->tags[tags_index]; - tags_index++) - { - for (i = 0; - subfiles[i] && entry->nodestart >= subfiles[i]->first_byte; - i++); - - /* If the Info file containing the indirect tags table is - malformed, then give up. */ - if (!i) - { - /* The Info file containing the indirect tags table is - malformed. Give up. */ - for (i = 0; subfiles[i]; i++) - { - free (subfiles[i]->filename); - free (subfiles[i]); - free (file_buffer->subfiles[i]); - } - file_buffer->subfiles = (char **)NULL; - free_file_buffer_tags (file_buffer); - return; - } - - /* SUBFILES[i] is the index of the first subfile whose logical - first byte is greater than the logical offset of this node's - starting position. This means that the subfile directly - preceding this one is the one containing the node. */ - - entry->filename = file_buffer->subfiles[i - 1]; - entry->nodestart -= subfiles[i -1]->first_byte; - entry->nodestart += header_length; - entry->nodelen = -1; - } + position. */ + for (tags_index = 0; (entry = file_buffer->tags[tags_index]); + tags_index++) + { + for (i = 0; + subfiles[i] && entry->nodestart >= subfiles[i]->first_byte; + i++); + + /* If the Info file containing the indirect tags table is + malformed, then give up. */ + if (!i) + { + /* The Info file containing the indirect tags table is + malformed. Give up. */ + for (i = 0; subfiles[i]; i++) + { + free (subfiles[i]->filename); + free (subfiles[i]); + free (file_buffer->subfiles[i]); + } + file_buffer->subfiles = (char **)NULL; + free_file_buffer_tags (file_buffer); + return; + } + + /* SUBFILES[i] is the index of the first subfile whose logical + first byte is greater than the logical offset of this node's + starting position. This means that the subfile directly + preceding this one is the one containing the node. */ + + entry->filename = file_buffer->subfiles[i - 1]; + entry->nodestart -= subfiles[i -1]->first_byte; + entry->nodestart += header_length; + entry->nodelen = -1; + } /* We have successfully built the tags table. Remember that it - was indirect. */ + was indirect. */ file_buffer->flags |= N_TagsIndirect; } @@ -878,105 +856,105 @@ info_node_of_file_buffer_tags (file_buffer, nodename) register int i; TAG *tag; - for (i = 0; tag = file_buffer->tags[i]; i++) + for (i = 0; (tag = file_buffer->tags[i]); i++) if (strcmp (nodename, tag->nodename) == 0) { - FILE_BUFFER *subfile; - - subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); - - if (!subfile) - return ((NODE *)NULL); - - if (!subfile->contents) - { - info_reload_file_buffer_contents (subfile); - - if (!subfile->contents) - return ((NODE *)NULL); - } - - /* If we were able to find this file and load it, then return - the node within it. */ - { - NODE *node; - - node = (NODE *)xmalloc (sizeof (NODE)); - node->filename = (subfile->fullpath); - node->nodename = tag->nodename; - node->contents = subfile->contents + tag->nodestart; - node->flags = 0; - node->parent = (char *)NULL; - - 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 - the node separator which starts this node, and NODE->contents - gets the address of the line defining this node. If we cannot - do that, the node isn't really here. */ - if (tag->nodelen == -1) - { - int min, max; - char *node_sep; - SEARCH_BINDING node_body; - char *buff_end; - - min = max = DEFAULT_INFO_FUDGE; - - if (tag->nodestart < DEFAULT_INFO_FUDGE) - min = tag->nodestart; - - if (DEFAULT_INFO_FUDGE > - (subfile->filesize - tag->nodestart)) - max = subfile->filesize - tag->nodestart; - - /* NODE_SEP gets the address of the separator which defines - this node, or (char *)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); - if (node_sep == (char *)NULL) - { - free (node); - return ((NODE *)NULL); - } - /* Readjust tag->nodestart. */ - tag->nodestart = node_sep - subfile->contents; - - /* Calculate the length of the current node. */ - buff_end = subfile->contents + subfile->filesize; - - node_body.buffer = node->contents; - node_body.start = 0; - node_body.end = buff_end - node_body.buffer; - node_body.flags = 0; - tag->nodelen = get_node_length (&node_body); - } - else - { - /* 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; - return (node); - } + FILE_BUFFER *subfile; + + subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); + + if (!subfile) + return ((NODE *)NULL); + + if (!subfile->contents) + { + info_reload_file_buffer_contents (subfile); + + if (!subfile->contents) + return ((NODE *)NULL); + } + + /* If we were able to find this file and load it, then return + the node within it. */ + { + NODE *node; + + node = (NODE *)xmalloc (sizeof (NODE)); + node->filename = (subfile->fullpath); + node->nodename = tag->nodename; + node->contents = subfile->contents + tag->nodestart; + node->flags = 0; + node->parent = (char *)NULL; + + 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 + the node separator which starts this node, and NODE->contents + gets the address of the line defining this node. If we cannot + do that, the node isn't really here. */ + if (tag->nodelen == -1) + { + int min, max; + char *node_sep; + SEARCH_BINDING node_body; + char *buff_end; + + min = max = DEFAULT_INFO_FUDGE; + + if (tag->nodestart < DEFAULT_INFO_FUDGE) + min = tag->nodestart; + + if (DEFAULT_INFO_FUDGE > + (subfile->filesize - tag->nodestart)) + max = subfile->filesize - tag->nodestart; + + /* NODE_SEP gets the address of the separator which defines + this node, or (char *)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); + if (node_sep == (char *)NULL) + { + free (node); + return ((NODE *)NULL); + } + /* Readjust tag->nodestart. */ + tag->nodestart = node_sep - subfile->contents; + + /* Calculate the length of the current node. */ + buff_end = subfile->contents + subfile->filesize; + + node_body.buffer = node->contents; + node_body.start = 0; + node_body.end = buff_end - node_body.buffer; + node_body.flags = 0; + tag->nodelen = get_node_length (&node_body); + } + else + { + /* 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; + return (node); + } } /* There was a tag table for this file, and the node wasn't found. @@ -985,9 +963,9 @@ info_node_of_file_buffer_tags (file_buffer, nodename) } /* **************************************************************** */ -/* */ -/* Managing file_buffers, nodes, and tags. */ -/* */ +/* */ +/* Managing file_buffers, nodes, and tags. */ +/* */ /* **************************************************************** */ /* Create a new, empty file buffer. */ @@ -1018,7 +996,7 @@ remember_info_file (file_buffer) ; add_pointer_to_array (file_buffer, i, info_loaded_files, - info_loaded_files_slots, 10, FILE_BUFFER *); + info_loaded_files_slots, 10, FILE_BUFFER *); } /* Forget the contents, tags table, nodes list, and names of FILENAME. */ @@ -1032,25 +1010,25 @@ forget_info_file (filename) if (!info_loaded_files) return; - for (i = 0; file_buffer = info_loaded_files[i]; i++) + for (i = 0; (file_buffer = info_loaded_files[i]); i++) if ((strcmp (filename, file_buffer->filename) == 0) || - (strcmp (filename, file_buffer->fullpath) == 0)) + (strcmp (filename, file_buffer->fullpath) == 0)) { - free (file_buffer->filename); - free (file_buffer->fullpath); + free (file_buffer->filename); + free (file_buffer->fullpath); - if (file_buffer->contents) - free (file_buffer->contents); - - /* Note that free_file_buffer_tags () also kills the subfiles - list, since the subfiles list is only of use in conjunction - with tags. */ - free_file_buffer_tags (file_buffer); + if (file_buffer->contents) + free (file_buffer->contents); + + /* Note that free_file_buffer_tags () also kills the subfiles + list, since the subfiles list is only of use in conjunction + with tags. */ + free_file_buffer_tags (file_buffer); - while (info_loaded_files[i] = info_loaded_files[++i]) - ; + while ((info_loaded_files[i] = info_loaded_files[++i])) + ; - break; + break; } } @@ -1065,8 +1043,8 @@ free_file_buffer_tags (file_buffer) { register TAG *tag; - for (i = 0; tag = file_buffer->tags[i]; i++) - free_info_tag (tag); + for (i = 0; (tag = file_buffer->tags[i]); i++) + free_info_tag (tag); free (file_buffer->tags); file_buffer->tags = (TAG **)NULL; @@ -1076,7 +1054,7 @@ free_file_buffer_tags (file_buffer) if (file_buffer->subfiles) { for (i = 0; file_buffer->subfiles[i]; i++) - free (file_buffer->subfiles[i]); + free (file_buffer->subfiles[i]); free (file_buffer->subfiles); file_buffer->subfiles = (char **)NULL; @@ -1160,29 +1138,29 @@ adjust_nodestart (node, min, max) sep_len = skip_node_separator (node->contents); /* If we managed to skip a node separator, then check for this node - being the right one. */ + being the right one. */ if (sep_len != 0) - { - char *nodedef, *nodestart; - int offset; - - nodestart = node_body.buffer + position + sep_len; - nodedef = nodestart; - offset = string_in_line (INFO_NODE_LABEL, nodedef); - - if (offset != -1) - { - nodedef += offset; - nodedef += skip_whitespace (nodedef); - offset = skip_node_characters (nodedef, DONT_SKIP_NEWLINES); - if ((offset == strlen (node->nodename)) && - (strncmp (node->nodename, nodedef, offset) == 0)) - { - node->contents = nodestart; - return (node_body.buffer + position); - } - } - } + { + char *nodedef, *nodestart; + int offset; + + nodestart = node_body.buffer + position + sep_len; + nodedef = nodestart; + offset = string_in_line (INFO_NODE_LABEL, nodedef); + + if (offset != -1) + { + nodedef += offset; + nodedef += skip_whitespace (nodedef); + offset = skip_node_characters (nodedef, DONT_SKIP_NEWLINES); + if ((offset == strlen (node->nodename)) && + (strncmp (node->nodename, nodedef, offset) == 0)) + { + node->contents = nodestart; + return (node_body.buffer + position); + } + } + } } /* Oh well, I guess we have to try to find it in a larger area. */ |