texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[5255] Implement the --all (-a) option as per bug #38168.


From: Sergey Poznyakoff
Subject: [5255] Implement the --all (-a) option as per bug #38168.
Date: Mon, 15 Apr 2013 21:39:11 +0000

Revision: 5255
          http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5255
Author:   gray
Date:     2013-04-15 21:39:09 +0000 (Mon, 15 Apr 2013)
Log Message:
-----------
Implement the --all (-a) option as per bug #38168.

* info/infopath.c: New file.
* info/Makefile.am (ginfo_SOURCES): Add new file.
* info/tilde.c (tilde_expand_word): Argument is const char *.
All uses changed.
* info/info.c (all_matches_p): New variable.
(long_options, short_options): New option --all (-a).
(single_file, all_files): New functions.
(main): Handle new option.
* info/nodes.c (forget_info_file): Now extern.
* info/nodes.h (forget_info_file): New proto.
* info/indices.c (create_virtindex_file_buffer): Allow for
NULL as the filename.
(allfiles_create_node, info_all_files): New functions.
* info/dir.c (maybe_build_dir_node): Use infopath_first and
infopath_next to iterate over the INFOPATH.
* info/filesys.c: Remove infopath functions. See infopath.c
(info_file_in_path, info_file_find_next_in_path): New functions.
* info/indices.h (allfiles_create_node): New prototype.
* info/filesys.h (infopath): Remove extern.
(infopath): New prototype.
(zap_infopath): Rename to infopath_clear.
(info_add_path): Rename to infopath_add.
(infopath_init,infopath_first,infopath_next)
(info_file_find_next_in_path): New prototypes.
(INFOPATH_INIT): New constant.
* info/session.c (info_read_and_dispatch): Do not set
quit_info_immediately, it is done by info_quit.
(info_follow_menus): Take an additional argument.
(info_quit): Set quit_info_immediately.
* info/session.h (quit_info_immediately): Extern.
(info_follow_menus): Change signature.
* info/infomap.c: Bind `C-x f' in Emacs mode, and `:a' in Vi mode
to info_all_files.

* doc/info-stnd.texi: Document the --all option.

Ticket Links:
------------
    http://savannah.gnu.org/bugs/?38168

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/info/Makefile.am
    trunk/info/dir.c
    trunk/info/filesys.c
    trunk/info/filesys.h
    trunk/info/indices.c
    trunk/info/indices.h
    trunk/info/info.c
    trunk/info/infodoc.c
    trunk/info/infomap.c
    trunk/info/nodes.c
    trunk/info/nodes.h
    trunk/info/session.c
    trunk/info/session.h
    trunk/info/tilde.c
    trunk/info/tilde.h

Added Paths:
-----------
    trunk/info/infopath.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog     2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/ChangeLog     2013-04-15 21:39:09 UTC (rev 5255)
@@ -1,3 +1,43 @@
+2013-04-16  Sergey Poznyakoff  <address@hidden>
+
+       Implement the --all (-a) option as per bug #38168.
+
+       * info/infopath.c: New file.
+       * info/Makefile.am (ginfo_SOURCES): Add new file.
+       * info/tilde.c (tilde_expand_word): Argument is const char *.
+       All uses changed.
+       * info/info.c (all_matches_p): New variable.
+       (long_options, short_options): New option --all (-a).
+       (single_file, all_files): New functions.
+       (main): Handle new option.
+       * info/nodes.c (forget_info_file): Now extern.
+       * info/nodes.h (forget_info_file): New proto.
+       * info/indices.c (create_virtindex_file_buffer): Allow for
+       NULL as the filename.
+       (allfiles_create_node, info_all_files): New functions.
+       * info/dir.c (maybe_build_dir_node): Use infopath_first and
+       infopath_next to iterate over the INFOPATH.
+       * info/filesys.c: Remove infopath functions. See infopath.c
+       (info_file_in_path, info_file_find_next_in_path): New functions.
+       * info/indices.h (allfiles_create_node): New prototype.
+       * info/filesys.h (infopath): Remove extern.
+       (infopath): New prototype.
+       (zap_infopath): Rename to infopath_clear.
+       (info_add_path): Rename to infopath_add.
+       (infopath_init,infopath_first,infopath_next)
+       (info_file_find_next_in_path): New prototypes.
+       (INFOPATH_INIT): New constant.
+       * info/session.c (info_read_and_dispatch): Do not set
+       quit_info_immediately, it is done by info_quit.
+       (info_follow_menus): Take an additional argument.
+       (info_quit): Set quit_info_immediately.
+       * info/session.h (quit_info_immediately): Extern.
+       (info_follow_menus): Change signature.
+       * info/infomap.c: Bind `C-x f' in Emacs mode, and `:a' in Vi mode
+       to info_all_files.
+
+       * doc/info-stnd.texi: Document the --all option.
+
 2013-04-13  Sergey Poznyakoff  <address@hidden>
 
        * info/infomap.c: Fix indentation and style.

Modified: trunk/info/Makefile.am
===================================================================
--- trunk/info/Makefile.am      2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/Makefile.am      2013-04-15 21:39:09 UTC (rev 5255)
@@ -38,7 +38,7 @@
   echo-area.c echo-area.h \
   filesys.c filesys.h footnotes.c footnotes.h gc.c gc.h \
   indices.c indices.h info-utils.c info-utils.h info.c info.h infodoc.c \
-  infomap.c infomap.h m-x.c man.c man.h nodemenu.c nodes.c nodes.h \
+  infomap.c infomap.h infopath.c m-x.c man.c man.h nodemenu.c nodes.c nodes.h \
   search.c search.h session.c session.h signals.c signals.h \
   tag.c tag.h termdep.h terminal.c terminal.h tilde.c tilde.h \
   variables.c variables.h window.c window.h

Modified: trunk/info/dir.c
===================================================================
--- trunk/info/dir.c    2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/dir.c    2013-04-15 21:39:09 UTC (rev 5255)
@@ -95,14 +95,15 @@
      with the dir file just found.  */
   new_dir_file_p (&dir_buffer->finfo);
   
-  path_index = update_tags = 0;
+  update_tags = 0;
 
   /* Using each element of the path, check for one of the files in
      DIRS_TO_ADD.  Do not check for "localdir.info.Z" or anything else.
      Only files explictly named are eligible.  This is a design decision.
      There can be an info file name "localdir.info" which contains
      information on the setting up of "localdir" files. */
