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