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