xref: /freebsd/contrib/bmake/var.c (revision cc16dea626cf2fc80cde667ac4798065108e596c)
1 /*	$NetBSD: var.c,v 1.183 2013/07/16 20:00:56 sjg Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Adam de Boor.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * Copyright (c) 1989 by Berkeley Softworks
37  * All rights reserved.
38  *
39  * This code is derived from software contributed to Berkeley by
40  * Adam de Boor.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *	This product includes software developed by the University of
53  *	California, Berkeley and its contributors.
54  * 4. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  */
70 
71 #ifndef MAKE_NATIVE
72 static char rcsid[] = "$NetBSD: var.c,v 1.183 2013/07/16 20:00:56 sjg Exp $";
73 #else
74 #include <sys/cdefs.h>
75 #ifndef lint
76 #if 0
77 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 3/19/94";
78 #else
79 __RCSID("$NetBSD: var.c,v 1.183 2013/07/16 20:00:56 sjg Exp $");
80 #endif
81 #endif /* not lint */
82 #endif
83 
84 /*-
85  * var.c --
86  *	Variable-handling functions
87  *
88  * Interface:
89  *	Var_Set		    Set the value of a variable in the given
90  *			    context. The variable is created if it doesn't
91  *			    yet exist. The value and variable name need not
92  *			    be preserved.
93  *
94  *	Var_Append	    Append more characters to an existing variable
95  *			    in the given context. The variable needn't
96  *			    exist already -- it will be created if it doesn't.
97  *			    A space is placed between the old value and the
98  *			    new one.
99  *
100  *	Var_Exists	    See if a variable exists.
101  *
102  *	Var_Value 	    Return the value of a variable in a context or
103  *			    NULL if the variable is undefined.
104  *
105  *	Var_Subst 	    Substitute named variable, or all variables if
106  *			    NULL in a string using
107  *			    the given context as the top-most one. If the
108  *			    third argument is non-zero, Parse_Error is
109  *			    called if any variables are undefined.
110  *
111  *	Var_Parse 	    Parse a variable expansion from a string and
112  *			    return the result and the number of characters
113  *			    consumed.
114  *
115  *	Var_Delete	    Delete a variable in a context.
116  *
117  *	Var_Init  	    Initialize this module.
118  *
119  * Debugging:
120  *	Var_Dump  	    Print out all variables defined in the given
121  *			    context.
122  *
123  * XXX: There's a lot of duplication in these functions.
124  */
125 
126 #include    <sys/stat.h>
127 #ifndef NO_REGEX
128 #include    <sys/types.h>
129 #include    <regex.h>
130 #endif
131 #include    <ctype.h>
132 #include    <inttypes.h>
133 #include    <stdlib.h>
134 #include    <limits.h>
135 #include    <time.h>
136 
137 #include    "make.h"
138 #include    "buf.h"
139 #include    "dir.h"
140 #include    "job.h"
141 
142 extern int makelevel;
143 /*
144  * XXX transition hack for FreeBSD ports.
145  * bsd.port.mk can set .MAKE.FreeBSD_UL=yes
146  * to cause us to treat :[LU] as aliases for :t[lu]
147  * To be reverted when ports converts to :t[lu] (when 8.3 is EOL)
148  */
149 #define MAKE_FREEBSD_UL ".MAKE.FreeBSD_UL"
150 #ifdef MAKE_FREEBSD_UL
151 static int FreeBSD_UL = FALSE;
152 #endif
153 
154 /*
155  * This lets us tell if we have replaced the original environ
156  * (which we cannot free).
157  */
158 char **savedEnv = NULL;
159 
160 /*
161  * This is a harmless return value for Var_Parse that can be used by Var_Subst
162  * to determine if there was an error in parsing -- easier than returning
163  * a flag, as things outside this module don't give a hoot.
164  */
165 char 	var_Error[] = "";
166 
167 /*
168  * Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
169  * set false. Why not just use a constant? Well, gcc likes to condense
170  * identical string instances...
171  */
172 static char	varNoError[] = "";
173 
174 /*
175  * Internally, variables are contained in four different contexts.
176  *	1) the environment. They may not be changed. If an environment
177  *	    variable is appended-to, the result is placed in the global
178  *	    context.
179  *	2) the global context. Variables set in the Makefile are located in
180  *	    the global context. It is the penultimate context searched when
181  *	    substituting.
182  *	3) the command-line context. All variables set on the command line
183  *	   are placed in this context. They are UNALTERABLE once placed here.
184  *	4) the local context. Each target has associated with it a context
185  *	   list. On this list are located the structures describing such
186  *	   local variables as $(@) and $(*)
187  * The four contexts are searched in the reverse order from which they are
188  * listed.
189  */
190 GNode          *VAR_GLOBAL;   /* variables from the makefile */
191 GNode          *VAR_CMD;      /* variables defined on the command-line */
192 
193 #define FIND_CMD	0x1   /* look in VAR_CMD when searching */
194 #define FIND_GLOBAL	0x2   /* look in VAR_GLOBAL as well */
195 #define FIND_ENV  	0x4   /* look in the environment also */
196 
197 typedef struct Var {
198     char          *name;	/* the variable's name */
199     Buffer	  val;		/* its value */
200     int		  flags;    	/* miscellaneous status flags */
201 #define VAR_IN_USE	1   	    /* Variable's value currently being used.
202 				     * Used to avoid recursion */
203 #define VAR_FROM_ENV	2   	    /* Variable comes from the environment */
204 #define VAR_JUNK  	4   	    /* Variable is a junk variable that
205 				     * should be destroyed when done with
206 				     * it. Used by Var_Parse for undefined,
207 				     * modified variables */
208 #define VAR_KEEP	8	    /* Variable is VAR_JUNK, but we found
209 				     * a use for it in some modifier and
210 				     * the value is therefore valid */
211 #define VAR_EXPORTED	16 	    /* Variable is exported */
212 #define VAR_REEXPORT	32	    /* Indicate if var needs re-export.
213 				     * This would be true if it contains $'s
214 				     */
215 #define VAR_FROM_CMD	64 	    /* Variable came from command line */
216 }  Var;
217 
218 /*
219  * Exporting vars is expensive so skip it if we can
220  */
221 #define VAR_EXPORTED_NONE	0
222 #define VAR_EXPORTED_YES	1
223 #define VAR_EXPORTED_ALL	2
224 static int var_exportedVars = VAR_EXPORTED_NONE;
225 /*
226  * We pass this to Var_Export when doing the initial export
227  * or after updating an exported var.
228  */
229 #define VAR_EXPORT_PARENT 1
230 
231 /* Var*Pattern flags */
232 #define VAR_SUB_GLOBAL	0x01	/* Apply substitution globally */
233 #define VAR_SUB_ONE	0x02	/* Apply substitution to one word */
234 #define VAR_SUB_MATCHED	0x04	/* There was a match */
235 #define VAR_MATCH_START	0x08	/* Match at start of word */
236 #define VAR_MATCH_END	0x10	/* Match at end of word */
237 #define VAR_NOSUBST	0x20	/* don't expand vars in VarGetPattern */
238 
239 /* Var_Set flags */
240 #define VAR_NO_EXPORT	0x01	/* do not export */
241 
242 typedef struct {
243     /*
244      * The following fields are set by Var_Parse() when it
245      * encounters modifiers that need to keep state for use by
246      * subsequent modifiers within the same variable expansion.
247      */
248     Byte	varSpace;	/* Word separator in expansions */
249     Boolean	oneBigWord;	/* TRUE if we will treat the variable as a
250 				 * single big word, even if it contains
251 				 * embedded spaces (as opposed to the
252 				 * usual behaviour of treating it as
253 				 * several space-separated words). */
254 } Var_Parse_State;
255 
256 /* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/",
257  * to VarSYSVMatch() for ":lhs=rhs". */
258 typedef struct {
259     const char   *lhs;	    /* String to match */
260     int		  leftLen; /* Length of string */
261     const char   *rhs;	    /* Replacement string (w/ &'s removed) */
262     int		  rightLen; /* Length of replacement */
263     int		  flags;
264 } VarPattern;
265 
266 /* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */
267 typedef struct {
268     GNode	*ctxt;		/* variable context */
269     char	*tvar;		/* name of temp var */
270     int		tvarLen;
271     char	*str;		/* string to expand */
272     int		strLen;
273     int		errnum;		/* errnum for not defined */
274 } VarLoop_t;
275 
276 #ifndef NO_REGEX
277 /* struct passed as 'void *' to VarRESubstitute() for ":C///" */
278 typedef struct {
279     regex_t	   re;
280     int		   nsub;
281     regmatch_t 	  *matches;
282     char 	  *replace;
283     int		   flags;
284 } VarREPattern;
285 #endif
286 
287 /* struct passed to VarSelectWords() for ":[start..end]" */
288 typedef struct {
289     int		start;		/* first word to select */
290     int		end;		/* last word to select */
291 } VarSelectWords_t;
292 
293 static Var *VarFind(const char *, GNode *, int);
294 static void VarAdd(const char *, const char *, GNode *);
295 static Boolean VarHead(GNode *, Var_Parse_State *,
296 			char *, Boolean, Buffer *, void *);
297 static Boolean VarTail(GNode *, Var_Parse_State *,
298 			char *, Boolean, Buffer *, void *);
299 static Boolean VarSuffix(GNode *, Var_Parse_State *,
300 			char *, Boolean, Buffer *, void *);
301 static Boolean VarRoot(GNode *, Var_Parse_State *,
302 			char *, Boolean, Buffer *, void *);
303 static Boolean VarMatch(GNode *, Var_Parse_State *,
304 			char *, Boolean, Buffer *, void *);
305 #ifdef SYSVVARSUB
306 static Boolean VarSYSVMatch(GNode *, Var_Parse_State *,
307 			char *, Boolean, Buffer *, void *);
308 #endif
309 static Boolean VarNoMatch(GNode *, Var_Parse_State *,
310 			char *, Boolean, Buffer *, void *);
311 #ifndef NO_REGEX
312 static void VarREError(int, regex_t *, const char *);
313 static Boolean VarRESubstitute(GNode *, Var_Parse_State *,
314 			char *, Boolean, Buffer *, void *);
315 #endif
316 static Boolean VarSubstitute(GNode *, Var_Parse_State *,
317 			char *, Boolean, Buffer *, void *);
318 static Boolean VarLoopExpand(GNode *, Var_Parse_State *,
319 			char *, Boolean, Buffer *, void *);
320 static char *VarGetPattern(GNode *, Var_Parse_State *,
321 			   int, const char **, int, int *, int *,
322 			   VarPattern *);
323 static char *VarQuote(char *);
324 static char *VarHash(char *);
325 static char *VarModify(GNode *, Var_Parse_State *,
326     const char *,
327     Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer *, void *),
328     void *);
329 static char *VarOrder(const char *, const char);
330 static char *VarUniq(const char *);
331 static int VarWordCompare(const void *, const void *);
332 static void VarPrintVar(void *);
333 
334 #define BROPEN	'{'
335 #define BRCLOSE	'}'
336 #define PROPEN	'('
337 #define PRCLOSE	')'
338 
339 /*-
340  *-----------------------------------------------------------------------
341  * VarFind --
342  *	Find the given variable in the given context and any other contexts
343  *	indicated.
344  *
345  * Input:
346  *	name		name to find
347  *	ctxt		context in which to find it
348  *	flags		FIND_GLOBAL set means to look in the
349  *			VAR_GLOBAL context as well. FIND_CMD set means
350  *			to look in the VAR_CMD context also. FIND_ENV
351  *			set means to look in the environment
352  *
353  * Results:
354  *	A pointer to the structure describing the desired variable or
355  *	NULL if the variable does not exist.
356  *
357  * Side Effects:
358  *	None
359  *-----------------------------------------------------------------------
360  */
361 static Var *
362 VarFind(const char *name, GNode *ctxt, int flags)
363 {
364     Hash_Entry         	*var;
365     Var			*v;
366 
367 	/*
368 	 * If the variable name begins with a '.', it could very well be one of
369 	 * the local ones.  We check the name against all the local variables
370 	 * and substitute the short version in for 'name' if it matches one of
371 	 * them.
372 	 */
373 	if (*name == '.' && isupper((unsigned char) name[1]))
374 		switch (name[1]) {
375 		case 'A':
376 			if (!strcmp(name, ".ALLSRC"))
377 				name = ALLSRC;
378 			if (!strcmp(name, ".ARCHIVE"))
379 				name = ARCHIVE;
380 			break;
381 		case 'I':
382 			if (!strcmp(name, ".IMPSRC"))
383 				name = IMPSRC;
384 			break;
385 		case 'M':
386 			if (!strcmp(name, ".MEMBER"))
387 				name = MEMBER;
388 			break;
389 		case 'O':
390 			if (!strcmp(name, ".OODATE"))
391 				name = OODATE;
392 			break;
393 		case 'P':
394 			if (!strcmp(name, ".PREFIX"))
395 				name = PREFIX;
396 			break;
397 		case 'T':
398 			if (!strcmp(name, ".TARGET"))
399 				name = TARGET;
400 			break;
401 		}
402 #ifdef notyet
403     /* for compatibility with gmake */
404     if (name[0] == '^' && name[1] == '\0')
405 	    name = ALLSRC;
406 #endif
407 
408     /*
409      * First look for the variable in the given context. If it's not there,
410      * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
411      * depending on the FIND_* flags in 'flags'
412      */
413     var = Hash_FindEntry(&ctxt->context, name);
414 
415     if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
416 	var = Hash_FindEntry(&VAR_CMD->context, name);
417     }
418     if (!checkEnvFirst && (var == NULL) && (flags & FIND_GLOBAL) &&
419 	(ctxt != VAR_GLOBAL))
420     {
421 	var = Hash_FindEntry(&VAR_GLOBAL->context, name);
422     }
423     if ((var == NULL) && (flags & FIND_ENV)) {
424 	char *env;
425 
426 	if ((env = getenv(name)) != NULL) {
427 	    int		len;
428 
429 	    v = bmake_malloc(sizeof(Var));
430 	    v->name = bmake_strdup(name);
431 
432 	    len = strlen(env);
433 
434 	    Buf_Init(&v->val, len + 1);
435 	    Buf_AddBytes(&v->val, len, env);
436 
437 	    v->flags = VAR_FROM_ENV;
438 	    return (v);
439 	} else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
440 		   (ctxt != VAR_GLOBAL))
441 	{
442 	    var = Hash_FindEntry(&VAR_GLOBAL->context, name);
443 	    if (var == NULL) {
444 		return NULL;
445 	    } else {
446 		return ((Var *)Hash_GetValue(var));
447 	    }
448 	} else {
449 	    return NULL;
450 	}
451     } else if (var == NULL) {
452 	return NULL;
453     } else {
454 	return ((Var *)Hash_GetValue(var));
455     }
456 }
457 
458 /*-
459  *-----------------------------------------------------------------------
460  * VarFreeEnv  --
461  *	If the variable is an environment variable, free it
462  *
463  * Input:
464  *	v		the variable
465  *	destroy		true if the value buffer should be destroyed.
466  *
467  * Results:
468  *	1 if it is an environment variable 0 ow.
469  *
470  * Side Effects:
471  *	The variable is free'ed if it is an environent variable.
472  *-----------------------------------------------------------------------
473  */
474 static Boolean
475 VarFreeEnv(Var *v, Boolean destroy)
476 {
477     if ((v->flags & VAR_FROM_ENV) == 0)
478 	return FALSE;
479     free(v->name);
480     Buf_Destroy(&v->val, destroy);
481     free(v);
482     return TRUE;
483 }
484 
485 /*-
486  *-----------------------------------------------------------------------
487  * VarAdd  --
488  *	Add a new variable of name name and value val to the given context
489  *
490  * Input:
491  *	name		name of variable to add
492  *	val		value to set it to
493  *	ctxt		context in which to set it
494  *
495  * Results:
496  *	None
497  *
498  * Side Effects:
499  *	The new variable is placed at the front of the given context
500  *	The name and val arguments are duplicated so they may
501  *	safely be freed.
502  *-----------------------------------------------------------------------
503  */
504 static void
505 VarAdd(const char *name, const char *val, GNode *ctxt)
506 {
507     Var   	  *v;
508     int		  len;
509     Hash_Entry    *h;
510 
511     v = bmake_malloc(sizeof(Var));
512 
513     len = val ? strlen(val) : 0;
514     Buf_Init(&v->val, len+1);
515     Buf_AddBytes(&v->val, len, val);
516 
517     v->flags = 0;
518 
519     h = Hash_CreateEntry(&ctxt->context, name, NULL);
520     Hash_SetValue(h, v);
521     v->name = h->name;
522     if (DEBUG(VAR)) {
523 	fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
524     }
525 }
526 
527 /*-
528  *-----------------------------------------------------------------------
529  * Var_Delete --
530  *	Remove a variable from a context.
531  *
532  * Results:
533  *	None.
534  *
535  * Side Effects:
536  *	The Var structure is removed and freed.
537  *
538  *-----------------------------------------------------------------------
539  */
540 void
541 Var_Delete(const char *name, GNode *ctxt)
542 {
543     Hash_Entry 	  *ln;
544     char *cp;
545 
546     if (strchr(name, '$')) {
547 	cp = Var_Subst(NULL, name, VAR_GLOBAL, 0);
548     } else {
549 	cp = (char *)name;
550     }
551     ln = Hash_FindEntry(&ctxt->context, cp);
552     if (DEBUG(VAR)) {
553 	fprintf(debug_file, "%s:delete %s%s\n",
554 	    ctxt->name, cp, ln ? "" : " (not found)");
555     }
556     if (cp != name) {
557 	free(cp);
558     }
559     if (ln != NULL) {
560 	Var 	  *v;
561 
562 	v = (Var *)Hash_GetValue(ln);
563 	if ((v->flags & VAR_EXPORTED)) {
564 	    unsetenv(v->name);
565 	}
566 	if (strcmp(MAKE_EXPORTED, v->name) == 0) {
567 	    var_exportedVars = VAR_EXPORTED_NONE;
568 	}
569 	if (v->name != ln->name)
570 		free(v->name);
571 	Hash_DeleteEntry(&ctxt->context, ln);
572 	Buf_Destroy(&v->val, TRUE);
573 	free(v);
574     }
575 }
576 
577 
578 /*
579  * Export a var.
580  * We ignore make internal variables (those which start with '.')
581  * Also we jump through some hoops to avoid calling setenv
582  * more than necessary since it can leak.
583  * We only manipulate flags of vars if 'parent' is set.
584  */
585 static int
586 Var_Export1(const char *name, int parent)
587 {
588     char tmp[BUFSIZ];
589     Var *v;
590     char *val = NULL;
591     int n;
592 
593     if (*name == '.')
594 	return 0;			/* skip internals */
595     if (!name[1]) {
596 	/*
597 	 * A single char.
598 	 * If it is one of the vars that should only appear in
599 	 * local context, skip it, else we can get Var_Subst
600 	 * into a loop.
601 	 */
602 	switch (name[0]) {
603 	case '@':
604 	case '%':
605 	case '*':
606 	case '!':
607 	    return 0;
608 	}
609     }
610     v = VarFind(name, VAR_GLOBAL, 0);
611     if (v == NULL) {
612 	return 0;
613     }
614     if (!parent &&
615 	(v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
616 	return 0;			/* nothing to do */
617     }
618     val = Buf_GetAll(&v->val, NULL);
619     if (strchr(val, '$')) {
620 	if (parent) {
621 	    /*
622 	     * Flag this as something we need to re-export.
623 	     * No point actually exporting it now though,
624 	     * the child can do it at the last minute.
625 	     */
626 	    v->flags |= (VAR_EXPORTED|VAR_REEXPORT);
627 	    return 1;
628 	}
629 	if (v->flags & VAR_IN_USE) {
630 	    /*
631 	     * We recursed while exporting in a child.
632 	     * This isn't going to end well, just skip it.
633 	     */
634 	    return 0;
635 	}
636 	n = snprintf(tmp, sizeof(tmp), "${%s}", name);
637 	if (n < (int)sizeof(tmp)) {
638 	    val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
639 	    setenv(name, val, 1);
640 	    free(val);
641 	}
642     } else {
643 	if (parent) {
644 	    v->flags &= ~VAR_REEXPORT;	/* once will do */
645 	}
646 	if (parent || !(v->flags & VAR_EXPORTED)) {
647 	    setenv(name, val, 1);
648 	}
649     }
650     /*
651      * This is so Var_Set knows to call Var_Export again...
652      */
653     if (parent) {
654 	v->flags |= VAR_EXPORTED;
655     }
656     return 1;
657 }
658 
659 /*
660  * This gets called from our children.
661  */
662 void
663 Var_ExportVars(void)
664 {
665     char tmp[BUFSIZ];
666     Hash_Entry         	*var;
667     Hash_Search 	state;
668     Var *v;
669     char *val;
670     int n;
671 
672     /*
673      * Several make's support this sort of mechanism for tracking
674      * recursion - but each uses a different name.
675      * We allow the makefiles to update MAKELEVEL and ensure
676      * children see a correctly incremented value.
677      */
678     snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
679     setenv(MAKE_LEVEL_ENV, tmp, 1);
680 
681     if (VAR_EXPORTED_NONE == var_exportedVars)
682 	return;
683 
684     if (VAR_EXPORTED_ALL == var_exportedVars) {
685 	/*
686 	 * Ouch! This is crazy...
687 	 */
688 	for (var = Hash_EnumFirst(&VAR_GLOBAL->context, &state);
689 	     var != NULL;
690 	     var = Hash_EnumNext(&state)) {
691 	    v = (Var *)Hash_GetValue(var);
692 	    Var_Export1(v->name, 0);
693 	}
694 	return;
695     }
696     /*
697      * We have a number of exported vars,
698      */
699     n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
700     if (n < (int)sizeof(tmp)) {
701 	char **av;
702 	char *as;
703 	int ac;
704 	int i;
705 
706 	val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
707 	av = brk_string(val, &ac, FALSE, &as);
708 	for (i = 0; i < ac; i++) {
709 	    Var_Export1(av[i], 0);
710 	}
711 	free(val);
712 	free(as);
713 	free(av);
714     }
715 }
716 
717 /*
718  * This is called when .export is seen or
719  * .MAKE.EXPORTED is modified.
720  * It is also called when any exported var is modified.
721  */
722 void
723 Var_Export(char *str, int isExport)
724 {
725     char *name;
726     char *val;
727     char **av;
728     char *as;
729     int track;
730     int ac;
731     int i;
732 
733     if (isExport && (!str || !str[0])) {
734 	var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
735 	return;
736     }
737 
738     if (strncmp(str, "-env", 4) == 0) {
739 	track = 0;
740 	str += 4;
741     } else {
742 	track = VAR_EXPORT_PARENT;
743     }
744     val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
745     av = brk_string(val, &ac, FALSE, &as);
746     for (i = 0; i < ac; i++) {
747 	name = av[i];
748 	if (!name[1]) {
749 	    /*
750 	     * A single char.
751 	     * If it is one of the vars that should only appear in
752 	     * local context, skip it, else we can get Var_Subst
753 	     * into a loop.
754 	     */
755 	    switch (name[0]) {
756 	    case '@':
757 	    case '%':
758 	    case '*':
759 	    case '!':
760 		continue;
761 	    }
762 	}
763 	if (Var_Export1(name, track)) {
764 	    if (VAR_EXPORTED_ALL != var_exportedVars)
765 		var_exportedVars = VAR_EXPORTED_YES;
766 	    if (isExport && track) {
767 		Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
768 	    }
769 	}
770     }
771     free(val);
772     free(as);
773     free(av);
774 }
775 
776 
777 /*
778  * This is called when .unexport[-env] is seen.
779  */
780 extern char **environ;
781 
782 void
783 Var_UnExport(char *str)
784 {
785     char tmp[BUFSIZ];
786     char *vlist;
787     char *cp;
788     Boolean unexport_env;
789     int n;
790 
791     if (!str || !str[0]) {
792 	return; 			/* assert? */
793     }
794 
795     vlist = NULL;
796 
797     str += 8;
798     unexport_env = (strncmp(str, "-env", 4) == 0);
799     if (unexport_env) {
800 	char **newenv;
801 
802 	cp = getenv(MAKE_LEVEL_ENV);	/* we should preserve this */
803 	if (environ == savedEnv) {
804 	    /* we have been here before! */
805 	    newenv = bmake_realloc(environ, 2 * sizeof(char *));
806 	} else {
807 	    if (savedEnv) {
808 		free(savedEnv);
809 		savedEnv = NULL;
810 	    }
811 	    newenv = bmake_malloc(2 * sizeof(char *));
812 	}
813 	if (!newenv)
814 	    return;
815 	/* Note: we cannot safely free() the original environ. */
816 	environ = savedEnv = newenv;
817 	newenv[0] = NULL;
818 	newenv[1] = NULL;
819 	setenv(MAKE_LEVEL_ENV, cp, 1);
820     } else {
821 	for (; *str != '\n' && isspace((unsigned char) *str); str++)
822 	    continue;
823 	if (str[0] && str[0] != '\n') {
824 	    vlist = str;
825 	}
826     }
827 
828     if (!vlist) {
829 	/* Using .MAKE.EXPORTED */
830 	n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
831 	if (n < (int)sizeof(tmp)) {
832 	    vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
833 	}
834     }
835     if (vlist) {
836 	Var *v;
837 	char **av;
838 	char *as;
839 	int ac;
840 	int i;
841 
842 	av = brk_string(vlist, &ac, FALSE, &as);
843 	for (i = 0; i < ac; i++) {
844 	    v = VarFind(av[i], VAR_GLOBAL, 0);
845 	    if (!v)
846 		continue;
847 	    if (!unexport_env &&
848 		(v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
849 		unsetenv(v->name);
850 	    }
851 	    v->flags &= ~(VAR_EXPORTED|VAR_REEXPORT);
852 	    /*
853 	     * If we are unexporting a list,
854 	     * remove each one from .MAKE.EXPORTED.
855 	     * If we are removing them all,
856 	     * just delete .MAKE.EXPORTED below.
857 	     */
858 	    if (vlist == str) {
859 		n = snprintf(tmp, sizeof(tmp),
860 			     "${" MAKE_EXPORTED ":N%s}", v->name);
861 		if (n < (int)sizeof(tmp)) {
862 		    cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
863 		    Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
864 		    free(cp);
865 		}
866 	    }
867 	}
868 	free(as);
869 	free(av);
870 	if (vlist != str) {
871 	    Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
872 	    free(vlist);
873 	}
874     }
875 }
876 
877 /*-
878  *-----------------------------------------------------------------------
879  * Var_Set --
880  *	Set the variable name to the value val in the given context.
881  *
882  * Input:
883  *	name		name of variable to set
884  *	val		value to give to the variable
885  *	ctxt		context in which to set it
886  *
887  * Results:
888  *	None.
889  *
890  * Side Effects:
891  *	If the variable doesn't yet exist, a new record is created for it.
892  *	Else the old value is freed and the new one stuck in its place
893  *
894  * Notes:
895  *	The variable is searched for only in its context before being
896  *	created in that context. I.e. if the context is VAR_GLOBAL,
897  *	only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
898  *	VAR_CMD->context is searched. This is done to avoid the literally
899  *	thousands of unnecessary strcmp's that used to be done to
900  *	set, say, $(@) or $(<).
901  *	If the context is VAR_GLOBAL though, we check if the variable
902  *	was set in VAR_CMD from the command line and skip it if so.
903  *-----------------------------------------------------------------------
904  */
905 void
906 Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
907 {
908     Var   *v;
909     char *expanded_name = NULL;
910 
911     /*
912      * We only look for a variable in the given context since anything set
913      * here will override anything in a lower context, so there's not much
914      * point in searching them all just to save a bit of memory...
915      */
916     if (strchr(name, '$') != NULL) {
917 	expanded_name = Var_Subst(NULL, name, ctxt, 0);
918 	if (expanded_name[0] == 0) {
919 	    if (DEBUG(VAR)) {
920 		fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
921 			"name expands to empty string - ignored\n",
922 			name, val);
923 	    }
924 	    free(expanded_name);
925 	    return;
926 	}
927 	name = expanded_name;
928     }
929     if (ctxt == VAR_GLOBAL) {
930 	v = VarFind(name, VAR_CMD, 0);
931 	if (v != NULL) {
932 	    if ((v->flags & VAR_FROM_CMD)) {
933 		if (DEBUG(VAR)) {
934 		    fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val);
935 		}
936 		goto out;
937 	    }
938 	    VarFreeEnv(v, TRUE);
939 	}
940     }
941     v = VarFind(name, ctxt, 0);
942     if (v == NULL) {
943 	if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
944 	    /*
945 	     * This var would normally prevent the same name being added
946 	     * to VAR_GLOBAL, so delete it from there if needed.
947 	     * Otherwise -V name may show the wrong value.
948 	     */
949 	    Var_Delete(name, VAR_GLOBAL);
950 	}
951 	VarAdd(name, val, ctxt);
952     } else {
953 	Buf_Empty(&v->val);
954 	Buf_AddBytes(&v->val, strlen(val), val);
955 
956 	if (DEBUG(VAR)) {
957 	    fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
958 	}
959 	if ((v->flags & VAR_EXPORTED)) {
960 	    Var_Export1(name, VAR_EXPORT_PARENT);
961 	}
962     }
963     /*
964      * Any variables given on the command line are automatically exported
965      * to the environment (as per POSIX standard)
966      */
967     if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
968 	if (v == NULL) {
969 	    /* we just added it */
970 	    v = VarFind(name, ctxt, 0);
971 	}
972 	if (v != NULL)
973 	    v->flags |= VAR_FROM_CMD;
974 	/*
975 	 * If requested, don't export these in the environment
976 	 * individually.  We still put them in MAKEOVERRIDES so
977 	 * that the command-line settings continue to override
978 	 * Makefile settings.
979 	 */
980 	if (varNoExportEnv != TRUE)
981 	    setenv(name, val, 1);
982 
983 	Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
984     }
985 
986 #ifdef MAKE_FREEBSD_UL
987     if (strcmp(MAKE_FREEBSD_UL, name) == 0) {
988 	FreeBSD_UL = getBoolean(MAKE_FREEBSD_UL, FALSE);
989     }
990 #endif
991 
992 
993  out:
994     if (expanded_name != NULL)
995 	free(expanded_name);
996     if (v != NULL)
997 	VarFreeEnv(v, TRUE);
998 }
999 
1000 /*-
1001  *-----------------------------------------------------------------------
1002  * Var_Append --
1003  *	The variable of the given name has the given value appended to it in
1004  *	the given context.
1005  *
1006  * Input:
1007  *	name		name of variable to modify
1008  *	val		String to append to it
1009  *	ctxt		Context in which this should occur
1010  *
1011  * Results:
1012  *	None
1013  *
1014  * Side Effects:
1015  *	If the variable doesn't exist, it is created. Else the strings
1016  *	are concatenated (with a space in between).
1017  *
1018  * Notes:
1019  *	Only if the variable is being sought in the global context is the
1020  *	environment searched.
1021  *	XXX: Knows its calling circumstances in that if called with ctxt
1022  *	an actual target, it will only search that context since only
1023  *	a local variable could be being appended to. This is actually
1024  *	a big win and must be tolerated.
1025  *-----------------------------------------------------------------------
1026  */
1027 void
1028 Var_Append(const char *name, const char *val, GNode *ctxt)
1029 {
1030     Var		   *v;
1031     Hash_Entry	   *h;
1032     char *expanded_name = NULL;
1033 
1034     if (strchr(name, '$') != NULL) {
1035 	expanded_name = Var_Subst(NULL, name, ctxt, 0);
1036 	if (expanded_name[0] == 0) {
1037 	    if (DEBUG(VAR)) {
1038 		fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
1039 			"name expands to empty string - ignored\n",
1040 			name, val);
1041 	    }
1042 	    free(expanded_name);
1043 	    return;
1044 	}
1045 	name = expanded_name;
1046     }
1047 
1048     v = VarFind(name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
1049 
1050     if (v == NULL) {
1051 	VarAdd(name, val, ctxt);
1052     } else {
1053 	Buf_AddByte(&v->val, ' ');
1054 	Buf_AddBytes(&v->val, strlen(val), val);
1055 
1056 	if (DEBUG(VAR)) {
1057 	    fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name,
1058 		   Buf_GetAll(&v->val, NULL));
1059 	}
1060 
1061 	if (v->flags & VAR_FROM_ENV) {
1062 	    /*
1063 	     * If the original variable came from the environment, we
1064 	     * have to install it in the global context (we could place
1065 	     * it in the environment, but then we should provide a way to
1066 	     * export other variables...)
1067 	     */
1068 	    v->flags &= ~VAR_FROM_ENV;
1069 	    h = Hash_CreateEntry(&ctxt->context, name, NULL);
1070 	    Hash_SetValue(h, v);
1071 	}
1072     }
1073     if (expanded_name != NULL)
1074 	free(expanded_name);
1075 }
1076 
1077 /*-
1078  *-----------------------------------------------------------------------
1079  * Var_Exists --
1080  *	See if the given variable exists.
1081  *
1082  * Input:
1083  *	name		Variable to find
1084  *	ctxt		Context in which to start search
1085  *
1086  * Results:
1087  *	TRUE if it does, FALSE if it doesn't
1088  *
1089  * Side Effects:
1090  *	None.
1091  *
1092  *-----------------------------------------------------------------------
1093  */
1094 Boolean
1095 Var_Exists(const char *name, GNode *ctxt)
1096 {
1097     Var		  *v;
1098     char          *cp;
1099 
1100     if ((cp = strchr(name, '$')) != NULL) {
1101 	cp = Var_Subst(NULL, name, ctxt, FALSE);
1102     }
1103     v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
1104     if (cp != NULL) {
1105 	free(cp);
1106     }
1107     if (v == NULL) {
1108 	return(FALSE);
1109     } else {
1110 	(void)VarFreeEnv(v, TRUE);
1111     }
1112     return(TRUE);
1113 }
1114 
1115 /*-
1116  *-----------------------------------------------------------------------
1117  * Var_Value --
1118  *	Return the value of the named variable in the given context
1119  *
1120  * Input:
1121  *	name		name to find
1122  *	ctxt		context in which to search for it
1123  *
1124  * Results:
1125  *	The value if the variable exists, NULL if it doesn't
1126  *
1127  * Side Effects:
1128  *	None
1129  *-----------------------------------------------------------------------
1130  */
1131 char *
1132 Var_Value(const char *name, GNode *ctxt, char **frp)
1133 {
1134     Var            *v;
1135 
1136     v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1137     *frp = NULL;
1138     if (v != NULL) {
1139 	char *p = (Buf_GetAll(&v->val, NULL));
1140 	if (VarFreeEnv(v, FALSE))
1141 	    *frp = p;
1142 	return p;
1143     } else {
1144 	return NULL;
1145     }
1146 }
1147 
1148 /*-
1149  *-----------------------------------------------------------------------
1150  * VarHead --
1151  *	Remove the tail of the given word and place the result in the given
1152  *	buffer.
1153  *
1154  * Input:
1155  *	word		Word to trim
1156  *	addSpace	True if need to add a space to the buffer
1157  *			before sticking in the head
1158  *	buf		Buffer in which to store it
1159  *
1160  * Results:
1161  *	TRUE if characters were added to the buffer (a space needs to be
1162  *	added to the buffer before the next word).
1163  *
1164  * Side Effects:
1165  *	The trimmed word is added to the buffer.
1166  *
1167  *-----------------------------------------------------------------------
1168  */
1169 static Boolean
1170 VarHead(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1171 	char *word, Boolean addSpace, Buffer *buf,
1172 	void *dummy)
1173 {
1174     char *slash;
1175 
1176     slash = strrchr(word, '/');
1177     if (slash != NULL) {
1178 	if (addSpace && vpstate->varSpace) {
1179 	    Buf_AddByte(buf, vpstate->varSpace);
1180 	}
1181 	*slash = '\0';
1182 	Buf_AddBytes(buf, strlen(word), word);
1183 	*slash = '/';
1184 	return (TRUE);
1185     } else {
1186 	/*
1187 	 * If no directory part, give . (q.v. the POSIX standard)
1188 	 */
1189 	if (addSpace && vpstate->varSpace)
1190 	    Buf_AddByte(buf, vpstate->varSpace);
1191 	Buf_AddByte(buf, '.');
1192     }
1193     return(dummy ? TRUE : TRUE);
1194 }
1195 
1196 /*-
1197  *-----------------------------------------------------------------------
1198  * VarTail --
1199  *	Remove the head of the given word and place the result in the given
1200  *	buffer.
1201  *
1202  * Input:
1203  *	word		Word to trim
1204  *	addSpace	True if need to add a space to the buffer
1205  *			before adding the tail
1206  *	buf		Buffer in which to store it
1207  *
1208  * Results:
1209  *	TRUE if characters were added to the buffer (a space needs to be
1210  *	added to the buffer before the next word).
1211  *
1212  * Side Effects:
1213  *	The trimmed word is added to the buffer.
1214  *
1215  *-----------------------------------------------------------------------
1216  */
1217 static Boolean
1218 VarTail(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1219 	char *word, Boolean addSpace, Buffer *buf,
1220 	void *dummy)
1221 {
1222     char *slash;
1223 
1224     if (addSpace && vpstate->varSpace) {
1225 	Buf_AddByte(buf, vpstate->varSpace);
1226     }
1227 
1228     slash = strrchr(word, '/');
1229     if (slash != NULL) {
1230 	*slash++ = '\0';
1231 	Buf_AddBytes(buf, strlen(slash), slash);
1232 	slash[-1] = '/';
1233     } else {
1234 	Buf_AddBytes(buf, strlen(word), word);
1235     }
1236     return (dummy ? TRUE : TRUE);
1237 }
1238 
1239 /*-
1240  *-----------------------------------------------------------------------
1241  * VarSuffix --
1242  *	Place the suffix of the given word in the given buffer.
1243  *
1244  * Input:
1245  *	word		Word to trim
1246  *	addSpace	TRUE if need to add a space before placing the
1247  *			suffix in the buffer
1248  *	buf		Buffer in which to store it
1249  *
1250  * Results:
1251  *	TRUE if characters were added to the buffer (a space needs to be
1252  *	added to the buffer before the next word).
1253  *
1254  * Side Effects:
1255  *	The suffix from the word is placed in the buffer.
1256  *
1257  *-----------------------------------------------------------------------
1258  */
1259 static Boolean
1260 VarSuffix(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1261 	  char *word, Boolean addSpace, Buffer *buf,
1262 	  void *dummy)
1263 {
1264     char *dot;
1265 
1266     dot = strrchr(word, '.');
1267     if (dot != NULL) {
1268 	if (addSpace && vpstate->varSpace) {
1269 	    Buf_AddByte(buf, vpstate->varSpace);
1270 	}
1271 	*dot++ = '\0';
1272 	Buf_AddBytes(buf, strlen(dot), dot);
1273 	dot[-1] = '.';
1274 	addSpace = TRUE;
1275     }
1276     return (dummy ? addSpace : addSpace);
1277 }
1278 
1279 /*-
1280  *-----------------------------------------------------------------------
1281  * VarRoot --
1282  *	Remove the suffix of the given word and place the result in the
1283  *	buffer.
1284  *
1285  * Input:
1286  *	word		Word to trim
1287  *	addSpace	TRUE if need to add a space to the buffer
1288  *			before placing the root in it
1289  *	buf		Buffer in which to store it
1290  *
1291  * Results:
1292  *	TRUE if characters were added to the buffer (a space needs to be
1293  *	added to the buffer before the next word).
1294  *
1295  * Side Effects:
1296  *	The trimmed word is added to the buffer.
1297  *
1298  *-----------------------------------------------------------------------
1299  */
1300 static Boolean
1301 VarRoot(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1302 	char *word, Boolean addSpace, Buffer *buf,
1303 	void *dummy)
1304 {
1305     char *dot;
1306 
1307     if (addSpace && vpstate->varSpace) {
1308 	Buf_AddByte(buf, vpstate->varSpace);
1309     }
1310 
1311     dot = strrchr(word, '.');
1312     if (dot != NULL) {
1313 	*dot = '\0';
1314 	Buf_AddBytes(buf, strlen(word), word);
1315 	*dot = '.';
1316     } else {
1317 	Buf_AddBytes(buf, strlen(word), word);
1318     }
1319     return (dummy ? TRUE : TRUE);
1320 }
1321 
1322 /*-
1323  *-----------------------------------------------------------------------
1324  * VarMatch --
1325  *	Place the word in the buffer if it matches the given pattern.
1326  *	Callback function for VarModify to implement the :M modifier.
1327  *
1328  * Input:
1329  *	word		Word to examine
1330  *	addSpace	TRUE if need to add a space to the buffer
1331  *			before adding the word, if it matches
1332  *	buf		Buffer in which to store it
1333  *	pattern		Pattern the word must match
1334  *
1335  * Results:
1336  *	TRUE if a space should be placed in the buffer before the next
1337  *	word.
1338  *
1339  * Side Effects:
1340  *	The word may be copied to the buffer.
1341  *
1342  *-----------------------------------------------------------------------
1343  */
1344 static Boolean
1345 VarMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1346 	 char *word, Boolean addSpace, Buffer *buf,
1347 	 void *pattern)
1348 {
1349     if (DEBUG(VAR))
1350 	fprintf(debug_file, "VarMatch [%s] [%s]\n", word, (char *)pattern);
1351     if (Str_Match(word, (char *)pattern)) {
1352 	if (addSpace && vpstate->varSpace) {
1353 	    Buf_AddByte(buf, vpstate->varSpace);
1354 	}
1355 	addSpace = TRUE;
1356 	Buf_AddBytes(buf, strlen(word), word);
1357     }
1358     return(addSpace);
1359 }
1360 
1361 #ifdef SYSVVARSUB
1362 /*-
1363  *-----------------------------------------------------------------------
1364  * VarSYSVMatch --
1365  *	Place the word in the buffer if it matches the given pattern.
1366  *	Callback function for VarModify to implement the System V %
1367  *	modifiers.
1368  *
1369  * Input:
1370  *	word		Word to examine
1371  *	addSpace	TRUE if need to add a space to the buffer
1372  *			before adding the word, if it matches
1373  *	buf		Buffer in which to store it
1374  *	patp		Pattern the word must match
1375  *
1376  * Results:
1377  *	TRUE if a space should be placed in the buffer before the next
1378  *	word.
1379  *
1380  * Side Effects:
1381  *	The word may be copied to the buffer.
1382  *
1383  *-----------------------------------------------------------------------
1384  */
1385 static Boolean
1386 VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
1387 	     char *word, Boolean addSpace, Buffer *buf,
1388 	     void *patp)
1389 {
1390     int len;
1391     char *ptr;
1392     VarPattern 	  *pat = (VarPattern *)patp;
1393     char *varexp;
1394 
1395     if (addSpace && vpstate->varSpace)
1396 	Buf_AddByte(buf, vpstate->varSpace);
1397 
1398     addSpace = TRUE;
1399 
1400     if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
1401         varexp = Var_Subst(NULL, pat->rhs, ctx, 0);
1402 	Str_SYSVSubst(buf, varexp, ptr, len);
1403 	free(varexp);
1404     } else {
1405 	Buf_AddBytes(buf, strlen(word), word);
1406     }
1407 
1408     return(addSpace);
1409 }
1410 #endif
1411 
1412 
1413 /*-
1414  *-----------------------------------------------------------------------
1415  * VarNoMatch --
1416  *	Place the word in the buffer if it doesn't match the given pattern.
1417  *	Callback function for VarModify to implement the :N modifier.
1418  *
1419  * Input:
1420  *	word		Word to examine
1421  *	addSpace	TRUE if need to add a space to the buffer
1422  *			before adding the word, if it matches
1423  *	buf		Buffer in which to store it
1424  *	pattern		Pattern the word must match
1425  *
1426  * Results:
1427  *	TRUE if a space should be placed in the buffer before the next
1428  *	word.
1429  *
1430  * Side Effects:
1431  *	The word may be copied to the buffer.
1432  *
1433  *-----------------------------------------------------------------------
1434  */
1435 static Boolean
1436 VarNoMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1437 	   char *word, Boolean addSpace, Buffer *buf,
1438 	   void *pattern)
1439 {
1440     if (!Str_Match(word, (char *)pattern)) {
1441 	if (addSpace && vpstate->varSpace) {
1442 	    Buf_AddByte(buf, vpstate->varSpace);
1443 	}
1444 	addSpace = TRUE;
1445 	Buf_AddBytes(buf, strlen(word), word);
1446     }
1447     return(addSpace);
1448 }
1449 
1450 
1451 /*-
1452  *-----------------------------------------------------------------------
1453  * VarSubstitute --
1454  *	Perform a string-substitution on the given word, placing the
1455  *	result in the passed buffer.
1456  *
1457  * Input:
1458  *	word		Word to modify
1459  *	addSpace	True if space should be added before
1460  *			other characters
1461  *	buf		Buffer for result
1462  *	patternp	Pattern for substitution
1463  *
1464  * Results:
1465  *	TRUE if a space is needed before more characters are added.
1466  *
1467  * Side Effects:
1468  *	None.
1469  *
1470  *-----------------------------------------------------------------------
1471  */
1472 static Boolean
1473 VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1474 	      char *word, Boolean addSpace, Buffer *buf,
1475 	      void *patternp)
1476 {
1477     int  	wordLen;    /* Length of word */
1478     char 	*cp;	    /* General pointer */
1479     VarPattern	*pattern = (VarPattern *)patternp;
1480 
1481     wordLen = strlen(word);
1482     if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) !=
1483 	(VAR_SUB_ONE|VAR_SUB_MATCHED)) {
1484 	/*
1485 	 * Still substituting -- break it down into simple anchored cases
1486 	 * and if none of them fits, perform the general substitution case.
1487 	 */
1488 	if ((pattern->flags & VAR_MATCH_START) &&
1489 	    (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
1490 		/*
1491 		 * Anchored at start and beginning of word matches pattern
1492 		 */
1493 		if ((pattern->flags & VAR_MATCH_END) &&
1494 		    (wordLen == pattern->leftLen)) {
1495 			/*
1496 			 * Also anchored at end and matches to the end (word
1497 			 * is same length as pattern) add space and rhs only
1498 			 * if rhs is non-null.
1499 			 */
1500 			if (pattern->rightLen != 0) {
1501 			    if (addSpace && vpstate->varSpace) {
1502 				Buf_AddByte(buf, vpstate->varSpace);
1503 			    }
1504 			    addSpace = TRUE;
1505 			    Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
1506 			}
1507 			pattern->flags |= VAR_SUB_MATCHED;
1508 		} else if (pattern->flags & VAR_MATCH_END) {
1509 		    /*
1510 		     * Doesn't match to end -- copy word wholesale
1511 		     */
1512 		    goto nosub;
1513 		} else {
1514 		    /*
1515 		     * Matches at start but need to copy in trailing characters
1516 		     */
1517 		    if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
1518 			if (addSpace && vpstate->varSpace) {
1519 			    Buf_AddByte(buf, vpstate->varSpace);
1520 			}
1521 			addSpace = TRUE;
1522 		    }
1523 		    Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
1524 		    Buf_AddBytes(buf, wordLen - pattern->leftLen,
1525 				 (word + pattern->leftLen));
1526 		    pattern->flags |= VAR_SUB_MATCHED;
1527 		}
1528 	} else if (pattern->flags & VAR_MATCH_START) {
1529 	    /*
1530 	     * Had to match at start of word and didn't -- copy whole word.
1531 	     */
1532 	    goto nosub;
1533 	} else if (pattern->flags & VAR_MATCH_END) {
1534 	    /*
1535 	     * Anchored at end, Find only place match could occur (leftLen
1536 	     * characters from the end of the word) and see if it does. Note
1537 	     * that because the $ will be left at the end of the lhs, we have
1538 	     * to use strncmp.
1539 	     */
1540 	    cp = word + (wordLen - pattern->leftLen);
1541 	    if ((cp >= word) &&
1542 		(strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
1543 		/*
1544 		 * Match found. If we will place characters in the buffer,
1545 		 * add a space before hand as indicated by addSpace, then
1546 		 * stuff in the initial, unmatched part of the word followed
1547 		 * by the right-hand-side.
1548 		 */
1549 		if (((cp - word) + pattern->rightLen) != 0) {
1550 		    if (addSpace && vpstate->varSpace) {
1551 			Buf_AddByte(buf, vpstate->varSpace);
1552 		    }
1553 		    addSpace = TRUE;
1554 		}
1555 		Buf_AddBytes(buf, cp - word, word);
1556 		Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
1557 		pattern->flags |= VAR_SUB_MATCHED;
1558 	    } else {
1559 		/*
1560 		 * Had to match at end and didn't. Copy entire word.
1561 		 */
1562 		goto nosub;
1563 	    }
1564 	} else {
1565 	    /*
1566 	     * Pattern is unanchored: search for the pattern in the word using
1567 	     * String_FindSubstring, copying unmatched portions and the
1568 	     * right-hand-side for each match found, handling non-global
1569 	     * substitutions correctly, etc. When the loop is done, any
1570 	     * remaining part of the word (word and wordLen are adjusted
1571 	     * accordingly through the loop) is copied straight into the
1572 	     * buffer.
1573 	     * addSpace is set FALSE as soon as a space is added to the
1574 	     * buffer.
1575 	     */
1576 	    Boolean done;
1577 	    int origSize;
1578 
1579 	    done = FALSE;
1580 	    origSize = Buf_Size(buf);
1581 	    while (!done) {
1582 		cp = Str_FindSubstring(word, pattern->lhs);
1583 		if (cp != NULL) {
1584 		    if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
1585 			Buf_AddByte(buf, vpstate->varSpace);
1586 			addSpace = FALSE;
1587 		    }
1588 		    Buf_AddBytes(buf, cp-word, word);
1589 		    Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
1590 		    wordLen -= (cp - word) + pattern->leftLen;
1591 		    word = cp + pattern->leftLen;
1592 		    if (wordLen == 0) {
1593 			done = TRUE;
1594 		    }
1595 		    if ((pattern->flags & VAR_SUB_GLOBAL) == 0) {
1596 			done = TRUE;
1597 		    }
1598 		    pattern->flags |= VAR_SUB_MATCHED;
1599 		} else {
1600 		    done = TRUE;
1601 		}
1602 	    }
1603 	    if (wordLen != 0) {
1604 		if (addSpace && vpstate->varSpace) {
1605 		    Buf_AddByte(buf, vpstate->varSpace);
1606 		}
1607 		Buf_AddBytes(buf, wordLen, word);
1608 	    }
1609 	    /*
1610 	     * If added characters to the buffer, need to add a space
1611 	     * before we add any more. If we didn't add any, just return
1612 	     * the previous value of addSpace.
1613 	     */
1614 	    return ((Buf_Size(buf) != origSize) || addSpace);
1615 	}
1616 	return (addSpace);
1617     }
1618  nosub:
1619     if (addSpace && vpstate->varSpace) {
1620 	Buf_AddByte(buf, vpstate->varSpace);
1621     }
1622     Buf_AddBytes(buf, wordLen, word);
1623     return(TRUE);
1624 }
1625 
1626 #ifndef NO_REGEX
1627 /*-
1628  *-----------------------------------------------------------------------
1629  * VarREError --
1630  *	Print the error caused by a regcomp or regexec call.
1631  *
1632  * Results:
1633  *	None.
1634  *
1635  * Side Effects:
1636  *	An error gets printed.
1637  *
1638  *-----------------------------------------------------------------------
1639  */
1640 static void
1641 VarREError(int errnum, regex_t *pat, const char *str)
1642 {
1643     char *errbuf;
1644     int errlen;
1645 
1646     errlen = regerror(errnum, pat, 0, 0);
1647     errbuf = bmake_malloc(errlen);
1648     regerror(errnum, pat, errbuf, errlen);
1649     Error("%s: %s", str, errbuf);
1650     free(errbuf);
1651 }
1652 
1653 
1654 /*-
1655  *-----------------------------------------------------------------------
1656  * VarRESubstitute --
1657  *	Perform a regex substitution on the given word, placing the
1658  *	result in the passed buffer.
1659  *
1660  * Results:
1661  *	TRUE if a space is needed before more characters are added.
1662  *
1663  * Side Effects:
1664  *	None.
1665  *
1666  *-----------------------------------------------------------------------
1667  */
1668 static Boolean
1669 VarRESubstitute(GNode *ctx MAKE_ATTR_UNUSED,
1670 		Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
1671 		char *word, Boolean addSpace, Buffer *buf,
1672 		void *patternp)
1673 {
1674     VarREPattern *pat;
1675     int xrv;
1676     char *wp;
1677     char *rp;
1678     int added;
1679     int flags = 0;
1680 
1681 #define MAYBE_ADD_SPACE()		\
1682 	if (addSpace && !added)		\
1683 	    Buf_AddByte(buf, ' ');	\
1684 	added = 1
1685 
1686     added = 0;
1687     wp = word;
1688     pat = patternp;
1689 
1690     if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
1691 	(VAR_SUB_ONE|VAR_SUB_MATCHED))
1692 	xrv = REG_NOMATCH;
1693     else {
1694     tryagain:
1695 	xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
1696     }
1697 
1698     switch (xrv) {
1699     case 0:
1700 	pat->flags |= VAR_SUB_MATCHED;
1701 	if (pat->matches[0].rm_so > 0) {
1702 	    MAYBE_ADD_SPACE();
1703 	    Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
1704 	}
1705 
1706 	for (rp = pat->replace; *rp; rp++) {
1707 	    if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
1708 		MAYBE_ADD_SPACE();
1709 		Buf_AddByte(buf,rp[1]);
1710 		rp++;
1711 	    }
1712 	    else if ((*rp == '&') ||
1713 		((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
1714 		int n;
1715 		const char *subbuf;
1716 		int sublen;
1717 		char errstr[3];
1718 
1719 		if (*rp == '&') {
1720 		    n = 0;
1721 		    errstr[0] = '&';
1722 		    errstr[1] = '\0';
1723 		} else {
1724 		    n = rp[1] - '0';
1725 		    errstr[0] = '\\';
1726 		    errstr[1] = rp[1];
1727 		    errstr[2] = '\0';
1728 		    rp++;
1729 		}
1730 
1731 		if (n > pat->nsub) {
1732 		    Error("No subexpression %s", &errstr[0]);
1733 		    subbuf = "";
1734 		    sublen = 0;
1735 		} else if ((pat->matches[n].rm_so == -1) &&
1736 			   (pat->matches[n].rm_eo == -1)) {
1737 		    Error("No match for subexpression %s", &errstr[0]);
1738 		    subbuf = "";
1739 		    sublen = 0;
1740 	        } else {
1741 		    subbuf = wp + pat->matches[n].rm_so;
1742 		    sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
1743 		}
1744 
1745 		if (sublen > 0) {
1746 		    MAYBE_ADD_SPACE();
1747 		    Buf_AddBytes(buf, sublen, subbuf);
1748 		}
1749 	    } else {
1750 		MAYBE_ADD_SPACE();
1751 		Buf_AddByte(buf, *rp);
1752 	    }
1753 	}
1754 	wp += pat->matches[0].rm_eo;
1755 	if (pat->flags & VAR_SUB_GLOBAL) {
1756 	    flags |= REG_NOTBOL;
1757 	    if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
1758 		MAYBE_ADD_SPACE();
1759 		Buf_AddByte(buf, *wp);
1760 		wp++;
1761 
1762 	    }
1763 	    if (*wp)
1764 		goto tryagain;
1765 	}
1766 	if (*wp) {
1767 	    MAYBE_ADD_SPACE();
1768 	    Buf_AddBytes(buf, strlen(wp), wp);
1769 	}
1770 	break;
1771     default:
1772 	VarREError(xrv, &pat->re, "Unexpected regex error");
1773        /* fall through */
1774     case REG_NOMATCH:
1775 	if (*wp) {
1776 	    MAYBE_ADD_SPACE();
1777 	    Buf_AddBytes(buf,strlen(wp),wp);
1778 	}
1779 	break;
1780     }
1781     return(addSpace||added);
1782 }
1783 #endif
1784 
1785 
1786 
1787 /*-
1788  *-----------------------------------------------------------------------
1789  * VarLoopExpand --
1790  *	Implements the :@<temp>@<string>@ modifier of ODE make.
1791  *	We set the temp variable named in pattern.lhs to word and expand
1792  *	pattern.rhs storing the result in the passed buffer.
1793  *
1794  * Input:
1795  *	word		Word to modify
1796  *	addSpace	True if space should be added before
1797  *			other characters
1798  *	buf		Buffer for result
1799  *	pattern		Datafor substitution
1800  *
1801  * Results:
1802  *	TRUE if a space is needed before more characters are added.
1803  *
1804  * Side Effects:
1805  *	None.
1806  *
1807  *-----------------------------------------------------------------------
1808  */
1809 static Boolean
1810 VarLoopExpand(GNode *ctx MAKE_ATTR_UNUSED,
1811 	      Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
1812 	      char *word, Boolean addSpace, Buffer *buf,
1813 	      void *loopp)
1814 {
1815     VarLoop_t	*loop = (VarLoop_t *)loopp;
1816     char *s;
1817     int slen;
1818 
1819     if (word && *word) {
1820         Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
1821         s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum);
1822         if (s != NULL && *s != '\0') {
1823             if (addSpace && *s != '\n')
1824                 Buf_AddByte(buf, ' ');
1825             Buf_AddBytes(buf, (slen = strlen(s)), s);
1826             addSpace = (slen > 0 && s[slen - 1] != '\n');
1827             free(s);
1828         }
1829     }
1830     return addSpace;
1831 }
1832 
1833 
1834 /*-
1835  *-----------------------------------------------------------------------
1836  * VarSelectWords --
1837  *	Implements the :[start..end] modifier.
1838  *	This is a special case of VarModify since we want to be able
1839  *	to scan the list backwards if start > end.
1840  *
1841  * Input:
1842  *	str		String whose words should be trimmed
1843  *	seldata		words to select
1844  *
1845  * Results:
1846  *	A string of all the words selected.
1847  *
1848  * Side Effects:
1849  *	None.
1850  *
1851  *-----------------------------------------------------------------------
1852  */
1853 static char *
1854 VarSelectWords(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1855 	       const char *str, VarSelectWords_t *seldata)
1856 {
1857     Buffer  	  buf;		    /* Buffer for the new string */
1858     Boolean 	  addSpace; 	    /* TRUE if need to add a space to the
1859 				     * buffer before adding the trimmed
1860 				     * word */
1861     char **av;			    /* word list */
1862     char *as;			    /* word list memory */
1863     int ac, i;
1864     int start, end, step;
1865 
1866     Buf_Init(&buf, 0);
1867     addSpace = FALSE;
1868 
1869     if (vpstate->oneBigWord) {
1870 	/* fake what brk_string() would do if there were only one word */
1871 	ac = 1;
1872     	av = bmake_malloc((ac + 1) * sizeof(char *));
1873 	as = bmake_strdup(str);
1874 	av[0] = as;
1875 	av[1] = NULL;
1876     } else {
1877 	av = brk_string(str, &ac, FALSE, &as);
1878     }
1879 
1880     /*
1881      * Now sanitize seldata.
1882      * If seldata->start or seldata->end are negative, convert them to
1883      * the positive equivalents (-1 gets converted to argc, -2 gets
1884      * converted to (argc-1), etc.).
1885      */
1886     if (seldata->start < 0)
1887 	seldata->start = ac + seldata->start + 1;
1888     if (seldata->end < 0)
1889 	seldata->end = ac + seldata->end + 1;
1890 
1891     /*
1892      * We avoid scanning more of the list than we need to.
1893      */
1894     if (seldata->start > seldata->end) {
1895 	start = MIN(ac, seldata->start) - 1;
1896 	end = MAX(0, seldata->end - 1);
1897 	step = -1;
1898     } else {
1899 	start = MAX(0, seldata->start - 1);
1900 	end = MIN(ac, seldata->end);
1901 	step = 1;
1902     }
1903 
1904     for (i = start;
1905 	 (step < 0 && i >= end) || (step > 0 && i < end);
1906 	 i += step) {
1907 	if (av[i] && *av[i]) {
1908 	    if (addSpace && vpstate->varSpace) {
1909 		Buf_AddByte(&buf, vpstate->varSpace);
1910 	    }
1911 	    Buf_AddBytes(&buf, strlen(av[i]), av[i]);
1912 	    addSpace = TRUE;
1913 	}
1914     }
1915 
1916     free(as);
1917     free(av);
1918 
1919     return Buf_Destroy(&buf, FALSE);
1920 }
1921 
1922 
1923 /*-
1924  * VarRealpath --
1925  *	Replace each word with the result of realpath()
1926  *	if successful.
1927  */
1928 static Boolean
1929 VarRealpath(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1930 	    char *word, Boolean addSpace, Buffer *buf,
1931 	    void *patternp MAKE_ATTR_UNUSED)
1932 {
1933 	struct stat st;
1934 	char rbuf[MAXPATHLEN];
1935 	char *rp;
1936 
1937 	if (addSpace && vpstate->varSpace) {
1938 	    Buf_AddByte(buf, vpstate->varSpace);
1939 	}
1940 	addSpace = TRUE;
1941 	rp = realpath(word, rbuf);
1942 	if (rp && *rp == '/' && stat(rp, &st) == 0)
1943 		word = rp;
1944 
1945 	Buf_AddBytes(buf, strlen(word), word);
1946 	return(addSpace);
1947 }
1948 
1949 /*-
1950  *-----------------------------------------------------------------------
1951  * VarModify --
1952  *	Modify each of the words of the passed string using the given
1953  *	function. Used to implement all modifiers.
1954  *
1955  * Input:
1956  *	str		String whose words should be trimmed
1957  *	modProc		Function to use to modify them
1958  *	datum		Datum to pass it
1959  *
1960  * Results:
1961  *	A string of all the words modified appropriately.
1962  *
1963  * Side Effects:
1964  *	None.
1965  *
1966  *-----------------------------------------------------------------------
1967  */
1968 static char *
1969 VarModify(GNode *ctx, Var_Parse_State *vpstate,
1970     const char *str,
1971     Boolean (*modProc)(GNode *, Var_Parse_State *, char *,
1972 		       Boolean, Buffer *, void *),
1973     void *datum)
1974 {
1975     Buffer  	  buf;		    /* Buffer for the new string */
1976     Boolean 	  addSpace; 	    /* TRUE if need to add a space to the
1977 				     * buffer before adding the trimmed
1978 				     * word */
1979     char **av;			    /* word list */
1980     char *as;			    /* word list memory */
1981     int ac, i;
1982 
1983     Buf_Init(&buf, 0);
1984     addSpace = FALSE;
1985 
1986     if (vpstate->oneBigWord) {
1987 	/* fake what brk_string() would do if there were only one word */
1988 	ac = 1;
1989     	av = bmake_malloc((ac + 1) * sizeof(char *));
1990 	as = bmake_strdup(str);
1991 	av[0] = as;
1992 	av[1] = NULL;
1993     } else {
1994 	av = brk_string(str, &ac, FALSE, &as);
1995     }
1996 
1997     for (i = 0; i < ac; i++) {
1998 	addSpace = (*modProc)(ctx, vpstate, av[i], addSpace, &buf, datum);
1999     }
2000 
2001     free(as);
2002     free(av);
2003 
2004     return Buf_Destroy(&buf, FALSE);
2005 }
2006 
2007 
2008 static int
2009 VarWordCompare(const void *a, const void *b)
2010 {
2011 	int r = strcmp(*(const char * const *)a, *(const char * const *)b);
2012 	return r;
2013 }
2014 
2015 /*-
2016  *-----------------------------------------------------------------------
2017  * VarOrder --
2018  *	Order the words in the string.
2019  *
2020  * Input:
2021  *	str		String whose words should be sorted.
2022  *	otype		How to order: s - sort, x - random.
2023  *
2024  * Results:
2025  *	A string containing the words ordered.
2026  *
2027  * Side Effects:
2028  *	None.
2029  *
2030  *-----------------------------------------------------------------------
2031  */
2032 static char *
2033 VarOrder(const char *str, const char otype)
2034 {
2035     Buffer  	  buf;		    /* Buffer for the new string */
2036     char **av;			    /* word list [first word does not count] */
2037     char *as;			    /* word list memory */
2038     int ac, i;
2039 
2040     Buf_Init(&buf, 0);
2041 
2042     av = brk_string(str, &ac, FALSE, &as);
2043 
2044     if (ac > 0)
2045 	switch (otype) {
2046 	case 's':	/* sort alphabetically */
2047 	    qsort(av, ac, sizeof(char *), VarWordCompare);
2048 	    break;
2049 	case 'x':	/* randomize */
2050 	{
2051 	    int rndidx;
2052 	    char *t;
2053 
2054 	    /*
2055 	     * We will use [ac..2] range for mod factors. This will produce
2056 	     * random numbers in [(ac-1)..0] interval, and minimal
2057 	     * reasonable value for mod factor is 2 (the mod 1 will produce
2058 	     * 0 with probability 1).
2059 	     */
2060 	    for (i = ac-1; i > 0; i--) {
2061 		rndidx = random() % (i + 1);
2062 		if (i != rndidx) {
2063 		    t = av[i];
2064 		    av[i] = av[rndidx];
2065 		    av[rndidx] = t;
2066 		}
2067 	    }
2068 	}
2069 	} /* end of switch */
2070 
2071     for (i = 0; i < ac; i++) {
2072 	Buf_AddBytes(&buf, strlen(av[i]), av[i]);
2073 	if (i != ac - 1)
2074 	    Buf_AddByte(&buf, ' ');
2075     }
2076 
2077     free(as);
2078     free(av);
2079 
2080     return Buf_Destroy(&buf, FALSE);
2081 }
2082 
2083 
2084 /*-
2085  *-----------------------------------------------------------------------
2086  * VarUniq --
2087  *	Remove adjacent duplicate words.
2088  *
2089  * Input:
2090  *	str		String whose words should be sorted
2091  *
2092  * Results:
2093  *	A string containing the resulting words.
2094  *
2095  * Side Effects:
2096  *	None.
2097  *
2098  *-----------------------------------------------------------------------
2099  */
2100 static char *
2101 VarUniq(const char *str)
2102 {
2103     Buffer	  buf;		    /* Buffer for new string */
2104     char 	**av;		    /* List of words to affect */
2105     char 	 *as;		    /* Word list memory */
2106     int 	  ac, i, j;
2107 
2108     Buf_Init(&buf, 0);
2109     av = brk_string(str, &ac, FALSE, &as);
2110 
2111     if (ac > 1) {
2112 	for (j = 0, i = 1; i < ac; i++)
2113 	    if (strcmp(av[i], av[j]) != 0 && (++j != i))
2114 		av[j] = av[i];
2115 	ac = j + 1;
2116     }
2117 
2118     for (i = 0; i < ac; i++) {
2119 	Buf_AddBytes(&buf, strlen(av[i]), av[i]);
2120 	if (i != ac - 1)
2121 	    Buf_AddByte(&buf, ' ');
2122     }
2123 
2124     free(as);
2125     free(av);
2126 
2127     return Buf_Destroy(&buf, FALSE);
2128 }
2129 
2130 
2131 /*-
2132  *-----------------------------------------------------------------------
2133  * VarGetPattern --
2134  *	Pass through the tstr looking for 1) escaped delimiters,
2135  *	'$'s and backslashes (place the escaped character in
2136  *	uninterpreted) and 2) unescaped $'s that aren't before
2137  *	the delimiter (expand the variable substitution unless flags
2138  *	has VAR_NOSUBST set).
2139  *	Return the expanded string or NULL if the delimiter was missing
2140  *	If pattern is specified, handle escaped ampersands, and replace
2141  *	unescaped ampersands with the lhs of the pattern.
2142  *
2143  * Results:
2144  *	A string of all the words modified appropriately.
2145  *	If length is specified, return the string length of the buffer
2146  *	If flags is specified and the last character of the pattern is a
2147  *	$ set the VAR_MATCH_END bit of flags.
2148  *
2149  * Side Effects:
2150  *	None.
2151  *-----------------------------------------------------------------------
2152  */
2153 static char *
2154 VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
2155 	      int errnum, const char **tstr, int delim, int *flags,
2156 	      int *length, VarPattern *pattern)
2157 {
2158     const char *cp;
2159     char *rstr;
2160     Buffer buf;
2161     int junk;
2162 
2163     Buf_Init(&buf, 0);
2164     if (length == NULL)
2165 	length = &junk;
2166 
2167 #define IS_A_MATCH(cp, delim) \
2168     ((cp[0] == '\\') && ((cp[1] == delim) ||  \
2169      (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
2170 
2171     /*
2172      * Skim through until the matching delimiter is found;
2173      * pick up variable substitutions on the way. Also allow
2174      * backslashes to quote the delimiter, $, and \, but don't
2175      * touch other backslashes.
2176      */
2177     for (cp = *tstr; *cp && (*cp != delim); cp++) {
2178 	if (IS_A_MATCH(cp, delim)) {
2179 	    Buf_AddByte(&buf, cp[1]);
2180 	    cp++;
2181 	} else if (*cp == '$') {
2182 	    if (cp[1] == delim) {
2183 		if (flags == NULL)
2184 		    Buf_AddByte(&buf, *cp);
2185 		else
2186 		    /*
2187 		     * Unescaped $ at end of pattern => anchor
2188 		     * pattern at end.
2189 		     */
2190 		    *flags |= VAR_MATCH_END;
2191 	    } else {
2192 		if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
2193 		    char   *cp2;
2194 		    int     len;
2195 		    void   *freeIt;
2196 
2197 		    /*
2198 		     * If unescaped dollar sign not before the
2199 		     * delimiter, assume it's a variable
2200 		     * substitution and recurse.
2201 		     */
2202 		    cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
2203 		    Buf_AddBytes(&buf, strlen(cp2), cp2);
2204 		    if (freeIt)
2205 			free(freeIt);
2206 		    cp += len - 1;
2207 		} else {
2208 		    const char *cp2 = &cp[1];
2209 
2210 		    if (*cp2 == PROPEN || *cp2 == BROPEN) {
2211 			/*
2212 			 * Find the end of this variable reference
2213 			 * and suck it in without further ado.
2214 			 * It will be interperated later.
2215 			 */
2216 			int have = *cp2;
2217 			int want = (*cp2 == PROPEN) ? PRCLOSE : BRCLOSE;
2218 			int depth = 1;
2219 
2220 			for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
2221 			    if (cp2[-1] != '\\') {
2222 				if (*cp2 == have)
2223 				    ++depth;
2224 				if (*cp2 == want)
2225 				    --depth;
2226 			    }
2227 			}
2228 			Buf_AddBytes(&buf, cp2 - cp, cp);
2229 			cp = --cp2;
2230 		    } else
2231 			Buf_AddByte(&buf, *cp);
2232 		}
2233 	    }
2234 	}
2235 	else if (pattern && *cp == '&')
2236 	    Buf_AddBytes(&buf, pattern->leftLen, pattern->lhs);
2237 	else
2238 	    Buf_AddByte(&buf, *cp);
2239     }
2240 
2241     if (*cp != delim) {
2242 	*tstr = cp;
2243 	*length = 0;
2244 	return NULL;
2245     }
2246 
2247     *tstr = ++cp;
2248     *length = Buf_Size(&buf);
2249     rstr = Buf_Destroy(&buf, FALSE);
2250     if (DEBUG(VAR))
2251 	fprintf(debug_file, "Modifier pattern: \"%s\"\n", rstr);
2252     return rstr;
2253 }
2254 
2255 /*-
2256  *-----------------------------------------------------------------------
2257  * VarQuote --
2258  *	Quote shell meta-characters in the string
2259  *
2260  * Results:
2261  *	The quoted string
2262  *
2263  * Side Effects:
2264  *	None.
2265  *
2266  *-----------------------------------------------------------------------
2267  */
2268 static char *
2269 VarQuote(char *str)
2270 {
2271 
2272     Buffer  	  buf;
2273     /* This should cover most shells :-( */
2274     static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
2275     const char	*newline;
2276     size_t len, nlen;
2277 
2278     if ((newline = Shell_GetNewline()) == NULL)
2279 	    newline = "\\\n";
2280     nlen = strlen(newline);
2281 
2282     Buf_Init(&buf, 0);
2283     while (*str != '\0') {
2284 	if ((len = strcspn(str, meta)) != 0) {
2285 	    Buf_AddBytes(&buf, len, str);
2286 	    str += len;
2287 	} else if (*str == '\n') {
2288 	    Buf_AddBytes(&buf, nlen, newline);
2289 	    ++str;
2290 	} else {
2291 	    Buf_AddByte(&buf, '\\');
2292 	    Buf_AddByte(&buf, *str);
2293 	    ++str;
2294 	}
2295     }
2296     str = Buf_Destroy(&buf, FALSE);
2297     if (DEBUG(VAR))
2298 	fprintf(debug_file, "QuoteMeta: [%s]\n", str);
2299     return str;
2300 }
2301 
2302 /*-
2303  *-----------------------------------------------------------------------
2304  * VarHash --
2305  *      Hash the string using the MurmurHash3 algorithm.
2306  *      Output is computed using 32bit Little Endian arithmetic.
2307  *
2308  * Input:
2309  *	str		String to modify
2310  *
2311  * Results:
2312  *      Hash value of str, encoded as 8 hex digits.
2313  *
2314  * Side Effects:
2315  *      None.
2316  *
2317  *-----------------------------------------------------------------------
2318  */
2319 static char *
2320 VarHash(char *str)
2321 {
2322     static const char    hexdigits[16] = "0123456789abcdef";
2323     Buffer         buf;
2324     size_t         len, len2;
2325     unsigned char  *ustr = (unsigned char *)str;
2326     uint32_t       h, k, c1, c2;
2327 
2328     h  = 0x971e137bU;
2329     c1 = 0x95543787U;
2330     c2 = 0x2ad7eb25U;
2331     len2 = strlen(str);
2332 
2333     for (len = len2; len; ) {
2334 	k = 0;
2335 	switch (len) {
2336 	default:
2337 	    k = (ustr[3] << 24) | (ustr[2] << 16) | (ustr[1] << 8) | ustr[0];
2338 	    len -= 4;
2339 	    ustr += 4;
2340 	    break;
2341 	case 3:
2342 	    k |= (ustr[2] << 16);
2343 	case 2:
2344 	    k |= (ustr[1] << 8);
2345 	case 1:
2346 	    k |= ustr[0];
2347 	    len = 0;
2348 	}
2349 	c1 = c1 * 5 + 0x7b7d159cU;
2350 	c2 = c2 * 5 + 0x6bce6396U;
2351 	k *= c1;
2352 	k = (k << 11) ^ (k >> 21);
2353 	k *= c2;
2354 	h = (h << 13) ^ (h >> 19);
2355 	h = h * 5 + 0x52dce729U;
2356 	h ^= k;
2357    }
2358    h ^= len2;
2359    h *= 0x85ebca6b;
2360    h ^= h >> 13;
2361    h *= 0xc2b2ae35;
2362    h ^= h >> 16;
2363 
2364    Buf_Init(&buf, 0);
2365    for (len = 0; len < 8; ++len) {
2366        Buf_AddByte(&buf, hexdigits[h & 15]);
2367        h >>= 4;
2368    }
2369 
2370    return Buf_Destroy(&buf, FALSE);
2371 }
2372 
2373 static char *
2374 VarStrftime(const char *fmt, int zulu)
2375 {
2376     char buf[BUFSIZ];
2377     time_t utc;
2378 
2379     time(&utc);
2380     if (!*fmt)
2381 	fmt = "%c";
2382     strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&utc) : localtime(&utc));
2383 
2384     buf[sizeof(buf) - 1] = '\0';
2385     return bmake_strdup(buf);
2386 }
2387 
2388 /*
2389  * Now we need to apply any modifiers the user wants applied.
2390  * These are:
2391  *  	  :M<pattern>	words which match the given <pattern>.
2392  *  			<pattern> is of the standard file
2393  *  			wildcarding form.
2394  *  	  :N<pattern>	words which do not match the given <pattern>.
2395  *  	  :S<d><pat1><d><pat2><d>[1gW]
2396  *  			Substitute <pat2> for <pat1> in the value
2397  *  	  :C<d><pat1><d><pat2><d>[1gW]
2398  *  			Substitute <pat2> for regex <pat1> in the value
2399  *  	  :H		Substitute the head of each word
2400  *  	  :T		Substitute the tail of each word
2401  *  	  :E		Substitute the extension (minus '.') of
2402  *  			each word
2403  *  	  :R		Substitute the root of each word
2404  *  			(pathname minus the suffix).
2405  *	  :O		("Order") Alphabeticaly sort words in variable.
2406  *	  :Ox		("intermiX") Randomize words in variable.
2407  *	  :u		("uniq") Remove adjacent duplicate words.
2408  *	  :tu		Converts the variable contents to uppercase.
2409  *	  :tl		Converts the variable contents to lowercase.
2410  *	  :ts[c]	Sets varSpace - the char used to
2411  *			separate words to 'c'. If 'c' is
2412  *			omitted then no separation is used.
2413  *	  :tW		Treat the variable contents as a single
2414  *			word, even if it contains spaces.
2415  *			(Mnemonic: one big 'W'ord.)
2416  *	  :tw		Treat the variable contents as multiple
2417  *			space-separated words.
2418  *			(Mnemonic: many small 'w'ords.)
2419  *	  :[index]	Select a single word from the value.
2420  *	  :[start..end]	Select multiple words from the value.
2421  *	  :[*] or :[0]	Select the entire value, as a single
2422  *			word.  Equivalent to :tW.
2423  *	  :[@]		Select the entire value, as multiple
2424  *			words.	Undoes the effect of :[*].
2425  *			Equivalent to :tw.
2426  *	  :[#]		Returns the number of words in the value.
2427  *
2428  *	  :?<true-value>:<false-value>
2429  *			If the variable evaluates to true, return
2430  *			true value, else return the second value.
2431  *    	  :lhs=rhs  	Like :S, but the rhs goes to the end of
2432  *    			the invocation.
2433  *	  :sh		Treat the current value as a command
2434  *			to be run, new value is its output.
2435  * The following added so we can handle ODE makefiles.
2436  *	  :@<tmpvar>@<newval>@
2437  *			Assign a temporary local variable <tmpvar>
2438  *			to the current value of each word in turn
2439  *			and replace each word with the result of
2440  *			evaluating <newval>
2441  *	  :D<newval>	Use <newval> as value if variable defined
2442  *	  :U<newval>	Use <newval> as value if variable undefined
2443  *	  :L		Use the name of the variable as the value.
2444  *	  :P		Use the path of the node that has the same
2445  *			name as the variable as the value.  This
2446  *			basically includes an implied :L so that
2447  *			the common method of refering to the path
2448  *			of your dependent 'x' in a rule is to use
2449  *			the form '${x:P}'.
2450  *	  :!<cmd>!	Run cmd much the same as :sh run's the
2451  *			current value of the variable.
2452  * The ::= modifiers, actually assign a value to the variable.
2453  * Their main purpose is in supporting modifiers of .for loop
2454  * iterators and other obscure uses.  They always expand to
2455  * nothing.  In a target rule that would otherwise expand to an
2456  * empty line they can be preceded with @: to keep make happy.
2457  * Eg.
2458  *
2459  * foo:	.USE
2460  * .for i in ${.TARGET} ${.TARGET:R}.gz
2461  * 	@: ${t::=$i}
2462  *	@echo blah ${t:T}
2463  * .endfor
2464  *
2465  *	  ::=<str>	Assigns <str> as the new value of variable.
2466  *	  ::?=<str>	Assigns <str> as value of variable if
2467  *			it was not already set.
2468  *	  ::+=<str>	Appends <str> to variable.
2469  *	  ::!=<cmd>	Assigns output of <cmd> as the new value of
2470  *			variable.
2471  */
2472 
2473 /* we now have some modifiers with long names */
2474 #define STRMOD_MATCH(s, want, n) \
2475     (strncmp(s, want, n) == 0 && (s[n] == endc || s[n] == ':'))
2476 
2477 static char *
2478 ApplyModifiers(char *nstr, const char *tstr,
2479 	       int startc, int endc,
2480 	       Var *v, GNode *ctxt, Boolean errnum,
2481 	       int *lengthPtr, void **freePtr)
2482 {
2483     const char 	   *start;
2484     const char     *cp;    	/* Secondary pointer into str (place marker
2485 				 * for tstr) */
2486     char	   *newStr;	/* New value to return */
2487     char	    termc;	/* Character which terminated scan */
2488     int             cnt;	/* Used to count brace pairs when variable in
2489 				 * in parens or braces */
2490     char	delim;
2491     int		modifier;	/* that we are processing */
2492     Var_Parse_State parsestate; /* Flags passed to helper functions */
2493 
2494     delim = '\0';
2495     parsestate.oneBigWord = FALSE;
2496     parsestate.varSpace = ' ';	/* word separator */
2497 
2498     start = cp = tstr;
2499 
2500     while (*tstr && *tstr != endc) {
2501 
2502 	if (*tstr == '$') {
2503 	    /*
2504 	     * We may have some complex modifiers in a variable.
2505 	     */
2506 	    void *freeIt;
2507 	    char *rval;
2508 	    int rlen;
2509 	    int c;
2510 
2511 	    rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
2512 
2513 	    /*
2514 	     * If we have not parsed up to endc or ':',
2515 	     * we are not interested.
2516 	     */
2517 	    if (rval != NULL && *rval &&
2518 		(c = tstr[rlen]) != '\0' &&
2519 		c != ':' &&
2520 		c != endc) {
2521 		if (freeIt)
2522 		    free(freeIt);
2523 		goto apply_mods;
2524 	    }
2525 
2526 	    if (DEBUG(VAR)) {
2527 		fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
2528 		       rval, rlen, tstr, rlen, tstr + rlen);
2529 	    }
2530 
2531 	    tstr += rlen;
2532 
2533 	    if (rval != NULL && *rval) {
2534 		int used;
2535 
2536 		nstr = ApplyModifiers(nstr, rval,
2537 				      0, 0,
2538 				      v, ctxt, errnum, &used, freePtr);
2539 		if (nstr == var_Error
2540 		    || (nstr == varNoError && errnum == 0)
2541 		    || strlen(rval) != (size_t) used) {
2542 		    if (freeIt)
2543 			free(freeIt);
2544 		    goto out;		/* error already reported */
2545 		}
2546 	    }
2547 	    if (freeIt)
2548 		free(freeIt);
2549 	    if (*tstr == ':')
2550 		tstr++;
2551 	    else if (!*tstr && endc) {
2552 		Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc, v->name);
2553 		goto out;
2554 	    }
2555 	    continue;
2556 	}
2557     apply_mods:
2558 	if (DEBUG(VAR)) {
2559 	    fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", v->name,
2560 		*tstr, nstr);
2561 	}
2562 	newStr = var_Error;
2563 	switch ((modifier = *tstr)) {
2564 	case ':':
2565 	    {
2566 		if (tstr[1] == '=' ||
2567 		    (tstr[2] == '=' &&
2568 		     (tstr[1] == '!' || tstr[1] == '+' || tstr[1] == '?'))) {
2569 		    /*
2570 		     * "::=", "::!=", "::+=", or "::?="
2571 		     */
2572 		    GNode *v_ctxt;		/* context where v belongs */
2573 		    const char *emsg;
2574 		    char *sv_name;
2575 		    VarPattern	pattern;
2576 		    int	how;
2577 
2578 		    if (v->name[0] == 0)
2579 			goto bad_modifier;
2580 
2581 		    v_ctxt = ctxt;
2582 		    sv_name = NULL;
2583 		    ++tstr;
2584 		    if (v->flags & VAR_JUNK) {
2585 			/*
2586 			 * We need to bmake_strdup() it incase
2587 			 * VarGetPattern() recurses.
2588 			 */
2589 			sv_name = v->name;
2590 			v->name = bmake_strdup(v->name);
2591 		    } else if (ctxt != VAR_GLOBAL) {
2592 			Var *gv = VarFind(v->name, ctxt, 0);
2593 			if (gv == NULL)
2594 			    v_ctxt = VAR_GLOBAL;
2595 			else
2596 			    VarFreeEnv(gv, TRUE);
2597 		    }
2598 
2599 		    switch ((how = *tstr)) {
2600 		    case '+':
2601 		    case '?':
2602 		    case '!':
2603 			cp = &tstr[2];
2604 			break;
2605 		    default:
2606 			cp = ++tstr;
2607 			break;
2608 		    }
2609 		    delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
2610 		    pattern.flags = 0;
2611 
2612 		    pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2613 						&cp, delim, NULL,
2614 						&pattern.rightLen,
2615 						NULL);
2616 		    if (v->flags & VAR_JUNK) {
2617 			/* restore original name */
2618 			free(v->name);
2619 			v->name = sv_name;
2620 		    }
2621 		    if (pattern.rhs == NULL)
2622 			goto cleanup;
2623 
2624 		    termc = *--cp;
2625 		    delim = '\0';
2626 
2627 		    switch (how) {
2628 		    case '+':
2629 			Var_Append(v->name, pattern.rhs, v_ctxt);
2630 			break;
2631 		    case '!':
2632 			newStr = Cmd_Exec(pattern.rhs, &emsg);
2633 			if (emsg)
2634 			    Error(emsg, nstr);
2635 			else
2636 			    Var_Set(v->name, newStr,  v_ctxt, 0);
2637 			if (newStr)
2638 			    free(newStr);
2639 			break;
2640 		    case '?':
2641 			if ((v->flags & VAR_JUNK) == 0)
2642 			    break;
2643 			/* FALLTHROUGH */
2644 		    default:
2645 			Var_Set(v->name, pattern.rhs, v_ctxt, 0);
2646 			break;
2647 		    }
2648 		    free(UNCONST(pattern.rhs));
2649 		    newStr = var_Error;
2650 		    break;
2651 		}
2652 		goto default_case; /* "::<unrecognised>" */
2653 	    }
2654 	case '@':
2655 	    {
2656 		VarLoop_t	loop;
2657 		int flags = VAR_NOSUBST;
2658 
2659 		cp = ++tstr;
2660 		delim = '@';
2661 		if ((loop.tvar = VarGetPattern(ctxt, &parsestate, errnum,
2662 					       &cp, delim,
2663 					       &flags, &loop.tvarLen,
2664 					       NULL)) == NULL)
2665 		    goto cleanup;
2666 
2667 		if ((loop.str = VarGetPattern(ctxt, &parsestate, errnum,
2668 					      &cp, delim,
2669 					      &flags, &loop.strLen,
2670 					      NULL)) == NULL)
2671 		    goto cleanup;
2672 
2673 		termc = *cp;
2674 		delim = '\0';
2675 
2676 		loop.errnum = errnum;
2677 		loop.ctxt = ctxt;
2678 		newStr = VarModify(ctxt, &parsestate, nstr, VarLoopExpand,
2679 				   &loop);
2680 		free(loop.tvar);
2681 		free(loop.str);
2682 		break;
2683 	    }
2684 	case 'U':
2685 #ifdef MAKE_FREEBSD_UL
2686 	    if (FreeBSD_UL) {
2687 		int nc = tstr[1];
2688 
2689 		/* we have to be careful, since :U is used internally */
2690 		if (nc == ':' || nc == endc) {
2691 		    char *dp = bmake_strdup(nstr);
2692 		    for (newStr = dp; *dp; dp++)
2693 			*dp = toupper((unsigned char)*dp);
2694 		    cp = tstr + 1;
2695 		    termc = *cp;
2696 		    break;		/* yes inside the conditional */
2697 		}
2698 		/* FALLTHROUGH */
2699 	    }
2700 #endif
2701 	case 'D':
2702 	    {
2703 		Buffer  buf;    	/* Buffer for patterns */
2704 		int	    wantit;	/* want data in buffer */
2705 
2706 		/*
2707 		 * Pass through tstr looking for 1) escaped delimiters,
2708 		 * '$'s and backslashes (place the escaped character in
2709 		 * uninterpreted) and 2) unescaped $'s that aren't before
2710 		 * the delimiter (expand the variable substitution).
2711 		 * The result is left in the Buffer buf.
2712 		 */
2713 		Buf_Init(&buf, 0);
2714 		for (cp = tstr + 1;
2715 		     *cp != endc && *cp != ':' && *cp != '\0';
2716 		     cp++) {
2717 		    if ((*cp == '\\') &&
2718 			((cp[1] == ':') ||
2719 			 (cp[1] == '$') ||
2720 			 (cp[1] == endc) ||
2721 			 (cp[1] == '\\')))
2722 			{
2723 			    Buf_AddByte(&buf, cp[1]);
2724 			    cp++;
2725 			} else if (*cp == '$') {
2726 			    /*
2727 			     * If unescaped dollar sign, assume it's a
2728 			     * variable substitution and recurse.
2729 			     */
2730 			    char    *cp2;
2731 			    int	    len;
2732 			    void    *freeIt;
2733 
2734 			    cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
2735 			    Buf_AddBytes(&buf, strlen(cp2), cp2);
2736 			    if (freeIt)
2737 				free(freeIt);
2738 			    cp += len - 1;
2739 			} else {
2740 			    Buf_AddByte(&buf, *cp);
2741 			}
2742 		}
2743 
2744 		termc = *cp;
2745 
2746 		if (*tstr == 'U')
2747 		    wantit = ((v->flags & VAR_JUNK) != 0);
2748 		else
2749 		    wantit = ((v->flags & VAR_JUNK) == 0);
2750 		if ((v->flags & VAR_JUNK) != 0)
2751 		    v->flags |= VAR_KEEP;
2752 		if (wantit) {
2753 		    newStr = Buf_Destroy(&buf, FALSE);
2754 		} else {
2755 		    newStr = nstr;
2756 		    Buf_Destroy(&buf, TRUE);
2757 		}
2758 		break;
2759 	    }
2760 	case 'L':
2761 #ifdef MAKE_FREEBSD_UL
2762 	    if (FreeBSD_UL) {
2763 		char *dp = bmake_strdup(nstr);
2764 		for (newStr = dp; *dp; dp++)
2765 		    *dp = tolower((unsigned char)*dp);
2766 		cp = tstr + 1;
2767 		termc = *cp;
2768 		break;
2769 	    }
2770 	    /* FALLTHROUGH */
2771 #endif
2772 	    {
2773 		if ((v->flags & VAR_JUNK) != 0)
2774 		    v->flags |= VAR_KEEP;
2775 		newStr = bmake_strdup(v->name);
2776 		cp = ++tstr;
2777 		termc = *tstr;
2778 		break;
2779 	    }
2780 	case 'P':
2781 	    {
2782 		GNode *gn;
2783 
2784 		if ((v->flags & VAR_JUNK) != 0)
2785 		    v->flags |= VAR_KEEP;
2786 		gn = Targ_FindNode(v->name, TARG_NOCREATE);
2787 		if (gn == NULL || gn->type & OP_NOPATH) {
2788 		    newStr = NULL;
2789 		} else if (gn->path) {
2790 		    newStr = bmake_strdup(gn->path);
2791 		} else {
2792 		    newStr = Dir_FindFile(v->name, Suff_FindPath(gn));
2793 		}
2794 		if (!newStr) {
2795 		    newStr = bmake_strdup(v->name);
2796 		}
2797 		cp = ++tstr;
2798 		termc = *tstr;
2799 		break;
2800 	    }
2801 	case '!':
2802 	    {
2803 		const char *emsg;
2804 		VarPattern 	    pattern;
2805 		pattern.flags = 0;
2806 
2807 		delim = '!';
2808 
2809 		cp = ++tstr;
2810 		if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2811 						 &cp, delim,
2812 						 NULL, &pattern.rightLen,
2813 						 NULL)) == NULL)
2814 		    goto cleanup;
2815 		newStr = Cmd_Exec(pattern.rhs, &emsg);
2816 		free(UNCONST(pattern.rhs));
2817 		if (emsg)
2818 		    Error(emsg, nstr);
2819 		termc = *cp;
2820 		delim = '\0';
2821 		if (v->flags & VAR_JUNK) {
2822 		    v->flags |= VAR_KEEP;
2823 		}
2824 		break;
2825 	    }
2826 	case '[':
2827 	    {
2828 		/*
2829 		 * Look for the closing ']', recursively
2830 		 * expanding any embedded variables.
2831 		 *
2832 		 * estr is a pointer to the expanded result,
2833 		 * which we must free().
2834 		 */
2835 		char *estr;
2836 
2837 		cp = tstr+1; /* point to char after '[' */
2838 		delim = ']'; /* look for closing ']' */
2839 		estr = VarGetPattern(ctxt, &parsestate,
2840 				     errnum, &cp, delim,
2841 				     NULL, NULL, NULL);
2842 		if (estr == NULL)
2843 		    goto cleanup; /* report missing ']' */
2844 		/* now cp points just after the closing ']' */
2845 		delim = '\0';
2846 		if (cp[0] != ':' && cp[0] != endc) {
2847 		    /* Found junk after ']' */
2848 		    free(estr);
2849 		    goto bad_modifier;
2850 		}
2851 		if (estr[0] == '\0') {
2852 		    /* Found empty square brackets in ":[]". */
2853 		    free(estr);
2854 		    goto bad_modifier;
2855 		} else if (estr[0] == '#' && estr[1] == '\0') {
2856 		    /* Found ":[#]" */
2857 
2858 		    /*
2859 		     * We will need enough space for the decimal
2860 		     * representation of an int.  We calculate the
2861 		     * space needed for the octal representation,
2862 		     * and add enough slop to cope with a '-' sign
2863 		     * (which should never be needed) and a '\0'
2864 		     * string terminator.
2865 		     */
2866 		    int newStrSize =
2867 			(sizeof(int) * CHAR_BIT + 2) / 3 + 2;
2868 
2869 		    newStr = bmake_malloc(newStrSize);
2870 		    if (parsestate.oneBigWord) {
2871 			strncpy(newStr, "1", newStrSize);
2872 		    } else {
2873 			/* XXX: brk_string() is a rather expensive
2874 			 * way of counting words. */
2875 			char **av;
2876 			char *as;
2877 			int ac;
2878 
2879 			av = brk_string(nstr, &ac, FALSE, &as);
2880 			snprintf(newStr, newStrSize,  "%d", ac);
2881 			free(as);
2882 			free(av);
2883 		    }
2884 		    termc = *cp;
2885 		    free(estr);
2886 		    break;
2887 		} else if (estr[0] == '*' && estr[1] == '\0') {
2888 		    /* Found ":[*]" */
2889 		    parsestate.oneBigWord = TRUE;
2890 		    newStr = nstr;
2891 		    termc = *cp;
2892 		    free(estr);
2893 		    break;
2894 		} else if (estr[0] == '@' && estr[1] == '\0') {
2895 		    /* Found ":[@]" */
2896 		    parsestate.oneBigWord = FALSE;
2897 		    newStr = nstr;
2898 		    termc = *cp;
2899 		    free(estr);
2900 		    break;
2901 		} else {
2902 		    /*
2903 		     * We expect estr to contain a single
2904 		     * integer for :[N], or two integers
2905 		     * separated by ".." for :[start..end].
2906 		     */
2907 		    char *ep;
2908 
2909 		    VarSelectWords_t seldata = { 0, 0 };
2910 
2911 		    seldata.start = strtol(estr, &ep, 0);
2912 		    if (ep == estr) {
2913 			/* Found junk instead of a number */
2914 			free(estr);
2915 			goto bad_modifier;
2916 		    } else if (ep[0] == '\0') {
2917 			/* Found only one integer in :[N] */
2918 			seldata.end = seldata.start;
2919 		    } else if (ep[0] == '.' && ep[1] == '.' &&
2920 			       ep[2] != '\0') {
2921 			/* Expecting another integer after ".." */
2922 			ep += 2;
2923 			seldata.end = strtol(ep, &ep, 0);
2924 			if (ep[0] != '\0') {
2925 			    /* Found junk after ".." */
2926 			    free(estr);
2927 			    goto bad_modifier;
2928 			}
2929 		    } else {
2930 			/* Found junk instead of ".." */
2931 			free(estr);
2932 			goto bad_modifier;
2933 		    }
2934 		    /*
2935 		     * Now seldata is properly filled in,
2936 		     * but we still have to check for 0 as
2937 		     * a special case.
2938 		     */
2939 		    if (seldata.start == 0 && seldata.end == 0) {
2940 			/* ":[0]" or perhaps ":[0..0]" */
2941 			parsestate.oneBigWord = TRUE;
2942 			newStr = nstr;
2943 			termc = *cp;
2944 			free(estr);
2945 			break;
2946 		    } else if (seldata.start == 0 ||
2947 			       seldata.end == 0) {
2948 			/* ":[0..N]" or ":[N..0]" */
2949 			free(estr);
2950 			goto bad_modifier;
2951 		    }
2952 		    /*
2953 		     * Normal case: select the words
2954 		     * described by seldata.
2955 		     */
2956 		    newStr = VarSelectWords(ctxt, &parsestate,
2957 					    nstr, &seldata);
2958 
2959 		    termc = *cp;
2960 		    free(estr);
2961 		    break;
2962 		}
2963 
2964 	    }
2965 	case 'g':
2966 	    cp = tstr + 1;	/* make sure it is set */
2967 	    if (STRMOD_MATCH(tstr, "gmtime", 6)) {
2968 		newStr = VarStrftime(nstr, 1);
2969 		cp = tstr + 6;
2970 		termc = *cp;
2971 	    } else {
2972 		goto default_case;
2973 	    }
2974 	    break;
2975 	case 'h':
2976 	    cp = tstr + 1;	/* make sure it is set */
2977 	    if (STRMOD_MATCH(tstr, "hash", 4)) {
2978 		newStr = VarHash(nstr);
2979 		cp = tstr + 4;
2980 		termc = *cp;
2981 	    } else {
2982 		goto default_case;
2983 	    }
2984 	    break;
2985 	case 'l':
2986 	    cp = tstr + 1;	/* make sure it is set */
2987 	    if (STRMOD_MATCH(tstr, "localtime", 9)) {
2988 		newStr = VarStrftime(nstr, 0);
2989 		cp = tstr + 9;
2990 		termc = *cp;
2991 	    } else {
2992 		goto default_case;
2993 	    }
2994 	    break;
2995 	case 't':
2996 	    {
2997 		cp = tstr + 1;	/* make sure it is set */
2998 		if (tstr[1] != endc && tstr[1] != ':') {
2999 		    if (tstr[1] == 's') {
3000 			/*
3001 			 * Use the char (if any) at tstr[2]
3002 			 * as the word separator.
3003 			 */
3004 			VarPattern pattern;
3005 
3006 			if (tstr[2] != endc &&
3007 			    (tstr[3] == endc || tstr[3] == ':')) {
3008 			    /* ":ts<unrecognised><endc>" or
3009 			     * ":ts<unrecognised>:" */
3010 			    parsestate.varSpace = tstr[2];
3011 			    cp = tstr + 3;
3012 			} else if (tstr[2] == endc || tstr[2] == ':') {
3013 			    /* ":ts<endc>" or ":ts:" */
3014 			    parsestate.varSpace = 0; /* no separator */
3015 			    cp = tstr + 2;
3016 			} else if (tstr[2] == '\\') {
3017 			    switch (tstr[3]) {
3018 			    case 'n':
3019 				parsestate.varSpace = '\n';
3020 				cp = tstr + 4;
3021 				break;
3022 			    case 't':
3023 				parsestate.varSpace = '\t';
3024 				cp = tstr + 4;
3025 				break;
3026 			    default:
3027 				if (isdigit((unsigned char)tstr[3])) {
3028 				    char *ep;
3029 
3030 				    parsestate.varSpace =
3031 					strtoul(&tstr[3], &ep, 0);
3032 				    if (*ep != ':' && *ep != endc)
3033 					goto bad_modifier;
3034 				    cp = ep;
3035 				} else {
3036 				    /*
3037 				     * ":ts<backslash><unrecognised>".
3038 				     */
3039 				    goto bad_modifier;
3040 				}
3041 				break;
3042 			    }
3043 			} else {
3044 			    /*
3045 			     * Found ":ts<unrecognised><unrecognised>".
3046 			     */
3047 			    goto bad_modifier;
3048 			}
3049 
3050 			termc = *cp;
3051 
3052 			/*
3053 			 * We cannot be certain that VarModify
3054 			 * will be used - even if there is a
3055 			 * subsequent modifier, so do a no-op
3056 			 * VarSubstitute now to for str to be
3057 			 * re-expanded without the spaces.
3058 			 */
3059 			pattern.flags = VAR_SUB_ONE;
3060 			pattern.lhs = pattern.rhs = "\032";
3061 			pattern.leftLen = pattern.rightLen = 1;
3062 
3063 			newStr = VarModify(ctxt, &parsestate, nstr,
3064 					   VarSubstitute,
3065 					   &pattern);
3066 		    } else if (tstr[2] == endc || tstr[2] == ':') {
3067 			/*
3068 			 * Check for two-character options:
3069 			 * ":tu", ":tl"
3070 			 */
3071 			if (tstr[1] == 'A') { /* absolute path */
3072 			    newStr = VarModify(ctxt, &parsestate, nstr,
3073 					       VarRealpath, NULL);
3074 			    cp = tstr + 2;
3075 			    termc = *cp;
3076 			} else if (tstr[1] == 'u') {
3077 			    char *dp = bmake_strdup(nstr);
3078 			    for (newStr = dp; *dp; dp++)
3079 				*dp = toupper((unsigned char)*dp);
3080 			    cp = tstr + 2;
3081 			    termc = *cp;
3082 			} else if (tstr[1] == 'l') {
3083 			    char *dp = bmake_strdup(nstr);
3084 			    for (newStr = dp; *dp; dp++)
3085 				*dp = tolower((unsigned char)*dp);
3086 			    cp = tstr + 2;
3087 			    termc = *cp;
3088 			} else if (tstr[1] == 'W' || tstr[1] == 'w') {
3089 			    parsestate.oneBigWord = (tstr[1] == 'W');
3090 			    newStr = nstr;
3091 			    cp = tstr + 2;
3092 			    termc = *cp;
3093 			} else {
3094 			    /* Found ":t<unrecognised>:" or
3095 			     * ":t<unrecognised><endc>". */
3096 			    goto bad_modifier;
3097 			}
3098 		    } else {
3099 			/*
3100 			 * Found ":t<unrecognised><unrecognised>".
3101 			 */
3102 			goto bad_modifier;
3103 		    }
3104 		} else {
3105 		    /*
3106 		     * Found ":t<endc>" or ":t:".
3107 		     */
3108 		    goto bad_modifier;
3109 		}
3110 		break;
3111 	    }
3112 	case 'N':
3113 	case 'M':
3114 	    {
3115 		char    *pattern;
3116 		const char *endpat; /* points just after end of pattern */
3117 		char    *cp2;
3118 		Boolean copy;	/* pattern should be, or has been, copied */
3119 		Boolean needSubst;
3120 		int nest;
3121 
3122 		copy = FALSE;
3123 		needSubst = FALSE;
3124 		nest = 1;
3125 		/*
3126 		 * In the loop below, ignore ':' unless we are at
3127 		 * (or back to) the original brace level.
3128 		 * XXX This will likely not work right if $() and ${}
3129 		 * are intermixed.
3130 		 */
3131 		for (cp = tstr + 1;
3132 		     *cp != '\0' && !(*cp == ':' && nest == 1);
3133 		     cp++)
3134 		    {
3135 			if (*cp == '\\' &&
3136 			    (cp[1] == ':' ||
3137 			     cp[1] == endc || cp[1] == startc)) {
3138 			    if (!needSubst) {
3139 				copy = TRUE;
3140 			    }
3141 			    cp++;
3142 			    continue;
3143 			}
3144 			if (*cp == '$') {
3145 			    needSubst = TRUE;
3146 			}
3147 			if (*cp == '(' || *cp == '{')
3148 			    ++nest;
3149 			if (*cp == ')' || *cp == '}') {
3150 			    --nest;
3151 			    if (nest == 0)
3152 				break;
3153 			}
3154 		    }
3155 		termc = *cp;
3156 		endpat = cp;
3157 		if (copy) {
3158 		    /*
3159 		     * Need to compress the \:'s out of the pattern, so
3160 		     * allocate enough room to hold the uncompressed
3161 		     * pattern (note that cp started at tstr+1, so
3162 		     * cp - tstr takes the null byte into account) and
3163 		     * compress the pattern into the space.
3164 		     */
3165 		    pattern = bmake_malloc(cp - tstr);
3166 		    for (cp2 = pattern, cp = tstr + 1;
3167 			 cp < endpat;
3168 			 cp++, cp2++)
3169 			{
3170 			    if ((*cp == '\\') && (cp+1 < endpat) &&
3171 				(cp[1] == ':' || cp[1] == endc)) {
3172 				cp++;
3173 			    }
3174 			    *cp2 = *cp;
3175 			}
3176 		    *cp2 = '\0';
3177 		    endpat = cp2;
3178 		} else {
3179 		    /*
3180 		     * Either Var_Subst or VarModify will need a
3181 		     * nul-terminated string soon, so construct one now.
3182 		     */
3183 		    pattern = bmake_strndup(tstr+1, endpat - (tstr + 1));
3184 		}
3185 		if (needSubst) {
3186 		    /*
3187 		     * pattern contains embedded '$', so use Var_Subst to
3188 		     * expand it.
3189 		     */
3190 		    cp2 = pattern;
3191 		    pattern = Var_Subst(NULL, cp2, ctxt, errnum);
3192 		    free(cp2);
3193 		}
3194 		if (DEBUG(VAR))
3195 		    fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
3196 			v->name, nstr, pattern);
3197 		if (*tstr == 'M') {
3198 		    newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
3199 				       pattern);
3200 		} else {
3201 		    newStr = VarModify(ctxt, &parsestate, nstr, VarNoMatch,
3202 				       pattern);
3203 		}
3204 		free(pattern);
3205 		break;
3206 	    }
3207 	case 'S':
3208 	    {
3209 		VarPattern 	    pattern;
3210 		Var_Parse_State tmpparsestate;
3211 
3212 		pattern.flags = 0;
3213 		tmpparsestate = parsestate;
3214 		delim = tstr[1];
3215 		tstr += 2;
3216 
3217 		/*
3218 		 * If pattern begins with '^', it is anchored to the
3219 		 * start of the word -- skip over it and flag pattern.
3220 		 */
3221 		if (*tstr == '^') {
3222 		    pattern.flags |= VAR_MATCH_START;
3223 		    tstr += 1;
3224 		}
3225 
3226 		cp = tstr;
3227 		if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
3228 						 &cp, delim,
3229 						 &pattern.flags,
3230 						 &pattern.leftLen,
3231 						 NULL)) == NULL)
3232 		    goto cleanup;
3233 
3234 		if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
3235 						 &cp, delim, NULL,
3236 						 &pattern.rightLen,
3237 						 &pattern)) == NULL)
3238 		    goto cleanup;
3239 
3240 		/*
3241 		 * Check for global substitution. If 'g' after the final
3242 		 * delimiter, substitution is global and is marked that
3243 		 * way.
3244 		 */
3245 		for (;; cp++) {
3246 		    switch (*cp) {
3247 		    case 'g':
3248 			pattern.flags |= VAR_SUB_GLOBAL;
3249 			continue;
3250 		    case '1':
3251 			pattern.flags |= VAR_SUB_ONE;
3252 			continue;
3253 		    case 'W':
3254 			tmpparsestate.oneBigWord = TRUE;
3255 			continue;
3256 		    }
3257 		    break;
3258 		}
3259 
3260 		termc = *cp;
3261 		newStr = VarModify(ctxt, &tmpparsestate, nstr,
3262 				   VarSubstitute,
3263 				   &pattern);
3264 
3265 		/*
3266 		 * Free the two strings.
3267 		 */
3268 		free(UNCONST(pattern.lhs));
3269 		free(UNCONST(pattern.rhs));
3270 		delim = '\0';
3271 		break;
3272 	    }
3273 	case '?':
3274 	    {
3275 		VarPattern 	pattern;
3276 		Boolean	value;
3277 
3278 		/* find ':', and then substitute accordingly */
3279 
3280 		pattern.flags = 0;
3281 
3282 		cp = ++tstr;
3283 		delim = ':';
3284 		if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
3285 						 &cp, delim, NULL,
3286 						 &pattern.leftLen,
3287 						 NULL)) == NULL)
3288 		    goto cleanup;
3289 
3290 		/* BROPEN or PROPEN */
3291 		delim = endc;
3292 		if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
3293 						 &cp, delim, NULL,
3294 						 &pattern.rightLen,
3295 						 NULL)) == NULL)
3296 		    goto cleanup;
3297 
3298 		termc = *--cp;
3299 		delim = '\0';
3300 		if (Cond_EvalExpression(NULL, v->name, &value, 0)
3301 		    == COND_INVALID) {
3302 		    Error("Bad conditional expression `%s' in %s?%s:%s",
3303 			  v->name, v->name, pattern.lhs, pattern.rhs);
3304 		    goto cleanup;
3305 		}
3306 
3307 		if (value) {
3308 		    newStr = UNCONST(pattern.lhs);
3309 		    free(UNCONST(pattern.rhs));
3310 		} else {
3311 		    newStr = UNCONST(pattern.rhs);
3312 		    free(UNCONST(pattern.lhs));
3313 		}
3314 		if (v->flags & VAR_JUNK) {
3315 		    v->flags |= VAR_KEEP;
3316 		}
3317 		break;
3318 	    }
3319 #ifndef NO_REGEX
3320 	case 'C':
3321 	    {
3322 		VarREPattern    pattern;
3323 		char           *re;
3324 		int             error;
3325 		Var_Parse_State tmpparsestate;
3326 
3327 		pattern.flags = 0;
3328 		tmpparsestate = parsestate;
3329 		delim = tstr[1];
3330 		tstr += 2;
3331 
3332 		cp = tstr;
3333 
3334 		if ((re = VarGetPattern(ctxt, &parsestate, errnum, &cp, delim,
3335 					NULL, NULL, NULL)) == NULL)
3336 		    goto cleanup;
3337 
3338 		if ((pattern.replace = VarGetPattern(ctxt, &parsestate,
3339 						     errnum, &cp, delim, NULL,
3340 						     NULL, NULL)) == NULL){
3341 		    free(re);
3342 		    goto cleanup;
3343 		}
3344 
3345 		for (;; cp++) {
3346 		    switch (*cp) {
3347 		    case 'g':
3348 			pattern.flags |= VAR_SUB_GLOBAL;
3349 			continue;
3350 		    case '1':
3351 			pattern.flags |= VAR_SUB_ONE;
3352 			continue;
3353 		    case 'W':
3354 			tmpparsestate.oneBigWord = TRUE;
3355 			continue;
3356 		    }
3357 		    break;
3358 		}
3359 
3360 		termc = *cp;
3361 
3362 		error = regcomp(&pattern.re, re, REG_EXTENDED);
3363 		free(re);
3364 		if (error)  {
3365 		    *lengthPtr = cp - start + 1;
3366 		    VarREError(error, &pattern.re, "RE substitution error");
3367 		    free(pattern.replace);
3368 		    goto cleanup;
3369 		}
3370 
3371 		pattern.nsub = pattern.re.re_nsub + 1;
3372 		if (pattern.nsub < 1)
3373 		    pattern.nsub = 1;
3374 		if (pattern.nsub > 10)
3375 		    pattern.nsub = 10;
3376 		pattern.matches = bmake_malloc(pattern.nsub *
3377 					  sizeof(regmatch_t));
3378 		newStr = VarModify(ctxt, &tmpparsestate, nstr,
3379 				   VarRESubstitute,
3380 				   &pattern);
3381 		regfree(&pattern.re);
3382 		free(pattern.replace);
3383 		free(pattern.matches);
3384 		delim = '\0';
3385 		break;
3386 	    }
3387 #endif
3388 	case 'Q':
3389 	    if (tstr[1] == endc || tstr[1] == ':') {
3390 		newStr = VarQuote(nstr);
3391 		cp = tstr + 1;
3392 		termc = *cp;
3393 		break;
3394 	    }
3395 	    goto default_case;
3396 	case 'T':
3397 	    if (tstr[1] == endc || tstr[1] == ':') {
3398 		newStr = VarModify(ctxt, &parsestate, nstr, VarTail,
3399 				   NULL);
3400 		cp = tstr + 1;
3401 		termc = *cp;
3402 		break;
3403 	    }
3404 	    goto default_case;
3405 	case 'H':
3406 	    if (tstr[1] == endc || tstr[1] == ':') {
3407 		newStr = VarModify(ctxt, &parsestate, nstr, VarHead,
3408 				   NULL);
3409 		cp = tstr + 1;
3410 		termc = *cp;
3411 		break;
3412 	    }
3413 	    goto default_case;
3414 	case 'E':
3415 	    if (tstr[1] == endc || tstr[1] == ':') {
3416 		newStr = VarModify(ctxt, &parsestate, nstr, VarSuffix,
3417 				   NULL);
3418 		cp = tstr + 1;
3419 		termc = *cp;
3420 		break;
3421 	    }
3422 	    goto default_case;
3423 	case 'R':
3424 	    if (tstr[1] == endc || tstr[1] == ':') {
3425 		newStr = VarModify(ctxt, &parsestate, nstr, VarRoot,
3426 				   NULL);
3427 		cp = tstr + 1;
3428 		termc = *cp;
3429 		break;
3430 	    }
3431 	    goto default_case;
3432 	case 'O':
3433 	    {
3434 		char otype;
3435 
3436 		cp = tstr + 1;	/* skip to the rest in any case */
3437 		if (tstr[1] == endc || tstr[1] == ':') {
3438 		    otype = 's';
3439 		    termc = *cp;
3440 		} else if ( (tstr[1] == 'x') &&
3441 			    (tstr[2] == endc || tstr[2] == ':') ) {
3442 		    otype = tstr[1];
3443 		    cp = tstr + 2;
3444 		    termc = *cp;
3445 		} else {
3446 		    goto bad_modifier;
3447 		}
3448 		newStr = VarOrder(nstr, otype);
3449 		break;
3450 	    }
3451 	case 'u':
3452 	    if (tstr[1] == endc || tstr[1] == ':') {
3453 		newStr = VarUniq(nstr);
3454 		cp = tstr + 1;
3455 		termc = *cp;
3456 		break;
3457 	    }
3458 	    goto default_case;
3459 #ifdef SUNSHCMD
3460 	case 's':
3461 	    if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
3462 		const char *emsg;
3463 		newStr = Cmd_Exec(nstr, &emsg);
3464 		if (emsg)
3465 		    Error(emsg, nstr);
3466 		cp = tstr + 2;
3467 		termc = *cp;
3468 		break;
3469 	    }
3470 	    goto default_case;
3471 #endif
3472 	default:
3473 	default_case:
3474 	{
3475 #ifdef SYSVVARSUB
3476 	    /*
3477 	     * This can either be a bogus modifier or a System-V
3478 	     * substitution command.
3479 	     */
3480 	    VarPattern      pattern;
3481 	    Boolean         eqFound;
3482 
3483 	    pattern.flags = 0;
3484 	    eqFound = FALSE;
3485 	    /*
3486 	     * First we make a pass through the string trying
3487 	     * to verify it is a SYSV-make-style translation:
3488 	     * it must be: <string1>=<string2>)
3489 	     */
3490 	    cp = tstr;
3491 	    cnt = 1;
3492 	    while (*cp != '\0' && cnt) {
3493 		if (*cp == '=') {
3494 		    eqFound = TRUE;
3495 		    /* continue looking for endc */
3496 		}
3497 		else if (*cp == endc)
3498 		    cnt--;
3499 		else if (*cp == startc)
3500 		    cnt++;
3501 		if (cnt)
3502 		    cp++;
3503 	    }
3504 	    if (*cp == endc && eqFound) {
3505 
3506 		/*
3507 		 * Now we break this sucker into the lhs and
3508 		 * rhs. We must null terminate them of course.
3509 		 */
3510 		delim='=';
3511 		cp = tstr;
3512 		if ((pattern.lhs = VarGetPattern(ctxt, &parsestate,
3513 						 errnum, &cp, delim, &pattern.flags,
3514 						 &pattern.leftLen, NULL)) == NULL)
3515 		    goto cleanup;
3516 		delim = endc;
3517 		if ((pattern.rhs = VarGetPattern(ctxt, &parsestate,
3518 						 errnum, &cp, delim, NULL, &pattern.rightLen,
3519 						 &pattern)) == NULL)
3520 		    goto cleanup;
3521 
3522 		/*
3523 		 * SYSV modifications happen through the whole
3524 		 * string. Note the pattern is anchored at the end.
3525 		 */
3526 		termc = *--cp;
3527 		delim = '\0';
3528 		if (pattern.leftLen == 0 && *nstr == '\0') {
3529 		    newStr = nstr;	/* special case */
3530 		} else {
3531 		    newStr = VarModify(ctxt, &parsestate, nstr,
3532 				       VarSYSVMatch,
3533 				       &pattern);
3534 		}
3535 		free(UNCONST(pattern.lhs));
3536 		free(UNCONST(pattern.rhs));
3537 	    } else
3538 #endif
3539 		{
3540 		    Error("Unknown modifier '%c'", *tstr);
3541 		    for (cp = tstr+1;
3542 			 *cp != ':' && *cp != endc && *cp != '\0';
3543 			 cp++)
3544 			continue;
3545 		    termc = *cp;
3546 		    newStr = var_Error;
3547 		}
3548 	    }
3549 	}
3550 	if (DEBUG(VAR)) {
3551 	    fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
3552 		v->name, modifier, newStr);
3553 	}
3554 
3555 	if (newStr != nstr) {
3556 	    if (*freePtr) {
3557 		free(nstr);
3558 		*freePtr = NULL;
3559 	    }
3560 	    nstr = newStr;
3561 	    if (nstr != var_Error && nstr != varNoError) {
3562 		*freePtr = nstr;
3563 	    }
3564 	}
3565 	if (termc == '\0' && endc != '\0') {
3566 	    Error("Unclosed variable specification (expecting '%c') for \"%s\" (value \"%s\") modifier %c", endc, v->name, nstr, modifier);
3567 	} else if (termc == ':') {
3568 	    cp++;
3569 	}
3570 	tstr = cp;
3571     }
3572  out:
3573     *lengthPtr = tstr - start;
3574     return (nstr);
3575 
3576  bad_modifier:
3577     /* "{(" */
3578     Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr, ":)}"), tstr,
3579 	  v->name);
3580 
3581  cleanup:
3582     *lengthPtr = cp - start;
3583     if (delim != '\0')
3584 	Error("Unclosed substitution for %s (%c missing)",
3585 	      v->name, delim);
3586     if (*freePtr) {
3587 	free(*freePtr);
3588 	*freePtr = NULL;
3589     }
3590     return (var_Error);
3591 }
3592 
3593 /*-
3594  *-----------------------------------------------------------------------
3595  * Var_Parse --
3596  *	Given the start of a variable invocation, extract the variable
3597  *	name and find its value, then modify it according to the
3598  *	specification.
3599  *
3600  * Input:
3601  *	str		The string to parse
3602  *	ctxt		The context for the variable
3603  *	errnum		TRUE if undefined variables are an error
3604  *	lengthPtr	OUT: The length of the specification
3605  *	freePtr		OUT: Non-NULL if caller should free *freePtr
3606  *
3607  * Results:
3608  *	The (possibly-modified) value of the variable or var_Error if the
3609  *	specification is invalid. The length of the specification is
3610  *	placed in *lengthPtr (for invalid specifications, this is just
3611  *	2...?).
3612  *	If *freePtr is non-NULL then it's a pointer that the caller
3613  *	should pass to free() to free memory used by the result.
3614  *
3615  * Side Effects:
3616  *	None.
3617  *
3618  *-----------------------------------------------------------------------
3619  */
3620 /* coverity[+alloc : arg-*4] */
3621 char *
3622 Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
3623 	  void **freePtr)
3624 {
3625     const char	   *tstr;    	/* Pointer into str */
3626     Var		   *v;		/* Variable in invocation */
3627     Boolean 	    haveModifier;/* TRUE if have modifiers for the variable */
3628     char	    endc;    	/* Ending character when variable in parens
3629 				 * or braces */
3630     char	    startc;	/* Starting character when variable in parens
3631 				 * or braces */
3632     int		    vlen;	/* Length of variable name */
3633     const char 	   *start;	/* Points to original start of str */
3634     char	   *nstr;	/* New string, used during expansion */
3635     Boolean 	    dynamic;	/* TRUE if the variable is local and we're
3636 				 * expanding it in a non-local context. This
3637 				 * is done to support dynamic sources. The
3638 				 * result is just the invocation, unaltered */
3639     Var_Parse_State parsestate; /* Flags passed to helper functions */
3640     char	  name[2];
3641 
3642     *freePtr = NULL;
3643     dynamic = FALSE;
3644     start = str;
3645     parsestate.oneBigWord = FALSE;
3646     parsestate.varSpace = ' ';	/* word separator */
3647 
3648     startc = str[1];
3649     if (startc != PROPEN && startc != BROPEN) {
3650 	/*
3651 	 * If it's not bounded by braces of some sort, life is much simpler.
3652 	 * We just need to check for the first character and return the
3653 	 * value if it exists.
3654 	 */
3655 
3656 	/* Error out some really stupid names */
3657 	if (startc == '\0' || strchr(")}:$", startc)) {
3658 	    *lengthPtr = 1;
3659 	    return var_Error;
3660 	}
3661 	name[0] = startc;
3662 	name[1] = '\0';
3663 
3664 	v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
3665 	if (v == NULL) {
3666 	    *lengthPtr = 2;
3667 
3668 	    if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
3669 		/*
3670 		 * If substituting a local variable in a non-local context,
3671 		 * assume it's for dynamic source stuff. We have to handle
3672 		 * this specially and return the longhand for the variable
3673 		 * with the dollar sign escaped so it makes it back to the
3674 		 * caller. Only four of the local variables are treated
3675 		 * specially as they are the only four that will be set
3676 		 * when dynamic sources are expanded.
3677 		 */
3678 		switch (str[1]) {
3679 		    case '@':
3680 			return UNCONST("$(.TARGET)");
3681 		    case '%':
3682 			return UNCONST("$(.ARCHIVE)");
3683 		    case '*':
3684 			return UNCONST("$(.PREFIX)");
3685 		    case '!':
3686 			return UNCONST("$(.MEMBER)");
3687 		}
3688 	    }
3689 	    /*
3690 	     * Error
3691 	     */
3692 	    return (errnum ? var_Error : varNoError);
3693 	} else {
3694 	    haveModifier = FALSE;
3695 	    tstr = &str[1];
3696 	    endc = str[1];
3697 	}
3698     } else {
3699 	Buffer buf;	/* Holds the variable name */
3700 
3701 	endc = startc == PROPEN ? PRCLOSE : BRCLOSE;
3702 	Buf_Init(&buf, 0);
3703 
3704 	/*
3705 	 * Skip to the end character or a colon, whichever comes first.
3706 	 */
3707 	for (tstr = str + 2;
3708 	     *tstr != '\0' && *tstr != endc && *tstr != ':';
3709 	     tstr++)
3710 	{
3711 	    /*
3712 	     * A variable inside a variable, expand
3713 	     */
3714 	    if (*tstr == '$') {
3715 		int rlen;
3716 		void *freeIt;
3717 		char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
3718 		if (rval != NULL) {
3719 		    Buf_AddBytes(&buf, strlen(rval), rval);
3720 		}
3721 		if (freeIt)
3722 		    free(freeIt);
3723 		tstr += rlen - 1;
3724 	    }
3725 	    else
3726 		Buf_AddByte(&buf, *tstr);
3727 	}
3728 	if (*tstr == ':') {
3729 	    haveModifier = TRUE;
3730 	} else if (*tstr != '\0') {
3731 	    haveModifier = FALSE;
3732 	} else {
3733 	    /*
3734 	     * If we never did find the end character, return NULL
3735 	     * right now, setting the length to be the distance to
3736 	     * the end of the string, since that's what make does.
3737 	     */
3738 	    *lengthPtr = tstr - str;
3739 	    Buf_Destroy(&buf, TRUE);
3740 	    return (var_Error);
3741 	}
3742 	str = Buf_GetAll(&buf, &vlen);
3743 
3744 	/*
3745 	 * At this point, str points into newly allocated memory from
3746 	 * buf, containing only the name of the variable.
3747 	 *
3748 	 * start and tstr point into the const string that was pointed
3749 	 * to by the original value of the str parameter.  start points
3750 	 * to the '$' at the beginning of the string, while tstr points
3751 	 * to the char just after the end of the variable name -- this
3752 	 * will be '\0', ':', PRCLOSE, or BRCLOSE.
3753 	 */
3754 
3755 	v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
3756 	/*
3757 	 * Check also for bogus D and F forms of local variables since we're
3758 	 * in a local context and the name is the right length.
3759 	 */
3760 	if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
3761 		(vlen == 2) && (str[1] == 'F' || str[1] == 'D') &&
3762 		strchr("@%*!<>", str[0]) != NULL) {
3763 	    /*
3764 	     * Well, it's local -- go look for it.
3765 	     */
3766 	    name[0] = *str;
3767 	    name[1] = '\0';
3768 	    v = VarFind(name, ctxt, 0);
3769 
3770 	    if (v != NULL) {
3771 		/*
3772 		 * No need for nested expansion or anything, as we're
3773 		 * the only one who sets these things and we sure don't
3774 		 * but nested invocations in them...
3775 		 */
3776 		nstr = Buf_GetAll(&v->val, NULL);
3777 
3778 		if (str[1] == 'D') {
3779 		    nstr = VarModify(ctxt, &parsestate, nstr, VarHead,
3780 				    NULL);
3781 		} else {
3782 		    nstr = VarModify(ctxt, &parsestate, nstr, VarTail,
3783 				    NULL);
3784 		}
3785 		/*
3786 		 * Resulting string is dynamically allocated, so
3787 		 * tell caller to free it.
3788 		 */
3789 		*freePtr = nstr;
3790 		*lengthPtr = tstr-start+1;
3791 		Buf_Destroy(&buf, TRUE);
3792 		VarFreeEnv(v, TRUE);
3793 		return nstr;
3794 	    }
3795 	}
3796 
3797 	if (v == NULL) {
3798 	    if (((vlen == 1) ||
3799 		 (((vlen == 2) && (str[1] == 'F' || str[1] == 'D')))) &&
3800 		((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
3801 	    {
3802 		/*
3803 		 * If substituting a local variable in a non-local context,
3804 		 * assume it's for dynamic source stuff. We have to handle
3805 		 * this specially and return the longhand for the variable
3806 		 * with the dollar sign escaped so it makes it back to the
3807 		 * caller. Only four of the local variables are treated
3808 		 * specially as they are the only four that will be set
3809 		 * when dynamic sources are expanded.
3810 		 */
3811 		switch (*str) {
3812 		    case '@':
3813 		    case '%':
3814 		    case '*':
3815 		    case '!':
3816 			dynamic = TRUE;
3817 			break;
3818 		}
3819 	    } else if ((vlen > 2) && (*str == '.') &&
3820 		       isupper((unsigned char) str[1]) &&
3821 		       ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
3822 	    {
3823 		int	len;
3824 
3825 		len = vlen - 1;
3826 		if ((strncmp(str, ".TARGET", len) == 0) ||
3827 		    (strncmp(str, ".ARCHIVE", len) == 0) ||
3828 		    (strncmp(str, ".PREFIX", len) == 0) ||
3829 		    (strncmp(str, ".MEMBER", len) == 0))
3830 		{
3831 		    dynamic = TRUE;
3832 		}
3833 	    }
3834 
3835 	    if (!haveModifier) {
3836 		/*
3837 		 * No modifiers -- have specification length so we can return
3838 		 * now.
3839 		 */
3840 		*lengthPtr = tstr - start + 1;
3841 		if (dynamic) {
3842 		    char *pstr = bmake_strndup(start, *lengthPtr);
3843 		    *freePtr = pstr;
3844 		    Buf_Destroy(&buf, TRUE);
3845 		    return(pstr);
3846 		} else {
3847 		    Buf_Destroy(&buf, TRUE);
3848 		    return (errnum ? var_Error : varNoError);
3849 		}
3850 	    } else {
3851 		/*
3852 		 * Still need to get to the end of the variable specification,
3853 		 * so kludge up a Var structure for the modifications
3854 		 */
3855 		v = bmake_malloc(sizeof(Var));
3856 		v->name = UNCONST(str);
3857 		Buf_Init(&v->val, 1);
3858 		v->flags = VAR_JUNK;
3859 		Buf_Destroy(&buf, FALSE);
3860 	    }
3861 	} else
3862 	    Buf_Destroy(&buf, TRUE);
3863     }
3864 
3865     if (v->flags & VAR_IN_USE) {
3866 	Fatal("Variable %s is recursive.", v->name);
3867 	/*NOTREACHED*/
3868     } else {
3869 	v->flags |= VAR_IN_USE;
3870     }
3871     /*
3872      * Before doing any modification, we have to make sure the value
3873      * has been fully expanded. If it looks like recursion might be
3874      * necessary (there's a dollar sign somewhere in the variable's value)
3875      * we just call Var_Subst to do any other substitutions that are
3876      * necessary. Note that the value returned by Var_Subst will have
3877      * been dynamically-allocated, so it will need freeing when we
3878      * return.
3879      */
3880     nstr = Buf_GetAll(&v->val, NULL);
3881     if (strchr(nstr, '$') != NULL) {
3882 	nstr = Var_Subst(NULL, nstr, ctxt, errnum);
3883 	*freePtr = nstr;
3884     }
3885 
3886     v->flags &= ~VAR_IN_USE;
3887 
3888     if ((nstr != NULL) && haveModifier) {
3889 	int used;
3890 	/*
3891 	 * Skip initial colon.
3892 	 */
3893 	tstr++;
3894 
3895 	nstr = ApplyModifiers(nstr, tstr, startc, endc,
3896 			      v, ctxt, errnum, &used, freePtr);
3897 	tstr += used;
3898     }
3899     if (*tstr) {
3900 	*lengthPtr = tstr - start + 1;
3901     } else {
3902 	*lengthPtr = tstr - start;
3903     }
3904 
3905     if (v->flags & VAR_FROM_ENV) {
3906 	Boolean	  destroy = FALSE;
3907 
3908 	if (nstr != Buf_GetAll(&v->val, NULL)) {
3909 	    destroy = TRUE;
3910 	} else {
3911 	    /*
3912 	     * Returning the value unmodified, so tell the caller to free
3913 	     * the thing.
3914 	     */
3915 	    *freePtr = nstr;
3916 	}
3917 	VarFreeEnv(v, destroy);
3918     } else if (v->flags & VAR_JUNK) {
3919 	/*
3920 	 * Perform any free'ing needed and set *freePtr to NULL so the caller
3921 	 * doesn't try to free a static pointer.
3922 	 * If VAR_KEEP is also set then we want to keep str as is.
3923 	 */
3924 	if (!(v->flags & VAR_KEEP)) {
3925 	    if (*freePtr) {
3926 		free(nstr);
3927 		*freePtr = NULL;
3928 	    }
3929 	    if (dynamic) {
3930 		nstr = bmake_strndup(start, *lengthPtr);
3931 		*freePtr = nstr;
3932 	    } else {
3933 		nstr = errnum ? var_Error : varNoError;
3934 	    }
3935 	}
3936 	if (nstr != Buf_GetAll(&v->val, NULL))
3937 	    Buf_Destroy(&v->val, TRUE);
3938 	free(v->name);
3939 	free(v);
3940     }
3941     return (nstr);
3942 }
3943 
3944 /*-
3945  *-----------------------------------------------------------------------
3946  * Var_Subst  --
3947  *	Substitute for all variables in the given string in the given context
3948  *	If undefErr is TRUE, Parse_Error will be called when an undefined
3949  *	variable is encountered.
3950  *
3951  * Input:
3952  *	var		Named variable || NULL for all
3953  *	str		the string which to substitute
3954  *	ctxt		the context wherein to find variables
3955  *	undefErr	TRUE if undefineds are an error
3956  *
3957  * Results:
3958  *	The resulting string.
3959  *
3960  * Side Effects:
3961  *	None. The old string must be freed by the caller
3962  *-----------------------------------------------------------------------
3963  */
3964 char *
3965 Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
3966 {
3967     Buffer  	  buf;		    /* Buffer for forming things */
3968     char    	  *val;		    /* Value to substitute for a variable */
3969     int		  length;   	    /* Length of the variable invocation */
3970     Boolean	  trailingBslash;   /* variable ends in \ */
3971     void 	  *freeIt = NULL;    /* Set if it should be freed */
3972     static Boolean errorReported;   /* Set true if an error has already
3973 				     * been reported to prevent a plethora
3974 				     * of messages when recursing */
3975 
3976     Buf_Init(&buf, 0);
3977     errorReported = FALSE;
3978     trailingBslash = FALSE;
3979 
3980     while (*str) {
3981 	if (*str == '\n' && trailingBslash)
3982 	    Buf_AddByte(&buf, ' ');
3983 	if (var == NULL && (*str == '$') && (str[1] == '$')) {
3984 	    /*
3985 	     * A dollar sign may be escaped either with another dollar sign.
3986 	     * In such a case, we skip over the escape character and store the
3987 	     * dollar sign into the buffer directly.
3988 	     */
3989 	    str++;
3990 	    Buf_AddByte(&buf, *str);
3991 	    str++;
3992 	} else if (*str != '$') {
3993 	    /*
3994 	     * Skip as many characters as possible -- either to the end of
3995 	     * the string or to the next dollar sign (variable invocation).
3996 	     */
3997 	    const char  *cp;
3998 
3999 	    for (cp = str++; *str != '$' && *str != '\0'; str++)
4000 		continue;
4001 	    Buf_AddBytes(&buf, str - cp, cp);
4002 	} else {
4003 	    if (var != NULL) {
4004 		int expand;
4005 		for (;;) {
4006 		    if (str[1] == '\0') {
4007 			/* A trailing $ is kind of a special case */
4008 			Buf_AddByte(&buf, str[0]);
4009 			str++;
4010 			expand = FALSE;
4011 		    } else if (str[1] != PROPEN && str[1] != BROPEN) {
4012 			if (str[1] != *var || strlen(var) > 1) {
4013 			    Buf_AddBytes(&buf, 2, str);
4014 			    str += 2;
4015 			    expand = FALSE;
4016 			}
4017 			else
4018 			    expand = TRUE;
4019 			break;
4020 		    }
4021 		    else {
4022 			const char *p;
4023 
4024 			/*
4025 			 * Scan up to the end of the variable name.
4026 			 */
4027 			for (p = &str[2]; *p &&
4028 			     *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++)
4029 			    if (*p == '$')
4030 				break;
4031 			/*
4032 			 * A variable inside the variable. We cannot expand
4033 			 * the external variable yet, so we try again with
4034 			 * the nested one
4035 			 */
4036 			if (*p == '$') {
4037 			    Buf_AddBytes(&buf, p - str, str);
4038 			    str = p;
4039 			    continue;
4040 			}
4041 
4042 			if (strncmp(var, str + 2, p - str - 2) != 0 ||
4043 			    var[p - str - 2] != '\0') {
4044 			    /*
4045 			     * Not the variable we want to expand, scan
4046 			     * until the next variable
4047 			     */
4048 			    for (;*p != '$' && *p != '\0'; p++)
4049 				continue;
4050 			    Buf_AddBytes(&buf, p - str, str);
4051 			    str = p;
4052 			    expand = FALSE;
4053 			}
4054 			else
4055 			    expand = TRUE;
4056 			break;
4057 		    }
4058 		}
4059 		if (!expand)
4060 		    continue;
4061 	    }
4062 
4063 	    val = Var_Parse(str, ctxt, undefErr, &length, &freeIt);
4064 
4065 	    /*
4066 	     * When we come down here, val should either point to the
4067 	     * value of this variable, suitably modified, or be NULL.
4068 	     * Length should be the total length of the potential
4069 	     * variable invocation (from $ to end character...)
4070 	     */
4071 	    if (val == var_Error || val == varNoError) {
4072 		/*
4073 		 * If performing old-time variable substitution, skip over
4074 		 * the variable and continue with the substitution. Otherwise,
4075 		 * store the dollar sign and advance str so we continue with
4076 		 * the string...
4077 		 */
4078 		if (oldVars) {
4079 		    str += length;
4080 		} else if (undefErr) {
4081 		    /*
4082 		     * If variable is undefined, complain and skip the
4083 		     * variable. The complaint will stop us from doing anything
4084 		     * when the file is parsed.
4085 		     */
4086 		    if (!errorReported) {
4087 			Parse_Error(PARSE_FATAL,
4088 				     "Undefined variable \"%.*s\"",length,str);
4089 		    }
4090 		    str += length;
4091 		    errorReported = TRUE;
4092 		} else {
4093 		    Buf_AddByte(&buf, *str);
4094 		    str += 1;
4095 		}
4096 	    } else {
4097 		/*
4098 		 * We've now got a variable structure to store in. But first,
4099 		 * advance the string pointer.
4100 		 */
4101 		str += length;
4102 
4103 		/*
4104 		 * Copy all the characters from the variable value straight
4105 		 * into the new string.
4106 		 */
4107 		length = strlen(val);
4108 		Buf_AddBytes(&buf, length, val);
4109 		trailingBslash = length > 0 && val[length - 1] == '\\';
4110 	    }
4111 	    if (freeIt) {
4112 		free(freeIt);
4113 		freeIt = NULL;
4114 	    }
4115 	}
4116     }
4117 
4118     return Buf_DestroyCompact(&buf);
4119 }
4120 
4121 /*-
4122  *-----------------------------------------------------------------------
4123  * Var_GetTail --
4124  *	Return the tail from each of a list of words. Used to set the
4125  *	System V local variables.
4126  *
4127  * Input:
4128  *	file		Filename to modify
4129  *
4130  * Results:
4131  *	The resulting string.
4132  *
4133  * Side Effects:
4134  *	None.
4135  *
4136  *-----------------------------------------------------------------------
4137  */
4138 #if 0
4139 char *
4140 Var_GetTail(char *file)
4141 {
4142     return(VarModify(file, VarTail, NULL));
4143 }
4144 
4145 /*-
4146  *-----------------------------------------------------------------------
4147  * Var_GetHead --
4148  *	Find the leading components of a (list of) filename(s).
4149  *	XXX: VarHead does not replace foo by ., as (sun) System V make
4150  *	does.
4151  *
4152  * Input:
4153  *	file		Filename to manipulate
4154  *
4155  * Results:
4156  *	The leading components.
4157  *
4158  * Side Effects:
4159  *	None.
4160  *
4161  *-----------------------------------------------------------------------
4162  */
4163 char *
4164 Var_GetHead(char *file)
4165 {
4166     return(VarModify(file, VarHead, NULL));
4167 }
4168 #endif
4169 
4170 /*-
4171  *-----------------------------------------------------------------------
4172  * Var_Init --
4173  *	Initialize the module
4174  *
4175  * Results:
4176  *	None
4177  *
4178  * Side Effects:
4179  *	The VAR_CMD and VAR_GLOBAL contexts are created
4180  *-----------------------------------------------------------------------
4181  */
4182 void
4183 Var_Init(void)
4184 {
4185     VAR_GLOBAL = Targ_NewGN("Global");
4186     VAR_CMD = Targ_NewGN("Command");
4187 
4188 }
4189 
4190 
4191 void
4192 Var_End(void)
4193 {
4194 }
4195 
4196 
4197 /****************** PRINT DEBUGGING INFO *****************/
4198 static void
4199 VarPrintVar(void *vp)
4200 {
4201     Var    *v = (Var *)vp;
4202     fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL));
4203 }
4204 
4205 /*-
4206  *-----------------------------------------------------------------------
4207  * Var_Dump --
4208  *	print all variables in a context
4209  *-----------------------------------------------------------------------
4210  */
4211 void
4212 Var_Dump(GNode *ctxt)
4213 {
4214     Hash_Search search;
4215     Hash_Entry *h;
4216 
4217     for (h = Hash_EnumFirst(&ctxt->context, &search);
4218 	 h != NULL;
4219 	 h = Hash_EnumNext(&search)) {
4220 	    VarPrintVar(Hash_GetValue(h));
4221     }
4222 }
4223