Back to index

tetex-bin  3.0
Defines | Functions | Variables
pathsearch.c File Reference
#include <kpathsea/config.h>
#include <kpathsea/c-pathch.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/absolute.h>
#include <kpathsea/expand.h>
#include <kpathsea/db.h>
#include <kpathsea/pathsearch.h>
#include <kpathsea/readable.h>
#include <kpathsea/str-list.h>
#include <kpathsea/str-llist.h>
#include <kpathsea/variable.h>
#include <time.h>

Go to the source code of this file.

Defines

#define INIT_ALLOC   75 /* Doesn't much matter what this number is. */

Functions

static void log_search P1C (str_list_type, filenames)
static str_list_type
dir_list_search 
P3C (str_llist_type *, dirs, const_string, name, boolean, search_all)
static str_list_type
dir_list_search_list 
P3C (str_llist_type *, dirs, const_string *, names, boolean, search_all)
static str_list_type
absolute_search 
P1C (string, name)
static str_list_type path_search P4C (const_string, path, string, name, boolean, must_exist, boolean, all)
static string *search P4C (const_string, path, const_string, original_name, boolean, must_exist, boolean, all)
static string *search_list P4C (const_string, path, const_string *, names, boolean, must_exist, boolean, all)
string kpse_path_search P3C (const_string, path, const_string, name, boolean, must_exist)
string kpse_path_search_list P3C (const_string, path, const_string *, names, boolean, must_exist)
string *kpse_all_path_search P2C (const_string, path, const_string, name)
string *kpse_all_path_search_list P2C (const_string, path, const_string *, names)

Variables

static boolean first_search = true

Define Documentation

#define INIT_ALLOC   75 /* Doesn't much matter what this number is. */

Definition at line 104 of file pathsearch.c.


Function Documentation

static void log_search P1C ( str_list_type  ,
filenames   
) [static]

Definition at line 53 of file pathsearch.c.

{
  static FILE *log_file = NULL;
  static boolean first_time = true; /* Need to open the log file?  */
  
  if (first_time) {
    /* Get name from either envvar or config file.  */
    string log_name = kpse_var_value ("TEXMFLOG");
    first_time = false;
    if (log_name) {
      log_file = fopen (log_name, FOPEN_A_MODE);
      if (!log_file)
        perror (log_name);
      free (log_name);
    }
  }

  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH) || log_file) {
    unsigned e;

    /* FILENAMES should never be null, but safety doesn't hurt.  */
    for (e = 0; e < STR_LIST_LENGTH (filenames) && STR_LIST_ELT (filenames, e);
         e++) {
      string filename = STR_LIST_ELT (filenames, e);

      /* Only record absolute filenames, for privacy.  */
      if (log_file && kpse_absolute_p (filename, false))
        fprintf (log_file, "%lu %s\n", (long unsigned) time (NULL),
                 filename);

      /* And show them online, if debugging.  We've already started
         the debugging line in `search', where this is called, so
         just print the filename here, don't use DEBUGF.  */
      if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
        putc (' ', stderr);
        fputs (filename, stderr);
      }
    }
  }
}

Here is the call graph for this function:

static str_list_type absolute_search P1C ( string  ,
name   
) [static]

Definition at line 222 of file pathsearch.c.

{
  str_list_type ret_list;
  string found = kpse_readable_file (name);
  
  /* Some old compilers can't initialize structs.  */
  ret_list = str_list_init ();

  /* If NAME wasn't found, free the expansion.  */
  if (name != found)
    free (name);

  /* Add `found' to the return list even if it's null; that tells
     the caller we didn't find anything.  */
  str_list_add (&ret_list, found);
  
  return ret_list;
}

Here is the call graph for this function:

string* kpse_all_path_search P2C ( const_string  ,
path  ,
const_string  ,
name   
)

Definition at line 568 of file pathsearch.c.

{
  string *ret = search (path, name, true, true);
  return ret;
}
string* kpse_all_path_search_list P2C ( const_string  ,
path  ,
const_string ,
names   
)

Definition at line 575 of file pathsearch.c.

