Пример #1
0
void
str_list_concat_elements P2C(str_list_type *, target,  str_list_type, more)
{
    if (STR_LIST_LENGTH(more) == 0) {
        return;
    } else if (STR_LIST_LENGTH(*target) == 0) {
        unsigned int i;
        STR_LIST_LENGTH(*target) = STR_LIST_LENGTH(more);
        STR_LIST(*target) = xmalloc(STR_LIST_LENGTH(more)*sizeof(char*));
        for (i=0;i!=STR_LIST_LENGTH(more);++i) {
            STR_LIST_ELT(*target,i)=xstrdup(STR_LIST_ELT(more,i));
        }
        return;
    } else {
        unsigned new_len;
        char ** new_list;
        unsigned int i,j;
        new_list = xmalloc(STR_LIST_LENGTH (*target)
                           * STR_LIST_LENGTH (more) * sizeof(char*));

        new_len = 0;
        for (j = 0; j != STR_LIST_LENGTH(more); ++j) {
            for (i = 0; i != STR_LIST_LENGTH(*target); ++i) {
                new_list[new_len] = concat(STR_LIST_ELT(*target,i),
                                           STR_LIST_ELT(more,j));
                ++new_len;
            }
        }
        for (i = 0; i != STR_LIST_LENGTH(*target); ++i)
            free(STR_LIST_ELT(*target, i));
        free(STR_LIST(*target));
        STR_LIST_LENGTH(*target) = new_len;
        STR_LIST(*target) = new_list;
    }
}
Пример #2
0
void
str_list_free P1C(str_list_type *, l)
{
  if (STR_LIST (*l))
    {
      free (STR_LIST (*l));
      STR_LIST (*l) = NULL;
    }
}
Пример #3
0
void
str_list_add P2C(str_list_type *, l,  string, s)
{
  STR_LIST_LENGTH (*l)++;
  XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), string);
  STR_LIST_LAST_ELT (*l) = s;
}
Пример #4
0
const_string *
hash_lookup (hash_table_type table,  const_string key)
{
    hash_element_type *p;
    cstr_list_type ret;
    unsigned n = hash (table, key);
    ret = cstr_list_init ();

    /* Look at everything in this bucket.  */
    for (p = table.buckets[n]; p != NULL; p = p->next)
        if (FILESTRCASEEQ (key, p->key))
            cstr_list_add (&ret, p->value);

    /* If we found anything, mark end of list with null.  */
    if (STR_LIST (ret))
        cstr_list_add (&ret, NULL);

#ifdef KPSE_DEBUG
#if defined (KPSE_COMPAT_API)
    {
        kpathsea kpse = kpse_def;
        if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH))
        {
            DEBUGF1 ("hash_lookup(%s) =>", key);
            if (!STR_LIST (ret))
                fputs (" (nil)\n", stderr);
            else
            {
                const_string *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
#endif

    return STR_LIST (ret);
}
Пример #5
0
str_list_type
str_list_init P1H(void)
{
  str_list_type ret;
  
  STR_LIST_LENGTH (ret) = 0;
  STR_LIST (ret) = NULL;
  
  return ret;
}
Пример #6
0
hash_lookup P2C(hash_table_type, table,  const_string, 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, (string) 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
        {
          string *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);
}
Пример #7
0
void
str_list_concat P2C(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), string);
  
  for (e = 0; e < STR_LIST_LENGTH (more); e++)
    STR_LIST_ELT (*target, prev_len + e) = STR_LIST_ELT (more, e);
}
Пример #8
0
search_list P4C(const_string, path,  const_string*, names,
                boolean, must_exist,  boolean, all)
{
  str_list_type ret_list;
  const_string* namep;
  string elt;
  boolean done = false;

#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.  */

  for (namep = names; *namep; namep++) {
      if (kpse_absolute_p(*namep, true) && kpse_readable_file(*namep)) {
          str_list_add(&ret_list, xstrdup(*namep));
          /* I know, I know... */
          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);
}
Пример #9
0
search P4C(const_string, path,  const_string, original_name,
           boolean, must_exist,  boolean, all)
{
  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);
}
Пример #10
0
static str_list_type
path_search P4C(const_string, path,  string, name,
                boolean, must_exist,  boolean, all)
{
  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;
}      
Пример #11
0
void
kpathsea_init_db (kpathsea kpse)
{
  const_string db_path;
  string *db_files;
  string *orig_db_files;
  str_list_type unique_list;
  int dbi;
  boolean ok = false;

  assert (sizeof(DB_NAME) == sizeof(DB_NAME_LC));

  db_path = kpathsea_init_format (kpse, kpse_db_format);
  db_files = kpathsea_path_search_list_generic (kpse, db_path, db_names,
                                                true, true);
  orig_db_files = db_files;
  
  /* Mac OS X and others can use a case-insensitive, case-preserving
     filesystem by default, in which case ls-R and ls-r point to the
     same file.  Also, Windows is case-insensitive.  In these cases,
     we want to avoid reading the same file multiple times. */
  dbi = 0;
  unique_list = str_list_init ();
  
  while (db_files[dbi] != NULL) {
    string path1 = db_files[dbi];
    string path2 = db_files[dbi + 1];

    /* first-pass check in case path1/path2 aren't even
       potentially equal; mainly in case the order from
       kpathsea_path_search_list_generic changes. */
    if (path2
        && strcasecmp (path1, path2) == 0
        && same_file_p (path1, path2)) {
      /* they are the same, skip over path1, we'll add path2
         on the next iteration (when it's path1). */
#ifdef KPSE_DEBUG
      if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
        DEBUGF2 ("db:init(): skipping db same_file_p %s, will add %s.\n",
                 path1, path2);
      }
#endif
      free (path1);

    } else {
     /* they are not the same, add path1.  */
#ifdef KPSE_DEBUG
      if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
        DEBUGF1 ("db:init(): using db file %s.\n", path1);
      }
#endif
      str_list_add (&unique_list, path1);
    }

    /* could be more clever and increment by two, but then would
       have to avoid jumping off the end of db_files */
    dbi++;
  }
  
  /* always add a NULL terminator.  */
  str_list_add (&unique_list, NULL);
  
  free (orig_db_files);
  db_files = STR_LIST (unique_list);
  orig_db_files = db_files;

  /* Must do this after the path searching (which ends up calling
     kpse_db_search recursively), so kpse->db.buckets stays NULL.  */
  kpse->db = hash_create (DB_HASH_SIZE);

  while (db_files && *db_files) {
    if (db_build (kpse, &(kpse->db), *db_files))
      ok = true;
    free (*db_files);
    db_files++;
  }

  if (!ok) {
    /* If db can't be built, leave `size' nonzero (so we don't
       rebuild it), but clear `buckets' (so we don't look in it).  */
    free (kpse->db.buckets);
    kpse->db.buckets = NULL;
  }

  free (orig_db_files);

  /* Add the content of any alias databases.  There may exist more than
     one alias file along DB_NAME files.  This duplicates the above code
     -- should be a function.  */
  ok = false;
  db_files = kpathsea_all_path_search (kpse, db_path, ALIAS_NAME);
  orig_db_files = db_files;

  kpse->alias_db = hash_create (ALIAS_HASH_SIZE);

  while (db_files && *db_files) {
    if (alias_build (kpse, &(kpse->alias_db), *db_files))
      ok = true;
    free (*db_files);
    db_files++;
  }

  if (!ok) {
    free (kpse->alias_db.buckets);
    kpse->alias_db.buckets = NULL;
  }

  free (orig_db_files);
}