diff options
Diffstat (limited to 'usr.bin/make/dir.c')
-rw-r--r-- | usr.bin/make/dir.c | 230 |
1 files changed, 101 insertions, 129 deletions
diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c index b19c5578a34..138dc794838 100644 --- a/usr.bin/make/dir.c +++ b/usr.bin/make/dir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dir.c,v 1.24 2000/09/14 13:32:06 espie Exp $ */ +/* $OpenBSD: dir.c,v 1.25 2000/09/14 13:43:30 espie Exp $ */ /* $NetBSD: dir.c,v 1.14 1997/03/29 16:51:26 christos Exp $ */ /* @@ -82,12 +82,14 @@ * Dir_PrintDirectories Print stats about the directory cache. */ +#include <stddef.h> #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include "make.h" #include "hash.h" +#include "ohash.h" #include "dir.h" #ifndef lint @@ -95,7 +97,7 @@ static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: dir.c,v 1.24 2000/09/14 13:32:06 espie Exp $"; +static char rcsid[] = "$OpenBSD: dir.c,v 1.25 2000/09/14 13:43:30 espie Exp $"; #endif #endif /* not lint */ @@ -109,8 +111,7 @@ static char rcsid[] = "$OpenBSD: dir.c,v 1.24 2000/09/14 13:32:06 espie Exp $"; * hampers the style of some makefiles, they must be changed. * * A list of all previously-read directories is kept in the - * openDirectories Lst. This list is checked first before a directory - * is opened. + * openDirectories cache. * * The need for the caching of whole directories is brought about by * the multi-level transformation code in suff.c, which tends to search @@ -171,7 +172,7 @@ static char rcsid[] = "$OpenBSD: dir.c,v 1.24 2000/09/14 13:32:06 espie Exp $"; LIST dirSearchPath; /* main search path */ -static LIST openDirectories; /* the list of all open directories */ +static struct hash openDirectories; /* cache all open directories */ /* * Variables for gathering statistics on the efficiency of the hashing @@ -193,8 +194,10 @@ static Hash_Table mtimes; /* Results of doing a last-resort stat in * be two rules to update a single file, so this * should be ok, but... */ +static struct hash_info dir_info = { offsetof(Path, name), + NULL, hash_alloc, hash_free, element_alloc }; -static int DirFindName __P((void *, void *)); +static Path *DirReaddir __P((const char *, const char *)); static int DirMatchFiles __P((char *, Path *, Lst)); static void DirExpandCurly __P((char *, char *, Lst, Lst)); static void DirExpandInt __P((char *, Lst, Lst)); @@ -217,23 +220,14 @@ void Dir_Init() { Lst_Init(&dirSearchPath); - Lst_Init(&openDirectories); + hash_init(&openDirectories, 4, &dir_info); Hash_InitTable(&mtimes, 0); - /* - * Since the Path structure is placed on both openDirectories and - * the path we give Dir_AddDir (which in this case is openDirectories), - * we need to remove "." from openDirectories and what better time to - * do it than when we have to fetch the thing anyway? - */ - Dir_AddDir(&openDirectories, "."); - dot = (Path *)Lst_DeQueue(&openDirectories); + dot = DirReaddir(".", NULL); - /* - * We always need to have dot around, so we increment its reference count - * to make sure it's not destroyed. - */ - dot->refCount += 1; + /* We always need to have dot around, so we increment its reference count + * to make sure it's not destroyed. */ + dot->refCount++; } /*- @@ -252,40 +246,22 @@ void Dir_End() { #ifdef CLEANUP - dot->refCount -= 1; + struct Path *p; + unsigned int i; + + dot->refCount--; Dir_Destroy(dot); - Dir_ClearPath(&dirSearchPath); - Lst_Destroy(&dirSearchPath, NOFREE); - Dir_ClearPath(&openDirectories); - Lst_Destroy(&openDirectories, NOFREE); + Lst_Destroy(&dirSearchPath, Dir_Destroy); + for (p = hash_first(&openDirectories, &i); p != NULL; + p = hash_next(&openDirectories, &i)) + Dir_Destroy(p); + hash_delete(&openDirectories); Hash_DeleteTable(&mtimes); #endif } /*- *----------------------------------------------------------------------- - * 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. - * - * Results: - * 0 if it is the same. Non-zero otherwise - * - * Side Effects: - * None - *----------------------------------------------------------------------- - */ -static int -DirFindName (p, dname) - void *p; /* Current name */ - void *dname; /* Desired name */ -{ - return strcmp(((Path *)p)->name, (char *)dname); -} - -/*- - *----------------------------------------------------------------------- * Dir_HasWildcards -- * see if the given name has any wildcard characters in it * be careful not to expand unmatching brackets or braces. @@ -620,7 +596,7 @@ Dir_Expand (word, path, expansions) if (*dp == '/') *dp = '\0'; Lst_Init(&temp); - Dir_AddDir(&temp, dirpath); + Dir_AddDir(&temp, dirpath, NULL); DirExpandInt(cp+1, &temp, expansions); Lst_Destroy(&temp, NOFREE); } @@ -836,10 +812,8 @@ Dir_FindFile (name, path) * again in such a manner, we will find it without having to do * numerous numbers of access calls. Hurrah! */ - cp = strrchr (file, '/'); - *cp = '\0'; - Dir_AddDir (path, file); - *cp = '/'; + cp = strrchr(file, '/'); + Dir_AddDir(path, file, cp); /* * Save the modification time so if it's needed, we don't have @@ -895,9 +869,7 @@ Dir_FindFile (name, path) * b/c we added it here. This is not good... */ #ifdef notdef - cp[-1] = '\0'; - Dir_AddDir (path, name); - cp[-1] = '/'; + Dir_AddDir(path, name, cp-1); bigmisses += 1; ln = Lst_Last(path); @@ -1015,6 +987,57 @@ Dir_MTime(gn) return exists; } +/* Read a directory, either from the disk, or from the cache. */ +static Path * +DirReaddir(name, end) + const char *name; + const char *end; +{ + Path *p; /* pointer to new Path structure */ + DIR *d; /* for reading directory */ + struct dirent *dp; /* entry in directory */ + unsigned int slot; + + slot = hash_qlookupi(&openDirectories, name, &end); + p = hash_find(&openDirectories, slot); + + if (p != NULL) + return p; + + p = hash_create_entry(&dir_info, name, &end); + p->hits = 0; + p->refCount = 0; + Hash_InitTable(&p->files, -1); + + if (DEBUG(DIR)) { + printf("Caching %s...", p->name); + fflush(stdout); + } + + if ((d = opendir(p->name)) == NULL) + return NULL; + /* Skip the first two entries -- these will *always* be . and .. */ + (void)readdir(d); + (void)readdir(d); + + 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, (Boolean *)NULL); + } + (void)closedir(d); + if (DEBUG(DIR)) + printf("done\n"); + + hash_insert(&openDirectories, slot, p); + return p; +} + /*- *----------------------------------------------------------------------- * Dir_AddDir -- @@ -1022,72 +1045,30 @@ Dir_MTime(gn) * the arguments is backwards so ParseDoDependency can do a * Lst_ForEach of its list of paths... * - * Results: - * none - * * Side Effects: * A structure is added to the list and the directory is * read and hashed. *----------------------------------------------------------------------- */ void -Dir_AddDir (path, name) - Lst path; /* the path to which the directory should be - * added */ - char *name; /* the name of the directory to add */ +Dir_AddDir(path, name, end) + Lst path; /* the path to which the directory should be + * added */ + const char *name; /* the name of the directory to add */ + const char *end; { - LstNode ln; /* node in case Path structure is found */ - register Path *p; /* pointer to new Path structure */ - DIR *d; /* for reading directory */ - register struct dirent *dp; /* entry in directory */ - - ln = Lst_Find(&openDirectories, DirFindName, name); - if (ln != NULL) { - p = (Path *)Lst_Datum(ln); - if (Lst_Member(path, p) == NULL) { - p->refCount += 1; - Lst_AtEnd(path, p); - } - } else { - if (DEBUG(DIR)) { - printf("Caching %s...", name); - fflush(stdout); - } - - if ((d = opendir (name)) != (DIR *) NULL) { - p = (Path *) emalloc (sizeof (Path)); - p->name = estrdup (name); - p->hits = 0; - p->refCount = 1; - Hash_InitTable (&p->files, -1); - - /* - * Skip the first two entries -- these will *always* be . and .. - */ - (void)readdir(d); - (void)readdir(d); - - while ((dp = readdir (d)) != (struct dirent *) 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, (Boolean *)NULL); - } - (void) closedir (d); - Lst_AtEnd(&openDirectories, p); - Lst_AtEnd(path, p); - } - if (DEBUG(DIR)) { - printf("done\n"); - } - } + Path *p; /* pointer to new Path structure */ + + p = DirReaddir(name, end); + if (p == NULL) + return; + if (p->refCount == 0) + Lst_AtEnd(path, p); + else if (Lst_Member(path, p) != NULL) + return; + else + Lst_AtEnd(path, p); + p->refCount++; } /*- @@ -1169,16 +1150,10 @@ Dir_Destroy (pp) void *pp; /* The directory descriptor to nuke */ { Path *p = (Path *) pp; - p->refCount -= 1; - - if (p->refCount == 0) { - LstNode ln; - - ln = Lst_Member(&openDirectories, p); - Lst_Remove(&openDirectories, ln); + if (--p->refCount == 0) { + hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name)); Hash_DeleteTable (&p->files); - free(p->name); free(p); } } @@ -1242,8 +1217,8 @@ Dir_Concat(path1, path2) void Dir_PrintDirectories() { - LstNode ln; Path *p; + unsigned int i; printf ("#*** Directory Cache:\n"); printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", @@ -1251,12 +1226,9 @@ Dir_PrintDirectories() (hits+bigmisses+nearmisses ? hits * 100 / (hits + bigmisses + nearmisses) : 0)); printf ("# %-20s referenced\thits\n", "directory"); - Lst_Open(&openDirectories); - while ((ln = Lst_Next(&openDirectories)) != NULL) { - p = (Path *)Lst_Datum(ln); - printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); - } - Lst_Close(&openDirectories); + for (p = hash_first(&openDirectories, &i); p != NULL; + p = hash_next(&openDirectories, &i)) + printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); } static void |