[tex-k] An idea for texinfo

Peter Breitenlohner peb at mppmu.mpg.de
Mon Jan 19 18:37:10 CET 2009


On Thu, 15 Jan 2009, Karl Berry wrote:

>    I'd like to implement a feature in texinfo that allows to set an info_path
>    constructed from PATH.
>
> Sounds good.

>    path="PREFIX/DIR"
>    => the first existing directory among
>            PREFIX/share/info
>            PREFIX/info
>    and possibly also (inspired by man-db)
>            PREFIX/DIR/share/info
>            PREFIX/DIR/info
>
> I guess it doesn't hurt to check for more directories, but when would
> /PREFIX/DIR/{info,share...} be found?

The last two were inspired by the way man-db constructs a manpath, they are now
gone.

Attached are three patches:

(1) patch-02-infopath-from-path:
The implementation of this idea.

(2) patch-03-tell-the-truth:
A correction to the info-stnd manual.

(3) patch-04-infopath-from-path-doc:
Documentation for (1).

====================

At the moment all this only works for the standalone info reader.
To make INFOPATH=PATH in the environment usefull, would certainly require
to have the same mechanism as well in the (X)Emacs info reader.

Regards
Peter Breitenlohner <peb at mppmu.mpg.de>
-------------- next part --------------
diff -ur texinfo-4.12.orig/info/filesys.c texinfo-4.12/info/filesys.c
--- texinfo-4.12.orig/info/filesys.c	2008-04-19 19:03:13.000000000 +0200
+++ texinfo-4.12/info/filesys.c	2009-01-17 02:04:38.000000000 +0100
@@ -28,6 +28,7 @@
 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);
@@ -365,12 +366,149 @@
     }
 }
 
+/* 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. */
+   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)
 {
   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 (!infopath)
     {
@@ -398,6 +536,9 @@
       strcat (infopath, temp);
       free (temp);
     }
+
+  if (found)
+    free (path);
 }
 
 /* Make INFOPATH have absolutely nothing in it. */
-------------- next part --------------
diff -ur texinfo-4.12.orig/doc/info-stnd.texi texinfo-4.12/doc/info-stnd.texi
--- texinfo-4.12.orig/doc/info-stnd.texi	2008-03-05 09:45:38.000000000 +0100
+++ texinfo-4.12/doc/info-stnd.texi	2009-01-19 17:22:27.000000000 +0100
@@ -151,10 +151,11 @@
 @itemx -d @var{directory-path}
 Prepend @var{directory-path} to the list of directory paths searched
 when Info needs to find a file.  You may issue @code{--directory}
-multiple times; once for each directory which contains Info files.  The
-list of directories searched by Info is constructed from the value of
-the environment variable @code{INFOPATH}; @code{--directory} causes the
-named @var{directory-path} to be prepended to that list.  The value of
+multiple times; once for each directory which contains Info files,
+or with a list of such directories separated by a colon (or semicolon
+on MS-DOS/MS-Windows).  In the absence of @code{--directory} options
+the list of directories searched by Info is constructed from the
+value of the environment variable @code{INFOPATH}.  The value of
 @code{INFOPATH} is a list of directories usually separated by a colon;
 on MS-DOS/MS-Windows systems, the semicolon is used.  If you do not
 define @code{INFOPATH}, Info uses a default path defined when Info was
-------------- next part --------------
diff -ur texinfo-4.12.orig/doc/info-stnd.texi texinfo-4.12/doc/info-stnd.texi
--- texinfo-4.12.orig/doc/info-stnd.texi	2009-01-19 17:22:27.000000000 +0100
+++ texinfo-4.12/doc/info-stnd.texi	2009-01-19 17:34:49.000000000 +0100
@@ -164,6 +164,12 @@
 the initial list of directories is constructed by appending the
 build-time default to the value of @code{INFOPATH}.
 
+If the list of directories contains the element @code{PATH}, that
+element is replaced by a list of directories derived from the value of
+the environment variable @code{PATH}.  Each path element of the form
+ at var{dir/base} is replaced by @var{dir}@code{/share/info} or
+ at var{dir}@code{/info}, provided that directory exists.
+
 @cindex keystrokes, recording
 @cindex remembering user keystrokes
 @item --dribble=@var{dribble-file}


More information about the tex-k mailing list