changeset 4385:de8c1d2ee728

[project @ 2003-04-24 03:27:41 by jwe]
author jwe
date Thu, 24 Apr 2003 03:27:41 +0000
parents f1fcc371e5ef
children 112a509bd2e6
files liboctave/ChangeLog liboctave/kpse-config.h liboctave/kpse-xfns.c liboctave/kpse-xfns.h liboctave/kpse.cc liboctave/kpse.h
diffstat 6 files changed, 1419 insertions(+), 2462 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/ChangeLog	Thu Apr 24 03:27:41 2003 +0000
@@ -1,5 +1,9 @@
 2003-04-23  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* kpse.cc: Move most functions from kpse-xfns.c here and make
+	static.  Include most of kpse-xfns.h directly, removing
+	unnecessary bits.
+
 	* dMatrix.cc (Matrix::pseudo_inverse): Now const.
 	* CMatrix.cc (ComplexMatrix::pseudo_inverse): Likewise.
 
--- a/liboctave/kpse-config.h	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/kpse-config.h	Thu Apr 24 03:27:41 2003 +0000
@@ -64,12 +64,6 @@
    from c-auto.in).  We use <...> instead of "..." so that the current
    cpp directory (i.e., kpathsea/) won't be searched. */
 
-#include "kpse-xfns.h"      /* STREQ, etc. */
-
-extern DIR *xopendir (char *dirname);
-
-extern void xclosedir (DIR *d);
-   
 /* If you want to find subdirectories in a directory with non-Unix
    semantics (specifically, if a directory with no subdirectories does
    not have exactly two links), define this.  */
--- a/liboctave/kpse-xfns.c	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/kpse-xfns.c	Thu Apr 24 03:27:41 2003 +0000
@@ -22,313 +22,10 @@
 #include <config.h>
 #endif
 
-#ifdef HAVE_UNISTD_H
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
+#include <string.h>
 
 #include "kpse-xfns.h"
 
-/* xfopen.c: fopen and fclose with error checking.  */
-
-/* These routines just check the return status from standard library
-   routines and abort if an error happens.  */
-
-FILE *
-xfopen (const char *filename, const char *mode)
-{
-  FILE *f;
-  
-  assert (filename && mode);
-  
-  f = fopen (filename, mode);
-  if (f == NULL)
-    FATAL_PERROR (filename);
-
-  return f;
-}
-
-void
-xfclose (FILE *f, const char *filename)
-{
-  assert (f);
-  
-  if (fclose (f) == EOF)
-    FATAL_PERROR (filename);
-}
-
-/* xfseek.c: fseek with error checking.  */
-
-void
-xfseek (FILE *f, long offset, int wherefrom, char *filename)
-{
-  if (fseek (f, offset, wherefrom) < 0)
-    FATAL_PERROR (filename);
-}
-
-/* xftell.c: ftell with error checking.  */
-
-unsigned long
-xftell (FILE *f, char *filename)
-{
-  long where = ftell (f);
-
-  if (where < 0)
-    FATAL_PERROR (filename);
-
-  return where;
-}
-
-/* xopendir.c: opendir and closedir with error checking.  */
-
-#ifndef WIN32
-DIR *
-xopendir (char *dirname)
-{
-  DIR *d = opendir (dirname);
-
-  if (d == NULL)
-    FATAL_PERROR (dirname);
-
-  return d;
-}
-#endif /* not WIN32 */
-
-void
-xclosedir (DIR *d)
-{
-#ifdef CLOSEDIR_VOID
-  closedir (d);
-#else
-  int ret = closedir (d);
-  
-  if (ret != 0)
-    FATAL ("closedir failed");
-#endif
-}
-
-/* xstat.c: stat and (maybe) lstat with error checking.  */
-
-struct stat
-xstat (const char *path)
-{
-  struct stat s;
-  
-  if (stat (path, &s) != 0)
-    FATAL_PERROR (path);
-  
-  return s;
-}
-
-/* If we don't have symbolic links, lstat is the same as stat, and
-   a #define is made in the include file.  */
-
-#ifdef S_ISLNK
-struct stat
-xlstat (const char *path)
-{
-  struct stat s;
-  
-  if (lstat (path, &s) != 0)
-    FATAL_PERROR (path);
-  
-  return s;
-}
-#endif
-
-/* xgetcwd.c: a from-scratch version of getwd.  Ideas from the tcsh 5.20
-   source, apparently uncopyrighted.  */
-
-#if ! (defined (HAVE_GETCWD) || defined (HAVE_GETWD))
-
-static void
-xchdir (char *dirname)
-{
-  if (chdir (dirname) != 0)
-    FATAL_PERROR (dirname);
-}
-
-#endif /* not HAVE_GETCWD && not HAVE_GETWD */
-
-/* Return the pathname of the current directory, or give a fatal error.  */
-
-char *
-xgetcwd (void)
-{
-  /* If the system provides getcwd, use it.  If not, use getwd if
-     available.  But provide a way not to use getcwd: on some systems
-     getcwd forks, which is expensive and may in fact be impossible for
-     large programs like tex.  If your system needs this define and it
-     is not detected by configure, let me know.
-                                       -- Olaf Weber <infovore@xs4all.nl */
-#if defined (HAVE_GETCWD) && !defined (GETCWD_FORKS)
-  char *path = (char *) xmalloc (PATH_MAX + 1);
-  
-  if (getcwd (path, PATH_MAX + 1) == 0)
-    {
-      fprintf (stderr, "getcwd: %s", path);
-      exit (1);
-    }
-  
-  return path;
-#elif defined (HAVE_GETWD)
-  char *path = (char *) xmalloc (PATH_MAX + 1);
-  
-  if (getwd (path) == 0)
-    {
-      fprintf (stderr, "getwd: %s", path);
-      exit (1);
-    }
-  
-  return path;
-#else /* not HAVE_GETCWD && not HAVE_GETWD */
-  struct stat root_stat, cwd_stat;
-  char *cwd_path = (char *) xmalloc (2); /* In case we assign "/" below.  */
-  
-  *cwd_path = 0;
-  
-  /* Find the inodes of the root and current directories.  */
-  root_stat = xstat ("/");
-  cwd_stat = xstat (".");
-
-  /* Go up the directory hierarchy until we get to root, prepending each
-     directory we pass through to `cwd_path'.  */
-  while (!SAME_FILE_P (root_stat, cwd_stat))
-    {
-      struct dirent *e;
-      DIR *parent_dir;
-      int found = 0;
-      
-      xchdir ("..");
-      parent_dir = xopendir (".");
-
-      /* Look through the parent directory for the entry with the same
-         inode, so we can get its name.  */
-      while ((e = readdir (parent_dir)) != NULL && !found)
-        {
-          struct stat test_stat;
-          test_stat = xlstat (e->d_name);
-          
-          if (SAME_FILE_P (test_stat, cwd_stat))
-            {
-              /* We've found it.  Prepend the pathname.  */
-              char *temp = cwd_path;
-              cwd_path = concat3 ("/", e->d_name, cwd_path);
-              free (temp);
-              
-              /* Set up to test the next parent.  */
-              cwd_stat = xstat (".");
-              
-              /* Stop reading this directory.  */
-              found = 1;
-            }
-        }
-      if (!found)
-        FATAL2 ("No inode %d/device %d in parent directory",
-                cwd_stat.st_ino, cwd_stat.st_dev);
-      
-      xclosedir (parent_dir);
-    }
-  
-  /* If the current directory is the root, cwd_path will be the empty
-     string, and we will have not gone through the loop.  */
-  if (*cwd_path == 0)
-    strcpy (cwd_path, "/");
-  else
-    /* Go back to where we were.  */
-    xchdir (cwd_path);
-
-#ifdef DOSISH
-  /* Prepend the drive letter to CWD_PATH, since this technique
-     never tells us what the drive is.
- 
-     Note that on MS-DOS/MS-Windows, the branch that works around
-     missing `getwd' will probably only work for DJGPP (which does
-     have `getwd'), because only DJGPP reports meaningful
-     st_ino numbers.  But someday, somebody might need this...  */
-  {
-    char drive[3];
-    char *temp = cwd_path;
-
-    /* Make the drive letter lower-case, unless it is beyond Z: (yes,
-       there ARE such drives, in case of Novell Netware on MS-DOS).  */
-    drive[0] = root_stat.st_dev + (root_stat.st_dev < 26 ? 'a' : 'A');
-    drive[1] = ':';
-    drive[2] = '\0';
-
-    cwd_path = concat (drive, cwd_path);
-    free (temp);
-  }
-#endif
-
-  return cwd_path;
-#endif /* not HAVE_GETCWD && not HAVE_GETWD */
-}
-
-/* xmalloc.c: malloc with error checking.  */
-
-void *
-xmalloc (unsigned size)
-{
-  void *new_mem = (void *) malloc (size);
-
-  if (new_mem == NULL)
-    {
-      fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n",
-               size);
-      /* 1 means success on VMS, so pick a random number (ASCII `K').  */
-      exit (75);
-    }
-
-  return new_mem;
-}
-
-/* xrealloc.c: realloc with error checking.  */
-
-extern void *xmalloc (unsigned);
-
-void *
-xrealloc (void *old_ptr, unsigned size)
-{
-  void *new_mem;
-
-  if (old_ptr == NULL)
-    new_mem = xmalloc (size);
-  else
-    {
-      new_mem = (void *) realloc (old_ptr, size);
-      if (new_mem == NULL)
-        {
-          /* We used to print OLD_PTR here using %x, and casting its
-             value to unsigned, but that lost on the Alpha, where
-             pointers and unsigned had different sizes.  Since the info
-             is of little or no value anyway, just don't print it.  */
-          fprintf (stderr, "fatal: memory exhausted (realloc of %u bytes).\n",
-                   size);
-          /* 1 means success on VMS, so pick a random number (ASCII `B').  */
-          exit (66);
-        }
-    }
-
-  return new_mem;
-}
-
-/* xstrdup.c: strdup with error checking.  */
-
-/* Return a copy of S in new storage.  */
-
-char *
-xstrdup (const char *s)
-{
-  char *new_string = (char *) xmalloc (strlen (s) + 1);
-  return strcpy (new_string, s);
-}
-
 /* basename.c: return the last element in a path.  */
 
 #ifndef HAVE_BASENAME
