diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 1160 |
1 files changed, 536 insertions, 624 deletions
@@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.76 2020/07/03 08:13:23 rillig Exp $ */ +/* $NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: dir.c,v 1.76 2020/07/03 08:13:23 rillig Exp $"; +static char rcsid[] = "$NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 rillig Exp $"; #else #include <sys/cdefs.h> #ifndef lint #if 0 static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else -__RCSID("$NetBSD: dir.c,v 1.76 2020/07/03 08:13:23 rillig Exp $"); +__RCSID("$NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 rillig Exp $"); #endif #endif /* not lint */ #endif @@ -143,10 +143,20 @@ __RCSID("$NetBSD: dir.c,v 1.76 2020/07/03 08:13:23 rillig Exp $"); #include <stdio.h> #include "make.h" -#include "hash.h" #include "dir.h" #include "job.h" + +#define DIR_DEBUG0(fmt) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt) + +#define DIR_DEBUG1(fmt, arg1) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt, arg1) + +#define DIR_DEBUG2(fmt, arg1, arg2) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2) + + /* * A search path consists of a Lst of Path structures. A Path structure * has in it the name of the directory and a hash table of all the files @@ -217,37 +227,35 @@ __RCSID("$NetBSD: dir.c,v 1.76 2020/07/03 08:13:23 rillig Exp $"); * in a cache for when Dir_MTime was actually called. */ -Lst dirSearchPath; /* main search path */ +Lst dirSearchPath; /* main search path */ -static Lst openDirectories; /* the list of all open directories */ +static Lst openDirectories; /* the list of all open directories */ /* * Variables for gathering statistics on the efficiency of the hashing * mechanism. */ -static int hits, /* Found in directory cache */ - misses, /* Sad, but not evil misses */ - nearmisses, /* Found under search path */ - bigmisses; /* Sought by itself */ - -static Path *dot; /* contents of current directory */ -static Path *cur; /* contents of current directory, if not dot */ -static Path *dotLast; /* a fake path entry indicating we need to - * look for . last */ -static Hash_Table mtimes; /* 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 Hash_Table lmtimes; /* same as mtimes but for lstat */ - -static int DirFindName(const void *, const void *); -static int DirMatchFiles(const char *, Path *, Lst); +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 Path *dot; /* contents of current directory */ +static Path *cur; /* contents of current directory, if not dot */ +static Path *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 Hash_Table mtimes; + +static Hash_Table lmtimes; /* same as mtimes but for lstat */ + static void DirExpandCurly(const char *, const char *, Lst, Lst); static void DirExpandInt(const char *, Lst, Lst); static int DirPrintWord(void *, void *); @@ -259,23 +267,28 @@ static char *DirLookupAbs(Path *, const char *, const char *); /* - * We use stat(2) a lot, cache the results + * We use stat(2) a lot, cache the results. * mtime and mode are all we care about. */ struct cache_st { - time_t lmtime; /* lstat */ - time_t mtime; /* stat */ - mode_t mode; + time_t lmtime; /* lstat */ + time_t mtime; /* stat */ + mode_t mode; }; /* minimize changes below */ -#define CST_LSTAT 1 -#define CST_UPDATE 2 +typedef enum { + CST_LSTAT = 0x01, /* call lstat(2) instead of stat(2) */ + CST_UPDATE = 0x02 /* ignore existing cached entry */ +} CachedStatsFlags; +/* Returns 0 and the result of stat(2) or lstat(2) in *mst, or -1 on error. */ static int -cached_stats(Hash_Table *htp, const char *pathname, struct stat *st, int flags) +cached_stats(Hash_Table *htp, const char *pathname, struct make_stat *mst, + CachedStatsFlags flags) { Hash_Entry *entry; + struct stat sys_st; struct cache_st *cst; int rc; @@ -284,83 +297,74 @@ cached_stats(Hash_Table *htp, const char *pathname, struct stat *st, int flags) entry = Hash_FindEntry(htp, pathname); - if (entry && (flags & CST_UPDATE) == 0) { - cst = entry->clientPtr; + if (entry && !(flags & CST_UPDATE)) { + cst = Hash_GetValue(entry); - memset(st, 0, sizeof(*st)); - st->st_mode = cst->mode; - st->st_mtime = (flags & CST_LSTAT) ? cst->lmtime : cst->mtime; - if (st->st_mtime) { - if (DEBUG(DIR)) { - fprintf(debug_file, "Using cached time %s for %s\n", - Targ_FmtTime(st->st_mtime), pathname); - } + mst->mst_mode = cst->mode; + mst->mst_mtime = (flags & CST_LSTAT) ? cst->lmtime : cst->mtime; + if (mst->mst_mtime) { + DIR_DEBUG2("Using cached time %s for %s\n", + Targ_FmtTime(mst->mst_mtime), pathname); return 0; } } - rc = (flags & CST_LSTAT) ? lstat(pathname, st) : stat(pathname, st); + rc = (flags & CST_LSTAT) + ? lstat(pathname, &sys_st) + : stat(pathname, &sys_st); if (rc == -1) return -1; - if (st->st_mtime == 0) - 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 */ + + mst->mst_mode = sys_st.st_mode; + mst->mst_mtime = sys_st.st_mtime; - if (!entry) + if (entry == NULL) entry = Hash_CreateEntry(htp, pathname, NULL); - if (!entry->clientPtr) { - entry->clientPtr = bmake_malloc(sizeof(*cst)); - memset(entry->clientPtr, 0, sizeof(*cst)); + if (Hash_GetValue(entry) == NULL) { + Hash_SetValue(entry, bmake_malloc(sizeof(*cst))); + memset(Hash_GetValue(entry), 0, sizeof(*cst)); } - cst = entry->clientPtr; - if ((flags & CST_LSTAT)) { - cst->lmtime = st->st_mtime; + cst = Hash_GetValue(entry); + if (flags & CST_LSTAT) { + cst->lmtime = sys_st.st_mtime; } else { - cst->mtime = st->st_mtime; - } - cst->mode = st->st_mode; - if (DEBUG(DIR)) { - fprintf(debug_file, " Caching %s for %s\n", - Targ_FmtTime(st->st_mtime), pathname); + cst->mtime = sys_st.st_mtime; } + cst->mode = sys_st.st_mode; + DIR_DEBUG2(" Caching %s for %s\n", + Targ_FmtTime(sys_st.st_mtime), pathname); return 0; } int -cached_stat(const char *pathname, void *st) +cached_stat(const char *pathname, struct make_stat *st) { return cached_stats(&mtimes, pathname, st, 0); } int -cached_lstat(const char *pathname, void *st) +cached_lstat(const char *pathname, struct make_stat *st) { return cached_stats(&lmtimes, pathname, st, CST_LSTAT); } -/*- - *----------------------------------------------------------------------- - * Dir_Init -- - * initialize things for this module - * - * Results: - * none - * - * Side Effects: - * some directories may be opened. - *----------------------------------------------------------------------- - */ +/* Initialize things for this module. */ void -Dir_Init(const char *cdname) +Dir_Init(void) +{ + dirSearchPath = Lst_Init(); + openDirectories = Lst_Init(); + Hash_InitTable(&mtimes, 0); + Hash_InitTable(&lmtimes, 0); +} + +void +Dir_InitDir(const char *cdname) { - if (!cdname) { - dirSearchPath = Lst_Init(FALSE); - openDirectories = Lst_Init(FALSE); - Hash_InitTable(&mtimes, 0); - Hash_InitTable(&lmtimes, 0); - return; - } Dir_InitCur(cdname); dotLast = bmake_malloc(sizeof(Path)); @@ -371,7 +375,7 @@ Dir_Init(const char *cdname) } /* - * Called by Dir_Init() and whenever .CURDIR is assigned to. + * Called by Dir_InitDir and whenever .CURDIR is assigned to. */ void Dir_InitCur(const char *cdname) @@ -397,18 +401,8 @@ Dir_InitCur(const char *cdname) } } -/*- - *----------------------------------------------------------------------- - * Dir_InitDot -- - * (re)initialize "dot" (current/object directory) path hash - * - * Results: - * none - * - * Side Effects: - * some directories may be opened. - *----------------------------------------------------------------------- - */ +/* (Re)initialize "dot" (current/object directory) path hash. + * Some directories may be opened. */ void Dir_InitDot(void) { @@ -416,8 +410,8 @@ Dir_InitDot(void) LstNode ln; /* Remove old entry from openDirectories, but do not destroy. */ - ln = Lst_Member(openDirectories, dot); - (void)Lst_Remove(openDirectories, ln); + ln = Lst_FindDatum(openDirectories, dot); + Lst_Remove(openDirectories, ln); } dot = Dir_AddDir(NULL, "."); @@ -432,21 +426,10 @@ Dir_InitDot(void) * to make sure it's not destroyed. */ dot->refCount += 1; - Dir_SetPATH(); /* initialize */ + Dir_SetPATH(); /* initialize */ } -/*- - *----------------------------------------------------------------------- - * Dir_End -- - * cleanup things for this module - * - * Results: - * none - * - * Side Effects: - * none - *----------------------------------------------------------------------- - */ +/* Clean up things for this module. */ void Dir_End(void) { @@ -460,9 +443,9 @@ Dir_End(void) Dir_Destroy(dotLast); Dir_Destroy(dot); Dir_ClearPath(dirSearchPath); - Lst_Destroy(dirSearchPath, NULL); + Lst_Free(dirSearchPath); Dir_ClearPath(openDirectories); - Lst_Destroy(openDirectories, NULL); + Lst_Free(openDirectories); Hash_DeleteTable(&mtimes); #endif } @@ -475,122 +458,100 @@ Dir_End(void) void Dir_SetPATH(void) { - LstNode ln; /* a list element */ + LstNode ln; /* a list element */ Path *p; - Boolean hasLastDot = FALSE; /* true we should search dot last */ + Boolean hasLastDot = FALSE; /* true if we should search dot last */ Var_Delete(".PATH", VAR_GLOBAL); - if (Lst_Open(dirSearchPath) == SUCCESS) { - if ((ln = Lst_First(dirSearchPath)) != NULL) { - p = (Path *)Lst_Datum(ln); - if (p == dotLast) { - hasLastDot = TRUE; - Var_Append(".PATH", dotLast->name, VAR_GLOBAL); - } + Lst_Open(dirSearchPath); + if ((ln = Lst_First(dirSearchPath)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) { + hasLastDot = 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 (!hasLastDot) { + if (dot) + Var_Append(".PATH", dot->name, VAR_GLOBAL); + if (cur) + Var_Append(".PATH", cur->name, VAR_GLOBAL); + } - while ((ln = Lst_Next(dirSearchPath)) != NULL) { - p = (Path *)Lst_Datum(ln); - if (p == dotLast) - continue; - if (p == dot && hasLastDot) - continue; - Var_Append(".PATH", p->name, VAR_GLOBAL); - } + while ((ln = Lst_Next(dirSearchPath)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if (p == dot && hasLastDot) + continue; + Var_Append(".PATH", p->name, VAR_GLOBAL); + } - if (hasLastDot) { - if (dot) - Var_Append(".PATH", dot->name, VAR_GLOBAL); - if (cur) - Var_Append(".PATH", cur->name, VAR_GLOBAL); - } - Lst_Close(dirSearchPath); + if (hasLastDot) { + if (dot) + Var_Append(".PATH", dot->name, VAR_GLOBAL); + if (cur) + Var_Append(".PATH", cur->name, VAR_GLOBAL); } + Lst_Close(dirSearchPath); } -/*- - *----------------------------------------------------------------------- - * DirFindName -- - * See if the Path structure describes the same directory as the - * given one by comparing their names. Called from Dir_AddDir via - * Lst_Find when searching the list of open directories. - * - * Input: - * p Current name - * dname Desired name - * - * Results: - * 0 if it is the same. Non-zero otherwise - * - * Side Effects: - * None - *----------------------------------------------------------------------- - */ -static int -DirFindName(const void *p, const void *dname) +/* See if the Path structure describes the same directory as the + * given one by comparing their names. Called from Dir_AddDir via + * Lst_Find when searching the list of open directories. */ +static Boolean +DirFindName(const void *p, const void *desiredName) { - return strcmp(((const Path *)p)->name, dname); + return strcmp(((const Path *)p)->name, desiredName) == 0; } -/*- - *----------------------------------------------------------------------- - * Dir_HasWildcards -- - * see if the given name has any wildcard characters in it - * be careful not to expand unmatching brackets or braces. - * XXX: This code is not 100% correct. ([^]] fails etc.) - * I really don't think that make(1) should be expanding - * patterns, because then you have to set a mechanism for - * escaping the expansion! +/* See if the given name has any wildcard characters in it. Be careful not to + * expand unmatching brackets or braces. + * + * XXX: This code is not 100% correct ([^]] fails etc.). I really don't think + * that make(1) should be expanding patterns, because then you have to set a + * mechanism for escaping the expansion! * * Input: * name name to check * * Results: * returns TRUE if the word should be expanded, FALSE otherwise - * - * Side Effects: - * none - *----------------------------------------------------------------------- */ Boolean -Dir_HasWildcards(char *name) +Dir_HasWildcards(const char *name) { - char *cp; - int wild = 0, brace = 0, bracket = 0; + const char *cp; + Boolean wild = FALSE; + int braces = 0, brackets = 0; for (cp = name; *cp; cp++) { - switch(*cp) { + switch (*cp) { case '{': - brace++; - wild = 1; - break; + braces++; + wild = TRUE; + break; case '}': - brace--; - break; + braces--; + break; case '[': - bracket++; - wild = 1; - break; + brackets++; + wild = TRUE; + break; case ']': - bracket--; - break; + brackets--; + break; case '?': case '*': - wild = 1; - break; + wild = TRUE; + break; default: - break; + break; } } - return wild && bracket == 0 && brace == 0; + return wild && brackets == 0 && braces == 0; } /*- @@ -607,20 +568,17 @@ Dir_HasWildcards(char *name) * p Directory to search * expansion Place to store the results * - * Results: - * Always returns 0 - * * Side Effects: * File names are added to the expansions lst. The directory will be * fully hashed when this is done. *----------------------------------------------------------------------- */ -static int +static void DirMatchFiles(const char *pattern, Path *p, Lst expansions) { - Hash_Search search; /* Index into the directory's table */ - Hash_Entry *entry; /* Current entry in the table */ - Boolean isDot; /* TRUE if the directory being searched is . */ + Hash_Search search; /* Index into the directory's table */ + Hash_Entry *entry; /* Current entry in the table */ + Boolean isDot; /* TRUE if the directory being searched is . */ isDot = (*p->name == '.' && p->name[1] == '\0'); @@ -638,13 +596,75 @@ DirMatchFiles(const char *pattern, Path *p, Lst expansions) ((entry->name[0] != '.') || (pattern[0] == '.'))) { - (void)Lst_AtEnd(expansions, - (isDot ? bmake_strdup(entry->name) : - str_concat(p->name, entry->name, - STR_ADDSLASH))); + Lst_Append(expansions, + (isDot ? bmake_strdup(entry->name) : + str_concat3(p->name, "/", entry->name))); } } - return 0; +} + +/* 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; +} + +/* 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; +} + +static Boolean +contains_wildcard(const char *p) +{ + for (; *p != '\0'; p++) { + switch (*p) { + case '*': + case '?': + case '{': + case '[': + return TRUE; + } + } + 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; } /*- @@ -672,91 +692,41 @@ DirMatchFiles(const char *pattern, Path *p, Lst expansions) static void DirExpandCurly(const char *word, const char *brace, Lst path, Lst expansions) { - const char *end; /* Character after the closing brace */ - const char *cp; /* Current position in brace clause */ - const char *start; /* Start of current piece of brace clause */ - int bracelevel; /* Number of braces we've seen. If we see a - * right brace when this is 0, we've hit the - * end of the clause. */ - char *file; /* Current expansion */ - int otherLen; /* The length of the other pieces of the - * expansion (chars before and after the - * clause in 'word') */ - char *cp2; /* Pointer for checking for wildcards in - * expansion before calling Dir_Expand */ - - start = brace+1; + const char *prefix, *middle, *piece, *middle_end, *suffix; + size_t prefix_len, suffix_len; - /* - * Find the end of the brace clause first, being wary of nested brace - * clauses. - */ - for (end = start, bracelevel = 0; *end != '\0'; end++) { - if (*end == '{') { - bracelevel++; - } else if ((*end == '}') && (bracelevel-- == 0)) { - break; - } - } - if (*end == '\0') { - Error("Unterminated {} clause \"%s\"", start); + /* 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; - } else { - end++; } - otherLen = brace - word + strlen(end); - for (cp = start; cp < end; cp++) { - /* - * Find the end of this piece of the clause. - */ - bracelevel = 0; - while (*cp != ',') { - if (*cp == '{') { - bracelevel++; - } else if ((*cp == '}') && (bracelevel-- <= 0)) { - break; - } - cp++; - } - /* - * Allocate room for the combination and install the three pieces. - */ - file = bmake_malloc(otherLen + cp - start + 1); - if (brace != word) { - strncpy(file, word, brace-word); - } - if (cp != start) { - strncpy(&file[brace-word], start, cp-start); - } - strcpy(&file[(brace-word)+(cp-start)], end); + prefix = word; + prefix_len = (size_t)(brace - prefix); + suffix = middle_end + 1; + suffix_len = strlen(suffix); - /* - * See if the result has any wildcards in it. If we find one, call - * Dir_Expand right away, telling it to place the result on our list - * of expansions. - */ - for (cp2 = file; *cp2 != '\0'; cp2++) { - switch(*cp2) { - case '*': - case '?': - case '{': - case '[': - Dir_Expand(file, path, expansions); - goto next; - } - } - if (*cp2 == '\0') { - /* - * Hit the end w/o finding any wildcards, so stick the expansion - * on the end of the list. - */ - (void)Lst_AtEnd(expansions, file); - } else { - next: + /* 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); + + 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); } - start = cp+1; + + piece = piece_end + 1; /* skip over the comma or closing brace */ } } @@ -784,32 +754,18 @@ DirExpandCurly(const char *word, const char *brace, Lst path, Lst expansions) static void DirExpandInt(const char *word, Lst path, Lst expansions) { - LstNode ln; /* Current node */ - Path *p; /* Directory in the node */ + LstNode ln; /* Current node */ - if (Lst_Open(path) == SUCCESS) { - while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); - DirMatchFiles(word, p, expansions); - } - Lst_Close(path); + Lst_Open(path); + while ((ln = Lst_Next(path)) != NULL) { + Path *p = LstNode_Datum(ln); + DirMatchFiles(word, p, expansions); } + Lst_Close(path); } -/*- - *----------------------------------------------------------------------- - * DirPrintWord -- - * Print a word in the list of expansions. Callback for Dir_Expand - * when DEBUG(DIR), via Lst_ForEach. - * - * Results: - * === 0 - * - * Side Effects: - * The passed word is printed, followed by a space. - * - *----------------------------------------------------------------------- - */ +/* Print a word in the list of expansions. + * Callback for Dir_Expand when DEBUG(DIR), via Lst_ForEach. */ static int DirPrintWord(void *word, void *dummy MAKE_ATTR_UNUSED) { @@ -836,16 +792,18 @@ DirPrintWord(void *word, void *dummy MAKE_ATTR_UNUSED) * * Side Effects: * Directories may be opened. Who knows? + * Undefined behavior if the word is really in read-only memory. *----------------------------------------------------------------------- */ void Dir_Expand(const char *word, Lst path, Lst expansions) { - const char *cp; + const char *cp; - if (DEBUG(DIR)) { - fprintf(debug_file, "Expanding \"%s\"... ", word); - } + assert(path != NULL); + assert(expansions != NULL); + + DIR_DEBUG1("Expanding \"%s\"... ", word); cp = strchr(word, '{'); if (cp) { @@ -872,13 +830,12 @@ Dir_Expand(const char *word, Lst path, Lst expansions) /* * Back up to the start of the component */ - char *dirpath; - while (cp > word && *cp != '/') { cp--; } if (cp != word) { char sc; + char *dirpath; /* * If the glob isn't in the first component, try and find * all the components up to the one with a wildcard. @@ -898,10 +855,10 @@ Dir_Expand(const char *word, Lst path, Lst expansions) char *dp = &dirpath[strlen(dirpath) - 1]; if (*dp == '/') *dp = '\0'; - path = Lst_Init(FALSE); + path = Lst_Init(); (void)Dir_AddDir(path, dirpath); - DirExpandInt(cp+1, path, expansions); - Lst_Destroy(path, NULL); + DirExpandInt(cp + 1, path, expansions); + Lst_Free(path); } } else { /* @@ -948,21 +905,17 @@ Dir_Expand(const char *word, Lst path, Lst expansions) */ static char * DirLookup(Path *p, const char *name MAKE_ATTR_UNUSED, const char *cp, - Boolean hasSlash MAKE_ATTR_UNUSED) + Boolean hasSlash MAKE_ATTR_UNUSED) { - char *file; /* the current filename to check */ + char *file; /* the current filename to check */ - if (DEBUG(DIR)) { - fprintf(debug_file, " %s ...\n", p->name); - } + DIR_DEBUG1(" %s ...\n", p->name); if (Hash_FindEntry(&p->files, cp) == NULL) return NULL; - file = str_concat(p->name, cp, STR_ADDSLASH); - if (DEBUG(DIR)) { - fprintf(debug_file, " returning %s\n", file); - } + file = str_concat3(p->name, "/", cp); + DIR_DEBUG1(" returning %s\n", file); p->hits += 1; hits += 1; return file; @@ -986,11 +939,11 @@ DirLookup(Path *p, const char *name MAKE_ATTR_UNUSED, const char *cp, static char * DirLookupSubdir(Path *p, const char *name) { - struct stat stb; /* Buffer for stat, if necessary */ - char *file; /* the current filename to check */ + struct make_stat mst; + char *file; /* the current filename to check */ if (p != dot) { - file = str_concat(p->name, name, STR_ADDSLASH); + file = str_concat3(p->name, "/", name); } else { /* * Checking in dot -- DON'T put a leading ./ on the thing. @@ -998,11 +951,9 @@ DirLookupSubdir(Path *p, const char *name) file = bmake_strdup(name); } - if (DEBUG(DIR)) { - fprintf(debug_file, "checking %s ...\n", file); - } + DIR_DEBUG1("checking %s ...\n", file); - if (cached_stat(file, &stb) == 0) { + if (cached_stat(file, &mst) == 0) { nearmisses += 1; return file; } @@ -1028,40 +979,34 @@ DirLookupSubdir(Path *p, const char *name) static char * DirLookupAbs(Path *p, const char *name, const char *cp) { - char *p1; /* pointer into p->name */ - const char *p2; /* pointer into name */ + char *p1; /* pointer into p->name */ + const char *p2; /* pointer into name */ - if (DEBUG(DIR)) { - fprintf(debug_file, " %s ...\n", p->name); - } + DIR_DEBUG1(" %s ...\n", p->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 (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { - continue; - } - if (*p1 != '\0' || p2 != 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 (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { + continue; + } + if (*p1 != '\0' || p2 != cp - 1) { + return NULL; + } - if (Hash_FindEntry(&p->files, cp) == NULL) { - if (DEBUG(DIR)) { - fprintf(debug_file, " must be here but isn't -- returning\n"); - } - /* Return empty string: terminates search */ - return bmake_strdup(""); - } + if (Hash_FindEntry(&p->files, cp) == NULL) { + DIR_DEBUG0(" must be here but isn't -- returning\n"); + /* Return empty string: terminates search */ + return bmake_strdup(""); + } - p->hits += 1; - hits += 1; - if (DEBUG(DIR)) { - fprintf(debug_file, " returning %s\n", name); - } - return bmake_strdup(name); + p->hits += 1; + hits += 1; + DIR_DEBUG1(" returning %s\n", name); + return bmake_strdup(name); } /*- @@ -1081,25 +1026,20 @@ static char * DirFindDot(Boolean hasSlash MAKE_ATTR_UNUSED, const char *name, const char *cp) { - if (Hash_FindEntry(&dot->files, cp) != NULL) { - if (DEBUG(DIR)) { - fprintf(debug_file, " in '.'\n"); - } - hits += 1; - dot->hits += 1; - return bmake_strdup(name); - } - if (cur && - Hash_FindEntry(&cur->files, cp) != NULL) { - if (DEBUG(DIR)) { - fprintf(debug_file, " in ${.CURDIR} = %s\n", cur->name); - } - hits += 1; - cur->hits += 1; - return str_concat(cur->name, cp, STR_ADDSLASH); - } + if (Hash_FindEntry(&dot->files, cp) != NULL) { + DIR_DEBUG0(" in '.'\n"); + hits += 1; + dot->hits += 1; + return bmake_strdup(name); + } + if (cur && Hash_FindEntry(&cur->files, cp) != NULL) { + DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name); + hits += 1; + cur->hits += 1; + return str_concat3(cur->name, "/", cp); + } - return NULL; + return NULL; } /*- @@ -1127,14 +1067,14 @@ DirFindDot(Boolean hasSlash MAKE_ATTR_UNUSED, const char *name, const char *cp) char * Dir_FindFile(const char *name, Lst path) { - LstNode ln; /* a list element */ - char *file; /* the current filename to check */ - Path *p; /* current path member */ - const char *cp; /* Terminal name of file */ - Boolean hasLastDot = FALSE; /* true we should search dot last */ - Boolean hasSlash; /* true if 'name' contains a / */ - struct stat stb; /* Buffer for stat, if necessary */ - const char *trailing_dot = "."; + LstNode ln; /* a list element */ + char *file; /* the current filename to check */ + Path *p; /* current path member */ + const char *cp; /* Terminal name of file */ + Boolean hasLastDot = FALSE; /* true we should search dot last */ + Boolean hasSlash; /* true if 'name' contains a / */ + struct make_stat mst; /* Buffer for stat, if necessary */ + const char *trailing_dot = "."; /* * Find the final component of the name and note whether it has a @@ -1149,29 +1089,23 @@ Dir_FindFile(const char *name, Lst path) cp = name; } - if (DEBUG(DIR)) { - fprintf(debug_file, "Searching for %s ...", name); - } + DIR_DEBUG1("Searching for %s ...", name); - if (Lst_Open(path) == FAILURE) { - if (DEBUG(DIR)) { - fprintf(debug_file, "couldn't open path, file not found\n"); - } + if (path == NULL) { + DIR_DEBUG0("couldn't open path, file not found\n"); misses += 1; return NULL; } + Lst_Open(path); if ((ln = Lst_First(path)) != NULL) { - p = (Path *)Lst_Datum(ln); + p = LstNode_Datum(ln); if (p == dotLast) { hasLastDot = TRUE; - if (DEBUG(DIR)) - fprintf(debug_file, "[dot last]..."); + DIR_DEBUG0("[dot last]..."); } } - if (DEBUG(DIR)) { - fprintf(debug_file, "\n"); - } + DIR_DEBUG0("\n"); /* * If there's no leading directory components or if the leading @@ -1179,41 +1113,39 @@ Dir_FindFile(const char *name, Lst path) * of each of the directories on the search path. */ if (!hasSlash || (cp - 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 (!hasLastDot && - (file = DirFindDot(hasSlash, name, cp)) != NULL) { - Lst_Close(path); - 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 (!hasLastDot && (file = DirFindDot(hasSlash, name, cp)) != NULL) { + Lst_Close(path); + return file; + } - while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); - if (p == dotLast) - continue; - if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) { - Lst_Close(path); - return file; - } + while ((ln = Lst_Next(path)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) { + Lst_Close(path); + return file; } + } - if (hasLastDot && - (file = DirFindDot(hasSlash, name, cp)) != NULL) { - Lst_Close(path); - return file; - } + if (hasLastDot && (file = DirFindDot(hasSlash, name, cp)) != NULL) { + Lst_Close(path); + return file; + } } Lst_Close(path); @@ -1232,9 +1164,7 @@ Dir_FindFile(const char *name, Lst path) * This phase is only performed if the file is *not* absolute. */ if (!hasSlash) { - if (DEBUG(DIR)) { - fprintf(debug_file, " failed.\n"); - } + DIR_DEBUG0(" failed.\n"); misses += 1; return NULL; } @@ -1245,30 +1175,28 @@ Dir_FindFile(const char *name, Lst path) } if (name[0] != '/') { - Boolean checkedDot = FALSE; + Boolean checkedDot = FALSE; - if (DEBUG(DIR)) { - fprintf(debug_file, " Trying subdirectories...\n"); - } + DIR_DEBUG0(" Trying subdirectories...\n"); if (!hasLastDot) { - if (dot) { - checkedDot = TRUE; - if ((file = DirLookupSubdir(dot, name)) != NULL) - return file; - } - if (cur && (file = DirLookupSubdir(cur, name)) != NULL) - return file; + if (dot) { + checkedDot = TRUE; + if ((file = DirLookupSubdir(dot, name)) != NULL) + return file; + } + if (cur && (file = DirLookupSubdir(cur, name)) != NULL) + return file; } - (void)Lst_Open(path); + Lst_Open(path); while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); + p = LstNode_Datum(ln); if (p == dotLast) continue; if (p == dot) { - if (checkedDot) - continue; + if (checkedDot) + continue; checkedDot = TRUE; } if ((file = DirLookupSubdir(p, name)) != NULL) { @@ -1279,13 +1207,13 @@ Dir_FindFile(const char *name, Lst path) Lst_Close(path); if (hasLastDot) { - if (dot && !checkedDot) { - checkedDot = TRUE; - if ((file = DirLookupSubdir(dot, name)) != NULL) - return file; - } - if (cur && (file = DirLookupSubdir(cur, name)) != NULL) - return file; + if (dot && !checkedDot) { + checkedDot = TRUE; + if ((file = DirLookupSubdir(dot, name)) != NULL) + return file; + } + if (cur && (file = DirLookupSubdir(cur, name)) != NULL) + return file; } if (checkedDot) { @@ -1293,9 +1221,7 @@ Dir_FindFile(const char *name, Lst path) * Already checked by the given name, since . was in the path, * so no point in proceeding... */ - if (DEBUG(DIR)) { - fprintf(debug_file, " Checked . already, returning NULL\n"); - } + DIR_DEBUG0(" Checked . already, returning NULL\n"); return NULL; } @@ -1310,12 +1236,10 @@ Dir_FindFile(const char *name, Lst path) * file does not exist at all. This is signified by DirLookupAbs() * returning an empty string. */ - if (DEBUG(DIR)) { - fprintf(debug_file, " Trying exact path matches...\n"); - } + DIR_DEBUG0(" Trying exact path matches...\n"); - if (!hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp)) - != NULL)) { + if (!hasLastDot && cur && + ((file = DirLookupAbs(cur, name, cp)) != NULL)) { if (file[0] == '\0') { free(file); return NULL; @@ -1323,9 +1247,9 @@ Dir_FindFile(const char *name, Lst path) return file; } - (void)Lst_Open(path); + Lst_Open(path); while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); + p = LstNode_Datum(ln); if (p == dotLast) continue; if ((file = DirLookupAbs(p, name, cp)) != NULL) { @@ -1339,8 +1263,8 @@ Dir_FindFile(const char *name, Lst path) } Lst_Close(path); - if (hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp)) - != NULL)) { + if (hasLastDot && cur && + ((file = DirLookupAbs(cur, name, cp)) != NULL)) { if (file[0] == '\0') { free(file); return NULL; @@ -1380,7 +1304,7 @@ Dir_FindFile(const char *name, Lst path) if (ln == NULL) { return NULL; } else { - p = (Path *)Lst_Datum(ln); + p = LstNode_Datum(ln); } if (Hash_FindEntry(&p->files, cp) != NULL) { @@ -1389,18 +1313,14 @@ Dir_FindFile(const char *name, Lst path) return NULL; } #else /* !notdef */ - if (DEBUG(DIR)) { - fprintf(debug_file, " Looking for \"%s\" ...\n", name); - } + DIR_DEBUG1(" Looking for \"%s\" ...\n", name); bigmisses += 1; - if (cached_stat(name, &stb) == 0) { + if (cached_stat(name, &mst) == 0) { return bmake_strdup(name); } - if (DEBUG(DIR)) { - fprintf(debug_file, " failed. Returning NULL\n"); - } + DIR_DEBUG0(" failed. Returning NULL\n"); return NULL; #endif /* notdef */ } @@ -1416,7 +1336,7 @@ Dir_FindFile(const char *name, Lst path) * here starting directory * search_path the path we are looking for * result the result of a successful search is placed here - * rlen the length of the result buffer + * result_len the length of the result buffer * (typically MAXPATHLEN + 1) * * Results: @@ -1426,62 +1346,57 @@ Dir_FindFile(const char *name, Lst path) * Side Effects: *----------------------------------------------------------------------- */ -int -Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen) { - - struct stat st; - char dirbase[MAXPATHLEN + 1], *db_end; - char try[MAXPATHLEN + 1], *try_end; - - /* copy out our starting point */ - snprintf(dirbase, sizeof(dirbase), "%s", here); - db_end = dirbase + strlen(dirbase); - - /* loop until we determine a result */ - while (1) { +Boolean +Dir_FindHereOrAbove(const char *here, const char *search_path, + char *result, int result_len) +{ + struct make_stat mst; + char dirbase[MAXPATHLEN + 1], *dirbase_end; + char try[MAXPATHLEN + 1], *try_end; - /* try and stat(2) it ... */ - snprintf(try, sizeof(try), "%s/%s", dirbase, search_path); - if (cached_stat(try, &st) != -1) { - /* - * success! if we found a file, chop off - * the filename so we return a directory. - */ - if ((st.st_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! */ - } + /* copy out our starting point */ + snprintf(dirbase, sizeof(dirbase), "%s", here); + dirbase_end = dirbase + strlen(dirbase); - /* - * done! - */ - snprintf(result, rlen, "%s", try); - return 1; - } + /* loop until we determine a result */ + while (TRUE) { - /* - * nope, we didn't find it. if we used up dirbase we've - * reached the root and failed. - */ - if (db_end == dirbase) - break; /* failed! */ + /* try and stat(2) it ... */ + snprintf(try, sizeof(try), "%s/%s", dirbase, search_path); + if (cached_stat(try, &mst) != -1) { + /* + * success! if we found a file, chop off + * the filename so we return a directory. + */ + if ((mst.mst_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! */ + } - /* - * truncate dirbase from the end to move up a dir - */ - while (db_end > dirbase && *db_end != '/') - db_end--; - *db_end = 0; /* chop! */ + snprintf(result, result_len, "%s", try); + return TRUE; + } - } /* while (1) */ + /* + * nope, we didn't find it. if we used up dirbase we've + * reached the root and failed. + */ + if (dirbase_end == dirbase) + break; /* failed! */ /* - * we failed... + * truncate dirbase from the end to move up a dir */ - return 0; + while (dirbase_end > dirbase && *dirbase_end != '/') + dirbase_end--; + *dirbase_end = '\0'; /* chop! */ + + } /* while (TRUE) */ + + return FALSE; } /*- @@ -1505,8 +1420,8 @@ Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen) { int Dir_MTime(GNode *gn, Boolean recheck) { - char *fullName; /* the full pathname of name */ - struct stat stb; /* buffer for finding the mod time */ + char *fullName; /* the full pathname of name */ + struct make_stat mst; /* buffer for finding the mod time */ if (gn->type & OP_ARCHV) { return Arch_MTime(gn); @@ -1519,7 +1434,7 @@ Dir_MTime(GNode *gn, Boolean recheck) else { fullName = Dir_FindFile(gn->name, Suff_FindPath(gn)); if (fullName == NULL && gn->flags & FROM_DEPEND && - !Lst_IsEmpty(gn->iParents)) { + !Lst_IsEmpty(gn->implicitParents)) { char *cp; cp = strrchr(gn->name, '/'); @@ -1539,15 +1454,15 @@ Dir_MTime(GNode *gn, Boolean recheck) 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); + "%s: %s, %d: ignoring stale %s for %s, " + "found %s\n", progname, gn->fname, + gn->lineno, + makeDependfile, gn->name, fullName); } } } - if (DEBUG(DIR)) - fprintf(debug_file, "Found '%s' as '%s'\n", - gn->name, fullName ? fullName : "(not found)" ); + DIR_DEBUG2("Found '%s' as '%s'\n", + gn->name, fullName ? fullName : "(not found)"); } } else { fullName = gn->path; @@ -1557,13 +1472,13 @@ Dir_MTime(GNode *gn, Boolean recheck) fullName = bmake_strdup(gn->name); } - if (cached_stats(&mtimes, fullName, &stb, recheck ? CST_UPDATE : 0) < 0) { + if (cached_stats(&mtimes, fullName, &mst, recheck ? CST_UPDATE : 0) < 0) { if (gn->type & OP_MEMBER) { if (fullName != gn->path) free(fullName); return Arch_MemMTime(gn); } else { - stb.st_mtime = 0; + mst.mst_mtime = 0; } } @@ -1571,7 +1486,7 @@ Dir_MTime(GNode *gn, Boolean recheck) gn->path = fullName; } - gn->mtime = stb.st_mtime; + gn->mtime = mst.mst_mtime; return gn->mtime; } @@ -1585,6 +1500,8 @@ Dir_MTime(GNode *gn, Boolean recheck) * Input: * path the path to which the directory should be * added + * XXX: Why would this ever be NULL, and what does + * that mean? * name the name of the directory to add * * Results: @@ -1598,78 +1515,70 @@ Dir_MTime(GNode *gn, Boolean recheck) Path * Dir_AddDir(Lst path, const char *name) { - LstNode ln = NULL; /* node in case Path structure is found */ - Path *p = NULL; /* pointer to new Path structure */ - DIR *d; /* for reading directory */ - struct dirent *dp; /* entry in directory */ + LstNode ln = NULL; /* node in case Path structure is found */ + Path *p = NULL; /* pointer to new Path structure */ + DIR *d; /* for reading directory */ + struct dirent *dp; /* entry in directory */ - if (strcmp(name, ".DOTLAST") == 0) { - ln = Lst_Find(path, name, DirFindName); + if (path != NULL && strcmp(name, ".DOTLAST") == 0) { + ln = Lst_Find(path, DirFindName, name); if (ln != NULL) - return (Path *)Lst_Datum(ln); - else { - dotLast->refCount += 1; - (void)Lst_AtFront(path, dotLast); - } + return LstNode_Datum(ln); + + dotLast->refCount++; + Lst_Prepend(path, dotLast); } - if (path) - ln = Lst_Find(openDirectories, name, DirFindName); + if (path != NULL) + ln = Lst_Find(openDirectories, DirFindName, name); if (ln != NULL) { - p = (Path *)Lst_Datum(ln); - if (path && Lst_Member(path, p) == NULL) { + p = LstNode_Datum(ln); + if (Lst_FindDatum(path, p) == NULL) { p->refCount += 1; - (void)Lst_AtEnd(path, p); - } - } else { - if (DEBUG(DIR)) { - fprintf(debug_file, "Caching %s ...", name); + Lst_Append(path, p); } + return p; + } + + DIR_DEBUG1("Caching %s ...", name); - if ((d = opendir(name)) != NULL) { - p = bmake_malloc(sizeof(Path)); - p->name = bmake_strdup(name); - p->hits = 0; - p->refCount = 1; - Hash_InitTable(&p->files, -1); + if ((d = opendir(name)) != NULL) { + p = bmake_malloc(sizeof(Path)); + p->name = bmake_strdup(name); + p->hits = 0; + p->refCount = 1; + Hash_InitTable(&p->files, -1); - while ((dp = readdir(d)) != NULL) { + 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)Hash_CreateEntry(&p->files, dp->d_name, NULL); + /* + * 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; } - (void)closedir(d); - (void)Lst_AtEnd(openDirectories, p); - if (path != NULL) - (void)Lst_AtEnd(path, p); - } - if (DEBUG(DIR)) { - fprintf(debug_file, "done\n"); +#endif /* sun && d_ino */ + (void)Hash_CreateEntry(&p->files, dp->d_name, NULL); } + (void)closedir(d); + Lst_Append(openDirectories, p); + if (path != NULL) + Lst_Append(path, p); } + DIR_DEBUG0("done\n"); return p; } /*- *----------------------------------------------------------------------- * Dir_CopyDir -- - * Callback function for duplicating a search path via Lst_Duplicate. + * Callback function for duplicating a search path via Lst_Copy. * Ups the reference count for the directory. * * Results: * Returns the Path it was given. - * - * Side Effects: - * The refCount of the path is incremented. - * *----------------------------------------------------------------------- */ void * @@ -1704,25 +1613,23 @@ Dir_CopyDir(void *p) char * Dir_MakeFlags(const char *flag, Lst path) { - char *str; /* the string which will be returned */ - char *s1, *s2;/* the current directory preceded by 'flag' */ - LstNode ln; /* the node of the current directory */ - Path *p; /* the structure describing the current directory */ + Buffer buf; + LstNode ln; /* the node of the current directory */ - str = bmake_strdup(""); + Buf_Init(&buf, 0); - if (Lst_Open(path) == SUCCESS) { + if (path != NULL) { + Lst_Open(path); while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); - s2 = str_concat(flag, p->name, 0); - str = str_concat(s1 = str, s2, STR_ADDSPACE); - free(s1); - free(s2); + Path *p = LstNode_Datum(ln); + Buf_AddStr(&buf, " "); + Buf_AddStr(&buf, flag); + Buf_AddStr(&buf, p->name); } Lst_Close(path); } - return str; + return Buf_Destroy(&buf, FALSE); } /*- @@ -1746,14 +1653,14 @@ Dir_MakeFlags(const char *flag, Lst path) void Dir_Destroy(void *pp) { - Path *p = (Path *)pp; + Path *p = (Path *)pp; p->refCount -= 1; if (p->refCount == 0) { - LstNode ln; + LstNode ln; - ln = Lst_Member(openDirectories, p); - (void)Lst_Remove(openDirectories, ln); + ln = Lst_FindDatum(openDirectories, p); + Lst_Remove(openDirectories, ln); Hash_DeleteTable(&p->files); free(p->name); @@ -1781,9 +1688,8 @@ Dir_Destroy(void *pp) void Dir_ClearPath(Lst path) { - Path *p; while (!Lst_IsEmpty(path)) { - p = (Path *)Lst_DeQueue(path); + Path *p = Lst_Dequeue(path); Dir_Destroy(p); } } @@ -1811,37 +1717,43 @@ void Dir_Concat(Lst path1, Lst path2) { LstNode ln; - Path *p; + Path *p; - for (ln = Lst_First(path2); ln != NULL; ln = Lst_Succ(ln)) { - p = (Path *)Lst_Datum(ln); - if (Lst_Member(path1, p) == NULL) { + for (ln = Lst_First(path2); ln != NULL; ln = LstNode_Next(ln)) { + p = LstNode_Datum(ln); + if (Lst_FindDatum(path1, p) == NULL) { p->refCount += 1; - (void)Lst_AtEnd(path1, p); + Lst_Append(path1, p); } } } +static int +percentage(int num, int den) +{ + return den != 0 ? num * 100 / den : 0; +} + /********** DEBUG INFO **********/ void Dir_PrintDirectories(void) { - LstNode ln; - Path *p; + LstNode ln; fprintf(debug_file, "#*** Directory Cache:\n"); - fprintf(debug_file, "# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", - hits, misses, nearmisses, bigmisses, - (hits+bigmisses+nearmisses ? - hits * 100 / (hits + bigmisses + nearmisses) : 0)); + fprintf(debug_file, + "# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", + hits, misses, nearmisses, bigmisses, + percentage(hits, hits + bigmisses + nearmisses)); fprintf(debug_file, "# %-20s referenced\thits\n", "directory"); - if (Lst_Open(openDirectories) == SUCCESS) { - while ((ln = Lst_Next(openDirectories)) != NULL) { - p = (Path *)Lst_Datum(ln); - fprintf(debug_file, "# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); - } - Lst_Close(openDirectories); + + Lst_Open(openDirectories); + while ((ln = Lst_Next(openDirectories)) != NULL) { + Path *p = LstNode_Datum(ln); + fprintf(debug_file, "# %-20s %10d\t%4d\n", p->name, p->refCount, + p->hits); } + Lst_Close(openDirectories); } static int |