Back to index

tetex-bin  3.0
Classes | Functions | Variables
elt-dirs.c File Reference
#include <kpathsea/config.h>
#include <kpathsea/c-pathch.h>
#include <kpathsea/expand.h>
#include <kpathsea/fn.h>
#include <kpathsea/pathsearch.h>
#include <kpathsea/xopendir.h>

Go to the source code of this file.

Classes

struct  cache_entry

Functions

static void dir_list_add P2C (str_llist_type *, l, const_string, dir)
static void cache P2C (const_string, key, str_llist_type *, value)
static str_llist_type *cached P1C (const_string, key)
static void expand_elt P3H (str_llist_type *, const_string, unsigned)
static void do_subdir P4C (str_llist_type *, str_list_ptr, const_string, elt, unsigned, elt_length, const_string, post)
static void expand_elt P3C (str_llist_type *, str_list_ptr, const_string, elt, unsigned, start)
unsigned kpse_normalize_path P1C (string, elt)

Variables

static cache_entrythe_cache = NULL
static unsigned cache_length = 0

Class Documentation

struct cache_entry

Definition at line 63 of file elt-dirs.c.

Collaboration diagram for cache_entry:
Class Members
const_string key
str_llist_type * value

Function Documentation

static str_llist_type* cached P1C ( const_string  ,
key   
) [static]

Definition at line 92 of file elt-dirs.c.

{
  unsigned p;
  
  for (p = 0; p < cache_length; p++)
    {
      if (FILESTRCASEEQ (the_cache[p].key, key))
        return the_cache[p].value;
    }
  
  return NULL;
}
str_llist_type *kpse_element_dirs P1C ( string  ,
elt   
)

Definition at line 364 of file elt-dirs.c.

{
  unsigned ret;
  unsigned i;

  if (NAME_BEGINS_WITH_DEVICE(elt)) {
      if (*elt >= 'A' && *elt <= 'Z')
          *elt += 'a' - 'A';
      for (i = 2; IS_DIR_SEP(elt[i]); ++i)
          ;
      if (i > 3)
          memmove(elt+3, elt+i, strlen(elt+i) + 1);
      ret = 2;
  } else if (IS_UNC_NAME(elt)) {
      for (ret = 2; elt[ret] && !IS_DIR_SEP(elt[ret]); ++ret)
          ;
      for (i = ret; elt[i] && IS_DIR_SEP(elt[i]); ++i)
          ;
      if (i > ret+1)
          memmove(elt+ret+1, elt+i, strlen(elt+i) + 1);
  } else {
      for (ret = 0; IS_DIR_SEP(elt[ret]); ++ret)
          ;
  }
  
  if (KPSE_DEBUG_P (KPSE_DEBUG_STAT))
       DEBUGF2 ("kpse_normalize_path (%s) => %u\n", elt, ret);

  return ret;
}

Here is the call graph for this function:

static void checked_dir_list_add P2C ( str_llist_type ,
,
const_string  ,
dir   
) [static]

Definition at line 36 of file elt-dirs.c.

{
  char last_char = dir[strlen (dir) - 1];
  string saved_dir
    = IS_DIR_SEP (last_char) || IS_DEVICE_SEP (last_char)
      ? xstrdup (dir)
      : concat (dir, DIR_SEP_STRING);
  
  str_llist_add (l, saved_dir);
}

Here is the call graph for this function:

static void cache P2C ( const_string  ,
key  ,
str_llist_type ,
value   
) [static]

Definition at line 80 of file elt-dirs.c.

Here is the call graph for this function:

static void expand_elt P3C ( str_llist_type ,
str_list_ptr  ,
const_string  ,
elt  ,
unsigned  ,
start   
) [static]

Definition at line 319 of file elt-dirs.c.