@@ -337,7 +34,7 @@
    pointer into NAME.  For example, `basename ("/foo/bar.baz")'
    returns "bar.baz".  */
 
-const char *
+static const char *
 basename (const char *name)
 {
   const char *base = NULL;
@@ -363,1261 +60,3 @@
 {
   return (char *) basename (name);
 }
-
-/* file-p.c: file predicates.  */
-
-/* Test whether FILENAME1 and FILENAME2 are actually the same file.  If
-   stat fails on either of the names, we return false, without error.  */
-
-int
-same_file_p (const char *filename1, const char *filename2)
-{
-    struct stat sb1, sb2;
-    /* These are put in variables only so the results can be inspected
-       under gdb.  */
-    int r1 = stat (filename1, &sb1);
-    int r2 = stat (filename2, &sb2);
-
-    return r1 == 0 && r2 == 0 ? SAME_FILE_P (sb1, sb2) : 0;
-}
-
-/* dir.c: directory operations.  */
-
-/* Return true if FN is a directory or a symlink to a directory,
-   false if not. */
-
-int
-dir_p (const char *fn)
-{
-#ifdef WIN32
-  int fa = GetFileAttributes(fn);
-  return (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
-#else
-  struct stat stats;
-  return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
-#endif
-}
-
-#ifndef WIN32
-
-/* Return -1 if FN isn't a directory, else its number of links.
-   Duplicate the call to stat; no need to incur overhead of a function
-   call for that little bit of cleanliness. */
-
-int
-dir_links (const char *fn)
-{
-  static hash_table_type link_table;
-  char **hash_ret;
-  long ret;
-  
-  if (link_table.size == 0)
-    link_table = hash_create (457);
-
-#ifdef KPSE_DEBUG
-  /* This is annoying, but since we're storing integers as pointers, we
-     can't print them as strings.  */
-  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
-    kpse_debug_hash_lookup_int = 1;
-#endif
-
-  hash_ret = hash_lookup (link_table, fn);
-  
-#ifdef KPSE_DEBUG
-  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
-    kpse_debug_hash_lookup_int = 0;
-#endif
-
-  /* Have to cast the int we need to/from the const_string that the hash
-     table stores for values. Let's hope an int fits in a pointer.  */
-  if (hash_ret)
-    ret = (long) *hash_ret;
-  else
-    {
-      struct stat stats;
-      ret = stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode)
-            ? stats.st_nlink : (unsigned) -1;
-
-      /* It's up to us to copy the value.  */
-      hash_insert (&link_table, xstrdup (fn), (const char *) ret);
-      
-#ifdef KPSE_DEBUG
-      if (KPSE_DEBUG_P (KPSE_DEBUG_STAT))
-        DEBUGF2 ("dir_links(%s) => %ld\n", fn, ret);
-#endif
-    }
-
-  return ret;
-}
-
-#endif /* !WIN32 */
-
-/* hash.c: hash table operations.  */
-
-/* The hash function.  We go for simplicity here.  */
-
-/* All our hash tables are related to filenames.  */
-#ifdef MONOCASE_FILENAMES
-#define TRANSFORM(x) toupper (x)
-#else
-#define TRANSFORM(x) (x)
-#endif
-
-static unsigned
-hash (hash_table_type table, const char *key)
-{
-  unsigned n = 0;
-  
-  /* Our keys aren't often anagrams of each other, so no point in
-     weighting the characters.  */
-  while (*key != 0)
-    n = (n + n + TRANSFORM (*key++)) % table.size;
-  
-  return n;
-}
-
-hash_table_type
-hash_create (unsigned size) 
-{
-  /* hash_table_type ret; changed into "static ..." to work around gcc
-     optimizer bug for Alpha.  */
-  static hash_table_type ret;
-  unsigned b;
-  ret.buckets = XTALLOC (size, hash_element_type *);
-  ret.size = size;
-  
-  /* calloc's zeroes aren't necessarily NULL, so be safe.  */
-  for (b = 0; b <ret.size; b++)
-    ret.buckets[b] = NULL;
-    
-  return ret;
-}
-
-/* Whether or not KEY is already in MAP, insert it and VALUE.  Do not
-   duplicate the strings, in case they're being purposefully shared.  */
-
-void
-hash_insert (hash_table_type *table, const char *key, const char *value)
-{
-  unsigned n = hash (*table, key);
-  hash_element_type *new_elt = XTALLOC1 (hash_element_type);
-
-  new_elt->key = key;
-  new_elt->value = value;
-  new_elt->next = NULL;
-  
-  /* Insert the new element at the end of the list.  */
-  if (!table->buckets[n])
-    /* first element in bucket is a special case.  */
-    table->buckets[n] = new_elt;
-  else
-    {
-      hash_element_type *loc = table->buckets[n];
-      while (loc->next)		/* Find the last element.  */
-        loc = loc->next;
-      loc->next = new_elt;	/* Insert the new one after.  */
-    }
-}
-
-/* Remove a (KEY, VALUE) pair.  */
-
-void
-hash_remove (hash_table_type *table, const char *key, const char *value)
-{
-  hash_element_type *p;
-  hash_element_type *q;
-  unsigned n = hash (*table, key);
-
-  /* Find pair.  */
-  for (q = NULL, p = table->buckets[n]; p != NULL; q = p, p = p->next)
-    if (FILESTRCASEEQ (key, p->key) && STREQ (value, p->value))
-      break;
-  if (p) {
-    /* We found something, remove it from the chain.  */
-    if (q) q->next = p->next; else table->buckets[n] = p->next;
-    /* We cannot dispose of the contents.  */
-    free (p);
-  }
-}
-
-/* Look up STR in MAP.  Return a (dynamically-allocated) list of the
-   corresponding strings or NULL if no match.  */ 
-
-#ifdef KPSE_DEBUG
-/* Print the hash values as integers if this is nonzero.  */
-int kpse_debug_hash_lookup_int = 0; 
-#endif
-
-char **
-hash_lookup (hash_table_type table, const char *key)
-{
-  hash_element_type *p;
-  str_list_type ret;
-  unsigned n = hash (table, key);
-  ret = str_list_init ();
-  
-  /* Look at everything in this bucket.  */
-  for (p = table.buckets[n]; p != NULL; p = p->next)
-    if (FILESTRCASEEQ (key, p->key))
-      /* Cast because the general str_list_type shouldn't force const data.  */
-      str_list_add (&ret, (char *) p->value);
-  
-  /* If we found anything, mark end of list with null.  */
-  if (STR_LIST (ret))
-    str_list_add (&ret, NULL);
-
-#ifdef KPSE_DEBUG
-  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
-    {
-      DEBUGF1 ("hash_lookup(%s) =>", key);
-      if (!STR_LIST (ret))
-        fputs (" (nil)\n", stderr);
-      else
-        {
-          char **r;
-          for (r = STR_LIST (ret); *r; r++)
-            {
-              putc (' ', stderr);
-              if (kpse_debug_hash_lookup_int)
-                fprintf (stderr, "%ld", (long) *r);
-              else
-                fputs (*r, stderr);
-            }
-          putc ('\n', stderr);
-        }
-      fflush (stderr);
-    }
-#endif
-
-  return STR_LIST (ret);
-}
-
-/* We only print nonempty buckets, to decrease output volume.  */
-
-void
-hash_print (hash_table_type table, int summary_only)
-{
-  unsigned b;
-  unsigned total_elements = 0, total_buckets = 0;
-  
-  for (b = 0; b < table.size; b++) {
-    hash_element_type *bucket = table.buckets[b];
-
-    if (bucket) {
-      unsigned len = 1;
-      hash_element_type *tb;
-
-      total_buckets++;
-      if (!summary_only) fprintf (stderr, "%4d ", b);
-
-      for (tb = bucket->next; tb != NULL; tb = tb->next)
-        len++;
-      if (!summary_only) fprintf (stderr, ":%-5d", len);
-      total_elements += len;
-
-      if (!summary_only) {
-        for (tb = bucket; tb != NULL; tb = tb->next)
-          fprintf (stderr, " %s=>%s", tb->key, tb->value);
-        putc ('\n', stderr);
-      }
-    }
-  }
-  
-  fprintf (stderr,
-          "%u buckets, %u nonempty (%u%%); %u entries, average chain %.1f.\n",
-          table.size,
-          total_buckets,
-          100 * total_buckets / table.size,
-          total_elements,
-          total_buckets ? total_elements / (double) total_buckets : 0.0);
-}
-
-/* concat.c: dynamic string concatenation.  */
-
-/* Return the concatenation of S1 and S2.  See `concatn.c' for a
-   `concatn', which takes a variable number of arguments.  */
-
-char *
-concat (const char *s1, const char *s2)
-{
-  char *answer = (char *) xmalloc (strlen (s1) + strlen (s2) + 1);
-  strcpy (answer, s1);
-  strcat (answer, s2);
-
-  return answer;
-}
-
-/* concat3.c: concatenate three strings.  */
-
-char *
-concat3 (const char *s1, const char *s2, const char *s3)
-{
-  char *answer
-    = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
-  strcpy (answer, s1);
-  strcat (answer, s2);
-  strcat (answer, s3);
-
-  return answer;
-}
-
-/* concatn.c: Concatenate an arbitrary number of strings.  */
-
-/* OK, it would be epsilon more efficient to compute the total length
-   and then do the copying ourselves, but I doubt it matters in reality.  */
-
-char *
-concatn (const char *str1, ...)
-{
-  char *arg;
-  char *ret;
-  va_list ap;
-
-  va_start (ap, str1);
-
-  if (!str1)
-    return NULL;
-  
-  ret = xstrdup (str1);
-  
-  while ((arg = va_arg (ap, char *)) != NULL)
-    {
-      char *temp = concat (ret, arg);
-      free (ret);
-      ret = temp;
-    }
-  va_end (ap);
-  
-  return ret;
-}
-
-/* debug.c: Help the user discover what's going on.  */
-
-#ifdef KPSE_DEBUG
-
-unsigned kpathsea_debug = 0;
-
-/* If the real definitions of fopen or fclose are macros, we lose -- the
-   #undef won't restore them. */
-
-FILE *
-fopen (const char *filename, const char *mode)
-{
-#undef fopen
-  FILE *ret = fopen (filename, mode);
-
-  if (KPSE_DEBUG_P (KPSE_DEBUG_FOPEN))
-    DEBUGF3 ("fopen(%s, %s) => 0x%lx\n", filename, mode, (unsigned long) ret);
-
-  return ret;
-}
-
-int
-fclose (FILE *f)
-{
-#undef fclose
-  int ret = fclose (f);
-  
-  if (KPSE_DEBUG_P (KPSE_DEBUG_FOPEN))
-    DEBUGF2 ("fclose(0x%lx) => %d\n", (unsigned long) f, ret);
-
-  return ret;
-}
-
-#endif
-
-/* libc replacement functions for win32.  */
-
-/*
-  This does make sense only under WIN32.
-  Functions:
-    - popen() rewritten
-    - pclose() rewritten
-    - stat() wrapper for _stat(), removing trailing slashes
-  */
-
-#ifdef WIN32
-
-#include <fcntl.h>
-
-/* The X library (among other things) defines `FALSE' and `TRUE', and so
-   we only want to define them if necessary, for use by application code.  */
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif /* FALSE */
-
-struct _popen_elt {
-  FILE *f;			/* File stream returned */
-  HANDLE hp;			/* Handle of associated process */
-  struct _popen_elt *next;	/* Next list element */
-};
-
-static struct _popen_elt _z = { NULL, 0, &_z };
-static struct _popen_elt *_popen_list = &_z;
-
-FILE *popen (const char *cmd, const char *mode)
-{
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
-  FILE *f = NULL;
-  int fno, i;
-  HANDLE child_in, child_out;
-  HANDLE father_in, father_out;
-  HANDLE father_in_dup, father_out_dup;
-  HANDLE current_in, current_out;
-  HANDLE current_pid;
-  int binary_mode;
-  char *new_cmd, *app_name = NULL;
-  char *p, *q;
-  struct _popen_elt *new_process;
-  char pname[PATH_MAX], *fp;
-  char *suffixes[] = { ".bat", ".cmd", ".com", ".exe", NULL };
-  char **s;
-  int go_on;
-
-  /* We should look for the application name along the PATH,
-     and decide to prepend "%COMSPEC% /c " or not to the command line.
-     Do nothing for the moment. */
-
-  /* Another way to do that would be to try CreateProcess first without
-     invoking cmd, and look at the error code. If it fails because of
-     command not found, try to prepend "cmd /c" to the cmd line.
-     */
-
-  /* Look for the application name */
-  for (p = cmd; *p && isspace(*p); p++);
-  if (*p == '"') {
-    q = ++p;
-    while(*p && *p != '"') p++;
-    if (*p != '\0') {
-      fprintf(stderr, "popen: malformed command (\" not terminated)\n");
-      return NULL;
-    }
-  }
-  else
-    for (q = p; *p && !isspace(*p); p++);
-  /* q points to the beginning of appname, p to the last + 1 char */
-  if ((app_name = malloc(p - q + 1)) == NULL) {
-    fprintf(stderr, "xpopen: malloc(app_name) failed.\n");
-    return NULL;
-  }
-  strncpy(app_name, q, p - q );
-  app_name[p - q] = '\0';
-  pname[0] = '\0';
-#ifdef TRACE
-  fprintf(stderr, "popen: app_name = %s\n", app_name);
-#endif
-
-  /* Looking for appname on the path */
-  for (s = suffixes, go_on = 1; go_on; *s++) {
-    if (SearchPath(NULL,	/* Address of search path */
-		   app_name,	/* Address of filename */
-		   *s,		/* Address of extension */
-		   PATH_MAX,	/* Size of destination buffer */
-		   pname,	/* Address of destination buffer */
-		   &fp)		/* File part of app_name */
-      != 0) {
-#ifdef TRACE
-      fprintf(stderr, "%s found with suffix %s\n", app_name, *s);
-#endif
-      new_cmd = xstrdup(cmd);
-      free(app_name);
-      app_name = xstrdup(pname);
-      break;
-    }
-    go_on = (*s != NULL);
-  }
-  if (go_on == 0) {
-    /* the app_name was not found */
-#ifdef TRACE
-    fprintf(stderr, "%s not found, concatenating comspec\n", app_name);
-#endif
-    new_cmd = concatn(getenv("COMSPEC"), " /c ", cmd, NULL);
-    free(app_name);
-    app_name = NULL;
-  }
-  else {
-  }
-#ifdef TRACE
-  fprintf(stderr, "popen: app_name = %s\n", app_name);
-  fprintf(stderr, "popen: cmd_line = %s\n", new_cmd);
-#endif
-
-  current_in = GetStdHandle(STD_INPUT_HANDLE);
-  current_out = GetStdHandle(STD_OUTPUT_HANDLE);
-  current_pid = GetCurrentProcess();
-  ZeroMemory( &si, sizeof(STARTUPINFO) );
-  si.cb = sizeof(STARTUPINFO);
-  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-  si.wShowWindow = SW_HIDE;
-
-  if (strchr(mode, 'b'))
-    binary_mode = _O_BINARY;
-  else
-    binary_mode = _O_TEXT;
-
-  /* Opening the pipe for writing */
-  if (strchr(mode, 'w')) {
-    binary_mode |= _O_WRONLY;
-    if (CreatePipe(&child_in, &father_out, &sa, 0) == FALSE) {
-      fprintf(stderr, "popen: error CreatePipe\n");
-      return NULL;
-    }
-#if 0
-    if (SetStdHandle(STD_INPUT_HANDLE, child_in) == FALSE) {
-      fprintf(stderr, "popen: error SetStdHandle child_in\n");
-      return NULL;
-    }
-#endif
-    si.hStdInput = child_in;
-    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-
-    if (DuplicateHandle(current_pid, father_out, 
-			current_pid, &father_out_dup, 
-			0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE) {
-      fprintf(stderr, "popen: error DuplicateHandle father_out\n");
-      return NULL;
-    }
-    CloseHandle(father_out);
-    fno = _open_osfhandle((long)father_out_dup, binary_mode);
-    f = _fdopen(fno, mode);
-    i = setvbuf( f, NULL, _IONBF, 0 );
-  }
-  /* Opening the pipe for reading */
-  else if (strchr(mode, 'r')) {
-    binary_mode |= _O_RDONLY;
-    if (CreatePipe(&father_in, &child_out, &sa, 0) == FALSE) {
-      fprintf(stderr, "popen: error CreatePipe\n");
-      return NULL;
-    }
-#if 0
-    if (SetStdHandle(STD_OUTPUT_HANDLE, child_out) == FALSE) {
-      fprintf(stderr, "popen: error SetStdHandle child_out\n");
-      return NULL;
-    }
-#endif
-    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-    si.hStdOutput = child_out;
-    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-    if (DuplicateHandle(current_pid, father_in, 
-			current_pid, &father_in_dup, 
-			0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE) {
-      fprintf(stderr, "popen: error DuplicateHandle father_in\n");
-      return NULL;
-    }
-    CloseHandle(father_in);
-    fno = _open_osfhandle((long)father_in_dup, binary_mode);
-    f = _fdopen(fno, mode);
-    i = setvbuf( f, NULL, _IONBF, 0 );
-  }
-  else {
-    fprintf(stderr, "popen: invalid mode %s\n", mode);
-    return NULL;
-  }
-
-  /* creating child process */
-  if (CreateProcess(app_name,	/* pointer to name of executable module */
-		    new_cmd,	/* pointer to command line string */
-		    NULL,	/* pointer to process security attributes */
-		    NULL,	/* pointer to thread security attributes */
-		    TRUE,	/* handle inheritance flag */
-		    CREATE_NEW_CONSOLE,		/* creation flags */
-		    NULL,	/* pointer to environment */
-		    NULL,	/* pointer to current directory */
-		    &si,	/* pointer to STARTUPINFO */
-		    &pi		/* pointer to PROCESS_INFORMATION */
-		  ) == FALSE) {
-    fprintf(stderr, "popen: CreateProcess %x\n", GetLastError());
-    return NULL;
-  }
-  
-#if 0
-  /* Restoring saved values for stdin/stdout */
-  if (SetStdHandle(STD_INPUT_HANDLE, current_in) == FALSE) 
-    fprintf(stderr, "popen: error re-redirecting Stdin\n");  
-  if (SetStdHandle(STD_OUTPUT_HANDLE, current_out) == FALSE) 
-    fprintf(stderr, "popen: error re-redirecting Stdout\n");  
-#endif  
-   /* Only the process handle is needed */
-  if (CloseHandle(pi.hThread) == FALSE) {
-    fprintf(stderr, "popen: error closing thread handle\n");
-    return NULL;
-  }
-
-  if (new_cmd) free(new_cmd);
-  if (app_name) free(app_name);
-
-#if 0
-  /* This does not seem to make sense for console apps */
-  while (1) {
-    i = WaitForInputIdle(pi.hProcess, 5); /* Wait 5ms  */
-    if (i == 0xFFFFFFFF) {
-      fprintf(stderr, "popen: process can't initialize\n");
-      return NULL;
-    }
-    else if (i == WAIT_TIMEOUT)
-      fprintf(stderr, "popen: warning, process still not initialized\n");
-    else
-      break;
-  }
-#endif
-
-  /* Add the pair (f, pi.hProcess) to the list */
-  if ((new_process = malloc(sizeof(struct _popen_elt))) == NULL) {
-    fprintf (stderr, "popen: malloc(new_process) error\n");
-    return NULL;
-  }
-  /* Saving the FILE * pointer, access key for retrieving the process
-     handle later on */
-  new_process->f = f;
-  /* Closing the unnecessary part of the pipe */
-  if (strchr(mode, 'r')) {
-    CloseHandle(child_out);
-  }
-  else if (strchr(mode, 'w')) {
-    CloseHandle(child_in);
-  }
-  /* Saving the process handle */
-  new_process->hp = pi.hProcess;
-  /* Linking it to the list of popen() processes */
-  new_process->next = _popen_list;
-  _popen_list = new_process;
-
-  return f;
-
-}
-
-int pclose (FILE *f)
-{
-  struct _popen_elt *p, *q;
-  int exit_code;
-
-  /* Look for f is the access key in the linked list */
-  for (q = NULL, p = _popen_list; 
-       p != &_z && p->f != f; 
-       q = p, p = p->next);
-
-  if (p == &_z) {
-    fprintf(stderr, "pclose: error, file not found.");
-    return -1;
-  }
-
-  /* Closing the FILE pointer */
-  fclose(f);
-
-  /* Waiting for the process to terminate */
-  if (WaitForSingleObject(p->hp, INFINITE) != WAIT_OBJECT_0) {
-    fprintf(stderr, "pclose: error, process still active\n");
-    return -1;
-  }
-
-  /* retrieving the exit code */
-  if (GetExitCodeProcess(p->hp, &exit_code) == 0) {
-    fprintf(stderr, "pclose: can't get process exit code\n");
-    return -1;
-  }
-
-  /* Closing the process handle, this will cause the system to
-     remove the process from memory */
-  if (CloseHandle(p->hp) == FALSE) {
-    fprintf(stderr, "pclose: error closing process handle\n");
-    return -1;
-  }
-
-  /* remove the elt from the list */
-  if (q != NULL)
-    q->next = p->next;
-  else
-    _popen_list = p->next;
-  free(p);
-    
-  return exit_code;
-}
-
-#endif
-
-/* find-suffix.c: return the stuff after a dot.  */
-
-/* Return pointer to first character after `.' in last directory element
-   of NAME.  If the name is `foo' or `/foo.bar/baz', we have no extension.  */
-
-char *
-find_suffix (const char *name)
-{
-  const char *slash_pos;
-  char *dot_pos = strrchr (name, '.');
-  
-  if (dot_pos == NULL)
-    return NULL;
-  
-  for (slash_pos = name + strlen (name);
-       slash_pos > dot_pos && !IS_DIR_SEP (*slash_pos);
-       slash_pos--)
-    ;
-  
-  return slash_pos > dot_pos ? NULL : dot_pos + 1;
-}
-
-/* rm-suffix.c: remove any suffix.  */
-
-/* Generic const warning -- see extend-fname.c.  */
-
-char *
-remove_suffix (const char *s)
-{
-  char *ret;
-  const char *suffix = find_suffix (s);
-  
-  if (suffix)
-    {
-      /* Back up to before the dot.  */
-      suffix--;
-      ret = (char *) xmalloc (suffix - s + 1);
-      strncpy (ret, s, suffix - s);
-      ret[suffix - s] = 0;
-    }
-  else
-    ret = (char *) s;
-    
-  return ret;
-}
-
-/* make-suffix.c: unconditionally add a filename suffix.  */
-
-/* Return a new string: S suffixed with SUFFIX, regardless of what it
-   was before. This returns a newly allocated string.  */ 
-
-char *
-make_suffix (const char *s, const char *suffix)
-{
-  char *new_s;
-  const char *dot_pos = strrchr (s, '.');
-  const char *slash_pos;
-  
-  for (slash_pos = s + strlen (s) - 1; slash_pos > dot_pos && slash_pos > s;
-       slash_pos--) {
-    if (IS_DIR_SEP (*slash_pos))
-      break;
-  }
-
-  if (dot_pos == NULL || slash_pos > dot_pos )
-    new_s = concat3 (s, ".", suffix);
-  else
-    {
-      unsigned past_dot_index = dot_pos + 1 - s;
-      
-      new_s = (char *) xmalloc (past_dot_index + strlen (suffix) + 1);
-      strncpy (new_s, s, dot_pos + 1 - s);
-      strcpy (new_s + past_dot_index, suffix);
-    }
-
-  return new_s;
-}
-
-/* readable.c: check if a filename is a readable non-directory file.  */
-
-/* Truncate any too-long components in NAME, returning the result.  It's
-   too bad this is necessary.  See comments in readable.c for why.  */
-
-static char *
-kpse_truncate_filename (const char *name)
-{
-  unsigned c_len = 0;        /* Length of current component.  */
-  unsigned ret_len = 0;      /* Length of constructed result.  */
-  
-  /* Allocate enough space.  */
-  char *ret = (char *) xmalloc (strlen (name) + 1);
-
-  for (; *name; name++)
-    {
-      if (IS_DIR_SEP (*name) || IS_DEVICE_SEP (*name))
-        { /* At a directory delimiter, reset component length.  */
-          c_len = 0;
-        }
-      else if (c_len > NAME_MAX)
-        { /* If past the max for a component, ignore this character.  */
-          continue;
-        }
-
-      /* Copy this character.  */
-      ret[ret_len++] = *name;
-      c_len++;
-    }
-  ret[ret_len] = 0;
-
-  return ret;
-}
-
-/* If access can read FN, run stat (assigning to stat buffer ST) and
-   check that fn is not a directory.  Don't check for just being a
-   regular file, as it is potentially useful to read fifo's or some
-   kinds of devices.  */
-
-#ifdef __DJGPP__
-/* `stat' is way too expensive for such a simple job.  */
-#define READABLE(fn, st) \
-  (access (fn, R_OK) == 0 && access (fn, D_OK) == -1)
-#elif WIN32
-#define READABLE(fn, st) \
-  (GetFileAttributes(fn) != 0xFFFFFFFF && \
-   !(GetFileAttributes(fn) & FILE_ATTRIBUTE_DIRECTORY))
-#else
-#define READABLE(fn, st) \
-  (access (fn, R_OK) == 0 && stat (fn, &(st)) == 0 && !S_ISDIR (st.st_mode))
-#endif
-
-/* POSIX invented the brain-damage of not necessarily truncating
-   filename components; the system's behavior is defined by the value of
-   the symbol _POSIX_NO_TRUNC, but you can't change it dynamically!
-   
-   Generic const return warning.  See extend-fname.c.  */
-
-char *
-kpse_readable_file (const char *name)
-{
-  struct stat st;
-  char *ret;
-  
-  if (READABLE (name, st)) {
-    ret = (char *) name;
-
-#ifdef ENAMETOOLONG
-  } else if (errno == ENAMETOOLONG) {
-    ret = kpse_truncate_filename (name);
-
-    /* Perhaps some other error will occur with the truncated name, so
-       let's call access again.  */
-    if (!READABLE (ret, st))
-      { /* Failed.  */
-        if (ret != name) free (ret);
-        ret = NULL;
-      }
-#endif /* ENAMETOOLONG */
-
-  } else { /* Some other error.  */
-    if (errno == EACCES) { /* Maybe warn them if permissions are bad.  */
-      perror (name);
-    }
-    ret = NULL;
-  }
-  
-  return ret;
-}
-
-/* absolute.c: Test if a filename is absolute or explicitly relative.  */
-
-/* Sorry this is such a system-dependent mess, but I can't see any way
-   to usefully generalize.  */
-
-int
-kpse_absolute_p (const char *filename, int relative_ok)
-{
-  int absolute = IS_DIR_SEP (*filename)
-#ifdef DOSISH
-                     /* Novell allows non-alphanumeric drive letters. */
-                     || (*filename && IS_DEVICE_SEP (filename[1]))
-#endif /* DOSISH */
-#ifdef WIN32
-                     /* UNC names */
-                     || (*filename == '\\' && filename[1] == '\\')
-#endif
-		      ;
-  int explicit_relative
-    = relative_ok
-      && (*filename == '.' && (IS_DIR_SEP (filename[1])
-                         || (filename[1] == '.' && IS_DIR_SEP (filename[2]))));
-
-  return absolute || explicit_relative;
-}
-
-/* str-list.c: define routines for string lists.  */
-
-/* See the lib.h file for comments.  */
-
-str_list_type
-str_list_init (void)
-{
-  str_list_type ret;
-  
-  STR_LIST_LENGTH (ret) = 0;
-  STR_LIST (ret) = NULL;
-  
-  return ret;
-}
-
-void
-str_list_add (str_list_type *l, char *s)
-{
-  STR_LIST_LENGTH (*l)++;
-  XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), char *);
-  STR_LIST_LAST_ELT (*l) = s;
-}
-
-/* May as well save some reallocations and do everything in a chunk
-   instead of calling str_list_add on each element.  */
-   
-void
-str_list_concat (str_list_type *target, str_list_type more)
-{
-  unsigned e;
-  unsigned prev_len = STR_LIST_LENGTH (*target);
-
-  STR_LIST_LENGTH (*target) += STR_LIST_LENGTH (more);
-  XRETALLOC (STR_LIST (*target), STR_LIST_LENGTH (*target), char *);
-  
-  for (e = 0; e < STR_LIST_LENGTH (more); e++)
-    STR_LIST_ELT (*target, prev_len + e) = STR_LIST_ELT (more, e);
-}
-
-/* Free the list (but not the elements within it).  */
-
-void
-str_list_free (str_list_type *l)
-{
-  if (STR_LIST (*l))
-    {
-      free (STR_LIST (*l));
-      STR_LIST (*l) = NULL;
-    }
-}
-
-/* str-llist.c: Implementation of a linked list of strings.  */
-
-/* Add the new string STR to the end of the list L.  */
-
-void
-str_llist_add (str_llist_type *l, char *str)
-{
-  str_llist_elt_type *e;
-  str_llist_elt_type *new_elt = XTALLOC1 (str_llist_elt_type);
-  
-  /* The new element will be at the end of the list.  */
-  STR_LLIST (*new_elt) = str;
-  STR_LLIST_MOVED (*new_elt) = 0;
-  STR_LLIST_NEXT (*new_elt) = NULL;
-  
-  /* Find the current end of the list.  */
-  for (e = *l; e && STR_LLIST_NEXT (*e); e = STR_LLIST_NEXT (*e))
-    ;
-  
-  if (!e)
-    *l = new_elt;
-  else
-    STR_LLIST_NEXT (*e) = new_elt;
-}
-
-/* Move an element towards the top. The idea is that when a file is
-   found in a given directory, later files will likely be in that same
-   directory, and looking for the file in all the directories in between
-   is thus a waste.  */
-
-void
-str_llist_float (str_llist_type *l, str_llist_elt_type *mover)
-{
-  str_llist_elt_type *last_moved, *unmoved;
-  
-  /* If we've already moved this element, never mind.  */
-  if (STR_LLIST_MOVED (*mover))
-    return;
-  
-  /* Find the first unmoved element (to insert before).  We're
-     guaranteed this will terminate, since MOVER itself is currently
-     unmoved, and it must be in L (by hypothesis).  */
-  for (last_moved = NULL, unmoved = *l; STR_LLIST_MOVED (*unmoved);
-       last_moved = unmoved, unmoved = STR_LLIST_NEXT (*unmoved))
-    ;
-
-  /* If we are the first unmoved element, nothing to relink.  */
-  if (unmoved != mover)
-    { /* Remember `mover's current successor, so we can relink `mover's
-         predecessor to it.  */
-      str_llist_elt_type *before_mover;
-      str_llist_elt_type *after_mover = STR_LLIST_NEXT (*mover);
-      
-      /* Find `mover's predecessor.  */
-      for (before_mover = unmoved; STR_LLIST_NEXT (*before_mover) != mover;
-           before_mover = STR_LLIST_NEXT (*before_mover))
-        ;
-      
-      /* `before_mover' now links to `after_mover'.  */
-      STR_LLIST_NEXT (*before_mover) = after_mover;
-
-      /* Insert `mover' before `unmoved' and after `last_moved' (or at
-         the head of the list).  */
-      STR_LLIST_NEXT (*mover) = unmoved;
-      if (!last_moved)
-        *l = mover;
-      else
-        STR_LLIST_NEXT (*last_moved) = mover;
-    }
-
-  /* We've moved it.  */
-  STR_LLIST_MOVED (*mover) = 1;
-}
-
-/* fn.c: arbitrarily long filenames (or just strings).  */
-
-/* /usr/local/lib/texmf/fonts/public/cm/pk/ljfour/cmr10.300pk is 58
-   chars, so ASCII `K' seems a good choice. */
-#define CHUNK_SIZE 75
-
-fn_type
-fn_init (void)
-{
-  fn_type ret;
-  
-  FN_ALLOCATED (ret) = FN_LENGTH (ret) = 0;
-  FN_STRING (ret) = NULL;
-  
-  return ret;
-}
-
-fn_type
-fn_copy0 (const char *s, unsigned len)
-{
-  fn_type ret;
-  
-  FN_ALLOCATED (ret) = CHUNK_SIZE > len ? CHUNK_SIZE : len + 1;
-  FN_STRING (ret) = (char *) xmalloc (FN_ALLOCATED (ret));
-  
-  strncpy (FN_STRING (ret), s, len);
-  FN_STRING (ret)[len] = 0;
-  FN_LENGTH (ret) = len + 1;
-  
-  return ret;
-}
-
-/* Don't think we ever try to free something that might usefully be
-   empty, so give fatal error if nothing allocated.  */
-
-void
-fn_free (fn_type *f)
-{
-  assert (FN_STRING (*f) != NULL);
-  free (FN_STRING (*f));
-  FN_STRING (*f) = NULL;
-  FN_ALLOCATED (*f) = 0;
-  FN_LENGTH (*f) = 0;
-}
-
-/* An arithmetic increase seems more reasonable than geometric.  We
-   don't increase the length member since it may be more convenient for
-   the caller to add than subtract when appending the stuff that will
-   presumably follow.  */
-
-static void
-grow (fn_type *f, unsigned len)
-{
-  while (FN_LENGTH (*f) + len > FN_ALLOCATED (*f))
-    {
-      FN_ALLOCATED (*f) += CHUNK_SIZE;
-      XRETALLOC (FN_STRING (*f), FN_ALLOCATED (*f), char);
-    }
-}
-
-void
-fn_1grow (fn_type *f, char c)
-{
-  grow (f, 1);
-  FN_STRING (*f)[FN_LENGTH (*f)] = c;
-  FN_LENGTH (*f)++;
-}
-
-void
-fn_grow (fn_type *f, void *source, unsigned len)
-{
-  grow (f, len);
-  strncpy (FN_STRING (*f) + FN_LENGTH (*f), (char *) source, len);
-  FN_LENGTH (*f) += len;
-}
-
-void
-fn_str_grow (fn_type *f, const char *s)
-{
-  unsigned more_len = strlen (s);
-  grow (f, more_len);
-  strcat (FN_STRING (*f), s);
-  FN_LENGTH (*f) += more_len;
-}
-
-void
-fn_shrink_to (fn_type *f, unsigned loc)
-{
-  assert (FN_LENGTH (*f) > loc);
-  FN_STRING (*f)[loc] = 0;
-  FN_LENGTH (*f) = loc + 1;
-}
-
-/* variable.c: variable expansion.  */
-
-/* Here's the simple one, when a program just wants a value.  */
-
-char *
-kpse_var_value (const char *var)
-{
-  char *ret = getenv (var);
-
-  if (ret)
-    ret = kpse_var_expand (ret);
-
-#ifdef KPSE_DEBUG
-  if (KPSE_DEBUG_P (KPSE_DEBUG_VARS))
-    DEBUGF2("variable: %s = %s\n", var, ret ? ret : "(nil)");
-#endif
-
-  return ret;
-}
-
-/* We have to keep track of variables being expanded, otherwise
-   constructs like TEXINPUTS = $TEXINPUTS result in an infinite loop.
-   (Or indirectly recursive variables, etc.)  Our simple solution is to
-   add to a list each time an expansion is started, and check the list
-   before expanding.  */
-
-typedef struct {
-  const char *var;
-  int expanding;
-} expansion_type;
-static expansion_type *expansions; /* The sole variable of this type.  */
-static unsigned expansion_len = 0;
-
-static void
-expanding (const char *var, int xp)
-{
-  unsigned e;
-  for (e = 0; e < expansion_len; e++) {
-    if (STREQ (expansions[e].var, var)) {
-      expansions[e].expanding = xp;
-      return;
-    }
-  }
-
-  /* New variable, add it to the list.  */
-  expansion_len++;
-  XRETALLOC (expansions, expansion_len, expansion_type);
-  expansions[expansion_len - 1].var = xstrdup (var);
-  expansions[expansion_len - 1].expanding = xp;
-}
-
-
-/* Return whether VAR is currently being expanding.  */
-
-static int
-expanding_p (const char *var)
-{
-  unsigned e;
-  for (e = 0; e < expansion_len; e++) {
-    if (STREQ (expansions[e].var, var))
-      return expansions[e].expanding;
-  }
-  
-  return 0;
-}
-
-/* Append the result of value of `var' to EXPANSION, where `var' begins
-   at START and ends at END.  If `var' is not set, do not complain.
-   This is a subroutine for the more complicated expansion function.  */
-
-static void
-expand (fn_type *expansion, const char *start, const char *end)
-{
-  char *value;
-  unsigned len = end - start + 1;
-  char *var = (char *) xmalloc (len + 1);
-  strncpy (var, start, len);
-  var[len] = 0;
-  
-  if (expanding_p (var)) {
-    WARNING1 ("kpathsea: variable `%s' references itself (eventually)", var);
-  } else {
-    /* Check for an environment variable.  */
-    value = getenv (var);
-
-    if (value) {
-      expanding (var, 1);
-      value = kpse_var_expand (value);
-      expanding (var, 0);
-      fn_grow (expansion, value, strlen (value));
-      free (value);
-    }
-
-    free (var);
-  }
-}
-
-/* Can't think of when it would be useful to change these (and the
-   diagnostic messages assume them), but ... */
-#ifndef IS_VAR_START /* starts all variable references */
-#define IS_VAR_START(c) ((c) == '$')
-#endif
-#ifndef IS_VAR_CHAR  /* variable name constituent */
-#define IS_VAR_CHAR(c) (ISALNUM (c) || (c) == '_')
-#endif
-#ifndef IS_VAR_BEGIN_DELIMITER /* start delimited variable name (after $) */
-#define IS_VAR_BEGIN_DELIMITER(c) ((c) == '{')
-#endif
-#ifndef IS_VAR_END_DELIMITER
-#define IS_VAR_END_DELIMITER(c) ((c) == '}')
-#endif
-
-
-/* Maybe we should support some or all of the various shell ${...}
-   constructs, especially ${var-value}.  */
-
-char *
-kpse_var_expand (const char *src)
-{
-  const char *s;
-  char *ret;
-  fn_type expansion;
-  expansion = fn_init ();
-  
-  /* Copy everything but variable constructs.  */
-  for (s = src; *s; s++) {
-    if (IS_VAR_START (*s)) {
-      s++;
-
-      /* Three cases: `$VAR', `${VAR}', `$<anything-else>'.  */
-      if (IS_VAR_CHAR (*s)) {
-        /* $V: collect name constituents, then expand.  */
-        const char *var_end = s;
-
-        do {
-          var_end++;
-        } while (IS_VAR_CHAR (*var_end));
-
-        var_end--; /* had to go one past */
-        expand (&expansion, s, var_end);
-        s = var_end;
-
-      } else if (IS_VAR_BEGIN_DELIMITER (*s)) {
-        /* ${: scan ahead for matching delimiter, then expand.  */
-        const char *var_end = ++s;
-
-        while (*var_end && !IS_VAR_END_DELIMITER (*var_end))
-          var_end++;
-
-        if (! *var_end) {
-          WARNING1 ("%s: No matching } for ${", src);
-          s = var_end - 1; /* will incr to null at top of loop */
-        } else {
-          expand (&expansion, s, var_end - 1);
-          s = var_end; /* will incr past } at top of loop*/
-        }
-
-      } else {
-        /* $<something-else>: error.  */
-        WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s);
-        /* Just ignore those chars and keep going.  */
-      }
-    } else
-     fn_1grow (&expansion, *s);
-  }
-  fn_1grow (&expansion, 0);
-          
-  ret = FN_STRING (expansion);
-  return ret;
-}
--- a/liboctave/kpse-xfns.h	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/kpse-xfns.h	Thu Apr 24 03:27:41 2003 +0000
@@ -18,209 +18,6 @@
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#ifndef KPATHSEA_LIB_H
-#define KPATHSEA_LIB_H
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/* c-std.h: the first header files.  */
-
-/* Header files that essentially all of our sources need, and
-   that all implementations have.  We include these first, to help with
-   NULL being defined multiple times.  */
-#include <math.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <sys/types.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <stdlib.h>
-
-#ifdef WIN32
-#include <malloc.h>
-#endif /* not WIN32 */
-
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-/* c-dir.h: directory headers.  */
-
-#ifdef WIN32
-
-#include <direct.h>
-
-#else /* not WIN32 */
-
-/* Use struct dirent instead of struct direct.  */
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#define NAMLEN(dirent) strlen ((dirent)->d_name)
-#else /* not DIRENT */
-#define dirent direct
-#define NAMLEN(dirent) ((dirent)->d_namlen)
-
-#ifdef HAVE_SYS_NDIR_H
-#include <sys/ndir.h>
-#endif
-
-#ifdef HAVE_SYS_DIR_H
-#include <sys/dir.h>
-#endif
-
-#ifdef HAVE_NDIR_H
-#include <ndir.h>
-#endif
-
-#endif /* not DIRENT */
-
-#endif /* not WIN32 */
-
-/* c-fopen.h: how to open files with fopen.  */
-
-/* How to open a text file:  */
-#ifndef FOPEN_A_MODE
-#define FOPEN_A_MODE "a"
-#endif
-
-#ifndef FOPEN_R_MODE
-#define FOPEN_R_MODE "r"
-#endif
-
-#ifndef FOPEN_W_MODE
-#define FOPEN_W_MODE "w"
-#endif
-
-/* How to open a binary file for reading:  */
-#ifndef FOPEN_RBIN_MODE
-#if defined(DOS) || defined (OS2) || defined (WIN32) || defined (__DJGPP__) || defined (__CYGWIN32__)
-#define	FOPEN_RBIN_MODE	"rb"
-#else
-#define	FOPEN_RBIN_MODE	"r"
-#endif /* not (DOS or OS2 or WIN32 or __DJGPP__ or __CYGWIN32__) */
-#endif /* not FOPEN_RBIN_MODE */
-
-/* How to open a binary file for writing:  */
-#ifndef FOPEN_WBIN_MODE
-#if defined (DOS) || defined (OS2) || defined (WIN32) || defined (__DJGPP__) || defined (__CYGWIN32__)
-#define FOPEN_WBIN_MODE "wb"
-#else
-#define	FOPEN_WBIN_MODE	"w"
-#endif /* not (DOS or OS2 or WIN32 or DJGPP or CYGWIN32) */
-#endif /* not FOPEN_WBIN_MODE */
-
-/* How to open a binary file for appending:  */
-#ifndef FOPEN_ABIN_MODE
-#if defined (DOS) || defined (OS2) || defined (WIN32) || defined (__DJGPP__) || defined (__CYGWIN32__)
-#define FOPEN_ABIN_MODE "ab"
-#else
-#define FOPEN_ABIN_MODE "a"
-#endif /* not (DOS or OS2 or WIN32 or DJGPP or CYGWIN32) */
-#endif /* not FOPEN_ABIN_MODE */
-
-/* How to switch an already open file handle to binary mode.
-   Used on DOSISH systems when we need to switch a standard
-   stream, such as stdin or stdout, to binary mode.  */
-#include <fcntl.h>
-#ifdef DOSISH
-#include <io.h>
-#ifndef O_BINARY
-#ifdef _O_BINARY
-#define O_BINARY _O_BINARY
-#endif
-#endif
-#if defined (__DJGPP__) || defined (WIN32) || defined (__CYGWIN32__)
-#define SET_BINARY(f) setmode((f), O_BINARY)
-#endif
-#else  /* not DOSISH */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#define SET_BINARY(f) 0
-#endif /* not DOSISH */
-
-/* c-namemx.h: define NAME_MAX, the maximum length of a single
-   component in a filename.  No such limit may exist, or may vary
-   depending on the filesystem.  */
-
-#include <limits.h>
-
-/* Most likely the system will truncate filenames if it is not POSIX,
-   and so we can use the BSD value here.  */
-#ifndef _POSIX_NAME_MAX
-#define _POSIX_NAME_MAX 255
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
-
-/* c-ctype.h: ASCII-safe versions of the <ctype.h> macros.  */
-
-#include <ctype.h>
-
-/* Be sure we have `isascii'.  */
-#ifndef isascii
-#define isascii(c) 1
-#endif
-
-#define ISALNUM(c) (isascii (c) && isalnum(c))
-#define ISALPHA(c) (isascii (c) && isalpha(c))
-#define ISASCII isascii
-#define ISCNTRL(c) (isascii (c) && iscntrl(c))
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
-#define ISGRAPH(c) (isascii (c) && isgraph(c))
-#define ISLOWER(c) (isascii (c) && islower(c))
-#define ISPRINT(c) (isascii (c) && isprint(c))
-#define ISPUNCT(c) (isascii (c) && ispunct(c))
-#define ISSPACE(c) (isascii (c) && isspace(c))
-#define ISUPPER(c) (isascii (c) && isupper(c))
-#define ISXDIGIT(c) (isascii (c) && isxdigit(c))
-#define TOASCII toascii
-#define TOLOWER(c) (ISUPPER (c) ? tolower (c) : (c))
-#define TOUPPER(c) (ISLOWER (c) ? toupper (c) : (c))
-
-/* This isn't part of the usual <ctype.h>, but it's useful sometimes.  */
-#ifndef isblank
-#define isblank(c) ((c) == ' ' || (c) == '\t')
-#endif
-
-/* Here's why this mess is necessary:
-
-From: meyering@cs.utexas.edu (Jim Meyering)
-Date: Wed, 25 Nov 1992 09:52:33 -0600
-Subject: ss-921123: using isascii with <ctype.h> macros
-
-  Yesterday some cursory regression testing found that GNU od
-  (in an upcoming release of textutils) generated incorrect output
-  when run on an SGI indigo because isprint ('\377') returned true.
-  Of course, '\377' is not a printing character;  the problem lay
-  in using isprint without first making sure its integer argument
-  corresponded to an ascii code.
-
-  MORAL: always guard uses of ctype macros with isascii if it's available.
-  An obvious alternative is to avoid <ctype.h> and define and use your
-  own versions of the ctype macros.
-
-  A pretty clean approach to using <ctype.h> and isascii was
-  suggested by David MacKenzie:
-
-  #ifndef isascii
-  #define isascii(c) 1
-  #endif
-
-  #define ISDIGIT(c) (isascii (c) && isdigit (c))
-  #define ISPRINT(c) (isascii (c) && isprint (c))
-  ...
-
-  then, use ISDIGIT, etc. instead of isdigit, etc.  */
-  
 /* c-pathch.h: define the characters which separate components of
    filenames and environment variable paths.  */
 
