changeset 4242:4d3994172bd5

[project @ 2002-12-26 22:06:10 by jwe]
author jwe
date Thu, 26 Dec 2002 22:06:30 +0000
parents 71209cc7ad4a
children 7e4d5b5520e5
files kpathsea/ChangeLog kpathsea/pathsearch.c kpathsea/pathsearch.h liboctave/ChangeLog liboctave/oct-kpse.c liboctave/oct-kpse.h liboctave/pathsearch.cc liboctave/pathsearch.h
diffstat 8 files changed, 401 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/kpathsea/ChangeLog	Thu Dec 26 00:24:10 2002 +0000
+++ b/kpathsea/ChangeLog	Thu Dec 26 22:06:30 2002 +0000
@@ -1,3 +1,11 @@
+2002-12-26  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* pathsearch.c (path_find_first_of, find_first_of,
+	kpse_path_find_first_of, kpse_all_path_find_first_of):
+	New functions. 
+	* pathsearch.h (kpse_path_find_first_of, kpse_all_path_find_first_of):
+	Provide declarations.
+
 2002-11-23  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* Makefile.in (objects): Include basename.lo in the list.
--- a/kpathsea/pathsearch.c	Thu Dec 26 00:24:10 2002 +0000
+++ b/kpathsea/pathsearch.c	Thu Dec 26 22:06:30 2002 +0000
@@ -367,6 +367,245 @@
   return ret;
 }
 
