xref: /netbsd-src/usr.bin/make/var.c (revision a8c74629f602faa0ccf8a463757d7baf858bbf3a)
1 /*	$NetBSD: var.c,v 1.688 2020/11/16 21:39:22 rillig 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 /*
72  * Handling of variables and the expressions formed from them.
73  *
74  * Variables are set using lines of the form VAR=value.  Both the variable
75  * name and the value can contain references to other variables, by using
76  * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
77  *
78  * Interface:
79  *	Var_Init	Initialize this module.
80  *
81  *	Var_End		Clean up the module.
82  *
83  *	Var_Set		Set the value of the variable, creating it if
84  *			necessary.
85  *
86  *	Var_Append	Append more characters to the variable, creating it if
87  *			necessary. A space is placed between the old value and
88  *			the new one.
89  *
90  *	Var_Exists	See if a variable exists.
91  *
92  *	Var_Value	Return the unexpanded value of a variable, or NULL if
93  *			the variable is undefined.
94  *
95  *	Var_Subst	Substitute all variable expressions in a string.
96  *
97  *	Var_Parse	Parse a variable expression such as ${VAR:Mpattern}.
98  *
99  *	Var_Delete	Delete a variable.
100  *
101  *	Var_ExportVars	Export some or even all variables to the environment
102  *			of this process and its child processes.
103  *
104  *	Var_Export	Export the variable to the environment of this process
105  *			and its child processes.
106  *
107  *	Var_UnExport	Don't export the variable anymore.
108  *
109  * Debugging:
110  *	Var_Stats	Print out hashing statistics if in -dh mode.
111  *
112  *	Var_Dump	Print out all variables defined in the given context.
113  *
114  * XXX: There's a lot of duplication in these functions.
115  */
116 
117 #include <sys/stat.h>
118 #ifndef NO_REGEX
119 #include <sys/types.h>
120 #include <regex.h>
121 #endif
122 #include <errno.h>
123 #include <inttypes.h>
124 #include <limits.h>
125 #include <time.h>
126 
127 #include "make.h"
128 #include "dir.h"
129 #include "job.h"
130 #include "metachar.h"
131 
132 /*	"@(#)var.c	8.3 (Berkeley) 3/19/94" */
133 MAKE_RCSID("$NetBSD: var.c,v 1.688 2020/11/16 21:39:22 rillig Exp $");
134 
135 #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
136 #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
137 #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3)
138 #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4)
139 
140 ENUM_FLAGS_RTTI_3(VarEvalFlags,
141 		  VARE_UNDEFERR, VARE_WANTRES, VARE_KEEP_DOLLAR);
142 
143 /*
144  * This lets us tell if we have replaced the original environ
145  * (which we cannot free).
146  */
147 char **savedEnv = NULL;
148 
149 /* Special return value for Var_Parse, indicating a parse error.  It may be
150  * caused by an undefined variable, a syntax error in a modifier or
151  * something entirely different. */
152 char var_Error[] = "";
153 
154 /* Special return value for Var_Parse, indicating an undefined variable in
155  * a case where VARE_UNDEFERR is not set.  This undefined variable is
156  * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
157  * be deferred until it is defined in an actual target. */
158 static char varUndefined[] = "";
159 
160 /*
161  * Traditionally this make consumed $$ during := like any other expansion.
162  * Other make's do not, and this make follows straight since 2016-01-09.
163  *
164  * This knob allows controlling the behavior.
165  * FALSE to consume $$ during := assignment.
166  * TRUE to preserve $$ during := assignment.
167  */
168 #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
169 static Boolean save_dollars = TRUE;
170 
171 /*
172  * Internally, variables are contained in four different contexts.
173  *	1) the environment. They cannot be changed. If an environment
174  *	   variable is appended to, the result is placed in the global
175  *	   context.
176  *	2) the global context. Variables set in the makefiles are located
177  *	   here.
178  *	3) the command-line context. All variables set on the command line
179  *	   are placed in this context.
180  *	4) the local context. Each target has associated with it a context
181  *	   list. On this list are located the structures describing such
182  *	   local variables as $(@) and $(*)
183  * The four contexts are searched in the reverse order from which they are
184  * listed (but see opts.checkEnvFirst).
185  */
186 GNode          *VAR_INTERNAL;	/* variables from make itself */
187 GNode          *VAR_GLOBAL;	/* variables from the makefile */
188 GNode          *VAR_CMDLINE;	/* variables defined on the command-line */
189 
190 typedef enum VarFlags {
191 
192     /* The variable's value is currently being used by Var_Parse or Var_Subst.
193      * This marker is used to avoid endless recursion. */
194     VAR_IN_USE = 0x01,
195 
196     /* The variable comes from the environment.
197      * These variables are not registered in any GNode, therefore they must
198      * be freed as soon as they are not used anymore. */
199     VAR_FROM_ENV = 0x02,
200 
201     /* The variable is exported to the environment, to be used by child
202      * processes. */
203     VAR_EXPORTED = 0x10,
204 
205     /* At the point where this variable was exported, it contained an
206      * unresolved reference to another variable.  Before any child process is
207      * started, it needs to be exported again, in the hope that the referenced
208      * variable can then be resolved. */
209     VAR_REEXPORT = 0x20,
210 
211     /* The variable came from the command line. */
212     VAR_FROM_CMD = 0x40,
213 
214     /* The variable value cannot be changed anymore, and the variable cannot
215      * be deleted.  Any attempts to do so are ignored. */
216     VAR_READONLY = 0x80
217 } VarFlags;
218 
219 ENUM_FLAGS_RTTI_6(VarFlags,
220 		  VAR_IN_USE, VAR_FROM_ENV,
221 		  VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY);
222 
223 /* Variables are defined using one of the VAR=value assignments.  Their
224  * value can be queried by expressions such as $V, ${VAR}, or with modifiers
225  * such as ${VAR:S,from,to,g:Q}.
226  *
227  * There are 3 kinds of variables: context variables, environment variables,
228  * undefined variables.
229  *
230  * Context variables are stored in a GNode.context.  The only way to undefine
231  * a context variable is using the .undef directive.  In particular, it must
232  * not be possible to undefine a variable during the evaluation of an
233  * expression, or Var.name might point nowhere.
234  *
235  * Environment variables are temporary.  They are returned by VarFind, and
236  * after using them, they must be freed using VarFreeEnv.
237  *
238  * Undefined variables occur during evaluation of variable expressions such
239  * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
240  */
241 typedef struct Var {
242     /* The name of the variable, once set, doesn't change anymore.
243      * For context variables, it aliases the corresponding HashEntry name.
244      * For environment and undefined variables, it is allocated. */
245     const char *name;
246     void *name_freeIt;
247 
248     Buffer	  val;		/* its value */
249     VarFlags	  flags;	/* miscellaneous status flags */
250 } Var;
251 
252 /*
253  * Exporting vars is expensive so skip it if we can
254  */
255 typedef enum VarExportedMode {
256     VAR_EXPORTED_NONE,
257     VAR_EXPORTED_SOME,
258     VAR_EXPORTED_ALL
259 } VarExportedMode;
260 
261 static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
262 
263 typedef enum VarExportFlags {
264     VAR_EXPORT_NORMAL = 0,
265     /*
266      * We pass this to Var_Export when doing the initial export
267      * or after updating an exported var.
268      */
269     VAR_EXPORT_PARENT	= 0x01,
270     /*
271      * We pass this to Var_Export1 to tell it to leave the value alone.
272      */
273     VAR_EXPORT_LITERAL	= 0x02
274 } VarExportFlags;
275 
276 /* Flags for pattern matching in the :S and :C modifiers */
277 typedef enum VarPatternFlags {
278     VARP_SUB_GLOBAL	= 0x01,	/* Replace as often as possible ('g') */
279     VARP_SUB_ONE	= 0x02,	/* Replace only once ('1') */
280     VARP_ANCHOR_START	= 0x04,	/* Match at start of word ('^') */
281     VARP_ANCHOR_END	= 0x08	/* Match at end of word ('$') */
282 } VarPatternFlags;
283 
284 static Var *
285 VarNew(const char *name, void *name_freeIt, const char *value, VarFlags flags)
286 {
287     size_t value_len = strlen(value);
288     Var *var = bmake_malloc(sizeof *var);
289     var->name = name;
290     var->name_freeIt = name_freeIt;
291     Buf_InitSize(&var->val, value_len + 1);
292     Buf_AddBytes(&var->val, value, value_len);
293     var->flags = flags;
294     return var;
295 }
296 
297 static const char *
298 CanonicalVarname(const char *name)
299 {
300     if (*name == '.' && ch_isupper(name[1])) {
301 	switch (name[1]) {
302 	case 'A':
303 	    if (strcmp(name, ".ALLSRC") == 0)
304 		name = ALLSRC;
305 	    if (strcmp(name, ".ARCHIVE") == 0)
306 		name = ARCHIVE;
307 	    break;
308 	case 'I':
309 	    if (strcmp(name, ".IMPSRC") == 0)
310 		name = IMPSRC;
311 	    break;
312 	case 'M':
313 	    if (strcmp(name, ".MEMBER") == 0)
314 		name = MEMBER;
315 	    break;
316 	case 'O':
317 	    if (strcmp(name, ".OODATE") == 0)
318 		name = OODATE;
319 	    break;
320 	case 'P':
321 	    if (strcmp(name, ".PREFIX") == 0)
322 		name = PREFIX;
323 	    break;
324 	case 'S':
325 	    if (strcmp(name, ".SHELL") == 0) {
326 		if (!shellPath)
327 		    Shell_Init();
328 	    }
329 	    break;
330 	case 'T':
331 	    if (strcmp(name, ".TARGET") == 0)
332 		name = TARGET;
333 	    break;
334 	}
335     }
336 
337     /* GNU make has an additional alias $^ == ${.ALLSRC}. */
338 
339     return name;
340 }
341 
342 static Var *
343 GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash)
344 {
345     return HashTable_FindValueHash(&ctxt->context, varname, hash);
346 }
347 
348 /* Find the variable in the context, and maybe in other contexts as well.
349  *
350  * Input:
351  *	name		name to find, is not expanded any further
352  *	ctxt		context in which to look first
353  *	elsewhere	TRUE to look in other contexts as well
354  *
355  * Results:
356  *	The found variable, or NULL if the variable does not exist.
357  *	If the variable is an environment variable, it must be freed using
358  *	VarFreeEnv after use.
359  */
360 static Var *
361 VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
362 {
363     Var *var;
364     unsigned int nameHash;
365 
366     /*
367      * If the variable name begins with a '.', it could very well be one of
368      * the local ones.  We check the name against all the local variables
369      * and substitute the short version in for 'name' if it matches one of
370      * them.
371      */
372     name = CanonicalVarname(name);
373     nameHash = Hash_Hash(name);
374 
375     /* First look for the variable in the given context. */
376     var = GNode_FindVar(ctxt, name, nameHash);
377     if (!elsewhere)
378 	return var;
379 
380     /* The variable was not found in the given context.  Now look for it in
381      * the other contexts as well. */
382     if (var == NULL && ctxt != VAR_CMDLINE)
383 	var = GNode_FindVar(VAR_CMDLINE, name, nameHash);
384 
385     if (!opts.checkEnvFirst && var == NULL && ctxt != VAR_GLOBAL) {
386 	var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
387 	if (var == NULL && ctxt != VAR_INTERNAL) {
388 	    /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
389 	    var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
390 	}
391     }
392 
393     if (var == NULL) {
394 	char *env;
395 
396 	if ((env = getenv(name)) != NULL) {
397 	    char *varname = bmake_strdup(name);
398 	    return VarNew(varname, varname, env, VAR_FROM_ENV);
399 	}
400 
401 	if (opts.checkEnvFirst && ctxt != VAR_GLOBAL) {
402 	    var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
403 	    if (var == NULL && ctxt != VAR_INTERNAL)
404 		var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
405 	    return var;
406 	}
407 
408 	return NULL;
409     }
410 
411     return var;
412 }
413 
414 /* If the variable is an environment variable, free it.
415  *
416  * Input:
417  *	v		the variable
418  *	freeValue	true if the variable value should be freed as well
419  *
420  * Results:
421  *	TRUE if it is an environment variable, FALSE otherwise.
422  */
423 static Boolean
424 VarFreeEnv(Var *v, Boolean freeValue)
425 {
426     if (!(v->flags & VAR_FROM_ENV))
427 	return FALSE;
428 
429     free(v->name_freeIt);
430     Buf_Destroy(&v->val, freeValue);
431     free(v);
432     return TRUE;
433 }
434 
435 /* Add a new variable of the given name and value to the given context.
436  * The name and val arguments are duplicated so they may safely be freed. */
437 static void
438 VarAdd(const char *name, const char *val, GNode *ctxt, VarSetFlags flags)
439 {
440     HashEntry *he = HashTable_CreateEntry(&ctxt->context, name, NULL);
441     Var *v = VarNew(he->key /* aliased */, NULL, val,
442 		    flags & VAR_SET_READONLY ? VAR_READONLY : 0);
443     HashEntry_Set(he, v);
444     if (!(ctxt->flags & INTERNAL)) {
445 	VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
446     }
447 }
448 
449 /* Remove a variable from a context, freeing all related memory as well.
450  * The variable name is expanded once. */
451 void
452 Var_Delete(const char *name, GNode *ctxt)
453 {
454     char *name_freeIt = NULL;
455     HashEntry *he;
456 
457     if (strchr(name, '$') != NULL) {
458 	(void)Var_Subst(name, VAR_GLOBAL, VARE_WANTRES, &name_freeIt);
459 	/* TODO: handle errors */
460 	name = name_freeIt;
461     }
462     he = HashTable_FindEntry(&ctxt->context, name);
463     VAR_DEBUG3("%s:delete %s%s\n",
464 	       ctxt->name, name, he != NULL ? "" : " (not found)");
465     free(name_freeIt);
466 
467     if (he != NULL) {
468 	Var *v = HashEntry_Get(he);
469 	if (v->flags & VAR_EXPORTED)
470 	    unsetenv(v->name);
471 	if (strcmp(v->name, MAKE_EXPORTED) == 0)
472 	    var_exportedVars = VAR_EXPORTED_NONE;
473 	assert(v->name_freeIt == NULL);
474 	HashTable_DeleteEntry(&ctxt->context, he);
475 	Buf_Destroy(&v->val, TRUE);
476 	free(v);
477     }
478 }
479 
480 static Boolean
481 MayExport(const char *name)
482 {
483     if (name[0] == '.')
484 	return FALSE;		/* skip internals */
485     if (name[0] == '-')
486 	return FALSE;		/* skip misnamed variables */
487     if (name[1] == '\0') {
488 	/*
489 	 * A single char.
490 	 * If it is one of the vars that should only appear in
491 	 * local context, skip it, else we can get Var_Subst
492 	 * into a loop.
493 	 */
494 	switch (name[0]) {
495 	case '@':
496 	case '%':
497 	case '*':
498 	case '!':
499 	    return FALSE;
500 	}
501     }
502     return TRUE;
503 }
504 
505 /*
506  * Export a single variable.
507  * We ignore make internal variables (those which start with '.').
508  * Also we jump through some hoops to avoid calling setenv
509  * more than necessary since it can leak.
510  * We only manipulate flags of vars if 'parent' is set.
511  */
512 static Boolean
513 Var_Export1(const char *name, VarExportFlags flags)
514 {
515     VarExportFlags parent = flags & VAR_EXPORT_PARENT;
516     Var *v;
517     char *val;
518 
519     if (!MayExport(name))
520 	return FALSE;
521 
522     v = VarFind(name, VAR_GLOBAL, FALSE);
523     if (v == NULL)
524 	return FALSE;
525 
526     if (!parent && (v->flags & VAR_EXPORTED) && !(v->flags & VAR_REEXPORT))
527 	return FALSE;		/* nothing to do */
528 
529     val = Buf_GetAll(&v->val, NULL);
530     if (!(flags & VAR_EXPORT_LITERAL) && strchr(val, '$') != NULL) {
531 	char *expr;
532 
533 	if (parent) {
534 	    /*
535 	     * Flag the variable as something we need to re-export.
536 	     * No point actually exporting it now though,
537 	     * the child process can do it at the last minute.
538 	     */
539 	    v->flags |= VAR_EXPORTED | VAR_REEXPORT;
540 	    return TRUE;
541 	}
542 	if (v->flags & VAR_IN_USE) {
543 	    /*
544 	     * We recursed while exporting in a child.
545 	     * This isn't going to end well, just skip it.
546 	     */
547 	    return FALSE;
548 	}
549 
550 	/* XXX: name is injected without escaping it */
551 	expr = str_concat3("${", name, "}");
552 	(void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &val);
553 	/* TODO: handle errors */
554 	setenv(name, val, 1);
555 	free(val);
556 	free(expr);
557     } else {
558 	if (parent)
559 	    v->flags &= ~(unsigned)VAR_REEXPORT;	/* once will do */
560 	if (parent || !(v->flags & VAR_EXPORTED))
561 	    setenv(name, val, 1);
562     }
563 
564     /*
565      * This is so Var_Set knows to call Var_Export again...
566      */
567     if (parent) {
568 	v->flags |= VAR_EXPORTED;
569     }
570     return TRUE;
571 }
572 
573 /*
574  * This gets called from our child processes.
575  */
576 void
577 Var_ExportVars(void)
578 {
579     char *val;
580 
581     /*
582      * Several make's support this sort of mechanism for tracking
583      * recursion - but each uses a different name.
584      * We allow the makefiles to update MAKELEVEL and ensure
585      * children see a correctly incremented value.
586      */
587     char tmp[BUFSIZ];
588     snprintf(tmp, sizeof tmp, "%d", makelevel + 1);
589     setenv(MAKE_LEVEL_ENV, tmp, 1);
590 
591     if (var_exportedVars == VAR_EXPORTED_NONE)
592 	return;
593 
594     if (var_exportedVars == VAR_EXPORTED_ALL) {
595 	HashIter hi;
596 
597 	/* Ouch! Exporting all variables at once is crazy... */
598 	HashIter_Init(&hi, &VAR_GLOBAL->context);
599 	while (HashIter_Next(&hi) != NULL) {
600 	    Var *var = hi.entry->value;
601 	    Var_Export1(var->name, VAR_EXPORT_NORMAL);
602 	}
603 	return;
604     }
605 
606     (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES, &val);
607     /* TODO: handle errors */
608     if (*val) {
609 	Words words = Str_Words(val, FALSE);
610 	size_t i;
611 
612 	for (i = 0; i < words.len; i++)
613 	    Var_Export1(words.words[i], VAR_EXPORT_NORMAL);
614 	Words_Free(words);
615     }
616     free(val);
617 }
618 
619 /*
620  * This is called when .export is seen or .MAKE.EXPORTED is modified.
621  *
622  * It is also called when any exported variable is modified.
623  * XXX: Is it really?
624  *
625  * str has the format "[-env|-literal] varname...".
626  */
627 void
628 Var_Export(const char *str, Boolean isExport)
629 {
630     VarExportFlags flags;
631     char *val;
632 
633     if (isExport && str[0] == '\0') {
634 	var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
635 	return;
636     }
637 
638     if (isExport && strncmp(str, "-env", 4) == 0) {
639 	str += 4;
640 	flags = 0;
641     } else if (isExport && strncmp(str, "-literal", 8) == 0) {
642 	str += 8;
643 	flags = VAR_EXPORT_LITERAL;
644     } else {
645 	flags = VAR_EXPORT_PARENT;
646     }
647 
648     (void)Var_Subst(str, VAR_GLOBAL, VARE_WANTRES, &val);
649     /* TODO: handle errors */
650     if (val[0] != '\0') {
651 	Words words = Str_Words(val, FALSE);
652 
653 	size_t i;
654 	for (i = 0; i < words.len; i++) {
655 	    const char *name = words.words[i];
656 	    if (Var_Export1(name, flags)) {
657 		if (var_exportedVars == VAR_EXPORTED_NONE)
658 		    var_exportedVars = VAR_EXPORTED_SOME;
659 		if (isExport && (flags & VAR_EXPORT_PARENT)) {
660 		    Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
661 		}
662 	    }
663 	}
664 	Words_Free(words);
665     }
666     free(val);
667 }
668 
669 
670 extern char **environ;
671 
672 /*
673  * This is called when .unexport[-env] is seen.
674  *
675  * str must have the form "unexport[-env] varname...".
676  */
677 void
678 Var_UnExport(const char *str)
679 {
680     const char *varnames;
681     char *varnames_freeIt;
682     Boolean unexport_env;
683 
684     varnames = NULL;
685     varnames_freeIt = NULL;
686 
687     str += strlen("unexport");
688     unexport_env = strncmp(str, "-env", 4) == 0;
689     if (unexport_env) {
690 	const char *cp;
691 	char **newenv;
692 
693 	cp = getenv(MAKE_LEVEL_ENV);	/* we should preserve this */
694 	if (environ == savedEnv) {
695 	    /* we have been here before! */
696 	    newenv = bmake_realloc(environ, 2 * sizeof(char *));
697 	} else {
698 	    if (savedEnv) {
699 		free(savedEnv);
700 		savedEnv = NULL;
701 	    }
702 	    newenv = bmake_malloc(2 * sizeof(char *));
703 	}
704 
705 	/* Note: we cannot safely free() the original environ. */
706 	environ = savedEnv = newenv;
707 	newenv[0] = NULL;
708 	newenv[1] = NULL;
709 	if (cp && *cp)
710 	    setenv(MAKE_LEVEL_ENV, cp, 1);
711     } else {
712 	cpp_skip_whitespace(&str);
713 	if (str[0] != '\0')
714 	    varnames = str;
715     }
716 
717     if (varnames == NULL) {
718 	/* Using .MAKE.EXPORTED */
719 	(void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES,
720 			&varnames_freeIt);
721 	/* TODO: handle errors */
722 	varnames = varnames_freeIt;
723     }
724 
725     {
726 	Var *v;
727 	size_t i;
728 
729 	Words words = Str_Words(varnames, FALSE);
730 	for (i = 0; i < words.len; i++) {
731 	    const char *varname = words.words[i];
732 	    v = VarFind(varname, VAR_GLOBAL, FALSE);
733 	    if (v == NULL) {
734 		VAR_DEBUG1("Not unexporting \"%s\" (not found)\n", varname);
735 		continue;
736 	    }
737 
738 	    VAR_DEBUG1("Unexporting \"%s\"\n", varname);
739 	    if (!unexport_env && (v->flags & VAR_EXPORTED) &&
740 		!(v->flags & VAR_REEXPORT))
741 		unsetenv(v->name);
742 	    v->flags &= ~(unsigned)(VAR_EXPORTED | VAR_REEXPORT);
743 
744 	    /*
745 	     * If we are unexporting a list,
746 	     * remove each one from .MAKE.EXPORTED.
747 	     * If we are removing them all,
748 	     * just delete .MAKE.EXPORTED below.
749 	     */
750 	    if (varnames == str) {
751 		/* XXX: v->name is injected without escaping it */
752 		char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}");
753 		char *cp;
754 		(void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp);
755 		/* TODO: handle errors */
756 		Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL);
757 		free(cp);
758 		free(expr);
759 	    }
760 	}
761 	Words_Free(words);
762 	if (varnames != str) {
763 	    Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
764 	    free(varnames_freeIt);
765 	}
766     }
767 }
768 
769 /* See Var_Set for documentation. */
770 void
771 Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
772 		 VarSetFlags flags)
773 {
774     const char *unexpanded_name = name;
775     char *name_freeIt = NULL;
776     Var *v;
777 
778     assert(val != NULL);
779 
780     if (strchr(name, '$') != NULL) {
781 	(void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
782 	/* TODO: handle errors */
783 	name = name_freeIt;
784     }
785 
786     if (name[0] == '\0') {
787 	VAR_DEBUG2("Var_Set(\"%s\", \"%s\", ...) "
788 		   "name expands to empty string - ignored\n",
789 		   unexpanded_name, val);
790 	free(name_freeIt);
791 	return;
792     }
793 
794     if (ctxt == VAR_GLOBAL) {
795 	v = VarFind(name, VAR_CMDLINE, FALSE);
796 	if (v != NULL) {
797 	    if (v->flags & VAR_FROM_CMD) {
798 		VAR_DEBUG3("%s:%s = %s ignored!\n", ctxt->name, name, val);
799 		goto out;
800 	    }
801 	    VarFreeEnv(v, TRUE);
802 	}
803     }
804 
805     /*
806      * We only look for a variable in the given context since anything set
807      * here will override anything in a lower context, so there's not much
808      * point in searching them all just to save a bit of memory...
809      */
810     v = VarFind(name, ctxt, FALSE);
811     if (v == NULL) {
812 	if (ctxt == VAR_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
813 	    /*
814 	     * This var would normally prevent the same name being added
815 	     * to VAR_GLOBAL, so delete it from there if needed.
816 	     * Otherwise -V name may show the wrong value.
817 	     */
818 	    /* XXX: name is expanded for the second time */
819 	    Var_Delete(name, VAR_GLOBAL);
820 	}
821 	VarAdd(name, val, ctxt, flags);
822     } else {
823 	if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) {
824 	    VAR_DEBUG3("%s:%s = %s ignored (read-only)\n",
825 		       ctxt->name, name, val);
826 	    goto out;
827 	}
828 	Buf_Empty(&v->val);
829 	Buf_AddStr(&v->val, val);
830 
831 	VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
832 	if (v->flags & VAR_EXPORTED) {
833 	    Var_Export1(name, VAR_EXPORT_PARENT);
834 	}
835     }
836     /*
837      * Any variables given on the command line are automatically exported
838      * to the environment (as per POSIX standard)
839      * Other than internals.
840      */
841     if (ctxt == VAR_CMDLINE && !(flags & VAR_SET_NO_EXPORT) && name[0] != '.') {
842 	if (v == NULL)
843 	    v = VarFind(name, ctxt, FALSE); /* we just added it */
844 	v->flags |= VAR_FROM_CMD;
845 
846 	/*
847 	 * If requested, don't export these in the environment
848 	 * individually.  We still put them in MAKEOVERRIDES so
849 	 * that the command-line settings continue to override
850 	 * Makefile settings.
851 	 */
852 	if (!opts.varNoExportEnv)
853 	    setenv(name, val, 1);
854 
855 	Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
856     }
857     if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
858 	save_dollars = ParseBoolean(val, save_dollars);
859 
860 out:
861     free(name_freeIt);
862     if (v != NULL)
863 	VarFreeEnv(v, TRUE);
864 }
865 
866 /*-
867  *-----------------------------------------------------------------------
868  * Var_Set --
869  *	Set the variable name to the value val in the given context.
870  *
871  *	If the variable doesn't yet exist, it is created.
872  *	Otherwise the new value overwrites and replaces the old value.
873  *
874  * Input:
875  *	name		name of the variable to set, is expanded once
876  *	val		value to give to the variable
877  *	ctxt		context in which to set it
878  *
879  * Notes:
880  *	The variable is searched for only in its context before being
881  *	created in that context. I.e. if the context is VAR_GLOBAL,
882  *	only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMDLINE,
883  *	only VAR_CMDLINE->context is searched. This is done to avoid the
884  *	literally thousands of unnecessary strcmp's that used to be done to
885  *	set, say, $(@) or $(<).
886  *	If the context is VAR_GLOBAL though, we check if the variable
887  *	was set in VAR_CMDLINE from the command line and skip it if so.
888  *-----------------------------------------------------------------------
889  */
890 void
891 Var_Set(const char *name, const char *val, GNode *ctxt)
892 {
893     Var_SetWithFlags(name, val, ctxt, VAR_SET_NONE);
894 }
895 
896 /*-
897  *-----------------------------------------------------------------------
898  * Var_Append --
899  *	The variable of the given name has the given value appended to it in
900  *	the given context.
901  *
902  *	If the variable doesn't exist, it is created. Otherwise the strings
903  *	are concatenated, with a space in between.
904  *
905  * Input:
906  *	name		name of the variable to modify, is expanded once
907  *	val		string to append to it
908  *	ctxt		context in which this should occur
909  *
910  * Notes:
911  *	Only if the variable is being sought in the global context is the
912  *	environment searched.
913  *	XXX: Knows its calling circumstances in that if called with ctxt
914  *	an actual target, it will only search that context since only
915  *	a local variable could be being appended to. This is actually
916  *	a big win and must be tolerated.
917  *-----------------------------------------------------------------------
918  */
919 void
920 Var_Append(const char *name, const char *val, GNode *ctxt)
921 {
922     char *name_freeIt = NULL;
923     Var *v;
924 
925     assert(val != NULL);
926 
927     if (strchr(name, '$') != NULL) {
928 	const char *unexpanded_name = name;
929 	(void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
930 	/* TODO: handle errors */
931 	name = name_freeIt;
932 	if (name[0] == '\0') {
933 	    VAR_DEBUG2("Var_Append(\"%s\", \"%s\", ...) "
934 		       "name expands to empty string - ignored\n",
935 		       unexpanded_name, val);
936 	    free(name_freeIt);
937 	    return;
938 	}
939     }
940 
941     v = VarFind(name, ctxt, ctxt == VAR_GLOBAL);
942 
943     if (v == NULL) {
944 	/* XXX: name is expanded for the second time */
945 	Var_Set(name, val, ctxt);
946     } else if (v->flags & VAR_READONLY) {
947 	VAR_DEBUG1("Ignoring append to %s since it is read-only\n", name);
948     } else if (ctxt == VAR_CMDLINE || !(v->flags & VAR_FROM_CMD)) {
949 	Buf_AddByte(&v->val, ' ');
950 	Buf_AddStr(&v->val, val);
951 
952 	VAR_DEBUG3("%s:%s = %s\n",
953 		   ctxt->name, name, Buf_GetAll(&v->val, NULL));
954 
955 	if (v->flags & VAR_FROM_ENV) {
956 	    /*
957 	     * If the original variable came from the environment, we
958 	     * have to install it in the global context (we could place
959 	     * it in the environment, but then we should provide a way to
960 	     * export other variables...)
961 	     */
962 	    v->flags &= ~(unsigned)VAR_FROM_ENV;
963 	    /* This is the only place where a variable is created whose
964 	     * v->name is not the same as ctxt->context->key. */
965 	    HashTable_Set(&ctxt->context, name, v);
966 	}
967     }
968     free(name_freeIt);
969 }
970 
971 /* See if the given variable exists, in the given context or in other
972  * fallback contexts.
973  *
974  * Input:
975  *	name		Variable to find, is expanded once
976  *	ctxt		Context in which to start search
977  */
978 Boolean
979 Var_Exists(const char *name, GNode *ctxt)
980 {
981     char *name_freeIt = NULL;
982     Var *v;
983 
984     if (strchr(name, '$') != NULL) {
985 	(void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
986 	/* TODO: handle errors */
987 	name = name_freeIt;
988     }
989 
990     v = VarFind(name, ctxt, TRUE);
991     free(name_freeIt);
992     if (v == NULL)
993 	return FALSE;
994 
995     (void)VarFreeEnv(v, TRUE);
996     return TRUE;
997 }
998 
999 /*-
1000  *-----------------------------------------------------------------------
1001  * Var_Value --
1002  *	Return the unexpanded value of the given variable in the given
1003  *	context, or the usual contexts.
1004  *
1005  * Input:
1006  *	name		name to find, is not expanded any further
1007  *	ctxt		context in which to search for it
1008  *
1009  * Results:
1010  *	The value if the variable exists, NULL if it doesn't.
1011  *	If the returned value is not NULL, the caller must free
1012  *	out_freeIt when the returned value is no longer needed.
1013  *-----------------------------------------------------------------------
1014  */
1015 const char *
1016 Var_Value(const char *name, GNode *ctxt, void **out_freeIt)
1017 {
1018     Var *v = VarFind(name, ctxt, TRUE);
1019     char *value;
1020 
1021     *out_freeIt = NULL;
1022     if (v == NULL)
1023 	return NULL;
1024 
1025     value = Buf_GetAll(&v->val, NULL);
1026     if (VarFreeEnv(v, FALSE))
1027 	*out_freeIt = value;
1028     return value;
1029 }
1030 
1031 /* Return the unexpanded variable value from this node, without trying to look
1032  * up the variable in any other context. */
1033 const char *
1034 Var_ValueDirect(const char *name, GNode *ctxt)
1035 {
1036     Var *v = VarFind(name, ctxt, FALSE);
1037     return v != NULL ? Buf_GetAll(&v->val, NULL) : NULL;
1038 }
1039 
1040 
1041 /* SepBuf is a string being built from words, interleaved with separators. */
1042 typedef struct SepBuf {
1043     Buffer buf;
1044     Boolean needSep;
1045     char sep;			/* usually ' ', but see the :ts modifier */
1046 } SepBuf;
1047 
1048 static void
1049 SepBuf_Init(SepBuf *buf, char sep)
1050 {
1051     Buf_InitSize(&buf->buf, 32);
1052     buf->needSep = FALSE;
1053     buf->sep = sep;
1054 }
1055 
1056 static void
1057 SepBuf_Sep(SepBuf *buf)
1058 {
1059     buf->needSep = TRUE;
1060 }
1061 
1062 static void
1063 SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1064 {
1065     if (mem_size == 0)
1066 	return;
1067     if (buf->needSep && buf->sep != '\0') {
1068 	Buf_AddByte(&buf->buf, buf->sep);
1069 	buf->needSep = FALSE;
1070     }
1071     Buf_AddBytes(&buf->buf, mem, mem_size);
1072 }
1073 
1074 static void
1075 SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end)
1076 {
1077     SepBuf_AddBytes(buf, start, (size_t)(end - start));
1078 }
1079 
1080 static void
1081 SepBuf_AddStr(SepBuf *buf, const char *str)
1082 {
1083     SepBuf_AddBytes(buf, str, strlen(str));
1084 }
1085 
1086 static char *
1087 SepBuf_Destroy(SepBuf *buf, Boolean free_buf)
1088 {
1089     return Buf_Destroy(&buf->buf, free_buf);
1090 }
1091 
1092 
1093 /* This callback for ModifyWords gets a single word from a variable expression
1094  * and typically adds a modification of this word to the buffer. It may also
1095  * do nothing or add several words.
1096  *
1097  * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for
1098  * each word of "a b c". */
1099 typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data);
1100 
1101 
1102 /* Callback for ModifyWords to implement the :H modifier.
1103  * Add the dirname of the given word to the buffer. */
1104 static void
1105 ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1106 {
1107     const char *slash = strrchr(word, '/');
1108     if (slash != NULL)
1109 	SepBuf_AddBytesBetween(buf, word, slash);
1110     else
1111 	SepBuf_AddStr(buf, ".");
1112 }
1113 
1114 /* Callback for ModifyWords to implement the :T modifier.
1115  * Add the basename of the given word to the buffer. */
1116 static void
1117 ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1118 {
1119     const char *slash = strrchr(word, '/');
1120     const char *base = slash != NULL ? slash + 1 : word;
1121     SepBuf_AddStr(buf, base);
1122 }
1123 
1124 /* Callback for ModifyWords to implement the :E modifier.
1125  * Add the filename suffix of the given word to the buffer, if it exists. */
1126 static void
1127 ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1128 {
1129     const char *dot = strrchr(word, '.');
1130     if (dot != NULL)
1131 	SepBuf_AddStr(buf, dot + 1);
1132 }
1133 
1134 /* Callback for ModifyWords to implement the :R modifier.
1135  * Add the basename of the given word to the buffer. */
1136 static void
1137 ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1138 {
1139     const char *dot = strrchr(word, '.');
1140     size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1141     SepBuf_AddBytes(buf, word, len);
1142 }
1143 
1144 /* Callback for ModifyWords to implement the :M modifier.
1145  * Place the word in the buffer if it matches the given pattern. */
1146 static void
1147 ModifyWord_Match(const char *word, SepBuf *buf, void *data)
1148 {
1149     const char *pattern = data;
1150     VAR_DEBUG2("VarMatch [%s] [%s]\n", word, pattern);
1151     if (Str_Match(word, pattern))
1152 	SepBuf_AddStr(buf, word);
1153 }
1154 
1155 /* Callback for ModifyWords to implement the :N modifier.
1156  * Place the word in the buffer if it doesn't match the given pattern. */
1157 static void
1158 ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
1159 {
1160     const char *pattern = data;
1161     if (!Str_Match(word, pattern))
1162 	SepBuf_AddStr(buf, word);
1163 }
1164 
1165 #ifdef SYSVVARSUB
1166 /* Check word against pattern for a match (% is a wildcard).
1167  *
1168  * Input:
1169  *	word		Word to examine
1170  *	pattern		Pattern to examine against
1171  *
1172  * Results:
1173  *	Returns the start of the match, or NULL.
1174  *	out_match_len returns the length of the match, if any.
1175  *	out_hasPercent returns whether the pattern contains a percent.
1176  */
1177 static const char *
1178 SysVMatch(const char *word, const char *pattern,
1179 	      size_t *out_match_len, Boolean *out_hasPercent)
1180 {
1181     const char *p = pattern;
1182     const char *w = word;
1183     const char *percent;
1184     size_t w_len;
1185     size_t p_len;
1186     const char *w_tail;
1187 
1188     *out_hasPercent = FALSE;
1189     percent = strchr(p, '%');
1190     if (percent != NULL) {	/* ${VAR:...%...=...} */
1191 	*out_hasPercent = TRUE;
1192 	if (*w == '\0')
1193 	    return NULL;	/* empty word does not match pattern */
1194 
1195 	/* check that the prefix matches */
1196 	for (; p != percent && *w != '\0' && *w == *p; w++, p++)
1197 	    continue;
1198 	if (p != percent)
1199 	    return NULL;	/* No match */
1200 
1201 	p++;			/* Skip the percent */
1202 	if (*p == '\0') {
1203 	    /* No more pattern, return the rest of the string */
1204 	    *out_match_len = strlen(w);
1205 	    return w;
1206 	}
1207     }
1208 
1209     /* Test whether the tail matches */
1210     w_len = strlen(w);
1211     p_len = strlen(p);
1212     if (w_len < p_len)
1213 	return NULL;
1214 
1215     w_tail = w + w_len - p_len;
1216     if (memcmp(p, w_tail, p_len) != 0)
1217 	return NULL;
1218 
1219     *out_match_len = (size_t)(w_tail - w);
1220     return w;
1221 }
1222 
1223 struct ModifyWord_SYSVSubstArgs {
1224     GNode *ctx;
1225     const char *lhs;
1226     const char *rhs;
1227 };
1228 
1229 /* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1230 static void
1231 ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
1232 {
1233     const struct ModifyWord_SYSVSubstArgs *args = data;
1234     char *rhs_expanded;
1235     const char *rhs;
1236     const char *percent;
1237 
1238     size_t match_len;
1239     Boolean lhsPercent;
1240     const char *match = SysVMatch(word, args->lhs, &match_len, &lhsPercent);
1241     if (match == NULL) {
1242 	SepBuf_AddStr(buf, word);
1243 	return;
1244     }
1245 
1246     /* Append rhs to the buffer, substituting the first '%' with the
1247      * match, but only if the lhs had a '%' as well. */
1248 
1249     (void)Var_Subst(args->rhs, args->ctx, VARE_WANTRES, &rhs_expanded);
1250     /* TODO: handle errors */
1251 
1252     rhs = rhs_expanded;
1253     percent = strchr(rhs, '%');
1254 
1255     if (percent != NULL && lhsPercent) {
1256 	/* Copy the prefix of the replacement pattern */
1257 	SepBuf_AddBytesBetween(buf, rhs, percent);
1258 	rhs = percent + 1;
1259     }
1260     if (percent != NULL || !lhsPercent)
1261 	SepBuf_AddBytes(buf, match, match_len);
1262 
1263     /* Append the suffix of the replacement pattern */
1264     SepBuf_AddStr(buf, rhs);
1265 
1266     free(rhs_expanded);
1267 }
1268 #endif
1269 
1270 
1271 struct ModifyWord_SubstArgs {
1272     const char	*lhs;
1273     size_t	lhsLen;
1274     const char	*rhs;
1275     size_t	rhsLen;
1276     VarPatternFlags pflags;
1277     Boolean	matched;
1278 };
1279 
1280 /* Callback for ModifyWords to implement the :S,from,to, modifier.
1281  * Perform a string substitution on the given word. */
1282 static void
1283 ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
1284 {
1285     size_t wordLen = strlen(word);
1286     struct ModifyWord_SubstArgs *args = data;
1287     const char *match;
1288 
1289     if ((args->pflags & VARP_SUB_ONE) && args->matched)
1290 	goto nosub;
1291 
1292     if (args->pflags & VARP_ANCHOR_START) {
1293 	if (wordLen < args->lhsLen ||
1294 	    memcmp(word, args->lhs, args->lhsLen) != 0)
1295 	    goto nosub;
1296 
1297 	if ((args->pflags & VARP_ANCHOR_END) && wordLen != args->lhsLen)
1298 	    goto nosub;
1299 
1300 	/* :S,^prefix,replacement, or :S,^whole$,replacement, */
1301 	SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1302 	SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen);
1303 	args->matched = TRUE;
1304 	return;
1305     }
1306 
1307     if (args->pflags & VARP_ANCHOR_END) {
1308 	const char *start;
1309 
1310 	if (wordLen < args->lhsLen)
1311 	    goto nosub;
1312 
1313 	start = word + (wordLen - args->lhsLen);
1314 	if (memcmp(start, args->lhs, args->lhsLen) != 0)
1315 	    goto nosub;
1316 
1317 	/* :S,suffix$,replacement, */
1318 	SepBuf_AddBytesBetween(buf, word, start);
1319 	SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1320 	args->matched = TRUE;
1321 	return;
1322     }
1323 
1324     if (args->lhs[0] == '\0')
1325 	goto nosub;
1326 
1327     /* unanchored case, may match more than once */
1328     while ((match = strstr(word, args->lhs)) != NULL) {
1329 	SepBuf_AddBytesBetween(buf, word, match);
1330 	SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1331 	args->matched = TRUE;
1332 	wordLen -= (size_t)(match - word) + args->lhsLen;
1333 	word += (size_t)(match - word) + args->lhsLen;
1334 	if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL))
1335 	    break;
1336     }
1337 nosub:
1338     SepBuf_AddBytes(buf, word, wordLen);
1339 }
1340 
1341 #ifndef NO_REGEX
1342 /* Print the error caused by a regcomp or regexec call. */
1343 static void
1344 VarREError(int reerr, const regex_t *pat, const char *str)
1345 {
1346     size_t errlen = regerror(reerr, pat, NULL, 0);
1347     char *errbuf = bmake_malloc(errlen);
1348     regerror(reerr, pat, errbuf, errlen);
1349     Error("%s: %s", str, errbuf);
1350     free(errbuf);
1351 }
1352 
1353 struct ModifyWord_SubstRegexArgs {
1354     regex_t re;
1355     size_t nsub;
1356     char *replace;
1357     VarPatternFlags pflags;
1358     Boolean matched;
1359 };
1360 
1361 /* Callback for ModifyWords to implement the :C/from/to/ modifier.
1362  * Perform a regex substitution on the given word. */
1363 static void
1364 ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data)
1365 {
1366     struct ModifyWord_SubstRegexArgs *args = data;
1367     int xrv;
1368     const char *wp = word;
1369     char *rp;
1370     int flags = 0;
1371     regmatch_t m[10];
1372 
1373     if ((args->pflags & VARP_SUB_ONE) && args->matched)
1374 	goto nosub;
1375 
1376 tryagain:
1377     xrv = regexec(&args->re, wp, args->nsub, m, flags);
1378 
1379     switch (xrv) {
1380     case 0:
1381 	args->matched = TRUE;
1382 	SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1383 
1384 	for (rp = args->replace; *rp; rp++) {
1385 	    if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
1386 		SepBuf_AddBytes(buf, rp + 1, 1);
1387 		rp++;
1388 		continue;
1389 	    }
1390 
1391 	    if (*rp == '&') {
1392 		SepBuf_AddBytesBetween(buf, wp + m[0].rm_so, wp + m[0].rm_eo);
1393 		continue;
1394 	    }
1395 
1396 	    if (*rp != '\\' || !ch_isdigit(rp[1])) {
1397 		SepBuf_AddBytes(buf, rp, 1);
1398 		continue;
1399 	    }
1400 
1401 	    {			/* \0 to \9 backreference */
1402 		size_t n = (size_t)(rp[1] - '0');
1403 		rp++;
1404 
1405 		if (n >= args->nsub) {
1406 		    Error("No subexpression \\%zu", n);
1407 		} else if (m[n].rm_so == -1) {
1408 		    Error("No match for subexpression \\%zu", n);
1409 		} else {
1410 		    SepBuf_AddBytesBetween(buf, wp + m[n].rm_so,
1411 					   wp + m[n].rm_eo);
1412 		}
1413 	    }
1414 	}
1415 
1416 	wp += m[0].rm_eo;
1417 	if (args->pflags & VARP_SUB_GLOBAL) {
1418 	    flags |= REG_NOTBOL;
1419 	    if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1420 		SepBuf_AddBytes(buf, wp, 1);
1421 		wp++;
1422 	    }
1423 	    if (*wp)
1424 		goto tryagain;
1425 	}
1426 	if (*wp) {
1427 	    SepBuf_AddStr(buf, wp);
1428 	}
1429 	break;
1430     default:
1431 	VarREError(xrv, &args->re, "Unexpected regex error");
1432 	/* FALLTHROUGH */
1433     case REG_NOMATCH:
1434     nosub:
1435 	SepBuf_AddStr(buf, wp);
1436 	break;
1437     }
1438 }
1439 #endif
1440 
1441 
1442 struct ModifyWord_LoopArgs {
1443     GNode	*ctx;
1444     char	*tvar;		/* name of temporary variable */
1445     char	*str;		/* string to expand */
1446     VarEvalFlags eflags;
1447 };
1448 
1449 /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1450 static void
1451 ModifyWord_Loop(const char *word, SepBuf *buf, void *data)
1452 {
1453     const struct ModifyWord_LoopArgs *args;
1454     char *s;
1455 
1456     if (word[0] == '\0')
1457 	return;
1458 
1459     args = data;
1460     Var_SetWithFlags(args->tvar, word, args->ctx, VAR_SET_NO_EXPORT);
1461     (void)Var_Subst(args->str, args->ctx, args->eflags, &s);
1462     /* TODO: handle errors */
1463 
1464     VAR_DEBUG4("ModifyWord_Loop: "
1465 	       "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n",
1466 	       word, args->tvar, args->str, s);
1467 
1468     if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1469 	buf->needSep = FALSE;
1470     SepBuf_AddStr(buf, s);
1471     free(s);
1472 }
1473 
1474 
1475 /* The :[first..last] modifier selects words from the expression.
1476  * It can also reverse the words. */
1477 static char *
1478 VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first,
1479 	       int last)
1480 {
1481     Words words;
1482     int len, start, end, step;
1483     int i;
1484 
1485     SepBuf buf;
1486     SepBuf_Init(&buf, sep);
1487 
1488     if (oneBigWord) {
1489 	/* fake what Str_Words() would do if there were only one word */
1490 	words.len = 1;
1491 	words.words = bmake_malloc((words.len + 1) * sizeof(words.words[0]));
1492 	words.freeIt = bmake_strdup(str);
1493 	words.words[0] = words.freeIt;
1494 	words.words[1] = NULL;
1495     } else {
1496 	words = Str_Words(str, FALSE);
1497     }
1498 
1499     /*
1500      * Now sanitize the given range.
1501      * If first or last are negative, convert them to the positive equivalents
1502      * (-1 gets converted to ac, -2 gets converted to (ac - 1), etc.).
1503      */
1504     len = (int)words.len;
1505     if (first < 0)
1506 	first += len + 1;
1507     if (last < 0)
1508 	last += len + 1;
1509 
1510     /*
1511      * We avoid scanning more of the list than we need to.
1512      */
1513     if (first > last) {
1514 	start = (first > len ? len : first) - 1;
1515 	end = last < 1 ? 0 : last - 1;
1516 	step = -1;
1517     } else {
1518 	start = first < 1 ? 0 : first - 1;
1519 	end = last > len ? len : last;
1520 	step = 1;
1521     }
1522 
1523     for (i = start; (step < 0) == (i >= end); i += step) {
1524 	SepBuf_AddStr(&buf, words.words[i]);
1525 	SepBuf_Sep(&buf);
1526     }
1527 
1528     Words_Free(words);
1529 
1530     return SepBuf_Destroy(&buf, FALSE);
1531 }
1532 
1533 
1534 /* Callback for ModifyWords to implement the :tA modifier.
1535  * Replace each word with the result of realpath() if successful. */
1536 static void
1537 ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1538 {
1539     struct stat st;
1540     char rbuf[MAXPATHLEN];
1541 
1542     const char *rp = cached_realpath(word, rbuf);
1543     if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1544 	word = rp;
1545 
1546     SepBuf_AddStr(buf, word);
1547 }
1548 
1549 /* Modify each of the words of the passed string using the given function.
1550  *
1551  * Input:
1552  *	str		String whose words should be modified
1553  *	modifyWord	Function that modifies a single word
1554  *	modifyWord_args Custom arguments for modifyWord
1555  *
1556  * Results:
1557  *	A string of all the words modified appropriately.
1558  *-----------------------------------------------------------------------
1559  */
1560 static char *
1561 ModifyWords(const char *str,
1562 	    ModifyWordsCallback modifyWord, void *modifyWord_args,
1563 	    Boolean oneBigWord, char sep)
1564 {
1565     SepBuf result;
1566     Words words;
1567     size_t i;
1568 
1569     if (oneBigWord) {
1570 	SepBuf_Init(&result, sep);
1571 	modifyWord(str, &result, modifyWord_args);
1572 	return SepBuf_Destroy(&result, FALSE);
1573     }
1574 
1575     SepBuf_Init(&result, sep);
1576 
1577     words = Str_Words(str, FALSE);
1578 
1579     VAR_DEBUG2("ModifyWords: split \"%s\" into %zu words\n", str, words.len);
1580 
1581     for (i = 0; i < words.len; i++) {
1582 	modifyWord(words.words[i], &result, modifyWord_args);
1583 	if (Buf_Len(&result.buf) > 0)
1584 	    SepBuf_Sep(&result);
1585     }
1586 
1587     Words_Free(words);
1588 
1589     return SepBuf_Destroy(&result, FALSE);
1590 }
1591 
1592 
1593 static char *
1594 Words_JoinFree(Words words)
1595 {
1596     Buffer buf;
1597     size_t i;
1598 
1599     Buf_Init(&buf);
1600 
1601     for (i = 0; i < words.len; i++) {
1602 	if (i != 0)
1603 	    Buf_AddByte(&buf, ' ');	/* XXX: st->sep, for consistency */
1604 	Buf_AddStr(&buf, words.words[i]);
1605     }
1606 
1607     Words_Free(words);
1608 
1609     return Buf_Destroy(&buf, FALSE);
1610 }
1611 
1612 /* Remove adjacent duplicate words. */
1613 static char *
1614 VarUniq(const char *str)
1615 {
1616     Words words = Str_Words(str, FALSE);
1617 
1618     if (words.len > 1) {
1619 	size_t i, j;
1620 	for (j = 0, i = 1; i < words.len; i++)
1621 	    if (strcmp(words.words[i], words.words[j]) != 0 && (++j != i))
1622 		words.words[j] = words.words[i];
1623 	words.len = j + 1;
1624     }
1625 
1626     return Words_JoinFree(words);
1627 }
1628 
1629 
1630 /* Quote shell meta-characters and space characters in the string.
1631  * If quoteDollar is set, also quote and double any '$' characters. */
1632 static char *
1633 VarQuote(const char *str, Boolean quoteDollar)
1634 {
1635     Buffer buf;
1636     Buf_Init(&buf);
1637 
1638     for (; *str != '\0'; str++) {
1639 	if (*str == '\n') {
1640 	    const char *newline = Shell_GetNewline();
1641 	    if (newline == NULL)
1642 		newline = "\\\n";
1643 	    Buf_AddStr(&buf, newline);
1644 	    continue;
1645 	}
1646 	if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str))
1647 	    Buf_AddByte(&buf, '\\');
1648 	Buf_AddByte(&buf, *str);
1649 	if (quoteDollar && *str == '$')
1650 	    Buf_AddStr(&buf, "\\$");
1651     }
1652 
1653     return Buf_Destroy(&buf, FALSE);
1654 }
1655 
1656 /* Compute the 32-bit hash of the given string, using the MurmurHash3
1657  * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */
1658 static char *
1659 VarHash(const char *str)
1660 {
1661     static const char    hexdigits[16] = "0123456789abcdef";
1662     const unsigned char *ustr = (const unsigned char *)str;
1663 
1664     uint32_t h  = 0x971e137bU;
1665     uint32_t c1 = 0x95543787U;
1666     uint32_t c2 = 0x2ad7eb25U;
1667     size_t len2 = strlen(str);
1668 
1669     char *buf;
1670     size_t i;
1671 
1672     size_t len;
1673     for (len = len2; len; ) {
1674 	uint32_t k = 0;
1675 	switch (len) {
1676 	default:
1677 	    k = ((uint32_t)ustr[3] << 24) |
1678 		((uint32_t)ustr[2] << 16) |
1679 		((uint32_t)ustr[1] << 8) |
1680 		(uint32_t)ustr[0];
1681 	    len -= 4;
1682 	    ustr += 4;
1683 	    break;
1684 	case 3:
1685 	    k |= (uint32_t)ustr[2] << 16;
1686 	    /* FALLTHROUGH */
1687 	case 2:
1688 	    k |= (uint32_t)ustr[1] << 8;
1689 	    /* FALLTHROUGH */
1690 	case 1:
1691 	    k |= (uint32_t)ustr[0];
1692 	    len = 0;
1693 	}
1694 	c1 = c1 * 5 + 0x7b7d159cU;
1695 	c2 = c2 * 5 + 0x6bce6396U;
1696 	k *= c1;
1697 	k = (k << 11) ^ (k >> 21);
1698 	k *= c2;
1699 	h = (h << 13) ^ (h >> 19);
1700 	h = h * 5 + 0x52dce729U;
1701 	h ^= k;
1702     }
1703     h ^= (uint32_t)len2;
1704     h *= 0x85ebca6b;
1705     h ^= h >> 13;
1706     h *= 0xc2b2ae35;
1707     h ^= h >> 16;
1708 
1709     buf = bmake_malloc(9);
1710     for (i = 0; i < 8; i++) {
1711 	buf[i] = hexdigits[h & 0x0f];
1712 	h >>= 4;
1713     }
1714     buf[8] = '\0';
1715     return buf;
1716 }
1717 
1718 static char *
1719 VarStrftime(const char *fmt, Boolean zulu, time_t tim)
1720 {
1721     char buf[BUFSIZ];
1722 
1723     if (tim == 0)
1724 	time(&tim);
1725     if (*fmt == '\0')
1726 	fmt = "%c";
1727     strftime(buf, sizeof buf, fmt, zulu ? gmtime(&tim) : localtime(&tim));
1728 
1729     buf[sizeof buf - 1] = '\0';
1730     return bmake_strdup(buf);
1731 }
1732 
1733 /*
1734  * The ApplyModifier functions take an expression that is being evaluated.
1735  * Their task is to apply a single modifier to the expression.
1736  * To do this, they parse the modifier and its parameters from pp and apply
1737  * the parsed modifier to the current value of the expression, generating a
1738  * new value from it.
1739  *
1740  * The modifier typically lasts until the next ':', or a closing '}' or ')'
1741  * (taken from st->endc), or the end of the string (parse error).
1742  *
1743  * The high-level behavior of these functions is:
1744  *
1745  * 1. parse the modifier
1746  * 2. evaluate the modifier
1747  * 3. housekeeping
1748  *
1749  * Parsing the modifier
1750  *
1751  * If parsing succeeds, the parsing position *pp is updated to point to the
1752  * first character following the modifier, which typically is either ':' or
1753  * st->endc.  The modifier doesn't have to check for this delimiter character,
1754  * this is done by ApplyModifiers.
1755  *
1756  * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not
1757  * need to be followed by a ':' or endc; this was an unintended mistake.
1758  *
1759  * If parsing fails because of a missing delimiter (as in the :S, :C or :@
1760  * modifiers), return AMR_CLEANUP.
1761  *
1762  * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
1763  * try the SysV modifier ${VAR:from=to} as fallback.  This should only be
1764  * done as long as there have been no side effects from evaluating nested
1765  * variables, to avoid evaluating them more than once.  In this case, the
1766  * parsing position may or may not be updated.  (XXX: Why not? The original
1767  * parsing position is well-known in ApplyModifiers.)
1768  *
1769  * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
1770  * as a fallback, either issue an error message using Error or Parse_Error
1771  * and then return AMR_CLEANUP, or return AMR_BAD for the default error
1772  * message.  Both of these return values will stop processing the variable
1773  * expression.  (XXX: As of 2020-08-23, evaluation of the whole string
1774  * continues nevertheless after skipping a few bytes, which essentially is
1775  * undefined behavior.  Not in the sense of C, but still it's impossible to
1776  * predict what happens in the parser.)
1777  *
1778  * Evaluating the modifier
1779  *
1780  * After parsing, the modifier is evaluated.  The side effects from evaluating
1781  * nested variable expressions in the modifier text often already happen
1782  * during parsing though.
1783  *
1784  * Evaluating the modifier usually takes the current value of the variable
1785  * expression from st->val, or the variable name from st->var->name and stores
1786  * the result in st->newVal.
1787  *
1788  * If evaluating fails (as of 2020-08-23), an error message is printed using
1789  * Error.  This function has no side-effects, it really just prints the error
1790  * message.  Processing the expression continues as if everything were ok.
1791  * XXX: This should be fixed by adding proper error handling to Var_Subst,
1792  * Var_Parse, ApplyModifiers and ModifyWords.
1793  *
1794  * Housekeeping
1795  *
1796  * Some modifiers such as :D and :U turn undefined expressions into defined
1797  * expressions (see VEF_UNDEF, VEF_DEF).
1798  *
1799  * Some modifiers need to free some memory.
1800  */
1801 
1802 typedef enum VarExprFlags {
1803     /* The variable expression is based on an undefined variable. */
1804     VEF_UNDEF = 0x01,
1805     /* The variable expression started as an undefined expression, but one
1806      * of the modifiers (such as :D or :U) has turned the expression from
1807      * undefined to defined. */
1808     VEF_DEF = 0x02
1809 } VarExprFlags;
1810 
1811 ENUM_FLAGS_RTTI_2(VarExprFlags,
1812 		  VEF_UNDEF, VEF_DEF);
1813 
1814 
1815 typedef struct ApplyModifiersState {
1816     const char startc;		/* '\0' or '{' or '(' */
1817     const char endc;		/* '\0' or '}' or ')' */
1818     Var * const var;
1819     GNode * const ctxt;
1820     const VarEvalFlags eflags;
1821 
1822     char *val;			/* The old value of the expression,
1823 				 * before applying the modifier, never NULL */
1824     char *newVal;		/* The new value of the expression,
1825 				 * after applying the modifier, never NULL */
1826     char sep;			/* Word separator in expansions
1827 				 * (see the :ts modifier) */
1828     Boolean oneBigWord;		/* TRUE if some modifiers that otherwise split
1829 				 * the variable value into words, like :S and
1830 				 * :C, treat the variable value as a single big
1831 				 * word, possibly containing spaces. */
1832     VarExprFlags exprFlags;
1833 } ApplyModifiersState;
1834 
1835 static void
1836 ApplyModifiersState_Define(ApplyModifiersState *st)
1837 {
1838     if (st->exprFlags & VEF_UNDEF)
1839 	st->exprFlags |= VEF_DEF;
1840 }
1841 
1842 typedef enum ApplyModifierResult {
1843     AMR_OK,			/* Continue parsing */
1844     AMR_UNKNOWN,		/* Not a match, try other modifiers as well */
1845     AMR_BAD,			/* Error out with "Bad modifier" message */
1846     AMR_CLEANUP			/* Error out without error message */
1847 } ApplyModifierResult;
1848 
1849 /* Allow backslashes to escape the delimiter, $, and \, but don't touch other
1850  * backslashes. */
1851 static Boolean
1852 IsEscapedModifierPart(const char *p, char delim,
1853 		      struct ModifyWord_SubstArgs *subst)
1854 {
1855     if (p[0] != '\\')
1856 	return FALSE;
1857     if (p[1] == delim || p[1] == '\\' || p[1] == '$')
1858 	return TRUE;
1859     return p[1] == '&' && subst != NULL;
1860 }
1861 
1862 /*
1863  * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
1864  * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
1865  * including the next unescaped delimiter.  The delimiter, as well as the
1866  * backslash or the dollar, can be escaped with a backslash.
1867  *
1868  * Return the parsed (and possibly expanded) string, or NULL if no delimiter
1869  * was found.  On successful return, the parsing position pp points right
1870  * after the delimiter.  The delimiter is not included in the returned
1871  * value though.
1872  */
1873 static VarParseResult
1874 ParseModifierPart(
1875     const char **pp,		/* The parsing position, updated upon return */
1876     char delim,			/* Parsing stops at this delimiter */
1877     VarEvalFlags eflags,	/* Flags for evaluating nested variables;
1878 				 * if VARE_WANTRES is not set, the text is
1879 				 * only parsed */
1880     ApplyModifiersState *st,
1881     char **out_part,
1882     size_t *out_length,		/* Optionally stores the length of the returned
1883 				 * string, just to save another strlen call. */
1884     VarPatternFlags *out_pflags,/* For the first part of the :S modifier,
1885 				 * sets the VARP_ANCHOR_END flag if the last
1886 				 * character of the pattern is a $. */
1887     struct ModifyWord_SubstArgs *subst
1888 				/* For the second part of the :S modifier,
1889 				 * allow ampersands to be escaped and replace
1890 				 * unescaped ampersands with subst->lhs. */
1891 ) {
1892     Buffer buf;
1893     const char *p;
1894 
1895     Buf_Init(&buf);
1896 
1897     /*
1898      * Skim through until the matching delimiter is found; pick up variable
1899      * expressions on the way.
1900      */
1901     p = *pp;
1902     while (*p != '\0' && *p != delim) {
1903 	const char *varstart;
1904 
1905 	if (IsEscapedModifierPart(p, delim, subst)) {
1906 	    Buf_AddByte(&buf, p[1]);
1907 	    p += 2;
1908 	    continue;
1909 	}
1910 
1911 	if (*p != '$') {	/* Unescaped, simple text */
1912 	    if (subst != NULL && *p == '&')
1913 		Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
1914 	    else
1915 		Buf_AddByte(&buf, *p);
1916 	    p++;
1917 	    continue;
1918 	}
1919 
1920 	if (p[1] == delim) {	/* Unescaped $ at end of pattern */
1921 	    if (out_pflags != NULL)
1922 		*out_pflags |= VARP_ANCHOR_END;
1923 	    else
1924 		Buf_AddByte(&buf, *p);
1925 	    p++;
1926 	    continue;
1927 	}
1928 
1929 	if (eflags & VARE_WANTRES) {	/* Nested variable, evaluated */
1930 	    const char *nested_p = p;
1931 	    const char *nested_val;
1932 	    void *nested_val_freeIt;
1933 	    VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_KEEP_DOLLAR;
1934 
1935 	    (void)Var_Parse(&nested_p, st->ctxt, nested_eflags,
1936 			    &nested_val, &nested_val_freeIt);
1937 	    /* TODO: handle errors */
1938 	    Buf_AddStr(&buf, nested_val);
1939 	    free(nested_val_freeIt);
1940 	    p += nested_p - p;
1941 	    continue;
1942 	}
1943 
1944 	/* XXX: This whole block is very similar to Var_Parse without
1945 	 * VARE_WANTRES.  There may be subtle edge cases though that are
1946 	 * not yet covered in the unit tests and that are parsed differently,
1947 	 * depending on whether they are evaluated or not.
1948 	 *
1949 	 * This subtle difference is not documented in the manual page,
1950 	 * neither is the difference between parsing :D and :M documented.
1951 	 * No code should ever depend on these details, but who knows. */
1952 
1953 	varstart = p;		/* Nested variable, only parsed */
1954 	if (p[1] == '(' || p[1] == '{') {
1955 	    /*
1956 	     * Find the end of this variable reference
1957 	     * and suck it in without further ado.
1958 	     * It will be interpreted later.
1959 	     */
1960 	    char startc = p[1];
1961 	    int endc = startc == '(' ? ')' : '}';
1962 	    int depth = 1;
1963 
1964 	    for (p += 2; *p != '\0' && depth > 0; p++) {
1965 		if (p[-1] != '\\') {
1966 		    if (*p == startc)
1967 			depth++;
1968 		    if (*p == endc)
1969 			depth--;
1970 		}
1971 	    }
1972 	    Buf_AddBytesBetween(&buf, varstart, p);
1973 	} else {
1974 	    Buf_AddByte(&buf, *varstart);
1975 	    p++;
1976 	}
1977     }
1978 
1979     if (*p != delim) {
1980 	*pp = p;
1981 	Error("Unfinished modifier for %s ('%c' missing)",
1982 	      st->var->name, delim);
1983 	*out_part = NULL;
1984 	return VPR_PARSE_MSG;
1985     }
1986 
1987     *pp = ++p;
1988     if (out_length != NULL)
1989 	*out_length = Buf_Len(&buf);
1990 
1991     *out_part = Buf_Destroy(&buf, FALSE);
1992     VAR_DEBUG1("Modifier part: \"%s\"\n", *out_part);
1993     return VPR_OK;
1994 }
1995 
1996 /* Test whether mod starts with modname, followed by a delimiter. */
1997 MAKE_INLINE Boolean
1998 ModMatch(const char *mod, const char *modname, char endc)
1999 {
2000     size_t n = strlen(modname);
2001     return strncmp(mod, modname, n) == 0 &&
2002 	   (mod[n] == endc || mod[n] == ':');
2003 }
2004 
2005 /* Test whether mod starts with modname, followed by a delimiter or '='. */
2006 MAKE_INLINE Boolean
2007 ModMatchEq(const char *mod, const char *modname, char endc)
2008 {
2009     size_t n = strlen(modname);
2010     return strncmp(mod, modname, n) == 0 &&
2011 	   (mod[n] == endc || mod[n] == ':' || mod[n] == '=');
2012 }
2013 
2014 static Boolean
2015 TryParseIntBase0(const char **pp, int *out_num)
2016 {
2017     char *end;
2018     long n;
2019 
2020     errno = 0;
2021     n = strtol(*pp, &end, 0);
2022     if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
2023 	return FALSE;
2024     if (n < INT_MIN || n > INT_MAX)
2025 	return FALSE;
2026 
2027     *pp = end;
2028     *out_num = (int)n;
2029     return TRUE;
2030 }
2031 
2032 static Boolean
2033 TryParseSize(const char **pp, size_t *out_num)
2034 {
2035     char *end;
2036     unsigned long n;
2037 
2038     if (!ch_isdigit(**pp))
2039 	return FALSE;
2040 
2041     errno = 0;
2042     n = strtoul(*pp, &end, 10);
2043     if (n == ULONG_MAX && errno == ERANGE)
2044 	return FALSE;
2045     if (n > SIZE_MAX)
2046 	return FALSE;
2047 
2048     *pp = end;
2049     *out_num = (size_t)n;
2050     return TRUE;
2051 }
2052 
2053 static Boolean
2054 TryParseChar(const char **pp, int base, char *out_ch)
2055 {
2056     char *end;
2057     unsigned long n;
2058 
2059     if (!ch_isalnum(**pp))
2060 	return FALSE;
2061 
2062     errno = 0;
2063     n = strtoul(*pp, &end, base);
2064     if (n == ULONG_MAX && errno == ERANGE)
2065 	return FALSE;
2066     if (n > UCHAR_MAX)
2067 	return FALSE;
2068 
2069     *pp = end;
2070     *out_ch = (char)n;
2071     return TRUE;
2072 }
2073 
2074 /* :@var@...${var}...@ */
2075 static ApplyModifierResult
2076 ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
2077 {
2078     struct ModifyWord_LoopArgs args;
2079     char prev_sep;
2080     VarParseResult res;
2081 
2082     args.ctx = st->ctxt;
2083 
2084     (*pp)++;			/* Skip the first '@' */
2085     res = ParseModifierPart(pp, '@', VARE_NONE, st,
2086 			    &args.tvar, NULL, NULL, NULL);
2087     if (res != VPR_OK)
2088 	return AMR_CLEANUP;
2089     if (opts.lint && strchr(args.tvar, '$') != NULL) {
2090 	Parse_Error(PARSE_FATAL,
2091 		    "In the :@ modifier of \"%s\", the variable name \"%s\" "
2092 		    "must not contain a dollar.",
2093 		    st->var->name, args.tvar);
2094 	return AMR_CLEANUP;
2095     }
2096 
2097     res = ParseModifierPart(pp, '@', VARE_NONE, st,
2098 			    &args.str, NULL, NULL, NULL);
2099     if (res != VPR_OK)
2100 	return AMR_CLEANUP;
2101 
2102     args.eflags = st->eflags & ~(unsigned)VARE_KEEP_DOLLAR;
2103     prev_sep = st->sep;
2104     st->sep = ' ';		/* XXX: should be st->sep for consistency */
2105     st->newVal = ModifyWords(st->val, ModifyWord_Loop, &args,
2106 			     st->oneBigWord, st->sep);
2107     st->sep = prev_sep;
2108     /* XXX: Consider restoring the previous variable instead of deleting. */
2109     Var_Delete(args.tvar, st->ctxt);
2110     free(args.tvar);
2111     free(args.str);
2112     return AMR_OK;
2113 }
2114 
2115 /* :Ddefined or :Uundefined */
2116 static ApplyModifierResult
2117 ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
2118 {
2119     Buffer buf;
2120     const char *p;
2121 
2122     VarEvalFlags eflags = VARE_NONE;
2123     if (st->eflags & VARE_WANTRES)
2124 	if ((**pp == 'D') == !(st->exprFlags & VEF_UNDEF))
2125 	    eflags = st->eflags;
2126 
2127     Buf_Init(&buf);
2128     p = *pp + 1;
2129     while (*p != st->endc && *p != ':' && *p != '\0') {
2130 
2131 	/* XXX: This code is similar to the one in Var_Parse.
2132 	 * See if the code can be merged.
2133 	 * See also ApplyModifier_Match. */
2134 
2135 	/* Escaped delimiter or other special character */
2136 	if (*p == '\\') {
2137 	    char c = p[1];
2138 	    if (c == st->endc || c == ':' || c == '$' || c == '\\') {
2139 		Buf_AddByte(&buf, c);
2140 		p += 2;
2141 		continue;
2142 	    }
2143 	}
2144 
2145 	/* Nested variable expression */
2146 	if (*p == '$') {
2147 	    const char *nested_val;
2148 	    void *nested_val_freeIt;
2149 
2150 	    (void)Var_Parse(&p, st->ctxt, eflags,
2151 			    &nested_val, &nested_val_freeIt);
2152 	    /* TODO: handle errors */
2153 	    Buf_AddStr(&buf, nested_val);
2154 	    free(nested_val_freeIt);
2155 	    continue;
2156 	}
2157 
2158 	/* Ordinary text */
2159 	Buf_AddByte(&buf, *p);
2160 	p++;
2161     }
2162     *pp = p;
2163 
2164     ApplyModifiersState_Define(st);
2165 
2166     if (eflags & VARE_WANTRES) {
2167 	st->newVal = Buf_Destroy(&buf, FALSE);
2168     } else {
2169 	st->newVal = st->val;
2170 	Buf_Destroy(&buf, TRUE);
2171     }
2172     return AMR_OK;
2173 }
2174 
2175 /* :L */
2176 static ApplyModifierResult
2177 ApplyModifier_Literal(const char **pp, ApplyModifiersState *st)
2178 {
2179     ApplyModifiersState_Define(st);
2180     st->newVal = bmake_strdup(st->var->name);
2181     (*pp)++;
2182     return AMR_OK;
2183 }
2184 
2185 static Boolean
2186 TryParseTime(const char **pp, time_t *out_time)
2187 {
2188     char *end;
2189     unsigned long n;
2190 
2191     if (!ch_isdigit(**pp))
2192 	return FALSE;
2193 
2194     errno = 0;
2195     n = strtoul(*pp, &end, 10);
2196     if (n == ULONG_MAX && errno == ERANGE)
2197 	return FALSE;
2198 
2199     *pp = end;
2200     *out_time = (time_t)n;	/* ignore possible truncation for now */
2201     return TRUE;
2202 }
2203 
2204 /* :gmtime */
2205 static ApplyModifierResult
2206 ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st)
2207 {
2208     time_t utc;
2209 
2210     const char *mod = *pp;
2211     if (!ModMatchEq(mod, "gmtime", st->endc))
2212 	return AMR_UNKNOWN;
2213 
2214     if (mod[6] == '=') {
2215 	const char *arg = mod + 7;
2216 	if (!TryParseTime(&arg, &utc)) {
2217 	    Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 7);
2218 	    return AMR_CLEANUP;
2219 	}
2220 	*pp = arg;
2221     } else {
2222 	utc = 0;
2223 	*pp = mod + 6;
2224     }
2225     st->newVal = VarStrftime(st->val, TRUE, utc);
2226     return AMR_OK;
2227 }
2228 
2229 /* :localtime */
2230 static ApplyModifierResult
2231 ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st)
2232 {
2233     time_t utc;
2234 
2235     const char *mod = *pp;
2236     if (!ModMatchEq(mod, "localtime", st->endc))
2237 	return AMR_UNKNOWN;
2238 
2239     if (mod[9] == '=') {
2240 	const char *arg = mod + 10;
2241 	if (!TryParseTime(&arg, &utc)) {
2242 	    Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 10);
2243 	    return AMR_CLEANUP;
2244 	}
2245 	*pp = arg;
2246     } else {
2247 	utc = 0;
2248 	*pp = mod + 9;
2249     }
2250     st->newVal = VarStrftime(st->val, FALSE, utc);
2251     return AMR_OK;
2252 }
2253 
2254 /* :hash */
2255 static ApplyModifierResult
2256 ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
2257 {
2258     if (!ModMatch(*pp, "hash", st->endc))
2259 	return AMR_UNKNOWN;
2260 
2261     st->newVal = VarHash(st->val);
2262     *pp += 4;
2263     return AMR_OK;
2264 }
2265 
2266 /* :P */
2267 static ApplyModifierResult
2268 ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
2269 {
2270     GNode *gn;
2271     char *path;
2272 
2273     ApplyModifiersState_Define(st);
2274 
2275     gn = Targ_FindNode(st->var->name);
2276     if (gn == NULL || gn->type & OP_NOPATH) {
2277 	path = NULL;
2278     } else if (gn->path != NULL) {
2279 	path = bmake_strdup(gn->path);
2280     } else {
2281 	SearchPath *searchPath = Suff_FindPath(gn);
2282 	path = Dir_FindFile(st->var->name, searchPath);
2283     }
2284     if (path == NULL)
2285 	path = bmake_strdup(st->var->name);
2286     st->newVal = path;
2287 
2288     (*pp)++;
2289     return AMR_OK;
2290 }
2291 
2292 /* :!cmd! */
2293 static ApplyModifierResult
2294 ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st)
2295 {
2296     char *cmd;
2297     const char *errfmt;
2298     VarParseResult res;
2299 
2300     (*pp)++;
2301     res = ParseModifierPart(pp, '!', st->eflags, st,
2302 			    &cmd, NULL, NULL, NULL);
2303     if (res != VPR_OK)
2304 	return AMR_CLEANUP;
2305 
2306     errfmt = NULL;
2307     if (st->eflags & VARE_WANTRES)
2308 	st->newVal = Cmd_Exec(cmd, &errfmt);
2309     else
2310 	st->newVal = bmake_strdup("");
2311     free(cmd);
2312 
2313     if (errfmt != NULL)
2314 	Error(errfmt, st->val);	/* XXX: why still return AMR_OK? */
2315 
2316     ApplyModifiersState_Define(st);
2317     return AMR_OK;
2318 }
2319 
2320 /* The :range modifier generates an integer sequence as long as the words.
2321  * The :range=7 modifier generates an integer sequence from 1 to 7. */
2322 static ApplyModifierResult
2323 ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
2324 {
2325     size_t n;
2326     Buffer buf;
2327     size_t i;
2328 
2329     const char *mod = *pp;
2330     if (!ModMatchEq(mod, "range", st->endc))
2331 	return AMR_UNKNOWN;
2332 
2333     if (mod[5] == '=') {
2334 	const char *p = mod + 6;
2335 	if (!TryParseSize(&p, &n)) {
2336 	    Parse_Error(PARSE_FATAL, "Invalid number: %s\n", mod + 6);
2337 	    return AMR_CLEANUP;
2338 	}
2339 	*pp = p;
2340     } else {
2341 	n = 0;
2342 	*pp = mod + 5;
2343     }
2344 
2345     if (n == 0) {
2346 	Words words = Str_Words(st->val, FALSE);
2347 	n = words.len;
2348 	Words_Free(words);
2349     }
2350 
2351     Buf_Init(&buf);
2352 
2353     for (i = 0; i < n; i++) {
2354 	if (i != 0)
2355 	    Buf_AddByte(&buf, ' ');	/* XXX: st->sep, for consistency */
2356 	Buf_AddInt(&buf, 1 + (int)i);
2357     }
2358 
2359     st->newVal = Buf_Destroy(&buf, FALSE);
2360     return AMR_OK;
2361 }
2362 
2363 /* :Mpattern or :Npattern */
2364 static ApplyModifierResult
2365 ApplyModifier_Match(const char **pp, ApplyModifiersState *st)
2366 {
2367     const char *mod = *pp;
2368     Boolean copy = FALSE;	/* pattern should be, or has been, copied */
2369     Boolean needSubst = FALSE;
2370     const char *endpat;
2371     char *pattern;
2372     ModifyWordsCallback callback;
2373 
2374     /*
2375      * In the loop below, ignore ':' unless we are at (or back to) the
2376      * original brace level.
2377      * XXX: This will likely not work right if $() and ${} are intermixed.
2378      */
2379     /* XXX: This code is similar to the one in Var_Parse.
2380      * See if the code can be merged.
2381      * See also ApplyModifier_Defined. */
2382     int nest = 0;
2383     const char *p;
2384     for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) {
2385 	if (*p == '\\' &&
2386 	    (p[1] == ':' || p[1] == st->endc || p[1] == st->startc)) {
2387 	    if (!needSubst)
2388 		copy = TRUE;
2389 	    p++;
2390 	    continue;
2391 	}
2392 	if (*p == '$')
2393 	    needSubst = TRUE;
2394 	if (*p == '(' || *p == '{')
2395 	    nest++;
2396 	if (*p == ')' || *p == '}') {
2397 	    nest--;
2398 	    if (nest < 0)
2399 		break;
2400 	}
2401     }
2402     *pp = p;
2403     endpat = p;
2404 
2405     if (copy) {
2406 	char *dst;
2407 	const char *src;
2408 
2409 	/* Compress the \:'s out of the pattern. */
2410 	pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
2411 	dst = pattern;
2412 	src = mod + 1;
2413 	for (; src < endpat; src++, dst++) {
2414 	    if (src[0] == '\\' && src + 1 < endpat &&
2415 		/* XXX: st->startc is missing here; see above */
2416 		(src[1] == ':' || src[1] == st->endc))
2417 		src++;
2418 	    *dst = *src;
2419 	}
2420 	*dst = '\0';
2421 	endpat = dst;
2422     } else {
2423 	pattern = bmake_strsedup(mod + 1, endpat);
2424     }
2425 
2426     if (needSubst) {
2427 	/* pattern contains embedded '$', so use Var_Subst to expand it. */
2428 	char *old_pattern = pattern;
2429 	(void)Var_Subst(pattern, st->ctxt, st->eflags, &pattern);
2430 	/* TODO: handle errors */
2431 	free(old_pattern);
2432     }
2433 
2434     VAR_DEBUG3("Pattern[%s] for [%s] is [%s]\n",
2435 	       st->var->name, st->val, pattern);
2436 
2437     callback = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
2438     st->newVal = ModifyWords(st->val, callback, pattern,
2439 			     st->oneBigWord, st->sep);
2440     free(pattern);
2441     return AMR_OK;
2442 }
2443 
2444 /* :S,from,to, */
2445 static ApplyModifierResult
2446 ApplyModifier_Subst(const char **pp, ApplyModifiersState *st)
2447 {
2448     struct ModifyWord_SubstArgs args;
2449     char *lhs, *rhs;
2450     Boolean oneBigWord;
2451     VarParseResult res;
2452 
2453     char delim = (*pp)[1];
2454     if (delim == '\0') {
2455 	Error("Missing delimiter for :S modifier");
2456 	(*pp)++;
2457 	return AMR_CLEANUP;
2458     }
2459 
2460     *pp += 2;
2461 
2462     args.pflags = 0;
2463     args.matched = FALSE;
2464 
2465     /*
2466      * If pattern begins with '^', it is anchored to the
2467      * start of the word -- skip over it and flag pattern.
2468      */
2469     if (**pp == '^') {
2470 	args.pflags |= VARP_ANCHOR_START;
2471 	(*pp)++;
2472     }
2473 
2474     res = ParseModifierPart(pp, delim, st->eflags, st,
2475 			    &lhs, &args.lhsLen, &args.pflags, NULL);
2476     if (res != VPR_OK)
2477 	return AMR_CLEANUP;
2478     args.lhs = lhs;
2479 
2480     res = ParseModifierPart(pp, delim, st->eflags, st,
2481 			    &rhs, &args.rhsLen, NULL, &args);
2482     if (res != VPR_OK)
2483 	return AMR_CLEANUP;
2484     args.rhs = rhs;
2485 
2486     oneBigWord = st->oneBigWord;
2487     for (;; (*pp)++) {
2488 	switch (**pp) {
2489 	case 'g':
2490 	    args.pflags |= VARP_SUB_GLOBAL;
2491 	    continue;
2492 	case '1':
2493 	    args.pflags |= VARP_SUB_ONE;
2494 	    continue;
2495 	case 'W':
2496 	    oneBigWord = TRUE;
2497 	    continue;
2498 	}
2499 	break;
2500     }
2501 
2502     st->newVal = ModifyWords(st->val, ModifyWord_Subst, &args,
2503 			     oneBigWord, st->sep);
2504 
2505     free(lhs);
2506     free(rhs);
2507     return AMR_OK;
2508 }
2509 
2510 #ifndef NO_REGEX
2511 
2512 /* :C,from,to, */
2513 static ApplyModifierResult
2514 ApplyModifier_Regex(const char **pp, ApplyModifiersState *st)
2515 {
2516     char *re;
2517     struct ModifyWord_SubstRegexArgs args;
2518     Boolean oneBigWord;
2519     int error;
2520     VarParseResult res;
2521 
2522     char delim = (*pp)[1];
2523     if (delim == '\0') {
2524 	Error("Missing delimiter for :C modifier");
2525 	(*pp)++;
2526 	return AMR_CLEANUP;
2527     }
2528 
2529     *pp += 2;
2530 
2531     res = ParseModifierPart(pp, delim, st->eflags, st,
2532 			    &re, NULL, NULL, NULL);
2533     if (res != VPR_OK)
2534 	return AMR_CLEANUP;
2535 
2536     res = ParseModifierPart(pp, delim, st->eflags, st,
2537 			    &args.replace, NULL, NULL, NULL);
2538     if (args.replace == NULL) {
2539 	free(re);
2540 	return AMR_CLEANUP;
2541     }
2542 
2543     args.pflags = 0;
2544     args.matched = FALSE;
2545     oneBigWord = st->oneBigWord;
2546     for (;; (*pp)++) {
2547 	switch (**pp) {
2548 	case 'g':
2549 	    args.pflags |= VARP_SUB_GLOBAL;
2550 	    continue;
2551 	case '1':
2552 	    args.pflags |= VARP_SUB_ONE;
2553 	    continue;
2554 	case 'W':
2555 	    oneBigWord = TRUE;
2556 	    continue;
2557 	}
2558 	break;
2559     }
2560 
2561     error = regcomp(&args.re, re, REG_EXTENDED);
2562     free(re);
2563     if (error) {
2564 	VarREError(error, &args.re, "Regex compilation error");
2565 	free(args.replace);
2566 	return AMR_CLEANUP;
2567     }
2568 
2569     args.nsub = args.re.re_nsub + 1;
2570     if (args.nsub > 10)
2571 	args.nsub = 10;
2572     st->newVal = ModifyWords(st->val, ModifyWord_SubstRegex, &args,
2573 			     oneBigWord, st->sep);
2574     regfree(&args.re);
2575     free(args.replace);
2576     return AMR_OK;
2577 }
2578 #endif
2579 
2580 /* :Q, :q */
2581 static ApplyModifierResult
2582 ApplyModifier_Quote(const char **pp, ApplyModifiersState *st)
2583 {
2584     if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
2585 	st->newVal = VarQuote(st->val, **pp == 'q');
2586 	(*pp)++;
2587 	return AMR_OK;
2588     } else
2589 	return AMR_UNKNOWN;
2590 }
2591 
2592 static void
2593 ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
2594 {
2595     SepBuf_AddStr(buf, word);
2596 }
2597 
2598 /* :ts<separator> */
2599 static ApplyModifierResult
2600 ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
2601 {
2602     const char *sep = *pp + 2;
2603 
2604     /* ":ts<any><endc>" or ":ts<any>:" */
2605     if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
2606 	st->sep = sep[0];
2607 	*pp = sep + 1;
2608 	goto ok;
2609     }
2610 
2611     /* ":ts<endc>" or ":ts:" */
2612     if (sep[0] == st->endc || sep[0] == ':') {
2613 	st->sep = '\0';		/* no separator */
2614 	*pp = sep;
2615 	goto ok;
2616     }
2617 
2618     /* ":ts<unrecognised><unrecognised>". */
2619     if (sep[0] != '\\') {
2620 	(*pp)++;		/* just for backwards compatibility */
2621 	return AMR_BAD;
2622     }
2623 
2624     /* ":ts\n" */
2625     if (sep[1] == 'n') {
2626 	st->sep = '\n';
2627 	*pp = sep + 2;
2628 	goto ok;
2629     }
2630 
2631     /* ":ts\t" */
2632     if (sep[1] == 't') {
2633 	st->sep = '\t';
2634 	*pp = sep + 2;
2635 	goto ok;
2636     }
2637 
2638     /* ":ts\x40" or ":ts\100" */
2639     {
2640 	const char *p = sep + 1;
2641 	int base = 8;		/* assume octal */
2642 
2643 	if (sep[1] == 'x') {
2644 	    base = 16;
2645 	    p++;
2646 	} else if (!ch_isdigit(sep[1])) {
2647 	    (*pp)++;		/* just for backwards compatibility */
2648 	    return AMR_BAD;	/* ":ts<backslash><unrecognised>". */
2649 	}
2650 
2651 	if (!TryParseChar(&p, base, &st->sep)) {
2652 	    Parse_Error(PARSE_FATAL, "Invalid character number: %s\n", p);
2653 	    return AMR_CLEANUP;
2654 	}
2655 	if (*p != ':' && *p != st->endc) {
2656 	    (*pp)++;		/* just for backwards compatibility */
2657 	    return AMR_BAD;
2658 	}
2659 
2660 	*pp = p;
2661     }
2662 
2663 ok:
2664     st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL,
2665 			     st->oneBigWord, st->sep);
2666     return AMR_OK;
2667 }
2668 
2669 /* :tA, :tu, :tl, :ts<separator>, etc. */
2670 static ApplyModifierResult
2671 ApplyModifier_To(const char **pp, ApplyModifiersState *st)
2672 {
2673     const char *mod = *pp;
2674     assert(mod[0] == 't');
2675 
2676     if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') {
2677 	*pp = mod + 1;
2678 	return AMR_BAD;		/* Found ":t<endc>" or ":t:". */
2679     }
2680 
2681     if (mod[1] == 's')
2682 	return ApplyModifier_ToSep(pp, st);
2683 
2684     if (mod[2] != st->endc && mod[2] != ':') {
2685 	*pp = mod + 1;
2686 	return AMR_BAD;		/* Found ":t<unrecognised><unrecognised>". */
2687     }
2688 
2689     /* Check for two-character options: ":tu", ":tl" */
2690     if (mod[1] == 'A') {	/* absolute path */
2691 	st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL,
2692 				 st->oneBigWord, st->sep);
2693 	*pp = mod + 2;
2694 	return AMR_OK;
2695     }
2696 
2697     if (mod[1] == 'u') {	/* :tu */
2698 	size_t i;
2699 	size_t len = strlen(st->val);
2700 	st->newVal = bmake_malloc(len + 1);
2701 	for (i = 0; i < len + 1; i++)
2702 	    st->newVal[i] = ch_toupper(st->val[i]);
2703 	*pp = mod + 2;
2704 	return AMR_OK;
2705     }
2706 
2707     if (mod[1] == 'l') {	/* :tl */
2708 	size_t i;
2709 	size_t len = strlen(st->val);
2710 	st->newVal = bmake_malloc(len + 1);
2711 	for (i = 0; i < len + 1; i++)
2712 	    st->newVal[i] = ch_tolower(st->val[i]);
2713 	*pp = mod + 2;
2714 	return AMR_OK;
2715     }
2716 
2717     if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
2718 	st->oneBigWord = mod[1] == 'W';
2719 	st->newVal = st->val;
2720 	*pp = mod + 2;
2721 	return AMR_OK;
2722     }
2723 
2724     /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
2725     *pp = mod + 1;
2726     return AMR_BAD;
2727 }
2728 
2729 /* :[#], :[1], :[-1..1], etc. */
2730 static ApplyModifierResult
2731 ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
2732 {
2733     char *estr;
2734     int first, last;
2735     VarParseResult res;
2736     const char *p;
2737 
2738     (*pp)++;			/* skip the '[' */
2739     res = ParseModifierPart(pp, ']', st->eflags, st,
2740 			    &estr, NULL, NULL, NULL);
2741     if (res != VPR_OK)
2742 	return AMR_CLEANUP;
2743 
2744     /* now *pp points just after the closing ']' */
2745     if (**pp != ':' && **pp != st->endc)
2746 	goto bad_modifier;	/* Found junk after ']' */
2747 
2748     if (estr[0] == '\0')
2749 	goto bad_modifier;	/* empty square brackets in ":[]". */
2750 
2751     if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
2752 	if (st->oneBigWord) {
2753 	    st->newVal = bmake_strdup("1");
2754 	} else {
2755 	    Buffer buf;
2756 
2757 	    Words words = Str_Words(st->val, FALSE);
2758 	    size_t ac = words.len;
2759 	    Words_Free(words);
2760 
2761 	    Buf_InitSize(&buf, 4);	/* 3 digits + '\0' is usually enough */
2762 	    Buf_AddInt(&buf, (int)ac);
2763 	    st->newVal = Buf_Destroy(&buf, FALSE);
2764 	}
2765 	goto ok;
2766     }
2767 
2768     if (estr[0] == '*' && estr[1] == '\0') {
2769 	/* Found ":[*]" */
2770 	st->oneBigWord = TRUE;
2771 	st->newVal = st->val;
2772 	goto ok;
2773     }
2774 
2775     if (estr[0] == '@' && estr[1] == '\0') {
2776 	/* Found ":[@]" */
2777 	st->oneBigWord = FALSE;
2778 	st->newVal = st->val;
2779 	goto ok;
2780     }
2781 
2782     /*
2783      * We expect estr to contain a single integer for :[N], or two integers
2784      * separated by ".." for :[start..end].
2785      */
2786     p = estr;
2787     if (!TryParseIntBase0(&p, &first))
2788 	goto bad_modifier;	/* Found junk instead of a number */
2789 
2790     if (p[0] == '\0') {	/* Found only one integer in :[N] */
2791 	last = first;
2792     } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') {
2793 	/* Expecting another integer after ".." */
2794 	p += 2;
2795 	if (!TryParseIntBase0(&p, &last) || *p != '\0')
2796 	    goto bad_modifier;	/* Found junk after ".." */
2797     } else
2798 	goto bad_modifier;	/* Found junk instead of ".." */
2799 
2800     /*
2801      * Now first and last are properly filled in, but we still have to check
2802      * for 0 as a special case.
2803      */
2804     if (first == 0 && last == 0) {
2805 	/* ":[0]" or perhaps ":[0..0]" */
2806 	st->oneBigWord = TRUE;
2807 	st->newVal = st->val;
2808 	goto ok;
2809     }
2810 
2811     /* ":[0..N]" or ":[N..0]" */
2812     if (first == 0 || last == 0)
2813 	goto bad_modifier;
2814 
2815     /* Normal case: select the words described by first and last. */
2816     st->newVal = VarSelectWords(st->sep, st->oneBigWord, st->val, first, last);
2817 
2818 ok:
2819     free(estr);
2820     return AMR_OK;
2821 
2822 bad_modifier:
2823     free(estr);
2824     return AMR_BAD;
2825 }
2826 
2827 static int
2828 str_cmp_asc(const void *a, const void *b)
2829 {
2830     return strcmp(*(const char * const *)a, *(const char * const *)b);
2831 }
2832 
2833 static int
2834 str_cmp_desc(const void *a, const void *b)
2835 {
2836     return strcmp(*(const char * const *)b, *(const char * const *)a);
2837 }
2838 
2839 /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
2840 static ApplyModifierResult
2841 ApplyModifier_Order(const char **pp, ApplyModifiersState *st)
2842 {
2843     const char *mod = (*pp)++;	/* skip past the 'O' in any case */
2844 
2845     Words words = Str_Words(st->val, FALSE);
2846 
2847     if (mod[1] == st->endc || mod[1] == ':') {
2848 	/* :O sorts ascending */
2849 	qsort(words.words, words.len, sizeof words.words[0], str_cmp_asc);
2850 
2851     } else if ((mod[1] == 'r' || mod[1] == 'x') &&
2852 	       (mod[2] == st->endc || mod[2] == ':')) {
2853 	(*pp)++;
2854 
2855 	if (mod[1] == 'r') {
2856 	    /* :Or sorts descending */
2857 	    qsort(words.words, words.len, sizeof words.words[0], str_cmp_desc);
2858 
2859 	} else {
2860 	    /* :Ox shuffles
2861 	     *
2862 	     * We will use [ac..2] range for mod factors. This will produce
2863 	     * random numbers in [(ac-1)..0] interval, and minimal
2864 	     * reasonable value for mod factor is 2 (the mod 1 will produce
2865 	     * 0 with probability 1).
2866 	     */
2867 	    size_t i;
2868 	    for (i = words.len - 1; i > 0; i--) {
2869 		size_t rndidx = (size_t)random() % (i + 1);
2870 		char *t = words.words[i];
2871 		words.words[i] = words.words[rndidx];
2872 		words.words[rndidx] = t;
2873 	    }
2874 	}
2875     } else {
2876 	Words_Free(words);
2877 	return AMR_BAD;
2878     }
2879 
2880     st->newVal = Words_JoinFree(words);
2881     return AMR_OK;
2882 }
2883 
2884 /* :? then : else */
2885 static ApplyModifierResult
2886 ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
2887 {
2888     char *then_expr, *else_expr;
2889     VarParseResult res;
2890 
2891     Boolean value = FALSE;
2892     VarEvalFlags then_eflags = VARE_NONE;
2893     VarEvalFlags else_eflags = VARE_NONE;
2894 
2895     int cond_rc = COND_PARSE;	/* anything other than COND_INVALID */
2896     if (st->eflags & VARE_WANTRES) {
2897 	cond_rc = Cond_EvalCondition(st->var->name, &value);
2898 	if (cond_rc != COND_INVALID && value)
2899 	    then_eflags = st->eflags;
2900 	if (cond_rc != COND_INVALID && !value)
2901 	    else_eflags = st->eflags;
2902     }
2903 
2904     (*pp)++;			/* skip past the '?' */
2905     res = ParseModifierPart(pp, ':', then_eflags, st,
2906 			    &then_expr, NULL, NULL, NULL);
2907     if (res != VPR_OK)
2908 	return AMR_CLEANUP;
2909 
2910     res = ParseModifierPart(pp, st->endc, else_eflags, st,
2911 			    &else_expr, NULL, NULL, NULL);
2912     if (res != VPR_OK)
2913 	return AMR_CLEANUP;
2914 
2915     (*pp)--;
2916     if (cond_rc == COND_INVALID) {
2917 	Error("Bad conditional expression `%s' in %s?%s:%s",
2918 	      st->var->name, st->var->name, then_expr, else_expr);
2919 	return AMR_CLEANUP;
2920     }
2921 
2922     if (value) {
2923 	st->newVal = then_expr;
2924 	free(else_expr);
2925     } else {
2926 	st->newVal = else_expr;
2927 	free(then_expr);
2928     }
2929     ApplyModifiersState_Define(st);
2930     return AMR_OK;
2931 }
2932 
2933 /*
2934  * The ::= modifiers actually assign a value to the variable.
2935  * Their main purpose is in supporting modifiers of .for loop
2936  * iterators and other obscure uses.  They always expand to
2937  * nothing.  In a target rule that would otherwise expand to an
2938  * empty line they can be preceded with @: to keep make happy.
2939  * Eg.
2940  *
2941  * foo:	.USE
2942  * .for i in ${.TARGET} ${.TARGET:R}.gz
2943  *	@: ${t::=$i}
2944  *	@echo blah ${t:T}
2945  * .endfor
2946  *
2947  *	  ::=<str>	Assigns <str> as the new value of variable.
2948  *	  ::?=<str>	Assigns <str> as value of variable if
2949  *			it was not already set.
2950  *	  ::+=<str>	Appends <str> to variable.
2951  *	  ::!=<cmd>	Assigns output of <cmd> as the new value of
2952  *			variable.
2953  */
2954 static ApplyModifierResult
2955 ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
2956 {
2957     GNode *v_ctxt;
2958     char delim;
2959     char *val;
2960     VarParseResult res;
2961 
2962     const char *mod = *pp;
2963     const char *op = mod + 1;
2964 
2965     if (op[0] == '=')
2966 	goto ok;
2967     if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=')
2968 	goto ok;
2969     return AMR_UNKNOWN;		/* "::<unrecognised>" */
2970 ok:
2971 
2972     if (st->var->name[0] == '\0') {
2973 	*pp = mod + 1;
2974 	return AMR_BAD;
2975     }
2976 
2977     v_ctxt = st->ctxt;		/* context where v belongs */
2978     if (!(st->exprFlags & VEF_UNDEF) && st->ctxt != VAR_GLOBAL) {
2979 	Var *gv = VarFind(st->var->name, st->ctxt, FALSE);
2980 	if (gv == NULL)
2981 	    v_ctxt = VAR_GLOBAL;
2982 	else
2983 	    VarFreeEnv(gv, TRUE);
2984     }
2985 
2986     switch (op[0]) {
2987     case '+':
2988     case '?':
2989     case '!':
2990 	*pp = mod + 3;
2991 	break;
2992     default:
2993 	*pp = mod + 2;
2994 	break;
2995     }
2996 
2997     delim = st->startc == '(' ? ')' : '}';
2998     res = ParseModifierPart(pp, delim, st->eflags, st, &val, NULL, NULL, NULL);
2999     if (res != VPR_OK)
3000 	return AMR_CLEANUP;
3001 
3002     (*pp)--;
3003 
3004     if (st->eflags & VARE_WANTRES) {
3005 	switch (op[0]) {
3006 	case '+':
3007 	    Var_Append(st->var->name, val, v_ctxt);
3008 	    break;
3009 	case '!': {
3010 	    const char *errfmt;
3011 	    char *cmd_output = Cmd_Exec(val, &errfmt);
3012 	    if (errfmt)
3013 		Error(errfmt, val);
3014 	    else
3015 		Var_Set(st->var->name, cmd_output, v_ctxt);
3016 	    free(cmd_output);
3017 	    break;
3018 	}
3019 	case '?':
3020 	    if (!(st->exprFlags & VEF_UNDEF))
3021 		break;
3022 	    /* FALLTHROUGH */
3023 	default:
3024 	    Var_Set(st->var->name, val, v_ctxt);
3025 	    break;
3026 	}
3027     }
3028     free(val);
3029     st->newVal = bmake_strdup("");
3030     return AMR_OK;
3031 }
3032 
3033 /* :_=...
3034  * remember current value */
3035 static ApplyModifierResult
3036 ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
3037 {
3038     const char *mod = *pp;
3039     if (!ModMatchEq(mod, "_", st->endc))
3040 	return AMR_UNKNOWN;
3041 
3042     if (mod[1] == '=') {
3043 	size_t n = strcspn(mod + 2, ":)}");
3044 	char *name = bmake_strldup(mod + 2, n);
3045 	Var_Set(name, st->val, st->ctxt);
3046 	free(name);
3047 	*pp = mod + 2 + n;
3048     } else {
3049 	Var_Set("_", st->val, st->ctxt);
3050 	*pp = mod + 1;
3051     }
3052     st->newVal = st->val;
3053     return AMR_OK;
3054 }
3055 
3056 /* Apply the given function to each word of the variable value,
3057  * for a single-letter modifier such as :H, :T. */
3058 static ApplyModifierResult
3059 ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
3060 		       ModifyWordsCallback modifyWord)
3061 {
3062     char delim = (*pp)[1];
3063     if (delim != st->endc && delim != ':')
3064 	return AMR_UNKNOWN;
3065 
3066     st->newVal = ModifyWords(st->val, modifyWord, NULL,
3067 			     st->oneBigWord, st->sep);
3068     (*pp)++;
3069     return AMR_OK;
3070 }
3071 
3072 static ApplyModifierResult
3073 ApplyModifier_Unique(const char **pp, ApplyModifiersState *st)
3074 {
3075     if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
3076 	st->newVal = VarUniq(st->val);
3077 	(*pp)++;
3078 	return AMR_OK;
3079     } else
3080 	return AMR_UNKNOWN;
3081 }
3082 
3083 #ifdef SYSVVARSUB
3084 /* :from=to */
3085 static ApplyModifierResult
3086 ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
3087 {
3088     char *lhs, *rhs;
3089     VarParseResult res;
3090 
3091     const char *mod = *pp;
3092     Boolean eqFound = FALSE;
3093 
3094     /*
3095      * First we make a pass through the string trying to verify it is a
3096      * SysV-make-style translation. It must be: <lhs>=<rhs>
3097      */
3098     int depth = 1;
3099     const char *p = mod;
3100     while (*p != '\0' && depth > 0) {
3101 	if (*p == '=') {	/* XXX: should also test depth == 1 */
3102 	    eqFound = TRUE;
3103 	    /* continue looking for st->endc */
3104 	} else if (*p == st->endc)
3105 	    depth--;
3106 	else if (*p == st->startc)
3107 	    depth++;
3108 	if (depth > 0)
3109 	    p++;
3110     }
3111     if (*p != st->endc || !eqFound)
3112 	return AMR_UNKNOWN;
3113 
3114     *pp = mod;
3115     res = ParseModifierPart(pp, '=', st->eflags, st,
3116 			    &lhs, NULL, NULL, NULL);
3117     if (res != VPR_OK)
3118 	return AMR_CLEANUP;
3119 
3120     /* The SysV modifier lasts until the end of the variable expression. */
3121     res = ParseModifierPart(pp, st->endc, st->eflags, st,
3122 			    &rhs, NULL, NULL, NULL);
3123     if (res != VPR_OK)
3124 	return AMR_CLEANUP;
3125 
3126     (*pp)--;
3127     if (lhs[0] == '\0' && st->val[0] == '\0') {
3128 	st->newVal = st->val;	/* special case */
3129     } else {
3130 	struct ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs};
3131 	st->newVal = ModifyWords(st->val, ModifyWord_SYSVSubst, &args,
3132 				 st->oneBigWord, st->sep);
3133     }
3134     free(lhs);
3135     free(rhs);
3136     return AMR_OK;
3137 }
3138 #endif
3139 
3140 #ifdef SUNSHCMD
3141 /* :sh */
3142 static ApplyModifierResult
3143 ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st)
3144 {
3145     const char *p = *pp;
3146     if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) {
3147 	if (st->eflags & VARE_WANTRES) {
3148 	    const char *errfmt;
3149 	    st->newVal = Cmd_Exec(st->val, &errfmt);
3150 	    if (errfmt)
3151 		Error(errfmt, st->val);
3152 	} else
3153 	    st->newVal = bmake_strdup("");
3154 	*pp = p + 2;
3155 	return AMR_OK;
3156     } else
3157 	return AMR_UNKNOWN;
3158 }
3159 #endif
3160 
3161 static void
3162 LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc)
3163 {
3164     char eflags_str[VarEvalFlags_ToStringSize];
3165     char vflags_str[VarFlags_ToStringSize];
3166     char exprflags_str[VarExprFlags_ToStringSize];
3167     Boolean is_single_char = mod[0] != '\0' &&
3168 			     (mod[1] == endc || mod[1] == ':');
3169 
3170     /* At this point, only the first character of the modifier can
3171      * be used since the end of the modifier is not yet known. */
3172     debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n",
3173 		 st->var->name, mod[0], is_single_char ? "" : "...", st->val,
3174 		 Enum_FlagsToString(eflags_str, sizeof eflags_str,
3175 				    st->eflags, VarEvalFlags_ToStringSpecs),
3176 		 Enum_FlagsToString(vflags_str, sizeof vflags_str,
3177 				    st->var->flags, VarFlags_ToStringSpecs),
3178 		 Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
3179 				    st->exprFlags,
3180 				    VarExprFlags_ToStringSpecs));
3181 }
3182 
3183 static void
3184 LogAfterApply(ApplyModifiersState *st, const char *p, const char *mod)
3185 {
3186     char eflags_str[VarEvalFlags_ToStringSize];
3187     char vflags_str[VarFlags_ToStringSize];
3188     char exprflags_str[VarExprFlags_ToStringSize];
3189     const char *quot = st->newVal == var_Error ? "" : "\"";
3190     const char *newVal = st->newVal == var_Error ? "error" : st->newVal;
3191 
3192     debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n",
3193 		 st->var->name, (int)(p - mod), mod, quot, newVal, quot,
3194 		 Enum_FlagsToString(eflags_str, sizeof eflags_str,
3195 				    st->eflags, VarEvalFlags_ToStringSpecs),
3196 		 Enum_FlagsToString(vflags_str, sizeof vflags_str,
3197 				    st->var->flags, VarFlags_ToStringSpecs),
3198 		 Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
3199 				    st->exprFlags,
3200 				    VarExprFlags_ToStringSpecs));
3201 }
3202 
3203 static ApplyModifierResult
3204 ApplyModifier(const char **pp, ApplyModifiersState *st)
3205 {
3206     switch (**pp) {
3207     case ':':
3208 	return ApplyModifier_Assign(pp, st);
3209     case '@':
3210 	return ApplyModifier_Loop(pp, st);
3211     case '_':
3212 	return ApplyModifier_Remember(pp, st);
3213     case 'D':
3214     case 'U':
3215 	return ApplyModifier_Defined(pp, st);
3216     case 'L':
3217 	return ApplyModifier_Literal(pp, st);
3218     case 'P':
3219 	return ApplyModifier_Path(pp, st);
3220     case '!':
3221 	return ApplyModifier_ShellCommand(pp, st);
3222     case '[':
3223 	return ApplyModifier_Words(pp, st);
3224     case 'g':
3225 	return ApplyModifier_Gmtime(pp, st);
3226     case 'h':
3227 	return ApplyModifier_Hash(pp, st);
3228     case 'l':
3229 	return ApplyModifier_Localtime(pp, st);
3230     case 't':
3231 	return ApplyModifier_To(pp, st);
3232     case 'N':
3233     case 'M':
3234 	return ApplyModifier_Match(pp, st);
3235     case 'S':
3236 	return ApplyModifier_Subst(pp, st);
3237     case '?':
3238 	return ApplyModifier_IfElse(pp, st);
3239 #ifndef NO_REGEX
3240     case 'C':
3241 	return ApplyModifier_Regex(pp, st);
3242 #endif
3243     case 'q':
3244     case 'Q':
3245 	return ApplyModifier_Quote(pp, st);
3246     case 'T':
3247 	return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail);
3248     case 'H':
3249 	return ApplyModifier_WordFunc(pp, st, ModifyWord_Head);
3250     case 'E':
3251 	return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix);
3252     case 'R':
3253 	return ApplyModifier_WordFunc(pp, st, ModifyWord_Root);
3254     case 'r':
3255 	return ApplyModifier_Range(pp, st);
3256     case 'O':
3257 	return ApplyModifier_Order(pp, st);
3258     case 'u':
3259 	return ApplyModifier_Unique(pp, st);
3260 #ifdef SUNSHCMD
3261     case 's':
3262 	return ApplyModifier_SunShell(pp, st);
3263 #endif
3264     default:
3265 	return AMR_UNKNOWN;
3266     }
3267 }
3268 
3269 static char *ApplyModifiers(const char **, char *, char, char, Var *,
3270 			    VarExprFlags *, GNode *, VarEvalFlags, void **);
3271 
3272 typedef enum ApplyModifiersIndirectResult {
3273     AMIR_CONTINUE,
3274     AMIR_APPLY_MODS,
3275     AMIR_OUT
3276 } ApplyModifiersIndirectResult;
3277 
3278 /* While expanding a variable expression, expand and apply indirect
3279  * modifiers such as in ${VAR:${M_indirect}}. */
3280 static ApplyModifiersIndirectResult
3281 ApplyModifiersIndirect(
3282 	ApplyModifiersState *const st,
3283 	const char **const inout_p,
3284 	void **const inout_freeIt
3285 ) {
3286     const char *p = *inout_p;
3287     const char *mods;
3288     void *mods_freeIt;
3289 
3290     (void)Var_Parse(&p, st->ctxt, st->eflags, &mods, &mods_freeIt);
3291     /* TODO: handle errors */
3292 
3293     /*
3294      * If we have not parsed up to st->endc or ':', we are not
3295      * interested.  This means the expression ${VAR:${M_1}${M_2}}
3296      * is not accepted, but ${VAR:${M_1}:${M_2}} is.
3297      */
3298     if (mods[0] != '\0' && *p != '\0' && *p != ':' && *p != st->endc) {
3299 	if (opts.lint)
3300 	    Parse_Error(PARSE_FATAL,
3301 			"Missing delimiter ':' after indirect modifier \"%.*s\"",
3302 			(int)(p - *inout_p), *inout_p);
3303 
3304 	free(mods_freeIt);
3305 	/* XXX: apply_mods doesn't sound like "not interested". */
3306 	/* XXX: Why is the indirect modifier parsed once more by
3307 	 * apply_mods?  If any, p should be advanced to nested_p. */
3308 	return AMIR_APPLY_MODS;
3309     }
3310 
3311     VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n",
3312 	       mods, (int)(p - *inout_p), *inout_p);
3313 
3314     if (mods[0] != '\0') {
3315 	const char *rval_pp = mods;
3316 	st->val = ApplyModifiers(&rval_pp, st->val, '\0', '\0', st->var,
3317 				 &st->exprFlags, st->ctxt, st->eflags,
3318 				 inout_freeIt);
3319 	if (st->val == var_Error || st->val == varUndefined ||
3320 	    *rval_pp != '\0') {
3321 	    free(mods_freeIt);
3322 	    *inout_p = p;
3323 	    return AMIR_OUT;	/* error already reported */
3324 	}
3325     }
3326     free(mods_freeIt);
3327 
3328     if (*p == ':')
3329 	p++;
3330     else if (*p == '\0' && st->endc != '\0') {
3331 	Error("Unclosed variable specification after complex "
3332 	      "modifier (expecting '%c') for %s", st->endc, st->var->name);
3333 	*inout_p = p;
3334 	return AMIR_OUT;
3335     }
3336 
3337     *inout_p = p;
3338     return AMIR_CONTINUE;
3339 }
3340 
3341 /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
3342 static char *
3343 ApplyModifiers(
3344     const char **const pp,	/* the parsing position, updated upon return */
3345     char *const val,		/* the current value of the expression */
3346     char const startc,		/* '(' or '{', or '\0' for indirect modifiers */
3347     char const endc,		/* ')' or '}', or '\0' for indirect modifiers */
3348     Var *const v,
3349     VarExprFlags *const exprFlags,
3350     GNode *const ctxt,		/* for looking up and modifying variables */
3351     VarEvalFlags const eflags,
3352     void **const inout_freeIt	/* free this after using the return value */
3353 ) {
3354     ApplyModifiersState st = {
3355 	startc, endc, v, ctxt, eflags,
3356 	val,			/* .val */
3357 	var_Error,		/* .newVal */
3358 	' ',			/* .sep */
3359 	FALSE,			/* .oneBigWord */
3360 	*exprFlags		/* .exprFlags */
3361     };
3362     const char *p;
3363     const char *mod;
3364     ApplyModifierResult res;
3365 
3366     assert(startc == '(' || startc == '{' || startc == '\0');
3367     assert(endc == ')' || endc == '}' || endc == '\0');
3368     assert(val != NULL);
3369 
3370     p = *pp;
3371 
3372     if (*p == '\0' && endc != '\0') {
3373 	Error("Unclosed variable expression (expecting '%c') for \"%s\"",
3374 	      st.endc, st.var->name);
3375 	goto cleanup;
3376     }
3377 
3378     while (*p != '\0' && *p != endc) {
3379 
3380 	if (*p == '$') {
3381 	    ApplyModifiersIndirectResult amir;
3382 	    amir = ApplyModifiersIndirect(&st, &p, inout_freeIt);
3383 	    if (amir == AMIR_CONTINUE)
3384 		continue;
3385 	    if (amir == AMIR_OUT)
3386 	        goto out;
3387 	}
3388 	st.newVal = var_Error;	/* default value, in case of errors */
3389 	mod = p;
3390 
3391 	if (DEBUG(VAR))
3392 	    LogBeforeApply(&st, mod, endc);
3393 
3394 	res = ApplyModifier(&p, &st);
3395 
3396 #ifdef SYSVVARSUB
3397 	if (res == AMR_UNKNOWN) {
3398 	    assert(p == mod);
3399 	    res = ApplyModifier_SysV(&p, &st);
3400 	}
3401 #endif
3402 
3403 	if (res == AMR_UNKNOWN) {
3404 	    Error("Unknown modifier '%c'", *mod);
3405 	    /* Guess the end of the current modifier.
3406 	     * XXX: Skipping the rest of the modifier hides errors and leads
3407 	     * to wrong results.  Parsing should rather stop here. */
3408 	    for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++)
3409 		continue;
3410 	    st.newVal = var_Error;
3411 	}
3412 	if (res == AMR_CLEANUP)
3413 	    goto cleanup;
3414 	if (res == AMR_BAD)
3415 	    goto bad_modifier;
3416 
3417 	if (DEBUG(VAR))
3418 	    LogAfterApply(&st, p, mod);
3419 
3420 	if (st.newVal != st.val) {
3421 	    if (*inout_freeIt != NULL) {
3422 		free(st.val);
3423 		*inout_freeIt = NULL;
3424 	    }
3425 	    st.val = st.newVal;
3426 	    if (st.val != var_Error && st.val != varUndefined)
3427 		*inout_freeIt = st.val;
3428 	}
3429 	if (*p == '\0' && st.endc != '\0') {
3430 	    Error("Unclosed variable specification (expecting '%c') "
3431 		  "for \"%s\" (value \"%s\") modifier %c",
3432 		  st.endc, st.var->name, st.val, *mod);
3433 	} else if (*p == ':') {
3434 	    p++;
3435 	} else if (opts.lint && *p != '\0' && *p != endc) {
3436 	    Parse_Error(PARSE_FATAL,
3437 			"Missing delimiter ':' after modifier \"%.*s\"",
3438 			(int)(p - mod), mod);
3439 	    /* TODO: propagate parse error to the enclosing expression */
3440 	}
3441     }
3442 out:
3443     *pp = p;
3444     assert(st.val != NULL);	/* Use var_Error or varUndefined instead. */
3445     *exprFlags = st.exprFlags;
3446     return st.val;
3447 
3448 bad_modifier:
3449     /* XXX: The modifier end is only guessed. */
3450     Error("Bad modifier `:%.*s' for %s",
3451 	  (int)strcspn(mod, ":)}"), mod, st.var->name);
3452 
3453 cleanup:
3454     *pp = p;
3455     free(*inout_freeIt);
3456     *inout_freeIt = NULL;
3457     *exprFlags = st.exprFlags;
3458     return var_Error;
3459 }
3460 
3461 /* Only four of the local variables are treated specially as they are the
3462  * only four that will be set when dynamic sources are expanded. */
3463 static Boolean
3464 VarnameIsDynamic(const char *name, size_t len)
3465 {
3466     if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
3467 	switch (name[0]) {
3468 	case '@':
3469 	case '%':
3470 	case '*':
3471 	case '!':
3472 	    return TRUE;
3473 	}
3474 	return FALSE;
3475     }
3476 
3477     if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
3478 	return strcmp(name, ".TARGET") == 0 ||
3479 	       strcmp(name, ".ARCHIVE") == 0 ||
3480 	       strcmp(name, ".PREFIX") == 0 ||
3481 	       strcmp(name, ".MEMBER") == 0;
3482     }
3483 
3484     return FALSE;
3485 }
3486 
3487 static const char *
3488 UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags)
3489 {
3490     if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) {
3491 	/*
3492 	 * If substituting a local variable in a non-local context,
3493 	 * assume it's for dynamic source stuff. We have to handle
3494 	 * this specially and return the longhand for the variable
3495 	 * with the dollar sign escaped so it makes it back to the
3496 	 * caller. Only four of the local variables are treated
3497 	 * specially as they are the only four that will be set
3498 	 * when dynamic sources are expanded.
3499 	 */
3500 	switch (varname) {
3501 	case '@':
3502 	    return "$(.TARGET)";
3503 	case '%':
3504 	    return "$(.MEMBER)";
3505 	case '*':
3506 	    return "$(.PREFIX)";
3507 	case '!':
3508 	    return "$(.ARCHIVE)";
3509 	}
3510     }
3511     return eflags & VARE_UNDEFERR ? var_Error : varUndefined;
3512 }
3513 
3514 /* Parse a variable name, until the end character or a colon, whichever
3515  * comes first. */
3516 static char *
3517 ParseVarname(const char **pp, char startc, char endc,
3518 	     GNode *ctxt, VarEvalFlags eflags,
3519 	     size_t *out_varname_len)
3520 {
3521     Buffer buf;
3522     const char *p = *pp;
3523     int depth = 1;
3524 
3525     Buf_Init(&buf);
3526 
3527     while (*p != '\0') {
3528 	/* Track depth so we can spot parse errors. */
3529 	if (*p == startc)
3530 	    depth++;
3531 	if (*p == endc) {
3532 	    if (--depth == 0)
3533 		break;
3534 	}
3535 	if (*p == ':' && depth == 1)
3536 	    break;
3537 
3538 	/* A variable inside a variable, expand. */
3539 	if (*p == '$') {
3540 	    const char *nested_val;
3541 	    void *nested_val_freeIt;
3542 	    (void)Var_Parse(&p, ctxt, eflags, &nested_val, &nested_val_freeIt);
3543 	    /* TODO: handle errors */
3544 	    Buf_AddStr(&buf, nested_val);
3545 	    free(nested_val_freeIt);
3546 	} else {
3547 	    Buf_AddByte(&buf, *p);
3548 	    p++;
3549 	}
3550     }
3551     *pp = p;
3552     *out_varname_len = Buf_Len(&buf);
3553     return Buf_Destroy(&buf, FALSE);
3554 }
3555 
3556 static VarParseResult
3557 ValidShortVarname(char varname, const char *start)
3558 {
3559     switch (varname) {
3560     case '\0':
3561     case ')':
3562     case '}':
3563     case ':':
3564     case '$':
3565 	break;			/* and continue below */
3566     default:
3567 	return VPR_OK;
3568     }
3569 
3570     if (!opts.lint)
3571 	return VPR_PARSE_SILENT;
3572 
3573     if (varname == '$')
3574 	Parse_Error(PARSE_FATAL,
3575 		    "To escape a dollar, use \\$, not $$, at \"%s\"", start);
3576     else if (varname == '\0')
3577 	Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
3578     else
3579 	Parse_Error(PARSE_FATAL,
3580 		    "Invalid variable name '%c', at \"%s\"", varname, start);
3581 
3582     return VPR_PARSE_MSG;
3583 }
3584 
3585 /* Parse a single-character variable name such as $V or $@.
3586  * Return whether to continue parsing. */
3587 static Boolean
3588 ParseVarnameShort(char startc, const char **pp, GNode *ctxt,
3589 		  VarEvalFlags eflags,
3590 		  VarParseResult *out_FALSE_res, const char **out_FALSE_val,
3591 		  Var **out_TRUE_var)
3592 {
3593     char name[2];
3594     Var *v;
3595     VarParseResult vpr;
3596 
3597     /*
3598      * If it's not bounded by braces of some sort, life is much simpler.
3599      * We just need to check for the first character and return the
3600      * value if it exists.
3601      */
3602 
3603     vpr = ValidShortVarname(startc, *pp);
3604     if (vpr != VPR_OK) {
3605 	(*pp)++;
3606 	*out_FALSE_val = var_Error;
3607 	*out_FALSE_res = vpr;
3608 	return FALSE;
3609     }
3610 
3611     name[0] = startc;
3612     name[1] = '\0';
3613     v = VarFind(name, ctxt, TRUE);
3614     if (v == NULL) {
3615 	*pp += 2;
3616 
3617 	*out_FALSE_val = UndefinedShortVarValue(startc, ctxt, eflags);
3618 	if (opts.lint && *out_FALSE_val == var_Error) {
3619 	    Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", name);
3620 	    *out_FALSE_res = VPR_UNDEF_MSG;
3621 	    return FALSE;
3622 	}
3623 	*out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF_SILENT : VPR_OK;
3624 	return FALSE;
3625     }
3626 
3627     *out_TRUE_var = v;
3628     return TRUE;
3629 }
3630 
3631 /* Find variables like @F or <D. */
3632 static Var *
3633 FindLocalLegacyVar(const char *varname, size_t namelen, GNode *ctxt,
3634 		   const char **out_extraModifiers)
3635 {
3636     /* Only resolve these variables if ctxt is a "real" target. */
3637     if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL)
3638 	return NULL;
3639 
3640     if (namelen != 2)
3641 	return NULL;
3642     if (varname[1] != 'F' && varname[1] != 'D')
3643 	return NULL;
3644     if (strchr("@%?*!<>", varname[0]) == NULL)
3645 	return NULL;
3646 
3647     {
3648 	char name[] = { varname[0], '\0' };
3649 	Var *v = VarFind(name, ctxt, FALSE);
3650 
3651 	if (v != NULL) {
3652 	    if (varname[1] == 'D') {
3653 		*out_extraModifiers = "H:";
3654 	    } else { /* F */
3655 		*out_extraModifiers = "T:";
3656 	    }
3657 	}
3658 	return v;
3659     }
3660 }
3661 
3662 static VarParseResult
3663 EvalUndefined(Boolean dynamic, const char *start, const char *p, char *varname,
3664 	      VarEvalFlags eflags,
3665 	      void **out_freeIt, const char **out_val)
3666 {
3667     if (dynamic) {
3668 	char *pstr = bmake_strsedup(start, p);
3669 	free(varname);
3670 	*out_freeIt = pstr;
3671 	*out_val = pstr;
3672 	return VPR_OK;
3673     }
3674 
3675     if ((eflags & VARE_UNDEFERR) && opts.lint) {
3676 	Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", varname);
3677 	free(varname);
3678 	*out_val = var_Error;
3679 	return VPR_UNDEF_MSG;
3680     }
3681 
3682     if (eflags & VARE_UNDEFERR) {
3683 	free(varname);
3684 	*out_val = var_Error;
3685 	return VPR_UNDEF_SILENT;
3686     }
3687 
3688     free(varname);
3689     *out_val = varUndefined;
3690     return VPR_OK;
3691 }
3692 
3693 /* Parse a long variable name enclosed in braces or parentheses such as $(VAR)
3694  * or ${VAR}, up to the closing brace or parenthesis, or in the case of
3695  * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
3696  * Return whether to continue parsing. */
3697 static Boolean
3698 ParseVarnameLong(
3699 	const char *p,
3700 	char startc,
3701 	GNode *ctxt,
3702 	VarEvalFlags eflags,
3703 
3704 	const char **out_FALSE_pp,
3705 	VarParseResult *out_FALSE_res,
3706 	const char **out_FALSE_val,
3707 	void **out_FALSE_freeIt,
3708 
3709 	char *out_TRUE_endc,
3710 	const char **out_TRUE_p,
3711 	Var **out_TRUE_v,
3712 	Boolean *out_TRUE_haveModifier,
3713 	const char **out_TRUE_extraModifiers,
3714 	Boolean *out_TRUE_dynamic,
3715 	VarExprFlags *out_TRUE_exprFlags
3716 ) {
3717     size_t namelen;
3718     char *varname;
3719     Var *v;
3720     Boolean haveModifier;
3721     Boolean dynamic = FALSE;
3722 
3723     const char *const start = p;
3724     char endc = startc == '(' ? ')' : '}';
3725 
3726     p += 2;			/* skip "${" or "$(" or "y(" */
3727     varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen);
3728 
3729     if (*p == ':') {
3730 	haveModifier = TRUE;
3731     } else if (*p == endc) {
3732 	haveModifier = FALSE;
3733     } else {
3734 	Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname);
3735 	free(varname);
3736 	*out_FALSE_pp = p;
3737 	*out_FALSE_val = var_Error;
3738 	*out_FALSE_res = VPR_PARSE_MSG;
3739 	return FALSE;
3740     }
3741 
3742     v = VarFind(varname, ctxt, TRUE);
3743 
3744     /* At this point, p points just after the variable name,
3745      * either at ':' or at endc. */
3746 
3747     if (v == NULL)
3748 	v = FindLocalLegacyVar(varname, namelen, ctxt, out_TRUE_extraModifiers);
3749 
3750     if (v == NULL) {
3751 	/* Defer expansion of dynamic variables if they appear in non-local
3752 	 * context since they are not defined there. */
3753 	dynamic = VarnameIsDynamic(varname, namelen) &&
3754 		  (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL);
3755 
3756 	if (!haveModifier) {
3757 	    p++;		/* skip endc */
3758 	    *out_FALSE_pp = p;
3759 	    *out_FALSE_res = EvalUndefined(dynamic, start, p, varname, eflags,
3760 					   out_FALSE_freeIt, out_FALSE_val);
3761 	    return FALSE;
3762 	}
3763 
3764 	/* The variable expression is based on an undefined variable.
3765 	 * Nevertheless it needs a Var, for modifiers that access the
3766 	 * variable name, such as :L or :?.
3767 	 *
3768 	 * Most modifiers leave this expression in the "undefined" state
3769 	 * (VEF_UNDEF), only a few modifiers like :D, :U, :L, :P turn this
3770 	 * undefined expression into a defined expression (VEF_DEF).
3771 	 *
3772 	 * At the end, after applying all modifiers, if the expression
3773 	 * is still undefined, Var_Parse will return an empty string
3774 	 * instead of the actually computed value. */
3775 	v = VarNew(varname, varname, "", 0);
3776 	*out_TRUE_exprFlags = VEF_UNDEF;
3777     } else
3778 	free(varname);
3779 
3780     *out_TRUE_endc = endc;
3781     *out_TRUE_p = p;
3782     *out_TRUE_v = v;
3783     *out_TRUE_haveModifier = haveModifier;
3784     *out_TRUE_dynamic = dynamic;
3785     return TRUE;
3786 }
3787 
3788 /*
3789  * Given the start of a variable expression (such as $v, $(VAR),
3790  * ${VAR:Mpattern}), extract the variable name and value, and the modifiers,
3791  * if any.  While doing that, apply the modifiers to the value of the
3792  * expression, forming its final value.  A few of the modifiers such as :!cmd!
3793  * or ::= have side effects.
3794  *
3795  * Input:
3796  *	*pp		The string to parse.
3797  *			When parsing a condition in ParseEmptyArg, it may also
3798  *			point to the "y" of "empty(VARNAME:Modifiers)", which
3799  *			is syntactically the same.
3800  *	ctxt		The context for finding variables
3801  *	eflags		Control the exact details of parsing
3802  *
3803  * Output:
3804  *	*pp		The position where to continue parsing.
3805  *			TODO: After a parse error, the value of *pp is
3806  *			unspecified.  It may not have been updated at all,
3807  *			point to some random character in the string, to the
3808  *			location of the parse error, or at the end of the
3809  *			string.
3810  *	*out_val	The value of the variable expression, never NULL.
3811  *	*out_val	var_Error if there was a parse error.
3812  *	*out_val	var_Error if the base variable of the expression was
3813  *			undefined, eflags contains VARE_UNDEFERR, and none of
3814  *			the modifiers turned the undefined expression into a
3815  *			defined expression.
3816  *			XXX: It is not guaranteed that an error message has
3817  *			been printed.
3818  *	*out_val	varUndefined if the base variable of the expression
3819  *			was undefined, eflags did not contain VARE_UNDEFERR,
3820  *			and none of the modifiers turned the undefined
3821  *			expression into a defined expression.
3822  *			XXX: It is not guaranteed that an error message has
3823  *			been printed.
3824  *	*out_val_freeIt	Must be freed by the caller after using *out_val.
3825  */
3826 /* coverity[+alloc : arg-*4] */
3827 VarParseResult
3828 Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags,
3829 	  const char **out_val, void **out_val_freeIt)
3830 {
3831     const char *p = *pp;
3832     const char *const start = p;
3833     Boolean haveModifier;	/* TRUE if have modifiers for the variable */
3834     char startc;		/* Starting character if variable in parens
3835 				 * or braces */
3836     char endc;			/* Ending character if variable in parens
3837 				 * or braces */
3838     Boolean dynamic;		/* TRUE if the variable is local and we're
3839 				 * expanding it in a non-local context. This
3840 				 * is done to support dynamic sources. The
3841 				 * result is just the expression, unaltered */
3842     const char *extramodifiers;
3843     Var *v;
3844     char *value;
3845     char eflags_str[VarEvalFlags_ToStringSize];
3846     VarExprFlags exprFlags = 0;
3847 
3848     VAR_DEBUG2("Var_Parse: %s with %s\n", start,
3849 	       Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags,
3850 				  VarEvalFlags_ToStringSpecs));
3851 
3852     *out_val_freeIt = NULL;
3853     extramodifiers = NULL;	/* extra modifiers to apply first */
3854     dynamic = FALSE;
3855 
3856     /* Appease GCC, which thinks that the variable might not be
3857      * initialized. */
3858     endc = '\0';
3859 
3860     startc = p[1];
3861     if (startc != '(' && startc != '{') {
3862 	VarParseResult res;
3863 	if (!ParseVarnameShort(startc, pp, ctxt, eflags, &res, out_val, &v))
3864 	    return res;
3865 	haveModifier = FALSE;
3866 	p++;
3867     } else {
3868 	VarParseResult res;
3869 	if (!ParseVarnameLong(p, startc, ctxt, eflags,
3870 			      pp, &res, out_val, out_val_freeIt,
3871 			      &endc, &p, &v, &haveModifier, &extramodifiers,
3872 			      &dynamic, &exprFlags))
3873 	    return res;
3874     }
3875 
3876     if (v->flags & VAR_IN_USE)
3877 	Fatal("Variable %s is recursive.", v->name);
3878 
3879     /* XXX: This assignment creates an alias to the current value of the
3880      * variable.  This means that as long as the value of the expression stays
3881      * the same, the value of the variable must not change.
3882      * Using the '::=' modifier, it could be possible to do exactly this.
3883      * At the bottom of this function, the resulting value is compared to the
3884      * then-current value of the variable.  This might also invoke undefined
3885      * behavior. */
3886     value = Buf_GetAll(&v->val, NULL);
3887 
3888     /* Before applying any modifiers, expand any nested expressions from the
3889      * variable value. */
3890     if (strchr(value, '$') != NULL && (eflags & VARE_WANTRES)) {
3891 	VarEvalFlags nested_eflags = eflags;
3892 	if (opts.lint)
3893 	    nested_eflags &= ~(unsigned)VARE_UNDEFERR;
3894 	v->flags |= VAR_IN_USE;
3895 	(void)Var_Subst(value, ctxt, nested_eflags, &value);
3896 	v->flags &= ~(unsigned)VAR_IN_USE;
3897 	/* TODO: handle errors */
3898 	*out_val_freeIt = value;
3899     }
3900 
3901     if (haveModifier || extramodifiers != NULL) {
3902 	void *extraFree;
3903 
3904 	extraFree = NULL;
3905 	if (extramodifiers != NULL) {
3906 	    const char *em = extramodifiers;
3907 	    value = ApplyModifiers(&em, value, '\0', '\0',
3908 				   v, &exprFlags, ctxt, eflags, &extraFree);
3909 	}
3910 
3911 	if (haveModifier) {
3912 	    /* Skip initial colon. */
3913 	    p++;
3914 
3915 	    value = ApplyModifiers(&p, value, startc, endc,
3916 				   v, &exprFlags, ctxt, eflags, out_val_freeIt);
3917 	    free(extraFree);
3918 	} else {
3919 	    *out_val_freeIt = extraFree;
3920 	}
3921     }
3922 
3923     if (*p != '\0')		/* Skip past endc if possible. */
3924 	p++;
3925 
3926     *pp = p;
3927 
3928     if (v->flags & VAR_FROM_ENV) {
3929 	/* Free the environment variable now since we own it,
3930 	 * but don't free the variable value if it will be returned. */
3931 	Boolean keepValue = value == Buf_GetAll(&v->val, NULL);
3932 	if (keepValue)
3933 	    *out_val_freeIt = value;
3934 	(void)VarFreeEnv(v, !keepValue);
3935 
3936     } else if (exprFlags & VEF_UNDEF) {
3937 	if (!(exprFlags & VEF_DEF)) {
3938 	    /* TODO: Use a local variable instead of out_val_freeIt.
3939 	     * Variables named out_* must only be written to. */
3940 	    if (*out_val_freeIt != NULL) {
3941 		free(*out_val_freeIt);
3942 		*out_val_freeIt = NULL;
3943 	    }
3944 	    if (dynamic) {
3945 		value = bmake_strsedup(start, p);
3946 		*out_val_freeIt = value;
3947 	    } else {
3948 		/* The expression is still undefined, therefore discard the
3949 		 * actual value and return an error marker instead. */
3950 		value = eflags & VARE_UNDEFERR ? var_Error : varUndefined;
3951 	    }
3952 	}
3953 	if (value != Buf_GetAll(&v->val, NULL))
3954 	    Buf_Destroy(&v->val, TRUE);
3955 	free(v->name_freeIt);
3956 	free(v);
3957     }
3958     *out_val = value;
3959     return VPR_UNKNOWN;
3960 }
3961 
3962 static void
3963 VarSubstNested(const char **const pp, Buffer *const buf, GNode *const ctxt,
3964 	       VarEvalFlags const eflags, Boolean *inout_errorReported)
3965 {
3966     const char *p = *pp;
3967     const char *nested_p = p;
3968     const char *val;
3969     void *val_freeIt;
3970 
3971     (void)Var_Parse(&nested_p, ctxt, eflags, &val, &val_freeIt);
3972     /* TODO: handle errors */
3973 
3974     if (val == var_Error || val == varUndefined) {
3975 	if (!preserveUndefined) {
3976 	    p = nested_p;
3977 	} else if ((eflags & VARE_UNDEFERR) || val == var_Error) {
3978 	    /* XXX: This condition is wrong.  If val == var_Error,
3979 	     * this doesn't necessarily mean there was an undefined
3980 	     * variable.  It could equally well be a parse error; see
3981 	     * unit-tests/varmod-order.exp. */
3982 
3983 	    /*
3984 	     * If variable is undefined, complain and skip the
3985 	     * variable. The complaint will stop us from doing anything
3986 	     * when the file is parsed.
3987 	     */
3988 	    if (!*inout_errorReported) {
3989 		Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",
3990 			    (int)(size_t)(nested_p - p), p);
3991 	    }
3992 	    p = nested_p;
3993 	    *inout_errorReported = TRUE;
3994 	} else {
3995 	    /* Copy the initial '$' of the undefined expression,
3996 	     * thereby deferring expansion of the expression, but
3997 	     * expand nested expressions if already possible.
3998 	     * See unit-tests/varparse-undef-partial.mk. */
3999 	    Buf_AddByte(buf, *p);
4000 	    p++;
4001 	}
4002     } else {
4003 	p = nested_p;
4004 	Buf_AddStr(buf, val);
4005     }
4006 
4007     free(val_freeIt);
4008 
4009     *pp = p;
4010 }
4011 
4012 /* Expand all variable expressions like $V, ${VAR}, $(VAR:Modifiers) in the
4013  * given string.
4014  *
4015  * Input:
4016  *	str		The string in which the variable expressions are
4017  *			expanded.
4018  *	ctxt		The context in which to start searching for
4019  *			variables.  The other contexts are searched as well.
4020  *	eflags		Special effects during expansion.
4021  */
4022 VarParseResult
4023 Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res)
4024 {
4025     const char *p = str;
4026     Buffer buf;			/* Buffer for forming things */
4027 
4028     /* Set true if an error has already been reported,
4029      * to prevent a plethora of messages when recursing */
4030     /* XXX: Why is the 'static' necessary here? */
4031     static Boolean errorReported;
4032 
4033     Buf_Init(&buf);
4034     errorReported = FALSE;
4035 
4036     while (*p != '\0') {
4037 	if (p[0] == '$' && p[1] == '$') {
4038 	    /* A dollar sign may be escaped with another dollar sign. */
4039 	    if (save_dollars && (eflags & VARE_KEEP_DOLLAR))
4040 		Buf_AddByte(&buf, '$');
4041 	    Buf_AddByte(&buf, '$');
4042 	    p += 2;
4043 
4044 	} else if (p[0] == '$') {
4045 	    VarSubstNested(&p, &buf, ctxt, eflags, &errorReported);
4046 
4047 	} else {
4048 	    /*
4049 	     * Skip as many characters as possible -- either to the end of
4050 	     * the string or to the next dollar sign (variable expression).
4051 	     */
4052 	    const char *plainStart = p;
4053 
4054 	    for (p++; *p != '$' && *p != '\0'; p++)
4055 		continue;
4056 	    Buf_AddBytesBetween(&buf, plainStart, p);
4057 	}
4058     }
4059 
4060     *out_res = Buf_DestroyCompact(&buf);
4061     return VPR_OK;
4062 }
4063 
4064 /* Initialize the variables module. */
4065 void
4066 Var_Init(void)
4067 {
4068     VAR_INTERNAL = GNode_New("Internal");
4069     VAR_GLOBAL = GNode_New("Global");
4070     VAR_CMDLINE = GNode_New("Command");
4071 }
4072 
4073 /* Clean up the variables module. */
4074 void
4075 Var_End(void)
4076 {
4077     Var_Stats();
4078 }
4079 
4080 void
4081 Var_Stats(void)
4082 {
4083     HashTable_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL");
4084 }
4085 
4086 /* Print all variables in a context, sorted by name. */
4087 void
4088 Var_Dump(GNode *ctxt)
4089 {
4090     Vector /* of const char * */ vec;
4091     HashIter hi;
4092     size_t i;
4093     const char **varnames;
4094 
4095     Vector_Init(&vec, sizeof(const char *));
4096 
4097     HashIter_Init(&hi, &ctxt->context);
4098     while (HashIter_Next(&hi) != NULL)
4099 	*(const char **)Vector_Push(&vec) = hi.entry->key;
4100     varnames = vec.items;
4101 
4102     qsort(varnames, vec.len, sizeof varnames[0], str_cmp_asc);
4103 
4104     for (i = 0; i < vec.len; i++) {
4105 	const char *varname = varnames[i];
4106 	Var *var = HashTable_FindValue(&ctxt->context, varname);
4107 	debug_printf("%-16s = %s\n", varname, Buf_GetAll(&var->val, NULL));
4108     }
4109 
4110     Vector_Done(&vec);
4111 }
4112