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