{
  const_string dir = elt + start, post;
  
  while (*dir != 0)
    {
      if (IS_DIR_SEP (*dir))
        {
          /* If two or more consecutive /'s, find subdirectories.  */
          if (IS_DIR_SEP (dir[1]))
            {
             for (post = dir + 1; IS_DIR_SEP (*post); post++) ;
              do_subdir (str_list_ptr, elt, dir - elt + 1, post);
             return;
            }

          /* No special stuff at this slash.  Keep going.  */
        }
      
      dir++;
    }
  
  /* When we reach the end of ELT, it will be a normal filename.  */
  checked_dir_list_add (str_list_ptr, elt);
}
static void expand_elt P3H ( str_llist_type ,
const_string  ,
unsigned   
) [static]
static void do_subdir P4C ( str_llist_type ,
str_list_ptr  ,
const_string  ,
elt  ,
unsigned  ,
elt_length  ,
const_string  ,
post   
) [static]

Definition at line 122 of file elt-dirs.c.

{
#ifdef WIN32
  WIN32_FIND_DATA find_file_data;
  HANDLE hnd;
  int proceed;
  int nlinks = 2;
#else
  DIR *dir;
  struct dirent *e;
#endif /* not WIN32 */
  fn_type name;
  
  /* Some old compilers don't allow aggregate initialization.  */
  name = fn_copy0 (elt, elt_length);
  
  assert (IS_DIR_SEP (elt[elt_length - 1])
          || IS_DEVICE_SEP (elt[elt_length - 1]));
  
#if defined (WIN32)
  strcpy(dirname, FN_STRING(name));
  strcat(dirname, "/*.*");         /* "*.*" or "*" -- seems equivalent. */
  hnd = FindFirstFile(dirname, &find_file_data);

  if (hnd == INVALID_HANDLE_VALUE) {
    fn_free(&name);
    return;
  }

  /* Include top level before subdirectories, if nothing to match.  */
  if (*post == 0)
    dir_list_add (str_list_ptr, FN_STRING (name));
  else {
    /* If we do have something to match, see if it exists.  For
       example, POST might be `pk/ljfour', and they might have a
       directory `$TEXMF/fonts/pk/ljfour' that we should find.  */
    fn_str_grow (&name, post);
    expand_elt (str_list_ptr, FN_STRING (name), elt_length);
    fn_shrink_to (&name, elt_length);
  }
  proceed = 1;
  while (proceed) {
    if (find_file_data.cFileName[0] != '.') {
      int links;

      /* Construct the potential subdirectory name.  */
      fn_str_grow (&name, find_file_data.cFileName);

      /* Maybe we have cached the leafness of this directory.
               The function will return 0 if unknown, 
               else the actual (Unix-like) value. */
      links = dir_links (FN_STRING (name), 0);

      if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
       unsigned potential_len = FN_LENGTH (name);
       /* in any case, compute the leafness */
       nlinks++;

       /* It's a directory, so append the separator.  */
       fn_str_grow (&name, DIR_SEP_STRING);
        if (*post != 0) { 
          fn_str_grow (&name, post);
          /* Unfortunately we can't check if the new element is
             a leaf directory, because we don't have a directory
             name here, we just have a path spec. This means we
             may descend into a leaf directory cm/pk, if the
             spec is ...fonts//pk//.  */
          expand_elt (str_list_ptr, FN_STRING (name), potential_len);
          fn_shrink_to (&name, potential_len);
        }
       /* Should we recurse?  To see if the subdirectory is a
          leaf, check if it has two links (one for . and one for
          ..).  This means that symbolic links to directories do
          not affect the leaf-ness.  This is arguably wrong, but
          the only alternative I know of is to stat every entry
          in the directory, and that is unacceptably slow. */
          
       if (links == 0 || links > 2)
         /* All criteria are met; find subdirectories.  */
         do_subdir (str_list_ptr, FN_STRING (name),
                   potential_len, post);
       else if (*post == 0)
         /* Nothing to match, no recursive subdirectories to
            look for: we're done with this branch.  Add it.  */
         dir_list_add (str_list_ptr, FN_STRING (name));
      }
      fn_shrink_to (&name, elt_length);
    }
    proceed = FindNextFile (hnd, &find_file_data);
  }
  /* Update the leafness of name. */
  dir_links(FN_STRING(name), nlinks);
  fn_free (&name);
  FindClose(hnd);