-  while ((this_dir = extract_colon_unit (infopath, &path_index)))
+  for (this_dir = infopath_first (&path_index); this_dir; 
+       this_dir = infopath_next (&path_index))
     {
       register int da_index;
       char *from_file;

Modified: trunk/info/filesys.c
===================================================================
--- trunk/info/filesys.c        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/filesys.c        2013-04-15 21:39:09 UTC (rev 5255)
@@ -29,10 +29,8 @@
 static char *info_file_in_path (char *filename, char *path);
 static char *lookup_info_filename (char *filename);
 static char *info_absolute_file (char *fname);
-static char *build_infopath_from_path (void);
 
 static void remember_info_filename (char *filename, char *expansion);
-static void maybe_initialize_infopath (void);
 
 typedef struct
 {
@@ -75,13 +73,6 @@
   { NULL, NULL }
 };
 
-/* The path on which we look for info files.  You can initialize this
-   from the environment variable INFOPATH if there is one, or you can
-   call info_add_path () to add paths to the beginning or end of it.
-   You can call zap_infopath () to make the path go away. */
-char *infopath = NULL;
-static int infopath_size = 0;
-
 /* Expand the filename in PARTIAL to make a real name for this operating
    system.  This looks in INFO_PATHS in order to find the correct file.
    If it can't find the file, it returns NULL. */
@@ -98,8 +89,6 @@
 
   filesys_error_number = 0;
 
-  maybe_initialize_infopath ();
-
   if (partial && (initial_character = *partial))
     {
       char *expansion;
@@ -149,7 +138,7 @@
            partial = local_temp_filename;
         }
       else
-        temp = info_file_in_path (partial, infopath);
+        temp = info_file_in_path (partial, infopath ());
 
       if (temp)
         {
@@ -169,8 +158,8 @@
 /* Scan the list of directories in PATH looking for FILENAME.  If we find
    one that is a regular file, return it as a new string.  Otherwise, return
    a NULL pointer. */
-static char *
-info_file_in_path (char *filename, char *path)
+char *
+info_file_find_next_in_path (char *filename, char *path, int *diridx)
 {
   struct stat finfo;
   char *temp_dirname;
@@ -181,9 +170,7 @@
   if (!*filename || STREQ (filename, ".") || STREQ (filename, ".."))
     return NULL;
 
-  dirname_index = 0;
-
-  while ((temp_dirname = extract_colon_unit (path, &dirname_index)))
+  while ((temp_dirname = extract_colon_unit (path, diridx)))
     {
       register int i, pre_suffix_length;
       char *temp;
@@ -268,6 +255,13 @@
   return NULL;
 }
 
+static char *
+info_file_in_path (char *filename, char *path)
+{
+  int i = 0;
+  return info_file_find_next_in_path (filename, path, &i);
+}
+
 /* Assume FNAME is an absolute file name, and check whether it is
    a regular file.  If it is, return it as a new string; otherwise
    return a NULL pointer.  We do it by taking the file name apart
@@ -369,205 +363,21 @@
   names_and_files[names_and_files_index] = NULL;
 }
 
-static void
-maybe_initialize_infopath (void)
-{
-  if (!infopath_size)
-    {
-      infopath = (char *)
-        xmalloc (infopath_size = (1 + strlen (DEFAULT_INFOPATH)));
-      debug(2, ("INFOPATH=%s", DEFAULT_INFOPATH));
-      strcpy (infopath, DEFAULT_INFOPATH);
-    }
-}
-
-/* For each path element PREFIX/DIR in PATH substitute either
-   PREFIX/share/info or PREFIX/info if that directory exists.
-   Avoid duplicates from, e.g., PREFIX/bin and PREFIX/sbin. */
-static char *
-build_infopath_from_path (void)
-{
-  typedef struct path_el
-    {
-      struct path_el *next;
-      char *path;
-      unsigned int len;
-    } PATH_EL, *PATH_PTR;
-
-  PATH_EL path_head = { NULL, NULL, 1 };
-  PATH_PTR path_prev, path_next;
-  char *res, *path_from_env, *temp_dirname;
-  int dirname_index = 0;
-  struct stat finfo;
-
-  path_from_env = getenv ("PATH");
-
-  while ((temp_dirname = extract_colon_unit (path_from_env, &dirname_index)))
-    {
-      unsigned int i, dir = 0;
-
-      /* Find end of DIRNAME/ (but ignore "/") */
-      for (i = 0; temp_dirname[i]; i++)
-        if (i && IS_SLASH (temp_dirname[i]))
-          dir = i + 1;
-
-      /* Discard path elements ending with "/", "/.", or "/.." */
-      if (!temp_dirname[dir] || STREQ (temp_dirname + dir, ".") || STREQ 
(temp_dirname + dir, "."))
-        dir = 0;
-      
-      path_prev = &path_head;
-      while (dir && (path_next = path_prev->next))
-        {
-          /* Ignore duplicate DIRNAME */
-          if (dir == path_next->len && strncmp (temp_dirname, path_next->path, 
dir) == 0)
-            dir = 0;
-
-          path_prev = path_next;
-        }
-
-      if (dir)
-        {
-          temp_dirname = xrealloc (temp_dirname, dir + strlen ("share/info") 
+1);
-
-          /* first try DIRNAME/share/info */
-          strcpy (temp_dirname + dir, "share/info");
-          if (stat (temp_dirname, &finfo) != 0 || !S_ISDIR (finfo.st_mode))
-            {
-              /* then try DIRNAME/info */
-              strcpy (temp_dirname + dir, "info");
-              if (stat (temp_dirname, &finfo) != 0 || !S_ISDIR (finfo.st_mode))
-                dir = 0;
-            }
-        }
-
-      if (dir)
-        {
-          path_next = xmalloc (sizeof (PATH_EL));
-          path_next->next = NULL;
-          path_next->path = temp_dirname;
-          path_next->len = dir;
-          path_prev->next = path_next;
-          path_head.len += strlen (temp_dirname) + 1;
-        }
-      else
-        free (temp_dirname);
-    }
-
-  /* Build the resulting sequence of paths */
-  res = xmalloc (path_head.len);
-  res[0] = '\0';
-
-  for (path_prev = path_head.next; path_prev; path_prev = path_next)
-    {
-      strcat (res, path_prev->path);
-      if ((path_next = path_prev->next))
-        strcat (res, PATH_SEP);
-
-      free (path_prev->path);
-      free (path_prev);
-    }
-
-  return res;
-}
-
-/* Add PATH to the list of paths found in INFOPATH.  2nd argument says
-   whether to put PATH at the front or end of INFOPATH.
-   Replace one path element "PATH" in PATH by a sequence of
-   path elements derived from the environment variable PATH. */
 void
-info_add_path (char *path, int where)
+forget_file_names (void)
 {
-  int len;
-  int found = 0;
-  unsigned int i, j;
+  int i;
 
-  /* Search for "PATH" in PATH */
-  for (i = 0; path[i]; i++)
+  for (i = 0; i < names_and_files_index; i++)
     {
-      j = i + strlen ("PATH");
-      if (strncmp (path + i, "PATH", strlen ("PATH")) == 0 &&
-          (!path[j] || path[j] == PATH_SEP[0]))
-        {
-          found = 1;
-          break;
-        }
-      else
-        {
-          /* Advance to next PATH_SEP.  */
-          while (path[i] && path[i] != PATH_SEP[0])
-            i++;
-
-          if (!path[i])
-            break;
-        }
+      free (names_and_files[i]->filename);
+      free (names_and_files[i]->expansion);
+      free (names_and_files[i]);
+      names_and_files[i] = NULL;
     }
-
-  if (found)
-    {
-      /* Build infopath from the environment variable PATH */
-      char *temp = build_infopath_from_path ();
-
-      if (i || path[j])
-        {
-          char *old_path = path;
-
-          /* Splice it into OLD_PATH */
-          path = xmalloc (1 + strlen (temp) + strlen (old_path) - strlen 
("PATH"));
-          if (i)
-            strncpy (path, old_path, i);
-          strcpy (path + i, temp);
-          if (old_path[j])
-            strcat (path, old_path + j);
-
-          free (temp);
-        }
-      else
-        path = temp;
-    }
-
-  if (!infopath)
-    {
-      infopath = xmalloc (infopath_size = 200 + strlen (path));
-      infopath[0] = '\0';
-    }
-
-  len = strlen (path) + strlen (infopath);
-
-  if (len + 2 >= infopath_size)
-    infopath = xrealloc (infopath, (infopath_size += (2 * len) + 2));
-
-  if (!*infopath)
-    strcpy (infopath, path);
-  else if (where == INFOPATH_APPEND)
-    {
-      strcat (infopath, PATH_SEP);
-      strcat (infopath, path);
-    }
-  else if (where == INFOPATH_PREPEND)
-    {
-      char *temp = xstrdup (infopath);
-      strcpy (infopath, path);
-      strcat (infopath, PATH_SEP);
-      strcat (infopath, temp);
-      free (temp);
-    }
-  debug(2, ("INFOPATH=%s", infopath));
-  if (found)
-    free (path);
+  names_and_files_index = 0;
 }
-
-/* Make INFOPATH have absolutely nothing in it. */
-void
-zap_infopath (void)
-{
-  if (infopath)
-    free (infopath);
-  
-  infopath = NULL;
-  infopath_size = 0;
-  debug(2, ("INFOPATH cleared"));
-}
-
+
 /* Given a chunk of text and its length, convert all CRLF pairs at every
    end-of-line into a single Newline character.  Return the length of
    produced text.

Modified: trunk/info/filesys.h
===================================================================
--- trunk/info/filesys.h        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/filesys.h        2013-04-15 21:39:09 UTC (rev 5255)
@@ -25,18 +25,27 @@
 /* The path on which we look for info files.  You can initialize this
    from the environment variable INFOPATH if there is one, or you can
    call info_add_path () to add paths to the beginning or end of it. */
-extern char *infopath;
 
+extern char *infopath ();
+
+/* Initialize INFOPATH */
+void infopath_init (void);
+
 /* Make INFOPATH have absolutely nothing in it. */
-extern void zap_infopath (void);
+extern void infopath_clear (void);
 
 /* Add PATH to the list of paths found in INFOPATH.  2nd argument says
    whether to put PATH at the front or end of INFOPATH. */
-extern void info_add_path (char *path, int where);
+extern void infopath_add (char *path, int where);
 
-/* Defines that are passed along with the pathname to info_add_path (). */
+/* Iterate over INFOPATH */
+char *infopath_first (int *idx);
+char *infopath_next (int *idx);
+
+/* Defines that are passed along with the pathname to infopath_add (). */
 #define INFOPATH_PREPEND 0
 #define INFOPATH_APPEND  1
+#define INFOPATH_INIT    2
 
 /* Expand the filename in PARTIAL to make a real name for this operating
    system.  This looks in INFO_PATHS in order to find the correct file.
@@ -76,6 +85,12 @@
 /* Return true if FILENAME is `dir', with a possible compression suffix.  */
 extern int is_dir_name (char *filename);
 
+/* Scan the list of directories in PATH looking for FILENAME.  If we find
+   one that is a regular file, return it as a new string.  Otherwise, return
+   a NULL pointer. */
+extern char *info_file_find_next_in_path (char *filename, char *path,
+                                         int *diridx);
+
 /* The default value of INFOPATH. */
 #if !defined (DEFAULT_INFOPATH)
 #  define DEFAULT_INFOPATH 
".:PATH:/usr/local/info:/usr/info:/usr/local/lib/info:/usr/lib/info:/usr/local/gnu/info:/usr/local/gnu/lib/info:/usr/gnu/info:/usr/gnu/lib/info:/opt/gnu/info:/usr/share/info:/usr/share/lib/info:/usr/local/share/info:/usr/local/share/lib/info:/usr/gnu/lib/emacs/info:/usr/local/gnu/lib/emacs/info:/usr/local/lib/emacs/info:/usr/local/emacs/info"

Modified: trunk/info/indices.c
===================================================================
--- trunk/info/indices.c        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/indices.c        2013-04-15 21:39:09 UTC (rev 5255)
@@ -810,8 +810,8 @@
   FILE_BUFFER *file_buffer;
 
   file_buffer = make_file_buffer ();
-  file_buffer->filename = xstrdup (filename);
-  file_buffer->fullpath = xstrdup (filename);
+  file_buffer->filename = filename ? xstrdup (filename) : NULL;
+  file_buffer->fullpath = filename ? xstrdup (filename) : NULL;
   file_buffer->finfo.st_size = 0;
   file_buffer->flags = (N_IsInternal | N_CannotGC);
 
@@ -960,3 +960,59 @@
   if (!info_error_was_printed)
     window_clear_echo_area ();
 }
+
+static NODE *allfiles_node;
+
+NODE *
+allfiles_create_node (char *term, REFERENCE *fref)
+{
+  int i;
+  struct text_buffer text;
+  size_t off;
+  FILE_BUFFER *fb;
+  NODE *node;
+  
+  text_buffer_init (&text);
+  text_buffer_printf (&text, _("File names matching `%s'"), term);
+  text_buffer_add_char (&text, 0);
+  off = text.off;
+
+  text_buffer_printf (&text,
+                     "\n\n%c\n%s %s\n\n"
+                     "Info File Index\n"
+                     "***************\n\n"
+                     "File names that match `%s':\n\n"
+                     "* Menu:\n\n",
+                     INFO_COOKIE,
+                     INFO_NODE_LABEL, text.base, term);
+
+  memmove (text.base, text.base + off, text.off - off);
+  text.off -= off;
+
+  for (i = 0; fref[i].filename; i++)
+    {
+      text_buffer_printf (&text, "* %4i: (%s)", i+1, fref[i].filename);
+      if (fref[i].nodename)
+       text_buffer_printf (&text, "%s", fref[i].nodename);
+      text_buffer_printf (&text, ".\n");
+    }
+
+  fb = create_virtindex_file_buffer (NULL, text.base, text.off);
+  allfiles_node = create_virtindex_node (fb);
+
+  return allfiles_node;
+}
+
+DECLARE_INFO_COMMAND (info_all_files, _("Show all matching files"))
+{
+  if (!allfiles_node)
+    {
+      info_error (_("No file index"));
+      return;
+    }
+
+  info_set_node_of_window (1, window, allfiles_node);
+
+  if (!info_error_was_printed)
+    window_clear_echo_area ();
+}

Modified: trunk/info/indices.h
===================================================================
--- trunk/info/indices.h        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/indices.h        2013-04-15 21:39:09 UTC (rev 5255)
@@ -41,4 +41,6 @@
 extern void do_info_index_search (WINDOW *window, int count, char 
*search_string);
 extern int index_entry_exists (WINDOW *window, char *string);
 
+NODE *allfiles_create_node (char *term, REFERENCE *fref);
+
 #endif /* not INFO_INDICES_H */

Modified: trunk/info/info.c
===================================================================
--- trunk/info/info.c   2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/info.c   2013-04-15 21:39:09 UTC (rev 5255)
@@ -80,6 +80,9 @@
 /* Non-zero means don't remove ANSI escape sequences.  */
 int raw_escapes_p = 1;
 
+/* Print/visit all matching documents. */
+static int all_matches_p = 0;
+
 /* Non-zero means print the absolute location of the file to be loaded.  */
 static int print_where_p = 0;
 
@@ -105,6 +108,7 @@
 #define RESTORE_OPTION 3
 #define IDXSRCH_OPTION 4
 static struct option long_options[] = {
+  { "all", 0, 0, 'a' },
   { "apropos", 1, 0, 'k' },
   { "debug", 0, 0, 'x' },
   { "directory", 1, 0, 'd' },
@@ -136,9 +140,9 @@
 
 /* String describing the shorthand versions of the long options found above. */
 #if defined(__MSDOS__) || defined(__MINGW32__)
-static char *short_options = "k:d:n:f:ho:ORsv:wbx";
+static char *short_options = "ak:d:n:f:ho:ORsv:wbx";
 #else
-static char *short_options = "k:d:n:f:ho:ORv:wsx";
+static char *short_options = "ak:d:n:f:ho:ORv:wsx";
 #endif
 
 /* When non-zero, the Info window system has been initialized. */
@@ -149,6 +153,314 @@
 static void init_messages (void);
 
 
+static const char *
+node_file_name (NODE *node, int dirok)
+{
+  if (node->parent)
+    return node->parent;
+  else if (node->filename
+          && (dirok ||
+              !is_dir_name (filename_non_directory (node->filename))))
+    return node->filename;
+  return 0;
+}
+
+static int
+single_file (char *filename, int argc, char **argv)
+{
+  NODE *initial_node;           /* First node loaded by Info. */
+  NODE *new_initial_node, *error_node;
+  
+  /* Get the initial Info node.  It is either "(dir)Top", or what the user
+     specifed with values in filename and user_nodenames. */
+  initial_node = info_get_node (filename,
+                                user_nodenames ? user_nodenames[0] : 0,
+                                PARSE_NODE_DFLT);
+
+  /* If we couldn't get the initial node, this user is in trouble. */
+  if (!initial_node)
+    {
+      if (info_recent_file_error)
+        info_error ("%s", info_recent_file_error);
+      else
+        info_error (msg_cant_find_node,
+                    user_nodenames ? user_nodenames[0] : "Top");
+      return EXIT_FAILURE;
+    }
+
+  /* Special cases for when the user specifies multiple nodes.  If we
+     are dumping to an output file, dump all of the nodes specified.
+     Otherwise, attempt to create enough windows to handle the nodes
+     that this user wants displayed. */
+  if (user_nodenames_index > 1)
+    {
+      free (initial_node);
+
+      if (print_where_p)
+        printf ("%s\n", filename ? filename : "unknown?!");
+      else if (user_output_filename)
+        dump_nodes_to_file
+          (filename, user_nodenames, user_output_filename, dump_subnodes);
+      else
+        begin_multiple_window_info_session (filename, user_nodenames);
+
+      return EXIT_SUCCESS;
+    }
+
+  /* If there are arguments remaining, they are the names of menu items
+     in sequential info files starting from the first one loaded.  That
+     file name is either "dir", or the contents of filename if one
+     was specified. */
+  /* If they say info -O info, we want to show them the invocation node
+     for standalone info; there's nothing useful in info.texi.  */
+  if (goto_invocation_p && *argv
+      && mbscasecmp (*argv, "info") == 0)
+    *argv = "info-stnd";
+
+  new_initial_node = info_follow_menus (initial_node, argv, &error_node, 0);
+
+  if (new_initial_node && new_initial_node != initial_node)
+    initial_node = new_initial_node;
+
+  if (print_where_p)
+    {
+      const char *name = node_file_name (initial_node, 0);
+      if (!name)
+       return EXIT_FAILURE;
+      printf ("%s\n", name);
+      return EXIT_SUCCESS;
+    }
+
+  /* If the user specified that this node should be output, then do that
+     now.  Otherwise, start the Info session with this node.  Or act
+     accordingly if the initial node was not found.  */
+  if (user_output_filename && !goto_invocation_p)
+    {
+      if (error_node)
+       show_error_node (error_node);
+      else
+       dump_node_to_file (initial_node, user_output_filename,
+                          dump_subnodes);
+    }
+  else
+    {
+      if (error_node)
+       {
+         initialize_info_session (initial_node, 1);
+         show_error_node (error_node);
+         info_session ();
+       }
+      
+      /* If the user specified `--index-search=STRING' or
+        --show-options, start the info session in the node
+        corresponding to what they want. */
+      else if (index_search_p || goto_invocation_p)
+       {
+         int status = EXIT_SUCCESS;
+         
+         initialize_info_session (initial_node, 0);
+         
+         if (goto_invocation_p ||
+             index_entry_exists (windows, index_search_string))
+           {
+             terminal_prep_terminal ();
+             terminal_clear_screen ();
+             info_last_executed_command = NULL;
+             
+             if (index_search_p)
+               do_info_index_search (windows, 0, index_search_string);
+             else
+               {
+                 /* If they said "info --show-options foo bar baz",
+                    the last of the arguments is the program whose
+                    options they want to see.  */
+                 char **p = argv;
+                 char *program;
+                 
+                 if (*p)
+                   {
+                     while (p[1])
+                       p++;
+                     program = xstrdup (*p);
+                   }
+                 else if (filename)
+                   /* If there's no command-line arguments to
+                      supply the program name, use the Info file
+                      name (sans extension and leading directories)
+                      instead.  */
+                   program = program_name_from_file_name (filename);
+                 else
+                   program = xstrdup ("");
+                 
+                 info_intuit_options_node (windows, initial_node, program);
+                 free (program);
+               }
+             
+             if (user_output_filename)
+               {
+                 dump_node_to_file (windows->node, user_output_filename,
+                                    dump_subnodes);
+               }
+             else
+               info_read_and_dispatch ();
+             
+             /* On program exit, leave the cursor at the bottom of the
+                window, and restore the terminal IO. */
+             terminal_goto_xy (0, screenheight - 1);
+             terminal_clear_to_eol ();
+             fflush (stdout);
+             terminal_unprep_terminal ();
+           }
+         else
+           {
+             fprintf (stderr, _("no index entries found for `%s'\n"),
+                      index_search_string);
+             status = EXIT_FAILURE;
+           }
+         
+         close_dribble_file ();
+         return status;
+       }
+      else
+       begin_info_session (initial_node);
+    }
+
+  return EXIT_SUCCESS;
+}
+
+static char *
+dirname (const char *file)
+{
+  char *p;
+  size_t len;
+
+  p = strrchr (file, '/');
+  if (!p)
+    return NULL;
+  len = p - file;
+  p = xmalloc (len + 1);
+  memcpy (p, file, len);
+  p[len] = 0;
+  return p;
+}
+
+REFERENCE *
+info_find_matching_files (char *filename)
+{
+  size_t argc = 0;
+  size_t argn = 0;
+  REFERENCE *argv = NULL;
+  int i = 0;
+  char *p;
+  
+  do
+    {
+      p = info_file_find_next_in_path (filename, infopath (), &i);
+      if (argc == argn)
+       {
+         if (argn == 0)
+           argn = 2;
+         argv = x2nrealloc (argv, &argn, sizeof (argv[0]));
+       }
+      memset (&argv[argc], 0, sizeof (argv[argc]));
+      argv[argc++].filename = p;
+    }
+  while (p);
+  return argv;
+}
+
+static int
+all_files (char *filename, int argc, char **argv)
+{
+  REFERENCE *fref;
+  char *fname;
+  int i, j;
+  int dirok;
+  size_t count;
+  
+  if (user_filename)
+    {
+      fname = user_filename;
+      dirok = 0;
+    }
+  else
+    {
+      fname = "dir";
+      dirok = 1;
+    }
+  
+  fref = info_find_matching_files (fname);
+  
+  for (i = 0; fref[i].filename; )
+    {
+      NODE *node;
+      
+      if (!user_filename)
+       {
+         char *p = dirname (fref[i].filename);
+         infopath_add (p, INFOPATH_INIT);
+         free (p);
+       }
+      node = info_get_node (fref[i].filename,
+                           user_nodenames ? user_nodenames[0] : 0,
+                           PARSE_NODE_DFLT);
+      
+      if (node)
+       {
+         NODE *errnode;
+         NODE *subnode = info_follow_menus (node, argv, &errnode, 1);
+         if (errnode)
+           show_error_node (errnode);
+         if (!subnode)
+           {
+             forget_info_file (fref[i].filename);
+             node = NULL;
+           }
+         else
+           node = subnode;
+       }
+      
+      if (node)
+       {
+         const char *name = node_file_name (node, dirok);
+         if (!name)
+           node = NULL;
+         else
+           {
+             free (fref[i].filename);
+             fref[i].filename = xstrdup (name);
+           }
+       }
+      
+      if (!node)
+       {
+         free (fref[i].filename);
+         for (j = i; (fref[j] = fref[j + 1]).filename; j++);
+       }
+      else
+       {
+         if (print_where_p)
+           printf ("%s\n", fref[i].filename);
+         else if (user_output_filename)
+           dump_node_to_file (node, user_output_filename,
+                              dump_subnodes);
+         else
+           fref[i].nodename = xstrdup (node->nodename);
+         ++i;
+       }
+    }
+  
+  if (print_where_p || user_output_filename)
+    return EXIT_SUCCESS;
+
+  if (i <= 1)
+    return single_file (user_filename, argc, argv);
+  
+  begin_info_session (allfiles_create_node (argc ? argv[0] : fname, fref));
+  return EXIT_SUCCESS;
+}
+
+
 /* **************************************************************** */
 /*                                                                  */
 /*                Main Entry Point to the Info Program              */
@@ -159,7 +471,6 @@
 main (int argc, char *argv[])
 {
   int getopt_long_index;        /* Index returned by getopt_long (). */
-  NODE *initial_node;           /* First node loaded by Info. */
 
 #ifdef HAVE_SETLOCALE
   /* Set locale via LC_ALL.  */
@@ -173,7 +484,7 @@
 #endif
 
   init_messages ();
-
+  infopath_init ();
   while (1)
     {
       int option_character;
@@ -195,9 +506,13 @@
         case 0:
           break;
 
+       case 'a':
+         all_matches_p = 1;
+         break;
+         
           /* User wants to add a directory. */
         case 'd':
-          info_add_path (optarg, INFOPATH_PREPEND);
+          infopath_add (optarg, INFOPATH_PREPEND);
           break;
 
           /* User is specifying a particular node. */
@@ -351,43 +666,6 @@
       exit (EXIT_SUCCESS);
     }
 
-  /* If the user hasn't specified a path for Info files, default it.
-     Lowest priority is our messy hardwired list in filesys.h.
-     Then comes the user's INFODIR from the Makefile.
-     Highest priority is the environment variable, if set.  */
-  if (!infopath)
-    {
-      char *path_from_env = getenv ("INFOPATH");
-
-      if (path_from_env)
-        {
-          unsigned len = strlen (path_from_env);
-          /* Trailing : on INFOPATH means insert the default path.  */
-          if (len && path_from_env[len - 1] == PATH_SEP[0])
-            {
-              path_from_env[len - 1] = 0;
-              info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
-            }
-#ifdef INFODIR /* from the Makefile */
-          info_add_path (INFODIR, INFOPATH_PREPEND);
-#endif
-          info_add_path (path_from_env, INFOPATH_PREPEND);
-        }
-      else
-        {
-          info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
-#ifdef INFODIR /* from the Makefile */
-          info_add_path (INFODIR, INFOPATH_PREPEND);
-#endif
-#ifdef INFODIR2 /* from the Makefile, too */
-#  ifdef INFODIR
-          if (!STREQ (INFODIR, INFODIR2))
-#  endif
-            info_add_path (INFODIR2, INFOPATH_PREPEND);
-#endif
-        }
-    }
-
   /* If the user specified a particular filename, add the path of that
      file to the contents of INFOPATH. */
   if (user_filename)
@@ -401,171 +679,13 @@
       exit (EXIT_SUCCESS);
     }
 
-  /* Get the initial Info node.  It is either "(dir)Top", or what the user
-     specifed with values in user_filename and user_nodenames. */
-  initial_node = info_get_node (user_filename,
-                                user_nodenames ? user_nodenames[0] : 0,
-                                PARSE_NODE_DFLT);
-
-  /* If we couldn't get the initial node, this user is in trouble. */
-  if (!initial_node)
-    {
-      if (info_recent_file_error)
-        info_error ("%s", info_recent_file_error);
-      else
-        info_error (msg_cant_find_node,
-                    user_nodenames ? user_nodenames[0] : "Top");
-      exit (EXIT_FAILURE);
-    }
-
-  /* Special cases for when the user specifies multiple nodes.  If we
-     are dumping to an output file, dump all of the nodes specified.
-     Otherwise, attempt to create enough windows to handle the nodes
-     that this user wants displayed. */
-  if (user_nodenames_index > 1)
-    {
-      free (initial_node);
-
-      if (print_where_p)
-        printf ("%s\n", user_filename ? user_filename : "unknown?!");
-      else if (user_output_filename)
-        dump_nodes_to_file
-          (user_filename, user_nodenames, user_output_filename, dump_subnodes);
-      else
-        begin_multiple_window_info_session (user_filename, user_nodenames);
-
-      exit (EXIT_SUCCESS);
-    }
-
-  /* If there are arguments remaining, they are the names of menu items
-     in sequential info files starting from the first one loaded.  That
-     file name is either "dir", or the contents of user_filename if one
-     was specified. */
-  {
-    NODE *new_initial_node, *error_node;
-    
-    /* If they say info -O info, we want to show them the invocation node
-       for standalone info; there's nothing useful in info.texi.  */
-    if (goto_invocation_p && argv[optind]
-       && mbscasecmp (argv[optind], "info") == 0)
-      argv[optind] = "info-stnd";
-    
-    new_initial_node = info_follow_menus (initial_node, argv + optind,
-                                         &error_node);
-
-    if (new_initial_node && new_initial_node != initial_node)
-      initial_node = new_initial_node;
-
-    if (print_where_p)
-      {
-        if (initial_node->parent)
-          printf ("%s\n", initial_node->parent);
-        else if (initial_node->filename
-            && !is_dir_name (filename_non_directory (initial_node->filename)))
-          printf ("%s\n", initial_node->filename);
-        else
-          exit (EXIT_FAILURE);
-        exit (EXIT_SUCCESS);
-      }
-
-    /* If the user specified that this node should be output, then do that
-       now.  Otherwise, start the Info session with this node.  Or act
-       accordingly if the initial node was not found.  */
-    if (user_output_filename && !goto_invocation_p)
-      {
-        if (error_node)
-         show_error_node (error_node);
-        else
-          dump_node_to_file (initial_node, user_output_filename,
-                             dump_subnodes);
-      }
-    else
-      {
-        if (error_node)
-         {
-           initialize_info_session (initial_node, 1);
-           show_error_node (error_node);
-           info_session ();
-         }
-       
-        /* If the user specified `--index-search=STRING' or
-           --show-options, start the info session in the node
-           corresponding to what they want. */
-        else if (index_search_p || goto_invocation_p)
-          {
-            int status = EXIT_SUCCESS;
-
-            initialize_info_session (initial_node, 0);
-
-            if (goto_invocation_p
-                || index_entry_exists (windows, index_search_string))
-              {
-                terminal_prep_terminal ();
-                terminal_clear_screen ();
-                info_last_executed_command = NULL;
-
-                if (index_search_p)
-                  do_info_index_search (windows, 0, index_search_string);
-                else
-                  {
-                    /* If they said "info --show-options foo bar baz",
-                       the last of the arguments is the program whose
-                       options they want to see.  */
-                    char **p = argv + optind;
-                    char *program;
-
-                    if (*p)
-                      {
-                        while (p[1])
-                          p++;
-                        program = xstrdup (*p);
-                      }
-                    else if (user_filename)
-                     /* If there's no command-line arguments to
-                        supply the program name, use the Info file
-                        name (sans extension and leading directories)
-                        instead.  */
-                     program = program_name_from_file_name (user_filename);
-                   else
-                     program = xstrdup ("");
-
-                    info_intuit_options_node (windows, initial_node, program);
-                    free (program);
-                  }
-
-               if (user_output_filename)
-                 {
-                   dump_node_to_file (windows->node, user_output_filename,
-                                      dump_subnodes);
-                 }
-               else
-                 info_read_and_dispatch ();
-
-                /* On program exit, leave the cursor at the bottom of the
-                   window, and restore the terminal IO. */
-                terminal_goto_xy (0, screenheight - 1);
-                terminal_clear_to_eol ();
-                fflush (stdout);
-                terminal_unprep_terminal ();
-              }
-            else
-              {
-                fprintf (stderr, _("no index entries found for `%s'\n"),
-                         index_search_string);
-                status = EXIT_FAILURE;
-              }
-
-            close_dribble_file ();
-            exit (status);
-          }
-        else
-          begin_info_session (initial_node);
-      }
-
-    exit (EXIT_SUCCESS);
-  }
-
-  return 0; /* Avoid bogus warnings.  */
+  argc -= optind;
+  argv += optind;
+  
+  if (all_matches_p)
+    return all_files (user_filename, argc, argv);
+  
+  return single_file (user_filename, argc, argv);
 }
 
 void
@@ -584,7 +704,7 @@
          temp += 2;
        }
       temp[-1] = 0;
-      info_add_path (directory_name, INFOPATH_PREPEND);
+      infopath_add (directory_name, INFOPATH_PREPEND);
     }
 
   free (directory_name);
