=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/dir.c,v retrieving revision 1.25 retrieving revision 1.26 diff -c -r1.25 -r1.26 *** src/usr.bin/make/dir.c 2000/09/14 13:43:30 1.25 --- src/usr.bin/make/dir.c 2000/09/14 13:46:44 1.26 *************** *** 1,4 **** ! /* $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 $ */ /* --- 1,4 ---- ! /* $OpenBSD: dir.c,v 1.26 2000/09/14 13:46:44 espie Exp $ */ /* $NetBSD: dir.c,v 1.14 1997/03/29 16:51:26 christos Exp $ */ /* *************** *** 97,103 **** static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else UNUSED ! static char rcsid[] = "$OpenBSD: dir.c,v 1.25 2000/09/14 13:43:30 espie Exp $"; #endif #endif /* not lint */ --- 97,103 ---- static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else UNUSED ! static char rcsid[] = "$OpenBSD: dir.c,v 1.26 2000/09/14 13:46:44 espie Exp $"; #endif #endif /* not lint */ *************** *** 194,209 **** * 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 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)); static void DirPrintWord __P((void *)); static void DirPrintDir __P((void *)); /*- *----------------------------------------------------------------------- * Dir_Init -- --- 194,258 ---- * be two rules to update a single file, so this * should be ok, but... */ + static struct hash_info file_info = { 0, + NULL, hash_alloc, hash_free, element_alloc }; + static struct hash_info dir_info = { offsetof(Path, name), NULL, hash_alloc, hash_free, element_alloc }; + static void add_file __P((Path *, const char *)); + static char *find_file_hash __P((Path *, const char *, const char *, u_int32_t)); + static void free_hash __P((struct hash *)); + static Path *DirReaddir __P((const char *, const char *)); ! static void DirMatchFiles __P((char *, Path *, Lst)); static void DirExpandCurly __P((char *, char *, Lst, Lst)); static void DirExpandInt __P((char *, Lst, Lst)); static void DirPrintWord __P((void *)); static void DirPrintDir __P((void *)); + static void + add_file(p, file) + Path *p; + const char *file; + { + unsigned slot; + const char *end = NULL; + char *n; + struct hash *h = &p->files; + + slot = hash_qlookupi(h, file, &end); + n = hash_find(h, slot); + if (n == NULL) { + n = hash_create_entry(&file_info, file, &end); + hash_insert(h, slot, n); + } + } + + static char * + find_file_hash(p, file, e, hv) + Path *p; + const char *file; + const char *e; + u_int32_t hv; + { + struct hash *h = &p->files; + + return hash_find(h, hash_lookup_interval(h, file, e, hv)); + } + + static void + free_hash(h) + struct hash *h; + { + void *e; + unsigned i; + + for (e = hash_first(h, &i); e != NULL; e = hash_next(h, &i)) + free(e); + hash_delete(h); + } + /*- *----------------------------------------------------------------------- * Dir_Init -- *************** *** 320,365 **** * src / *src / *.c properly (just *.c on any of the directories), but it * will do for now. * - * 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 DirMatchFiles (pattern, p, expansions) char *pattern; /* Pattern to look for */ Path *p; /* Directory to search */ Lst expansions; /* Place to store the results */ { ! 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'); ! for (entry = Hash_EnumFirst(&p->files, &search); ! entry != (Hash_Entry *)NULL; ! entry = Hash_EnumNext(&search)) ! { ! /* ! * See if the file matches the given pattern. Note we follow the UNIX * convention that dot files will only be found if the pattern * begins with a dot (note also that as a side effect of the hashing ! * scheme, .* won't match . or .. since they aren't hashed). ! */ ! if (Str_Match(entry->name, pattern) && ! ((entry->name[0] != '.') || ! (pattern[0] == '.'))) ! { Lst_AtEnd(expansions, ! (isDot ? estrdup(entry->name) : ! str_concat(p->name, entry->name, '/'))); ! } } - return (0); } /*- --- 369,404 ---- * src / *src / *.c properly (just *.c on any of the directories), but it * will do for now. * * Side Effects: * File names are added to the expansions lst. The directory will be * fully hashed when this is done. *----------------------------------------------------------------------- */ ! static void DirMatchFiles (pattern, p, expansions) char *pattern; /* Pattern to look for */ Path *p; /* Directory to search */ Lst expansions; /* Place to store the results */ { ! unsigned int search; /* Index into the directory's table */ ! char *entry; /* Current entry in the table */ Boolean isDot; /* TRUE if the directory being searched is . */ isDot = (*p->name == '.' && p->name[1] == '\0'); ! for (entry = hash_first(&p->files, &search); entry != NULL; ! entry = hash_next(&p->files, &search)) { ! /* See if the file matches the given pattern. Note we follow the UNIX * convention that dot files will only be found if the pattern * begins with a dot (note also that as a side effect of the hashing ! * scheme, .* won't match . or .. since they aren't hashed). */ ! if (*pattern != '.' && * entry == '.') ! continue; ! if (Str_Match(entry, pattern)) Lst_AtEnd(expansions, ! (isDot ? estrdup(entry) : ! str_concat(p->name, entry, '/'))); } } /*- *************** *** 481,489 **** * path one by one, calling DirMatchFiles for each. NOTE: This still * doesn't handle patterns in directories... * - * Results: - * None. - * * Side Effects: * Things are added to the expansions list. * --- 520,525 ---- *************** *** 639,645 **** *----------------------------------------------------------------------- */ char * ! Dir_FindFile (name, path) char *name; /* the file to find */ Lst path; /* the Lst of directories to search */ { --- 675,681 ---- *----------------------------------------------------------------------- */ char * ! Dir_FindFile(name, path) char *name; /* the file to find */ Lst path; /* the Lst of directories to search */ { *************** *** 651,663 **** register char *cp; /* index of first slash, if any */ Boolean hasSlash; /* true if 'name' contains a / */ struct stat stb; /* Buffer for stat, if necessary */ ! Hash_Entry *entry; /* Entry for mtimes table */ /* * Find the final component of the name and note whether it has a * slash in it (the name, I mean) */ ! cp = strrchr (name, '/'); if (cp) { hasSlash = TRUE; cp += 1; --- 687,701 ---- register char *cp; /* index of first slash, if any */ Boolean hasSlash; /* true if 'name' contains a / */ struct stat stb; /* Buffer for stat, if necessary */ ! const char *e; ! u_int32_t hv; ! Hash_Entry *entry; /* * Find the final component of the name and note whether it has a * slash in it (the name, I mean) */ ! cp = strrchr(name, '/'); if (cp) { hasSlash = TRUE; cp += 1; *************** *** 666,671 **** --- 704,712 ---- cp = name; } + e = NULL; + hv = hash_interval(cp, &e); + if (DEBUG(DIR)) { printf("Searching for %s...", name); } *************** *** 676,692 **** * (fish.c) and what pmake finds (./fish.c). */ if ((!hasSlash || (cp - name == 2 && *name == '.')) && ! (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL)) { ! if (DEBUG(DIR)) { printf("in '.'\n"); - } hits += 1; dot->hits += 1; return (estrdup (name)); } - Lst_Open(path); - /* * We look through all the directories on the path seeking one which * contains the final component of the given name and whose final --- 717,730 ---- * (fish.c) and what pmake finds (./fish.c). */ if ((!hasSlash || (cp - name == 2 && *name == '.')) && ! find_file_hash(dot, cp, e, hv) != NULL) { ! if (DEBUG(DIR)) printf("in '.'\n"); hits += 1; dot->hits += 1; return (estrdup (name)); } /* * We look through all the directories on the path seeking one which * contains the final component of the given name and whose final *************** *** 695,709 **** * and return the resulting string. If we don't find any such thing, * we go on to phase two... */ ! while ((ln = Lst_Next (path)) != NULL) { p = (Path *)Lst_Datum(ln); ! if (DEBUG(DIR)) { printf("%s...", p->name); ! } ! if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) { ! if (DEBUG(DIR)) { printf("here..."); - } if (hasSlash) { /* * If the name had a slash, its initial components and p's --- 733,745 ---- * and return the resulting string. If we don't find any such thing, * we go on to phase two... */ ! for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); ! if (DEBUG(DIR)) printf("%s...", p->name); ! if (find_file_hash(p, cp, e, hv) != NULL) { ! if (DEBUG(DIR)) printf("here..."); if (hasSlash) { /* * If the name had a slash, its initial components and p's *************** *** 719,759 **** p1 -= 1; p2 -= 1; } if (p2 >= name || (p1 >= p->name && *p1 != '/')) { ! if (DEBUG(DIR)) { printf("component mismatch -- continuing..."); - } continue; } } file = str_concat(p->name, cp, '/'); ! if (DEBUG(DIR)) { printf("returning %s\n", file); - } - Lst_Close (path); p->hits += 1; hits += 1; ! return (file); } else if (hasSlash) { ! /* ! * If the file has a leading path component and that component * exactly matches the entire name of the current search ! * directory, we assume the file doesn't exist and return NULL. ! */ for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { continue; } if (*p1 == '\0' && p2 == cp - 1) { ! if (DEBUG(DIR)) { printf("must be here but isn't -- returing NULL\n"); ! } ! Lst_Close (path); ! return ((char *) NULL); } } } ! /* ! * We didn't find the file on any existing members of the directory. * 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 --- 755,787 ---- p1 -= 1; p2 -= 1; } if (p2 >= name || (p1 >= p->name && *p1 != '/')) { ! if (DEBUG(DIR)) printf("component mismatch -- continuing..."); continue; } } file = str_concat(p->name, cp, '/'); ! if (DEBUG(DIR)) printf("returning %s\n", file); p->hits += 1; hits += 1; ! return file; } else if (hasSlash) { ! /* If the file has a leading path component and that component * exactly matches the entire name of the current search ! * directory, we assume the file doesn't exist and return NULL. */ for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { continue; } if (*p1 == '\0' && p2 == cp - 1) { ! if (DEBUG(DIR)) printf("must be here but isn't -- returing NULL\n"); ! return NULL; } } } ! /* We didn't find the file on any existing members of the directory. * 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 *************** *** 762,858 **** * /usr/include/sys/types.h) 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) { ! if (DEBUG(DIR)) { printf("failed.\n"); - } misses += 1; ! return ((char *) NULL); } if (*name != '/') { Boolean checkedDot = FALSE; ! if (DEBUG(DIR)) { printf("failed. Trying subdirectories..."); - } Lst_Open(path); ! while ((ln = Lst_Next (path)) != NULL) { p = (Path *)Lst_Datum(ln); ! if (p != dot) { file = str_concat(p->name, name, '/'); ! } else { ! /* ! * Checking in dot -- DON'T put a leading ./ on the thing. ! */ file = estrdup(name); checkedDot = TRUE; } ! if (DEBUG(DIR)) { printf("checking %s...", file); - } ! ! if (stat (file, &stb) == 0) { ! if (DEBUG(DIR)) { printf("got it.\n"); - } ! Lst_Close (path); ! ! /* ! * We've found another directory to search. We know there's ! * a slash in 'file' because we put one there. We nuke it after ! * finding it and call Dir_AddDir to add this new directory ! * onto the existing search path. Once that's done, we restore ! * the slash and triumphantly return the file name, knowing ! * that should a file in this directory every be referenced ! * again in such a manner, we will find it without having to do ! * numerous numbers of access calls. Hurrah! ! */ cp = strrchr(file, '/'); Dir_AddDir(path, file, cp); ! /* ! * Save the modification time so if it's needed, we don't have ! * to fetch it again. ! */ ! if (DEBUG(DIR)) { printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), file); - } entry = Hash_CreateEntry(&mtimes, (char *) file, (Boolean *)NULL); /* XXX */ Hash_SetValue(entry, (void *)((long)stb.st_mtime)); nearmisses += 1; ! return (file); ! } else { ! free (file); ! } } ! if (DEBUG(DIR)) { printf("failed. "); - } - Lst_Close (path); - if (checkedDot) { ! /* ! * Already checked by the given name, since . was in the path, ! * so no point in proceeding... ! */ ! if (DEBUG(DIR)) { printf("Checked . already, returning NULL\n"); ! } ! return(NULL); } } ! /* ! * 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. --- 790,862 ---- * /usr/include/sys/types.h) 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) { ! if (DEBUG(DIR)) printf("failed.\n"); misses += 1; ! return NULL; } if (*name != '/') { Boolean checkedDot = FALSE; ! if (DEBUG(DIR)) printf("failed. Trying subdirectories..."); Lst_Open(path); ! for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); ! if (p != dot) file = str_concat(p->name, name, '/'); ! else { ! /* Checking in dot -- DON'T put a leading ./ on the thing. */ file = estrdup(name); checkedDot = TRUE; } ! if (DEBUG(DIR)) printf("checking %s...", file); ! if (stat(file, &stb) == 0) { ! if (DEBUG(DIR)) printf("got it.\n"); ! /* We've found another directory to search. We know there's ! * a slash in 'file' because we put one there. We call ! * Dir_AddDir to add this new directory onto the existing ! * search path. Once that's done, we return the file name, ! * knowing that should a file in this directory ever be ! * referenced again in such a manner, we will find it ! * without having to do numerous access calls. Hurrah! */ cp = strrchr(file, '/'); Dir_AddDir(path, file, cp); ! /* Save the modification time so if it's needed, we don't have ! * to fetch it again. */ ! if (DEBUG(DIR)) printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), file); entry = Hash_CreateEntry(&mtimes, (char *) file, (Boolean *)NULL); /* XXX */ Hash_SetValue(entry, (void *)((long)stb.st_mtime)); nearmisses += 1; ! return file; ! } else ! free(file); } ! if (DEBUG(DIR)) printf("failed. "); if (checkedDot) { ! /* Already checked by the given name, since . was in the path, ! * so no point in proceeding... */ ! if (DEBUG(DIR)) printf("Checked . already, returning NULL\n"); ! return NULL; } } ! /* 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. *************** *** 866,873 **** * * $(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... ! */ #ifdef notdef Dir_AddDir(path, name, cp-1); --- 870,876 ---- * * $(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... */ #ifdef notdef Dir_AddDir(path, name, cp-1); *************** *** 878,914 **** else p = (Path *)Lst_Datum(ln); ! if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) { ! return (estrdup (name)); ! } else { ! return ((char *) NULL); ! } #else /* !notdef */ ! if (DEBUG(DIR)) { printf("Looking for \"%s\"...", name); - } bigmisses += 1; entry = Hash_FindEntry(&mtimes, name); if (entry != (Hash_Entry *)NULL) { ! if (DEBUG(DIR)) { printf("got it (in mtime cache)\n"); ! } ! return(estrdup(name)); ! } else if (stat (name, &stb) == 0) { entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL); ! if (DEBUG(DIR)) { printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), name); - } /* XXX */ Hash_SetValue(entry, (void *)(long)stb.st_mtime); ! return (estrdup (name)); } else { ! if (DEBUG(DIR)) { printf("failed. Returning NULL\n"); ! } ! return ((char *)NULL); } #endif /* notdef */ } --- 881,912 ---- else p = (Path *)Lst_Datum(ln); ! if (find_file_hash(p, cp, e, hv) != NULL) ! return estrdup (name); ! else ! return NULL; #else /* !notdef */ ! if (DEBUG(DIR)) printf("Looking for \"%s\"...", name); bigmisses += 1; entry = Hash_FindEntry(&mtimes, name); if (entry != (Hash_Entry *)NULL) { ! if (DEBUG(DIR)) printf("got it (in mtime cache)\n"); ! return estrdup(name); ! } else if (stat(name, &stb) == 0) { entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL); ! if (DEBUG(DIR)) printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), name); /* XXX */ Hash_SetValue(entry, (void *)(long)stb.st_mtime); ! return estrdup(name); } else { ! if (DEBUG(DIR)) printf("failed. Returning NULL\n"); ! return NULL; } #endif /* notdef */ } *************** *** 1007,1013 **** 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); --- 1005,1011 ---- p = hash_create_entry(&dir_info, name, &end); p->hits = 0; p->refCount = 0; ! hash_init(&p->files, 4, &file_info); if (DEBUG(DIR)) { printf("Caching %s...", p->name); *************** *** 1028,1034 **** 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)) --- 1026,1032 ---- if (dp->d_fileno == 0) continue; #endif /* sun && d_ino */ ! add_file(p, dp->d_name); } (void)closedir(d); if (DEBUG(DIR)) *************** *** 1153,1159 **** if (--p->refCount == 0) { hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name)); ! Hash_DeleteTable (&p->files); free(p); } } --- 1151,1157 ---- if (--p->refCount == 0) { hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name)); ! free_hash(&p->files); free(p); } }