Subject: Re: toolchain/20828: make: .WAIT doesn't work if macro expansion needed.
To: None <gnats-bugs@netbsd.org>
From: Simon J. Gerraty <sjg@crufty.net>
List: tech-toolchain
Date: 03/21/2003 00:20:45
Currently, given:
job-one job-two: a b c .WAIT finish-${.TARGET:S/job-//}
make will run finish-one or finish-two in parallel with a b and c.
Which is incorrect. The patch below deals with this (and possibly
some other nasty cases - have to check).
Thanks
--sjg
Index: parse.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/parse.c,v
retrieving revision 1.86
diff -u -p -r1.86 parse.c
--- parse.c 2002/12/01 05:53:30 1.86
+++ parse.c 2003/03/21 08:08:21
@@ -250,6 +250,15 @@ static struct {
{ ".WAIT", Wait, 0 },
};
+/*
+ * Used by ParseDoSpecialSrc()
+ */
+typedef struct {
+ int op;
+ char *src;
+ Lst allsrc;
+} SpecialSrc;
+
static int ParseIsEscaped(const char *, const char *);
static void ParseErrorInternal(char *, size_t, int, char *, ...)
__attribute__((__format__(__printf__, 4, 5)));
@@ -259,6 +268,7 @@ static int ParseFindKeyword(char *);
static int ParseLinkSrc(ClientData, ClientData);
static int ParseDoOp(ClientData, ClientData);
static int ParseAddDep(ClientData, ClientData);
+static int ParseDoSpecialSrc(ClientData, ClientData);
static void ParseDoSrc(int, char *, Lst);
static int ParseFindMain(ClientData, ClientData);
static int ParseAddDir(ClientData, ClientData);
@@ -590,6 +600,56 @@ ParseAddDep(ClientData pp, ClientData sp
return 1;
}
+/* -
+ *---------------------------------------------------------------------
+ * ParseDoSpecialSrc --
+ * ParseDoSrc struck an unexpanded variable in a src.
+ * The most likely reason is a src that refers to .TARGET or
+ * .PREFIX so we get called to set those for each target
+ * and then call ParseDoSrc again provided we were able to
+ * resolve things.
+ * XXX We set the fail on undefined var flag TRUE when we call
+ * Var_Subst.
+ *
+ * Input:
+ * tp A target GNode *
+ * sp A SpecialSrc * which contains the args we need
+ * for ParseDoSrc.
+ *
+ * Results:
+ * Goodness
+ *
+ * Side Effects:
+ * The target GNode will have .TARGET and .PREFIX set, this seems
+ * harmless.
+ */
+static int
+ParseDoSpecialSrc(ClientData tp, ClientData sp)
+{
+ GNode *tn = (GNode *) tp;
+ SpecialSrc *ss = (SpecialSrc *) sp;
+ char *cp;
+ char *cp2;
+ char *pref;
+
+ Var_Set(TARGET, tn->name, tn, 0);
+ if ((pref = strrchr(tn->name, '/')))
+ pref++;
+ else
+ pref = tn->name;
+ if ((cp2 = strchr(pref, '.')) > tn->name) {
+ cp = strdup(pref);
+ cp[cp2 - pref] = '\0';
+ Var_Set(PREFIX, cp, tn, 0);
+ free(cp);
+ } else
+ Var_Set(PREFIX, pref, tn, 0);
+ cp = Var_Subst(NULL, ss->src, tn, TRUE);
+ if (!strchr(cp, '$')) /* avoid trouble! */
+ ParseDoSrc(ss->op, cp, ss->allsrc);
+ return 0;
+}
+
/*-
*---------------------------------------------------------------------
@@ -679,6 +739,19 @@ ParseDoSrc(int tOp, char *src, Lst allsr
* the 'cohorts' list of the node) or all the cohorts are linked
* to all the targets.
*/
+ if (strchr(src, '$')) {
+ SpecialSrc ss;
+
+ ss.op = tOp;
+ ss.src = src;
+ ss.allsrc = allsrc;
+
+ /*
+ * This will come back to us in a sec if possible.
+ */
+ Lst_ForEach(targets, ParseDoSpecialSrc, (ClientData)&ss);
+ return;
+ }
gn = Targ_FindNode (src, TARG_CREATE);
if (tOp) {
gn->type |= tOp;