Subject: revised patch for MAKEOVERRIDES.
To: None <tech-toolchain@netbsd.org>
From: Simon Gerraty <sjg@juniper.net>
List: tech-toolchain
Date: 06/08/2001 11:43:21
The patch below is against bmake, but is close enough for feedback.
Apart from adding the ability to turn off the export of command line
vars by putting:

.MAKEOVERRIDES=

in a Makefile, this version ensures the exported vars are properly
quoted. 

--sjg

Index: main.c
===================================================================
RCS file: /cvs/juniper/src/buildtools/bmake/main.c,v
retrieving revision 1.5
diff -u -p -r1.5 main.c
--- main.c	2001/06/01 23:13:58	1.5
+++ main.c	2001/06/08 18:24:00
@@ -413,7 +413,6 @@ rearg:	while((c = getopt(argc, argv, OPT
 	 */
 	for (argv += optind, argc -= optind; *argv; ++argv, --argc)
 		if (Parse_IsVar(*argv)) {
-			Var_Append(MAKEFLAGS, *argv, VAR_GLOBAL);
 			Parse_DoVar(*argv, VAR_CMD);
 		} else {
 			if (!**argv)
@@ -545,7 +544,7 @@ main(argc, argv)
 	Lst targs;	/* target nodes to create -- passed to Make_Init */
 	Boolean outOfDate = TRUE; 	/* FALSE if all targets up to date */
 	struct stat sb, sa;
-	char *p, *p1, *path, *pathp, *pwd, *getenv(), *getcwd();
+	char *p1, *path, *pathp, *pwd, *getenv(), *getcwd();
 	char mdpath[MAXPATHLEN + 1];
 	char obpath[MAXPATHLEN + 1];
 	char cdpath[MAXPATHLEN + 1];
@@ -754,6 +753,7 @@ main(argc, argv)
 	Var_Set("MAKE", argv[0], VAR_GLOBAL);
 	Var_Set(".MAKE", argv[0], VAR_GLOBAL);
 	Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
+	Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL);
 	Var_Set("MFLAGS", "", VAR_GLOBAL);
 
 	/*
@@ -875,15 +875,7 @@ main(argc, argv)
 	    printf("job_pipe %d %d, maxjobs %d maxlocal %d compat %d\n", job_pipe[0], job_pipe[1], maxJobs,
 	           maxLocal, compatMake);
 
-	/* Install all the flags into the MAKE envariable. */
-	if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
-#ifdef POSIX
-		setenv("MAKEFLAGS", p, 1);
-#else
-		setenv("MAKE", p, 1);
-#endif
-	if (p1)
-	    free(p1);
+	ExportMAKEFLAGS(1);		/* initial export */
 
 	Check_Cwd_av(0, NULL, 0);	/* initialize it */
 	
@@ -1702,4 +1694,28 @@ PrintOnError(s)
     s = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
     if (s && *s)
 	printf("%s", s);
+}
+
+void
+ExportMAKEFLAGS(first)
+     int first;
+{
+    static int once = 1;
+    char tmp[64];
+    char *s;
+
+    if (once != first)
+	return;
+    once = 0;
+    
+    /* supress duplicates in MAKEOVERRIDES */
+    strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u}", sizeof(tmp));
+    s = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+    if (s && *s) {
+#ifdef POSIX
+	setenv("MAKEFLAGS", s, 1);
+#else
+	setenv("MAKE", s, 1);
+#endif
+    }
 }
Index: make.h
===================================================================
RCS file: /cvs/juniper/src/buildtools/bmake/make.h,v
retrieving revision 1.3
diff -u -p -r1.3 make.h
--- make.h	2001/06/01 23:13:58	1.3
+++ make.h	2001/06/08 18:24:00
@@ -385,6 +385,7 @@ extern Lst	sysIncPath;	/* The system inc
 extern char	*progname;	/* The program name */
 
 #define	MAKEFLAGS	".MAKEFLAGS"
+#define	MAKEOVERRIDES	".MAKEOVERRIDES"
 
 /*
  * debug control:
@@ -431,5 +432,6 @@ Boolean Make_Run __P((Lst));
 char * Check_Cwd_Cmd __P((char *));
 void Check_Cwd __P((char **));
 void PrintOnError __P((char *));
+void ExportMAKEFLAGS __P((int));
 
 #endif /* _MAKE_H_ */
Index: parse.c
===================================================================
RCS file: /cvs/juniper/src/buildtools/bmake/parse.c,v
retrieving revision 1.3
diff -u -p -r1.3 parse.c
--- parse.c	2001/06/01 23:13:58	1.3
+++ parse.c	2001/06/08 18:24:00
@@ -1582,6 +1582,8 @@ Parse_DoVar (line, ctxt)
 	 * Normal assignment -- just do it.
 	 */
 	Var_Set(line, cp, ctxt);
+	if (strcmp(line, MAKEOVERRIDES) == 0)
+	    ExportMAKEFLAGS(0);		/* re-export MAKEFLAGS */
     }
 }
 
Index: var.c
===================================================================
RCS file: /cvs/juniper/src/buildtools/bmake/var.c,v
retrieving revision 1.4
diff -u -p -r1.4 var.c
--- var.c	2001/06/01 23:13:58	1.4
+++ var.c	2001/06/08 18:24:00
@@ -467,7 +467,26 @@ Var_Set (name, val, ctxt)
      * to the environment (as per POSIX standard)
      */
     if (ctxt == VAR_CMD) {
+	char tmp[256];
+	char *exp;
+	int nbytes;
+	
 	setenv(name, val, 1);
+
+	exp = 0;
+	if ((nbytes = snprintf(tmp, sizeof(tmp), "%s='%s'", name, val))
+	    < sizeof(tmp)) {
+	    exp = tmp;
+	} else {
+	    /* alloca is handy, but not everyone has it. */
+	    if ((exp = malloc(nbytes + 1)))
+		snprintf(exp, nbytes + 1, "%s='%s'", name, val);
+	}
+	if (exp) {
+	    Var_Append(MAKEOVERRIDES, exp, VAR_GLOBAL);
+	    if (exp != tmp)
+		free(exp);
+	}
     }
     if (name != cp)
 	free(name);