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