@@ -723,6 +843,7 @@
 
   puts (_("\
 Options:\n\
+  -a, --all                    visit all matching documents.\n\
   -k, --apropos=STRING         look up STRING in all indices of all manuals.\n\
   -d, --directory=DIR          add DIR to INFOPATH.\n\
       --dribble=FILENAME       remember user keystrokes in FILENAME.\n\
@@ -748,9 +869,11 @@
   puts (_("\
       --strict-node-location   (for debugging) use Info file pointers as-is.\n\
       --subnodes               recursively output menu items.\n\
+  -v, --variable VAR=VALUE     assign VALUE to the info variable VAR.\n\
       --vi-keys                use vi-like and less-like key bindings.\n\
       --version                display version information and exit.\n\
-  -w, --where, --location      print physical location of Info file."));
+  -w, --where, --location      print physical location of Info file.\n\
+  -x, --debug                  increase debugging level.\n"));
 
   puts (_("\n\
 The first non-option argument, if present, is the menu entry to start from;\n\

Modified: trunk/info/infodoc.c
===================================================================
--- trunk/info/infodoc.c        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/infodoc.c        2013-04-15 21:39:09 UTC (rev 5255)
@@ -310,7 +310,7 @@
 
       printf_to_message_buffer ("---------------------\n");
       printf_to_message_buffer (_("The current search path is:\n"));
-      printf_to_message_buffer ("%s\n", infopath);
+      printf_to_message_buffer ("%s\n", infopath ());
       printf_to_message_buffer ("---------------------\n\n");
       printf_to_message_buffer (_("Commands available in Info windows:\n\n"));
       dump_map_to_message_buffer ("", info_keymap);

Modified: trunk/info/infomap.c
===================================================================
--- trunk/info/infomap.c        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/infomap.c        2013-04-15 21:39:09 UTC (rev 5255)
@@ -297,7 +297,6 @@
   CONTROL('f'), NUL,              A_info_forward_char,
   CONTROL('h'), NUL,              A_info_get_help_window,
   CONTROL('l'), NUL,              A_info_redraw_display,
-  CONTROL('n'), NUL,              A_info_next_line,
   CONTROL('p'), NUL,              A_info_prev_line,
   CONTROL('r'), NUL,              A_isearch_backward,
   CONTROL('s'), NUL,              A_isearch_forward,
@@ -398,13 +397,14 @@
   CONTROL('x'), '2', NUL,         A_info_split_window,
   CONTROL('x'), '^', NUL,         A_info_grow_window,
   CONTROL('x'), 'b', NUL,         A_select_visited_node,
+  CONTROL('x'), 'f', NUL,         A_info_all_files,
   CONTROL('x'), 'k', NUL,         A_info_kill_node,
   CONTROL('x'), 'n', NUL,         A_info_search_next,
   CONTROL('x'), 'N', NUL,         A_info_search_previous,
   CONTROL('x'), 'o', NUL,         A_info_next_window,
   CONTROL('x'), 't', NUL,         A_info_tile_windows,
   CONTROL('x'), 'w', NUL,         A_info_toggle_wrap,
-
+  
 /*      Arrow key bindings for info keymaps.  It seems that some
         terminals do not match their termcap entries, so it's best to just
         define everything with both of the usual prefixes.  */
@@ -634,6 +634,7 @@
   'l', NUL,                       A_info_history_node,
   'm', NUL,                       A_info_menu_item,
   'n', NUL,                       A_info_search_next,
+  ':', 'a', NUL,                  A_info_all_files,
   'N', NUL,                       A_info_search_previous,
   'O', NUL,                       A_info_goto_invocation_node,
   'p', NUL,                       A_info_prev_node,

Added: trunk/info/infopath.c
===================================================================
--- trunk/info/infopath.c                               (rev 0)
+++ trunk/info/infopath.c       2013-04-15 21:39:09 UTC (rev 5255)
@@ -0,0 +1,335 @@
+/* infopath.c -- INFOPATH handling.
+
+   Copyright 1993, 1997, 1998, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2011,
+   2012, 2013 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "info.h"
+#include "filesys.h"
+
+/* The path on which we look for info files. */
+static char *infopath_base = NULL;
+/* Allocated size of infopath_base. */
+static int infopath_size = 0;
+/* If 1, infopath_base has been modified and needs compaction */
+static int infopath_dirty = 0;
+
+/* Return a pointer to the next directory in STR (having length LEN).
+   *IDX points to the offset in STR where to start searching.  Return
+   NULL if *IDX points at or after the trailing null character.  Otherwise,
+   store the length of the returned directory segment into the memory
+   location pointed to by RETLEN. */
+static char *
+nextdir (char *str, int len, int *idx, int *retlen)
+{
+  int i;
+  char *ret;
+  
+  if (!str || *idx >= len)
+    return NULL;
+
+  if (*idx > 0)
+    ++*idx;
+  ret = str + *idx;
+  
+  for (i = *idx; str[i]; i++)
+    if (str[i] == PATH_SEP[0])
+      break;
+
+  *retlen = i - *idx;
+  *idx = i;
+  return ret;
+}
+
+/* Compact the INFOPATH value by removing repeated directory entries */
+void
+compact_infopath (void)
+{
+  int i, j, k, l;
+  int dl, pl;
+  char *dir, *p;
+  int chg = 0;
+  
+  l = strlen (infopath_base);
+  for (i = 0; (dir = nextdir (infopath_base, l, &i, &dl)); )
+    {
+      for (j = k = i; (p = nextdir (infopath_base, l, &j, &pl)); k = j)
+       {
+         if (pl == dl && memcmp (dir, p, dl) == 0)
+           {
+             memmove (infopath_base + k, infopath_base + j, (l - j + 1));
+             l -= pl + 1;
+             chg = 1;
+           }
+       }
+    }
+  if (chg)
+    debug(2, ("INFOPATH compacted: %s", infopath_base));
+  infopath_dirty = 0;
+}
+
+void
+infopath_init ()
+{
+  /* Initialize INFOPATH.
+     The hardwired default settings (filesy.h) are the lowest priority.
+     Then comes the user's INFODIR from the Makefile.
+     Highest priority is the environment variable, if set.  */
+  char *path_from_env = getenv ("INFOPATH");
+
+  if (path_from_env)
+    {
+      unsigned len = strlen (path_from_env);
+      /* Trailing : on INFOPATH means insert the default path.  */
+      if (len && path_from_env[len - 1] == PATH_SEP[0])
+       {
+         path_from_env[len - 1] = 0;
+         infopath_add (DEFAULT_INFOPATH, INFOPATH_PREPEND);
+       }
+#ifdef INFODIR /* from the Makefile */
+      infopath_add (INFODIR, INFOPATH_PREPEND);
+#endif
+      infopath_add (path_from_env, INFOPATH_PREPEND);
+    }
+  else
+    {
+      infopath_add (DEFAULT_INFOPATH, INFOPATH_PREPEND);
+#ifdef INFODIR /* from the Makefile */
+      infopath_add (INFODIR, INFOPATH_PREPEND);
+#endif
+#ifdef INFODIR2 /* from the Makefile, too */
+#  ifdef INFODIR
+      if (!STREQ (INFODIR, INFODIR2))
+#  endif
+       infopath_add (INFODIR2, INFOPATH_PREPEND);
+#endif
+    }
+}
+
+char *
+infopath ()
+{
+  if (!infopath_base)
+    infopath_add (DEFAULT_INFOPATH, INFOPATH_INIT);
+  if (infopath_dirty)
+    compact_infopath ();
+  return infopath_base;
+}
+
+/* Make INFOPATH have absolutely nothing in it. */
+void
+infopath_clear (void)
+{
+  if (infopath_base)
+    {
+      infopath_base[0] = 0;
+      infopath_dirty = 0;
+    }
+  debug(2, ("INFOPATH cleared"));
+}
+
+/* For each path element PREFIX/DIR in PATH substitute either
+   PREFIX/share/info or PREFIX/info if that directory exists.
+   Avoid duplicates from, e.g., PREFIX/bin and PREFIX/sbin. */
+static char *
+build_infopath_from_path (void)
+{
+  typedef struct path_el
+  {
+      struct path_el *next;
+      char *path;
+      unsigned int len;
+    } PATH_EL, *PATH_PTR;
+
+  PATH_EL path_head = { NULL, NULL, 1 };
+  PATH_PTR path_prev, path_next;
+  char *res, *path_from_env, *temp_dirname;
+  int dirname_index = 0;
+  struct stat finfo;
+
+  path_from_env = getenv ("PATH");
+
+  while ((temp_dirname = extract_colon_unit (path_from_env, &dirname_index)))
+    {
+      unsigned int i, dir = 0;
+
+      /* Find end of DIRNAME/ (but ignore "/") */
+      for (i = 0; temp_dirname[i]; i++)
+        if (i && IS_SLASH (temp_dirname[i]))
+          dir = i + 1;
+
+      /* Discard path elements ending with "/", "/.", or "/.." */
+      if (!temp_dirname[dir] || STREQ (temp_dirname + dir, ".") || STREQ 
(temp_dirname + dir, "."))
+        dir = 0;
+      
+      path_prev = &path_head;
+      while (dir && (path_next = path_prev->next))
+        {
+          /* Ignore duplicate DIRNAME */
+          if (dir == path_next->len && strncmp (temp_dirname, path_next->path, 
dir) == 0)
+            dir = 0;
+
+          path_prev = path_next;
+        }
+
+      if (dir)
+        {
+          temp_dirname = xrealloc (temp_dirname, dir + strlen ("share/info") 
+1);
+
+          /* first try DIRNAME/share/info */
+          strcpy (temp_dirname + dir, "share/info");
+          if (stat (temp_dirname, &finfo) != 0 || !S_ISDIR (finfo.st_mode))
+            {
+              /* then try DIRNAME/info */
+              strcpy (temp_dirname + dir, "info");
+              if (stat (temp_dirname, &finfo) != 0 || !S_ISDIR (finfo.st_mode))
+                dir = 0;
+            }
+        }
+
+      if (dir)
+        {
+          path_next = xmalloc (sizeof (PATH_EL));
+          path_next->next = NULL;
+          path_next->path = temp_dirname;
+          path_next->len = dir;
+          path_prev->next = path_next;
+          path_head.len += strlen (temp_dirname) + 1;
+        }
+      else
+        free (temp_dirname);
+    }
+
+  /* Build the resulting sequence of paths */
+  res = xmalloc (path_head.len);
+  res[0] = '\0';
+
+  for (path_prev = path_head.next; path_prev; path_prev = path_next)
+    {
+      strcat (res, path_prev->path);
+      if ((path_next = path_prev->next))
+        strcat (res, PATH_SEP);
+
+      free (path_prev->path);
+      free (path_prev);
+    }
+
+  return res;
+}
+
+/* Add PATH to the list of paths found in INFOPATH.  2nd argument says
+   whether to put PATH at the front or end of INFOPATH.
+   Replace one path element "PATH" in PATH by a sequence of
+   path elements derived from the environment variable PATH. */
+void
+infopath_add (char *path, int where)
+{
+  int len;
+  int found = 0;
+  unsigned int i, j;
+
+  /* Search for "PATH" in PATH */
+  for (i = 0; path[i]; i++)
+    {
+      j = i + strlen ("PATH");
+      if (strncmp (path + i, "PATH", strlen ("PATH")) == 0 &&
+          (!path[j] || path[j] == PATH_SEP[0]))
+        {
+          found = 1;
+          break;
+        }
+      else
+        {
+          /* Advance to next PATH_SEP.  */
+          while (path[i] && path[i] != PATH_SEP[0])
+            i++;
+
+          if (!path[i])
+            break;
+        }
+    }
+
+  if (found)
+    {
+      /* Build infopath from the environment variable PATH */
+      char *temp = build_infopath_from_path ();
+
+      if (i || path[j])
+        {
+          char *old_path = path;
+
+          /* Splice it into OLD_PATH */
+          path = xmalloc (1 + strlen (temp) +
+                             strlen (old_path) - strlen ("PATH"));
+          if (i)
+            strncpy (path, old_path, i);
+          strcpy (path + i, temp);
+          if (old_path[j])
+            strcat (path, old_path + j);
+
+          free (temp);
+        }
+      else
+        path = temp;
+    }
+
+  if (where == INFOPATH_INIT)
+    infopath_clear ();
+  
+  if (!infopath_base)
+    {
+      infopath_base = xmalloc (infopath_size = 200 + strlen (path));
+      infopath_base[0] = '\0';
+    }
+
+  len = strlen (path) + strlen (infopath_base);
+
+  if (len + 2 >= infopath_size)
+    infopath_base = xrealloc (infopath_base, (infopath_size += (2 * len) + 2));
+
+  if (!*infopath_base || !infopath_base[0])
+    strcpy (infopath_base, path);
+  else if (where == INFOPATH_APPEND)
+    {
+      strcat (infopath_base, PATH_SEP);
+      strcat (infopath_base, path);
+    }
+  else if (where == INFOPATH_PREPEND)
+    {
+      char *temp = xstrdup (infopath_base);
+      strcpy (infopath_base, path);
+      strcat (infopath_base, PATH_SEP);
+      strcat (infopath_base, temp);
+      free (temp);
+    }
+  infopath_dirty = 1;
+  debug(2, ("INFOPATH=%s", infopath_base));
+  if (found)
+    free (path);
+}
+
+char *
+infopath_next (int *idx)
+{
+  return extract_colon_unit (infopath_base, idx);
+}
+
+char *
+infopath_first (int *idx)
+{
+  *idx = 0;
+  return infopath_next (idx);
+}

Modified: trunk/info/nodes.c
===================================================================
--- trunk/info/nodes.c  2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/nodes.c  2013-04-15 21:39:09 UTC (rev 5255)
@@ -30,7 +30,6 @@
 #  include "man.h"
 #endif /* HANDLE_MAN_PAGES */
 
-static void forget_info_file (char *filename);
 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);
@@ -1118,7 +1117,7 @@
 }
 
 /* Forget the contents, tags table, nodes list, and names of FILENAME. */
-static void
+void
 forget_info_file (char *filename)
 {
   int i;

Modified: trunk/info/nodes.h
===================================================================
--- trunk/info/nodes.h  2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/nodes.h  2013-04-15 21:39:09 UTC (rev 5255)
@@ -161,4 +161,6 @@
 /* Create a new, empty file buffer. */
 extern FILE_BUFFER *make_file_buffer (void);
 
+void forget_info_file (char *filename);
+
 #endif /* not NODES_H */

Modified: trunk/info/session.c
===================================================================
--- trunk/info/session.c        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/session.c        2013-04-15 21:39:09 UTC (rev 5255)
@@ -188,10 +188,8 @@
 info_read_and_dispatch (void)
 {
   unsigned char key;
-  int done;
-  done = 0;
 
-  while (!done && !quit_info_immediately)
+  for (quit_info_immediately = 0; !quit_info_immediately; )
     {
       int lk = 0;
 
@@ -239,14 +237,9 @@
               info_aborted_echo_area)
             {
               ea_last_executed_command = NULL;
-              done = 1;
+              break;
             }
-
-          if (info_last_executed_command == (VFunction *) info_quit)
-            quit_info_immediately = 1;
         }
-      else if (info_last_executed_command == (VFunction *) info_quit)
-        done = 1;
     }
 }
 
@@ -2796,7 +2789,8 @@
    will be NULL.  */
 
 NODE *
-info_follow_menus (NODE *initial_node, char **menus, NODE **err_node)
+info_follow_menus (NODE *initial_node, char **menus, NODE **err_node,
+                  int strict)
 {
   NODE *node = NULL;
 
@@ -2826,7 +2820,7 @@
          realize it. */
       if (!menu)
         {
-          if (arg == first_arg)
+          if (arg == first_arg && !strict)
             {
               node = make_manpage_node (first_arg);
               if (node)
@@ -2866,6 +2860,8 @@
          node anyway.  It is probably a misspelling. */
       if (!entry)
         {
+         if (strict)
+           return NULL;
           if (arg == first_arg)
             {
               /* Maybe they typed "info foo" instead of "info -f foo".  */
@@ -2999,7 +2995,7 @@
       if (!dir_node)
         info_error (msg_cant_find_node, "Top");
       else
-        node = info_follow_menus (dir_node, nodes, &err_node);
+        node = info_follow_menus (dir_node, nodes, &err_node, 0);
 
       free (nodes);
       if (err_node)
@@ -4944,10 +4940,12 @@
       set_window_pagetop (window, new_pagetop);
     }
 }
-/* This command does nothing.  It is the fact that a key is bound to it
-   that has meaning.  See the code at the top of info_session (). */
+
+/* Exit from info */
 DECLARE_INFO_COMMAND (info_quit, _("Quit using Info"))
-{}
+{
+  quit_info_immediately = 1;
+}
 
 
 /* **************************************************************** */

Modified: trunk/info/session.h
===================================================================
--- trunk/info/session.h        2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/session.h        2013-04-15 21:39:09 UTC (rev 5255)
@@ -25,6 +25,8 @@
 #include "info.h"
 #include "dribble.h"
 
+extern int quit_info_immediately;
+
 /* All commands that can be invoked from within info_session () receive
    arguments in the same way.  This simple define declares the header
    of a function named NAME, with associated documentation DOC.  The
@@ -197,7 +199,7 @@
 extern void info_view_file (WINDOW *window, int count, unsigned char key);
 extern void info_menu_sequence (WINDOW *window, int count, unsigned char key);
 extern NODE *info_follow_menus (NODE *initial_node, char **menus,
-                               NODE **err_node);
+                               NODE **err_node, int strict);
 extern void info_man (WINDOW *window, int count, unsigned char key);
 extern void list_visited_nodes (WINDOW *window, int count, unsigned char key);
 extern void select_visited_node (WINDOW *window, int count, unsigned char key);

Modified: trunk/info/tilde.c
===================================================================
--- trunk/info/tilde.c  2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/tilde.c  2013-04-15 21:39:09 UTC (rev 5255)
@@ -174,7 +174,7 @@
 /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
    tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
 char *
-tilde_expand_word (char *filename)
+tilde_expand_word (const char *filename)
 {
   char *dirname = filename ? xstrdup (filename) : NULL;
 

Modified: trunk/info/tilde.h
===================================================================
--- trunk/info/tilde.h  2013-04-13 15:41:58 UTC (rev 5254)
+++ trunk/info/tilde.h  2013-04-15 21:39:09 UTC (rev 5255)
@@ -48,6 +48,6 @@
 
 /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
    tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
-extern char *tilde_expand_word (char *filename);
+extern char *tilde_expand_word (const char *filename);
 
 #endif /* not TILDE_H */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]