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