{
    string *ret = search_list (path, names, true, true);
    return ret;
}
static str_list_type dir_list_search P3C ( str_llist_type ,
dirs  ,
const_string  ,
name  ,
boolean  ,
search_all   
) [static]

Definition at line 107 of file pathsearch.c.

{
  str_llist_elt_type *elt;
  str_list_type ret;
  unsigned name_len = strlen (name);
  unsigned allocated = INIT_ALLOC;
  string potential = (string)xmalloc (allocated);

  ret = str_list_init ();
  
  for (elt = *dirs; elt; elt = STR_LLIST_NEXT (*elt))
    {
      const_string dir = STR_LLIST (*elt);
      unsigned dir_len = strlen (dir);
      
      while (dir_len + name_len + 1 > allocated)
        {
          allocated += allocated;
          XRETALLOC (potential, allocated, char);
        }
      
      strcpy (potential, dir);
      strcat (potential, name);
      
      if (kpse_readable_file (potential))
        { 
          str_list_add (&ret, potential);
          
          /* Move this element towards the top of the list.  */
          str_llist_float (dirs, elt);
          
          /* If caller only wanted one file returned, no need to
             terminate the list with NULL; the caller knows to only look
             at the first element.  */
          if (!search_all)
            return ret;

          /* Start new filename.  */
          allocated = INIT_ALLOC;
          potential = (string)xmalloc (allocated);
        }
    }
  
  /* If we get here, either we didn't find any files, or we were finding
     all the files.  But we're done with the last filename, anyway.  */
  free (potential);
  
  return ret;
}

Here is the call graph for this function:

static str_list_type dir_list_search_list P3C ( str_llist_type ,
dirs  ,
const_string ,
names  ,
boolean  ,
search_all   
) [static]

Definition at line 159 of file pathsearch.c.

{
  str_llist_elt_type *elt;
  str_list_type ret;
  unsigned allocated = INIT_ALLOC;
  string potential = XTALLOC(allocated, char);

  ret = str_list_init ();

  for (elt = *dirs; elt; elt = STR_LLIST_NEXT(*elt)) {
      const_string dir = STR_LLIST (*elt);
      unsigned dir_len = strlen (dir);
      int i;
      
      for (i = 0; names[i]; i++) {
          const_string name = names[i];
          unsigned name_len;

          /* Don't bother with absolute & explicit relative. */
          if (kpse_absolute_p(name, true))
              continue;
          
          name_len = strlen(name);

          while (dir_len + name_len + 1 > allocated) {
              allocated += allocated;
              XRETALLOC (potential, allocated, char);
          }

          strcpy (potential, dir);
          strcat (potential+dir_len, name);

          if (kpse_readable_file (potential)) {
              str_list_add (&ret, potential);

              /* Move this element towards the top of the list.  */
              str_llist_float (dirs, elt);

              /* If caller only wanted one file returned, no need to
                 terminate the list with NULL; the caller knows to only look
                 at the first element.  */
              if (!search_all)
                  return ret;

              /* Start new filename. */
              allocated = INIT_ALLOC;
              potential = XTALLOC(allocated, char);
          }
      }
  }

  /* If we get here, either we didn't find any files, or we were finding
     all the files.  But we're done with the last filename, anyway.  */
  free (potential);
  
  return ret;
}

Here is the call graph for this function:

string kpse_path_search P3C ( const_string  ,
path  ,
const_string  ,
name  ,
boolean  ,
must_exist   
)

Definition at line 543 of file pathsearch.c.

{
  string *ret_list = search (path, name, must_exist, false);
  string ret = *ret_list;
  free (ret_list);
  return ret;
}

Here is the call graph for this function:

string kpse_path_search_list P3C ( const_string  ,
path  ,
const_string ,
names  ,
boolean  ,
must_exist   
)

Definition at line 555 of file pathsearch.c.

{
  string *ret_list = search_list (path, names, must_exist, false);
  string ret = *ret_list;
  free (ret_list);
  return ret;
}    

Here is the call graph for this function:

static str_list_type path_search P4C ( const_string  ,
path  ,
string  ,
name  ,
boolean  ,
must_exist  ,
boolean  ,
all   
) [static]

