summaryrefslogtreecommitdiff
path: root/Build/source/texk/kpathsea/db.c
diff options
context:
space:
mode:
authorDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
committerDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
commitc6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch)
tree1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/texk/kpathsea/db.c
parent07ee7222e389b0777456b427a55c22d0e6ffd267 (diff)
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/kpathsea/db.c')
-rw-r--r--Build/source/texk/kpathsea/db.c807
1 files changed, 0 insertions, 807 deletions
diff --git a/Build/source/texk/kpathsea/db.c b/Build/source/texk/kpathsea/db.c
deleted file mode 100644
index fb4658c1968..00000000000
--- a/Build/source/texk/kpathsea/db.c
+++ /dev/null
@@ -1,807 +0,0 @@
-/* db.c: an external database to avoid filesystem lookups.
-
- Copyright 1994, 1995, 1996, 1997, 2008, 2009, 2011, 2012, 2014, 2016,
- 2017 Karl Berry.
- Copyright 1997-2005 Olaf Weber.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this library; if not, see <http://www.gnu.org/licenses/>. */
-
-#include <kpathsea/config.h>
-#include <kpathsea/absolute.h>
-#include <kpathsea/c-stat.h>
-#include <kpathsea/c-fopen.h>
-#include <kpathsea/c-pathch.h>
-#include <kpathsea/db.h>
-#include <kpathsea/hash.h>
-#include <kpathsea/line.h>
-#include <kpathsea/pathsearch.h>
-#include <kpathsea/readable.h>
-#include <kpathsea/str-list.h>
-#include <kpathsea/tex-file.h>
-#include <kpathsea/variable.h>
-
-#ifndef DB_HASH_SIZE
-/* Based on the size of 2014 texmf-dist/ls-R, about 130,000 entries. */
-#define DB_HASH_SIZE 64007
-#endif
-#ifndef DB_NAME
-#define DB_NAME "ls-R"
-#endif
-#ifndef DB_NAME_LC
-#define DB_NAME_LC "ls-r"
-#endif
-
-/* In the loop in init() below where we check for DB_NAME_LC and DB_NAME
- being the same file, it's convenient to ignore the first of a pair.
- So put the canonical name second. Sure wish I hadn't used a capital
- letter in the name in the first place. */
-/* We use non-const strings initialized with string constants in order
- to avoid some compiler warnings. */
-static char db_name_lc[] = DB_NAME_LC;
-static char db_name[] = DB_NAME;
-static string db_names[] = {
- db_name_lc,
- db_name,
- NULL
-};
-
-#ifndef ALIAS_NAME
-#define ALIAS_NAME "aliases"
-#endif
-#ifndef ALIAS_HASH_SIZE
-#define ALIAS_HASH_SIZE 1009
-#endif
-
-
-/* If DIRNAME contains any element beginning with a `.' (that is more
- than just `./'), return true. This is to allow ``hidden''
- directories -- ones that don't get searched. */
-
-static boolean
-ignore_dir_p (const_string dirname)
-{
- const_string dot_pos = dirname;
-
- while ((dot_pos = strchr (dot_pos + 1, '.'))) {
- /* If / before and no / after, skip it. */
- if (IS_DIR_SEP_CH (dot_pos[-1]) && dot_pos[1] && !IS_DIR_SEP_CH (dot_pos[1]))
- return true;
- }
-
- return false;
-}
-
-/* If no DB_FILENAME, return false (maybe they aren't using this feature).
- Otherwise, add entries from DB_FILENAME to TABLE, and return true. */
-
-static boolean
-db_build (kpathsea kpse, hash_table_type *table, const_string db_filename)
-{
- string line;
- unsigned dir_count = 0, file_count = 0, ignore_dir_count = 0;
- unsigned len = strlen (db_filename) - sizeof (DB_NAME) + 1; /* Keep the /. */
- string top_dir = (string)xmalloc (len + 1);
- string cur_dir = NULL; /* First thing in ls-R might be a filename. */
- FILE *db_file = fopen (db_filename, FOPEN_R_MODE);
-#if defined(MONOCASE_FILENAMES)
- string pp;
-#endif /* MONOCASE_FILENAMES */
-
- strncpy (top_dir, db_filename, len);
- top_dir[len] = 0;
-
- if (db_file) {
- while ((line = read_line (db_file)) != NULL) {
- len = strlen (line);
-
-#if defined(MONOCASE_FILENAMES)
- for (pp = line; *pp; pp++) {
-#if defined(_WIN32)
- if (kpathsea_IS_KANJI(kpse, pp))
- pp++;
- else
-#endif /* _WIN32 */
- *pp = TRANSFORM(*pp);
- }
-#endif /* MONOCASE_FILENAMES */
-
- /* A line like `/foo:' = new dir foo. Allow both absolute (/...)
- and explicitly relative (./...) names here. It's a kludge to
- pass in the directory name with the trailing : still attached,
- but it doesn't actually hurt. */
- if (len > 0 && line[len - 1] == ':'
- && kpathsea_absolute_p (kpse, line, true)) {
- /* New directory line. */
- if (!ignore_dir_p (line)) {
- /* If they gave a relative name, prepend full directory name now. */
- line[len - 1] = DIR_SEP;
- /* Skip over leading `./', it confuses `match' and is just a
- waste of space, anyway. This will lose on `../', but `match'
- won't work there, either, so it doesn't matter. */
- cur_dir = *line == '.' ? concat (top_dir, line + 2) : xstrdup (line);
- dir_count++;
- } else {
- cur_dir = NULL;
- ignore_dir_count++;
- }
-
- /* Ignore blank, `.' and `..' lines. */
- } else if (*line != 0 && cur_dir /* a file line? */
- && !(*line == '.'
- && (line[1] == 0 || (line[1] == '.' && line[2] == 0))))
- {
- /* Make a new hash table entry with a key of `line' and a data
- of `cur_dir'. An already-existing identical key is ok, since
- a file named `foo' can be in more than one directory. Share
- `cur_dir' among all its files (and hence never free it).
-
- Note that we assume that all names in the ls-R file have already
- been case-smashed to lowercase where appropriate.
- */
- hash_insert_normalized (table, xstrdup (line), cur_dir);
- file_count++;
-
- } /* else ignore blank lines or top-level files
- or files in ignored directories*/
-
- free (line);
- }
-
- xfclose (db_file, db_filename);
-
- if (file_count == 0) {
- WARNING1 ("kpathsea: %s: No usable entries in ls-R", db_filename);
- WARNING ("kpathsea: See the manual for how to generate ls-R");
- db_file = NULL;
- } else {
- str_list_add (&(kpse->db_dir_list), xstrdup (top_dir));
- }
-
-#ifdef KPSE_DEBUG
- if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
- /* Don't make this a debugging bit, since the output is so
- voluminous, and being able to specify -1 is too useful.
- Instead, let people who want it run the program under
- a debugger and change the variable that way. */
- boolean hash_summary_only = true;
-
- DEBUGF4 ("%s: %u entries in %d directories (%d hidden).\n",
- db_filename, file_count, dir_count, ignore_dir_count);
- DEBUGF ("ls-R hash table:");
- hash_print (*table, hash_summary_only);
- fflush (stderr);
- }
-#endif /* KPSE_DEBUG */
- }
-
- free (top_dir);
-
- return db_file != NULL;
-}
-
-
-/* Insert FNAME into the hash table. This is for files that get built
- during a run. We wouldn't want to reread all of ls-R, even if it got
- rebuilt. */
-
-void
-kpathsea_db_insert (kpathsea kpse, const_string passed_fname)
-{
- /* We might not have found ls-R, or even had occasion to look for it
- yet, so do nothing if we have no hash table. */
- if (kpse->db.buckets) {
- const_string dir_part;
- string fname = xstrdup (passed_fname);
- string baseptr = fname + (xbasename (fname) - fname);
- const_string file_part = xstrdup (baseptr);
-
- *baseptr = '\0'; /* Chop off the filename. */
- dir_part = fname; /* That leaves the dir, with the trailing /. */
-
- /* Note that we do not assuse that these names have been normalized. */
- hash_insert (&(kpse->db), file_part, dir_part);
- }
-}
-
-/* Return true if FILENAME could be in PATH_ELT, i.e., if the directory
- part of FILENAME matches PATH_ELT. Have to consider // wildcards, but
- $ and ~ expansion have already been done. */
-
-static boolean
-match (const_string filename, const_string path_elt)
-{
- const_string original_filename = filename;
- boolean matched = false;
-
- for (; *filename && *path_elt; filename++, path_elt++) {
- if (FILECHARCASEEQ (*filename, *path_elt)) /* normal character match */
- ;
-
- else if (IS_DIR_SEP_CH (*path_elt) /* at // */
- && original_filename < filename && IS_DIR_SEP_CH (path_elt[-1])) {
- while (IS_DIR_SEP_CH (*path_elt))
- path_elt++; /* get past second and any subsequent /'s */
- if (*path_elt == 0) {
- /* Trailing //, matches anything. We could make this part of the
- other case, but it seems pointless to do the extra work. */
- matched = true;
- break;
- } else {
- /* Intermediate //, have to match rest of PATH_ELT. */
- for (; !matched && *filename; filename++) {
- /* Try matching at each possible character. */
- if (IS_DIR_SEP_CH (filename[-1])
- && FILECHARCASEEQ (*filename, *path_elt))
- matched = match (filename, path_elt);
- }
- /* Prevent filename++ when *filename='\0'. */
- break;
- }
- }
-
- else /* normal character nonmatch, quit */
- break;
- }
-
- /* If we've reached the end of PATH_ELT, check that we're at the last
- component of FILENAME (that is, no directory separators remaining);
- only then have we matched. */
- if (!matched && *path_elt == 0) {
- /* Typically PATH_ELT ends with, say, `vf', and FILENAME ends with
- `vf/ptmr.vf'. In that case, we'll be at the /. On the other
- hand, if PATH_ELT ended with a / (as in `vf/'), FILENAME being
- the same `vf/ptmr.vf', we'll be at the `p'.
- Upshot: if we're at a dir sep in FILENAME, skip it. */
- if (IS_DIR_SEP_CH (*filename))
- filename++;
-
- /* Here are the basic possibilities for the check on being at the
- last component:
- 1) PATH_ELT is empty and FILENAME is `ptmr.vf' => match.
- (we now have original_filename == filename)
- 2) PATH_ELT is empty and FILENAME is `foo/ptmr.vf' => no match.
- (we now have original_filename == filename)
- 3) PATH_ELT is `vf/' and FILENAME is `vf/ptmr.vf'
- (we are now after the / in each) => match.
- 4) PATH_ELT is `vf' and FILENAME is `vfoo.ext'
- (we are now after the f in each) => no match.
-
- When (the original) PATH_ELT was the empty string, we want to match
- a FILENAME without dir seps. (This could be argued, and may never
- happen in practice, but is the historical behavior.) */
- /* if original_filename != filename then original_filename < filename */
- if (original_filename == filename || IS_DIR_SEP_CH (filename[-1])) {
- while (*filename && !IS_DIR_SEP_CH (*filename))
- filename++;
- matched = *filename == 0;
- }
- }
-
- return matched;
-}
-
-
-/* If DB_DIR is a prefix of PATH_ELT, return true; otherwise false.
- That is, the question is whether to try the db for a file looked up
- in PATH_ELT. If PATH_ELT == ".", for example, the answer is no. If
- PATH_ELT == "/usr/local/lib/texmf/fonts//tfm", the answer is yes.
- If either string is NULL or empty, return false.
-
- In practice, ls-R is only needed for lengthy subdirectory
- comparisons, but there's no gain to checking PATH_ELT to see if it is
- a subdir match, since the only way to do that is to do a string
- search in it, which is all we do anyway. */
-
-static boolean
-elt_in_db (const_string db_dir, const_string path_elt)
-{
- boolean found = false;
-
- /* If both strings are empty or null return false on the grounds that
- it's useless to do anything further with such a strange case (which
- likely never happens). In theory one could argue that the empty
- string is a prefix of any other string, but let's just declare the
- result otherwise. */
- if (db_dir == NULL || *db_dir == 0
- || path_elt == NULL || *path_elt == 0)
- return false;
-
- while (!found && FILECHARCASEEQ (*db_dir++, *path_elt++)) {
- /* If we've matched the entire db directory, it's good. */
- if (*db_dir == 0)
- found = true;
-
- /* If we've reached the end of PATH_ELT, but not the end of the db
- directory, it's no good. */
- else if (*path_elt == 0)
- break;
- }
-
- return found;
-}
-
-/* If ALIAS_FILENAME exists, read it into TABLE. */
-
-static boolean
-alias_build (kpathsea kpse, hash_table_type *table,
- const_string alias_filename)
-{
- string line, real, alias;
- unsigned count = 0;
- FILE *alias_file = fopen (alias_filename, FOPEN_R_MODE);
-
- if (alias_file) {
- while ((line = read_line (alias_file)) != NULL) {
- /* comments or empty */
- if (*line == 0 || *line == '%' || *line == '#') {
- ;
- } else {
- /* Each line should have two fields: realname aliasname. */
- real = line;
- while (*real && ISSPACE (*real))
- real++;
- alias = real;
- while (*alias && !ISSPACE (*alias))
- alias++;
- *alias++ = 0;
- while (*alias && ISSPACE (*alias))
- alias++;
- /* Is the check for errors strong enough? Should we warn the user
- for potential errors? */
- if (strlen (real) != 0 && strlen (alias) != 0) {
- /* Stuff in the alias file should be normalized. */
- hash_insert_normalized (table, xstrdup (alias), xstrdup (real));
- count++;
- }
- }
- free (line);
- }
-
-#ifdef KPSE_DEBUG
- if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
- /* As with ls-R above ... */
- boolean hash_summary_only = true;
- DEBUGF2 ("%s: %u aliases.\n", alias_filename, count);
- DEBUGF ("alias hash table:");
- hash_print (*table, hash_summary_only);
- fflush (stderr);
- }
-#endif /* KPSE_DEBUG */
-
- xfclose (alias_file, alias_filename);
- }
-
- return alias_file != NULL;
-}
-
-/* Initialize the path for ls-R files, and read them all into the hash
- table `db'. If no usable ls-R's found, set kpse->db.buckets to NULL. */
-
-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);
-}
-
-/* Avoid doing anything if this PATH_ELT is irrelevant to the databases. */
-str_list_type *
-kpathsea_db_search (kpathsea kpse, const_string name,
- const_string orig_path_elt, boolean all)
-{
- const_string *db_dirs, *orig_dirs;
- const_string last_slash, path_elt;
- string temp_str = NULL;
- boolean done;
- unsigned e;
- str_list_type *ret = NULL;
- const_string *aliases, *r;
- boolean relevant = false;
-
- /* If we failed to build the database (or if this is the recursive
- call to build the db path), quit. */
- if (kpse->db.buckets == NULL)
- return NULL;
-
- /* When tex-glyph.c calls us looking for, e.g., dpi600/cmr10.pk, we
- won't find it unless we change NAME to just `cmr10.pk' and append
- `/dpi600' to PATH_ELT. We are justified in using a literal `/'
- here, since that's what tex-glyph.c unconditionally uses in
- DPI_BITMAP_SPEC. But don't do anything if the / begins NAME; that
- should never happen. */
- last_slash = strrchr (name, '/');
- if (last_slash && last_slash != name) {
- unsigned len = last_slash - name + 1;
- string dir_part = (string)xmalloc (len);
- strncpy (dir_part, name, len - 1);
- dir_part[len - 1] = 0;
- path_elt = temp_str = concat3 (orig_path_elt, "/", dir_part);
- name = last_slash + 1;
- free (dir_part);
- } else
- path_elt = orig_path_elt;
-
- /* Don't bother doing any lookups if this `path_elt' isn't covered by
- any of database directories. We do this not so much because the
- extra couple of hash lookups matter -- they don't -- but rather
- because we want to return NULL in this case, so path_search can
- know to do a disk search. */
- for (e = 0; !relevant && e < STR_LIST_LENGTH (kpse->db_dir_list); e++) {
- relevant = elt_in_db (STR_LIST_ELT (kpse->db_dir_list, e), path_elt);
- }
- if (!relevant)
- return NULL;
-
- /* If we have aliases for this name, use them. */
- if (kpse->alias_db.buckets)
- aliases = hash_lookup (kpse->alias_db, name);
- else
- aliases = NULL;
-
- if (!aliases) {
- aliases = XTALLOC1 (const_string);
- aliases[0] = NULL;
- }
- { /* Push aliases up by one and insert the original name at the front. */
- unsigned i;
- unsigned len = 1; /* Have NULL element already allocated. */
- for (r = aliases; *r; r++)
- len++;
- /* This is essentially
- XRETALLOC (aliases, len + 1, const_string);
- except that MSVC warns without the cast to `void *'. */
- aliases = (const_string *) xrealloc ((void *) aliases,
- (len + 1) * sizeof(const_string));
- for (i = len; i > 0; i--) {
- aliases[i] = aliases[i - 1];
- }
- aliases[0] = name;
- }
-
- done = false;
- for (r = aliases; !done && *r; r++) {
- const_string ctry = *r;
-
- /* We have an ls-R db. Look up `try'. */
- orig_dirs = db_dirs = hash_lookup (kpse->db, ctry);
-
- ret = XTALLOC1 (str_list_type);
- *ret = str_list_init ();
-
- /* For each filename found, see if it matches the path element. For
- example, if we have .../cx/cmr10.300pk and .../ricoh/cmr10.300pk,
- and the path looks like .../cx, we don't want the ricoh file. */
- while (!done && db_dirs && *db_dirs) {
- string db_file = concat (*db_dirs, ctry);
- boolean matched = match (db_file, path_elt);
-
-#ifdef KPSE_DEBUG
- if (KPATHSEA_DEBUG_P (KPSE_DEBUG_SEARCH))
- DEBUGF3 ("db:match(%s,%s) = %d\n", db_file, path_elt, matched);
-#endif
-
- /* We got a hit in the database. Now see if the file actually
- exists, possibly under an alias. */
- if (matched) {
- string found = NULL;
- if (kpathsea_readable_file (kpse, db_file)) {
- found = db_file;
-
- } else {
- const_string *a;
-
- free (db_file); /* `db_file' wasn't on disk. */
-
- /* The hit in the DB doesn't exist in disk. Now try all its
- aliases. For example, suppose we have a hierarchy on CD,
- thus `mf.bas', but ls-R contains `mf.base'. Find it anyway.
- Could probably work around this with aliases, but
- this is pretty easy and shouldn't hurt. The upshot is that
- if one of the aliases actually exists, we use that. */
- for (a = aliases + 1; *a && !found; a++) {
- string atry = concat (*db_dirs, *a);
- if (kpathsea_readable_file (kpse, atry))
- found = atry;
- else
- free (atry);
- }
- }
-
- /* If we have a real file, add it to the list, maybe done. */
- if (found) {
- str_list_add (ret, found);
- if (!all && found)
- done = true;
- }
- } else { /* no match in the db */
- free (db_file);
- }
-
-
- /* On to the next directory, if any. */
- db_dirs++;
- }
-
- /* This is just the space for the pointers, not the strings. */
- if (orig_dirs && *orig_dirs)
- free (orig_dirs);
- }
-
- free ((void *) aliases);
-
- /* If we had to break up NAME, free the TEMP_STR. */
- if (temp_str)
- free (temp_str);
-
- return ret;
-}
-
-str_list_type *
-kpathsea_db_search_list (kpathsea kpse, string* names,
- const_string path_elt, boolean all)
-{
- const_string *db_dirs, *orig_dirs;
- const_string last_slash, name, path;
- string temp_str = NULL;
- boolean done;
- unsigned e;
- const_string *aliases, *r;
- int n;
- str_list_type *ret = NULL;
- boolean relevant = false;
-
- /* If we failed to build the database (or if this is the recursive
- call to build the db path), quit. */
- if (kpse->db.buckets == NULL)
- return NULL;
-
- /* Don't bother doing any lookups if this `path_elt' isn't covered by
- any of database directories. We do this not so much because the
- extra couple of hash lookups matter -- they don't -- but rather
- because we want to return NULL in this case, so path_search can
- know to do a disk search. */
- for (e = 0; !relevant && e < STR_LIST_LENGTH (kpse->db_dir_list); e++) {
- relevant = elt_in_db (STR_LIST_ELT (kpse->db_dir_list, e), path_elt);
- }
- if (!relevant)
- return NULL;
-
- done = false;
- ret = XTALLOC1 (str_list_type);
- *ret = str_list_init ();
-
- /* Handle each name. */
- for (n = 0; !done && names[n]; n++) {
- name = names[n];
-
- /* Absolute names should have been caught in our caller. */
- if (kpathsea_absolute_p(kpse, name, true))
- continue;
-
- /* When tex-glyph.c calls us looking for, e.g., dpi600/cmr10.pk, we
- won't find it unless we change NAME to just `cmr10.pk' and append
- `/dpi600' to PATH_ELT. We are justified in using a literal `/'
- here, since that's what tex-glyph.c unconditionally uses in
- DPI_BITMAP_SPEC. But don't do anything if the / begins NAME; that
- should never happen. */
- last_slash = strrchr (name, '/');
- if (last_slash && last_slash != name) {
- unsigned len = last_slash - name + 1;
- string dir_part = (string)xmalloc (len);
- strncpy (dir_part, name, len - 1);
- dir_part[len - 1] = 0;
- path = temp_str = concat3 (path_elt, "/", dir_part);
- name = last_slash + 1;
- free (dir_part);
- } else {
- path = path_elt;
- }
-
- /* If we have aliases for this name, use them. */
- if (kpse->alias_db.buckets)
- aliases = hash_lookup (kpse->alias_db, name);
- else
- aliases = NULL;
-
- if (!aliases) {
- aliases = XTALLOC1 (const_string);
- aliases[0] = NULL;
- }
- { /* Push aliases up by one and insert the original name at front. */
- unsigned i;
- unsigned len = 1; /* Have NULL element already allocated. */
- for (r = aliases; *r; r++)
- len++;
- aliases = (const_string *) xrealloc ((void *) aliases,
- (len + 1) * sizeof(const_string));
- for (i = len; i > 0; i--) {
- aliases[i] = aliases[i - 1];
- }
- aliases[0] = name;
- }
-
- for (r = aliases; !done && *r; r++) {
- const_string ctry = *r;
-
- /* We have an ls-R db. Look up `try'. */
- orig_dirs = db_dirs = hash_lookup (kpse->db, ctry);
-
- /* For each filename found, see if it matches the path element. For
- example, if we have .../cx/cmr10.300pk and .../ricoh/cmr10.300pk,
- and the path looks like .../cx, we don't want the ricoh file. */
- while (!done && db_dirs && *db_dirs) {
- string db_file = concat (*db_dirs, ctry);
- boolean matched = match (db_file, path);
-
-#ifdef KPSE_DEBUG
- if (KPATHSEA_DEBUG_P (KPSE_DEBUG_SEARCH))
- DEBUGF3 ("db:match(%s,%s) = %d\n", db_file, path, matched);
-#endif
-
- /* We got a hit in the database. Now see if the file actually
- exists, possibly under an alias. */
- if (matched) {
- string found = NULL;
- if (kpathsea_readable_file (kpse, db_file)) {
- found = db_file;
-
- } else {
- const_string *a;
-
- free (db_file); /* `db_file' wasn't on disk. */
-
- /* The hit in the DB doesn't exist in disk. Now try all its
- aliases. For example, suppose we have a hierarchy on CD,
- thus `mf.bas', but ls-R contains `mf.base'. Find it anyway.
- Could probably work around this with aliases, but
- this is pretty easy and shouldn't hurt. The upshot is that
- if one of the aliases actually exists, we use that. */
- for (a = aliases + 1; *a && !found; a++) {
- string atry = concat (*db_dirs, *a);
- if (kpathsea_readable_file (kpse, atry))
- found = atry;
- else
- free (atry);
- }
- }
-
- /* If we have a real file, add it to the list, maybe done. */
- if (found) {
- str_list_add (ret, found);
- if (!all)
- done = true;
- }
- } else { /* no match in the db */
- free (db_file);
- }
-
- /* On to the next directory, if any. */
- db_dirs++;
- }
-
- /* This is just the space for the pointers, not the strings. */
- if (orig_dirs && *orig_dirs)
- free (orig_dirs);
- }
-
- free ((void *) aliases);
- if (temp_str)
- free (temp_str);
- }
-
- return ret;
-}