@@ -250,625 +47,3 @@
 #ifndef NAME_BEGINS_WITH_DEVICE
 #define NAME_BEGINS_WITH_DEVICE(name) 0 
 #endif
-
-/* What separates elements in environment variable path lists?  */
-#ifndef ENV_SEP
-#ifdef DOSISH
-#define ENV_SEP ';'
-#define ENV_SEP_STRING ";"
-#else
-#define ENV_SEP ':'
-#define ENV_SEP_STRING ":"
-#endif /* not DOS */
-#endif /* not ENV_SEP */
-
-#ifndef IS_ENV_SEP
-#define IS_ENV_SEP(ch) ((ch) == ENV_SEP)
-#endif
-
-/* c-pathmx.h: define PATH_MAX, the maximum length of a filename.
-   Since no such limit may exist, it's preferable to dynamically grow
-   filenames as needed.  */
-
-#include <limits.h>
-
-/* Cheat and define this as a manifest constant no matter what, instead
-   of using pathconf.  I forget why we want to do this.  */
-
-#ifndef _POSIX_PATH_MAX
-#define _POSIX_PATH_MAX 255
-#endif
-
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX _POSIX_PATH_MAX
-#endif
-#endif /* not PATH_MAX */
-
-/* c-proto.h: macros to include or discard prototypes.  */
-
-#if !defined(WIN32)
-#define DllImport
-#define __cdecl
-#elif (defined(_DLL) && !defined(_IMPORT)) || !defined(_DLL)
-#define DllImport
-#else
-#define DllImport __declspec(dllimport)
-#endif
-
-/* debug.h: Runtime tracing.  */
-
-/* If NO_DEBUG is defined (not recommended), skip all this.  */
-#ifndef NO_DEBUG
-
-#if defined(WIN32)
-#if defined(_DEBUG)
-/* This was needed at some time for catching errors in pdftex. */
-#include <crtdbg.h>
-#define  SET_CRT_DEBUG_FIELD(a) \
-            _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
-#define  CLEAR_CRT_DEBUG_FIELD(a) \
-            _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
-#define  SETUP_CRTDBG \
-   { _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );    \
-     _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );  \
-     _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );   \
-     _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); \
-     _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );  \
-     _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );\
-   }
-#else /* ! _DEBUG */
-#define SET_CRT_DEBUG_FIELD(a) 
-#define CLEAR_CRT_DEBUG_FIELD(a)
-#define SETUP_CRTDBG
-#endif /* _DEBUG */
-#endif /* WIN32 */
-
-/* OK, we'll have tracing support.  */
-#define KPSE_DEBUG
-
-/* Bit vector defining what we should trace.  */
-extern DllImport unsigned kpathsea_debug;
-
-/* Set a bit.  */
-#define KPSE_DEBUG_SET(bit) kpathsea_debug |= 1 << (bit)
-
-/* Test if a bit is on.  */
-#define KPSE_DEBUG_P(bit) (kpathsea_debug & (1 << (bit)))
-
-#define KPSE_DEBUG_STAT 0		/* stat calls */
-#define KPSE_DEBUG_HASH 1		/* hash lookups */
-#define KPSE_DEBUG_FOPEN 2		/* fopen/fclose calls */
-#define KPSE_DEBUG_PATHS 3		/* search path initializations */
-#define KPSE_DEBUG_EXPAND 4		/* path element expansion */
-#define KPSE_DEBUG_SEARCH 5		/* searches */
-#define KPSE_DEBUG_VARS 6		/* variable values */
-#define KPSE_LAST_DEBUG KPSE_DEBUG_VARS
-
-/* A printf for the debugging.  */
-#define DEBUGF_START() do { fputs ("kdebug:", stderr)
-#define DEBUGF_END()        fflush (stderr); } while (0)
-
-#define DEBUGF(str)							\
-  DEBUGF_START (); fputs (str, stderr); DEBUGF_END ()
-#define DEBUGF1(str, e1)						\
-  DEBUGF_START (); fprintf (stderr, str, e1); DEBUGF_END ()
-#define DEBUGF2(str, e1, e2)						\
-  DEBUGF_START (); fprintf (stderr, str, e1, e2); DEBUGF_END ()
-#define DEBUGF3(str, e1, e2, e3)					\
-  DEBUGF_START (); fprintf (stderr, str, e1, e2, e3); DEBUGF_END ()
-#define DEBUGF4(str, e1, e2, e3, e4)					\
-  DEBUGF_START (); fprintf (stderr, str, e1, e2, e3, e4); DEBUGF_END ()
-
-#undef fopen
-#define fopen kpse_fopen_trace
-extern FILE *fopen (const char *filename, const char *mode);
-#undef fclose
-#define fclose kpse_fclose_trace
-extern int fclose (FILE *);
-
-#endif /* not NO_DEBUG */
-
-/* c-stat.h: declarations for using stat(2).  */
-
-#include <sys/types.h>
-
-/* This is the symbol that X uses to determine if <sys/types.h> has been
-   read, so we define it.  */
-#define __TYPES__
-
-#include <sys/stat.h>
-
-#if defined (WIN32) && !defined (__MINGW32__)
-
-/* System description file for Windows NT.  */
-
-/*
- *      Define symbols to identify the version of Unix this is.
- *      Define all the symbols that apply correctly.
- */
-
-#ifndef DOSISH
-#define DOSISH
-#endif
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN      _MAX_PATH
-#endif
-
-#define HAVE_DUP2       	1
-#define HAVE_RENAME     	1
-#define HAVE_RMDIR      	1
-#define HAVE_MKDIR      	1
-#define HAVE_GETHOSTNAME	1
-#define HAVE_RANDOM		1
-#define USE_UTIME		1
-#define HAVE_MOUSE		1
-#define HAVE_TZNAME		1
-
-/* These have to be defined because our compilers treat __STDC__ as being
-   defined (most of them anyway). */
-
-#define access  _access
-#define alloca  _alloca
-#define chdir   _chdir
-#define chmod   _chmod
-#define close   _close
-#define creat   _creat
-#define dup     _dup
-#define dup2    _dup2
-#define execlp  _execlp
-#define execvp  _execvp
-#define fdopen  _fdopen
-#define fileno  _fileno
-#define getpid  _getpid
-#define getwd(dir)  GetCurrentDirectory(MAXPATHLEN, dir)
-#define index   strchr
-#define isatty  _isatty
-#define itoa    _itoa
-#define link    _link
-#define lseek   _lseek
-#define mkdir   _mkdir
-#define mktemp  _mktemp
-#define open    _open
-#define pipe    _pipe
-#if 0
-#define popen	_popen
-#define pclose	_pclose
-#endif
-#define read    _read
-#define rmdir   _rmdir
-#define setmode _setmode
-#define spawnlp _spawnlp
-#define stat    _stat
-#define strcasecmp _stricmp
-#define strdup  _strdup
-#define strncasecmp _strnicmp
-#define unlink  _unlink
-#define umask	_umask
-#define utime	_utime
-#define write   _write
-
-#define S_IFMT   _S_IFMT
-#define S_IFDIR  _S_IFDIR
-#define S_IFCHR  _S_IFCHR
-#define S_IFIFO  _S_IFIFO
-#define S_IFREG  _S_IFREG
-#define S_IREAD  _S_IREAD
-#define S_IWRITE _S_IWRITE
-#define S_IEXEC  _S_IEXEC 
-#define S_IXUSR  _S_IEXEC
-#define S_IXGRP  _S_IEXEC
-#define S_IXOTH  _S_IEXEC
-#define S_IRUSR  _S_IREAD
-#define S_IWUSR  _S_IWRITE
-#define O_RDWR   _O_RDWR
-#define O_CREAT  _O_CREAT
-#define O_TRUNC  _O_TRUNC
-#define O_RDONLY _O_RDONLY
-#define O_WRONLY _O_WRONLY
-#define O_APPEND _O_APPEND
-#define O_TEXT   _O_TEXT
-#define O_BINARY _O_BINARY
-
-/* Define this so that winsock.h definitions don't get included when
-   windows.h is...  For this to have proper effect, config.h must
-   always be included before windows.h.  */ 
-#define _WINSOCKAPI_    1
-
-#include <windows.h>
-
-/* Defines size_t and alloca ().  */
-#include <malloc.h>
-
-/* For proper declaration of environ.  */
-#include <stdlib.h>
-#include <io.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <process.h>
-
-/* Web2C takes care of ensuring that these are defined.  */
-#ifdef max
-#undef max
-#undef min
-#endif
-
-/* Functions from win32lib.c */
-extern FILE *popen(const char *, const char *);
-extern int pclose(FILE *);
-
-/* ============================================================ */
-
-#endif /* WIN32 */
-
-/* POSIX predicates for testing file attributes.  */
-
-#if !defined (S_ISBLK) && defined (S_IFBLK)
-#define	S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
-#endif
-#if !defined (S_ISCHR) && defined (S_IFCHR)
-#define	S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-#endif
-#if !defined (S_ISDIR) && defined (S_IFDIR)
-#define	S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-#if !defined (S_ISREG) && defined (S_IFREG)
-#define	S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-#if !defined (S_ISFIFO) && defined (S_IFIFO)
-#define	S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-#endif
-#if !defined (S_ISLNK) && defined (S_IFLNK)
-#define	S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#endif
-#if !defined (S_ISSOCK) && defined (S_IFSOCK)
-#define	S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
-#endif
-#if !defined (S_ISMPB) && defined (S_IFMPB) /* V7 */
-#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
-#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
-#endif
-#if !defined (S_ISNWK) && defined (S_IFNWK) /* HP/UX */
-#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
-#endif
-
-/* readable.h: Is a file readable?  */
-
-/* If NAME is readable and is a regular file, return it.  If the error is
-   ENAMETOOLONG, truncate any too-long path components, and if the
-   result is a readable file, return that.  Otherwise return NULL.  */
-   
-extern char *kpse_readable_file (const char *name);
-
-/* absolute.h: Declare absolute filename predicate.  */
-
-extern int kpse_absolute_p (const char *filename, int relative_ok);
-
-/* hash.h: declarations for a hash table.  */
-
-/* A single (key,value) pair.  */
-typedef struct hash_element_struct
-{
-  const char *key;
-  const char *value;
-  struct hash_element_struct *next;
-} hash_element_type;
-
-/* The usual arrangement of buckets initialized to null.  */
-typedef struct
-{
-  hash_element_type **buckets;
-  unsigned size;
-} hash_table_type;
-
-#ifdef KPSE_DEBUG
-/* How to print the hash results when debugging.  */
-extern int kpse_debug_hash_lookup_int;
-#endif
-
-/* Create a hash table of size SIZE.  */
-extern hash_table_type hash_create (unsigned size);
-
-/* Insert the (KEY,VALUE) association into TABLE.  KEY may have more
-   than one VALUE.  Neither KEY nor VALUE is copied.  */
-extern void hash_insert (hash_table_type *table,  const char *key,
-			 const char *value);
-
-/* Remove the (KEY,VALUE) association from TABLE.  */
-extern void hash_remove (hash_table_type *table,  const char *key,
-			 const char *value);
-
-/* Look up KEY in MAP, and return NULL-terminated list of all matching
-   values (not copies), in insertion order.  If none, return NULL.  */
-extern char **hash_lookup (hash_table_type table, const char *key);
-
-/* Print TABLE to stderr.  */
-extern void hash_print (hash_table_type table, int summary_only);
-
-/* str-list.h: Declarations for string lists.  */
-
-/* Lists of strings; used for, e.g., directory lists.  */
-
-typedef struct
-{
-  unsigned length;
-  char **list;
-} str_list_type;
-
-#define STR_LIST_LENGTH(l) ((l).length)
-#define STR_LIST(l) ((l).list)
-#define STR_LIST_ELT(l, n) STR_LIST (l)[n]
-#define STR_LIST_LAST_ELT(l) STR_LIST_ELT (l, STR_LIST_LENGTH (l) - 1)
-
-/* Return a new, empty, list.  */
-extern str_list_type str_list_init (void);
-
-/* Append the string S to the list L.  It's up to the caller to not
-   deallocate S; we don't copy it.  Also up to the caller to terminate
-   the list with a null entry.  */
-extern void str_list_add (str_list_type *l, char *s);
-
-/* Append all the elements from MORE to TARGET.  */
-extern void str_list_concat (str_list_type * target, str_list_type more);
-
-/* Free the space for the list elements (but not the list elements
-   themselves).  */
-extern void str_list_free (str_list_type *l);
-
-/* str-llist.h: A linked list of strings,
-
-It's pretty disgusting that both this and str-list exist; the reason is
-that C cannot express iterators very well, and I don't want to change
-all the for loops right now.  */
-
-/* It's a little bizarre to be using the same type for the list and the
-   elements of the list, but no reason not to in this case, I think --
-   we never need a NULL string in the middle of the list, and an extra
-   NULL/NULL element always at the end is inconsequential.  */
-
-struct str_llist_elt
-{
-  char *str;
-  int moved;
-  struct str_llist_elt *next;
-};
-typedef struct str_llist_elt str_llist_elt_type;
-typedef struct str_llist_elt *str_llist_type;
-
-#define STR_LLIST(sl) ((sl).str)
-#define STR_LLIST_MOVED(sl) ((sl).moved)
-#define STR_LLIST_NEXT(sl) ((sl).next)
-
-
-/* Add the new string E to the end of the list L.  */
-extern void str_llist_add (str_llist_type *l, char *e);
-
-/* Reorganize L so that E is below only other elements that have already
-   been moved.  Set `moved' member for E.  */
-extern void str_llist_float (str_llist_type *l, str_llist_elt_type *e);
-
-/* xstat.h: stat with error checking.  */
-
-/* Two files are indistinguishable if they are on the same device
-   and have the same inode.  This checks two stat buffers for that.  Cf.
-   the `same_file_p' routine in file-p.c, declared in kpathlib.h.  */
-#define SAME_FILE_P(s1, s2) \
-  ((s1).st_ino == (s2).st_ino && (s1).st_dev == (s2).st_dev)
-
-/* Does stat(2) on PATH, and aborts if the stat fails.  */
-extern struct stat xstat (const char *path);
-
-/* Ditto, for lstat(2) (except that lstat might not exist).  */
-#ifdef S_ISLNK
-extern struct stat xlstat (const char *path);
-#else
-#define xlstat xstat
-#endif
-
-/* fn.h: arbitrarily long filenames (or just strings).  */
-
-/* Arbitrarily long filenames; it's inconvenient to use obstacks here,
-   because we want to maintain a null terminator.  Also used for
-   dynamically growing strings even when the null byte isn't necessary,
-   e.g., in `variable.c', since I don't want to pass obstacks around
-   everywhere, and one can't free parts of an obstack arbitrarily.  */
-
-typedef struct
-{
-  char *str;
-  unsigned allocated;
-  unsigned length; /* includes the terminating null byte, if any */
-} fn_type;
-
-#define FN_STRING(fn) ((fn).str)
-#define FN_ALLOCATED(fn) ((fn).allocated)
-#define FN_LENGTH(fn) ((fn).length)
-
-
-/* Create a new empty fn.  */
-extern fn_type fn_init (void);
-
-/* Create a new fn from the first LEN characters from S and a null.  */
-extern fn_type fn_copy0 (const char *s,  unsigned len);
-
-/* Free what's been allocated.  Can also just free the string if it's
-   been extracted out.  Fatal error if nothing allocated in F.  */
-extern void fn_free (fn_type *f);
-
-/* Append the character C to the fn F.  Don't append trailing null.  */
-extern void fn_1grow (fn_type *f, char c);
-
-/* Append LENGTH bytes from SOURCE to F.  */
-extern void fn_grow (fn_type *f, void *source, unsigned length);
-
-/* Concatenate the component S to the fn F.  Assumes string currently in
-   F is null terminated.  */
-extern void fn_str_grow (fn_type *f, const char *s);
-
-/* Add a null to F's string at position LOC, and update its length.
-   Fatal error if LOC is past the end of the string.  */
-extern void fn_shrink_to (fn_type *f, unsigned loc);
-
-/* variable.h: Declare variable expander.  */
-
-/* Return the (variable-expanded) environment variable value or config
-   file value, or NULL.  */
-extern char *kpse_var_value (const char *var);
-
-/* Expand $VAR and ${VAR} references in SRC, returning the (always newly
-   dynamically-allocated) result.  An unterminated ${ or any other
-   character following $ produce error messages, and that part of SRC is
-   ignored.  In the $VAR form, the variable name consists of consecutive
-   letters, digits, and underscores.  In the ${VAR} form, the variable
-   name consists of whatever is between the braces.
-   
-   In any case, ``expansion'' means calling `getenv'; if the variable is not
-   set, look in texmf.cnf files for a definition.  If not set there, either,
-   the expansion is the empty string (no error).  */
-extern char *kpse_var_expand (const char *src);
-
-/* lib.h: other stuff.  */
-
-/* Define common sorts of messages.  */
-
-/* This should be called only after a system call fails.  Don't exit
-   with status `errno', because that might be 256, which would mean
-   success (exit statuses are truncated to eight bits).  */
-#define FATAL_PERROR(str) do { \
-  fputs ("pathsearch: ", stderr); \
-  perror (str); exit (EXIT_FAILURE); } while (0)
-
-#define START_FATAL() do { \
-  fputs ("pathsearch: fatal: ", stderr);
-#define END_FATAL() fputs (".\n", stderr); exit (1); } while (0)
-
-#define FATAL(str)							\
-  START_FATAL (); fputs (str, stderr); END_FATAL ()
-#define FATAL1(str, e1)							\
-  START_FATAL (); fprintf (stderr, str, e1); END_FATAL ()
-#define FATAL2(str, e1, e2)						\
-  START_FATAL (); fprintf (stderr, str, e1, e2); END_FATAL ()
-#define FATAL3(str, e1, e2, e3)						\
-  START_FATAL (); fprintf (stderr, str, e1, e2, e3); END_FATAL ()
-#define FATAL4(str, e1, e2, e3, e4)					\
-  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4); END_FATAL ()
-#define FATAL5(str, e1, e2, e3, e4, e5)					\
-  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4, e5); END_FATAL ()
-#define FATAL6(str, e1, e2, e3, e4, e5, e6)				\
-  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4, e5, e6); END_FATAL ()
-
-
-#define START_WARNING() do { fputs ("warning: ", stderr)
-#define END_WARNING() fputs (".\n", stderr); fflush (stderr); } while (0)
-
-#define WARNING(str)							\
-  START_WARNING (); fputs (str, stderr); END_WARNING ()
-#define WARNING1(str, e1)						\
-  START_WARNING (); fprintf (stderr, str, e1); END_WARNING ()
-#define WARNING2(str, e1, e2)						\
-  START_WARNING (); fprintf (stderr, str, e1, e2); END_WARNING ()
-#define WARNING3(str, e1, e2, e3)					\
-  START_WARNING (); fprintf (stderr, str, e1, e2, e3); END_WARNING ()
-#define WARNING4(str, e1, e2, e3, e4)					\
-  START_WARNING (); fprintf (stderr, str, e1, e2, e3, e4); END_WARNING ()
-
-
-/* I find this easier to read.  */
-#define STREQ(s1, s2) (strcmp (s1, s2) == 0)
-#define STRNEQ(s1, s2, n) (strncmp (s1, s2, n) == 0)
-      
-/* Support for FAT/ISO-9660 filesystems.  Theoretically this should be
-   done at runtime, per filesystem, but that's painful to program.  */
-#ifdef MONOCASE_FILENAMES
-#define FILESTRCASEEQ(s1, s2) (strcasecmp (s1, s2) == 0)
-#define FILESTRNCASEEQ(s1, s2, l) (strncasecmp (s1, s2, l) == 0)
-#define FILECHARCASEEQ(c1, c2) (toupper (c1) == toupper (c2))
-#else
-#define FILESTRCASEEQ STREQ
-#define FILESTRNCASEEQ STRNEQ
-#define FILECHARCASEEQ(c1, c2) ((c1) == (c2))
-#endif
-
-/* This is the maximum number of numerals that result when a 64-bit
-   integer is converted to a string, plus one for a trailing null byte,
-   plus one for a sign.  */
-#define MAX_INT_LENGTH 21
-
-/* If the environment variable TEST is set, return it; otherwise,
-   DEFAULT.  This is useful for paths that use more than one envvar.  */
-#define ENVVAR(test, default) (getenv (test) ? (test) : (default))
-
-/* Return a fresh copy of S1 followed by S2, et al.  */
-extern DllImport char *concat (const char *s1, const char *s2);
-extern DllImport char *concat3 (const char *, const char *, const char *);
-extern DllImport char *concatn (const char *str1, ...);
-
-/* A fresh copy of just S.  */
-extern DllImport char *xstrdup (const char *s);
-
-/* True if FILENAME1 and FILENAME2 are the same file.  If stat fails on
-   either name, return false, no error message.
-   Cf. `SAME_FILE_P' in xstat.h.  */
-extern DllImport int same_file_p (const char *filename1,
-				  const char *filename2);
-
-#ifndef HAVE_BASENAME
-/* Return NAME with any leading path stripped off.  This returns a
-   pointer into NAME.  */
-extern DllImport const char *basename (const char *name);
-#endif /* not HAVE_BASENAME */
-
-/* If NAME has a suffix, return a pointer to its first character (i.e.,
-   the one after the `.'); otherwise, return NULL.  */
-extern DllImport char *find_suffix (const char *name);
-
-/* Return NAME with any suffix removed.  */
-extern DllImport char *remove_suffix (const char *name);
-
-/* Return S with the suffix SUFFIX, removing any suffix already present.
-   For example, `make_suffix ("/foo/bar.baz", "quux")' returns
-   `/foo/bar.quux'.  Returns a string allocated with malloc.  */
-extern DllImport char *make_suffix (const char *s,  const char *suffix);
-
-/* Return NAME with STEM_PREFIX prepended to the stem. For example,
-   `make_prefix ("/foo/bar.baz", "x")' returns `/foo/xbar.baz'.
-   Returns a string allocated with malloc.  */
-extern DllImport char *make_prefix (char *stem_prefix, char *name);
-
-
-/* Return the current working directory.  */
-extern DllImport char *xgetcwd (void);
-
-/* Returns true if FN is a directory or a symlink to a directory.  */
-extern DllImport int dir_p (const char *fn);
-
-/* If FN is a readable directory, return the number of links it has.
-   Otherwise, return -1.  */
-extern DllImport int dir_links (const char *fn);
-
-/* Like their stdio counterparts, but abort on error, after calling
-   perror(3) with FILENAME as its argument.  */
-extern DllImport FILE *xfopen (const char *filename, const char *mode);
-extern DllImport void xfclose (FILE *, const char *filename);
-
-/* These call the corresponding function in the standard library, and
-   abort if those routines fail.  Also, `xrealloc' calls `xmalloc' if
-   OLD_ADDRESS is null.  */
-extern DllImport void *xmalloc (unsigned size);
-extern DllImport void *xrealloc (void *old_address, unsigned new_size);
-
-extern DllImport char *xbasename (const char *name);
-
-/* (Re)Allocate N items of type T using xmalloc/xrealloc.  */
-#define XTALLOC(n, t) ((t *) xmalloc ((n) * sizeof (t)))
-#define XTALLOC1(t) XTALLOC (1, t)
-#define XRETALLOC(addr, n, t) ((addr) = (t *) xrealloc (addr, (n) * sizeof(t)))
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* not KPATHSEA_LIB_H */
--- a/liboctave/kpse.cc	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/kpse.cc	Thu Apr 24 03:27:41 2003 +0000
@@ -1,7 +1,8 @@
 /* pathsearch.c: look up a filename in a path.
 
-Copyright (C) 1993, 94, 95, 96, 97 Karl Berry.
+Copyright (C) 1993, 94, 95, 96, 97, 98 Karl Berry.
 Copyright (C) 1993, 94, 95, 96, 97 Karl Berry & O. Weber.
+Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -25,12 +26,398 @@
 #include "kpse-xfns.h"
 #include "kpse.h"
 
-#include <time.h> /* for `time' */
-
-#ifdef __DJGPP__
-#include <sys/stat.h>	/* for stat bits */
+/* c-std.h: the first header files.  */
+
+/* Header files that essentially all of our sources need, and
+   that all implementations have.  We include these first, to help with
+   NULL being defined multiple times.  */
+#include <cstdio>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
+#include <climits>
+#include <cerrno>
+#include <cassert>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#ifdef WIN32
+#include <malloc.h>
+#endif /* not WIN32 */
+
+#include "sysdir.h"
+#include "statdefs.h"
+
+/* define NAME_MAX, the maximum length of a single
+   component in a filename.  No such limit may exist, or may vary
+   depending on the filesystem.  */
+
+/* Most likely the system will truncate filenames if it is not POSIX,
+   and so we can use the BSD value here.  */
+#ifndef _POSIX_NAME_MAX
+#define _POSIX_NAME_MAX 255
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX _POSIX_NAME_MAX
+#endif
+
+/* c-ctype.h: ASCII-safe versions of the <ctype.h> macros.  */
+
+#include <cctype>
+
+/* What separates elements in environment variable path lists?  */
+#ifndef ENV_SEP
+#ifdef DOSISH
+#define ENV_SEP ';'
+#define ENV_SEP_STRING ";"
+#else
+#define ENV_SEP ':'
+#define ENV_SEP_STRING ":"
+#endif /* not DOS */
+#endif /* not ENV_SEP */
+
+#ifndef IS_ENV_SEP
+#define IS_ENV_SEP(ch) ((ch) == ENV_SEP)
+#endif
+
+/* c-pathmx.h: define PATH_MAX, the maximum length of a filename.
+   Since no such limit may exist, it's preferable to dynamically grow
+   filenames as needed.  */
+
+/* Cheat and define this as a manifest constant no matter what, instead
+   of using pathconf.  I forget why we want to do this.  */
+
+#ifndef _POSIX_PATH_MAX
+#define _POSIX_PATH_MAX 255
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+#endif /* not PATH_MAX */
+
+/* debug.h: Runtime tracing.  */
+
+/* If NO_DEBUG is defined (not recommended), skip all this.  */
+#ifndef NO_DEBUG
+
+/* OK, we'll have tracing support.  */
+#define KPSE_DEBUG
+
+/* Set a bit.  */
+#define KPSE_DEBUG_SET(bit) kpathsea_debug |= 1 << (bit)
+
+/* Test if a bit is on.  */
+#define KPSE_DEBUG_P(bit) (kpathsea_debug & (1 << (bit)))
+
+#define KPSE_DEBUG_STAT 0		/* stat calls */
+#define KPSE_DEBUG_HASH 1		/* hash lookups */
+#define KPSE_DEBUG_FOPEN 2		/* fopen/fclose calls */
+#define KPSE_DEBUG_PATHS 3		/* search path initializations */
+#define KPSE_DEBUG_EXPAND 4		/* path element expansion */
+#define KPSE_DEBUG_SEARCH 5		/* searches */
+#define KPSE_DEBUG_VARS 6		/* variable values */
+#define KPSE_LAST_DEBUG KPSE_DEBUG_VARS
+
+/* A printf for the debugging.  */
+#define DEBUGF_START() do { fputs ("kdebug:", stderr)
+#define DEBUGF_END()        fflush (stderr); } while (0)
+
+#define DEBUGF(str)							\
+  DEBUGF_START (); fputs (str, stderr); DEBUGF_END ()
+#define DEBUGF1(str, e1)						\
+  DEBUGF_START (); fprintf (stderr, str, e1); DEBUGF_END ()
+#define DEBUGF2(str, e1, e2)						\
+  DEBUGF_START (); fprintf (stderr, str, e1, e2); DEBUGF_END ()
+#define DEBUGF3(str, e1, e2, e3)					\
+  DEBUGF_START (); fprintf (stderr, str, e1, e2, e3); DEBUGF_END ()
+#define DEBUGF4(str, e1, e2, e3, e4)					\
+  DEBUGF_START (); fprintf (stderr, str, e1, e2, e3, e4); DEBUGF_END ()
+
+#undef fopen
+#define fopen kpse_fopen_trace
+extern FILE *fopen (const char *filename, const char *mode);
+#undef fclose
+#define fclose kpse_fclose_trace
+extern int fclose (FILE *);
+
+#endif /* not NO_DEBUG */
+
+#if defined (WIN32) && !defined (__MINGW32__)
+
+/* System description file for Windows NT.  */
+
+/*
+ *      Define symbols to identify the version of Unix this is.
+ *      Define all the symbols that apply correctly.
+ */
+
+#ifndef DOSISH
+#define DOSISH
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN      _MAX_PATH
 #endif
 