Definition at line 245 of file pathsearch.c.

{
  string elt;
  str_list_type ret_list;
  boolean done = false;
  ret_list = str_list_init (); /* some compilers lack struct initialization */

  for (elt = kpse_path_element (path); !done && elt;
       elt = kpse_path_element (NULL)) {
    str_list_type *found;
    boolean allow_disk_search = true;

    if (*elt == '!' && *(elt + 1) == '!') {
      /* Those magic leading chars in a path element means don't search the
         disk for this elt.  And move past the magic to get to the name.  */
      allow_disk_search = false;
      elt += 2;
    }

    /* See elt-dirs.c for side effects of this function */
    kpse_normalize_path(elt);
    
    /* Try ls-R, unless we're searching for texmf.cnf.  Our caller
       (search), also tests first_search, and does the resetting.  */
    found = first_search ? NULL : kpse_db_search (name, elt, all);

    /* Search the filesystem if (1) the path spec allows it, and either
         (2a) we are searching for texmf.cnf ; or
         (2b) no db exists; or 
         (2c) no db's are relevant to this elt; or
         (3) MUST_EXIST && NAME was not in the db.
       In (2*), `found' will be NULL.
       In (3),  `found' will be an empty list. */
    if (allow_disk_search && (!found || (must_exist && !STR_LIST (*found)))) {
      str_llist_type *dirs = kpse_element_dirs (elt);
      if (dirs && *dirs) {
        if (!found)
          found = XTALLOC1 (str_list_type);
        *found = dir_list_search (dirs, name, all);
      }
    }
    
    /* Did we find anything anywhere?  */
    if (found && STR_LIST (*found))
      if (all)
        str_list_concat (&ret_list, *found);
      else {
        str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
        done = true;
      }

    /* Free the list space, if any (but not the elements).  */
    if (found) {
      str_list_free (found);
      free (found);
    }
  }

  /* Free the expanded name we were passed.  It can't be in the return
     list, since the path directories got unconditionally prepended.  */
  free (name);
  
  return ret_list;
}      

Here is the call graph for this function:

static string* search P4C ( const_string  ,
path  ,
const_string  ,
original_name  ,
boolean  ,
must_exist  ,
boolean  ,
all   
) [static]

Definition at line 320 of file pathsearch.c.

