From 51659857a77240128692bea347a76ab877790d2a Mon Sep 17 00:00:00 2001 From: chuck Date: Tue, 3 Feb 2004 19:25:29 +0000 Subject: [PATCH] add parent directory search for make as discussed on tech-toolchain. - new dir.c function: Dir_FindHereOrAbove: Search for a path in the current directory and then all the directories above it in turn until the path is found or we reach the root ("/"). - add hooks to use it in main.c for -m and syspath (compiled in _PATH_DEFSYSPATH and $MAKESYSPATH). - updated man page --- usr.bin/make/dir.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- usr.bin/make/dir.h | 3 +- usr.bin/make/main.c | 31 ++++++++++++---- usr.bin/make/make.1 | 31 ++++++++++++++-- 4 files changed, 139 insertions(+), 15 deletions(-) diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c index 74c1f3dfb5fd..123da049fc32 100644 --- a/usr.bin/make/dir.c +++ b/usr.bin/make/dir.c @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.39 2004/01/11 12:22:40 dsl Exp $ */ +/* $NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifdef MAKE_BOOTSTRAP -static char rcsid[] = "$NetBSD: dir.c,v 1.39 2004/01/11 12:22:40 dsl Exp $"; +static char rcsid[] = "$NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else -__RCSID("$NetBSD: dir.c,v 1.39 2004/01/11 12:22:40 dsl Exp $"); +__RCSID("$NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $"); #endif #endif /* not lint */ #endif @@ -109,6 +109,10 @@ __RCSID("$NetBSD: dir.c,v 1.39 2004/01/11 12:22:40 dsl Exp $"); * If it exists, the entire path is returned. * Otherwise NULL is returned. * + * Dir_FindHereOrAbove Search for a path in the current directory and + * then all the directories above it in turn until + * the path is found or we reach the root ("/"). + * * Dir_MTime Return the modification time of a node. The file * is searched for along the default search path. * The path and mtime fields of the node are filled @@ -1312,6 +1316,85 @@ Dir_FindFile(const char *name, Lst path) #endif /* notdef */ } + +/*- + *----------------------------------------------------------------------- + * Dir_FindHereOrAbove -- + * search for a path starting at a given directory and then working + * our way up towards the root. + * + * Input: + * 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 + * (typically MAXPATHLEN + 1) + * + * Results: + * 0 on failure, 1 on success [in which case the found path is put + * in the result buffer]. + * + * 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) { + + /* try and stat(2) it ... */ + snprintf(try, sizeof(try), "%s/%s", dirbase, search_path); + if (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! */ + } + + /* + * done! + */ + snprintf(result, rlen, "%s", try); + return(1); + } + + /* + * nope, we didn't find it. if we used up dirbase we've + * reached the root and failed. + */ + if (db_end == dirbase) + break; /* failed! */ + + /* + * truncate dirbase from the end to move up a dir + */ + while (db_end > dirbase && *db_end != '/') + db_end--; + *db_end = 0; /* chop! */ + + } /* while (1) */ + + /* + * we failed... + */ + return(0); +} + /*- *----------------------------------------------------------------------- * Dir_MTime -- diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h index b55bec9f2a18..8586f4cd4fec 100644 --- a/usr.bin/make/dir.h +++ b/usr.bin/make/dir.h @@ -1,4 +1,4 @@ -/* $NetBSD: dir.h,v 1.10 2003/08/07 11:14:50 agc Exp $ */ +/* $NetBSD: dir.h,v 1.11 2004/02/03 19:25:29 chuck Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -94,6 +94,7 @@ void Dir_SetPATH(void); Boolean Dir_HasWildcards(char *); void Dir_Expand(const char *, Lst, Lst); char *Dir_FindFile(const char *, Lst); +int Dir_FindHereOrAbove(char *, char *, char *, int); int Dir_MTime(GNode *); Path *Dir_AddDir(Lst, const char *); char *Dir_MakeFlags(const char *, Lst); diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 9d217bd711f9..c089ff806562 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.96 2004/01/05 23:23:35 jmmv Exp $ */ +/* $NetBSD: main.c,v 1.97 2004/02/03 19:25:29 chuck Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,7 +69,7 @@ */ #ifdef MAKE_BOOTSTRAP -static char rcsid[] = "$NetBSD: main.c,v 1.96 2004/01/05 23:23:35 jmmv Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.97 2004/02/03 19:25:29 chuck Exp $"; #else #include #ifndef lint @@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: main.c,v 1.96 2004/01/05 23:23:35 jmmv Exp $"); +__RCSID("$NetBSD: main.c,v 1.97 2004/02/03 19:25:29 chuck Exp $"); #endif #endif /* not lint */ #endif @@ -206,6 +206,7 @@ MainParseArgs(int argc, char **argv) { char *p; int c; + char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ optind = 1; /* since we're called more than once */ #ifdef REMOTE @@ -391,7 +392,16 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); break; case 'm': - (void) Dir_AddDir(sysIncPath, optarg); + /* look for magic parent directory search string */ + if (strncmp(".../", optarg, 4) == 0) { + if (!Dir_FindHereOrAbove(curdir, optarg+4, + found_path, sizeof(found_path))) + break; /* nothing doing */ + (void) Dir_AddDir(sysIncPath, found_path); + + } else { + (void) Dir_AddDir(sysIncPath, optarg); + } Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; @@ -565,6 +575,7 @@ main(int argc, char **argv) char *cp = NULL, *start; /* avoid faults on read-only strings */ static char defsyspath[] = _PATH_DEFSYSPATH; + char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ if ((progname = strrchr(argv[0], '/')) != NULL) progname++; @@ -808,11 +819,17 @@ main(int argc, char **argv) for (start = syspath; *start != '\0'; start = cp) { for (cp = start; *cp != '\0' && *cp != ':'; cp++) continue; - if (*cp == '\0') { + if (*cp == ':') { + *cp++ = '\0'; + } + /* look for magic parent directory search string */ + if (strncmp(".../", start, 4) != 0) { (void) Dir_AddDir(defIncPath, start); } else { - *cp++ = '\0'; - (void) Dir_AddDir(defIncPath, start); + if (Dir_FindHereOrAbove(curdir, start+4, + found_path, sizeof(found_path))) { + (void) Dir_AddDir(defIncPath, found_path); + } } } if (syspath != defsyspath) diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1 index ea00a67f0273..3e96c9a80445 100644 --- a/usr.bin/make/make.1 +++ b/usr.bin/make/make.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.97 2004/01/27 01:38:01 lukem Exp $ +.\" $NetBSD: make.1,v 1.98 2004/02/03 19:25:29 chuck Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -188,13 +188,36 @@ Continue processing after errors are encountered, but only on those targets that do not depend on the target whose creation caused the error. .It Fl m Ar directory Specify a directory in which to search for sys.mk and makefiles included -via the \*[Lt]...\*[Gt] style. -Multiple directories can be added to form a search path. +via the +.Aq Ar file +style include statement. +The +.Fl m +option can be used multiple times to form a search path. This path will override the default system include path: /usr/share/mk. Furthermore the system include path will be appended to the search path used -for "..."-style inclusions (see the +for +.Pf \*q Ar file Ns \*q +style include statements (see the .Fl I option). +.Pp +If a file or directory name in the +.Fl m +argument (or the +.Ev MAKESYSPATH +environment variable) starts with the string ".../" then +.Nm +will search for the specified file or directory named in the remaining part +of the argument string. The search starts with the current directory of +the Makefile and then works upward towards the root of the filesystem. +If the search is successful, then the resulting directory replaces the +".../" specification in the +.Fl m +argument. If used, this feature allows +.Nm +to easily search in the current source tree for customized sys.mk files +(e.g. by using ".../mk/sys.mk" as an argument). .It Fl n Display the commands that would have been executed, but do not actually execute them unless the target depends on the .MAKE special