#else /* not WIN32 */

  /* If we can't open it, quit.  */
  dir = opendir (FN_STRING (name));
  if (dir == NULL)
    {
      fn_free (&name);
      return;
    }
  
  /* Include top level before subdirectories, if nothing to match.  */
  if (*post == 0)
    dir_list_add (str_list_ptr, FN_STRING (name));
  else
    { /* If we do have something to match, see if it exists.  For
         example, POST might be `pk/ljfour', and they might have a
         directory `$TEXMF/fonts/pk/ljfour' that we should find.  */
      fn_str_grow (&name, post);
      expand_elt (str_list_ptr, FN_STRING (name), elt_length);
      fn_shrink_to (&name, elt_length);
    }

  while ((e = readdir (dir)) != NULL)
    { /* If it begins with a `.', never mind.  (This allows ``hidden''
         directories that the algorithm won't find.)  */
      if (e->d_name[0] != '.')
        {
          int links;
          
          /* Construct the potential subdirectory name.  */
          fn_str_grow (&name, e->d_name);
          
          /* If we can't stat it, or if it isn't a directory, continue.  */
          links = dir_links (FN_STRING (name), 0);

          if (links >= 0)
            { 
              unsigned potential_len = FN_LENGTH (name);

              /* It's a directory, so append the separator.  */
              fn_str_grow (&name, DIR_SEP_STRING);

              if (*post != 0)
                { 
                  fn_str_grow (&name, post);
                  /* Unfortunately we can't check if the new element is
                     a leaf directory, because we don't have a directory
                     name here, we just have a path spec. This means we
                     may descend into a leaf directory cm/pk, if the
                     spec is ...fonts//pk//.  */
                  expand_elt (str_list_ptr, FN_STRING (name), potential_len);
                  fn_shrink_to (&name, potential_len);
                }
              
              /* Should we recurse?  To see if the subdirectory is a
                 leaf, check if it has two links (one for . and one for
                 ..).  This means that symbolic links to directories do
                 not affect the leaf-ness.  This is arguably wrong, but
                 the only alternative I know of is to stat every entry
                 in the directory, and that is unacceptably slow.
                 
                 The #ifdef here makes all this configurable at
                 compile-time, so that if we're using VMS directories or
                 some such, we can still find subdirectories, even if it
                 is much slower.  */
#ifdef ST_NLINK_TRICK
#ifdef AMIGA
              /* With SAS/C++ 6.55 on the Amiga, `stat' sets the `st_nlink'
                 field to -1 for a file, or to 1 for a directory.  */
              if (links == 1)
#else
              if (links > 2)
#endif /* not AMIGA */
#endif /* not ST_NLINK_TRICK */
                /* All criteria are met; find subdirectories.  */
                do_subdir (str_list_ptr, FN_STRING (name),
                           potential_len, post);
#ifdef ST_NLINK_TRICK
              else if (*post == 0)
                /* Nothing to match, no recursive subdirectories to
                   look for: we're done with this branch.  Add it.  */
                dir_list_add (str_list_ptr, FN_STRING (name));
#endif
            }

          /* Remove the directory entry we just checked from `name'.  */
          fn_shrink_to (&name, elt_length);
        }
    }
  
  fn_free (&name);
  xclosedir (dir);
#endif /* not WIN32 */
}

Here is the call graph for this function:


Variable Documentation

unsigned cache_length = 0 [static]

Definition at line 70 of file elt-dirs.c.

cache_entry* the_cache = NULL [static]

Definition at line 69 of file elt-dirs.c.