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