+#define HAVE_DUP2       	1
+#define HAVE_RENAME     	1
+#define HAVE_RMDIR      	1
+#define HAVE_MKDIR      	1
+#define HAVE_GETHOSTNAME	1
+#define HAVE_RANDOM		1
+#define USE_UTIME		1
+#define HAVE_MOUSE		1
+#define HAVE_TZNAME		1
+
+/* These have to be defined because our compilers treat __STDC__ as being
+   defined (most of them anyway). */
+
+#define access  _access
+#define stat    _stat
+#define strcasecmp _stricmp
+#define strdup  _strdup
+#define strncasecmp _strnicmp
+
+#define S_IFMT   _S_IFMT
+#define S_IFDIR  _S_IFDIR
+
+/* Define this so that winsock.h definitions don't get included when
+   windows.h is...  For this to have proper effect, config.h must
+   always be included before windows.h.  */ 
+#define _WINSOCKAPI_    1
+
+#include <windows.h>
+
+/* Defines size_t and alloca ().  */
+#include <malloc.h>
+
+/* For proper declaration of environ.  */
+#include <io.h>
+#include <fcntl.h>
+#include <process.h>
+
+/* ============================================================ */
+
+#endif /* WIN32 */
+
+/* hash.h: declarations for a hash table.  */
+
+/* A single (key,value) pair.  */
+typedef struct hash_element_struct
+{
+  const char *key;
+  const char *value;
+  struct hash_element_struct *next;
+} hash_element_type;
+
+/* The usual arrangement of buckets initialized to null.  */
+typedef struct
+{
+  hash_element_type **buckets;
+  unsigned size;
+} hash_table_type;
+
+static hash_table_type hash_create (unsigned size);
+
+
+#ifdef KPSE_DEBUG
+/* How to print the hash results when debugging.  */
+extern int kpse_debug_hash_lookup_int;
+#endif
+
+/* fn.h: arbitrarily long filenames (or just strings).  */
+
+/* Arbitrarily long filenames; it's inconvenient to use obstacks here,
+   because we want to maintain a null terminator.  Also used for
+   dynamically growing strings even when the null byte isn't necessary,
+   e.g., in `variable.c', since I don't want to pass obstacks around
+   everywhere, and one can't free parts of an obstack arbitrarily.  */
+
+typedef struct
+{
+  char *str;
+  unsigned allocated;
+  unsigned length; /* includes the terminating null byte, if any */
+} fn_type;
+
+#define FN_STRING(fn) ((fn).str)
+#define FN_ALLOCATED(fn) ((fn).allocated)
+#define FN_LENGTH(fn) ((fn).length)
+
+/* lib.h: other stuff.  */
+
+/* Define common sorts of messages.  */
+
+/* This should be called only after a system call fails.  Don't exit
+   with status `errno', because that might be 256, which would mean
+   success (exit statuses are truncated to eight bits).  */
+#define FATAL_PERROR(str) do { \
+  fputs ("pathsearch: ", stderr); \
+  perror (str); exit (EXIT_FAILURE); } while (0)
+
+#define START_FATAL() do { \
+  fputs ("pathsearch: fatal: ", stderr);
+#define END_FATAL() fputs (".\n", stderr); exit (1); } while (0)
+
+#define FATAL(str)							\
+  START_FATAL (); fputs (str, stderr); END_FATAL ()
+#define FATAL1(str, e1)							\
+  START_FATAL (); fprintf (stderr, str, e1); END_FATAL ()
+#define FATAL2(str, e1, e2)						\
+  START_FATAL (); fprintf (stderr, str, e1, e2); END_FATAL ()
+#define FATAL3(str, e1, e2, e3)						\
+  START_FATAL (); fprintf (stderr, str, e1, e2, e3); END_FATAL ()
+#define FATAL4(str, e1, e2, e3, e4)					\
+  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4); END_FATAL ()
+#define FATAL5(str, e1, e2, e3, e4, e5)					\
+  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4, e5); END_FATAL ()
+#define FATAL6(str, e1, e2, e3, e4, e5, e6)				\
+  START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4, e5, e6); END_FATAL ()
+
+
+#define START_WARNING() do { fputs ("warning: ", stderr)
+#define END_WARNING() fputs (".\n", stderr); fflush (stderr); } while (0)
+
+#define WARNING(str)							\
+  START_WARNING (); fputs (str, stderr); END_WARNING ()
+#define WARNING1(str, e1)						\
+  START_WARNING (); fprintf (stderr, str, e1); END_WARNING ()
+#define WARNING2(str, e1, e2)						\
+  START_WARNING (); fprintf (stderr, str, e1, e2); END_WARNING ()
+#define WARNING3(str, e1, e2, e3)					\
+  START_WARNING (); fprintf (stderr, str, e1, e2, e3); END_WARNING ()
+#define WARNING4(str, e1, e2, e3, e4)					\
+  START_WARNING (); fprintf (stderr, str, e1, e2, e3, e4); END_WARNING ()
+
+
+/* I find this easier to read.  */
+#define STREQ(s1, s2) (strcmp (s1, s2) == 0)
+#define STRNEQ(s1, s2, n) (strncmp (s1, s2, n) == 0)
+      
+/* Support for FAT/ISO-9660 filesystems.  Theoretically this should be
+   done at runtime, per filesystem, but that's painful to program.  */
+#ifdef MONOCASE_FILENAMES
+#define FILESTRCASEEQ(s1, s2) (strcasecmp (s1, s2) == 0)
+#define FILESTRNCASEEQ(s1, s2, l) (strncasecmp (s1, s2, l) == 0)
+#define FILECHARCASEEQ(c1, c2) (toupper (c1) == toupper (c2))
+#else
+#define FILESTRCASEEQ STREQ
+#define FILESTRNCASEEQ STRNEQ
+#define FILECHARCASEEQ(c1, c2) ((c1) == (c2))
+#endif
+
+/* This is the maximum number of numerals that result when a 64-bit
+   integer is converted to a string, plus one for a trailing null byte,
+   plus one for a sign.  */
+#define MAX_INT_LENGTH 21
+
+/* If the environment variable TEST is set, return it; otherwise,
+   DEFAULT.  This is useful for paths that use more than one envvar.  */
+#define ENVVAR(test, default) (getenv (test) ? (test) : (default))
+
+
+/* (Re)Allocate N items of type T using xmalloc/xrealloc.  */
+#define XTALLOC(n, t) ((t *) xmalloc ((n) * sizeof (t)))
+#define XTALLOC1(t) XTALLOC (1, t)
+#define XRETALLOC(addr, n, t) ((addr) = (t *) xrealloc (addr, (n) * sizeof(t)))
+
+extern "C" char *xbasename (const char *name);
+
+static FILE *xfopen (const char *filename, const char *mode);
+
+static void xfclose (FILE *f, const char *filename);
+
+unsigned long xftell (FILE *f, char *filename);
+
+static void xclosedir (DIR *d);
+
+static void *xmalloc (unsigned size);
+
+static void *xrealloc (void *old_ptr, unsigned size);
+
+static char *xstrdup (const char *s);
+
+extern char *xbasename (const char *name);
+
+static int dir_p (const char *fn);
+
+#ifndef WIN32
+int dir_links (const char *fn);
+#endif
+
+static unsigned hash (hash_table_type table, const char *key);
+
+static void hash_insert (hash_table_type *table, const char *key,
+			 const char *value);
+
+static char **hash_lookup (hash_table_type table, const char *key);
+
+static void hash_print (hash_table_type table, int summary_only);
+
+static char *concat (const char *s1, const char *s2);
+
+static char *concat3 (const char *s1, const char *s2, const char *s3);
+
+static char *concatn (const char *str1, ...);
+
+static char *find_suffix (const char *name);
+
+static char *kpse_truncate_filename (const char *name);
+
+static char *kpse_readable_file (const char *name);
+
+static int kpse_absolute_p (const char *filename, int relative_ok);
+
+static str_list_type str_list_init (void);
+
+static void str_list_add (str_list_type *l, char *s);
+
+static void str_list_concat (str_list_type *target, str_list_type more);
+
+static void str_list_free (str_list_type *l);
+
+static void str_llist_add (str_llist_type *l, char *str);
+
+static void str_llist_float (str_llist_type *l, str_llist_elt_type *mover);
+
+static fn_type fn_init (void);
+
+static fn_type fn_copy0 (const char *s, unsigned len);
+
+static void fn_free (fn_type *f);
+
+static void grow (fn_type *f, unsigned len);
+
+static void fn_1grow (fn_type *f, char c);
+
+static void fn_grow (fn_type *f, void *source, unsigned len);
+
+static void fn_str_grow (fn_type *f, const char *s);
+
+static void fn_shrink_to (fn_type *f, unsigned loc);
+
+static char *kpse_var_value (const char *var);
+
+static void expanding (const char *var, int xp);
+
+static int expanding_p (const char *var);
+
+static void expand (fn_type *expansion, const char *start, const char *end);
+
+static char *kpse_var_expand (const char *src);
+
+#include <ctime> /* for `time' */
+
 /* The very first search is for texmf.cnf, called when someone tries to
    initialize the TFM path or whatever.  init_path calls kpse_cnf_get
    which calls kpse_all_path_search to find all the texmf.cnf's.  We
@@ -56,7 +443,7 @@
     char *log_name = kpse_var_value ("TEXMFLOG");
     first_time = false;
     if (log_name) {
-      log_file = fopen (log_name, FOPEN_A_MODE);
+      log_file = xfopen (log_name, "a");
       if (!log_file)
         perror (log_name);
       free (log_name);
@@ -266,29 +653,6 @@
   char *name;
   bool 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
-
   /* Make a leading ~ count as an absolute filename, and expand $FOO's.  */
   name = kpse_expand (original_name);
   
