summaryrefslogtreecommitdiff
path: root/usr.bin/make
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make')
-rw-r--r--usr.bin/make/Makefile5
-rw-r--r--usr.bin/make/arch.c3
-rw-r--r--usr.bin/make/dir.c281
-rw-r--r--usr.bin/make/dir.h22
-rw-r--r--usr.bin/make/direxpand.c343
-rw-r--r--usr.bin/make/direxpand.h53
-rw-r--r--usr.bin/make/main.c3
-rw-r--r--usr.bin/make/parse.c3
-rw-r--r--usr.bin/make/suff.c3
9 files changed, 420 insertions, 296 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
index 8d83964ef88..9a19d075a2f 100644
--- a/usr.bin/make/Makefile
+++ b/usr.bin/make/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.43 2007/07/21 14:40:33 espie Exp $
+# $OpenBSD: Makefile,v 1.44 2007/09/16 10:14:26 espie Exp $
PROG= make
CFLAGS+= -I${.OBJDIR} -I${.CURDIR}
@@ -15,7 +15,8 @@ CDEFS+=-DHAS_EXTENDED_GETCWD
CFLAGS+=${CDEFS}
HOSTCFLAGS+=${CDEFS}
-SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c error.c for.c \
+SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c direxpand.c \
+ error.c for.c \
init.c job.c lowparse.c main.c make.c memory.c parse.c \
parsevar.c str.c stats.c suff.c targ.c timestamp.c \
var.c varmodifiers.c varname.c
diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c
index 7617dc10803..b60cf3346a2 100644
--- a/usr.bin/make/arch.c
+++ b/usr.bin/make/arch.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: arch.c,v 1.62 2007/09/16 09:49:24 espie Exp $ */
+/* $OpenBSD: arch.c,v 1.63 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: arch.c,v 1.17 1996/11/06 17:58:59 christos Exp $ */
/*
@@ -87,6 +87,7 @@
#include "config.h"
#include "defines.h"
#include "dir.h"
+#include "direxpand.h"
#include "arch.h"
#include "var.h"
#include "targ.h"
diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c
index 2f403d4fcff..45171f2e395 100644
--- a/usr.bin/make/dir.c
+++ b/usr.bin/make/dir.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: dir.c,v 1.46 2007/07/24 21:09:07 espie Exp $ */
+/* $OpenBSD: dir.c,v 1.47 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: dir.c,v 1.14 1997/03/29 16:51:26 christos Exp $ */
/*
@@ -175,7 +175,7 @@ static int hits, /* Found in directory cache */
bigmisses; /* Sought by itself */
#endif
-static Path *dot; /* contents of current directory */
+Path *dot; /* contents of current directory */
struct file_stamp {
TIMESTAMP mtime; /* time stamp... */
@@ -225,18 +225,6 @@ static void free_hash(struct ohash *);
/* p = DirReaddiri(name, end): read an actual directory, caching results
* as we go. */
static Path *DirReaddiri(const char *, const char *);
-/* Handles wildcard expansion on a given directory. */
-static void DirMatchFilesi(const char *, const char *, Path *, Lst);
-/* Handles simple wildcard expansion on a path. */
-static void PathMatchFilesi(const char *, const char *, Lst, Lst);
-/* Handles wildcards expansion except for curly braces. */
-static void DirExpandWildi(const char *, const char *, Lst, Lst);
-#define DirExpandWild(s, l1, l2) DirExpandWildi(s, strchr(s, '\0'), l1, l2)
-/* Handles wildcard expansion including curly braces. */
-static void DirExpandCurlyi(const char *, const char *, Lst, Lst);
-
-/* Debugging: show each word in an expansion list. */
-static void DirPrintWord(void *);
/* Debugging: show a dir name in a path. */
static void DirPrintDir(void *);
@@ -339,49 +327,9 @@ Dir_End(void)
}
#endif
-
-/* XXX: This code is not 100% correct ([^]] fails) */
-bool
-Dir_HasWildcardsi(const char *name, const char *ename)
-{
- const char *cp;
- bool wild = false;
- unsigned long brace = 0, bracket = 0;
-
- for (cp = name; cp != ename; cp++) {
- switch (*cp) {
- case '{':
- brace++;
- wild = true;
- break;
- case '}':
- if (brace == 0)
- return false;
- brace--;
- break;
- case '[':
- bracket++;
- wild = true;
- break;
- case ']':
- if (bracket == 0)
- return false;
- bracket--;
- break;
- case '?':
- case '*':
- wild = true;
- break;
- default:
- break;
- }
- }
- return wild && bracket == 0 && brace == 0;
-}
-
/*-
*-----------------------------------------------------------------------
- * DirMatchFilesi --
+ * Dir_MatchFilesi --
* Given a pattern and a Path structure, see if any files
* match the pattern and add their names to the 'expansions' list if
* any do. This is incomplete -- it doesn't take care of patterns like
@@ -389,8 +337,8 @@ Dir_HasWildcardsi(const char *name, const char *ename)
* will do for now.
*-----------------------------------------------------------------------
*/
-static void
-DirMatchFilesi(const char *word, const char *eword, Path *p, Lst expansions)
+void
+Dir_MatchFilesi(const char *word, const char *eword, Path *p, Lst expansions)
{
unsigned int search; /* Index into the directory's table */
const char *entry; /* Current entry in the table */
@@ -414,225 +362,6 @@ DirMatchFilesi(const char *word, const char *eword, Path *p, Lst expansions)
}
/*-
- *-----------------------------------------------------------------------
- * PathMatchFilesi --
- * Traverse directories in the path, calling DirMatchFiles for each.
- * NOTE: This doesn't handle patterns in directories.
- *-----------------------------------------------------------------------
- */
-static void
-PathMatchFilesi(const char *word, const char *eword, Lst path, Lst expansions)
-{
- LstNode ln; /* Current node */
-
- for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln))
- DirMatchFilesi(word, eword, (Path *)Lst_Datum(ln), expansions);
-}
-
-static void
-DirPrintWord(void *word)
-{
- printf("%s ", (char *)word);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * DirExpandWildi:
- * Expand all wild cards in a fully qualified name, except for
- * curly braces.
- * Side-effect:
- * Will hash any directory in which a file is found, and add it to
- * the path, on the assumption that future lookups will find files
- * there as well.
- *-----------------------------------------------------------------------
- */
-static void
-DirExpandWildi(const char *word, const char *eword, Lst path, Lst expansions)
-{
- const char *cp;
- const char *slash; /* keep track of first slash before wildcard */
-
- slash = memchr(word, '/', eword - word);
- if (slash == NULL) {
- /* First the files in dot. */
- DirMatchFilesi(word, eword, dot, expansions);
-
- /* Then the files in every other directory on the path. */
- PathMatchFilesi(word, eword, path, expansions);
- return;
- }
- /* The thing has a directory component -- find the first wildcard
- * in the string. */
- slash = word;
- for (cp = word; cp != eword; cp++) {
- if (*cp == '/')
- slash = cp;
- if (*cp == '?' || *cp == '[' || *cp == '*') {
-
- if (slash != word) {
- char *dirpath;
-
- /* If the glob isn't in the first component,
- * try and find all the components up to
- * the one with a wildcard. */
- dirpath = Dir_FindFilei(word, slash+1, path);
- /* dirpath is null if we 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. */
- if (dirpath != NULL) {
- char *dp;
- LIST temp;
-
- dp = strchr(dirpath, '\0');
- while (dp > dirpath && dp[-1] == '/')
- dp--;
-
- Lst_Init(&temp);
- Dir_AddDiri(&temp, dirpath, dp);
- PathMatchFilesi(slash+1, eword, &temp,
- expansions);
- Lst_Destroy(&temp, NOFREE);
- }
- } else
- /* Start the search from the local directory. */
- PathMatchFilesi(word, eword, path, expansions);
- return;
- }
- }
- /* Return the file -- this should never happen. */
- PathMatchFilesi(word, eword, path, expansions);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * DirExpandCurly --
- * Expand curly braces like the C shell, and other wildcards as per
- * Str_Match.
- * XXX: if curly expansion yields a result with
- * no wildcards, the result is placed on the list WITHOUT CHECKING
- * FOR ITS EXISTENCE.
- *-----------------------------------------------------------------------
- */
-static void
-DirExpandCurlyi(const char *word, const char *eword, Lst path, Lst expansions)
-{
- const char *cp2;/* Pointer for checking for wildcards in
- * expansion before calling Dir_Expand */
- LIST curled; /* Queue of words to expand */
- char *toexpand; /* Current word to expand */
- bool dowild; /* Wildcard left after curlies ? */
-
- /* Determine once and for all if there is something else going on */
- dowild = false;
- for (cp2 = word; cp2 != eword; cp2++)
- if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') {
- dowild = true;
- break;
- }
-
- /* Prime queue with copy of initial word */
- Lst_Init(&curled);
- Lst_EnQueue(&curled, Str_dupi(word, eword));
- while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) {
- const char *brace;
- const char *start;
- /* Start of current chunk of brace clause */
- const char *end;/* Character after the closing brace */
- int bracelevel; /* Keep track of nested braces. If we hit
- * the right brace with bracelevel == 0,
- * this is the end of the clause. */
- size_t endLen; /* The length of the ending non-curlied
- * part of the current expansion */
-
- /* End case: no curly left to expand */
- brace = strchr(toexpand, '{');
- if (brace == NULL) {
- if (dowild) {
- DirExpandWild(toexpand, path, expansions);
- free(toexpand);
- } else
- Lst_AtEnd(expansions, toexpand);
- continue;
- }
-
- start = brace+1;
-
- /* Find the end of the brace clause first, being wary of
- * nested brace clauses. */
- for (end = start, bracelevel = 0;; end++) {
- if (*end == '{')
- bracelevel++;
- else if (*end == '\0') {
- Error("Unterminated {} clause \"%s\"", start);
- return;
- } else if (*end == '}' && bracelevel-- == 0)
- break;
- }
- end++;
- endLen = strlen(end);
-
- for (;;) {
- char *file; /* To hold current expansion */
- const char *cp; /* Current position in brace clause */
-
- /* Find the end of the current expansion */
- for (bracelevel = 0, cp = start;
- bracelevel != 0 || (*cp != '}' && *cp != ',');
- cp++) {
- if (*cp == '{')
- bracelevel++;
- else if (*cp == '}')
- bracelevel--;
- }
-
- /* Build the current combination and enqueue it. */
- file = emalloc((brace - toexpand) + (cp - start) +
- endLen + 1);
- if (brace != toexpand)
- memcpy(file, toexpand, brace-toexpand);
- if (cp != start)
- memcpy(file+(brace-toexpand), start, cp-start);
- memcpy(file+(brace-toexpand)+(cp-start), end,
- endLen + 1);
- Lst_EnQueue(&curled, file);
- if (*cp == '}')
- break;
- start = cp+1;
- }
- free(toexpand);
- }
-}
-
-/* Side effects:
- * Dir_Expandi will hash directories that were not yet visited */
-void
-Dir_Expandi(const char *word, const char *eword, Lst path, Lst expansions)
-{
- const char *cp;
-
- if (DEBUG(DIR)) {
- char *s = Str_dupi(word, eword);
- printf("expanding \"%s\"...", s);
- free(s);
- }
-
- cp = memchr(word, '{', eword - word);
- if (cp)
- DirExpandCurlyi(word, eword, path, expansions);
- else
- DirExpandWildi(word, eword, path, expansions);
-
- if (DEBUG(DIR)) {
- Lst_Every(expansions, DirPrintWord);
- fputc('\n', stdout);
- }
-}
-
-
-/*-
* Side Effects:
* If the file is found in a directory which is not on the path
* already (either 'name' is absolute or it is a relative path
diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h
index 58bfdf73ced..d87c983211e 100644
--- a/usr.bin/make/dir.h
+++ b/usr.bin/make/dir.h
@@ -2,7 +2,7 @@
#define DIR_H
/* $OpenPackages$ */
-/* $OpenBSD: dir.h,v 1.17 2007/01/18 17:49:51 espie Exp $ */
+/* $OpenBSD: dir.h,v 1.18 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: dir.h,v 1.4 1996/11/06 17:59:05 christos Exp $ */
/*
@@ -102,19 +102,6 @@ extern void Dir_PrintPath(Lst);
* Handling file names, and looking them up in paths
*/
-/* boolean = Dir_HasWildcardsi(name, end)
- * Returns true if (name, end) needs to be wildcard-expanded.
- */
-extern bool Dir_HasWildcardsi(const char *, const char *);
-#define Dir_HasWildcards(n) Dir_HasWildcardsi(n, strchr(n, '\0'))
-
-/* Dir_Expandi(pattern, endp, path, expansions);
- * Expand (pattern, endp) to Lst of names matching on the search path.
- * Put result in expansions.
- */
-extern void Dir_Expandi(const char *, const char *, Lst, Lst);
-#define Dir_Expand(n, l1, l2) Dir_Expandi(n, strchr(n, '\0'), l1, l2)
-
/* fullname = Dir_FindFileComplexi(name, end, path, checkCurdirFirst)
* Searches for a file (name, end) on a given search path. If it exists,
* return the fullname of the file, otherwise NULL.
@@ -165,4 +152,11 @@ extern void Dir_PrintDirectories(void);
/* List of directories to search when looking for targets. */
extern Lst dirSearchPath;
+
+/* communication between dir.c and direxpand.c */
+struct Path_;
+extern struct Path_ *dot;
+/* Handles wildcard expansion on a given directory. */
+extern void Dir_MatchFilesi(const char *, const char *, struct Path_ *,
+ Lst);
#endif /* DIR_H */
diff --git a/usr.bin/make/direxpand.c b/usr.bin/make/direxpand.c
new file mode 100644
index 00000000000..a81cc84f716
--- /dev/null
+++ b/usr.bin/make/direxpand.c
@@ -0,0 +1,343 @@
+/* $OpenBSD: direxpand.c,v 1.1 2007/09/16 10:14:26 espie Exp $ */
+/*
+ * Copyright (c) 1999,2007 Marc Espie.
+ *
+ * Extensive code changes for the OpenBSD project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+ * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+#include "defines.h"
+#include "lst.h"
+#include "dir.h"
+#include "direxpand.h"
+#include "error.h"
+#include "memory.h"
+#include "str.h"
+
+/* Handles simple wildcard expansion on a path. */
+static void PathMatchFilesi(const char *, const char *, Lst, Lst);
+/* Handles wildcards expansion except for curly braces. */
+static void DirExpandWildi(const char *, const char *, Lst, Lst);
+#define DirExpandWild(s, l1, l2) DirExpandWildi(s, strchr(s, '\0'), l1, l2)
+/* Handles wildcard expansion including curly braces. */
+static void DirExpandCurlyi(const char *, const char *, Lst, Lst);
+
+/* Debugging: show each word in an expansion list. */
+static void DirPrintWord(void *);
+
+/*-
+ *-----------------------------------------------------------------------
+ * PathMatchFilesi --
+ * Traverse directories in the path, calling Dir_MatchFiles for each.
+ * NOTE: This doesn't handle patterns in directories.
+ *-----------------------------------------------------------------------
+ */
+static void
+PathMatchFilesi(const char *word, const char *eword, Lst path, Lst expansions)
+{
+ LstNode ln; /* Current node */
+
+ for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln))
+ Dir_MatchFilesi(word, eword, (struct Path_ *)Lst_Datum(ln), expansions);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * DirExpandWildi:
+ * Expand all wild cards in a fully qualified name, except for
+ * curly braces.
+ * Side-effect:
+ * Will hash any directory in which a file is found, and add it to
+ * the path, on the assumption that future lookups will find files
+ * there as well.
+ *-----------------------------------------------------------------------
+ */
+static void
+DirExpandWildi(const char *word, const char *eword, Lst path, Lst expansions)
+{
+ const char *cp;
+ const char *slash; /* keep track of first slash before wildcard */
+
+ slash = memchr(word, '/', eword - word);
+ if (slash == NULL) {
+ /* First the files in dot. */
+ Dir_MatchFilesi(word, eword, dot, expansions);
+
+ /* Then the files in every other directory on the path. */
+ PathMatchFilesi(word, eword, path, expansions);
+ return;
+ }
+ /* The thing has a directory component -- find the first wildcard
+ * in the string. */
+ slash = word;
+ for (cp = word; cp != eword; cp++) {
+ if (*cp == '/')
+ slash = cp;
+ if (*cp == '?' || *cp == '[' || *cp == '*') {
+
+ if (slash != word) {
+ char *dirpath;
+
+ /* If the glob isn't in the first component,
+ * try and find all the components up to
+ * the one with a wildcard. */
+ dirpath = Dir_FindFilei(word, slash+1, path);
+ /* dirpath is null if we 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. */
+ if (dirpath != NULL) {
+ char *dp;
+ LIST temp;
+
+ dp = strchr(dirpath, '\0');
+ while (dp > dirpath && dp[-1] == '/')
+ dp--;
+
+ Lst_Init(&temp);
+ Dir_AddDiri(&temp, dirpath, dp);
+ PathMatchFilesi(slash+1, eword, &temp,
+ expansions);
+ Lst_Destroy(&temp, NOFREE);
+ }
+ } else
+ /* Start the search from the local directory. */
+ PathMatchFilesi(word, eword, path, expansions);
+ return;
+ }
+ }
+ /* Return the file -- this should never happen. */
+ PathMatchFilesi(word, eword, path, expansions);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * DirExpandCurly --
+ * Expand curly braces like the C shell, and other wildcards as per
+ * Str_Match.
+ * XXX: if curly expansion yields a result with
+ * no wildcards, the result is placed on the list WITHOUT CHECKING
+ * FOR ITS EXISTENCE.
+ *-----------------------------------------------------------------------
+ */
+static void
+DirExpandCurlyi(const char *word, const char *eword, Lst path, Lst expansions)
+{
+ const char *cp2;/* Pointer for checking for wildcards in
+ * expansion before calling Dir_Expand */
+ LIST curled; /* Queue of words to expand */
+ char *toexpand; /* Current word to expand */
+ bool dowild; /* Wildcard left after curlies ? */
+
+ /* Determine once and for all if there is something else going on */
+ dowild = false;
+ for (cp2 = word; cp2 != eword; cp2++)
+ if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') {
+ dowild = true;
+ break;
+ }
+
+ /* Prime queue with copy of initial word */
+ Lst_Init(&curled);
+ Lst_EnQueue(&curled, Str_dupi(word, eword));
+ while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) {
+ const char *brace;
+ const char *start;
+ /* Start of current chunk of brace clause */
+ const char *end;/* Character after the closing brace */
+ int bracelevel; /* Keep track of nested braces. If we hit
+ * the right brace with bracelevel == 0,
+ * this is the end of the clause. */
+ size_t endLen; /* The length of the ending non-curlied
+ * part of the current expansion */
+
+ /* End case: no curly left to expand */
+ brace = strchr(toexpand, '{');
+ if (brace == NULL) {
+ if (dowild) {
+ DirExpandWild(toexpand, path, expansions);
+ free(toexpand);
+ } else
+ Lst_AtEnd(expansions, toexpand);
+ continue;
+ }
+
+ start = brace+1;
+
+ /* Find the end of the brace clause first, being wary of
+ * nested brace clauses. */
+ for (end = start, bracelevel = 0;; end++) {
+ if (*end == '{')
+ bracelevel++;
+ else if (*end == '\0') {
+ Error("Unterminated {} clause \"%s\"", start);
+ return;
+ } else if (*end == '}' && bracelevel-- == 0)
+ break;
+ }
+ end++;
+ endLen = strlen(end);
+
+ for (;;) {
+ char *file; /* To hold current expansion */
+ const char *cp; /* Current position in brace clause */
+
+ /* Find the end of the current expansion */
+ for (bracelevel = 0, cp = start;
+ bracelevel != 0 || (*cp != '}' && *cp != ',');
+ cp++) {
+ if (*cp == '{')
+ bracelevel++;
+ else if (*cp == '}')
+ bracelevel--;
+ }
+
+ /* Build the current combination and enqueue it. */
+ file = emalloc((brace - toexpand) + (cp - start) +
+ endLen + 1);
+ if (brace != toexpand)
+ memcpy(file, toexpand, brace-toexpand);
+ if (cp != start)
+ memcpy(file+(brace-toexpand), start, cp-start);
+ memcpy(file+(brace-toexpand)+(cp-start), end,
+ endLen + 1);
+ Lst_EnQueue(&curled, file);
+ if (*cp == '}')
+ break;
+ start = cp+1;
+ }
+ free(toexpand);
+ }
+}
+
+/* Side effects:
+ * Dir_Expandi will hash directories that were not yet visited */
+void
+Dir_Expandi(const char *word, const char *eword, Lst path, Lst expansions)
+{
+ const char *cp;
+
+ if (DEBUG(DIR)) {
+ char *s = Str_dupi(word, eword);
+ printf("expanding \"%s\"...", s);
+ free(s);
+ }
+
+ cp = memchr(word, '{', eword - word);
+ if (cp)
+ DirExpandCurlyi(word, eword, path, expansions);
+ else
+ DirExpandWildi(word, eword, path, expansions);
+
+ if (DEBUG(DIR)) {
+ Lst_Every(expansions, DirPrintWord);
+ fputc('\n', stdout);
+ }
+}
+
+static void
+DirPrintWord(void *word)
+{
+ printf("%s ", (char *)word);
+}
+
+
+/* XXX: This code is not 100% correct ([^]] fails) */
+bool
+Dir_HasWildcardsi(const char *name, const char *ename)
+{
+ const char *cp;
+ bool wild = false;
+ unsigned long brace = 0, bracket = 0;
+
+ for (cp = name; cp != ename; cp++) {
+ switch (*cp) {
+ case '{':
+ brace++;
+ wild = true;
+ break;
+ case '}':
+ if (brace == 0)
+ return false;
+ brace--;
+ break;
+ case '[':
+ bracket++;
+ wild = true;
+ break;
+ case ']':
+ if (bracket == 0)
+ return false;
+ bracket--;
+ break;
+ case '?':
+ case '*':
+ wild = true;
+ break;
+ default:
+ break;
+ }
+ }
+ return wild && bracket == 0 && brace == 0;
+}
+
+
diff --git a/usr.bin/make/direxpand.h b/usr.bin/make/direxpand.h
new file mode 100644
index 00000000000..7cbd13914f4
--- /dev/null
+++ b/usr.bin/make/direxpand.h
@@ -0,0 +1,53 @@
+#ifndef DIREXPAND_H
+#define DIREXPAND_H
+/* $OpenBSD: direxpand.h,v 1.1 2007/09/16 10:14:26 espie Exp $ */
+/*
+ * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)dir.h 8.1 (Berkeley) 6/6/93
+ */
+
+/* boolean = Dir_HasWildcardsi(name, end)
+ * Returns true if (name, end) needs to be wildcard-expanded.
+ */
+extern bool Dir_HasWildcardsi(const char *, const char *);
+#define Dir_HasWildcards(n) Dir_HasWildcardsi(n, strchr(n, '\0'))
+
+/* Dir_Expandi(pattern, endp, path, expansions);
+ * Expand (pattern, endp) to Lst of names matching on the search path.
+ * Put result in expansions.
+ */
+extern void Dir_Expandi(const char *, const char *, Lst, Lst);
+#define Dir_Expand(n, l1, l2) Dir_Expandi(n, strchr(n, '\0'), l1, l2)
+
+#endif
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 8d6c4e0b94b..2ef60a3c732 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: main.c,v 1.77 2007/09/16 09:46:14 espie Exp $ */
+/* $OpenBSD: main.c,v 1.78 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */
/*
@@ -53,6 +53,7 @@
#include "parse.h"
#include "parsevar.h"
#include "dir.h"
+#include "direxpand.h"
#include "error.h"
#include "pathnames.h"
#include "init.h"
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index cf114ecfd55..272712508c5 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: parse.c,v 1.80 2007/08/05 11:00:58 espie Exp $ */
+/* $OpenBSD: parse.c,v 1.81 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
/*
@@ -70,6 +70,7 @@
#include "config.h"
#include "defines.h"
#include "dir.h"
+#include "direxpand.h"
#include "job.h"
#include "buf.h"
#include "for.h"
diff --git a/usr.bin/make/suff.c b/usr.bin/make/suff.c
index 2b43ed72aa2..729f3e2e16b 100644
--- a/usr.bin/make/suff.c
+++ b/usr.bin/make/suff.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: suff.c,v 1.62 2007/09/16 09:49:24 espie Exp $ */
+/* $OpenBSD: suff.c,v 1.63 2007/09/16 10:14:26 espie Exp $ */
/* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */
/*
@@ -94,6 +94,7 @@
#include "config.h"
#include "defines.h"
#include "dir.h"
+#include "direxpand.h"
#include "arch.h"
#include "suff.h"
#include "var.h"