+/* This is the hard case -- look in each element of PATH for each
+   element of NAMES.  If ALL is false, return the first file found.
+   Otherwise, search all elements of PATH.  */
+
+static str_list_type
+path_find_first_of P4C(const_string, path, const_string *, names,
+		       boolean, must_exist, boolean, all)
+{
+  const_string *p;
+  string elt;
+  const_string name;
+  str_list_type ret_list;
+  boolean done = false;
+  ret_list = str_list_init (); /* some compilers lack struct initialization */
+
+  for (elt = kpse_path_element (path); !done && elt;
+       elt = kpse_path_element (NULL))
+    {
+      str_llist_type *dirs;
+      str_llist_elt_type *dirs_elt;
+      str_list_type *found;
+      boolean allow_disk_search = true;
+
+      if (*elt == '!' && *(elt + 1) == '!')
+	{
+	  /* Those magic leading chars in a path element means don't
+	     search the disk for this elt.  And move past the magic to
+	     get to the name.  */
+
+	  allow_disk_search = false;
+	  elt += 2;
+	}
+
+      /* Do not touch the device if present */
+
+      if (NAME_BEGINS_WITH_DEVICE (elt))
+	{
+	  while (IS_DIR_SEP (*(elt + 2)) && IS_DIR_SEP (*(elt + 3)))
+	    {
+	      *(elt + 2) = *(elt + 1);
+	      *(elt + 1) = *elt;
+	      elt++;
+	    }
+	}
+      else
+	{
+	  /* We never want to search the whole disk.  */
+	  while (IS_DIR_SEP (*elt) && IS_DIR_SEP (*(elt + 1)))
+	    elt++;
+	}
+
+      /* We have to search one directory at a time.  */
+      dirs = kpse_element_dirs (elt);
+      for (dirs_elt = *dirs; dirs_elt; dirs_elt = STR_LLIST_NEXT (*dirs_elt))
+	{
+	  string dir = STR_LLIST (*dirs_elt);
+
+	  for (p = names; !done && *p; p++)
+	    {
+	      name = *p;
+
+	      /* Try ls-R, unless we're searching for texmf.cnf.  Our caller
+		 (find_first_of), also tests first_search, and does the
+		 resetting.  */
+	      found = first_search ? NULL : kpse_db_search (name, dir, all);
+
+	      /* Search the filesystem if (1) the path spec allows it,
+		 and either
+
+		   (2a) we are searching for texmf.cnf ; or
+		   (2b) no db exists; or 
+		   (2c) no db's are relevant to this elt; or
+		   (3) MUST_EXIST && NAME was not in the db.
+
+		 In (2*), `found' will be NULL.
+		 In (3),  `found' will be an empty list. */
+
+	      if (allow_disk_search
+		  && (!found || (must_exist && !STR_LIST (*found))))
+		{
+		  static str_llist_type *tmp = 0;
+
+		  if (! tmp)
+		    {
+		      tmp = XTALLOC1 (str_llist_type);
+		      *tmp = NULL;
+		      str_llist_add (tmp, "");
+		    }
+
+		  STR_LLIST (*(*tmp)) = dir;
+
+		  if (!found)
+		    found = XTALLOC1 (str_list_type);
+
+		  *found = dir_list_search (tmp, name, all);
+		}
+
+	      /* Did we find anything anywhere?  */
+	      if (found && STR_LIST (*found))
+		{
+		  if (all)
+		    str_list_concat (&ret_list, *found);
+		  else
+		    {
+		      str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
+		      done = true;
+		    }
+		}
+
+	      /* Free the list space, if any (but not the elements).  */
+	      if (found)
+		{
+		  str_list_free (found);
+		  free (found);
+		}
+	    }
+	}
+    }
+
+  return ret_list;
+}      
+
+static string *
+find_first_of P4C(const_string, path, const_string *, names,
+		  boolean, must_exist, boolean, all)
+{
+  str_list_type ret_list;
+  boolean absolute_p;
+
+#ifdef __DJGPP__
+  /* We will use `stat' heavily, so let's request for
+     the fastest possible version of `stat', by telling
+     it what members of struct stat do we really need.
+
+     We need to set this on each call because this is a
+     library function; the caller might need other options
+     from `stat'.  Thus save the flags and restore them
+     before exit.
+
+     This call tells `stat' that we do NOT need to recognize
+     executable files (neither by an extension nor by a magic
+     signature); that we do NOT need time stamp of root directories;
+     and that we do NOT need the write access bit in st_mode.
+
+     Note that `kpse_set_progname' needs the EXEC bits,
+     but it was already called by the time we get here.  */
+  unsigned short save_djgpp_flags  = _djstat_flags;
+
+  _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
+		  | _STAT_ROOT_TIME | _STAT_WRITEBIT;
+#endif
+
+  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
+    {
+      const_string *p;
+      fputs ("start find_first_of((", stderr);
+      for (p = names; *p; p++)
+	{
+	  if (p == names)
+	    fputs (*p, stderr);
+	  else
+	    fprintf (stderr, ", %s", *p);
+	}
+      fprintf (stderr, "), path=%s, must_exist=%d).\n", path, must_exist);
+    }
+
+  /* Find the file. */
+  ret_list = path_find_first_of (path, names, must_exist, all);
+
+  /* Append NULL terminator if we didn't find anything at all, or we're
+     supposed to find ALL and the list doesn't end in NULL now.  */
+  if (STR_LIST_LENGTH (ret_list) == 0
+      || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
+    str_list_add (&ret_list, NULL);
+
+  /* The very first search is for texmf.cnf.  We can't log that, since
+     we want to allow setting TEXMFLOG in texmf.cnf.  */
+  if (first_search) {
+    first_search = false;
+  } else {
+    /* Record the filenames we found, if desired.  And wrap them in a
+       debugging line if we're doing that.  */
+    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
+      {
+	const_string *p;
+	fputs ("find_first_of(", stderr);
+	for (p = names; *p; p++)
+	  {
+	    if (p == names)
+	      fputs (*p, stderr);
+	    else
+	      fprintf (stderr, ", %s", *p);
+	  }
+	fputs (") =>", stderr);
+      }
+    log_search (ret_list);
+    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
+      putc ('\n', stderr);
+  }  
+
+#ifdef __DJGPP__
+  /* Undo any side effects.  */
+  _djstat_flags = save_djgpp_flags;
+#endif
+
+  return STR_LIST (ret_list);
+}
+
+/* Search each element of PATH for each element of NAMES.  Return the
+   first one found.  */
+
+string
+kpse_path_find_first_of P3C(const_string, path, const_string *, names,
+			    boolean, must_exist)
+{
+  static string *ret_list = 0;
+
+  if (ret_list)
+    {
+      free (ret_list);
+      ret_list = 0;  /* Don't let an interrupt in search() cause trouble */
+    }
+
+  ret_list = find_first_of (path, names, must_exist, false);
+
+  return *ret_list;  /* Freeing this is caller's responsibility */
+}
+
+/* Search each element of PATH for each element of NAMES and return a
+   list containing everything found, in the order found.  */
+
+string *
+kpse_all_path_find_first_of P2C(const_string, path,  const_string *, names)
+{
+  string *ret = find_first_of (path, names, true, true);
+  return ret;
+}
+
+
 #ifdef TEST
 
 void
--- a/kpathsea/pathsearch.h	Thu Dec 26 00:24:10 2002 +0000
+++ b/kpathsea/pathsearch.h	Thu Dec 26 22:06:30 2002 +0000
@@ -72,6 +72,18 @@
    all the filenames (or NULL if none), instead of taking the first.  */
 extern string *kpse_all_path_search P2H(const_string path, const_string name);
 
+/* Search each element of PATH for each element in the list of NAMES.
+   Return the first one found.  */
+extern string kpse_path_find_first_of P3H(const_string path,
+					  const_string *names,
+					  boolean must_exist);
+
+/* Like `kpse_path_find_first_of' with MUST_EXIST true, but return a
+   list of all the filenames (or NULL if none), instead of taking the
+   first.  */
+extern string *kpse_all_path_find_first_of P2H(const_string path,
+					       const_string *names);
+
 #if 0
 /* Clear the directory cache.  */
 extern void kpse_clear_dir_cache P1H(void);
--- a/liboctave/ChangeLog	Thu Dec 26 00:24:10 2002 +0000
+++ b/liboctave/ChangeLog	Thu Dec 26 22:06:30 2002 +0000
@@ -1,3 +1,15 @@
+2002-12-26  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* pathsearch.cc (make_retval, free_c_array, make_c_names,
+	delete_c_names): New helper functions.
+	(dir_path::find_first_of): New function.
+	(dir_path::find_all_first_of): Likewise.
+	* pathsearch.h: Provide decls.
+
+	* oct-kpse.c (octave_kpse_path_find_first_of): New function.
+	(octave_kpse_all_path_find_first_of): Likewise.
+	* oct-kpse.h: Provide decls.
+
 2002-12-19  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* ODESSA.cc (ODESSA::integrate): Handle maxord.
--- a/liboctave/oct-kpse.c	Thu Dec 26 00:24:10 2002 +0000
+++ b/liboctave/oct-kpse.c	Thu Dec 26 22:06:30 2002 +0000
@@ -51,6 +51,19 @@
   return kpse_all_path_search (path, name);
 }
 