@@ -324,11 +688,6 @@
       putc ('\n', stderr);
   }  
 
-#ifdef __DJGPP__
-  /* Undo any side effects.  */
-  _djstat_flags = save_djgpp_flags;
-#endif
-
   return STR_LIST (ret_list);
 }
 
@@ -489,29 +848,6 @@
 {
   str_list_type ret_list;
 
-#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 char **p;
@@ -560,11 +896,6 @@
       putc ('\n', stderr);
   }  
 
-#ifdef __DJGPP__
-  /* Undo any side effects.  */
-  _djstat_flags = save_djgpp_flags;
-#endif
-
   return STR_LIST (ret_list);
 }
 
@@ -1526,7 +1857,7 @@
   unsigned len = strlen (db_filename) - sizeof (DB_NAME) + 1; /* Keep the /. */
   char *top_dir = (char *) xmalloc (len + 1);
   char *cur_dir = NULL; /* First thing in ls-R might be a filename.  */
-  FILE *db_file = fopen (db_filename, FOPEN_R_MODE);
+  FILE *db_file = xfopen (db_filename, "r");
   
   strncpy (top_dir, db_filename, len);
   top_dir[len] = 0;
@@ -1723,7 +2054,7 @@
 {
   char *line, *real, *alias;
   unsigned count = 0;
-  FILE *alias_file = fopen (alias_filename, FOPEN_R_MODE);
+  FILE *alias_file = xfopen (alias_filename, "r");
 
   if (alias_file) {
     while ((line = read_line (alias_file)) != NULL) {
@@ -1733,13 +2064,13 @@
       } else {
         /* Each line should have two fields: realname aliasname.  */
         real = line;
-        while (*real && ISSPACE (*real))
+        while (*real && isspace (*real))
           real++;
         alias = real;
-        while (*alias && !ISSPACE (*alias))
+        while (*alias && !isspace (*alias))
           alias++;
         *alias++ = 0;
-        while (*alias && ISSPACE (*alias)) 
+        while (*alias && isspace (*alias)) 
           alias++;
         /* Is the check for errors strong enough?  Should we warn the user
            for potential errors?  */
@@ -2428,3 +2759,986 @@
   return element (p, false);
 }
 
+/* xfopen.c: fopen and fclose with error checking.  */
+
+/* These routines just check the return status from standard library
+   routines and abort if an error happens.  */
+
+FILE *
+xfopen (const char *filename, const char *mode)
+{
+  FILE *f;
+  
+  assert (filename && mode);
+  
+  f = fopen (filename, mode);
+  if (f == NULL)
+    FATAL_PERROR (filename);
+
+  return f;
+}
+
+void
+xfclose (FILE *f, const char *filename)
+{
+  assert (f);
+  
+  if (fclose (f) == EOF)
+    FATAL_PERROR (filename);
+}
+
+/* xftell.c: ftell with error checking.  */
+
+unsigned long
+xftell (FILE *f, char *filename)
+{
+  long where = ftell (f);
+
+  if (where < 0)
+    FATAL_PERROR (filename);
+
+  return where;
+}
+
+void
+xclosedir (DIR *d)
+{
+#ifdef CLOSEDIR_VOID
+  closedir (d);
+#else
+  int ret = closedir (d);
+  
+  if (ret != 0)
+    FATAL ("closedir failed");
+#endif
+}
+
+/* xmalloc.c: malloc with error checking.  */
+
+void *
+xmalloc (unsigned size)
+{
+  void *new_mem = (void *) malloc (size);
+
+  if (new_mem == NULL)
+    {
+      fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n",
+               size);
+      /* 1 means success on VMS, so pick a random number (ASCII `K').  */
+      exit (75);
+    }
+
+  return new_mem;
+}
+
+/* xrealloc.c: realloc with error checking.  */
+
+extern void *xmalloc (unsigned);
+
+void *
+xrealloc (void *old_ptr, unsigned size)
+{
+  void *new_mem;
+
+  if (old_ptr == NULL)
+    new_mem = xmalloc (size);
+  else
+    {
+      new_mem = (void *) realloc (old_ptr, size);
+      if (new_mem == NULL)
+        {
+          /* We used to print OLD_PTR here using %x, and casting its
+             value to unsigned, but that lost on the Alpha, where
+             pointers and unsigned had different sizes.  Since the info
+             is of little or no value anyway, just don't print it.  */
+          fprintf (stderr, "fatal: memory exhausted (realloc of %u bytes).\n",
+                   size);
+          /* 1 means success on VMS, so pick a random number (ASCII `B').  */
+          exit (66);
+        }
+    }
+
+  return new_mem;
+}
+
+/* xstrdup.c: strdup with error checking.  */
+
+/* Return a copy of S in new storage.  */
+
+char *
+xstrdup (const char *s)
+{
+  char *new_string = (char *) xmalloc (strlen (s) + 1);
+  return strcpy (new_string, s);
+}
+
+/* dir.c: directory operations.  */
+
+/* Return true if FN is a directory or a symlink to a directory,
+   false if not. */
+
+int
+dir_p (const char *fn)
+{
+#ifdef WIN32
+  int fa = GetFileAttributes(fn);
+  return (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
+#else
+  struct stat stats;
+  return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
+#endif
+}
+
+#ifndef WIN32
+
+/* Return -1 if FN isn't a directory, else its number of links.
+   Duplicate the call to stat; no need to incur overhead of a function
+   call for that little bit of cleanliness. */
+
+int
+dir_links (const char *fn)
+{
+  static hash_table_type link_table;
+  char **hash_ret;
+  long ret;
+  
+  if (link_table.size == 0)
+    link_table = hash_create (457);
+
+#ifdef KPSE_DEBUG
+  /* This is annoying, but since we're storing integers as pointers, we
+     can't print them as strings.  */
+  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
+    kpse_debug_hash_lookup_int = 1;
+#endif
+
+  hash_ret = hash_lookup (link_table, fn);
+  
+#ifdef KPSE_DEBUG
+  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
+    kpse_debug_hash_lookup_int = 0;
+#endif
+
+  /* Have to cast the int we need to/from the const_string that the hash
+     table stores for values. Let's hope an int fits in a pointer.  */
+  if (hash_ret)
+    ret = (long) *hash_ret;
+  else
+    {
+      struct stat stats;
+      ret = stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode)
+            ? stats.st_nlink : (unsigned) -1;
+
+      /* It's up to us to copy the value.  */
+      hash_insert (&link_table, xstrdup (fn), (const char *) ret);
+      
+#ifdef KPSE_DEBUG
+      if (KPSE_DEBUG_P (KPSE_DEBUG_STAT))
+        DEBUGF2 ("dir_links(%s) => %ld\n", fn, ret);
+#endif
+    }
+
+  return ret;
+}
+
+#endif /* !WIN32 */
+
+/* hash.c: hash table operations.  */
+
+/* The hash function.  We go for simplicity here.  */
+
+/* All our hash tables are related to filenames.  */
+#ifdef MONOCASE_FILENAMES
+#define TRANSFORM(x) toupper (x)
+#else
+#define TRANSFORM(x) (x)
+#endif
+
+static unsigned
+hash (hash_table_type table, const char *key)
+{
+  unsigned n = 0;
+  
+  /* Our keys aren't often anagrams of each other, so no point in
+     weighting the characters.  */
+  while (*key != 0)
+    n = (n + n + TRANSFORM (*key++)) % table.size;
+  
+  return n;
+}
+
+hash_table_type
+hash_create (unsigned size) 
+{
+  /* hash_table_type ret; changed into "static ..." to work around gcc
+     optimizer bug for Alpha.  */
+  static hash_table_type ret;
+  unsigned b;
+  ret.buckets = XTALLOC (size, hash_element_type *);
+  ret.size = size;
+  
+  /* calloc's zeroes aren't necessarily NULL, so be safe.  */
+  for (b = 0; b <ret.size; b++)
+    ret.buckets[b] = NULL;
+    
+  return ret;
+}
+
+/* Whether or not KEY is already in MAP, insert it and VALUE.  Do not
+   duplicate the strings, in case they're being purposefully shared.  */
+
+void
+hash_insert (hash_table_type *table, const char *key, const char *value)
+{
+  unsigned n = hash (*table, key);
+  hash_element_type *new_elt = XTALLOC1 (hash_element_type);
+
+  new_elt->key = key;
+  new_elt->value = value;
+  new_elt->next = NULL;
+  
+  /* Insert the new element at the end of the list.  */
+  if (!table->buckets[n])
+    /* first element in bucket is a special case.  */
+    table->buckets[n] = new_elt;
+  else
+    {
+      hash_element_type *loc = table->buckets[n];
+      while (loc->next)		/* Find the last element.  */
+        loc = loc->next;
+      loc->next = new_elt;	/* Insert the new one after.  */
+    }
+}
+
+/* Look up STR in MAP.  Return a (dynamically-allocated) list of the
+   corresponding strings or NULL if no match.  */ 
+
+#ifdef KPSE_DEBUG
+/* Print the hash values as integers if this is nonzero.  */
+int kpse_debug_hash_lookup_int = 0; 
+#endif
+
+char **
+hash_lookup (hash_table_type table, const char *key)
+{
+  hash_element_type *p;
+  str_list_type ret;
+  unsigned n = hash (table, key);
+  ret = str_list_init ();
+  
+  /* Look at everything in this bucket.  */
+  for (p = table.buckets[n]; p != NULL; p = p->next)
+    if (FILESTRCASEEQ (key, p->key))
+      /* Cast because the general str_list_type shouldn't force const data.  */
+      str_list_add (&ret, (char *) p->value);
+  
+  /* If we found anything, mark end of list with null.  */
+  if (STR_LIST (ret))
+    str_list_add (&ret, NULL);
+
+#ifdef KPSE_DEBUG
+  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
+    {
+      DEBUGF1 ("hash_lookup(%s) =>", key);
+      if (!STR_LIST (ret))
+        fputs (" (nil)\n", stderr);
+      else
+        {
+          char **r;
+          for (r = STR_LIST (ret); *r; r++)
+            {
+              putc (' ', stderr);
+              if (kpse_debug_hash_lookup_int)
+                fprintf (stderr, "%ld", (long) *r);
+              else
+                fputs (*r, stderr);
+            }
+          putc ('\n', stderr);
+        }
+      fflush (stderr);
+    }
+#endif
+
+  return STR_LIST (ret);
+}
+
+/* We only print nonempty buckets, to decrease output volume.  */
+
+void
+hash_print (hash_table_type table, int summary_only)
+{
+  unsigned b;
+  unsigned total_elements = 0, total_buckets = 0;
+  
+  for (b = 0; b < table.size; b++) {
+    hash_element_type *bucket = table.buckets[b];
+
+    if (bucket) {
+      unsigned len = 1;
+      hash_element_type *tb;
+
+      total_buckets++;
+      if (!summary_only) fprintf (stderr, "%4d ", b);
+
+      for (tb = bucket->next; tb != NULL; tb = tb->next)
+        len++;
+      if (!summary_only) fprintf (stderr, ":%-5d", len);
+      total_elements += len;
+
+      if (!summary_only) {
+        for (tb = bucket; tb != NULL; tb = tb->next)
+          fprintf (stderr, " %s=>%s", tb->key, tb->value);
+        putc ('\n', stderr);
+      }
+    }
+  }
+  
+  fprintf (stderr,
+          "%u buckets, %u nonempty (%u%%); %u entries, average chain %.1f.\n",
+          table.size,
+          total_buckets,
+          100 * total_buckets / table.size,
+          total_elements,
+          total_buckets ? total_elements / (double) total_buckets : 0.0);
+}
+
+/* concat.c: dynamic string concatenation.  */
+
+/* Return the concatenation of S1 and S2.  See `concatn.c' for a
+   `concatn', which takes a variable number of arguments.  */
+
+char *
+concat (const char *s1, const char *s2)
+{
+  char *answer = (char *) xmalloc (strlen (s1) + strlen (s2) + 1);
+  strcpy (answer, s1);
+  strcat (answer, s2);
+
+  return answer;
+}
+
+/* concat3.c: concatenate three strings.  */
+
+char *
+concat3 (const char *s1, const char *s2, const char *s3)
+{
+  char *answer
+    = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
+  strcpy (answer, s1);
+  strcat (answer, s2);
+  strcat (answer, s3);
+
+  return answer;
+}
+
+/* concatn.c: Concatenate an arbitrary number of strings.  */
+
+/* OK, it would be epsilon more efficient to compute the total length
+   and then do the copying ourselves, but I doubt it matters in reality.  */
+
+char *
+concatn (const char *str1, ...)
+{
+  char *arg;
+  char *ret;
+  va_list ap;
+
+  va_start (ap, str1);
+
+  if (!str1)
+    return NULL;
+  
+  ret = xstrdup (str1);
+  
+  while ((arg = va_arg (ap, char *)) != NULL)
+    {
+      char *temp = concat (ret, arg);
+      free (ret);
+      ret = temp;
+    }
+  va_end (ap);
+  
+  return ret;
+}
+
+/* debug.c: Help the user discover what's going on.  */
+
+#ifdef KPSE_DEBUG
+
+unsigned int kpathsea_debug = 0;
+
+/* If the real definitions of fopen or fclose are macros, we lose -- the
+   #undef won't restore them. */
+
+FILE *
+fopen (const char *filename, const char *mode)
+{
+#undef fopen
+  FILE *ret = fopen (filename, mode);
+
+  if (KPSE_DEBUG_P (KPSE_DEBUG_FOPEN))
+    DEBUGF3 ("fopen(%s, %s) => 0x%lx\n", filename, mode, (unsigned long) ret);
+
+  return ret;
+}
+
+int
+fclose (FILE *f)
+{
+#undef fclose
+  int ret = fclose (f);
+  
+  if (KPSE_DEBUG_P (KPSE_DEBUG_FOPEN))
+    DEBUGF2 ("fclose(0x%lx) => %d\n", (unsigned long) f, ret);
+
+  return ret;
+}
+
+#endif
+
+/* find-suffix.c: return the stuff after a dot.  */
+
+/* Return pointer to first character after `.' in last directory element
+   of NAME.  If the name is `foo' or `/foo.bar/baz', we have no extension.  */
+
+char *
+find_suffix (const char *name)
+{
+  const char *slash_pos;
+  char *dot_pos = strrchr (name, '.');
+  
+  if (dot_pos == NULL)
+    return NULL;
+  
+  for (slash_pos = name + strlen (name);
+       slash_pos > dot_pos && !IS_DIR_SEP (*slash_pos);
+       slash_pos--)
+    ;
+  
+  return slash_pos > dot_pos ? NULL : dot_pos + 1;
+}
+
+/* rm-suffix.c: remove any suffix.  */
+
+/* Generic const warning -- see extend-fname.c.  */
+
+char *
+remove_suffix (const char *s)
+{
+  char *ret;
+  const char *suffix = find_suffix (s);
+  
+  if (suffix)
+    {
+      /* Back up to before the dot.  */
+      suffix--;
+      ret = (char *) xmalloc (suffix - s + 1);
+      strncpy (ret, s, suffix - s);
+      ret[suffix - s] = 0;
+    }
+  else
+    ret = (char *) s;
+    
+  return ret;
+}
+
+/* readable.c: check if a filename is a readable non-directory file.  */
+
+/* Truncate any too-long components in NAME, returning the result.  It's
+   too bad this is necessary.  See comments in readable.c for why.  */
+
+static char *
+kpse_truncate_filename (const char *name)
+{
+  unsigned c_len = 0;        /* Length of current component.  */
+  unsigned ret_len = 0;      /* Length of constructed result.  */
+  
+  /* Allocate enough space.  */
+  char *ret = (char *) xmalloc (strlen (name) + 1);
+
+  for (; *name; name++)
+    {
+      if (IS_DIR_SEP (*name) || IS_DEVICE_SEP (*name))
+        { /* At a directory delimiter, reset component length.  */
+          c_len = 0;
+        }
+      else if (c_len > NAME_MAX)
+        { /* If past the max for a component, ignore this character.  */
+          continue;
+        }
+
+      /* Copy this character.  */
+      ret[ret_len++] = *name;
+      c_len++;
+    }
+  ret[ret_len] = 0;
+
+  return ret;
+}
+
+/* If access can read FN, run stat (assigning to stat buffer ST) and
+   check that fn is not a directory.  Don't check for just being a
+   regular file, as it is potentially useful to read fifo's or some
+   kinds of devices.  */
+
+#ifdef WIN32
+#define READABLE(fn, st) \
+  (GetFileAttributes(fn) != 0xFFFFFFFF && \
+   !(GetFileAttributes(fn) & FILE_ATTRIBUTE_DIRECTORY))
+#else
+#define READABLE(fn, st) \
+  (access (fn, R_OK) == 0 && stat (fn, &(st)) == 0 && !S_ISDIR (st.st_mode))
+#endif
+
+/* POSIX invented the brain-damage of not necessarily truncating
+   filename components; the system's behavior is defined by the value of
+   the symbol _POSIX_NO_TRUNC, but you can't change it dynamically!
+   
+   Generic const return warning.  See extend-fname.c.  */
+
+char *
+kpse_readable_file (const char *name)
+{
+  struct stat st;
+  char *ret;
+  
+  if (READABLE (name, st)) {
+    ret = (char *) name;
+
+#ifdef ENAMETOOLONG
+  } else if (errno == ENAMETOOLONG) {
+    ret = kpse_truncate_filename (name);
+
+    /* Perhaps some other error will occur with the truncated name, so
+       let's call access again.  */
+    if (!READABLE (ret, st))
+      { /* Failed.  */
+        if (ret != name) free (ret);
+        ret = NULL;
+      }
+#endif /* ENAMETOOLONG */
+
+  } else { /* Some other error.  */
+    if (errno == EACCES) { /* Maybe warn them if permissions are bad.  */
+      perror (name);
+    }
+    ret = NULL;
+  }
+  
+  return ret;
+}
+
+/* absolute.c: Test if a filename is absolute or explicitly relative.  */
+
+/* Sorry this is such a system-dependent mess, but I can't see any way
+   to usefully generalize.  */
+
+int
+kpse_absolute_p (const char *filename, int relative_ok)
+{
+  int absolute = IS_DIR_SEP (*filename)
+#ifdef DOSISH
+                     /* Novell allows non-alphanumeric drive letters. */
+                     || (*filename && IS_DEVICE_SEP (filename[1]))
+#endif /* DOSISH */
+#ifdef WIN32
+                     /* UNC names */
+                     || (*filename == '\\' && filename[1] == '\\')
+#endif
+		      ;
+  int explicit_relative
+    = relative_ok
+      && (*filename == '.' && (IS_DIR_SEP (filename[1])
+                         || (filename[1] == '.' && IS_DIR_SEP (filename[2]))));
+
+  return absolute || explicit_relative;
+}
+
+/* str-list.c: define routines for string lists.  */
+
+/* See the lib.h file for comments.  */
+
+str_list_type
+str_list_init (void)
+{
+  str_list_type ret;
+  
+  STR_LIST_LENGTH (ret) = 0;
+  STR_LIST (ret) = NULL;
+  
+  return ret;
+}
+
+void
+str_list_add (str_list_type *l, char *s)
+{
+  STR_LIST_LENGTH (*l)++;
+  XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), char *);
+  STR_LIST_LAST_ELT (*l) = s;
+}
+
+/* May as well save some reallocations and do everything in a chunk
+   instead of calling str_list_add on each element.  */
+   
+void
+str_list_concat (str_list_type *target, str_list_type more)
+{
+  unsigned e;
+  unsigned prev_len = STR_LIST_LENGTH (*target);
+
+  STR_LIST_LENGTH (*target) += STR_LIST_LENGTH (more);
+  XRETALLOC (STR_LIST (*target), STR_LIST_LENGTH (*target), char *);
+  
+  for (e = 0; e < STR_LIST_LENGTH (more); e++)
+    STR_LIST_ELT (*target, prev_len + e) = STR_LIST_ELT (more, e);
+}
+
+/* Free the list (but not the elements within it).  */
+
+void
+str_list_free (str_list_type *l)
+{
+  if (STR_LIST (*l))
+    {
+      free (STR_LIST (*l));
+      STR_LIST (*l) = NULL;
+    }
+}
+
+/* str-llist.c: Implementation of a linked list of strings.  */
+
+/* Add the new string STR to the end of the list L.  */
+
+void
+str_llist_add (str_llist_type *l, char *str)
+{
+  str_llist_elt_type *e;
+  str_llist_elt_type *new_elt = XTALLOC1 (str_llist_elt_type);
+  
+  /* The new element will be at the end of the list.  */
+  STR_LLIST (*new_elt) = str;
+  STR_LLIST_MOVED (*new_elt) = 0;
+  STR_LLIST_NEXT (*new_elt) = NULL;
+  
+  /* Find the current end of the list.  */
+  for (e = *l; e && STR_LLIST_NEXT (*e); e = STR_LLIST_NEXT (*e))
+    ;
+  
+  if (!e)
+    *l = new_elt;
+  else
+    STR_LLIST_NEXT (*e) = new_elt;
+}
+
+/* Move an element towards the top. The idea is that when a file is
+   found in a given directory, later files will likely be in that same
+   directory, and looking for the file in all the directories in between
+   is thus a waste.  */
+
+void
+str_llist_float (str_llist_type *l, str_llist_elt_type *mover)
+{
+  str_llist_elt_type *last_moved, *unmoved;
+  
+  /* If we've already moved this element, never mind.  */
+  if (STR_LLIST_MOVED (*mover))
+    return;
+  
+  /* Find the first unmoved element (to insert before).  We're
+     guaranteed this will terminate, since MOVER itself is currently
+     unmoved, and it must be in L (by hypothesis).  */
+  for (last_moved = NULL, unmoved = *l; STR_LLIST_MOVED (*unmoved);
+       last_moved = unmoved, unmoved = STR_LLIST_NEXT (*unmoved))
+    ;
+
+  /* If we are the first unmoved element, nothing to relink.  */
+  if (unmoved != mover)
+    { /* Remember `mover's current successor, so we can relink `mover's
+         predecessor to it.  */
+      str_llist_elt_type *before_mover;
+      str_llist_elt_type *after_mover = STR_LLIST_NEXT (*mover);
+      
+      /* Find `mover's predecessor.  */
+      for (before_mover = unmoved; STR_LLIST_NEXT (*before_mover) != mover;
+           before_mover = STR_LLIST_NEXT (*before_mover))
+        ;
+      
+      /* `before_mover' now links to `after_mover'.  */
+      STR_LLIST_NEXT (*before_mover) = after_mover;
+
+      /* Insert `mover' before `unmoved' and after `last_moved' (or at
+         the head of the list).  */
+      STR_LLIST_NEXT (*mover) = unmoved;
+      if (!last_moved)
+        *l = mover;
+      else
+        STR_LLIST_NEXT (*last_moved) = mover;
+    }
+
+  /* We've moved it.  */
+  STR_LLIST_MOVED (*mover) = 1;
+}
+
+/* fn.c: arbitrarily long filenames (or just strings).  */
+
+/* /usr/local/lib/texmf/fonts/public/cm/pk/ljfour/cmr10.300pk is 58
+   chars, so ASCII `K' seems a good choice. */
+#define CHUNK_SIZE 75
+
+fn_type
+fn_init (void)
+{
+  fn_type ret;
+  
+  FN_ALLOCATED (ret) = FN_LENGTH (ret) = 0;
+  FN_STRING (ret) = NULL;
+  
+  return ret;
+}
+
+fn_type
+fn_copy0 (const char *s, unsigned len)
+{
+  fn_type ret;
+  
+  FN_ALLOCATED (ret) = CHUNK_SIZE > len ? CHUNK_SIZE : len + 1;
+  FN_STRING (ret) = (char *) xmalloc (FN_ALLOCATED (ret));
+  
+  strncpy (FN_STRING (ret), s, len);
+  FN_STRING (ret)[len] = 0;
+  FN_LENGTH (ret) = len + 1;
+  
+  return ret;
+}
+
+/* Don't think we ever try to free something that might usefully be
+   empty, so give fatal error if nothing allocated.  */
+
+void
+fn_free (fn_type *f)
+{
+  assert (FN_STRING (*f) != NULL);
+  free (FN_STRING (*f));
+  FN_STRING (*f) = NULL;
+  FN_ALLOCATED (*f) = 0;
+  FN_LENGTH (*f) = 0;
+}
+
+/* An arithmetic increase seems more reasonable than geometric.  We
+   don't increase the length member since it may be more convenient for
+   the caller to add than subtract when appending the stuff that will
+   presumably follow.  */
+
+static void
+grow (fn_type *f, unsigned len)
+{
+  while (FN_LENGTH (*f) + len > FN_ALLOCATED (*f))
+    {
+      FN_ALLOCATED (*f) += CHUNK_SIZE;
+      XRETALLOC (FN_STRING (*f), FN_ALLOCATED (*f), char);
+    }
+}
+
+void
+fn_1grow (fn_type *f, char c)
+{
+  grow (f, 1);
+  FN_STRING (*f)[FN_LENGTH (*f)] = c;
+  FN_LENGTH (*f)++;
+}
+
+void
+fn_grow (fn_type *f, void *source, unsigned len)
+{
+  grow (f, len);
+  strncpy (FN_STRING (*f) + FN_LENGTH (*f), (char *) source, len);
+  FN_LENGTH (*f) += len;
+}
+
+void
+fn_str_grow (fn_type *f, const char *s)
+{
+  unsigned more_len = strlen (s);
+  grow (f, more_len);
+  strcat (FN_STRING (*f), s);
+  FN_LENGTH (*f) += more_len;
+}
+
+void
+fn_shrink_to (fn_type *f, unsigned loc)
+{
+  assert (FN_LENGTH (*f) > loc);
+  FN_STRING (*f)[loc] = 0;
+  FN_LENGTH (*f) = loc + 1;
+}
+
+/* variable.c: variable expansion.  */
+
+/* Here's the simple one, when a program just wants a value.  */
+
+char *
+kpse_var_value (const char *var)
+{
+  char *ret = getenv (var);
+
+  if (ret)
+    ret = kpse_var_expand (ret);
+
+#ifdef KPSE_DEBUG
+  if (KPSE_DEBUG_P (KPSE_DEBUG_VARS))
+    DEBUGF2("variable: %s = %s\n", var, ret ? ret : "(nil)");
+#endif
+
+  return ret;
+}
+
+/* We have to keep track of variables being expanded, otherwise
+   constructs like TEXINPUTS = $TEXINPUTS result in an infinite loop.
+   (Or indirectly recursive variables, etc.)  Our simple solution is to
+   add to a list each time an expansion is started, and check the list
+   before expanding.  */
+
+typedef struct {
+  const char *var;
+  int expanding;
+} expansion_type;
+static expansion_type *expansions; /* The sole variable of this type.  */
+static unsigned expansion_len = 0;
+
+static void
+expanding (const char *var, int xp)
+{
+  unsigned e;
+  for (e = 0; e < expansion_len; e++) {
+    if (STREQ (expansions[e].var, var)) {
+      expansions[e].expanding = xp;
+      return;
+    }
+  }
+
+  /* New variable, add it to the list.  */
+  expansion_len++;
+  XRETALLOC (expansions, expansion_len, expansion_type);
+  expansions[expansion_len - 1].var = xstrdup (var);
+  expansions[expansion_len - 1].expanding = xp;
+}
+
+
+/* Return whether VAR is currently being expanding.  */
+
+static int
+expanding_p (const char *var)
+{
+  unsigned e;
+  for (e = 0; e < expansion_len; e++) {
+    if (STREQ (expansions[e].var, var))
+      return expansions[e].expanding;
+  }
+  
+  return 0;
+}
+
+/* Append the result of value of `var' to EXPANSION, where `var' begins
+   at START and ends at END.  If `var' is not set, do not complain.
+   This is a subroutine for the more complicated expansion function.  */
+
+static void
+expand (fn_type *expansion, const char *start, const char *end)
+{
+  char *value;
+  unsigned len = end - start + 1;
+  char *var = (char *) xmalloc (len + 1);
+  strncpy (var, start, len);
+  var[len] = 0;
+  
+  if (expanding_p (var)) {
+    WARNING1 ("kpathsea: variable `%s' references itself (eventually)", var);
+  } else {
+    /* Check for an environment variable.  */
+    value = getenv (var);
+
+    if (value) {
+      expanding (var, 1);
+      value = kpse_var_expand (value);
+      expanding (var, 0);
+      fn_grow (expansion, value, strlen (value));
+      free (value);
+    }
+
+    free (var);
+  }
+}
+
+/* Can't think of when it would be useful to change these (and the
+   diagnostic messages assume them), but ... */
+#ifndef IS_VAR_START /* starts all variable references */
+#define IS_VAR_START(c) ((c) == '$')
+#endif
+#ifndef IS_VAR_CHAR  /* variable name constituent */
+#define IS_VAR_CHAR(c) (isalnum (c) || (c) == '_')
+#endif
+#ifndef IS_VAR_BEGIN_DELIMITER /* start delimited variable name (after $) */
+#define IS_VAR_BEGIN_DELIMITER(c) ((c) == '{')
+#endif
+#ifndef IS_VAR_END_DELIMITER
+#define IS_VAR_END_DELIMITER(c) ((c) == '}')
+#endif
+
+
+/* Maybe we should support some or all of the various shell ${...}
+   constructs, especially ${var-value}.  */
+
+char *
+kpse_var_expand (const char *src)
+{
+  const char *s;
+  char *ret;
+  fn_type expansion;
+  expansion = fn_init ();
+  
+  /* Copy everything but variable constructs.  */
+  for (s = src; *s; s++) {
+    if (IS_VAR_START (*s)) {
+      s++;
+
+      /* Three cases: `$VAR', `${VAR}', `$<anything-else>'.  */
+      if (IS_VAR_CHAR (*s)) {
+        /* $V: collect name constituents, then expand.  */
+        const char *var_end = s;
+
+        do {
+          var_end++;
+        } while (IS_VAR_CHAR (*var_end));
+
+        var_end--; /* had to go one past */
+        expand (&expansion, s, var_end);
+        s = var_end;
+
+      } else if (IS_VAR_BEGIN_DELIMITER (*s)) {
+        /* ${: scan ahead for matching delimiter, then expand.  */
+        const char *var_end = ++s;
+
+        while (*var_end && !IS_VAR_END_DELIMITER (*var_end))
+          var_end++;
+
+        if (! *var_end) {
+          WARNING1 ("%s: No matching } for ${", src);
+          s = var_end - 1; /* will incr to null at top of loop */
+        } else {
+          expand (&expansion, s, var_end - 1);
+          s = var_end; /* will incr past } at top of loop*/
+        }
+
+      } else {
+        /* $<something-else>: error.  */
+        WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s);
+        /* Just ignore those chars and keep going.  */
+      }
+    } else
+     fn_1grow (&expansion, *s);
+  }
+  fn_1grow (&expansion, 0);
+          
+  ret = FN_STRING (expansion);
+  return ret;
+}
--- a/liboctave/kpse.h	Wed Apr 23 19:51:58 2003 +0000
+++ b/liboctave/kpse.h	Thu Apr 24 03:27:41 2003 +0000
@@ -19,7 +19,36 @@
 #ifndef KPATHSEA_PATHSEARCH_H
 #define KPATHSEA_PATHSEARCH_H
 
