[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[5443] nodes.c: reorder
From: |
Gavin D. Smith |
Subject: |
[5443] nodes.c: reorder |
Date: |
Sun, 13 Apr 2014 15:44:22 +0000 |
Revision: 5443
http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5443
Author: gavin
Date: 2014-04-13 15:44:21 +0000 (Sun, 13 Apr 2014)
Log Message:
-----------
nodes.c: reorder
Modified Paths:
--------------
trunk/ChangeLog
trunk/info/nodes.c
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2014-04-13 13:58:18 UTC (rev 5442)
+++ trunk/ChangeLog 2014-04-13 15:44:21 UTC (rev 5443)
@@ -1,5 +1,9 @@
2014-04-13 Gavin Smith <address@hidden>
+ * info/nodes.c: Reorder file into sections. No functional changes.
+
+2014-04-13 Gavin Smith <address@hidden>
+
* info/t/file.sh, info/t/file-node.sh, info/t/dir.sh,
info/t/dir-to-file.sh, info/t/dir-to-no-file.sh,
info/t/dir-file-menu.sh, info/t/dir-file-no-menu.sh,
Modified: trunk/info/nodes.c
===================================================================
--- trunk/info/nodes.c 2014-04-13 13:58:18 UTC (rev 5442)
+++ trunk/info/nodes.c 2014-04-13 15:44:21 UTC (rev 5443)
@@ -31,31 +31,6 @@
# include "man.h"
#endif /* HANDLE_MAN_PAGES */
-static void remember_info_file (FILE_BUFFER *file_buffer);
-static void free_file_buffer_tags (FILE_BUFFER *file_buffer);
-static void free_info_tag (TAG *tag);
-static void get_nodes_of_tags_table (FILE_BUFFER *file_buffer,
- SEARCH_BINDING *buffer_binding);
-static void get_nodes_of_info_file (FILE_BUFFER *file_buffer);
-static void get_tags_of_indirect_tags_table (FILE_BUFFER *file_buffer,
- SEARCH_BINDING *indirect_binding, SEARCH_BINDING *tags_binding);
-static void info_reload_file_buffer_contents (FILE_BUFFER *fb);
-static char *adjust_nodestart (NODE *node, int min, int max);
-static FILE_BUFFER *info_load_file_internal (char *filename, int get_tags);
-static FILE_BUFFER *info_find_file_internal (char *filename, int get_tags);
-static NODE *info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer,
- char *nodename);
-
-static long get_node_length (SEARCH_BINDING *binding);
-
-/* Magic number that RMS used to decide how much a tags table pointer could
- be off by. I feel that it should be much smaller, like 4. */
-#define DEFAULT_INFO_FUDGE 1000
-
-/* Passed to *_internal functions. INFO_GET_TAGS says to do what is
- neccessary to fill in the nodes or tags arrays in FILE_BUFFER. */
-#define INFO_NO_TAGS 0
-#define INFO_GET_TAGS 1
/* Global variables. */
@@ -68,342 +43,17 @@
/* The number of slots currently allocated to LOADED_FILES. */
size_t info_loaded_files_slots = 0;
-/* Public functions for node manipulation. */
+/* Functions for tag table creation and destruction. */
-/* Used to build `dir' menu from `localdir' files found in INFOPATH. */
-extern void maybe_build_dir_node (char *dirname);
+static long get_node_length (SEARCH_BINDING *binding);
+static void get_nodes_of_info_file (FILE_BUFFER *file_buffer);
+static void get_nodes_of_tags_table (FILE_BUFFER *file_buffer,
+ SEARCH_BINDING *buffer_binding);
+static void get_tags_of_indirect_tags_table (FILE_BUFFER *file_buffer,
+ SEARCH_BINDING *indirect_binding, SEARCH_BINDING *tags_binding);
+static void free_file_buffer_tags (FILE_BUFFER *file_buffer);
+static void free_info_tag (TAG *tag);
-/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME.
- If FILENAME is NULL, `dir' is used.
- If NODENAME is NULL, `Top' is used.
- The FLAG argument (one of the PARSE_NODE_* constants) instructs how to
- parse NODENAME.
-
- If the node cannot be found, return NULL. */
-NODE *
-info_get_node (char *filename, char *nodename, int flag)
-{
- NODE *node;
- FILE_BUFFER *file_buffer = NULL;
-
- info_recent_file_error = NULL;
- info_parse_node (nodename, flag);
- nodename = NULL;
-
- if (info_parsed_filename)
- filename = info_parsed_filename;
-
- if (info_parsed_nodename)
- nodename = info_parsed_nodename;
-
- /* If FILENAME is not specified, it defaults to "dir". */
- if (!filename)
- filename = "dir";
-
- /* If the file to be looked up is "dir", build the contents from all of
- the "dir"s and "localdir"s found in INFOPATH. */
- if (is_dir_name (filename))
- maybe_build_dir_node (filename);
-
- /* Find the correct info file, or give up. */
- file_buffer = info_find_file (filename);
- if (!file_buffer)
- {
- node = make_manpage_node (filename);
- if (!node)
- {
- if (filesys_error_number)
- info_recent_file_error =
- filesys_error_string (filename, filesys_error_number);
- return NULL;
- }
- }
- else
- /* Look for the node. */
- node = info_get_node_of_file_buffer (nodename, file_buffer);
-
- /* If the node not found was "Top", try again with different case,
- unless this was a man page. */
- if (!node
- && mbscasecmp (filename, MANPAGE_FILE_BUFFER_NAME) != 0
- && (nodename == NULL || mbscasecmp (nodename, "Top") == 0))
- {
- node = info_get_node_of_file_buffer ("Top", file_buffer);
- if (!node)
- node = info_get_node_of_file_buffer ("top", file_buffer);
- if (!node)
- node = info_get_node_of_file_buffer ("TOP", file_buffer);
- }
-
- return node;
-}
-
-static void
-node_set_body_start (NODE *node)
-{
- int n = skip_node_separator (node->contents);
- node->body_start = strcspn(node->contents + n, "\n");
- node->body_start += n;
- if (node->contents[++node->body_start] == '\n')
- ++node->body_start;
-}
-
-/* Return a pointer to a NODE structure for the Info node NODENAME in
- FILE_BUFFER. NODENAME can be passed as NULL, in which case the
- nodename of "Top" is used. If the node cannot be found, return a
- NULL pointer. */
-NODE *
-info_get_node_of_file_buffer (char *nodename, FILE_BUFFER *file_buffer)
-{
- NODE *node = NULL;
- int implicit_nodename = 0;
-
- /* If we are unable to find the file, we have to give up. There isn't
- anything else we can do. */
- if (!file_buffer)
- return NULL;
-
- /* If the file buffer was gc'ed, reload the contents now. */
- if (!file_buffer->contents)
- info_reload_file_buffer_contents (file_buffer);
-
- /* If NODENAME is not specified, it defaults to "Top". */
- if (!nodename)
- {
- nodename = "Top";
- implicit_nodename = 1; /* don't return man page for top */
- }
-
- /* If the name of the node that we wish to find is exactly "*", then the
- node body is the contents of the entire file. Create and return such
- a node. */
- if (strcmp (nodename, "*") == 0)
- {
- node = xmalloc (sizeof (NODE));
- node->filename = file_buffer->fullpath;
- node->parent = NULL;
- node->nodename = xstrdup ("*");
- node->contents = file_buffer->contents;
- node->nodelen = file_buffer->filesize;
- node->flags = 0;
- node->display_pos = 0;
- node_set_body_start (node);
- }
-#if defined (HANDLE_MAN_PAGES)
- /* If the file buffer is the magic one associated with manpages, call
- the manpage node finding function instead. */
- else if (!implicit_nodename && file_buffer->flags & N_IsManPage)
- {
- 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
- the tags table for an entry which matches the node that we want. If
- there is a tags table, get the file which contains this node, but don't
- bother building a node list for it. */
- else if (file_buffer->tags)
- {
- node = info_node_of_file_buffer_tags (file_buffer, nodename);
- }
-
- /* Return the results of our node search. */
- return node;
-}
-
-/* Locate the file named by FILENAME, and return the information structure
- describing this file. The file may appear in our list of loaded files
- already, or it may not. If it does not already appear, find the file,
- and add it to the list of loaded files. If the file cannot be found,
- return a NULL FILE_BUFFER *. */
-FILE_BUFFER *
-info_find_file (char *filename)
-{
- return info_find_file_internal (filename, INFO_GET_TAGS);
-}
-
-/* Load the info file FILENAME, remembering information about it in a
- file buffer. */
-FILE_BUFFER *
-info_load_file (char *filename)
-{
- return info_load_file_internal (filename, INFO_GET_TAGS);
-}
-
-
-/* Private functions implementation. */
-
-/* The workhorse for info_find_file (). Non-zero 2nd argument says to
- try to build a tags table (or otherwise glean the nodes) for this
- file once found. By default, we build the tags table, but when this
- function is called by info_get_node () when we already have a valid
- tags table describing the nodes, it is unnecessary. */
-static FILE_BUFFER *
-info_find_file_internal (char *filename, int get_tags)
-{
- int i;
- FILE_BUFFER *file_buffer;
-
- /* 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 ((FILENAME_CMP (filename, file_buffer->filename) == 0)
- || (FILENAME_CMP (filename, file_buffer->fullpath) == 0)
- || (!IS_ABSOLUTE (filename)
- && FILENAME_CMP (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 (is_dir_name (filename_non_directory (filename)))
- 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;
-#endif /* HANDLE_MAN_PAGES */
-
- /* The file appears to be already loaded, and is not "dir". Check
- to see if it's changed since the last time it was loaded. */
- if (stat (file_buffer->fullpath, &new_info) == -1)
- {
- filesys_error_number = errno;
- return 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 (!file_buffer->contents)
- {
- /* The file's contents have been gc'ed. Reload it. */
- info_reload_file_buffer_contents (file_buffer);
- if (!file_buffer->contents)
- return NULL;
- }
-
- 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. */
-#if defined (HANDLE_MAN_PAGES)
- /* If the name of the file that we want is our special file buffer for
- Unix manual pages, then create the file buffer, and return it now. */
- if (mbscasecmp (filename, MANPAGE_FILE_BUFFER_NAME) == 0)
- file_buffer = create_manpage_file_buffer ();
- else
-#endif /* HANDLE_MAN_PAGES */
- file_buffer = info_load_file_internal (filename, get_tags);
-
- /* If the file was loaded, remember the name under which it was found. */
- if (file_buffer)
- remember_info_file (file_buffer);
-
- return file_buffer;
-}
-
-/* The workhorse function for info_load_file (). Non-zero second argument
- says to build a list of tags (or nodes) for this file. This is the
- default behaviour when info_load_file () is called, but it is not
- necessary when loading a subfile for which we already have tags. */
-static FILE_BUFFER *
-info_load_file_internal (char *filename, int get_tags)
-{
- char *fullpath, *contents;
- size_t filesize;
- struct stat finfo;
- int retcode, compressed;
- FILE_BUFFER *file_buffer = NULL;
-
- /* Get the full pathname of this file, as known by the info system.
- That is to say, search along INFOPATH and expand tildes, etc. */
- fullpath = info_find_fullpath (filename);
-
- /* Did we actually find the file? */
- retcode = stat (fullpath, &finfo);
-
- /* If the file referenced by the name returned from info_find_fullpath ()
- doesn't exist, then try again with the last part of the filename
- appearing in lowercase. */
- /* This is probably not needed at all on those systems which define
- FILENAME_CMP to be mbscasecmp. But let's do it anyway, lest some
- network redirector supports case sensitivity. */
- if (retcode < 0)
- {
- char *lowered_name;
- char *tmp_basename;
-
- lowered_name = xstrdup (filename);
- tmp_basename = filename_non_directory (lowered_name);
-
- while (*tmp_basename)
- {
- if (isupper (*tmp_basename))
- *tmp_basename = tolower (*tmp_basename);
-
- tmp_basename++;
- }
-
- fullpath = info_find_fullpath (lowered_name);
-
- retcode = stat (fullpath, &finfo);
- free (lowered_name);
- }
-
- /* If the file wasn't found, give up, returning a NULL pointer. */
- if (retcode < 0)
- {
- filesys_error_number = errno;
- return NULL;
- }
-
- /* Otherwise, try to load the file. */
- contents = filesys_read_info_file (fullpath, &filesize, &finfo, &compressed);
-
- if (!contents)
- return NULL;
-
- /* 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 = xstrdup (filename);
- file_buffer->fullpath = xstrdup (fullpath);
- file_buffer->finfo = finfo;
- file_buffer->filesize = filesize;
- file_buffer->contents = contents;
- if (compressed)
- file_buffer->flags |= N_IsCompressed;
-
- /* If requested, build the tags and nodes for this file buffer. */
- if (get_tags)
- build_tags_and_nodes (file_buffer);
-
- return file_buffer;
-}
-
/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the
various slots. This can also be used to rebuild a tag or node table. */
void
@@ -509,6 +159,22 @@
get_nodes_of_info_file (file_buffer);
}
+/* Return the length of the node which starts at BINDING. */
+static long
+get_node_length (SEARCH_BINDING *binding)
+{
+ int i;
+ char *body;
+
+ /* [A node] ends with either a ^_, a ^L, or end of file. */
+ for (i = binding->start, body = binding->buffer; i < binding->end; i++)
+ {
+ if (body[i] == INFO_FF || body[i] == INFO_COOKIE)
+ break;
+ }
+ return i - binding->start;
+}
+
/* Search through FILE_BUFFER->contents building an array of TAG *,
one entry per each node present in the file. Store the tags in
FILE_BUFFER->tags, and the number of allocated slots in
@@ -589,22 +255,6 @@
}
}
-/* Return the length of the node which starts at BINDING. */
-static long
-get_node_length (SEARCH_BINDING *binding)
-{
- int i;
- char *body;
-
- /* [A node] ends with either a ^_, a ^L, or end of file. */
- for (i = binding->start, body = binding->buffer; i < binding->end; i++)
- {
- if (body[i] == INFO_FF || body[i] == INFO_COOKIE)
- break;
- }
- return i - binding->start;
-}
-
/* Build and save the array of nodes in FILE_BUFFER by searching through the
contents of BUFFER_BINDING for a tags table, and groveling the contents. */
static void
@@ -876,7 +526,496 @@
free (subfiles);
}
+/* Free the tags (if any) associated with FILE_BUFFER. */
+static void
+free_file_buffer_tags (FILE_BUFFER *file_buffer)
+{
+ int i;
+ if (file_buffer->tags)
+ {
+ TAG *tag;
+
+ for (i = 0; (tag = file_buffer->tags[i]); i++)
+ free_info_tag (tag);
+
+ free (file_buffer->tags);
+ file_buffer->tags = NULL;
+ file_buffer->tags_slots = 0;
+ }
+
+ if (file_buffer->subfiles)
+ {
+ for (i = 0; file_buffer->subfiles[i]; i++)
+ free (file_buffer->subfiles[i]);
+
+ free (file_buffer->subfiles);
+ file_buffer->subfiles = NULL;
+ }
+}
+
+/* Free the data associated with TAG, as well as TAG itself. */
+static void
+free_info_tag (TAG *tag)
+{
+ free (tag->nodename);
+ free (tag->content_cache);
+
+ /* We don't free tag->filename, because that filename is part of the
+ subfiles list for the containing FILE_BUFFER. free_info_tags ()
+ will free the subfiles when it is appropriate. */
+
+ free (tag);
+}
+
+/* Functions for retrieving files. */
+
+/* Passed to *_internal functions. INFO_GET_TAGS says to do what is
+ neccessary to fill in the nodes or tags arrays in FILE_BUFFER. */
+#define INFO_NO_TAGS 0
+#define INFO_GET_TAGS 1
+
+static FILE_BUFFER *info_find_file_internal (char *filename, int get_tags);
+static FILE_BUFFER *info_load_file_internal (char *filename, int get_tags);
+static void remember_info_file (FILE_BUFFER *file_buffer);
+static void info_reload_file_buffer_contents (FILE_BUFFER *fb);
+
+/* Locate the file named by FILENAME, and return the information structure
+ describing this file. The file may appear in our list of loaded files
+ already, or it may not. If it does not already appear, find the file,
+ and add it to the list of loaded files. If the file cannot be found,
+ return a NULL FILE_BUFFER *. */
+FILE_BUFFER *
+info_find_file (char *filename)
+{
+ return info_find_file_internal (filename, INFO_GET_TAGS);
+}
+
+/* Load the info file FILENAME, remembering information about it in a
+ file buffer. */
+FILE_BUFFER *
+info_load_file (char *filename)
+{
+ return info_load_file_internal (filename, INFO_GET_TAGS);
+}
+
+/* The workhorse for info_find_file (). Non-zero 2nd argument says to
+ try to build a tags table (or otherwise glean the nodes) for this
+ file once found. By default, we build the tags table, but when this
+ function is called by info_get_node () when we already have a valid
+ tags table describing the nodes, it is unnecessary. */
+static FILE_BUFFER *
+info_find_file_internal (char *filename, int get_tags)
+{
+ int i;
+ FILE_BUFFER *file_buffer;
+
+ /* 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 ((FILENAME_CMP (filename, file_buffer->filename) == 0)
+ || (FILENAME_CMP (filename, file_buffer->fullpath) == 0)
+ || (!IS_ABSOLUTE (filename)
+ && FILENAME_CMP (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 (is_dir_name (filename_non_directory (filename)))
+ 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;
+#endif /* HANDLE_MAN_PAGES */
+
+ /* The file appears to be already loaded, and is not "dir". Check
+ to see if it's changed since the last time it was loaded. */
+ if (stat (file_buffer->fullpath, &new_info) == -1)
+ {
+ filesys_error_number = errno;
+ return 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 (!file_buffer->contents)
+ {
+ /* The file's contents have been gc'ed. Reload it. */
+ info_reload_file_buffer_contents (file_buffer);
+ if (!file_buffer->contents)
+ return NULL;
+ }
+
+ 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. */
+#if defined (HANDLE_MAN_PAGES)
+ /* If the name of the file that we want is our special file buffer for
+ Unix manual pages, then create the file buffer, and return it now. */
+ if (mbscasecmp (filename, MANPAGE_FILE_BUFFER_NAME) == 0)
+ file_buffer = create_manpage_file_buffer ();
+ else
+#endif /* HANDLE_MAN_PAGES */
+ file_buffer = info_load_file_internal (filename, get_tags);
+
+ /* If the file was loaded, remember the name under which it was found. */
+ if (file_buffer)
+ remember_info_file (file_buffer);
+
+ return file_buffer;
+}
+
+/* The workhorse function for info_load_file (). Non-zero second argument
+ says to build a list of tags (or nodes) for this file. This is the
+ default behaviour when info_load_file () is called, but it is not
+ necessary when loading a subfile for which we already have tags. */
+static FILE_BUFFER *
+info_load_file_internal (char *filename, int get_tags)
+{
+ char *fullpath, *contents;
+ size_t filesize;
+ struct stat finfo;
+ int retcode, compressed;
+ FILE_BUFFER *file_buffer = NULL;
+
+ /* Get the full pathname of this file, as known by the info system.
+ That is to say, search along INFOPATH and expand tildes, etc. */
+ fullpath = info_find_fullpath (filename);
+
+ /* Did we actually find the file? */
+ retcode = stat (fullpath, &finfo);
+
+ /* If the file referenced by the name returned from info_find_fullpath ()
+ doesn't exist, then try again with the last part of the filename
+ appearing in lowercase. */
+ /* This is probably not needed at all on those systems which define
+ FILENAME_CMP to be mbscasecmp. But let's do it anyway, lest some
+ network redirector supports case sensitivity. */
+ if (retcode < 0)
+ {
+ char *lowered_name;
+ char *tmp_basename;
+
+ lowered_name = xstrdup (filename);
+ tmp_basename = filename_non_directory (lowered_name);
+
+ while (*tmp_basename)
+ {
+ if (isupper (*tmp_basename))
+ *tmp_basename = tolower (*tmp_basename);
+
+ tmp_basename++;
+ }
+
+ fullpath = info_find_fullpath (lowered_name);
+
+ retcode = stat (fullpath, &finfo);
+ free (lowered_name);
+ }
+
+ /* If the file wasn't found, give up, returning a NULL pointer. */
+ if (retcode < 0)
+ {
+ filesys_error_number = errno;
+ return NULL;
+ }
+
+ /* Otherwise, try to load the file. */
+ contents = filesys_read_info_file (fullpath, &filesize, &finfo, &compressed);
+
+ if (!contents)
+ return NULL;
+
+ /* 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 = xstrdup (filename);
+ file_buffer->fullpath = xstrdup (fullpath);
+ file_buffer->finfo = finfo;
+ file_buffer->filesize = filesize;
+ file_buffer->contents = contents;
+ if (compressed)
+ file_buffer->flags |= N_IsCompressed;
+
+ /* If requested, build the tags and nodes for this file buffer. */
+ if (get_tags)
+ build_tags_and_nodes (file_buffer);
+
+ return file_buffer;
+}
+
+/* Create a new, empty file buffer. */
+FILE_BUFFER *
+make_file_buffer (void)
+{
+ FILE_BUFFER *file_buffer = xmalloc (sizeof (FILE_BUFFER));
+
+ file_buffer->filename = file_buffer->fullpath = NULL;
+ file_buffer->contents = NULL;
+ file_buffer->tags = NULL;
+ file_buffer->subfiles = NULL;
+ file_buffer->tags_slots = 0;
+ file_buffer->flags = 0;
+
+ return file_buffer;
+}
+
+/* Add FILE_BUFFER to our list of already loaded info files. */
+static void
+remember_info_file (FILE_BUFFER *file_buffer)
+{
+ int i;
+
+ for (i = 0; info_loaded_files && info_loaded_files[i]; i++)
+ ;
+
+ add_pointer_to_array (file_buffer, i, info_loaded_files,
+ info_loaded_files_slots, 10);
+}
+
+/* Forget the contents, tags table, nodes list, and names of FILENAME. */
+void
+forget_info_file (char *filename)
+{
+ int i;
+ FILE_BUFFER *file_buffer;
+
+ if (!info_loaded_files)
+ return;
+
+ for (i = 0; (file_buffer = info_loaded_files[i]); i++)
+ if (FILENAME_CMP (filename, file_buffer->filename) == 0
+ || FILENAME_CMP (filename, file_buffer->fullpath) == 0)
+ {
+ free (file_buffer->filename);
+ free (file_buffer->fullpath);
+
+ if (file_buffer->contents)
+ free (file_buffer->contents);
+
+ /* 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);
+
+ /* Move rest of list down. */
+ while (info_loaded_files[i + 1])
+ {
+ info_loaded_files[i] = info_loaded_files[i + 1];
+ i++;
+ }
+ info_loaded_files[i] = 0;
+
+ break;
+ }
+}
+
+/* Load the contents of FILE_BUFFER->contents. This function is called
+ when a file buffer was loaded, and then in order to conserve memory, the
+ file buffer's contents were freed and the pointer was zero'ed. Note that
+ the file was already loaded at least once successfully, so the tags and/or
+ nodes members are still correctly filled. */
+static void
+info_reload_file_buffer_contents (FILE_BUFFER *fb)
+{
+ int is_compressed;
+
+#if defined (HANDLE_MAN_PAGES)
+ /* If this is the magic manpage node, don't try to reload, just give up. */
+ if (fb->flags & N_IsManPage)
+ return;
+#endif
+
+ fb->flags &= ~N_IsCompressed;
+
+ /* Let the filesystem do all the work for us. */
+ fb->contents =
+ filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo),
+ &is_compressed);
+ if (is_compressed)
+ fb->flags |= N_IsCompressed;
+}
+
+
+/* Functions for node retrieval. */
+
+/* Magic number that RMS used to decide how much a tags table pointer could
+ be off by. I feel that it should be much smaller, like 4. */
+#define DEFAULT_INFO_FUDGE 1000
+
+static char *adjust_nodestart (NODE *node, int min, int max);
+static void node_set_body_start (NODE *node);
+static NODE *find_node_of_anchor (FILE_BUFFER *file_buffer, TAG *tag);
+static char *adjust_nodestart (NODE *node, int min, int max);
+static NODE *info_node_of_file_buffer_tags (FILE_BUFFER *file_buffer,
+ char *nodename);
+
+/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME.
+ If FILENAME is NULL, `dir' is used.
+ If NODENAME is NULL, `Top' is used.
+ The FLAG argument (one of the PARSE_NODE_* constants) instructs how to
+ parse NODENAME.
+
+ If the node cannot be found, return NULL. */
+NODE *
+info_get_node (char *filename, char *nodename, int flag)
+{
+ NODE *node;
+ FILE_BUFFER *file_buffer = NULL;
+
+ /* Used to build `dir' menu from `localdir' files found in INFOPATH. */
+ extern void maybe_build_dir_node (char *dirname);
+
+ info_recent_file_error = NULL;
+ info_parse_node (nodename, flag);
+ nodename = NULL;
+
+ if (info_parsed_filename)
+ filename = info_parsed_filename;
+
+ if (info_parsed_nodename)
+ nodename = info_parsed_nodename;
+
+ /* If FILENAME is not specified, it defaults to "dir". */
+ if (!filename)
+ filename = "dir";
+
+ /* If the file to be looked up is "dir", build the contents from all of
+ the "dir"s and "localdir"s found in INFOPATH. */
+ if (is_dir_name (filename))
+ maybe_build_dir_node (filename);
+
+ /* Find the correct info file, or give up. */
+ file_buffer = info_find_file (filename);
+ if (!file_buffer)
+ {
+ node = make_manpage_node (filename);
+ if (!node)
+ {
+ if (filesys_error_number)
+ info_recent_file_error =
+ filesys_error_string (filename, filesys_error_number);
+ return NULL;
+ }
+ }
+ else
+ /* Look for the node. */
+ node = info_get_node_of_file_buffer (nodename, file_buffer);
+
+ /* If the node not found was "Top", try again with different case,
+ unless this was a man page. */
+ if (!node
+ && mbscasecmp (filename, MANPAGE_FILE_BUFFER_NAME) != 0
+ && (nodename == NULL || mbscasecmp (nodename, "Top") == 0))
+ {
+ node = info_get_node_of_file_buffer ("Top", file_buffer);
+ if (!node)
+ node = info_get_node_of_file_buffer ("top", file_buffer);
+ if (!node)
+ node = info_get_node_of_file_buffer ("TOP", file_buffer);
+ }
+
+ return node;
+}
+
+static void
+node_set_body_start (NODE *node)
+{
+ int n = skip_node_separator (node->contents);
+ node->body_start = strcspn(node->contents + n, "\n");
+ node->body_start += n;
+ if (node->contents[++node->body_start] == '\n')
+ ++node->body_start;
+}
+
+/* Return a pointer to a NODE structure for the Info node NODENAME in
+ FILE_BUFFER. NODENAME can be passed as NULL, in which case the
+ nodename of "Top" is used. If the node cannot be found, return a
+ NULL pointer. */
+NODE *
+info_get_node_of_file_buffer (char *nodename, FILE_BUFFER *file_buffer)
+{
+ NODE *node = NULL;
+ int implicit_nodename = 0;
+
+ /* If we are unable to find the file, we have to give up. There isn't
+ anything else we can do. */
+ if (!file_buffer)
+ return NULL;
+
+ /* If the file buffer was gc'ed, reload the contents now. */
+ if (!file_buffer->contents)
+ info_reload_file_buffer_contents (file_buffer);
+
+ /* If NODENAME is not specified, it defaults to "Top". */
+ if (!nodename)
+ {
+ nodename = "Top";
+ implicit_nodename = 1; /* don't return man page for top */
+ }
+
+ /* If the name of the node that we wish to find is exactly "*", then the
+ node body is the contents of the entire file. Create and return such
+ a node. */
+ if (strcmp (nodename, "*") == 0)
+ {
+ node = xmalloc (sizeof (NODE));
+ node->filename = file_buffer->fullpath;
+ node->parent = NULL;
+ node->nodename = xstrdup ("*");
+ node->contents = file_buffer->contents;
+ node->nodelen = file_buffer->filesize;
+ node->flags = 0;
+ node->display_pos = 0;
+ node_set_body_start (node);
+ }
+#if defined (HANDLE_MAN_PAGES)
+ /* If the file buffer is the magic one associated with manpages, call
+ the manpage node finding function instead. */
+ else if (!implicit_nodename && file_buffer->flags & N_IsManPage)
+ {
+ 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
+ the tags table for an entry which matches the node that we want. If
+ there is a tags table, get the file which contains this node, but don't
+ bother building a node list for it. */
+ else if (file_buffer->tags)
+ {
+ node = info_node_of_file_buffer_tags (file_buffer, nodename);
+ }
+
+ /* Return the results of our node search. */
+ return node;
+}
+
/* Return the node that contains TAG in FILE_BUFFER, else
(pathologically) NULL. Called from info_node_of_file_buffer_tags. */
static NODE *
@@ -945,6 +1084,90 @@
return node;
}
+/* Return the actual starting memory location of NODE, side-effecting
+ NODE->contents. MIN and MAX are bounds for a search if one is necessary.
+ Because of the way that tags are implemented, the physical nodestart may
+ not actually be where the tag says it is. If that is the case, but the
+ node was found anyway, set N_UpdateTags in NODE->flags. If the node is
+ found, return non-zero. NODE->contents is returned positioned right after
+ the node separator that precedes this node, while the return value is
+ position directly on the separator that precedes this node. If the node
+ could not be found, return a NULL pointer. */
+static char *
+adjust_nodestart (NODE *node, int min, int max)
+{
+ long position;
+ SEARCH_BINDING node_body;
+
+ /* Define the node body. */
+ node_body.buffer = node->contents;
+ node_body.start = 0;
+ node_body.end = max;
+ node_body.flags = 0;
+
+ /* Try the optimal case first. Who knows? This file may actually be
+ formatted (mostly) correctly. */
+ if (node_body.buffer[0] != INFO_COOKIE && min > 2)
+ node_body.buffer -= 3;
+
+ position = find_node_separator (&node_body);
+
+ /* If we found a node start, then check it out. */
+ if (position != -1)
+ {
+ int sep_len;
+
+ sep_len = skip_node_separator (node->contents);
+
+ /* If we managed to skip a node separator, then check for this node
+ 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, PARSE_NODE_START);
+ if (((unsigned int) offset == strlen (node->nodename)) &&
+ (strncmp (node->nodename, nodedef, offset) == 0))
+ {
+ node->contents = nodestart;
+ node_set_body_start (node);
+ return node_body.buffer + position;
+ }
+ }
+ }
+ }
+
+ /* Oh well, I guess we have to try to find it in a larger area. */
+ node_body.buffer = node->contents - min;
+ node_body.start = 0;
+ node_body.end = min + max;
+ node_body.flags = 0;
+
+ position = find_node_in_binding (node->nodename, &node_body);
+
+ /* If the node couldn't be found, we lose big. */
+ if (position == -1)
+ return NULL;
+
+ /* Otherwise, the node was found, but the tags table could need updating
+ (if we used a tag to get here, that is). Set the flag in NODE->flags. */
+ node->contents = node_body.buffer + position;
+ node->contents += skip_node_separator (node->contents);
+ node_set_body_start (node);
+ if (node->flags & N_HasTagsTable)
+ node->flags |= N_UpdateTags;
+ return node_body.buffer + position;
+}
+
/* Return the node from FILE_BUFFER which matches NODENAME by searching
the tags table in FILE_BUFFER, or NULL. */
static NODE *
@@ -1084,222 +1307,3 @@
Return NULL, since this file doesn't contain the desired node. */
return NULL;
}
-
-/* Managing file_buffers, nodes, and tags. */
-
-/* Create a new, empty file buffer. */
-FILE_BUFFER *
-make_file_buffer (void)
-{
- FILE_BUFFER *file_buffer = xmalloc (sizeof (FILE_BUFFER));
-
- file_buffer->filename = file_buffer->fullpath = NULL;
- file_buffer->contents = NULL;
- file_buffer->tags = NULL;
- file_buffer->subfiles = NULL;
- file_buffer->tags_slots = 0;
- file_buffer->flags = 0;
-
- return file_buffer;
-}
-
-/* Add FILE_BUFFER to our list of already loaded info files. */
-static void
-remember_info_file (FILE_BUFFER *file_buffer)
-{
- int i;
-
- for (i = 0; info_loaded_files && info_loaded_files[i]; i++)
- ;
-
- add_pointer_to_array (file_buffer, i, info_loaded_files,
- info_loaded_files_slots, 10);
-}
-
-/* Forget the contents, tags table, nodes list, and names of FILENAME. */
-void
-forget_info_file (char *filename)
-{
- int i;
- FILE_BUFFER *file_buffer;
-
- if (!info_loaded_files)
- return;
-
- for (i = 0; (file_buffer = info_loaded_files[i]); i++)
- if (FILENAME_CMP (filename, file_buffer->filename) == 0
- || FILENAME_CMP (filename, file_buffer->fullpath) == 0)
- {
- free (file_buffer->filename);
- free (file_buffer->fullpath);
-
- if (file_buffer->contents)
- free (file_buffer->contents);
-
- /* 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);
-
- /* Move rest of list down. */
- while (info_loaded_files[i + 1])
- {
- info_loaded_files[i] = info_loaded_files[i + 1];
- i++;
- }
- info_loaded_files[i] = 0;
-
- break;
- }
-}
-
-/* Free the tags (if any) associated with FILE_BUFFER. */
-static void
-free_file_buffer_tags (FILE_BUFFER *file_buffer)
-{
- int i;
-
- if (file_buffer->tags)
- {
- TAG *tag;
-
- for (i = 0; (tag = file_buffer->tags[i]); i++)
- free_info_tag (tag);
-
- free (file_buffer->tags);
- file_buffer->tags = NULL;
- file_buffer->tags_slots = 0;
- }
-
- if (file_buffer->subfiles)
- {
- for (i = 0; file_buffer->subfiles[i]; i++)
- free (file_buffer->subfiles[i]);
-
- free (file_buffer->subfiles);
- file_buffer->subfiles = NULL;
- }
-}
-
-/* Free the data associated with TAG, as well as TAG itself. */
-static void
-free_info_tag (TAG *tag)
-{
- free (tag->nodename);
- free (tag->content_cache);
-
- /* We don't free tag->filename, because that filename is part of the
- subfiles list for the containing FILE_BUFFER. free_info_tags ()
- will free the subfiles when it is appropriate. */
-
- free (tag);
-}
-
-/* Load the contents of FILE_BUFFER->contents. This function is called
- when a file buffer was loaded, and then in order to conserve memory, the
- file buffer's contents were freed and the pointer was zero'ed. Note that
- the file was already loaded at least once successfully, so the tags and/or
- nodes members are still correctly filled. */
-static void
-info_reload_file_buffer_contents (FILE_BUFFER *fb)
-{
- int is_compressed;
-
-#if defined (HANDLE_MAN_PAGES)
- /* If this is the magic manpage node, don't try to reload, just give up. */
- if (fb->flags & N_IsManPage)
- return;
-#endif
-
- fb->flags &= ~N_IsCompressed;
-
- /* Let the filesystem do all the work for us. */
- fb->contents =
- filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo),
- &is_compressed);
- if (is_compressed)
- fb->flags |= N_IsCompressed;
-}
-
-/* Return the actual starting memory location of NODE, side-effecting
- NODE->contents. MIN and MAX are bounds for a search if one is necessary.
- Because of the way that tags are implemented, the physical nodestart may
- not actually be where the tag says it is. If that is the case, but the
- node was found anyway, set N_UpdateTags in NODE->flags. If the node is
- found, return non-zero. NODE->contents is returned positioned right after
- the node separator that precedes this node, while the return value is
- position directly on the separator that precedes this node. If the node
- could not be found, return a NULL pointer. */
-static char *
-adjust_nodestart (NODE *node, int min, int max)
-{
- long position;
- SEARCH_BINDING node_body;
-
- /* Define the node body. */
- node_body.buffer = node->contents;
- node_body.start = 0;
- node_body.end = max;
- node_body.flags = 0;
-
- /* Try the optimal case first. Who knows? This file may actually be
- formatted (mostly) correctly. */
- if (node_body.buffer[0] != INFO_COOKIE && min > 2)
- node_body.buffer -= 3;
-
- position = find_node_separator (&node_body);
-
- /* If we found a node start, then check it out. */
- if (position != -1)
- {
- int sep_len;
-
- sep_len = skip_node_separator (node->contents);
-
- /* If we managed to skip a node separator, then check for this node
- 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, PARSE_NODE_START);
- if (((unsigned int) offset == strlen (node->nodename)) &&
- (strncmp (node->nodename, nodedef, offset) == 0))
- {
- node->contents = nodestart;
- node_set_body_start (node);
- return node_body.buffer + position;
- }
- }
- }
- }
-
- /* Oh well, I guess we have to try to find it in a larger area. */
- node_body.buffer = node->contents - min;
- node_body.start = 0;
- node_body.end = min + max;
- node_body.flags = 0;
-
- position = find_node_in_binding (node->nodename, &node_body);
-
- /* If the node couldn't be found, we lose big. */
- if (position == -1)
- return NULL;
-
- /* Otherwise, the node was found, but the tags table could need updating
- (if we used a tag to get here, that is). Set the flag in NODE->flags. */
- node->contents = node_body.buffer + position;
- node->contents += skip_node_separator (node->contents);
- node_set_body_start (node);
- if (node->flags & N_HasTagsTable)
- node->flags |= N_UpdateTags;
- return node_body.buffer + position;
-}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [5443] nodes.c: reorder,
Gavin D. Smith <=