summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c1975
1 files changed, 1058 insertions, 917 deletions
diff --git a/dir.c b/dir.c
index 359e61adb669..230b66b3baf3 100644
--- a/dir.c
+++ b/dir.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dir.c,v 1.210 2020/11/14 21:29:44 rillig Exp $ */
+/* $NetBSD: dir.c,v 1.255 2021/01/10 21:20:46 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -69,7 +69,8 @@
* SUCH DAMAGE.
*/
-/* Directory searching using wildcards and/or normal names.
+/*
+ * Directory searching using wildcards and/or normal names.
* Used both for source wildcarding in the makefile and for finding
* implicit sources.
*
@@ -106,7 +107,8 @@
*
* Dir_AddDir Add a directory to a search path.
*
- * Dir_MakeFlags Given a search path and a command flag, create
+ * SearchPath_ToFlags
+ * Given a search path and a command flag, create
* a string with each of the directories in the path
* preceded by the command flag and all of them
* separated by a space.
@@ -116,7 +118,8 @@
* as the element is no longer referenced by any other
* search path.
*
- * Dir_ClearPath Resets a search path to the empty list.
+ * SearchPath_Clear
+ * Resets a search path to the empty list.
*
* For debugging:
* Dir_PrintDirectories
@@ -134,13 +137,10 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: dir.c,v 1.210 2020/11/14 21:29:44 rillig Exp $");
-
-#define DIR_DEBUG0(text) DEBUG0(DIR, text)
-#define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1)
-#define DIR_DEBUG2(fmt, arg1, arg2) DEBUG2(DIR, fmt, arg1, arg2)
+MAKE_RCSID("$NetBSD: dir.c,v 1.255 2021/01/10 21:20:46 rillig Exp $");
-/* A search path is a list of CachedDir structures. A CachedDir has in it the
+/*
+ * A search path is a list of CachedDir structures. A CachedDir has in it the
* name of the directory and the names of all the files in the directory.
* This is used to cut down on the number of system calls necessary to find
* implicit dependents and their like. Since these searches are made before
@@ -207,179 +207,277 @@ MAKE_RCSID("$NetBSD: dir.c,v 1.210 2020/11/14 21:29:44 rillig Exp $");
* the mtime in a cache for when Dir_UpdateMTime was actually called.
*/
+
+/* A cache for the filenames in a directory. */
+struct CachedDir {
+ /*
+ * Name of directory, either absolute or relative to the current
+ * directory. The name is not normalized in any way, that is, "."
+ * and "./." are different.
+ *
+ * Not sure what happens when .CURDIR is assigned a new value; see
+ * Parse_DoVar.
+ */
+ char *name;
+
+ /*
+ * The number of SearchPaths that refer to this directory.
+ * Plus the number of global variables that refer to this directory.
+ * References from openDirs do not count though.
+ */
+ int refCount;
+
+ /* The number of times a file in this directory has been found. */
+ int hits;
+
+ /* The names of the directory entries. */
+ HashSet files;
+};
+
typedef List CachedDirList;
typedef ListNode CachedDirListNode;
typedef ListNode SearchPathNode;
-SearchPath *dirSearchPath; /* main search path */
-
/* A list of cached directories, with fast lookup by directory name. */
typedef struct OpenDirs {
- CachedDirList *list;
- HashTable /* of CachedDirListNode */ table;
+ CachedDirList list;
+ HashTable /* of CachedDirListNode */ table;
} OpenDirs;
+typedef enum CachedStatsFlags {
+ CST_NONE = 0,
+ CST_LSTAT = 1 << 0, /* call lstat(2) instead of stat(2) */
+ CST_UPDATE = 1 << 1 /* ignore existing cached entry */
+} CachedStatsFlags;
+
+
+SearchPath dirSearchPath = LST_INIT; /* main search path */
+
+static OpenDirs openDirs; /* all cached directories */
+
+/*
+ * Variables for gathering statistics on the efficiency of the caching
+ * mechanism.
+ */
+static int hits; /* Found in directory cache */
+static int misses; /* Sad, but not evil misses */
+static int nearmisses; /* Found under search path */
+static int bigmisses; /* Sought by itself */
+
+/* The cached contents of ".", the relative current directory. */
+static CachedDir *dot = NULL;
+/* The cached contents of the absolute current directory. */
+static CachedDir *cur = NULL;
+/* A fake path entry indicating we need to look for '.' last. */
+static CachedDir *dotLast = NULL;
+
+/*
+ * Results of doing a last-resort stat in Dir_FindFile -- if we have to go to
+ * the system to find the file, we might as well have its mtime on record.
+ *
+ * XXX: If this is done way early, there's a chance other rules will have
+ * already updated the file, in which case we'll update it again. Generally,
+ * there won't be two rules to update a single file, so this should be ok,
+ * but...
+ */
+static HashTable mtimes;
+
+static HashTable lmtimes; /* same as mtimes but for lstat */
+
+
+static void OpenDirs_Remove(OpenDirs *, const char *);
+
+
+static CachedDir *
+CachedDir_New(const char *name)
+{
+ CachedDir *dir = bmake_malloc(sizeof *dir);
+
+ dir->name = bmake_strdup(name);
+ dir->refCount = 0;
+ dir->hits = 0;
+ HashSet_Init(&dir->files);
+
+#ifdef DEBUG_REFCNT
+ DEBUG2(DIR, "CachedDir %p new for \"%s\"\n", dir, dir->name);
+#endif
+
+ return dir;
+}
+
+static CachedDir *
+CachedDir_Ref(CachedDir *dir)
+{
+ dir->refCount++;
+
+#ifdef DEBUG_REFCNT
+ DEBUG3(DIR, "CachedDir %p ++ %d for \"%s\"\n",
+ dir, dir->refCount, dir->name);
+#endif
+
+ return dir;
+}
+
+static void
+CachedDir_Unref(CachedDir *dir)
+{
+ dir->refCount--;
+
+#ifdef DEBUG_REFCNT
+ DEBUG3(DIR, "CachedDir %p -- %d for \"%s\"\n",
+ dir, dir->refCount, dir->name);
+#endif
+
+ if (dir->refCount > 0)
+ return;
+
+#ifdef DEBUG_REFCNT
+ DEBUG2(DIR, "CachedDir %p free for \"%s\"\n", dir, dir->name);
+#endif
+
+ OpenDirs_Remove(&openDirs, dir->name);
+
+ free(dir->name);
+ HashSet_Done(&dir->files);
+ free(dir);
+}
+
+/* Update the value of the CachedDir variable, updating the reference counts. */
+static void
+CachedDir_Assign(CachedDir **var, CachedDir *dir)
+{
+ CachedDir *prev;
+
+ prev = *var;
+ *var = dir;
+ if (dir != NULL)
+ CachedDir_Ref(dir);
+ if (prev != NULL)
+ CachedDir_Unref(prev);
+}
+
static void
OpenDirs_Init(OpenDirs *odirs)
{
- odirs->list = Lst_New();
- HashTable_Init(&odirs->table);
+ Lst_Init(&odirs->list);
+ HashTable_Init(&odirs->table);
}
#ifdef CLEANUP
static void
OpenDirs_Done(OpenDirs *odirs)
{
- CachedDirListNode *ln = odirs->list->first;
- while (ln != NULL) {
- CachedDirListNode *next = ln->next;
- CachedDir *dir = ln->datum;
- Dir_Destroy(dir); /* removes the dir from odirs->list */
- ln = next;
- }
- Lst_Free(odirs->list);
- HashTable_Done(&odirs->table);
+ CachedDirListNode *ln = odirs->list.first;
+ DEBUG1(DIR, "OpenDirs_Done: %u entries to remove\n",
+ odirs->table.numEntries);
+ while (ln != NULL) {
+ CachedDirListNode *next = ln->next;
+ CachedDir *dir = ln->datum;
+ DEBUG2(DIR, "OpenDirs_Done: refCount %d for \"%s\"\n",
+ dir->refCount, dir->name);
+ CachedDir_Unref(dir); /* removes the dir from odirs->list */
+ ln = next;
+ }
+ Lst_Done(&odirs->list);
+ HashTable_Done(&odirs->table);
}
#endif
static CachedDir *
OpenDirs_Find(OpenDirs *odirs, const char *name)
{
- CachedDirListNode *ln = HashTable_FindValue(&odirs->table, name);
- return ln != NULL ? ln->datum : NULL;
+ CachedDirListNode *ln = HashTable_FindValue(&odirs->table, name);
+ return ln != NULL ? ln->datum : NULL;
}
static void
OpenDirs_Add(OpenDirs *odirs, CachedDir *cdir)
{
- if (HashTable_FindEntry(&odirs->table, cdir->name) != NULL)
- return;
- Lst_Append(odirs->list, cdir);
- HashTable_Set(&odirs->table, cdir->name, odirs->list->last);
+ if (HashTable_FindEntry(&odirs->table, cdir->name) != NULL)
+ return;
+ Lst_Append(&odirs->list, cdir);
+ HashTable_Set(&odirs->table, cdir->name, odirs->list.last);
}
static void
OpenDirs_Remove(OpenDirs *odirs, const char *name)
{
- HashEntry *he = HashTable_FindEntry(&odirs->table, name);
- CachedDirListNode *ln;
- if (he == NULL)
- return;
- ln = HashEntry_Get(he);
- HashTable_DeleteEntry(&odirs->table, he);
- Lst_Remove(odirs->list, ln);
+ HashEntry *he = HashTable_FindEntry(&odirs->table, name);
+ CachedDirListNode *ln;
+ if (he == NULL)
+ return;
+ ln = HashEntry_Get(he);
+ HashTable_DeleteEntry(&odirs->table, he);
+ Lst_Remove(&odirs->list, ln);
}
-static OpenDirs openDirs; /* all cached directories */
-
/*
- * Variables for gathering statistics on the efficiency of the caching
- * mechanism.
+ * Returns 0 and the result of stat(2) or lstat(2) in *out_cst,
+ * or -1 on error.
*/
-static int hits; /* Found in directory cache */
-static int misses; /* Sad, but not evil misses */
-static int nearmisses; /* Found under search path */
-static int bigmisses; /* Sought by itself */
-
-static CachedDir *dot; /* contents of current directory */
-static CachedDir *cur; /* contents of current directory, if not dot */
-static CachedDir *dotLast; /* a fake path entry indicating we need to
- * look for . last */
-
-/* Results of doing a last-resort stat in Dir_FindFile -- if we have to go to
- * the system to find the file, we might as well have its mtime on record.
- *
- * XXX: If this is done way early, there's a chance other rules will have
- * already updated the file, in which case we'll update it again. Generally,
- * there won't be two rules to update a single file, so this should be ok,
- * but... */
-static HashTable mtimes;
-
-static HashTable lmtimes; /* same as mtimes but for lstat */
-
-typedef enum CachedStatsFlags {
- CST_NONE = 0,
- CST_LSTAT = 1 << 0, /* call lstat(2) instead of stat(2) */
- CST_UPDATE = 1 << 1 /* ignore existing cached entry */
-} CachedStatsFlags;
-
-/* Returns 0 and the result of stat(2) or lstat(2) in *out_cst,
- * or -1 on error. */
static int
cached_stats(const char *pathname, struct cached_stat *out_cst,
CachedStatsFlags flags)
{
- HashTable *tbl = flags & CST_LSTAT ? &lmtimes : &mtimes;
- struct stat sys_st;
- struct cached_stat *cst;
- int rc;
+ HashTable *tbl = flags & CST_LSTAT ? &lmtimes : &mtimes;
+ struct stat sys_st;
+ struct cached_stat *cst;
+ int rc;
- if (pathname == NULL || pathname[0] == '\0')
- return -1; /* This can happen in meta mode. */
+ if (pathname == NULL || pathname[0] == '\0')
+ return -1; /* This can happen in meta mode. */
- cst = HashTable_FindValue(tbl, pathname);
- if (cst != NULL && !(flags & CST_UPDATE)) {
- *out_cst = *cst;
- DIR_DEBUG2("Using cached time %s for %s\n",
- Targ_FmtTime(cst->cst_mtime), pathname);
- return 0;
- }
+ cst = HashTable_FindValue(tbl, pathname);
+ if (cst != NULL && !(flags & CST_UPDATE)) {
+ *out_cst = *cst;
+ DEBUG2(DIR, "Using cached time %s for %s\n",
+ Targ_FmtTime(cst->cst_mtime), pathname);
+ return 0;
+ }
- rc = (flags & CST_LSTAT ? lstat : stat)(pathname, &sys_st);
- if (rc == -1)
- return -1; /* don't cache negative lookups */
+ rc = (flags & CST_LSTAT ? lstat : stat)(pathname, &sys_st);
+ if (rc == -1)
+ return -1; /* don't cache negative lookups */
- if (sys_st.st_mtime == 0)
- sys_st.st_mtime = 1; /* avoid confusion with missing file */
+ if (sys_st.st_mtime == 0)
+ sys_st.st_mtime = 1; /* avoid confusion with missing file */
- if (cst == NULL) {
- cst = bmake_malloc(sizeof *cst);
- HashTable_Set(tbl, pathname, cst);
- }
+ if (cst == NULL) {
+ cst = bmake_malloc(sizeof *cst);
+ HashTable_Set(tbl, pathname, cst);
+ }
- cst->cst_mtime = sys_st.st_mtime;
- cst->cst_mode = sys_st.st_mode;
+ cst->cst_mtime = sys_st.st_mtime;
+ cst->cst_mode = sys_st.st_mode;
- *out_cst = *cst;
- DIR_DEBUG2(" Caching %s for %s\n",
- Targ_FmtTime(sys_st.st_mtime), pathname);
+ *out_cst = *cst;
+ DEBUG2(DIR, " Caching %s for %s\n",
+ Targ_FmtTime(sys_st.st_mtime), pathname);
- return 0;
+ return 0;
}
int
cached_stat(const char *pathname, struct cached_stat *cst)
{
- return cached_stats(pathname, cst, CST_NONE);
+ return cached_stats(pathname, cst, CST_NONE);
}
int
cached_lstat(const char *pathname, struct cached_stat *cst)
{
- return cached_stats(pathname, cst, CST_LSTAT);
+ return cached_stats(pathname, cst, CST_LSTAT);
}
/* Initialize the directories module. */
void
Dir_Init(void)
{
- dirSearchPath = Lst_New();
- OpenDirs_Init(&openDirs);
- HashTable_Init(&mtimes);
- HashTable_Init(&lmtimes);
-}
-
-void
-Dir_InitDir(const char *cdname)
-{
- Dir_InitCur(cdname);
-
- dotLast = bmake_malloc(sizeof *dotLast);
- dotLast->refCount = 1;
- dotLast->hits = 0;
- dotLast->name = bmake_strdup(".DOTLAST");
- HashTable_Init(&dotLast->files);
+ OpenDirs_Init(&openDirs);
+ HashTable_Init(&mtimes);
+ HashTable_Init(&lmtimes);
+ CachedDir_Assign(&dotLast, CachedDir_New(".DOTLAST"));
}
/*
@@ -388,58 +486,40 @@ Dir_InitDir(const char *cdname)
void
Dir_InitCur(const char *cdname)
{
- CachedDir *dir;
-
- if (cdname == NULL)
- return;
+ CachedDir *dir;
- /*
- * Our build directory is not the same as our source directory.
- * Keep this one around too.
- */
- dir = Dir_AddDir(NULL, cdname);
- if (dir == NULL)
- return;
+ if (cdname == NULL)
+ return;
- /* XXX: Reference counting is wrong here.
- * If this function is called repeatedly with the same directory name,
- * its reference count increases each time even though the number of
- * actual references stays the same. */
-
- dir->refCount++;
- if (cur != NULL && cur != dir) {
/*
- * We've been here before, clean up.
+ * Our build directory is not the same as our source directory.
+ * Keep this one around too.
*/
- cur->refCount--;
- Dir_Destroy(cur);
- }
- cur = dir;
+ dir = Dir_AddDir(NULL, cdname);
+ if (dir == NULL)
+ return;
+
+ CachedDir_Assign(&cur, dir);
}
-/* (Re)initialize "dot" (current/object directory) path hash.
- * Some directories may be opened. */
+/*
+ * (Re)initialize "dot" (current/object directory) path hash.
+ * Some directories may be cached.
+ */
void
Dir_InitDot(void)
{
- if (dot != NULL) {
- /* Remove old entry from openDirs, but do not destroy. */
- OpenDirs_Remove(&openDirs, dot->name);
- }
+ CachedDir *dir;
- dot = Dir_AddDir(NULL, ".");
+ dir = Dir_AddDir(NULL, ".");
+ if (dir == NULL) {
+ Error("Cannot open `.' (%s)", strerror(errno));
+ exit(2); /* Not 1 so -q can distinguish error */
+ }
- if (dot == NULL) {
- Error("Cannot open `.' (%s)", strerror(errno));
- exit(1);
- }
+ CachedDir_Assign(&dot, dir);
- /*
- * We always need to have dot around, so we increment its reference count
- * to make sure it's not destroyed.
- */
- dot->refCount++;
- Dir_SetPATH(); /* initialize */
+ Dir_SetPATH(); /* initialize */
}
/* Clean up the directories module. */
@@ -447,18 +527,13 @@ void
Dir_End(void)
{
#ifdef CLEANUP
- if (cur) {
- cur->refCount--;
- Dir_Destroy(cur);
- }
- dot->refCount--;
- dotLast->refCount--;
- Dir_Destroy(dotLast);
- Dir_Destroy(dot);
- Dir_ClearPath(dirSearchPath);
- Lst_Free(dirSearchPath);
- OpenDirs_Done(&openDirs);
- HashTable_Done(&mtimes);
+ CachedDir_Assign(&cur, NULL);
+ CachedDir_Assign(&dot, NULL);
+ CachedDir_Assign(&dotLast, NULL);
+ SearchPath_Clear(&dirSearchPath);
+ OpenDirs_Done(&openDirs);
+ HashTable_Done(&mtimes);
+ HashTable_Done(&lmtimes);
#endif
}
@@ -470,44 +545,45 @@ Dir_End(void)
void
Dir_SetPATH(void)
{
- CachedDirListNode *ln;
- Boolean hasLastDot = FALSE; /* true if we should search dot last */
+ CachedDirListNode *ln;
+ Boolean seenDotLast = FALSE; /* true if we should search '.' last */
- Var_Delete(".PATH", VAR_GLOBAL);
+ Var_Delete(".PATH", VAR_GLOBAL);
- if ((ln = dirSearchPath->first) != NULL) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast) {
- hasLastDot = TRUE;
- Var_Append(".PATH", dotLast->name, VAR_GLOBAL);
+ if ((ln = dirSearchPath.first) != NULL) {
+ CachedDir *dir = ln->datum;
+ if (dir == dotLast) {
+ seenDotLast = TRUE;
+ Var_Append(".PATH", dotLast->name, VAR_GLOBAL);
+ }
}
- }
- if (!hasLastDot) {
- if (dot)
- Var_Append(".PATH", dot->name, VAR_GLOBAL);
- if (cur)
- Var_Append(".PATH", cur->name, VAR_GLOBAL);
- }
+ if (!seenDotLast) {
+ if (dot != NULL)
+ Var_Append(".PATH", dot->name, VAR_GLOBAL);
+ if (cur != NULL)
+ Var_Append(".PATH", cur->name, VAR_GLOBAL);
+ }
- for (ln = dirSearchPath->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast)
- continue;
- if (dir == dot && hasLastDot)
- continue;
- Var_Append(".PATH", dir->name, VAR_GLOBAL);
- }
+ for (ln = dirSearchPath.first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ if (dir == dotLast)
+ continue;
+ if (dir == dot && seenDotLast)
+ continue;
+ Var_Append(".PATH", dir->name, VAR_GLOBAL);
+ }
- if (hasLastDot) {
- if (dot)
- Var_Append(".PATH", dot->name, VAR_GLOBAL);
- if (cur)
- Var_Append(".PATH", cur->name, VAR_GLOBAL);
- }
+ if (seenDotLast) {
+ if (dot != NULL)
+ Var_Append(".PATH", dot->name, VAR_GLOBAL);
+ if (cur != NULL)
+ Var_Append(".PATH", cur->name, VAR_GLOBAL);
+ }
}
-/* See if the given name has any wildcard characters in it and all braces and
+/*
+ * See if the given name has any wildcard characters in it and all braces and
* brackets are properly balanced.
*
* XXX: This code is not 100% correct ([^]] fails etc.). I really don't think
@@ -519,38 +595,39 @@ Dir_SetPATH(void)
Boolean
Dir_HasWildcards(const char *name)
{
- const char *p;
- Boolean wild = FALSE;
- int braces = 0, brackets = 0;
+ const char *p;
+ Boolean wild = FALSE;
+ int braces = 0, brackets = 0;
- for (p = name; *p != '\0'; p++) {
- switch (*p) {
- case '{':
- braces++;
- wild = TRUE;
- break;
- case '}':
- braces--;
- break;
- case '[':
- brackets++;
- wild = TRUE;
- break;
- case ']':
- brackets--;
- break;
- case '?':
- case '*':
- wild = TRUE;
- break;
- default:
- break;
+ for (p = name; *p != '\0'; p++) {
+ switch (*p) {
+ case '{':
+ braces++;
+ wild = TRUE;
+ break;
+ case '}':
+ braces--;
+ break;
+ case '[':
+ brackets++;
+ wild = TRUE;
+ break;
+ case ']':
+ brackets--;
+ break;
+ case '?':
+ case '*':
+ wild = TRUE;
+ break;
+ default:
+ break;
+ }
}
- }
- return wild && brackets == 0 && braces == 0;
+ return wild && brackets == 0 && braces == 0;
}
-/* See if any files match the pattern and add their names to the 'expansions'
+/*
+ * See if any files match the pattern and add their names to the 'expansions'
* list if they do.
*
* This is incomplete -- wildcards are only expanded in the final path
@@ -566,105 +643,114 @@ Dir_HasWildcards(const char *name)
static void
DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions)
{
- const char *dirName = dir->name;
- Boolean isDot = dirName[0] == '.' && dirName[1] == '\0';
- HashIter hi;
+ const char *dirName = dir->name;
+ Boolean isDot = dirName[0] == '.' && dirName[1] == '\0';
+ HashIter hi;
- /* XXX: Iterating over all hash entries is inefficient. If the pattern
- * is a plain string without any wildcards, a direct lookup is faster. */
+ /*
+ * XXX: Iterating over all hash entries is inefficient. If the
+ * pattern is a plain string without any wildcards, a direct lookup
+ * is faster.
+ */
- HashIter_Init(&hi, &dir->files);
- while (HashIter_Next(&hi) != NULL) {
- const char *base = hi.entry->key;
+ HashIter_InitSet(&hi, &dir->files);
+ while (HashIter_Next(&hi) != NULL) {
+ const char *base = hi.entry->key;
- if (!Str_Match(base, pattern))
- continue;
+ if (!Str_Match(base, pattern))
+ continue;
- /*
- * Follow the UNIX convention that dot files are only found if the
- * pattern begins with a dot. The pattern '.*' does not match '.' or
- * '..' since these are not included in the directory cache.
- *
- * This means that the pattern '[a-z.]*' does not find '.file', which
- * is consistent with bash, NetBSD sh and csh.
- */
- if (base[0] == '.' && pattern[0] != '.')
- continue;
+ /*
+ * Follow the UNIX convention that dot files are only found
+ * if the pattern begins with a dot. The pattern '.*' does
+ * not match '.' or '..' since these are not included in the
+ * directory cache.
+ *
+ * This means that the pattern '[a-z.]*' does not find
+ * '.file', which is consistent with bash, NetBSD sh and csh.
+ */
+ if (base[0] == '.' && pattern[0] != '.')
+ continue;
- {
- char *fullName = isDot
- ? bmake_strdup(base)
- : str_concat3(dirName, "/", base);
- Lst_Append(expansions, fullName);
+ {
+ char *fullName = isDot
+ ? bmake_strdup(base)
+ : str_concat3(dirName, "/", base);
+ Lst_Append(expansions, fullName);
+ }
}
- }
}
-/* Find the next closing brace in the string, taking nested braces into
- * account. */
+/*
+ * Find the next closing brace in the string, taking nested braces into
+ * account.
+ */
static const char *
closing_brace(const char *p)
{
- int nest = 0;
- while (*p != '\0') {
- if (*p == '}' && nest == 0)
- break;
- if (*p == '{')
- nest++;
- if (*p == '}')
- nest--;
- p++;
- }
- return p;
+ int nest = 0;
+ while (*p != '\0') {
+ if (*p == '}' && nest == 0)
+ break;
+ if (*p == '{')
+ nest++;
+ if (*p == '}')
+ nest--;
+ p++;
+ }
+ return p;
}
-/* Find the next closing brace or comma in the string, taking nested braces
- * into account. */
+/*
+ * Find the next closing brace or comma in the string, taking nested braces
+ * into account.
+ */
static const char *
separator_comma(const char *p)
{
- int nest = 0;
- while (*p != '\0') {
- if ((*p == '}' || *p == ',') && nest == 0)
- break;
- if (*p == '{')
- nest++;
- if (*p == '}')
- nest--;
- p++;
- }
- return p;
+ int nest = 0;
+ while (*p != '\0') {
+ if ((*p == '}' || *p == ',') && nest == 0)
+ break;
+ if (*p == '{')
+ nest++;
+ if (*p == '}')
+ nest--;
+ p++;
+ }
+ return p;
}
static Boolean
contains_wildcard(const char *p)
{
- for (; *p != '\0'; p++) {
- switch (*p) {
- case '*':
- case '?':
- case '{':
- case '[':
- return TRUE;
+ for (; *p != '\0'; p++) {
+ switch (*p) {
+ case '*':
+ case '?':
+ case '{':
+ case '[':
+ return TRUE;
+ }
}
- }
- return FALSE;
+ return FALSE;
}
static char *
concat3(const char *a, size_t a_len, const char *b, size_t b_len,
const char *c, size_t c_len)
{
- size_t s_len = a_len + b_len + c_len;
- char *s = bmake_malloc(s_len + 1);
- memcpy(s, a, a_len);
- memcpy(s + a_len, b, b_len);
- memcpy(s + a_len + b_len, c, c_len);
- s[s_len] = '\0';
- return s;
+ size_t s_len = a_len + b_len + c_len;
+ char *s = bmake_malloc(s_len + 1);
+ memcpy(s, a, a_len);
+ memcpy(s + a_len, b, b_len);
+ memcpy(s + a_len + b_len, c, c_len);
+ s[s_len] = '\0';
+ return s;
}
-/* Expand curly braces like the C shell. Brace expansion by itself is purely
+/*
+ * Expand curly braces like the C shell. Brace expansion by itself is purely
* textual, the expansions are not looked up in the file system. But if an
* expanded word contains wildcard characters, it is expanded further,
* matching only the actually existing files.
@@ -683,42 +769,43 @@ static void
DirExpandCurly(const char *word, const char *brace, SearchPath *path,
StringList *expansions)
{
- const char *prefix, *middle, *piece, *middle_end, *suffix;
- size_t prefix_len, suffix_len;
+ const char *prefix, *middle, *piece, *middle_end, *suffix;
+ size_t prefix_len, suffix_len;
- /* Split the word into prefix '{' middle '}' suffix. */
+ /* Split the word into prefix '{' middle '}' suffix. */
- middle = brace + 1;
- middle_end = closing_brace(middle);
- if (*middle_end == '\0') {
- Error("Unterminated {} clause \"%s\"", middle);
- return;
- }
+ middle = brace + 1;
+ middle_end = closing_brace(middle);
+ if (*middle_end == '\0') {
+ Error("Unterminated {} clause \"%s\"", middle);
+ return;
+ }
- prefix = word;
- prefix_len = (size_t)(brace - prefix);
- suffix = middle_end + 1;
- suffix_len = strlen(suffix);
+ prefix = word;
+ prefix_len = (size_t)(brace - prefix);
+ suffix = middle_end + 1;
+ suffix_len = strlen(suffix);
- /* Split the middle into pieces, separated by commas. */
+ /* Split the middle into pieces, separated by commas. */
- piece = middle;
- while (piece < middle_end + 1) {
- const char *piece_end = separator_comma(piece);
- size_t piece_len = (size_t)(piece_end - piece);
+ piece = middle;
+ while (piece < middle_end + 1) {
+ const char *piece_end = separator_comma(piece);
+ size_t piece_len = (size_t)(piece_end - piece);
- char *file = concat3(prefix, prefix_len, piece, piece_len,
- suffix, suffix_len);
+ char *file = concat3(prefix, prefix_len, piece, piece_len,
+ suffix, suffix_len);
- if (contains_wildcard(file)) {
- Dir_Expand(file, path, expansions);
- free(file);
- } else {
- Lst_Append(expansions, file);
- }
+ if (contains_wildcard(file)) {
+ Dir_Expand(file, path, expansions);
+ free(file);
+ } else {
+ Lst_Append(expansions, file);
+ }
- piece = piece_end + 1; /* skip over the comma or closing brace */
- }
+ /* skip over the comma or closing brace */
+ piece = piece_end + 1;
+ }
}
@@ -726,27 +813,28 @@ DirExpandCurly(const char *word, const char *brace, SearchPath *path,
static void
DirExpandPath(const char *word, SearchPath *path, StringList *expansions)
{
- SearchPathNode *ln;
- for (ln = path->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- DirMatchFiles(word, dir, expansions);
- }
+ SearchPathNode *ln;
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ DirMatchFiles(word, dir, expansions);
+ }
}
static void
PrintExpansions(StringList *expansions)
{
- const char *sep = "";
- StringListNode *ln;
- for (ln = expansions->first; ln != NULL; ln = ln->next) {
- const char *word = ln->datum;
- debug_printf("%s%s", sep, word);
- sep = " ";
- }
- debug_printf("\n");
+ const char *sep = "";
+ StringListNode *ln;
+ for (ln = expansions->first; ln != NULL; ln = ln->next) {
+ const char *word = ln->datum;
+ debug_printf("%s%s", sep, word);
+ sep = " ";
+ }
+ debug_printf("\n");
}
-/* Expand the given word into a list of words by globbing it, looking in the
+/*
+ * Expand the given word into a list of words by globbing it, looking in the
* directories on the given search path.
*
* Input:
@@ -757,185 +845,214 @@ PrintExpansions(StringList *expansions)
void
Dir_Expand(const char *word, SearchPath *path, StringList *expansions)
{
- const char *cp;
+ const char *cp;
+
+ assert(path != NULL);
+ assert(expansions != NULL);
+
+ DEBUG1(DIR, "Expanding \"%s\"... ", word);
- assert(path != NULL);
- assert(expansions != NULL);
+ cp = strchr(word, '{');
+ if (cp != NULL) {
+ DirExpandCurly(word, cp, path, expansions);
+ goto done;
+ }
- DIR_DEBUG1("Expanding \"%s\"... ", word);
+ /* At this point, the word does not contain '{'. */
- cp = strchr(word, '{');
- if (cp) {
- DirExpandCurly(word, cp, path, expansions);
- } else {
cp = strchr(word, '/');
- if (cp) {
- /*
- * The thing has a directory component -- find the first wildcard
- * in the string.
- */
- for (cp = word; *cp; cp++) {
- if (*cp == '?' || *cp == '[' || *cp == '*') {
- break;
- }
- }
+ if (cp == NULL) {
+ /* The word has no directory component. */
+ /* First the files in dot. */
+ DirMatchFiles(word, dot, expansions);
- if (*cp != '\0') {
+ /* Then the files in every other directory on the path. */
+ DirExpandPath(word, path, expansions);
+ goto done;
+ }
+
+ /* At this point, the word has a directory component. */
+
+ /* Find the first wildcard in the word. */
+ for (cp = word; *cp != '\0'; cp++)
+ if (*cp == '?' || *cp == '[' || *cp == '*')
+ break;
+
+ if (*cp == '\0') {
/*
- * Back up to the start of the component
+ * No directory component and no wildcard at all -- this
+ * should never happen as in such a simple case there is no
+ * need to expand anything.
*/
- while (cp > word && *cp != '/') {
- cp--;
- }
- if (cp != word) {
- char *prefix = bmake_strsedup(word, cp + 1);
- /*
- * If the glob isn't in the first component, try and find
- * all the components up to the one with a wildcard.
- */
- char *dirpath = Dir_FindFile(prefix, path);
- free(prefix);
- /*
- * dirpath is null if can't find the leading component
- * XXX: Dir_FindFile won't find internal components.
- * i.e. if the path contains ../Etc/Object and we're
- * looking for Etc, it won't be found. Ah well.
- * Probably not important.
- */
- if (dirpath != NULL) {
- char *dp = &dirpath[strlen(dirpath) - 1];
- if (*dp == '/')
- *dp = '\0';
- path = Lst_New();
- (void)Dir_AddDir(path, dirpath);
- DirExpandPath(cp + 1, path, expansions);
- Lst_Free(path);
- }
- } else {
- /*
- * Start the search from the local directory
- */
- DirExpandPath(word, path, expansions);
- }
- } else {
+ DirExpandPath(word, path, expansions);
+ goto done;
+ }
+
+ /* Back up to the start of the component containing the wildcard. */
+ /* XXX: This handles '///' and '/' differently. */
+ while (cp > word && *cp != '/')
+ cp--;
+
+ if (cp == word) {
+ /* The first component contains the wildcard. */
+ /* Start the search from the local directory */
+ DirExpandPath(word, path, expansions);
+ goto done;
+ }
+
+ {
+ char *prefix = bmake_strsedup(word, cp + 1);
/*
- * Return the file -- this should never happen.
+ * The wildcard isn't in the first component.
+ * Find all the components up to the one with the wildcard.
*/
- DirExpandPath(word, path, expansions);
- }
- } else {
- /*
- * First the files in dot
- */
- DirMatchFiles(word, dot, expansions);
+ /*
+ * XXX: Check the "the directory is added to the path" part.
+ * It is probably surprising that the directory before a
+ * wildcard gets added to the path.
+ */
+ /*
+ * XXX: Only the first match of the prefix in the path is
+ * taken, any others are ignored. The expectation may be
+ * that the pattern is expanded in the whole path.
+ */
+ char *dirpath = Dir_FindFile(prefix, path);
+ free(prefix);
+
+ /*
+ * dirpath is null if can't find the leading component
+ * XXX: Dir_FindFile won't find internal components.
+ * i.e. if the path contains ../Etc/Object and we're
+ * looking for Etc, it won't be found. Ah well.
+ * Probably not important.
+ * XXX: Check whether the above comment is still true.
+ */
+ if (dirpath != NULL) {
+ SearchPath *partPath;
+
+ char *end = &dirpath[strlen(dirpath) - 1];
+ /* XXX: What about multiple trailing slashes? */
+ if (*end == '/')
+ *end = '\0';
- /*
- * Then the files in every other directory on the path.
- */
- DirExpandPath(word, path, expansions);
+ partPath = SearchPath_New();
+ (void)Dir_AddDir(partPath, dirpath);
+ DirExpandPath(cp + 1, partPath, expansions);
+ SearchPath_Free(partPath);
+ }
}
- }
- if (DEBUG(DIR))
- PrintExpansions(expansions);
+
+done:
+ if (DEBUG(DIR))
+ PrintExpansions(expansions);
}
-/* Find if the file with the given name exists in the given path.
- * Return the freshly allocated path to the file, or NULL. */
+/*
+ * Find if the file with the given name exists in the given path.
+ * Return the freshly allocated path to the file, or NULL.
+ */
static char *
DirLookup(CachedDir *dir, const char *base)
{
- char *file; /* the current filename to check */
+ char *file; /* the current filename to check */
- DIR_DEBUG1(" %s ...\n", dir->name);
+ DEBUG1(DIR, " %s ...\n", dir->name);
- if (HashTable_FindEntry(&dir->files, base) == NULL)
- return NULL;
+ if (!HashSet_Contains(&dir->files, base))
+ return NULL;
- file = str_concat3(dir->name, "/", base);
- DIR_DEBUG1(" returning %s\n", file);
- dir->hits++;
- hits++;
- return file;
+ file = str_concat3(dir->name, "/", base);
+ DEBUG1(DIR, " returning %s\n", file);
+ dir->hits++;
+ hits++;
+ return file;
}
-/* Find if the file with the given name exists in the given directory.
- * Return the freshly allocated path to the file, or NULL. */
+/*
+ * Find if the file with the given name exists in the given directory.
+ * Return the freshly allocated path to the file, or NULL.
+ */
static char *
DirLookupSubdir(CachedDir *dir, const char *name)
{
- struct cached_stat cst;
- char *file = dir == dot ? bmake_strdup(name)
- : str_concat3(dir->name, "/", name);
+ struct cached_stat cst;
+ char *file = dir == dot ? bmake_strdup(name)
+ : str_concat3(dir->name, "/", name);
- DIR_DEBUG1("checking %s ...\n", file);
+ DEBUG1(DIR, "checking %s ...\n", file);
- if (cached_stat(file, &cst) == 0) {
- nearmisses++;
- return file;
- }
- free(file);
- return NULL;
+ if (cached_stat(file, &cst) == 0) {
+ nearmisses++;
+ return file;
+ }
+ free(file);
+ return NULL;
}
-/* Find if the file with the given name exists in the given path.
+/*
+ * Find if the file with the given name exists in the given path.
* Return the freshly allocated path to the file, the empty string, or NULL.
* Returning the empty string means that the search should be terminated.
*/
static char *
DirLookupAbs(CachedDir *dir, const char *name, const char *cp)
{
- const char *dnp; /* pointer into dir->name */
- const char *np; /* pointer into name */
+ const char *dnp; /* pointer into dir->name */
+ const char *np; /* pointer into name */
- DIR_DEBUG1(" %s ...\n", dir->name);
+ DEBUG1(DIR, " %s ...\n", dir->name);
- /*
- * If the file has a leading path component and that component
- * exactly matches the entire name of the current search
- * directory, we can attempt another cache lookup. And if we don't
- * have a hit, we can safely assume the file does not exist at all.
- */
- for (dnp = dir->name, np = name; *dnp != '\0' && *dnp == *np; dnp++, np++)
- continue;
- if (*dnp != '\0' || np != cp - 1)
- return NULL;
+ /*
+ * If the file has a leading path component and that component
+ * exactly matches the entire name of the current search
+ * directory, we can attempt another cache lookup. And if we don't
+ * have a hit, we can safely assume the file does not exist at all.
+ */
+ for (dnp = dir->name, np = name;
+ *dnp != '\0' && *dnp == *np; dnp++, np++)
+ continue;
+ if (*dnp != '\0' || np != cp - 1)
+ return NULL;
- if (HashTable_FindEntry(&dir->files, cp) == NULL) {
- DIR_DEBUG0(" must be here but isn't -- returning\n");
- return bmake_strdup(""); /* to terminate the search */
- }
+ if (!HashSet_Contains(&dir->files, cp)) {
+ DEBUG0(DIR, " must be here but isn't -- returning\n");
+ return bmake_strdup(""); /* to terminate the search */
+ }
- dir->hits++;
- hits++;
- DIR_DEBUG1(" returning %s\n", name);
- return bmake_strdup(name);
+ dir->hits++;
+ hits++;
+ DEBUG1(DIR, " returning %s\n", name);
+ return bmake_strdup(name);
}
-/* Find the file given on "." or curdir.
- * Return the freshly allocated path to the file, or NULL. */
+/*
+ * Find the file given on "." or curdir.
+ * Return the freshly allocated path to the file, or NULL.
+ */
static char *
DirFindDot(const char *name, const char *base)
{
- if (HashTable_FindEntry(&dot->files, base) != NULL) {
- DIR_DEBUG0(" in '.'\n");
- hits++;
- dot->hits++;
- return bmake_strdup(name);
- }
+ if (HashSet_Contains(&dot->files, base)) {
+ DEBUG0(DIR, " in '.'\n");
+ hits++;
+ dot->hits++;
+ return bmake_strdup(name);
+ }
- if (cur != NULL && HashTable_FindEntry(&cur->files, base) != NULL) {
- DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name);
- hits++;
- cur->hits++;
- return str_concat3(cur->name, "/", base);
- }
+ if (cur != NULL && HashSet_Contains(&cur->files, base)) {
+ DEBUG1(DIR, " in ${.CURDIR} = %s\n", cur->name);
+ hits++;
+ cur->hits++;
+ return str_concat3(cur->name, "/", base);
+ }
- return NULL;
+ return NULL;
}
-/* Find the file with the given name along the given search path.
+/*
+ * Find the file with the given name along the given search path.
*
* If the file is found in a directory that is not on the path
* already (either 'name' is absolute or it is a relative path
@@ -954,250 +1071,244 @@ DirFindDot(const char *name, const char *base)
char *
Dir_FindFile(const char *name, SearchPath *path)
{
- SearchPathNode *ln;
- char *file; /* the current filename to check */
- const char *base; /* Terminal name of file */
- Boolean hasLastDot = FALSE; /* true if we should search dot last */
- Boolean hasSlash; /* true if 'name' contains a / */
- struct cached_stat cst; /* Buffer for stat, if necessary */
- const char *trailing_dot = ".";
+ char *file; /* the current filename to check */
+ Boolean seenDotLast = FALSE; /* true if we should search dot last */
+ struct cached_stat cst; /* Buffer for stat, if necessary */
+ const char *trailing_dot = ".";
+ const char *base = str_basename(name);
- /*
- * Find the final component of the name and note whether it has a
- * slash in it (the name, I mean)
- */
- base = strrchr(name, '/');
- if (base) {
- hasSlash = TRUE;
- base++;
- } else {
- hasSlash = FALSE;
- base = name;
- }
+ DEBUG1(DIR, "Searching for %s ...", name);
- DIR_DEBUG1("Searching for %s ...", name);
-
- if (path == NULL) {
- DIR_DEBUG0("couldn't open path, file not found\n");
- misses++;
- return NULL;
- }
+ if (path == NULL) {
+ DEBUG0(DIR, "couldn't open path, file not found\n");
+ misses++;
+ return NULL;
+ }
- if ((ln = path->first) != NULL) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast) {
- hasLastDot = TRUE;
- DIR_DEBUG0("[dot last]...");
+ if (path->first != NULL) {
+ CachedDir *dir = path->first->datum;
+ if (dir == dotLast) {
+ seenDotLast = TRUE;
+ DEBUG0(DIR, "[dot last]...");
+ }
}
- }
- DIR_DEBUG0("\n");
+ DEBUG0(DIR, "\n");
- /*
- * If there's no leading directory components or if the leading
- * directory component is exactly `./', consult the cached contents
- * of each of the directories on the search path.
- */
- if (!hasSlash || (base - name == 2 && *name == '.')) {
/*
- * We look through all the directories on the path seeking one which
- * contains the final component of the given name. If such a beast
- * is found, we concatenate the directory name and the final
- * component and return the resulting string. If we don't find any
- * such thing, we go on to phase two...
- *
- * No matter what, we always look for the file in the current
- * directory before anywhere else (unless we found the magic
- * DOTLAST path, in which case we search it last) and we *do not*
- * add the ./ to it if it exists.
- * This is so there are no conflicts between what the user
- * specifies (fish.c) and what pmake finds (./fish.c).
+ * If there's no leading directory components or if the leading
+ * directory component is exactly `./', consult the cached contents
+ * of each of the directories on the search path.
*/
- if (!hasLastDot && (file = DirFindDot(name, base)) != NULL)
- return file;
+ if (base == name || (base - name == 2 && *name == '.')) {
+ SearchPathNode *ln;
- for (; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast)
- continue;
- if ((file = DirLookup(dir, base)) != NULL)
- return file;
- }
+ /*
+ * We look through all the directories on the path seeking one
+ * which contains the final component of the given name. If
+ * such a beast is found, we concatenate the directory name
+ * and the final component and return the resulting string.
+ * If we don't find any such thing, we go on to phase two.
+ *
+ * No matter what, we always look for the file in the current
+ * directory before anywhere else (unless we found the magic
+ * DOTLAST path, in which case we search it last) and we *do
+ * not* add the ./ to it if it exists.
+ * This is so there are no conflicts between what the user
+ * specifies (fish.c) and what pmake finds (./fish.c).
+ */
+ if (!seenDotLast && (file = DirFindDot(name, base)) != NULL)
+ return file;
- if (hasLastDot && (file = DirFindDot(name, base)) != NULL)
- return file;
- }
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ if (dir == dotLast)
+ continue;
+ if ((file = DirLookup(dir, base)) != NULL)
+ return file;
+ }
- /*
- * We didn't find the file on any directory in the search path.
- * If the name doesn't contain a slash, that means it doesn't exist.
- * If it *does* contain a slash, however, there is still hope: it
- * could be in a subdirectory of one of the members of the search
- * path. (eg. /usr/include and sys/types.h. The above search would
- * fail to turn up types.h in /usr/include, but it *is* in
- * /usr/include/sys/types.h).
- * [ This no longer applies: If we find such a beast, we assume there
- * will be more (what else can we assume?) and add all but the last
- * component of the resulting name onto the search path (at the
- * end).]
- * This phase is only performed if the file is *not* absolute.
- */
- if (!hasSlash) {
- DIR_DEBUG0(" failed.\n");
- misses++;
- return NULL;
- }
+ if (seenDotLast && (file = DirFindDot(name, base)) != NULL)
+ return file;
+ }
- if (*base == '\0') {
- /* we were given a trailing "/" */
- base = trailing_dot;
- }
+ /*
+ * We didn't find the file on any directory in the search path.
+ * If the name doesn't contain a slash, that means it doesn't exist.
+ * If it *does* contain a slash, however, there is still hope: it
+ * could be in a subdirectory of one of the members of the search
+ * path. (eg. /usr/include and sys/types.h. The above search would
+ * fail to turn up types.h in /usr/include, but it *is* in
+ * /usr/include/sys/types.h).
+ * [ This no longer applies: If we find such a beast, we assume there
+ * will be more (what else can we assume?) and add all but the last
+ * component of the resulting name onto the search path (at the
+ * end).]
+ * This phase is only performed if the file is *not* absolute.
+ */
+ if (base == name) {
+ DEBUG0(DIR, " failed.\n");
+ misses++;
+ return NULL;
+ }
- if (name[0] != '/') {
- Boolean checkedDot = FALSE;
+ if (*base == '\0') {
+ /* we were given a trailing "/" */
+ base = trailing_dot;
+ }
- DIR_DEBUG0(" Trying subdirectories...\n");
+ if (name[0] != '/') {
+ SearchPathNode *ln;
+ Boolean checkedDot = FALSE;
- if (!hasLastDot) {
- if (dot) {
- checkedDot = TRUE;
- if ((file = DirLookupSubdir(dot, name)) != NULL)
- return file;
- }
- if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
- return file;
- }
+ DEBUG0(DIR, " Trying subdirectories...\n");
- for (ln = path->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast)
- continue;
- if (dir == dot) {
- if (checkedDot)
- continue;
- checkedDot = TRUE;
- }
- if ((file = DirLookupSubdir(dir, name)) != NULL)
- return file;
- }
+ if (!seenDotLast) {
+ if (dot != NULL) {
+ checkedDot = TRUE;
+ if ((file = DirLookupSubdir(dot, name)) != NULL)
+ return file;
+ }
+ if (cur != NULL &&
+ (file = DirLookupSubdir(cur, name)) != NULL)
+ return file;
+ }
- if (hasLastDot) {
- if (dot && !checkedDot) {
- checkedDot = TRUE;
- if ((file = DirLookupSubdir(dot, name)) != NULL)
- return file;
- }
- if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
- return file;
- }
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ if (dir == dotLast)
+ continue;
+ if (dir == dot) {
+ if (checkedDot)
+ continue;
+ checkedDot = TRUE;
+ }
+ if ((file = DirLookupSubdir(dir, name)) != NULL)
+ return file;
+ }
- if (checkedDot) {
- /*
- * Already checked by the given name, since . was in the path,
- * so no point in proceeding...
- */
- DIR_DEBUG0(" Checked . already, returning NULL\n");
- return NULL;
- }
+ if (seenDotLast) {
+ if (dot != NULL && !checkedDot) {
+ checkedDot = TRUE;
+ if ((file = DirLookupSubdir(dot, name)) != NULL)
+ return file;
+ }
+ if (cur != NULL &&
+ (file = DirLookupSubdir(cur, name)) != NULL)
+ return file;
+ }
- } else { /* name[0] == '/' */
+ if (checkedDot) {
+ /*
+ * Already checked by the given name, since . was in
+ * the path, so no point in proceeding.
+ */
+ DEBUG0(DIR, " Checked . already, returning NULL\n");
+ return NULL;
+ }
- /*
- * For absolute names, compare directory path prefix against the
- * the directory path of each member on the search path for an exact
- * match. If we have an exact match on any member of the search path,
- * use the cached contents of that member to lookup the final file
- * component. If that lookup fails we can safely assume that the
- * file does not exist at all. This is signified by DirLookupAbs()
- * returning an empty string.
- */
- DIR_DEBUG0(" Trying exact path matches...\n");
+ } else { /* name[0] == '/' */
+ SearchPathNode *ln;
- if (!hasLastDot && cur &&
- ((file = DirLookupAbs(cur, name, base)) != NULL)) {
- if (file[0] == '\0') {
- free(file);
- return NULL;
- }
- return file;
- }
+ /*
+ * For absolute names, compare directory path prefix against
+ * the the directory path of each member on the search path
+ * for an exact match. If we have an exact match on any member
+ * of the search path, use the cached contents of that member
+ * to lookup the final file component. If that lookup fails we
+ * can safely assume that the file does not exist at all.
+ * This is signified by DirLookupAbs() returning an empty
+ * string.
+ */
+ DEBUG0(DIR, " Trying exact path matches...\n");
- for (ln = path->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- if (dir == dotLast)
- continue;
- if ((file = DirLookupAbs(dir, name, base)) != NULL) {
- if (file[0] == '\0') {
- free(file);
- return NULL;
+ if (!seenDotLast && cur != NULL &&
+ ((file = DirLookupAbs(cur, name, base)) != NULL)) {
+ if (file[0] == '\0') {
+ free(file);
+ return NULL;
+ }
+ return file;
}
- return file;
- }
- }
- if (hasLastDot && cur &&
- ((file = DirLookupAbs(cur, name, base)) != NULL)) {
- if (file[0] == '\0') {
- free(file);
- return NULL;
- }
- return file;
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ if (dir == dotLast)
+ continue;
+ if ((file = DirLookupAbs(dir, name, base)) != NULL) {
+ if (file[0] == '\0') {
+ free(file);
+ return NULL;
+ }
+ return file;
+ }
+ }
+
+ if (seenDotLast && cur != NULL &&
+ ((file = DirLookupAbs(cur, name, base)) != NULL)) {
+ if (file[0] == '\0') {
+ free(file);
+ return NULL;
+ }
+ return file;
+ }
}
- }
- /*
- * Didn't find it that way, either. Sigh. Phase 3. Add its directory
- * onto the search path in any case, just in case, then look for the
- * thing in the hash table. If we find it, grand. We return a new
- * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.
- * Note that if the directory holding the file doesn't exist, this will
- * do an extra search of the final directory on the path. Unless something
- * weird happens, this search won't succeed and life will be groovy.
- *
- * Sigh. We cannot add the directory onto the search path because
- * of this amusing case:
- * $(INSTALLDIR)/$(FILE): $(FILE)
- *
- * $(FILE) exists in $(INSTALLDIR) but not in the current one.
- * When searching for $(FILE), we will find it in $(INSTALLDIR)
- * b/c we added it here. This is not good...
- */
+ /*
+ * Didn't find it that way, either. Sigh. Phase 3. Add its directory
+ * onto the search path in any case, just in case, then look for the
+ * thing in the hash table. If we find it, grand. We return a new
+ * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.
+ * Note that if the directory holding the file doesn't exist, this
+ * will do an extra search of the final directory on the path. Unless
+ * something weird happens, this search won't succeed and life will
+ * be groovy.
+ *
+ * Sigh. We cannot add the directory onto the search path because
+ * of this amusing case:
+ * $(INSTALLDIR)/$(FILE): $(FILE)
+ *
+ * $(FILE) exists in $(INSTALLDIR) but not in the current one.
+ * When searching for $(FILE), we will find it in $(INSTALLDIR)
+ * b/c we added it here. This is not good...
+ */
#if 0
- if (base == trailing_dot) {
- base = strrchr(name, '/');
- base++;
- }
- base[-1] = '\0';
- (void)Dir_AddDir(path, name);
- base[-1] = '/';
+ {
+ CachedDir *dir;
+ char *prefix;
- bigmisses++;
- ln = Lst_Last(path);
- if (ln == NULL) {
- return NULL;
- } else {
- dir = LstNode_Datum(ln);
- }
+ if (base == trailing_dot) {
+ base = strrchr(name, '/');
+ base++;
+ }
+ prefix = bmake_strsedup(name, base - 1);
+ (void)Dir_AddDir(path, prefix);
+ free(prefix);
- if (Hash_FindEntry(&dir->files, base) != NULL) {
- return bmake_strdup(name);
- } else {
- return NULL;
- }
+ bigmisses++;
+ if (path->last == NULL)
+ return NULL;
+
+ dir = path->last->datum;
+ if (HashSet_Contains(&dir->files, base))
+ return bmake_strdup(name);
+ return NULL;
+ }
#else
- DIR_DEBUG1(" Looking for \"%s\" ...\n", name);
+ DEBUG1(DIR, " Looking for \"%s\" ...\n", name);
- bigmisses++;
- if (cached_stat(name, &cst) == 0) {
- return bmake_strdup(name);
- }
+ bigmisses++;
+ if (cached_stat(name, &cst) == 0) {
+ return bmake_strdup(name);
+ }
- DIR_DEBUG0(" failed. Returning NULL\n");
- return NULL;
+ DEBUG0(DIR, " failed. Returning NULL\n");
+ return NULL;
#endif
}
-/* Search for a path starting at a given directory and then working our way
+/*
+ * Search for a path starting at a given directory and then working our way
* up towards the root.
*
* Input:
@@ -1210,346 +1321,376 @@ Dir_FindFile(const char *name, SearchPath *path)
char *
Dir_FindHereOrAbove(const char *here, const char *search_path)
{
- struct cached_stat cst;
- char *dirbase, *dirbase_end;
- char *try, *try_end;
+ struct cached_stat cst;
+ char *dirbase, *dirbase_end;
+ char *try, *try_end;
+
+ /* copy out our starting point */
+ dirbase = bmake_strdup(here);
+ dirbase_end = dirbase + strlen(dirbase);
- /* copy out our starting point */
- dirbase = bmake_strdup(here);
- dirbase_end = dirbase + strlen(dirbase);
+ /* loop until we determine a result */
+ for (;;) {
- /* loop until we determine a result */
- for (;;) {
+ /* try and stat(2) it ... */
+ try = str_concat3(dirbase, "/", search_path);
+ if (cached_stat(try, &cst) != -1) {
+ /*
+ * success! if we found a file, chop off
+ * the filename so we return a directory.
+ */
+ if ((cst.cst_mode & S_IFMT) != S_IFDIR) {
+ try_end = try + strlen(try);
+ while (try_end > try && *try_end != '/')
+ try_end--;
+ if (try_end > try)
+ *try_end = '\0'; /* chop! */
+ }
- /* try and stat(2) it ... */
- try = str_concat3(dirbase, "/", search_path);
- if (cached_stat(try, &cst) != -1) {
- /*
- * success! if we found a file, chop off
- * the filename so we return a directory.
- */
- if ((cst.cst_mode & S_IFMT) != S_IFDIR) {
- try_end = try + strlen(try);
- while (try_end > try && *try_end != '/')
- try_end--;
- if (try_end > try)
- *try_end = '\0'; /* chop! */
- }
+ free(dirbase);
+ return try;
+ }
+ free(try);
- free(dirbase);
- return try;
+ /*
+ * nope, we didn't find it. if we used up dirbase we've
+ * reached the root and failed.
+ */
+ if (dirbase_end == dirbase)
+ break; /* failed! */
+
+ /*
+ * truncate dirbase from the end to move up a dir
+ */
+ while (dirbase_end > dirbase && *dirbase_end != '/')
+ dirbase_end--;
+ *dirbase_end = '\0'; /* chop! */
}
- free(try);
+
+ free(dirbase);
+ return NULL;
+}
+
+/*
+ * This is an implied source, and it may have moved,
+ * see if we can find it via the current .PATH
+ */
+static char *
+ResolveMovedDepends(GNode *gn)
+{
+ char *fullName;
+
+ const char *base = str_basename(gn->name);
+ if (base == gn->name)
+ return NULL;
+
+ fullName = Dir_FindFile(base, Suff_FindPath(gn));
+ if (fullName == NULL)
+ return NULL;
/*
- * nope, we didn't find it. if we used up dirbase we've
- * reached the root and failed.
+ * Put the found file in gn->path so that we give that to the compiler.
*/
- if (dirbase_end == dirbase)
- break; /* failed! */
-
/*
- * truncate dirbase from the end to move up a dir
+ * XXX: Better just reset gn->path to NULL; updating it is already done
+ * by Dir_UpdateMTime.
*/
- while (dirbase_end > dirbase && *dirbase_end != '/')
- dirbase_end--;
- *dirbase_end = '\0'; /* chop! */
- }
+ gn->path = bmake_strdup(fullName);
+ if (!Job_RunTarget(".STALE", gn->fname))
+ fprintf(stdout, /* XXX: Why stdout? */
+ "%s: %s, %d: ignoring stale %s for %s, found %s\n",
+ progname, gn->fname, gn->lineno,
+ makeDependfile, gn->name, fullName);
- free(dirbase);
- return NULL;
+ return fullName;
}
-/* Search gn along dirSearchPath and store its modification time in gn->mtime.
+static char *
+ResolveFullName(GNode *gn)
+{
+ char *fullName;
+
+ fullName = gn->path;
+ if (fullName == NULL && !(gn->type & OP_NOPATH)) {
+
+ fullName = Dir_FindFile(gn->name, Suff_FindPath(gn));
+
+ if (fullName == NULL && gn->flags & FROM_DEPEND &&
+ !Lst_IsEmpty(&gn->implicitParents))
+ fullName = ResolveMovedDepends(gn);
+
+ DEBUG2(DIR, "Found '%s' as '%s'\n",
+ gn->name, fullName != NULL ? fullName : "(not found)");
+ }
+
+ if (fullName == NULL)
+ fullName = bmake_strdup(gn->name);
+
+ /* XXX: Is every piece of memory freed as it should? */
+
+ return fullName;
+}
+
+/*
+ * Search gn along dirSearchPath and store its modification time in gn->mtime.
* If no file is found, store 0 instead.
*
- * The found file is stored in gn->path, unless the node already had a path. */
+ * The found file is stored in gn->path, unless the node already had a path.
+ */
void
Dir_UpdateMTime(GNode *gn, Boolean recheck)
{
- char *fullName;
- struct cached_stat cst;
-
- if (gn->type & OP_ARCHV) {
- Arch_UpdateMTime(gn);
- return;
- }
+ char *fullName;
+ struct cached_stat cst;
- if (gn->type & OP_PHONY) {
- gn->mtime = 0;
- return;
- }
+ if (gn->type & OP_ARCHV) {
+ Arch_UpdateMTime(gn);
+ return;
+ }
- if (gn->path == NULL) {
- if (gn->type & OP_NOPATH)
- fullName = NULL;
- else {
- fullName = Dir_FindFile(gn->name, Suff_FindPath(gn));
- if (fullName == NULL && gn->flags & FROM_DEPEND &&
- !Lst_IsEmpty(gn->implicitParents)) {
- char *cp;
+ if (gn->type & OP_PHONY) {
+ gn->mtime = 0;
+ return;
+ }
- cp = strrchr(gn->name, '/');
- if (cp) {
- /*
- * This is an implied source, and it may have moved,
- * see if we can find it via the current .PATH
- */
- cp++;
+ fullName = ResolveFullName(gn);
- fullName = Dir_FindFile(cp, Suff_FindPath(gn));
- if (fullName) {
- /*
- * Put the found file in gn->path
- * so that we give that to the compiler.
- */
- gn->path = bmake_strdup(fullName);
- if (!Job_RunTarget(".STALE", gn->fname))
- fprintf(stdout,
- "%s: %s, %d: ignoring stale %s for %s, "
- "found %s\n", progname, gn->fname,
- gn->lineno,
- makeDependfile, gn->name, fullName);
- }
+ if (cached_stats(fullName, &cst, recheck ? CST_UPDATE : CST_NONE) < 0) {
+ if (gn->type & OP_MEMBER) {
+ if (fullName != gn->path)
+ free(fullName);
+ Arch_UpdateMemberMTime(gn);
+ return;
}
- }
- DIR_DEBUG2("Found '%s' as '%s'\n",
- gn->name, fullName ? fullName : "(not found)");
+
+ cst.cst_mtime = 0;
}
- } else {
- fullName = gn->path;
- }
- if (fullName == NULL)
- fullName = bmake_strdup(gn->name);
+ if (fullName != NULL && gn->path == NULL)
+ gn->path = fullName;
+ /* XXX: else free(fullName)? */
+
+ gn->mtime = cst.cst_mtime;
+}
- if (cached_stats(fullName, &cst, recheck ? CST_UPDATE : CST_NONE) < 0) {
- if (gn->type & OP_MEMBER) {
- if (fullName != gn->path)
- free(fullName);
- Arch_UpdateMemberMTime(gn);
- return;
+/*
+ * Read the directory and add it to the cache in openDirs.
+ * If a path is given, add the directory to that path as well.
+ */
+static CachedDir *
+CacheNewDir(const char *name, SearchPath *path)
+{
+ CachedDir *dir = NULL;
+ DIR *d;
+ struct dirent *dp;
+
+ if ((d = opendir(name)) == NULL) {
+ DEBUG1(DIR, "Caching %s ... not found\n", name);
+ return dir;
}
- cst.cst_mtime = 0;
- }
+ DEBUG1(DIR, "Caching %s ...\n", name);
+
+ dir = CachedDir_New(name);
- if (fullName != NULL && gn->path == NULL)
- gn->path = fullName;
+ while ((dp = readdir(d)) != NULL) {
- gn->mtime = cst.cst_mtime;
+#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
+ /*
+ * The sun directory library doesn't check for a 0 inode
+ * (0-inode slots just take up space), so we have to do
+ * it ourselves.
+ */
+ if (dp->d_fileno == 0)
+ continue;
+#endif /* sun && d_ino */
+
+ (void)HashSet_Add(&dir->files, dp->d_name);
+ }
+ (void)closedir(d);
+
+ OpenDirs_Add(&openDirs, dir);
+ if (path != NULL)
+ Lst_Append(path, CachedDir_Ref(dir));
+
+ DEBUG1(DIR, "Caching %s done\n", name);
+ return dir;
}
-/* Read the list of filenames in the directory and store the result
- * in openDirectories.
+/*
+ * Read the list of filenames in the directory and store the result
+ * in openDirs.
*
* If a path is given, append the directory to that path.
*
* Input:
* path The path to which the directory should be
- * added, or NULL to only add the directory to
- * openDirectories
+ * added, or NULL to only add the directory to openDirs
* name The name of the directory to add.
* The name is not normalized in any way.
+ * Output:
+ * result If no path is given and the directory exists, the
+ * returned CachedDir has a reference count of 0. It
+ * must either be assigned to a variable using
+ * CachedDir_Assign or be appended to a SearchPath using
+ * Lst_Append and CachedDir_Ref.
*/
CachedDir *
Dir_AddDir(SearchPath *path, const char *name)
{
- CachedDir *dir = NULL; /* the added directory */
- DIR *d;
- struct dirent *dp;
- if (path != NULL && strcmp(name, ".DOTLAST") == 0) {
- SearchPathNode *ln;
+ if (path != NULL && strcmp(name, ".DOTLAST") == 0) {
+ SearchPathNode *ln;
- /* XXX: Linear search gets slow with thousands of entries. */
- for (ln = path->first; ln != NULL; ln = ln->next) {
- CachedDir *pathDir = ln->datum;
- if (strcmp(pathDir->name, name) == 0)
- return pathDir;
- }
-
- dotLast->refCount++;
- Lst_Prepend(path, dotLast);
- }
+ /* XXX: Linear search gets slow with thousands of entries. */
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *pathDir = ln->datum;
+ if (strcmp(pathDir->name, name) == 0)
+ return pathDir;
+ }
- if (path != NULL)
- dir = OpenDirs_Find(&openDirs, name);
- if (dir != NULL) {
- if (Lst_FindDatum(path, dir) == NULL) {
- dir->refCount++;
- Lst_Append(path, dir);
+ Lst_Prepend(path, CachedDir_Ref(dotLast));
}
- return dir;
- }
-
- DIR_DEBUG1("Caching %s ...", name);
- if ((d = opendir(name)) != NULL) {
- dir = bmake_malloc(sizeof *dir);
- dir->name = bmake_strdup(name);
- dir->hits = 0;
- dir->refCount = 1;
- HashTable_Init(&dir->files);
-
- while ((dp = readdir(d)) != NULL) {
-#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
- /*
- * The sun directory library doesn't check for a 0 inode
- * (0-inode slots just take up space), so we have to do
- * it ourselves.
- */
- if (dp->d_fileno == 0) {
- continue;
- }
-#endif /* sun && d_ino */
- (void)HashTable_CreateEntry(&dir->files, dp->d_name, NULL);
+ if (path != NULL) {
+ /* XXX: Why is OpenDirs only checked if path != NULL? */
+ CachedDir *dir = OpenDirs_Find(&openDirs, name);
+ if (dir != NULL) {
+ if (Lst_FindDatum(path, dir) == NULL)
+ Lst_Append(path, CachedDir_Ref(dir));
+ return dir;
+ }
}
- (void)closedir(d);
- OpenDirs_Add(&openDirs, dir);
- if (path != NULL)
- Lst_Append(path, dir);
- }
- DIR_DEBUG0("done\n");
- return dir;
+
+ return CacheNewDir(name, path);
}
-/* Return a copy of dirSearchPath, incrementing the reference counts for
- * the contained directories. */
+/*
+ * Return a copy of dirSearchPath, incrementing the reference counts for
+ * the contained directories.
+ */
SearchPath *
Dir_CopyDirSearchPath(void)
{
- SearchPath *path = Lst_New();
- SearchPathNode *ln;
- for (ln = dirSearchPath->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- dir->refCount++;
- Lst_Append(path, dir);
- }
- return path;
+ SearchPath *path = SearchPath_New();
+ SearchPathNode *ln;
+ for (ln = dirSearchPath.first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ Lst_Append(path, CachedDir_Ref(dir));
+ }
+ return path;
}
-/*-
- *-----------------------------------------------------------------------
- * Dir_MakeFlags --
- * Make a string by taking all the directories in the given search
- * path and preceding them by the given flag. Used by the suffix
- * module to create variables for compilers based on suffix search
- * paths.
+/*
+ * Make a string by taking all the directories in the given search path and
+ * preceding them by the given flag. Used by the suffix module to create
+ * variables for compilers based on suffix search paths.
*
* Input:
* flag flag which should precede each directory
* path list of directories
*
* Results:
- * The string mentioned above. Note that there is no space between
- * the given flag and each directory. The empty string is returned if
- * Things don't go well.
- *
- * Side Effects:
- * None
- *-----------------------------------------------------------------------
+ * The string mentioned above. Note that there is no space between the
+ * given flag and each directory. The empty string is returned if things
+ * don't go well.
*/
char *
-Dir_MakeFlags(const char *flag, SearchPath *path)
+SearchPath_ToFlags(const char *flag, SearchPath *path)
{
- Buffer buf;
- SearchPathNode *ln;
+ Buffer buf;
+ SearchPathNode *ln;
- Buf_Init(&buf);
+ Buf_Init(&buf);
- if (path != NULL) {
- for (ln = path->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- Buf_AddStr(&buf, " ");
- Buf_AddStr(&buf, flag);
- Buf_AddStr(&buf, dir->name);
+ if (path != NULL) {
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ Buf_AddStr(&buf, " ");
+ Buf_AddStr(&buf, flag);
+ Buf_AddStr(&buf, dir->name);
+ }
}
- }
- return Buf_Destroy(&buf, FALSE);
+ return Buf_Destroy(&buf, FALSE);
}
-/* Nuke a directory descriptor, if possible. Callback procedure for the
- * suffixes module when destroying a search path.
- *
- * Input:
- * dirp The directory descriptor to nuke
- */
+/* Free the search path and all directories mentioned in it. */
void
-Dir_Destroy(void *dirp)
+SearchPath_Free(SearchPath *path)
{
- CachedDir *dir = dirp;
- dir->refCount--;
-
- if (dir->refCount == 0) {
- OpenDirs_Remove(&openDirs, dir->name);
+ SearchPathNode *ln;
- HashTable_Done(&dir->files);
- free(dir->name);
- free(dir);
- }
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ CachedDir_Unref(dir);
+ }
+ Lst_Free(path);
}
-/* Clear out all elements from the given search path.
- * The path is set to the empty list but is not destroyed. */
+/*
+ * Clear out all elements from the given search path.
+ * The path is set to the empty list but is not destroyed.
+ */
void
-Dir_ClearPath(SearchPath *path)
+SearchPath_Clear(SearchPath *path)
{
- while (!Lst_IsEmpty(path)) {
- CachedDir *dir = Lst_Dequeue(path);
- Dir_Destroy(dir);
- }
+ while (!Lst_IsEmpty(path)) {
+ CachedDir *dir = Lst_Dequeue(path);
+ CachedDir_Unref(dir);
+ }
}
-/* Concatenate two paths, adding the second to the end of the first,
- * skipping duplicates. */
+/*
+ * Concatenate two paths, adding the second to the end of the first,
+ * skipping duplicates.
+ */
void
-Dir_Concat(SearchPath *dst, SearchPath *src)
+SearchPath_AddAll(SearchPath *dst, SearchPath *src)
{
- SearchPathNode *ln;
+ SearchPathNode *ln;
- for (ln = src->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- if (Lst_FindDatum(dst, dir) == NULL) {
- dir->refCount++;
- Lst_Append(dst, dir);
+ for (ln = src->first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ if (Lst_FindDatum(dst, dir) == NULL)
+ Lst_Append(dst, CachedDir_Ref(dir));
}
- }
}
static int
percentage(int num, int den)
{
- return den != 0 ? num * 100 / den : 0;
+ return den != 0 ? num * 100 / den : 0;
}
/********** DEBUG INFO **********/
void
Dir_PrintDirectories(void)
{
- CachedDirListNode *ln;
+ CachedDirListNode *ln;
- debug_printf("#*** Directory Cache:\n");
- debug_printf("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n",
- hits, misses, nearmisses, bigmisses,
- percentage(hits, hits + bigmisses + nearmisses));
- debug_printf("# %-20s referenced\thits\n", "directory");
+ debug_printf("#*** Directory Cache:\n");
+ debug_printf(
+ "# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n",
+ hits, misses, nearmisses, bigmisses,
+ percentage(hits, hits + bigmisses + nearmisses));
+ debug_printf("# refs hits directory\n");
- for (ln = openDirs.list->first; ln != NULL; ln = ln->next) {
- CachedDir *dir = ln->datum;
- debug_printf("# %-20s %10d\t%4d\n", dir->name, dir->refCount,
- dir->hits);
- }
+ for (ln = openDirs.list.first; ln != NULL; ln = ln->next) {
+ CachedDir *dir = ln->datum;
+ debug_printf("# %4d %4d %s\n",
+ dir->refCount, dir->hits, dir->name);
+ }
}
void
-Dir_PrintPath(SearchPath *path)
+SearchPath_Print(SearchPath *path)
{
- SearchPathNode *node;
- for (node = path->first; node != NULL; node = node->next) {
- const CachedDir *dir = node->datum;
- debug_printf("%s ", dir->name);
- }
+ SearchPathNode *ln;
+
+ for (ln = path->first; ln != NULL; ln = ln->next) {
+ const CachedDir *dir = ln->datum;
+ debug_printf("%s ", dir->name);
+ }
}