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