{
  str_list_type ret_list;
  string name;
  boolean absolute_p;

#ifdef __DJGPP__
  /* We will use `stat' heavily, so let's request for
     the fastest possible version of `stat', by telling
     it what members of struct stat do we really need.

     We need to set this on each call because this is a
     library function; the caller might need other options
     from `stat'.  Thus save the flags and restore them
     before exit.

     This call tells `stat' that we do NOT need to recognize
     executable files (neither by an extension nor by a magic
     signature); that we do NOT need time stamp of root directories;
     and that we do NOT need the write access bit in st_mode.

     Note that `kpse_set_progname' needs the EXEC bits,
     but it was already called by the time we get here.  */
  unsigned short save_djgpp_flags  = _djstat_flags;

  _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
                | _STAT_ROOT_TIME | _STAT_WRITEBIT;
#endif

  /* Make a leading ~ count as an absolute filename, and expand $FOO's.  */
  name = kpse_expand (original_name);
  
  /* If the first name is absolute or explicitly relative, no need to
     consider PATH at all.  */
  absolute_p = kpse_absolute_p (name, true);
  
  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
    DEBUGF4 ("start search(file=%s, must_exist=%d, find_all=%d, path=%s).\n",
             name, must_exist, all, path);

  /* Find the file(s). */
  ret_list = absolute_p ? absolute_search (name)
                        : path_search (path, name, must_exist, all);
  
  /* Append NULL terminator if we didn't find anything at all, or we're
     supposed to find ALL and the list doesn't end in NULL now.  */
  if (STR_LIST_LENGTH (ret_list) == 0
      || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
    str_list_add (&ret_list, NULL);

  /* The very first search is for texmf.cnf.  We can't log that, since
     we want to allow setting TEXMFLOG in texmf.cnf.  */
  if (first_search) {
    first_search = false;
  } else {
    /* Record the filenames we found, if desired.  And wrap them in a
       debugging line if we're doing that.  */
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      DEBUGF1 ("search(%s) =>", original_name);
    log_search (ret_list);
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      putc ('\n', stderr);
  }  

#ifdef __DJGPP__
  /* Undo any side effects.  */
  _djstat_flags = save_djgpp_flags;
#endif

  return STR_LIST (ret_list);
}
static string* search_list P4C ( const_string  ,
path  ,
const_string ,
names  ,
boolean  ,
must_exist  ,
boolean  ,
all   
) [static]

Definition at line 399 of file pathsearch.c.

{
  str_list_type ret_list;
  const_string* namep;
  string elt;
  boolean done = false;
  boolean all_absolute = true;

#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

  ret_list = str_list_init();

  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
    DEBUGF1  ("start search(files=[%s", *names);
    for (namep = names+1; *namep != NULL; namep++) {
      fputc(' ', stderr);
      fputs(*namep, stderr);
    }
    fprintf (stderr, "], must_exist=%d, find_all=%d, path=%s).\n",
             must_exist, all, path);
  }
  
  /* No need to do any expansion on names.  */

  /* First catch any absolute or explicit relative names. */
  for (namep = names; *namep; namep++) {
      if (kpse_absolute_p(*namep, true)) {
          if (kpse_readable_file(*namep)) {
          str_list_add(&ret_list, xstrdup(*namep));
          /* I know, I know... */
          if (!all)
              goto out;
          }
      } else {
          all_absolute = false;
      }
  }
  /* Shortcut: if we were only given absolute/explicit relative names,
     we can skip the rest.  Typically, if one name is absolute, they
     all are, because our caller derived them from each other. */
  if (all_absolute)
      goto out;

  /* Look at each path element in turn. */
  for (elt = kpse_path_element (path); !done && elt;
       elt = kpse_path_element (NULL))
  {
    str_list_type *found;
    boolean allow_disk_search = true;
    if (elt[0] == '!' && elt[1] == '!') {
      /* !! magic -> disallow disk searches. */
      allow_disk_search = false;
      elt += 2;
    }

    /* See elt-dirs.c for side effects of this function. */
    kpse_normalize_path(elt);

    /* Try ls-R, unless we're searching for texmf.cnf. */
    found = first_search ? NULL : kpse_db_search_list(names, elt, all);

    /* Search the filesystem if (1) the path spec allows it, and either
         (2a) we are searching for texmf.cnf ; or
         (2b) no db exists; or 
         (2c) no db's are relevant to this elt; or
         (3) MUST_EXIST && NAME was not in the db.
       In (2*), `found' will be NULL.
       In (3),  `found' will be an empty list. */
    if (allow_disk_search && (!found || (must_exist && !STR_LIST(*found)))) {
      str_llist_type *dirs = kpse_element_dirs (elt);
      if (dirs && *dirs) {
        if (!found)
          found = XTALLOC1 (str_list_type);
        *found = dir_list_search_list (dirs, names, all);
      }
    }

    /* Did we find anything? */
    if (found && STR_LIST (*found)) {
      if (all) {
        str_list_concat (&ret_list, *found);
      } else {
        str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
        done = true;
      }
    }
  }

 out:
  if (STR_LIST_LENGTH (ret_list) == 0
      || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
    str_list_add (&ret_list, NULL);

  if (first_search) {
    first_search = false;
  } else {
    /* Record the filenames we found, if desired.  And wrap them in a
       debugging line if we're doing that.  */
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
      DEBUGF1 ("search([%s", *names);
      for (namep = names+1; *namep != NULL; namep++) {
        fputc(' ', stderr);
        fputs(*namep, stderr);
      }
      fputs ("]) =>", stderr);
    }
    log_search (ret_list);
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      putc ('\n', stderr);
  }

#ifdef __DJGPP__
  /* Undo any side effects.  */
  _djstat_flags = save_djgpp_flags;
#endif
  
  return STR_LIST (ret_list);
}

Here is the call graph for this function:


Variable Documentation

Definition at line 44 of file pathsearch.c.