-#include "kpse-xfns.h"
+/* Lists of strings; used for, e.g., directory lists.  */
+
+typedef struct
+{
+  unsigned length;
+  char **list;
+} str_list_type;
+
+#define STR_LIST_LENGTH(l) ((l).length)
+#define STR_LIST(l) ((l).list)
+#define STR_LIST_ELT(l, n) STR_LIST (l)[n]
+#define STR_LIST_LAST_ELT(l) STR_LIST_ELT (l, STR_LIST_LENGTH (l) - 1)
+
+/* It's a little bizarre to be using the same type for the list and the
+   elements of the list, but no reason not to in this case, I think --
+   we never need a NULL string in the middle of the list, and an extra
+   NULL/NULL element always at the end is inconsequential.  */
+
+struct str_llist_elt
+{
+  char *str;
+  int moved;
+  struct str_llist_elt *next;
+};
+typedef struct str_llist_elt str_llist_elt_type;
+typedef struct str_llist_elt *str_llist_type;
+
+#define STR_LLIST(sl) ((sl).str)
+#define STR_LLIST_MOVED(sl) ((sl).moved)
+#define STR_LLIST_NEXT(sl) ((sl).next)
 
 /* If PATH is non-null, return its first element (as defined by
    IS_ENV_SEP).  If it's NULL, return the next element in the previous
@@ -126,5 +155,7 @@
    Called by mktexpk et al.  */
 extern void kpse_db_insert (const char *fname);
 
+extern unsigned int kpathsea_debug;
+
 #endif /* not KPATHSEA_PATHSEARCH_H */