+char *
+octave_kpse_path_find_first_of (const char *path, const char **names,
+				int must_exist)
+{
+  return kpse_path_find_first_of (path, names, must_exist);
+}
+
+char **
+octave_kpse_all_path_find_first_of (const char *path, const char **names)
+{
+  return kpse_all_path_find_first_of (path, names);
+}
+
 void
 octave_kpse_set_progname (const char *name)
 {
--- a/liboctave/oct-kpse.h	Thu Dec 26 00:24:10 2002 +0000
+++ b/liboctave/oct-kpse.h	Thu Dec 26 22:06:30 2002 +0000
@@ -51,6 +51,10 @@
 
 extern char **octave_kpse_all_path_search (const char *, const char *);
 
+extern char *octave_kpse_path_find_first_of (const char *, const char **, int);
+
+extern char **octave_kpse_all_path_find_first_of (const char *, const char **);
+
 extern void octave_kpse_set_progname (const char *);
 
 extern char *octave_kpse_expand_default (const char *, const char *);
--- a/liboctave/pathsearch.cc	Thu Dec 26 00:24:10 2002 +0000
+++ b/liboctave/pathsearch.cc	Thu Dec 26 22:06:30 2002 +0000
@@ -97,6 +97,109 @@
   if (initialized)
     {
       char *tmp = ::octave_kpse_path_search (p.c_str (), nm.c_str (), true);
+
+      if (tmp)
+	{
+	  retval = tmp;
+	  free (tmp);
+	}
+    }
+
+  return retval;
+}
+
+static string_vector
+make_retval (char **tmp)
+{
+  string_vector retval;
+
+  if (tmp)
+    {
+      int count = 0;
+      char **ptr = tmp;
+      while (*ptr++)
+	count++;
+
+      retval.resize (count);
+
+      for (int i = 0; i < count; i++)
+	retval[i] = tmp[i];
+    }
+
+  return retval;
+}
+
+static void
+free_c_array (char **tmp)
+{
+  if (tmp)
+    {
+      char **ptr = tmp;
+
+      while (char *elt = *ptr++)
+	if (elt)
+	  free (elt);
+
+      free (tmp);
+    }
+}
+
+string_vector
+dir_path::find_all (const std::string& nm)
+{
+  string_vector retval;
+
+  if (initialized)
+    {
+      char **tmp = ::octave_kpse_all_path_search (p.c_str (), nm.c_str ());
+
+      retval = make_retval (tmp);
+
+      free_c_array (tmp);
+    }
+
+  return retval;
+}
+
+static const char **
+make_c_names (const string_vector& names)
+{
+  int len = names.length ();
+
+  const char **c_names = new const char *[len+1];
+
+  for (int i = 0; i < len; i++)
+    c_names[i] = strsave (names[i].c_str ());
+
+  c_names[len] = 0;
+
+  return c_names;
+}
+
+static void
+delete_c_names (const char **c_names)
+{
+  const char **p = c_names;
+
+  while (const char *elt = *p++)
+    delete [] elt;
+
+  delete [] c_names;
+}
+
+std::string
+dir_path::find_first_of (const string_vector& names)
+{
+  std::string retval;
+
+  if (initialized)
+    {
+      const char **c_names = make_c_names (names);
+
+      char *tmp = ::octave_kpse_path_find_first_of (p.c_str (), c_names, true);
+
+      delete_c_names (c_names);
+
       if (tmp)
 	{
 	  retval = tmp;
@@ -108,26 +211,21 @@
 }
 
 string_vector
-dir_path::find_all (const std::string& nm)
+dir_path::find_all_first_of (const string_vector& names)
 {
   string_vector retval;
 
   if (initialized)
     {
-      char **tmp = ::octave_kpse_all_path_search (p.c_str (), nm.c_str ());
+      const char **c_names = make_c_names (names);
+
+      char **tmp = ::octave_kpse_all_path_find_first_of (p.c_str (), c_names);
 
-      if (tmp)
-	{
-	  int count = 0;
-	  char **ptr = tmp;
-	  while (*ptr++)
-	    count++;
+      delete_c_names (c_names);
 
-	  retval.resize (count);
+      retval = make_retval (tmp);
 
-	  for (int i = 0; i < count; i++)
-	    retval[i] = tmp[i];
-	}
+      free_c_array (tmp);
     }
 
   return retval;
--- a/liboctave/pathsearch.h	Thu Dec 26 00:24:10 2002 +0000
+++ b/liboctave/pathsearch.h	Thu Dec 26 22:06:30 2002 +0000
@@ -72,6 +72,9 @@
 
   string_vector find_all (const std::string&);
 
+  std::string find_first_of (const string_vector& names);
+  string_vector find_all_first_of (const string_vector& names);
+
   static void set_program_name (const std::string&);
 
   void rehash (void)