Module Name: src Committed By: rillig Date: Mon Nov 23 21:45:30 UTC 2020
Modified Files: src/usr.bin/make: dir.c Log Message: make(1): flatten Dir_Expand While here, leave comments in all places where unexpected edge cases might have hidden. To generate a diff of this commit: cvs rdiff -u -r1.214 -r1.215 src/usr.bin/make/dir.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/dir.c diff -u src/usr.bin/make/dir.c:1.214 src/usr.bin/make/dir.c:1.215 --- src/usr.bin/make/dir.c:1.214 Mon Nov 23 20:52:59 2020 +++ src/usr.bin/make/dir.c Mon Nov 23 21:45:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.214 2020/11/23 20:52:59 rillig Exp $ */ +/* $NetBSD: dir.c,v 1.215 2020/11/23 21:45:30 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -134,7 +134,7 @@ #include "job.h" /* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: dir.c,v 1.214 2020/11/23 20:52:59 rillig Exp $"); +MAKE_RCSID("$NetBSD: dir.c,v 1.215 2020/11/23 21:45:30 rillig Exp $"); #define DIR_DEBUG0(text) DEBUG0(DIR, text) #define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1) @@ -772,74 +772,86 @@ Dir_Expand(const char *word, SearchPath cp = strchr(word, '{'); if (cp != NULL) { DirExpandCurly(word, cp, path, expansions); - } else { - cp = strchr(word, '/'); - if (cp != NULL) { - /* - * The thing has a directory component -- find the first wildcard - * in the string. - */ - for (cp = word; *cp != '\0'; cp++) { - if (*cp == '?' || *cp == '[' || *cp == '*') { - break; - } - } + goto done; + } - if (*cp != '\0') { - /* - * Back up to the start of the component - */ - 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 { - /* - * Return the file -- this should never happen. - */ - DirExpandPath(word, path, expansions); - } - } else { - /* - * First the files in dot - */ - DirMatchFiles(word, dot, expansions); - - /* - * Then the files in every other directory on the path. - */ - DirExpandPath(word, path, expansions); + /* At this point, the word does not contain '{'. */ + + cp = strchr(word, '/'); + if (cp == NULL) { + /* The word has no directory component. */ + /* First the files in dot. */ + DirMatchFiles(word, dot, expansions); + + /* 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 string. */ + for (cp = word; *cp != '\0'; cp++) + if (*cp == '?' || *cp == '[' || *cp == '*') + break; + + if (*cp == '\0') { + /* + * 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. + */ + 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); + /* + * The wildcard isn't in the first component. + * Find all the components up to the one with the wildcard. + */ + /* + * 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. + */ + 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) { + 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); } } + +done: if (DEBUG(DIR)) PrintExpansions(expansions); } @@ -1349,19 +1361,22 @@ Dir_UpdateMTime(GNode *gn, Boolean reche } /* Read the list of filenames in the directory and store the result - * in openDirectories. + * 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. */ CachedDir * Dir_AddDir(SearchPath *path, const char *name) +/* + * XXX: Maybe return const CachedDir, as a hint that the return value must + * not be freed since it is owned by openDirs. + */ { CachedDir *dir = NULL; /* the added directory */ DIR *d;