xref: /netbsd-src/usr.bin/make/var.c (revision 5aefcfdc06931dd97e76246d2fe0302f7b3fe094)
1 /*	$NetBSD: var.c,v 1.56 2000/09/05 21:08:35 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 1989 by Berkeley Softworks
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Adam de Boor.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  */
40 
41 #ifdef MAKE_BOOTSTRAP
42 static char rcsid[] = "$NetBSD: var.c,v 1.56 2000/09/05 21:08:35 christos Exp $";
43 #else
44 #include <sys/cdefs.h>
45 #ifndef lint
46 #if 0
47 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 3/19/94";
48 #else
49 __RCSID("$NetBSD: var.c,v 1.56 2000/09/05 21:08:35 christos Exp $");
50 #endif
51 #endif /* not lint */
52 #endif
53 
54 /*-
55  * var.c --
56  *	Variable-handling functions
57  *
58  * Interface:
59  *	Var_Set	  	    Set the value of a variable in the given
60  *	    	  	    context. The variable is created if it doesn't
61  *	    	  	    yet exist. The value and variable name need not
62  *	    	  	    be preserved.
63  *
64  *	Var_Append	    Append more characters to an existing variable
65  *	    	  	    in the given context. The variable needn't
66  *	    	  	    exist already -- it will be created if it doesn't.
67  *	    	  	    A space is placed between the old value and the
68  *	    	  	    new one.
69  *
70  *	Var_Exists	    See if a variable exists.
71  *
72  *	Var_Value 	    Return the value of a variable in a context or
73  *	    	  	    NULL if the variable is undefined.
74  *
75  *	Var_Subst 	    Substitute named variable, or all variables if
76  *			    NULL in a string using
77  *	    	  	    the given context as the top-most one. If the
78  *	    	  	    third argument is non-zero, Parse_Error is
79  *	    	  	    called if any variables are undefined.
80  *
81  *	Var_Parse 	    Parse a variable expansion from a string and
82  *	    	  	    return the result and the number of characters
83  *	    	  	    consumed.
84  *
85  *	Var_Delete	    Delete a variable in a context.
86  *
87  *	Var_Init  	    Initialize this module.
88  *
89  * Debugging:
90  *	Var_Dump  	    Print out all variables defined in the given
91  *	    	  	    context.
92  *
93  * XXX: There's a lot of duplication in these functions.
94  */
95 
96 #include    <ctype.h>
97 #ifndef NO_REGEX
98 #include    <sys/types.h>
99 #include    <regex.h>
100 #endif
101 #include    <stdlib.h>
102 #include    "make.h"
103 #include    "buf.h"
104 
105 /*
106  * This is a harmless return value for Var_Parse that can be used by Var_Subst
107  * to determine if there was an error in parsing -- easier than returning
108  * a flag, as things outside this module don't give a hoot.
109  */
110 char 	var_Error[] = "";
111 
112 /*
113  * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
114  * set false. Why not just use a constant? Well, gcc likes to condense
115  * identical string instances...
116  */
117 static char	varNoError[] = "";
118 
119 /*
120  * Internally, variables are contained in four different contexts.
121  *	1) the environment. They may not be changed. If an environment
122  *	    variable is appended-to, the result is placed in the global
123  *	    context.
124  *	2) the global context. Variables set in the Makefile are located in
125  *	    the global context. It is the penultimate context searched when
126  *	    substituting.
127  *	3) the command-line context. All variables set on the command line
128  *	   are placed in this context. They are UNALTERABLE once placed here.
129  *	4) the local context. Each target has associated with it a context
130  *	   list. On this list are located the structures describing such
131  *	   local variables as $(@) and $(*)
132  * The four contexts are searched in the reverse order from which they are
133  * listed.
134  */
135 GNode          *VAR_GLOBAL;   /* variables from the makefile */
136 GNode          *VAR_CMD;      /* variables defined on the command-line */
137 
138 #define FIND_CMD	0x1   /* look in VAR_CMD when searching */
139 #define FIND_GLOBAL	0x2   /* look in VAR_GLOBAL as well */
140 #define FIND_ENV  	0x4   /* look in the environment also */
141 
142 typedef struct Var {
143     char          *name;	/* the variable's name */
144     Buffer	  val;	    	/* its value */
145     int	    	  flags;    	/* miscellaneous status flags */
146 #define VAR_IN_USE	1   	    /* Variable's value currently being used.
147 				     * Used to avoid recursion */
148 #define VAR_FROM_ENV	2   	    /* Variable comes from the environment */
149 #define VAR_JUNK  	4   	    /* Variable is a junk variable that
150 				     * should be destroyed when done with
151 				     * it. Used by Var_Parse for undefined,
152 				     * modified variables */
153 #define VAR_KEEP	8	    /* Variable is VAR_JUNK, but we found
154 				     * a use for it in some modifier and
155 				     * the value is therefore valid */
156 }  Var;
157 
158 
159 /* Var*Pattern flags */
160 #define VAR_SUB_GLOBAL	0x01	/* Apply substitution globally */
161 #define VAR_SUB_ONE	0x02	/* Apply substitution to one word */
162 #define VAR_SUB_MATCHED	0x04	/* There was a match */
163 #define VAR_MATCH_START	0x08	/* Match at start of word */
164 #define VAR_MATCH_END	0x10	/* Match at end of word */
165 #define VAR_NOSUBST	0x20	/* don't expand vars in VarGetPattern */
166 
167 typedef struct {
168     char    	  *lhs;	    /* String to match */
169     int	    	   leftLen; /* Length of string */
170     char    	  *rhs;	    /* Replacement string (w/ &'s removed) */
171     int	    	  rightLen; /* Length of replacement */
172     int	    	  flags;
173 } VarPattern;
174 
175 typedef struct {
176     GNode	*ctxt;		/* variable context */
177     char	*tvar;		/* name of temp var */
178     int		tvarLen;
179     char	*str;		/* string to expand */
180     int		strLen;
181     int		err;		/* err for not defined */
182 } VarLoop_t;
183 
184 #ifndef NO_REGEX
185 typedef struct {
186     regex_t	   re;
187     int		   nsub;
188     regmatch_t 	  *matches;
189     char 	  *replace;
190     int		   flags;
191 } VarREPattern;
192 #endif
193 
194 static Var *VarFind __P((char *, GNode *, int));
195 static void VarAdd __P((char *, char *, GNode *));
196 static Boolean VarHead __P((char *, Boolean, Buffer, ClientData));
197 static Boolean VarTail __P((char *, Boolean, Buffer, ClientData));
198 static Boolean VarSuffix __P((char *, Boolean, Buffer, ClientData));
199 static Boolean VarRoot __P((char *, Boolean, Buffer, ClientData));
200 static Boolean VarMatch __P((char *, Boolean, Buffer, ClientData));
201 #ifdef SYSVVARSUB
202 static Boolean VarSYSVMatch __P((char *, Boolean, Buffer, ClientData));
203 #endif
204 static Boolean VarNoMatch __P((char *, Boolean, Buffer, ClientData));
205 #ifndef NO_REGEX
206 static void VarREError __P((int, regex_t *, const char *));
207 static Boolean VarRESubstitute __P((char *, Boolean, Buffer, ClientData));
208 #endif
209 static Boolean VarSubstitute __P((char *, Boolean, Buffer, ClientData));
210 static Boolean VarLoopExpand __P((char *, Boolean, Buffer, ClientData));
211 static char *VarGetPattern __P((GNode *, int, char **, int, int *, int *,
212 				VarPattern *));
213 static char *VarQuote __P((char *));
214 static char *VarModify __P((char *, Boolean (*)(char *, Boolean, Buffer,
215 						ClientData),
216 			    ClientData));
217 static char *VarSort __P((char *));
218 static char *VarUniq __P((char *));
219 static int VarWordCompare __P((const void *, const void *));
220 static void VarPrintVar __P((ClientData));
221 
222 /*-
223  *-----------------------------------------------------------------------
224  * VarFind --
225  *	Find the given variable in the given context and any other contexts
226  *	indicated.
227  *
228  * Results:
229  *	A pointer to the structure describing the desired variable or
230  *	NIL if the variable does not exist.
231  *
232  * Side Effects:
233  *	None
234  *-----------------------------------------------------------------------
235  */
236 static Var *
237 VarFind (name, ctxt, flags)
238     char           	*name;	/* name to find */
239     GNode          	*ctxt;	/* context in which to find it */
240     int             	flags;	/* FIND_GLOBAL set means to look in the
241 				 * VAR_GLOBAL context as well.
242 				 * FIND_CMD set means to look in the VAR_CMD
243 				 * context also.
244 				 * FIND_ENV set means to look in the
245 				 * environment */
246 {
247     Hash_Entry         	*var;
248     Var		  	*v;
249 
250 	/*
251 	 * If the variable name begins with a '.', it could very well be one of
252 	 * the local ones.  We check the name against all the local variables
253 	 * and substitute the short version in for 'name' if it matches one of
254 	 * them.
255 	 */
256 	if (*name == '.' && isupper((unsigned char) name[1]))
257 		switch (name[1]) {
258 		case 'A':
259 			if (!strcmp(name, ".ALLSRC"))
260 				name = ALLSRC;
261 			if (!strcmp(name, ".ARCHIVE"))
262 				name = ARCHIVE;
263 			break;
264 		case 'I':
265 			if (!strcmp(name, ".IMPSRC"))
266 				name = IMPSRC;
267 			break;
268 		case 'M':
269 			if (!strcmp(name, ".MEMBER"))
270 				name = MEMBER;
271 			break;
272 		case 'O':
273 			if (!strcmp(name, ".OODATE"))
274 				name = OODATE;
275 			break;
276 		case 'P':
277 			if (!strcmp(name, ".PREFIX"))
278 				name = PREFIX;
279 			break;
280 		case 'T':
281 			if (!strcmp(name, ".TARGET"))
282 				name = TARGET;
283 			break;
284 		}
285     /*
286      * First look for the variable in the given context. If it's not there,
287      * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
288      * depending on the FIND_* flags in 'flags'
289      */
290     var = Hash_FindEntry (&ctxt->context, name);
291 
292     if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
293 	var = Hash_FindEntry (&VAR_CMD->context, name);
294     }
295     if (!checkEnvFirst && (var == NULL) && (flags & FIND_GLOBAL) &&
296 	(ctxt != VAR_GLOBAL))
297     {
298 	var = Hash_FindEntry (&VAR_GLOBAL->context, name);
299     }
300     if ((var == NULL) && (flags & FIND_ENV)) {
301 	char *env;
302 
303 	if ((env = getenv (name)) != NULL) {
304 	    int	  	len;
305 
306 	    v = (Var *) emalloc(sizeof(Var));
307 	    v->name = estrdup(name);
308 
309 	    len = strlen(env);
310 
311 	    v->val = Buf_Init(len);
312 	    Buf_AddBytes(v->val, len, (Byte *)env);
313 
314 	    v->flags = VAR_FROM_ENV;
315 	    return (v);
316 	} else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
317 		   (ctxt != VAR_GLOBAL))
318 	{
319 	    var = Hash_FindEntry (&VAR_GLOBAL->context, name);
320 	    if (var == NULL) {
321 		return ((Var *) NIL);
322 	    } else {
323 		return ((Var *)Hash_GetValue(var));
324 	    }
325 	} else {
326 	    return((Var *)NIL);
327 	}
328     } else if (var == NULL) {
329 	return ((Var *) NIL);
330     } else {
331 	return ((Var *) Hash_GetValue(var));
332     }
333 }
334 
335 /*-
336  *-----------------------------------------------------------------------
337  * VarAdd  --
338  *	Add a new variable of name name and value val to the given context
339  *
340  * Results:
341  *	None
342  *
343  * Side Effects:
344  *	The new variable is placed at the front of the given context
345  *	The name and val arguments are duplicated so they may
346  *	safely be freed.
347  *-----------------------------------------------------------------------
348  */
349 static void
350 VarAdd (name, val, ctxt)
351     char           *name;	/* name of variable to add */
352     char           *val;	/* value to set it to */
353     GNode          *ctxt;	/* context in which to set it */
354 {
355     register Var   *v;
356     int	    	  len;
357     Hash_Entry      *h;
358 
359     v = (Var *) emalloc (sizeof (Var));
360 
361     len = val ? strlen(val) : 0;
362     v->val = Buf_Init(len+1);
363     Buf_AddBytes(v->val, len, (Byte *)val);
364 
365     v->flags = 0;
366 
367     h = Hash_CreateEntry (&ctxt->context, name, NULL);
368     Hash_SetValue(h, v);
369     v->name = h->name;
370     if (DEBUG(VAR)) {
371 	printf("%s:%s = %s\n", ctxt->name, name, val);
372     }
373 }
374 
375 /*-
376  *-----------------------------------------------------------------------
377  * Var_Delete --
378  *	Remove a variable from a context.
379  *
380  * Results:
381  *	None.
382  *
383  * Side Effects:
384  *	The Var structure is removed and freed.
385  *
386  *-----------------------------------------------------------------------
387  */
388 void
389 Var_Delete(name, ctxt)
390     char    	  *name;
391     GNode	  *ctxt;
392 {
393     Hash_Entry 	  *ln;
394 
395     if (DEBUG(VAR)) {
396 	printf("%s:delete %s\n", ctxt->name, name);
397     }
398     ln = Hash_FindEntry(&ctxt->context, name);
399     if (ln != NULL) {
400 	register Var 	  *v;
401 
402 	v = (Var *)Hash_GetValue(ln);
403 	if (v->name != ln->name)
404 		free(v->name);
405 	Hash_DeleteEntry(&ctxt->context, ln);
406 	Buf_Destroy(v->val, TRUE);
407 	free((Address) v);
408     }
409 }
410 
411 /*-
412  *-----------------------------------------------------------------------
413  * Var_Set --
414  *	Set the variable name to the value val in the given context.
415  *
416  * Results:
417  *	None.
418  *
419  * Side Effects:
420  *	If the variable doesn't yet exist, a new record is created for it.
421  *	Else the old value is freed and the new one stuck in its place
422  *
423  * Notes:
424  *	The variable is searched for only in its context before being
425  *	created in that context. I.e. if the context is VAR_GLOBAL,
426  *	only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
427  *	VAR_CMD->context is searched. This is done to avoid the literally
428  *	thousands of unnecessary strcmp's that used to be done to
429  *	set, say, $(@) or $(<).
430  *-----------------------------------------------------------------------
431  */
432 void
433 Var_Set (name, val, ctxt)
434     char           *name;	/* name of variable to set */
435     char           *val;	/* value to give to the variable */
436     GNode          *ctxt;	/* context in which to set it */
437 {
438     register Var   *v;
439     char *cp = name;
440 
441     /*
442      * We only look for a variable in the given context since anything set
443      * here will override anything in a lower context, so there's not much
444      * point in searching them all just to save a bit of memory...
445      */
446     if ((name = strchr(cp, '$'))) {
447 	name = Var_Subst(NULL, cp, ctxt, 0);
448     } else
449 	name = cp;
450     v = VarFind (name, ctxt, 0);
451     if (v == (Var *) NIL) {
452 	VarAdd (name, val, ctxt);
453     } else {
454 	Buf_Discard(v->val, Buf_Size(v->val));
455 	Buf_AddBytes(v->val, strlen(val), (Byte *)val);
456 
457 	if (DEBUG(VAR)) {
458 	    printf("%s:%s = %s\n", ctxt->name, name, val);
459 	}
460     }
461     /*
462      * Any variables given on the command line are automatically exported
463      * to the environment (as per POSIX standard)
464      */
465     if (ctxt == VAR_CMD) {
466 	setenv(name, val, 1);
467     }
468     if (name != cp)
469 	free(name);
470 }
471 
472 /*-
473  *-----------------------------------------------------------------------
474  * Var_Append --
475  *	The variable of the given name has the given value appended to it in
476  *	the given context.
477  *
478  * Results:
479  *	None
480  *
481  * Side Effects:
482  *	If the variable doesn't exist, it is created. Else the strings
483  *	are concatenated (with a space in between).
484  *
485  * Notes:
486  *	Only if the variable is being sought in the global context is the
487  *	environment searched.
488  *	XXX: Knows its calling circumstances in that if called with ctxt
489  *	an actual target, it will only search that context since only
490  *	a local variable could be being appended to. This is actually
491  *	a big win and must be tolerated.
492  *-----------------------------------------------------------------------
493  */
494 void
495 Var_Append (name, val, ctxt)
496     char           *name;	/* Name of variable to modify */
497     char           *val;	/* String to append to it */
498     GNode          *ctxt;	/* Context in which this should occur */
499 {
500     register Var   *v;
501     Hash_Entry	   *h;
502     char *cp = name;
503 
504     if ((name = strchr(cp, '$'))) {
505 	name = Var_Subst(NULL, cp, ctxt, 0);
506     } else
507 	name = cp;
508 
509     v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
510 
511     if (v == (Var *) NIL) {
512 	VarAdd (name, val, ctxt);
513     } else {
514 	Buf_AddByte(v->val, (Byte)' ');
515 	Buf_AddBytes(v->val, strlen(val), (Byte *)val);
516 
517 	if (DEBUG(VAR)) {
518 	    printf("%s:%s = %s\n", ctxt->name, name,
519 		   (char *) Buf_GetAll(v->val, (int *)NULL));
520 	}
521 
522 	if (v->flags & VAR_FROM_ENV) {
523 	    /*
524 	     * If the original variable came from the environment, we
525 	     * have to install it in the global context (we could place
526 	     * it in the environment, but then we should provide a way to
527 	     * export other variables...)
528 	     */
529 	    v->flags &= ~VAR_FROM_ENV;
530 	    h = Hash_CreateEntry (&ctxt->context, name, NULL);
531 	    Hash_SetValue(h, v);
532 	}
533     }
534     if (name != cp)
535 	free(name);
536 }
537 
538 /*-
539  *-----------------------------------------------------------------------
540  * Var_Exists --
541  *	See if the given variable exists.
542  *
543  * Results:
544  *	TRUE if it does, FALSE if it doesn't
545  *
546  * Side Effects:
547  *	None.
548  *
549  *-----------------------------------------------------------------------
550  */
551 Boolean
552 Var_Exists(name, ctxt)
553     char	  *name;    	/* Variable to find */
554     GNode	  *ctxt;    	/* Context in which to start search */
555 {
556     Var	    	  *v;
557 
558     v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
559 
560     if (v == (Var *)NIL) {
561 	return(FALSE);
562     } else if (v->flags & VAR_FROM_ENV) {
563 	free(v->name);
564 	Buf_Destroy(v->val, TRUE);
565 	free((char *)v);
566     }
567     return(TRUE);
568 }
569 
570 /*-
571  *-----------------------------------------------------------------------
572  * Var_Value --
573  *	Return the value of the named variable in the given context
574  *
575  * Results:
576  *	The value if the variable exists, NULL if it doesn't
577  *
578  * Side Effects:
579  *	None
580  *-----------------------------------------------------------------------
581  */
582 char *
583 Var_Value (name, ctxt, frp)
584     char           *name;	/* name to find */
585     GNode          *ctxt;	/* context in which to search for it */
586     char	   **frp;
587 {
588     Var            *v;
589 
590     v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
591     *frp = NULL;
592     if (v != (Var *) NIL) {
593 	char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
594 	if (v->flags & VAR_FROM_ENV) {
595 	    free(v->name);
596 	    Buf_Destroy(v->val, FALSE);
597 	    free((Address) v);
598 	    *frp = p;
599 	}
600 	return p;
601     } else {
602 	return ((char *) NULL);
603     }
604 }
605 
606 /*-
607  *-----------------------------------------------------------------------
608  * VarHead --
609  *	Remove the tail of the given word and place the result in the given
610  *	buffer.
611  *
612  * Results:
613  *	TRUE if characters were added to the buffer (a space needs to be
614  *	added to the buffer before the next word).
615  *
616  * Side Effects:
617  *	The trimmed word is added to the buffer.
618  *
619  *-----------------------------------------------------------------------
620  */
621 static Boolean
622 VarHead (word, addSpace, buf, dummy)
623     char    	  *word;    	/* Word to trim */
624     Boolean 	  addSpace; 	/* True if need to add a space to the buffer
625 				 * before sticking in the head */
626     Buffer  	  buf;	    	/* Buffer in which to store it */
627     ClientData	  dummy;
628 {
629     register char *slash;
630 
631     slash = strrchr (word, '/');
632     if (slash != (char *)NULL) {
633 	if (addSpace) {
634 	    Buf_AddByte (buf, (Byte)' ');
635 	}
636 	*slash = '\0';
637 	Buf_AddBytes (buf, strlen (word), (Byte *)word);
638 	*slash = '/';
639 	return (TRUE);
640     } else {
641 	/*
642 	 * If no directory part, give . (q.v. the POSIX standard)
643 	 */
644 	if (addSpace) {
645 	    Buf_AddBytes(buf, 2, (Byte *)" .");
646 	} else {
647 	    Buf_AddByte(buf, (Byte)'.');
648 	}
649     }
650     return(dummy ? TRUE : TRUE);
651 }
652 
653 /*-
654  *-----------------------------------------------------------------------
655  * VarTail --
656  *	Remove the head of the given word and place the result in the given
657  *	buffer.
658  *
659  * Results:
660  *	TRUE if characters were added to the buffer (a space needs to be
661  *	added to the buffer before the next word).
662  *
663  * Side Effects:
664  *	The trimmed word is added to the buffer.
665  *
666  *-----------------------------------------------------------------------
667  */
668 static Boolean
669 VarTail (word, addSpace, buf, dummy)
670     char    	  *word;    	/* Word to trim */
671     Boolean 	  addSpace; 	/* TRUE if need to stick a space in the
672 				 * buffer before adding the tail */
673     Buffer  	  buf;	    	/* Buffer in which to store it */
674     ClientData	  dummy;
675 {
676     register char *slash;
677 
678     if (addSpace) {
679 	Buf_AddByte (buf, (Byte)' ');
680     }
681 
682     slash = strrchr (word, '/');
683     if (slash != (char *)NULL) {
684 	*slash++ = '\0';
685 	Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
686 	slash[-1] = '/';
687     } else {
688 	Buf_AddBytes (buf, strlen(word), (Byte *)word);
689     }
690     return (dummy ? TRUE : TRUE);
691 }
692 
693 /*-
694  *-----------------------------------------------------------------------
695  * VarSuffix --
696  *	Place the suffix of the given word in the given buffer.
697  *
698  * Results:
699  *	TRUE if characters were added to the buffer (a space needs to be
700  *	added to the buffer before the next word).
701  *
702  * Side Effects:
703  *	The suffix from the word is placed in the buffer.
704  *
705  *-----------------------------------------------------------------------
706  */
707 static Boolean
708 VarSuffix (word, addSpace, buf, dummy)
709     char    	  *word;    	/* Word to trim */
710     Boolean 	  addSpace; 	/* TRUE if need to add a space before placing
711 				 * the suffix in the buffer */
712     Buffer  	  buf;	    	/* Buffer in which to store it */
713     ClientData	  dummy;
714 {
715     register char *dot;
716 
717     dot = strrchr (word, '.');
718     if (dot != (char *)NULL) {
719 	if (addSpace) {
720 	    Buf_AddByte (buf, (Byte)' ');
721 	}
722 	*dot++ = '\0';
723 	Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
724 	dot[-1] = '.';
725 	addSpace = TRUE;
726     }
727     return (dummy ? addSpace : addSpace);
728 }
729 
730 /*-
731  *-----------------------------------------------------------------------
732  * VarRoot --
733  *	Remove the suffix of the given word and place the result in the
734  *	buffer.
735  *
736  * Results:
737  *	TRUE if characters were added to the buffer (a space needs to be
738  *	added to the buffer before the next word).
739  *
740  * Side Effects:
741  *	The trimmed word is added to the buffer.
742  *
743  *-----------------------------------------------------------------------
744  */
745 static Boolean
746 VarRoot (word, addSpace, buf, dummy)
747     char    	  *word;    	/* Word to trim */
748     Boolean 	  addSpace; 	/* TRUE if need to add a space to the buffer
749 				 * before placing the root in it */
750     Buffer  	  buf;	    	/* Buffer in which to store it */
751     ClientData	  dummy;
752 {
753     register char *dot;
754 
755     if (addSpace) {
756 	Buf_AddByte (buf, (Byte)' ');
757     }
758 
759     dot = strrchr (word, '.');
760     if (dot != (char *)NULL) {
761 	*dot = '\0';
762 	Buf_AddBytes (buf, strlen (word), (Byte *)word);
763 	*dot = '.';
764     } else {
765 	Buf_AddBytes (buf, strlen(word), (Byte *)word);
766     }
767     return (dummy ? TRUE : TRUE);
768 }
769 
770 /*-
771  *-----------------------------------------------------------------------
772  * VarMatch --
773  *	Place the word in the buffer if it matches the given pattern.
774  *	Callback function for VarModify to implement the :M modifier.
775  *
776  * Results:
777  *	TRUE if a space should be placed in the buffer before the next
778  *	word.
779  *
780  * Side Effects:
781  *	The word may be copied to the buffer.
782  *
783  *-----------------------------------------------------------------------
784  */
785 static Boolean
786 VarMatch (word, addSpace, buf, pattern)
787     char    	  *word;    	/* Word to examine */
788     Boolean 	  addSpace; 	/* TRUE if need to add a space to the
789 				 * buffer before adding the word, if it
790 				 * matches */
791     Buffer  	  buf;	    	/* Buffer in which to store it */
792     ClientData    pattern; 	/* Pattern the word must match */
793 {
794     if (Str_Match(word, (char *) pattern)) {
795 	if (addSpace) {
796 	    Buf_AddByte(buf, (Byte)' ');
797 	}
798 	addSpace = TRUE;
799 	Buf_AddBytes(buf, strlen(word), (Byte *)word);
800     }
801     return(addSpace);
802 }
803 
804 #ifdef SYSVVARSUB
805 /*-
806  *-----------------------------------------------------------------------
807  * VarSYSVMatch --
808  *	Place the word in the buffer if it matches the given pattern.
809  *	Callback function for VarModify to implement the System V %
810  *	modifiers.
811  *
812  * Results:
813  *	TRUE if a space should be placed in the buffer before the next
814  *	word.
815  *
816  * Side Effects:
817  *	The word may be copied to the buffer.
818  *
819  *-----------------------------------------------------------------------
820  */
821 static Boolean
822 VarSYSVMatch (word, addSpace, buf, patp)
823     char    	  *word;    	/* Word to examine */
824     Boolean 	  addSpace; 	/* TRUE if need to add a space to the
825 				 * buffer before adding the word, if it
826 				 * matches */
827     Buffer  	  buf;	    	/* Buffer in which to store it */
828     ClientData 	  patp; 	/* Pattern the word must match */
829 {
830     int len;
831     char *ptr;
832     VarPattern 	  *pat = (VarPattern *) patp;
833 
834     if (addSpace)
835 	Buf_AddByte(buf, (Byte)' ');
836 
837     addSpace = TRUE;
838 
839     if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL)
840 	Str_SYSVSubst(buf, pat->rhs, ptr, len);
841     else
842 	Buf_AddBytes(buf, strlen(word), (Byte *) word);
843 
844     return(addSpace);
845 }
846 #endif
847 
848 
849 /*-
850  *-----------------------------------------------------------------------
851  * VarNoMatch --
852  *	Place the word in the buffer if it doesn't match the given pattern.
853  *	Callback function for VarModify to implement the :N modifier.
854  *
855  * Results:
856  *	TRUE if a space should be placed in the buffer before the next
857  *	word.
858  *
859  * Side Effects:
860  *	The word may be copied to the buffer.
861  *
862  *-----------------------------------------------------------------------
863  */
864 static Boolean
865 VarNoMatch (word, addSpace, buf, pattern)
866     char    	  *word;    	/* Word to examine */
867     Boolean 	  addSpace; 	/* TRUE if need to add a space to the
868 				 * buffer before adding the word, if it
869 				 * matches */
870     Buffer  	  buf;	    	/* Buffer in which to store it */
871     ClientData    pattern; 	/* Pattern the word must match */
872 {
873     if (!Str_Match(word, (char *) pattern)) {
874 	if (addSpace) {
875 	    Buf_AddByte(buf, (Byte)' ');
876 	}
877 	addSpace = TRUE;
878 	Buf_AddBytes(buf, strlen(word), (Byte *)word);
879     }
880     return(addSpace);
881 }
882 
883 
884 /*-
885  *-----------------------------------------------------------------------
886  * VarSubstitute --
887  *	Perform a string-substitution on the given word, placing the
888  *	result in the passed buffer.
889  *
890  * Results:
891  *	TRUE if a space is needed before more characters are added.
892  *
893  * Side Effects:
894  *	None.
895  *
896  *-----------------------------------------------------------------------
897  */
898 static Boolean
899 VarSubstitute (word, addSpace, buf, patternp)
900     char    	  	*word;	    /* Word to modify */
901     Boolean 	  	addSpace;   /* True if space should be added before
902 				     * other characters */
903     Buffer  	  	buf;	    /* Buffer for result */
904     ClientData	        patternp;   /* Pattern for substitution */
905 {
906     register int  	wordLen;    /* Length of word */
907     register char 	*cp;	    /* General pointer */
908     VarPattern	*pattern = (VarPattern *) patternp;
909 
910     wordLen = strlen(word);
911     if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) !=
912 	(VAR_SUB_ONE|VAR_SUB_MATCHED)) {
913 	/*
914 	 * Still substituting -- break it down into simple anchored cases
915 	 * and if none of them fits, perform the general substitution case.
916 	 */
917 	if ((pattern->flags & VAR_MATCH_START) &&
918 	    (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
919 		/*
920 		 * Anchored at start and beginning of word matches pattern
921 		 */
922 		if ((pattern->flags & VAR_MATCH_END) &&
923 		    (wordLen == pattern->leftLen)) {
924 			/*
925 			 * Also anchored at end and matches to the end (word
926 			 * is same length as pattern) add space and rhs only
927 			 * if rhs is non-null.
928 			 */
929 			if (pattern->rightLen != 0) {
930 			    if (addSpace) {
931 				Buf_AddByte(buf, (Byte)' ');
932 			    }
933 			    addSpace = TRUE;
934 			    Buf_AddBytes(buf, pattern->rightLen,
935 					 (Byte *)pattern->rhs);
936 			}
937 			pattern->flags |= VAR_SUB_MATCHED;
938 		} else if (pattern->flags & VAR_MATCH_END) {
939 		    /*
940 		     * Doesn't match to end -- copy word wholesale
941 		     */
942 		    goto nosub;
943 		} else {
944 		    /*
945 		     * Matches at start but need to copy in trailing characters
946 		     */
947 		    if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
948 			if (addSpace) {
949 			    Buf_AddByte(buf, (Byte)' ');
950 			}
951 			addSpace = TRUE;
952 		    }
953 		    Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
954 		    Buf_AddBytes(buf, wordLen - pattern->leftLen,
955 				 (Byte *)(word + pattern->leftLen));
956 		    pattern->flags |= VAR_SUB_MATCHED;
957 		}
958 	} else if (pattern->flags & VAR_MATCH_START) {
959 	    /*
960 	     * Had to match at start of word and didn't -- copy whole word.
961 	     */
962 	    goto nosub;
963 	} else if (pattern->flags & VAR_MATCH_END) {
964 	    /*
965 	     * Anchored at end, Find only place match could occur (leftLen
966 	     * characters from the end of the word) and see if it does. Note
967 	     * that because the $ will be left at the end of the lhs, we have
968 	     * to use strncmp.
969 	     */
970 	    cp = word + (wordLen - pattern->leftLen);
971 	    if ((cp >= word) &&
972 		(strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
973 		/*
974 		 * Match found. If we will place characters in the buffer,
975 		 * add a space before hand as indicated by addSpace, then
976 		 * stuff in the initial, unmatched part of the word followed
977 		 * by the right-hand-side.
978 		 */
979 		if (((cp - word) + pattern->rightLen) != 0) {
980 		    if (addSpace) {
981 			Buf_AddByte(buf, (Byte)' ');
982 		    }
983 		    addSpace = TRUE;
984 		}
985 		Buf_AddBytes(buf, cp - word, (Byte *)word);
986 		Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
987 		pattern->flags |= VAR_SUB_MATCHED;
988 	    } else {
989 		/*
990 		 * Had to match at end and didn't. Copy entire word.
991 		 */
992 		goto nosub;
993 	    }
994 	} else {
995 	    /*
996 	     * Pattern is unanchored: search for the pattern in the word using
997 	     * String_FindSubstring, copying unmatched portions and the
998 	     * right-hand-side for each match found, handling non-global
999 	     * substitutions correctly, etc. When the loop is done, any
1000 	     * remaining part of the word (word and wordLen are adjusted
1001 	     * accordingly through the loop) is copied straight into the
1002 	     * buffer.
1003 	     * addSpace is set FALSE as soon as a space is added to the
1004 	     * buffer.
1005 	     */
1006 	    register Boolean done;
1007 	    int origSize;
1008 
1009 	    done = FALSE;
1010 	    origSize = Buf_Size(buf);
1011 	    while (!done) {
1012 		cp = Str_FindSubstring(word, pattern->lhs);
1013 		if (cp != (char *)NULL) {
1014 		    if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
1015 			Buf_AddByte(buf, (Byte)' ');
1016 			addSpace = FALSE;
1017 		    }
1018 		    Buf_AddBytes(buf, cp-word, (Byte *)word);
1019 		    Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
1020 		    wordLen -= (cp - word) + pattern->leftLen;
1021 		    word = cp + pattern->leftLen;
1022 		    if (wordLen == 0) {
1023 			done = TRUE;
1024 		    }
1025 		    if ((pattern->flags & VAR_SUB_GLOBAL) == 0) {
1026 			done = TRUE;
1027 		    }
1028 		    pattern->flags |= VAR_SUB_MATCHED;
1029 		} else {
1030 		    done = TRUE;
1031 		}
1032 	    }
1033 	    if (wordLen != 0) {
1034 		if (addSpace) {
1035 		    Buf_AddByte(buf, (Byte)' ');
1036 		}
1037 		Buf_AddBytes(buf, wordLen, (Byte *)word);
1038 	    }
1039 	    /*
1040 	     * If added characters to the buffer, need to add a space
1041 	     * before we add any more. If we didn't add any, just return
1042 	     * the previous value of addSpace.
1043 	     */
1044 	    return ((Buf_Size(buf) != origSize) || addSpace);
1045 	}
1046 	return (addSpace);
1047     }
1048  nosub:
1049     if (addSpace) {
1050 	Buf_AddByte(buf, (Byte)' ');
1051     }
1052     Buf_AddBytes(buf, wordLen, (Byte *)word);
1053     return(TRUE);
1054 }
1055 
1056 #ifndef NO_REGEX
1057 /*-
1058  *-----------------------------------------------------------------------
1059  * VarREError --
1060  *	Print the error caused by a regcomp or regexec call.
1061  *
1062  * Results:
1063  *	None.
1064  *
1065  * Side Effects:
1066  *	An error gets printed.
1067  *
1068  *-----------------------------------------------------------------------
1069  */
1070 static void
1071 VarREError(err, pat, str)
1072     int err;
1073     regex_t *pat;
1074     const char *str;
1075 {
1076     char *errbuf;
1077     int errlen;
1078 
1079     errlen = regerror(err, pat, 0, 0);
1080     errbuf = emalloc(errlen);
1081     regerror(err, pat, errbuf, errlen);
1082     Error("%s: %s", str, errbuf);
1083     free(errbuf);
1084 }
1085 
1086 
1087 /*-
1088  *-----------------------------------------------------------------------
1089  * VarRESubstitute --
1090  *	Perform a regex substitution on the given word, placing the
1091  *	result in the passed buffer.
1092  *
1093  * Results:
1094  *	TRUE if a space is needed before more characters are added.
1095  *
1096  * Side Effects:
1097  *	None.
1098  *
1099  *-----------------------------------------------------------------------
1100  */
1101 static Boolean
1102 VarRESubstitute(word, addSpace, buf, patternp)
1103     char *word;
1104     Boolean addSpace;
1105     Buffer buf;
1106     ClientData patternp;
1107 {
1108     VarREPattern *pat;
1109     int xrv;
1110     char *wp;
1111     char *rp;
1112     int added;
1113     int flags = 0;
1114 
1115 #define MAYBE_ADD_SPACE()		\
1116 	if (addSpace && !added)		\
1117 	    Buf_AddByte(buf, ' ');	\
1118 	added = 1
1119 
1120     added = 0;
1121     wp = word;
1122     pat = patternp;
1123 
1124     if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
1125 	(VAR_SUB_ONE|VAR_SUB_MATCHED))
1126 	xrv = REG_NOMATCH;
1127     else {
1128     tryagain:
1129 	xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
1130     }
1131 
1132     switch (xrv) {
1133     case 0:
1134 	pat->flags |= VAR_SUB_MATCHED;
1135 	if (pat->matches[0].rm_so > 0) {
1136 	    MAYBE_ADD_SPACE();
1137 	    Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
1138 	}
1139 
1140 	for (rp = pat->replace; *rp; rp++) {
1141 	    if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
1142 		MAYBE_ADD_SPACE();
1143 		Buf_AddByte(buf,rp[1]);
1144 		rp++;
1145 	    }
1146 	    else if ((*rp == '&') ||
1147 		((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
1148 		int n;
1149 		char *subbuf;
1150 		int sublen;
1151 		char errstr[3];
1152 
1153 		if (*rp == '&') {
1154 		    n = 0;
1155 		    errstr[0] = '&';
1156 		    errstr[1] = '\0';
1157 		} else {
1158 		    n = rp[1] - '0';
1159 		    errstr[0] = '\\';
1160 		    errstr[1] = rp[1];
1161 		    errstr[2] = '\0';
1162 		    rp++;
1163 		}
1164 
1165 		if (n > pat->nsub) {
1166 		    Error("No subexpression %s", &errstr[0]);
1167 		    subbuf = "";
1168 		    sublen = 0;
1169 		} else if ((pat->matches[n].rm_so == -1) &&
1170 			   (pat->matches[n].rm_eo == -1)) {
1171 		    Error("No match for subexpression %s", &errstr[0]);
1172 		    subbuf = "";
1173 		    sublen = 0;
1174 	        } else {
1175 		    subbuf = wp + pat->matches[n].rm_so;
1176 		    sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
1177 		}
1178 
1179 		if (sublen > 0) {
1180 		    MAYBE_ADD_SPACE();
1181 		    Buf_AddBytes(buf, sublen, subbuf);
1182 		}
1183 	    } else {
1184 		MAYBE_ADD_SPACE();
1185 		Buf_AddByte(buf, *rp);
1186 	    }
1187 	}
1188 	wp += pat->matches[0].rm_eo;
1189 	if (pat->flags & VAR_SUB_GLOBAL) {
1190 	    flags |= REG_NOTBOL;
1191 	    if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
1192 		MAYBE_ADD_SPACE();
1193 		Buf_AddByte(buf, *wp);
1194 		wp++;
1195 
1196 	    }
1197 	    if (*wp)
1198 		goto tryagain;
1199 	}
1200 	if (*wp) {
1201 	    MAYBE_ADD_SPACE();
1202 	    Buf_AddBytes(buf, strlen(wp), wp);
1203 	}
1204 	break;
1205     default:
1206 	VarREError(xrv, &pat->re, "Unexpected regex error");
1207        /* fall through */
1208     case REG_NOMATCH:
1209 	if (*wp) {
1210 	    MAYBE_ADD_SPACE();
1211 	    Buf_AddBytes(buf,strlen(wp),wp);
1212 	}
1213 	break;
1214     }
1215     return(addSpace||added);
1216 }
1217 #endif
1218 
1219 
1220 
1221 /*-
1222  *-----------------------------------------------------------------------
1223  * VarLoopExpand --
1224  *	Implements the :@<temp>@<string>@ modifier of ODE make.
1225  *	We set the temp variable named in pattern.lhs to word and expand
1226  *	pattern.rhs storing the result in the passed buffer.
1227  *
1228  * Results:
1229  *	TRUE if a space is needed before more characters are added.
1230  *
1231  * Side Effects:
1232  *	None.
1233  *
1234  *-----------------------------------------------------------------------
1235  */
1236 static Boolean
1237 VarLoopExpand (word, addSpace, buf, loopp)
1238     char    	  	*word;	    /* Word to modify */
1239     Boolean 	  	addSpace;   /* True if space should be added before
1240 				     * other characters */
1241     Buffer  	  	buf;	    /* Buffer for result */
1242     ClientData	        loopp;      /* Data for substitution */
1243 {
1244     VarLoop_t	*loop = (VarLoop_t *) loopp;
1245     char *s;
1246 
1247     Var_Set(loop->tvar, word, loop->ctxt);
1248     s = Var_Subst(NULL, loop->str, loop->ctxt, loop->err);
1249     if (s != NULL && *s != '\0') {
1250 	if (addSpace)
1251 	    Buf_AddByte(buf, ' ');
1252 	Buf_AddBytes(buf, strlen(s), (Byte *)s);
1253 	free(s);
1254 	addSpace = TRUE;
1255     }
1256     return addSpace;
1257 }
1258 
1259 /*-
1260  *-----------------------------------------------------------------------
1261  * VarModify --
1262  *	Modify each of the words of the passed string using the given
1263  *	function. Used to implement all modifiers.
1264  *
1265  * Results:
1266  *	A string of all the words modified appropriately.
1267  *
1268  * Side Effects:
1269  *	None.
1270  *
1271  *-----------------------------------------------------------------------
1272  */
1273 static char *
1274 VarModify (str, modProc, datum)
1275     char    	  *str;	    	    /* String whose words should be trimmed */
1276 				    /* Function to use to modify them */
1277     Boolean    	  (*modProc) __P((char *, Boolean, Buffer, ClientData));
1278     ClientData	  datum;    	    /* Datum to pass it */
1279 {
1280     Buffer  	  buf;	    	    /* Buffer for the new string */
1281     Boolean 	  addSpace; 	    /* TRUE if need to add a space to the
1282 				     * buffer before adding the trimmed
1283 				     * word */
1284     char **av;			    /* word list [first word does not count] */
1285     char *as;			    /* word list memory */
1286     int ac, i;
1287 
1288     buf = Buf_Init (0);
1289     addSpace = FALSE;
1290 
1291     av = brk_string(str, &ac, FALSE, &as);
1292 
1293     for (i = 0; i < ac; i++)
1294 	addSpace = (*modProc)(av[i], addSpace, buf, datum);
1295 
1296     free(as);
1297     free(av);
1298 
1299     Buf_AddByte (buf, '\0');
1300     str = (char *)Buf_GetAll (buf, (int *)NULL);
1301     Buf_Destroy (buf, FALSE);
1302     return (str);
1303 }
1304 
1305 
1306 static int
1307 VarWordCompare(a, b)
1308 	const void *a;
1309 	const void *b;
1310 {
1311 	int r = strcmp(*(char **)a, *(char **)b);
1312 	return r;
1313 }
1314 
1315 /*-
1316  *-----------------------------------------------------------------------
1317  * VarSort --
1318  *	Sort the words in the string.
1319  *
1320  * Results:
1321  *	A string containing the words sorted
1322  *
1323  * Side Effects:
1324  *	None.
1325  *
1326  *-----------------------------------------------------------------------
1327  */
1328 static char *
1329 VarSort (str)
1330     char    	  *str;	    	    /* String whose words should be sorted */
1331 				    /* Function to use to modify them */
1332 {
1333     Buffer  	  buf;	    	    /* Buffer for the new string */
1334     char **av;			    /* word list [first word does not count] */
1335     char *as;			    /* word list memory */
1336     int ac, i;
1337 
1338     buf = Buf_Init (0);
1339 
1340     av = brk_string(str, &ac, FALSE, &as);
1341 
1342     if (ac > 0)
1343 	qsort(av, ac, sizeof(char *), VarWordCompare);
1344 
1345     for (i = 0; i < ac; i++) {
1346 	Buf_AddBytes(buf, strlen(av[i]), (Byte *) av[i]);
1347 	if (i != ac - 1)
1348 	    Buf_AddByte (buf, ' ');
1349     }
1350 
1351     free(as);
1352     free(av);
1353 
1354     Buf_AddByte (buf, '\0');
1355     str = (char *)Buf_GetAll (buf, (int *)NULL);
1356     Buf_Destroy (buf, FALSE);
1357     return (str);
1358 }
1359 
1360 
1361 /*-
1362  *-----------------------------------------------------------------------
1363  * VarUniq --
1364  *	Remove adjacent duplicate words.
1365  *
1366  * Results:
1367  *	A string containing the resulting words.
1368  *
1369  * Side Effects:
1370  *	None.
1371  *
1372  *-----------------------------------------------------------------------
1373  */
1374 static char *
1375 VarUniq(str)
1376     char 	 *str;	    	    /* String whose words should be sorted */
1377 				    /* Function to use to modify them */
1378 {
1379     Buffer	  buf;	    	    /* Buffer for new string */
1380     char 	**av;		    /* List of words to affect */
1381     char 	 *as;		    /* Word list memory */
1382     int 	  ac, i, j;
1383 
1384     buf = Buf_Init(0);
1385     av = brk_string(str, &ac, FALSE, &as);
1386 
1387     if (ac > 1) {
1388 	for (j = 0, i = 1; i < ac; i++)
1389 	    if (strcmp(av[i], av[j]) != 0 && (++j != i))
1390 		av[j] = av[i];
1391 	ac = j + 1;
1392     }
1393 
1394     for (i = 0; i < ac; i++) {
1395 	Buf_AddBytes(buf, strlen(av[i]), (Byte *)av[i]);
1396 	if (i != ac - 1)
1397 	    Buf_AddByte(buf, ' ');
1398     }
1399 
1400     free(as);
1401     free(av);
1402 
1403     Buf_AddByte(buf, '\0');
1404     str = (char *)Buf_GetAll(buf, (int *)NULL);
1405     Buf_Destroy(buf, FALSE);
1406     return str;
1407 }
1408 
1409 
1410 /*-
1411  *-----------------------------------------------------------------------
1412  * VarGetPattern --
1413  *	Pass through the tstr looking for 1) escaped delimiters,
1414  *	'$'s and backslashes (place the escaped character in
1415  *	uninterpreted) and 2) unescaped $'s that aren't before
1416  *	the delimiter (expand the variable substitution unless flags
1417  *	has VAR_NOSUBST set).
1418  *	Return the expanded string or NULL if the delimiter was missing
1419  *	If pattern is specified, handle escaped ampersands, and replace
1420  *	unescaped ampersands with the lhs of the pattern.
1421  *
1422  * Results:
1423  *	A string of all the words modified appropriately.
1424  *	If length is specified, return the string length of the buffer
1425  *	If flags is specified and the last character of the pattern is a
1426  *	$ set the VAR_MATCH_END bit of flags.
1427  *
1428  * Side Effects:
1429  *	None.
1430  *-----------------------------------------------------------------------
1431  */
1432 static char *
1433 VarGetPattern(ctxt, err, tstr, delim, flags, length, pattern)
1434     GNode *ctxt;
1435     int err;
1436     char **tstr;
1437     int delim;
1438     int *flags;
1439     int *length;
1440     VarPattern *pattern;
1441 {
1442     char *cp;
1443     Buffer buf = Buf_Init(0);
1444     int junk;
1445     if (length == NULL)
1446 	length = &junk;
1447 
1448 #define IS_A_MATCH(cp, delim) \
1449     ((cp[0] == '\\') && ((cp[1] == delim) ||  \
1450      (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
1451 
1452     /*
1453      * Skim through until the matching delimiter is found;
1454      * pick up variable substitutions on the way. Also allow
1455      * backslashes to quote the delimiter, $, and \, but don't
1456      * touch other backslashes.
1457      */
1458     for (cp = *tstr; *cp && (*cp != delim); cp++) {
1459 	if (IS_A_MATCH(cp, delim)) {
1460 	    Buf_AddByte(buf, (Byte) cp[1]);
1461 	    cp++;
1462 	} else if (*cp == '$') {
1463 	    if (cp[1] == delim) {
1464 		if (flags == NULL)
1465 		    Buf_AddByte(buf, (Byte) *cp);
1466 		else
1467 		    /*
1468 		     * Unescaped $ at end of pattern => anchor
1469 		     * pattern at end.
1470 		     */
1471 		    *flags |= VAR_MATCH_END;
1472 	    } else {
1473 		if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
1474 		    char   *cp2;
1475 		    int     len;
1476 		    Boolean freeIt;
1477 
1478 		    /*
1479 		     * If unescaped dollar sign not before the
1480 		     * delimiter, assume it's a variable
1481 		     * substitution and recurse.
1482 		     */
1483 		    cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1484 		    Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
1485 		    if (freeIt)
1486 			free(cp2);
1487 		    cp += len - 1;
1488 		} else {
1489 		    char *cp2 = &cp[1];
1490 
1491 		    if (*cp2 == '(' || *cp2 == '{') {
1492 			/*
1493 			 * Find the end of this variable reference
1494 			 * and suck it in without further ado.
1495 			 * It will be interperated later.
1496 			 */
1497 			int have = *cp2;
1498 			int want = (*cp2 == '(') ? ')' : '}';
1499 			int depth = 1;
1500 
1501 			for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
1502 			    if (cp2[-1] != '\\') {
1503 				if (*cp2 == have)
1504 				    ++depth;
1505 				if (*cp2 == want)
1506 				    --depth;
1507 			    }
1508 			}
1509 			Buf_AddBytes(buf, cp2 - cp, (Byte *)cp);
1510 			cp = --cp2;
1511 		    } else
1512 			Buf_AddByte(buf, (Byte) *cp);
1513 		}
1514 	    }
1515 	}
1516 	else if (pattern && *cp == '&')
1517 	    Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs);
1518 	else
1519 	    Buf_AddByte(buf, (Byte) *cp);
1520     }
1521 
1522     Buf_AddByte(buf, (Byte) '\0');
1523 
1524     if (*cp != delim) {
1525 	*tstr = cp;
1526 	*length = 0;
1527 	return NULL;
1528     }
1529     else {
1530 	*tstr = ++cp;
1531 	cp = (char *) Buf_GetAll(buf, length);
1532 	*length -= 1;	/* Don't count the NULL */
1533 	Buf_Destroy(buf, FALSE);
1534 	return cp;
1535     }
1536 }
1537 
1538 /*-
1539  *-----------------------------------------------------------------------
1540  * VarQuote --
1541  *	Quote shell meta-characters in the string
1542  *
1543  * Results:
1544  *	The quoted string
1545  *
1546  * Side Effects:
1547  *	None.
1548  *
1549  *-----------------------------------------------------------------------
1550  */
1551 static char *
1552 VarQuote(str)
1553 	char *str;
1554 {
1555 
1556     Buffer  	  buf;
1557     /* This should cover most shells :-( */
1558     static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
1559 
1560     buf = Buf_Init (MAKE_BSIZE);
1561     for (; *str; str++) {
1562 	if (strchr(meta, *str) != NULL)
1563 	    Buf_AddByte(buf, (Byte)'\\');
1564 	Buf_AddByte(buf, (Byte)*str);
1565     }
1566     Buf_AddByte(buf, (Byte) '\0');
1567     str = (char *)Buf_GetAll (buf, (int *)NULL);
1568     Buf_Destroy (buf, FALSE);
1569     return str;
1570 }
1571 
1572 
1573 /*-
1574  *-----------------------------------------------------------------------
1575  * Var_Parse --
1576  *	Given the start of a variable invocation, extract the variable
1577  *	name and find its value, then modify it according to the
1578  *	specification.
1579  *
1580  * Results:
1581  *	The (possibly-modified) value of the variable or var_Error if the
1582  *	specification is invalid. The length of the specification is
1583  *	placed in *lengthPtr (for invalid specifications, this is just
1584  *	2...?).
1585  *	A Boolean in *freePtr telling whether the returned string should
1586  *	be freed by the caller.
1587  *
1588  * Side Effects:
1589  *	None.
1590  *
1591  *-----------------------------------------------------------------------
1592  */
1593 char *
1594 Var_Parse (str, ctxt, err, lengthPtr, freePtr)
1595     char    	  *str;	    	/* The string to parse */
1596     GNode   	  *ctxt;    	/* The context for the variable */
1597     Boolean 	    err;    	/* TRUE if undefined variables are an error */
1598     int	    	    *lengthPtr;	/* OUT: The length of the specification */
1599     Boolean 	    *freePtr; 	/* OUT: TRUE if caller should free result */
1600 {
1601     register char   *tstr;    	/* Pointer into str */
1602     Var	    	    *v;	    	/* Variable in invocation */
1603     char   	    *cp;    	/* Secondary pointer into str (place marker
1604 				 * for tstr) */
1605     Boolean 	    haveModifier;/* TRUE if have modifiers for the variable */
1606     register char   endc;    	/* Ending character when variable in parens
1607 				 * or braces */
1608     register char   startc=0;	/* Starting character when variable in parens
1609 				 * or braces */
1610     int             cnt;	/* Used to count brace pairs when variable in
1611 				 * in parens or braces */
1612     int		    vlen;	/* Length of variable name */
1613     char    	    *start;
1614     char	     delim;
1615     Boolean 	    dynamic;	/* TRUE if the variable is local and we're
1616 				 * expanding it in a non-local context. This
1617 				 * is done to support dynamic sources. The
1618 				 * result is just the invocation, unaltered */
1619 
1620     *freePtr = FALSE;
1621     dynamic = FALSE;
1622     start = str;
1623 
1624     if (str[1] != '(' && str[1] != '{') {
1625 	/*
1626 	 * If it's not bounded by braces of some sort, life is much simpler.
1627 	 * We just need to check for the first character and return the
1628 	 * value if it exists.
1629 	 */
1630 	char	  name[2];
1631 
1632 	name[0] = str[1];
1633 	name[1] = '\0';
1634 
1635 	v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1636 	if (v == (Var *)NIL) {
1637 	    *lengthPtr = 2;
1638 
1639 	    if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
1640 		/*
1641 		 * If substituting a local variable in a non-local context,
1642 		 * assume it's for dynamic source stuff. We have to handle
1643 		 * this specially and return the longhand for the variable
1644 		 * with the dollar sign escaped so it makes it back to the
1645 		 * caller. Only four of the local variables are treated
1646 		 * specially as they are the only four that will be set
1647 		 * when dynamic sources are expanded.
1648 		 */
1649 		switch (str[1]) {
1650 		    case '@':
1651 			return("$(.TARGET)");
1652 		    case '%':
1653 			return("$(.ARCHIVE)");
1654 		    case '*':
1655 			return("$(.PREFIX)");
1656 		    case '!':
1657 			return("$(.MEMBER)");
1658 		}
1659 	    }
1660 	    /*
1661 	     * Error
1662 	     */
1663 	    return (err ? var_Error : varNoError);
1664 	} else {
1665 	    haveModifier = FALSE;
1666 	    tstr = &str[1];
1667 	    endc = str[1];
1668 	}
1669     } else {
1670 	Buffer buf;	/* Holds the variable name */
1671 
1672 	startc = str[1];
1673 	endc = startc == '(' ? ')' : '}';
1674 	buf = Buf_Init (MAKE_BSIZE);
1675 
1676 	/*
1677 	 * Skip to the end character or a colon, whichever comes first.
1678 	 */
1679 	for (tstr = str + 2;
1680 	     *tstr != '\0' && *tstr != endc && *tstr != ':';
1681 	     tstr++)
1682 	{
1683 	    /*
1684 	     * A variable inside a variable, expand
1685 	     */
1686 	    if (*tstr == '$') {
1687 		int rlen;
1688 		Boolean rfree;
1689 		char *rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
1690 		if (rval != NULL) {
1691 		    Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
1692 		    if (rfree)
1693 			free(rval);
1694 		}
1695 		tstr += rlen - 1;
1696 	    }
1697 	    else
1698 		Buf_AddByte(buf, (Byte) *tstr);
1699 	}
1700 	if (*tstr == ':') {
1701 	    haveModifier = TRUE;
1702 	} else if (*tstr != '\0') {
1703 	    haveModifier = FALSE;
1704 	} else {
1705 	    /*
1706 	     * If we never did find the end character, return NULL
1707 	     * right now, setting the length to be the distance to
1708 	     * the end of the string, since that's what make does.
1709 	     */
1710 	    *lengthPtr = tstr - str;
1711 	    return (var_Error);
1712 	}
1713 	*tstr = '\0';
1714 	Buf_AddByte(buf, (Byte) '\0');
1715 	str = Buf_GetAll(buf, (int *) NULL);
1716 	vlen = strlen(str);
1717 
1718 	v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1719 	if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
1720 	    (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
1721 	{
1722 	    /*
1723 	     * Check for bogus D and F forms of local variables since we're
1724 	     * in a local context and the name is the right length.
1725 	     */
1726 	    switch(*str) {
1727 		case '@':
1728 		case '%':
1729 		case '*':
1730 		case '!':
1731 		case '>':
1732 		case '<':
1733 		{
1734 		    char    vname[2];
1735 		    char    *val;
1736 
1737 		    /*
1738 		     * Well, it's local -- go look for it.
1739 		     */
1740 		    vname[0] = *str;
1741 		    vname[1] = '\0';
1742 		    v = VarFind(vname, ctxt, 0);
1743 
1744 		    if (v != (Var *)NIL) {
1745 			/*
1746 			 * No need for nested expansion or anything, as we're
1747 			 * the only one who sets these things and we sure don't
1748 			 * but nested invocations in them...
1749 			 */
1750 			val = (char *)Buf_GetAll(v->val, (int *)NULL);
1751 
1752 			if (str[1] == 'D') {
1753 			    val = VarModify(val, VarHead, (ClientData)0);
1754 			} else {
1755 			    val = VarModify(val, VarTail, (ClientData)0);
1756 			}
1757 			/*
1758 			 * Resulting string is dynamically allocated, so
1759 			 * tell caller to free it.
1760 			 */
1761 			*freePtr = TRUE;
1762 			*lengthPtr = tstr-start+1;
1763 			*tstr = endc;
1764 			Buf_Destroy (buf, TRUE);
1765 			return(val);
1766 		    }
1767 		    break;
1768 		}
1769 	    }
1770 	}
1771 
1772 	if (v == (Var *)NIL) {
1773 	    if (((vlen == 1) ||
1774 		 (((vlen == 2) && (str[1] == 'F' ||
1775 					 str[1] == 'D')))) &&
1776 		((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
1777 	    {
1778 		/*
1779 		 * If substituting a local variable in a non-local context,
1780 		 * assume it's for dynamic source stuff. We have to handle
1781 		 * this specially and return the longhand for the variable
1782 		 * with the dollar sign escaped so it makes it back to the
1783 		 * caller. Only four of the local variables are treated
1784 		 * specially as they are the only four that will be set
1785 		 * when dynamic sources are expanded.
1786 		 */
1787 		switch (*str) {
1788 		    case '@':
1789 		    case '%':
1790 		    case '*':
1791 		    case '!':
1792 			dynamic = TRUE;
1793 			break;
1794 		}
1795 	    } else if ((vlen > 2) && (*str == '.') &&
1796 		       isupper((unsigned char) str[1]) &&
1797 		       ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
1798 	    {
1799 		int	len;
1800 
1801 		len = vlen - 1;
1802 		if ((strncmp(str, ".TARGET", len) == 0) ||
1803 		    (strncmp(str, ".ARCHIVE", len) == 0) ||
1804 		    (strncmp(str, ".PREFIX", len) == 0) ||
1805 		    (strncmp(str, ".MEMBER", len) == 0))
1806 		{
1807 		    dynamic = TRUE;
1808 		}
1809 	    }
1810 
1811 	    if (!haveModifier) {
1812 		/*
1813 		 * No modifiers -- have specification length so we can return
1814 		 * now.
1815 		 */
1816 		*lengthPtr = tstr - start + 1;
1817 		*tstr = endc;
1818 		if (dynamic) {
1819 		    str = emalloc(*lengthPtr + 1);
1820 		    strncpy(str, start, *lengthPtr);
1821 		    str[*lengthPtr] = '\0';
1822 		    *freePtr = TRUE;
1823 		    Buf_Destroy (buf, TRUE);
1824 		    return(str);
1825 		} else {
1826 		    Buf_Destroy (buf, TRUE);
1827 		    return (err ? var_Error : varNoError);
1828 		}
1829 	    } else {
1830 		/*
1831 		 * Still need to get to the end of the variable specification,
1832 		 * so kludge up a Var structure for the modifications
1833 		 */
1834 		v = (Var *) emalloc(sizeof(Var));
1835 		v->name = str;
1836 		v->val = Buf_Init(1);
1837 		v->flags = VAR_JUNK;
1838 		Buf_Destroy (buf, FALSE);
1839 	    }
1840 	} else
1841 	    Buf_Destroy (buf, TRUE);
1842     }
1843 
1844 
1845     if (v->flags & VAR_IN_USE) {
1846 	Fatal("Variable %s is recursive.", v->name);
1847 	/*NOTREACHED*/
1848     } else {
1849 	v->flags |= VAR_IN_USE;
1850     }
1851     /*
1852      * Before doing any modification, we have to make sure the value
1853      * has been fully expanded. If it looks like recursion might be
1854      * necessary (there's a dollar sign somewhere in the variable's value)
1855      * we just call Var_Subst to do any other substitutions that are
1856      * necessary. Note that the value returned by Var_Subst will have
1857      * been dynamically-allocated, so it will need freeing when we
1858      * return.
1859      */
1860     str = (char *)Buf_GetAll(v->val, (int *)NULL);
1861     if (strchr (str, '$') != (char *)NULL) {
1862 	str = Var_Subst(NULL, str, ctxt, err);
1863 	*freePtr = TRUE;
1864     }
1865 
1866     v->flags &= ~VAR_IN_USE;
1867 
1868     /*
1869      * Now we need to apply any modifiers the user wants applied.
1870      * These are:
1871      *  	  :M<pattern>	words which match the given <pattern>.
1872      *  	  	    	<pattern> is of the standard file
1873      *  	  	    	wildcarding form.
1874      *  	  :N<pattern>	words which do not match the given <pattern>.
1875      *  	  :S<d><pat1><d><pat2><d>[g]
1876      *  	  	    	Substitute <pat2> for <pat1> in the value
1877      *  	  :C<d><pat1><d><pat2><d>[g]
1878      *  	  	    	Substitute <pat2> for regex <pat1> in the value
1879      *  	  :H	    	Substitute the head of each word
1880      *  	  :T	    	Substitute the tail of each word
1881      *  	  :E	    	Substitute the extension (minus '.') of
1882      *  	  	    	each word
1883      *  	  :R	    	Substitute the root of each word
1884      *  	  	    	(pathname minus the suffix).
1885      *		  :O		("Order") Sort words in variable.
1886      *		  :u		("uniq") Remove adjacent duplicate words.
1887      *		  :?<true-value>:<false-value>
1888      *				If the variable evaluates to true, return
1889      *				true value, else return the second value.
1890      *	    	  :lhs=rhs  	Like :S, but the rhs goes to the end of
1891      *	    	    	    	the invocation.
1892      *		  :sh		Treat the current value as a command
1893      *				to be run, new value is its output.
1894      * The following added so we can handle ODE makefiles.
1895      *		  :@<tmpvar>@<newval>@
1896      *				Assign a temporary local variable <tmpvar>
1897      *				to the current value of each word in turn
1898      *				and replace each word with the result of
1899      *				evaluating <newval>
1900      *		  :D<newval>	Use <newval> as value if variable defined
1901      *		  :U<newval>	Use <newval> as value if variable undefined
1902      *		  :L		Use the name of the variable as the value.
1903      *		  :P		Use the path of the node that has the same
1904      *				name as the variable as the value.  This
1905      *				basically includes an implied :L so that
1906      *				the common method of refering to the path
1907      *				of your dependent 'x' in a rule is to use
1908      *				the form '${x:P}'.
1909      *		  :!<cmd>!	Run cmd much the same as :sh run's the
1910      *				current value of the variable.
1911      * The ::= modifiers, actually assign a value to the variable.
1912      * Their main purpose is in supporting modifiers of .for loop
1913      * iterators and other obscure uses.  They always expand to
1914      * nothing.  In a target rule that would otherwise expand to an
1915      * empty line they can be preceded with @: to keep make happy.
1916      * Eg.
1917      *
1918      * foo:	.USE
1919      * .for i in ${.TARGET} ${.TARGET:R}.gz
1920      * 		@: ${t::=$i}
1921      *		@echo blah ${t:T}
1922      * .endfor
1923      *
1924      *		  ::=<str>	Assigns <str> as the new value of variable.
1925      *		  ::?=<str>	Assigns <str> as value of variable if
1926      *				it was not already set.
1927      *		  ::+=<str>	Appends <str> to variable.
1928      *		  ::!=<cmd>	Assigns output of <cmd> as the new value of
1929      *				variable.
1930      */
1931     if ((str != (char *)NULL) && haveModifier) {
1932 	/*
1933 	 * Skip initial colon while putting it back.
1934 	 */
1935 	*tstr++ = ':';
1936 	while (*tstr != endc) {
1937 	    char	*newStr;    /* New value to return */
1938 	    char	termc;	    /* Character which terminated scan */
1939 
1940 	    if (DEBUG(VAR)) {
1941 		printf("Applying :%c to \"%s\"\n", *tstr, str);
1942 	    }
1943 	    switch (*tstr) {
1944 	        case ':':
1945 
1946 		if (tstr[1] == '=' ||
1947 		    (tstr[2] == '=' &&
1948 		     (tstr[1] == '!' || tstr[1] == '+' || tstr[1] == '?'))) {
1949 		    GNode *v_ctxt;		/* context where v belongs */
1950 		    char *emsg;
1951 		    VarPattern	pattern;
1952 		    int	how;
1953 
1954 		    ++tstr;
1955 		    if (v->flags & VAR_JUNK) {
1956 			/*
1957 			 * We need to strdup() it incase
1958 			 * VarGetPattern() recurses.
1959 			 */
1960 			v->name = strdup(v->name);
1961 			v_ctxt = ctxt;
1962 		    } else if (ctxt != VAR_GLOBAL) {
1963 			if (VarFind(v->name, ctxt, 0) == (Var *)NIL)
1964 			    v_ctxt = VAR_GLOBAL;
1965 			else
1966 			    v_ctxt = ctxt;
1967 		    }
1968 
1969 		    switch ((how = *tstr)) {
1970 		    case '+':
1971 		    case '?':
1972 		    case '!':
1973 			cp = &tstr[2];
1974 			break;
1975 		    default:
1976 			cp = ++tstr;
1977 			break;
1978 		    }
1979 		    delim = '}';
1980 		    pattern.flags = 0;
1981 
1982 		    if ((pattern.rhs = VarGetPattern(ctxt, err, &cp, delim,
1983 						     NULL, &pattern.rightLen, NULL)) == NULL) {
1984 			if (v->flags & VAR_JUNK) {
1985 			    free(v->name);
1986 			    v->name = str;
1987 			}
1988 			goto cleanup;
1989 		    }
1990 		    termc = *--cp;
1991 		    delim = '\0';
1992 
1993 		    switch (how) {
1994 		    case '+':
1995 			Var_Append(v->name, pattern.rhs, v_ctxt);
1996 			break;
1997 		    case '!':
1998 			newStr = Cmd_Exec (pattern.rhs, &emsg);
1999 			if (emsg)
2000 			    Error (emsg, str);
2001 			else
2002 			   Var_Set(v->name, newStr,  v_ctxt);
2003 			if (newStr)
2004 			    free(newStr);
2005 			break;
2006 		    case '?':
2007 			if ((v->flags & VAR_JUNK) == 0)
2008 			    break;
2009 			/* FALLTHROUGH */
2010 		    default:
2011 			Var_Set(v->name, pattern.rhs, v_ctxt);
2012 			break;
2013 		    }
2014 		    if (v->flags & VAR_JUNK) {
2015 			free(v->name);
2016 			v->name = str;
2017 		    }
2018 		    free(pattern.rhs);
2019 		    newStr = var_Error;
2020 		    break;
2021 		}
2022 		goto default_case;
2023 	        case '@':
2024 		{
2025 		    VarLoop_t	loop;
2026 		    int flags = VAR_NOSUBST;
2027 
2028 		    cp = ++tstr;
2029 		    delim = '@';
2030 		    if ((loop.tvar = VarGetPattern(ctxt, err, &cp, delim,
2031 						   &flags, &loop.tvarLen,
2032 						   NULL)) == NULL)
2033 			goto cleanup;
2034 
2035 		    if ((loop.str = VarGetPattern(ctxt, err, &cp, delim,
2036 						  &flags, &loop.strLen,
2037 						  NULL)) == NULL)
2038 			goto cleanup;
2039 
2040 		    termc = *cp;
2041 		    delim = '\0';
2042 
2043 		    loop.err = err;
2044 		    loop.ctxt = ctxt;
2045 		    newStr = VarModify(str, VarLoopExpand,
2046 				       (ClientData)&loop);
2047 		    free(loop.tvar);
2048 		    free(loop.str);
2049 		    break;
2050 		}
2051 	        case 'D':
2052 	        case 'U':
2053 		{
2054 		    Buffer  buf;    	/* Buffer for patterns */
2055 		    int	    wantit;	/* want data in buffer */
2056 
2057 		    /*
2058 		     * Pass through tstr looking for 1) escaped delimiters,
2059 		     * '$'s and backslashes (place the escaped character in
2060 		     * uninterpreted) and 2) unescaped $'s that aren't before
2061 		     * the delimiter (expand the variable substitution).
2062 		     * The result is left in the Buffer buf.
2063 		     */
2064 		    buf = Buf_Init(0);
2065 		    for (cp = tstr + 1;
2066 			 *cp != endc && *cp != ':' && *cp != '\0';
2067 			 cp++) {
2068 			if ((*cp == '\\') &&
2069 			    ((cp[1] == ':') ||
2070 			     (cp[1] == '$') ||
2071 			     (cp[1] == endc) ||
2072 			     (cp[1] == '\\')))
2073 			{
2074 			    Buf_AddByte(buf, (Byte) cp[1]);
2075 			    cp++;
2076 			} else if (*cp == '$') {
2077 			    /*
2078 			     * If unescaped dollar sign, assume it's a
2079 			     * variable substitution and recurse.
2080 			     */
2081 			    char    *cp2;
2082 			    int	    len;
2083 			    Boolean freeIt;
2084 
2085 			    cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
2086 			    Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
2087 			    if (freeIt)
2088 				free(cp2);
2089 			    cp += len - 1;
2090 			} else {
2091 			    Buf_AddByte(buf, (Byte) *cp);
2092 			}
2093 		    }
2094 		    Buf_AddByte(buf, (Byte) '\0');
2095 
2096 		    termc = *cp;
2097 
2098 		    if (*tstr == 'U')
2099 			wantit = ((v->flags & VAR_JUNK) != 0);
2100 		    else
2101 			wantit = ((v->flags & VAR_JUNK) == 0);
2102 		    if ((v->flags & VAR_JUNK) != 0)
2103 			v->flags |= VAR_KEEP;
2104 		    if (wantit) {
2105 			newStr = (char *)Buf_GetAll(buf, (int *)NULL);
2106 			Buf_Destroy(buf, FALSE);
2107 		    } else {
2108 			newStr = str;
2109 			Buf_Destroy(buf, TRUE);
2110 		    }
2111 		    break;
2112 		}
2113 	        case 'L':
2114 		{
2115 		    if ((v->flags & VAR_JUNK) != 0)
2116 			v->flags |= VAR_KEEP;
2117 		    newStr = strdup(v->name);
2118 		    cp = ++tstr;
2119 		    termc = *tstr;
2120 		    break;
2121 		}
2122 	        case 'P':
2123 		{
2124 		    GNode *gn;
2125 
2126 		    if ((v->flags & VAR_JUNK) != 0)
2127 			v->flags |= VAR_KEEP;
2128 		    gn = Targ_FindNode(v->name, TARG_NOCREATE);
2129 		    if (gn == NILGNODE)
2130 			newStr = strdup(v->name);
2131 		    else
2132 			newStr = strdup(gn->path);
2133 		    cp = ++tstr;
2134 		    termc = *tstr;
2135 		    break;
2136 		}
2137 	        case '!':
2138 		{
2139 		    char *emsg;
2140 		    VarPattern 	    pattern;
2141 		    pattern.flags = 0;
2142 
2143 		    delim = '!';
2144 
2145 		    cp = ++tstr;
2146 		    if ((pattern.rhs = VarGetPattern(ctxt, err, &cp, delim,
2147 						     NULL, &pattern.rightLen, NULL)) == NULL)
2148 			goto cleanup;
2149 		    newStr = Cmd_Exec (pattern.rhs, &emsg);
2150 		    free(pattern.rhs);
2151 		    if (emsg)
2152 			Error (emsg, str);
2153 		    termc = *cp;
2154 		    delim = '\0';
2155 		    if (v->flags & VAR_JUNK) {
2156 			v->flags |= VAR_KEEP;
2157 		    }
2158 		    break;
2159 		}
2160 		case 'N':
2161 		case 'M':
2162 		{
2163 		    char    *pattern;
2164 		    char    *cp2;
2165 		    Boolean copy;
2166 		    int nest;
2167 
2168 		    copy = FALSE;
2169 		    nest = 1;
2170 		    for (cp = tstr + 1;
2171 			 *cp != '\0' && *cp != ':';
2172 			 cp++)
2173 		    {
2174 			if (*cp == '\\' &&
2175 			    (cp[1] == ':' ||
2176 			     cp[1] == endc || cp[1] == startc)) {
2177 			    copy = TRUE;
2178 			    cp++;
2179 			    continue;
2180 			}
2181 			if (*cp == startc)
2182 			    ++nest;
2183 			if (*cp == endc) {
2184 			    --nest;
2185 			    if (nest == 0)
2186 				break;
2187 			}
2188 		    }
2189 		    termc = *cp;
2190 		    *cp = '\0';
2191 		    if (copy) {
2192 			/*
2193 			 * Need to compress the \:'s out of the pattern, so
2194 			 * allocate enough room to hold the uncompressed
2195 			 * pattern (note that cp started at tstr+1, so
2196 			 * cp - tstr takes the null byte into account) and
2197 			 * compress the pattern into the space.
2198 			 */
2199 			pattern = emalloc(cp - tstr);
2200 			for (cp2 = pattern, cp = tstr + 1;
2201 			     *cp != '\0';
2202 			     cp++, cp2++)
2203 			{
2204 			    if ((*cp == '\\') &&
2205 				(cp[1] == ':' || cp[1] == endc)) {
2206 				    cp++;
2207 			    }
2208 			    *cp2 = *cp;
2209 			}
2210 			*cp2 = '\0';
2211 		    } else {
2212 			pattern = &tstr[1];
2213 		    }
2214 		    if ((cp2 = strchr(pattern, '$'))) {
2215 			cp2 = pattern;
2216 			pattern = Var_Subst(NULL, cp2, ctxt, err);
2217 			if (copy)
2218 			    free(cp2);
2219 			copy = TRUE;
2220 		    }
2221 		    if (*tstr == 'M' || *tstr == 'm') {
2222 			newStr = VarModify(str, VarMatch, (ClientData)pattern);
2223 		    } else {
2224 			newStr = VarModify(str, VarNoMatch,
2225 					   (ClientData)pattern);
2226 		    }
2227 		    if (copy) {
2228 			free(pattern);
2229 		    }
2230 		    break;
2231 		}
2232 		case 'S':
2233 		{
2234 		    VarPattern 	    pattern;
2235 
2236 		    pattern.flags = 0;
2237 		    delim = tstr[1];
2238 		    tstr += 2;
2239 
2240 		    /*
2241 		     * If pattern begins with '^', it is anchored to the
2242 		     * start of the word -- skip over it and flag pattern.
2243 		     */
2244 		    if (*tstr == '^') {
2245 			pattern.flags |= VAR_MATCH_START;
2246 			tstr += 1;
2247 		    }
2248 
2249 		    cp = tstr;
2250 		    if ((pattern.lhs = VarGetPattern(ctxt, err, &cp, delim,
2251 			&pattern.flags, &pattern.leftLen, NULL)) == NULL)
2252 			goto cleanup;
2253 
2254 		    if ((pattern.rhs = VarGetPattern(ctxt, err, &cp, delim,
2255 			NULL, &pattern.rightLen, &pattern)) == NULL)
2256 			goto cleanup;
2257 
2258 		    /*
2259 		     * Check for global substitution. If 'g' after the final
2260 		     * delimiter, substitution is global and is marked that
2261 		     * way.
2262 		     */
2263 		    for (;; cp++) {
2264 			switch (*cp) {
2265 			case 'g':
2266 			    pattern.flags |= VAR_SUB_GLOBAL;
2267 			    continue;
2268 			case '1':
2269 			    pattern.flags |= VAR_SUB_ONE;
2270 			    continue;
2271 			}
2272 			break;
2273 		    }
2274 
2275 		    termc = *cp;
2276 		    newStr = VarModify(str, VarSubstitute,
2277 				       (ClientData)&pattern);
2278 
2279 		    /*
2280 		     * Free the two strings.
2281 		     */
2282 		    free(pattern.lhs);
2283 		    free(pattern.rhs);
2284 		    break;
2285 		}
2286 		case '?':
2287 		{
2288 		    VarPattern 	pattern;
2289 		    Boolean	value;
2290 
2291 		    /* find ':', and then substitute accordingly */
2292 
2293 		    pattern.flags = 0;
2294 
2295 		    cp = ++tstr;
2296 		    delim = ':';
2297 		    if ((pattern.lhs = VarGetPattern(ctxt, err, &cp, delim,
2298 			NULL, &pattern.leftLen, NULL)) == NULL)
2299 			goto cleanup;
2300 
2301 		    delim = '}';
2302 		    if ((pattern.rhs = VarGetPattern(ctxt, err, &cp, delim,
2303 			NULL, &pattern.rightLen, NULL)) == NULL)
2304 			goto cleanup;
2305 
2306 		    termc = *--cp;
2307 		    delim = '\0';
2308 		    if (Cond_EvalExpression(1, str, &value, 0) == COND_INVALID){
2309 			Error("Bad conditional expression `%s' in %s?%s:%s",
2310 			      str, str, pattern.lhs, pattern.rhs);
2311 			goto cleanup;
2312 		    }
2313 
2314 		    if (value) {
2315 			newStr = pattern.lhs;
2316 			free(pattern.rhs);
2317 		    } else {
2318 			newStr = pattern.rhs;
2319 			free(pattern.lhs);
2320 		    }
2321 		    break;
2322 		}
2323 #ifndef NO_REGEX
2324 		case 'C':
2325 		{
2326 		    VarREPattern    pattern;
2327 		    char           *re;
2328 		    int             error;
2329 
2330 		    pattern.flags = 0;
2331 		    delim = tstr[1];
2332 		    tstr += 2;
2333 
2334 		    cp = tstr;
2335 
2336 		    if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
2337 			NULL, NULL)) == NULL)
2338 			goto cleanup;
2339 
2340 		    if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
2341 			delim, NULL, NULL, NULL)) == NULL){
2342 			free(re);
2343 			goto cleanup;
2344 		    }
2345 
2346 		    for (;; cp++) {
2347 			switch (*cp) {
2348 			case 'g':
2349 			    pattern.flags |= VAR_SUB_GLOBAL;
2350 			    continue;
2351 			case '1':
2352 			    pattern.flags |= VAR_SUB_ONE;
2353 			    continue;
2354 			}
2355 			break;
2356 		    }
2357 
2358 		    termc = *cp;
2359 
2360 		    error = regcomp(&pattern.re, re, REG_EXTENDED);
2361 		    free(re);
2362 		    if (error)  {
2363 			*lengthPtr = cp - start + 1;
2364 			VarREError(error, &pattern.re, "RE substitution error");
2365 			free(pattern.replace);
2366 			return (var_Error);
2367 		    }
2368 
2369 		    pattern.nsub = pattern.re.re_nsub + 1;
2370 		    if (pattern.nsub < 1)
2371 			pattern.nsub = 1;
2372 		    if (pattern.nsub > 10)
2373 			pattern.nsub = 10;
2374 		    pattern.matches = emalloc(pattern.nsub *
2375 					      sizeof(regmatch_t));
2376 		    newStr = VarModify(str, VarRESubstitute,
2377 				       (ClientData) &pattern);
2378 		    regfree(&pattern.re);
2379 		    free(pattern.replace);
2380 		    free(pattern.matches);
2381 		    break;
2382 		}
2383 #endif
2384 		case 'Q':
2385 		    if (tstr[1] == endc || tstr[1] == ':') {
2386 			newStr = VarQuote (str);
2387 			cp = tstr + 1;
2388 			termc = *cp;
2389 			break;
2390 		    }
2391 		    /*FALLTHRU*/
2392 		case 'T':
2393 		    if (tstr[1] == endc || tstr[1] == ':') {
2394 			newStr = VarModify (str, VarTail, (ClientData)0);
2395 			cp = tstr + 1;
2396 			termc = *cp;
2397 			break;
2398 		    }
2399 		    /*FALLTHRU*/
2400 		case 'H':
2401 		    if (tstr[1] == endc || tstr[1] == ':') {
2402 			newStr = VarModify (str, VarHead, (ClientData)0);
2403 			cp = tstr + 1;
2404 			termc = *cp;
2405 			break;
2406 		    }
2407 		    /*FALLTHRU*/
2408 		case 'E':
2409 		    if (tstr[1] == endc || tstr[1] == ':') {
2410 			newStr = VarModify (str, VarSuffix, (ClientData)0);
2411 			cp = tstr + 1;
2412 			termc = *cp;
2413 			break;
2414 		    }
2415 		    /*FALLTHRU*/
2416 		case 'R':
2417 		    if (tstr[1] == endc || tstr[1] == ':') {
2418 			newStr = VarModify (str, VarRoot, (ClientData)0);
2419 			cp = tstr + 1;
2420 			termc = *cp;
2421 			break;
2422 		    }
2423 		    /*FALLTHRU*/
2424 		case 'O':
2425 		    if (tstr[1] == endc || tstr[1] == ':') {
2426 			newStr = VarSort (str);
2427 			cp = tstr + 1;
2428 			termc = *cp;
2429 			break;
2430 		    }
2431 		    /*FALLTHRU*/
2432 		case 'u':
2433 		    if (tstr[1] == endc || tstr[1] == ':') {
2434 			newStr = VarUniq (str);
2435 			cp = tstr + 1;
2436 			termc = *cp;
2437 			break;
2438 		    }
2439 		    /*FALLTHRU*/
2440 #ifdef SUNSHCMD
2441 		case 's':
2442 		    if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
2443 			char *err;
2444 			newStr = Cmd_Exec (str, &err);
2445 			if (err)
2446 			    Error (err, str);
2447 			cp = tstr + 2;
2448 			termc = *cp;
2449 			break;
2450 		    }
2451 		    /*FALLTHRU*/
2452 #endif
2453                 default:
2454 		default_case:
2455 		{
2456 #ifdef SYSVVARSUB
2457 		    /*
2458 		     * This can either be a bogus modifier or a System-V
2459 		     * substitution command.
2460 		     */
2461 		    VarPattern      pattern;
2462 		    Boolean         eqFound;
2463 
2464 		    pattern.flags = 0;
2465 		    eqFound = FALSE;
2466 		    /*
2467 		     * First we make a pass through the string trying
2468 		     * to verify it is a SYSV-make-style translation:
2469 		     * it must be: <string1>=<string2>)
2470 		     */
2471 		    cp = tstr;
2472 		    cnt = 1;
2473 		    while (*cp != '\0' && cnt) {
2474 			if (*cp == '=') {
2475 			    eqFound = TRUE;
2476 			    /* continue looking for endc */
2477 			}
2478 			else if (*cp == endc)
2479 			    cnt--;
2480 			else if (*cp == startc)
2481 			    cnt++;
2482 			if (cnt)
2483 			    cp++;
2484 		    }
2485 		    if (*cp == endc && eqFound) {
2486 
2487 			/*
2488 			 * Now we break this sucker into the lhs and
2489 			 * rhs. We must null terminate them of course.
2490 			 */
2491 			for (cp = tstr; *cp != '='; cp++)
2492 			    continue;
2493 			pattern.lhs = tstr;
2494 			pattern.leftLen = cp - tstr;
2495 			*cp++ = '\0';
2496 
2497 			pattern.rhs = cp;
2498 			cnt = 1;
2499 			while (cnt) {
2500 			    if (*cp == endc)
2501 				cnt--;
2502 			    else if (*cp == startc)
2503 				cnt++;
2504 			    if (cnt)
2505 				cp++;
2506 			}
2507 			pattern.rightLen = cp - pattern.rhs;
2508 			*cp = '\0';
2509 
2510 			/*
2511 			 * SYSV modifications happen through the whole
2512 			 * string. Note the pattern is anchored at the end.
2513 			 */
2514 			newStr = VarModify(str, VarSYSVMatch,
2515 					   (ClientData)&pattern);
2516 
2517 			/*
2518 			 * Restore the nulled characters
2519 			 */
2520 			pattern.lhs[pattern.leftLen] = '=';
2521 			pattern.rhs[pattern.rightLen] = endc;
2522 			termc = endc;
2523 		    } else
2524 #endif
2525 		    {
2526 			Error ("Unknown modifier '%c'\n", *tstr);
2527 			for (cp = tstr+1;
2528 			     *cp != ':' && *cp != endc && *cp != '\0';
2529 			     cp++)
2530 				 continue;
2531 			termc = *cp;
2532 			newStr = var_Error;
2533 		    }
2534 		}
2535 	    }
2536 	    if (DEBUG(VAR)) {
2537 		printf("Result is \"%s\"\n", newStr);
2538 	    }
2539 
2540 	    if (newStr != str) {
2541 		if (*freePtr) {
2542 		    free (str);
2543 		}
2544 		str = newStr;
2545 		if (str != var_Error && str != varNoError) {
2546 		    *freePtr = TRUE;
2547 		} else {
2548 		    *freePtr = FALSE;
2549 		}
2550 	    }
2551 	    if (termc == '\0') {
2552 		Error("Unclosed variable specification for %s", v->name);
2553 	    } else if (termc == ':') {
2554 		*cp++ = termc;
2555 	    } else {
2556 		*cp = termc;
2557 	    }
2558 	    tstr = cp;
2559 	}
2560 	*lengthPtr = tstr - start + 1;
2561     } else {
2562 	*lengthPtr = tstr - start + 1;
2563 	*tstr = endc;
2564     }
2565 
2566     if (v->flags & VAR_FROM_ENV) {
2567 	Boolean	  destroy = FALSE;
2568 
2569 	if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) {
2570 	    destroy = TRUE;
2571 	} else {
2572 	    /*
2573 	     * Returning the value unmodified, so tell the caller to free
2574 	     * the thing.
2575 	     */
2576 	    *freePtr = TRUE;
2577 	}
2578 	Buf_Destroy(v->val, destroy);
2579 	free((Address)v->name);
2580 	free((Address)v);
2581     } else if (v->flags & VAR_JUNK) {
2582 	/*
2583 	 * Perform any free'ing needed and set *freePtr to FALSE so the caller
2584 	 * doesn't try to free a static pointer.
2585 	 * If VAR_KEEP is also set then we want to keep str as is.
2586 	 */
2587 	if (!(v->flags & VAR_KEEP)) {
2588 	    if (*freePtr) {
2589 		free(str);
2590 	    }
2591 	    *freePtr = FALSE;
2592 	    if (dynamic) {
2593 		str = emalloc(*lengthPtr + 1);
2594 		strncpy(str, start, *lengthPtr);
2595 		str[*lengthPtr] = '\0';
2596 		*freePtr = TRUE;
2597 	    } else {
2598 		str = var_Error;
2599 	    }
2600 	}
2601 	Buf_Destroy(v->val, TRUE);
2602 	free((Address)v->name);
2603 	free((Address)v);
2604     }
2605     return (str);
2606 
2607 cleanup:
2608     *lengthPtr = cp - start + 1;
2609     if (*freePtr)
2610 	free(str);
2611     if (delim != '\0')
2612 	Error("Unclosed substitution for %s (%c missing)",
2613 	      v->name, delim);
2614     return (var_Error);
2615 }
2616 
2617 /*-
2618  *-----------------------------------------------------------------------
2619  * Var_Subst  --
2620  *	Substitute for all variables in the given string in the given context
2621  *	If undefErr is TRUE, Parse_Error will be called when an undefined
2622  *	variable is encountered.
2623  *
2624  * Results:
2625  *	The resulting string.
2626  *
2627  * Side Effects:
2628  *	None. The old string must be freed by the caller
2629  *-----------------------------------------------------------------------
2630  */
2631 char *
2632 Var_Subst (var, str, ctxt, undefErr)
2633     char	  *var;		    /* Named variable || NULL for all */
2634     char 	  *str;	    	    /* the string in which to substitute */
2635     GNode         *ctxt;	    /* the context wherein to find variables */
2636     Boolean 	  undefErr; 	    /* TRUE if undefineds are an error */
2637 {
2638     Buffer  	  buf;	    	    /* Buffer for forming things */
2639     char    	  *val;		    /* Value to substitute for a variable */
2640     int	    	  length;   	    /* Length of the variable invocation */
2641     Boolean 	  doFree;   	    /* Set true if val should be freed */
2642     static Boolean errorReported;   /* Set true if an error has already
2643 				     * been reported to prevent a plethora
2644 				     * of messages when recursing */
2645 
2646     buf = Buf_Init (MAKE_BSIZE);
2647     errorReported = FALSE;
2648 
2649     while (*str) {
2650 	if (var == NULL && (*str == '$') && (str[1] == '$')) {
2651 	    /*
2652 	     * A dollar sign may be escaped either with another dollar sign.
2653 	     * In such a case, we skip over the escape character and store the
2654 	     * dollar sign into the buffer directly.
2655 	     */
2656 	    str++;
2657 	    Buf_AddByte(buf, (Byte)*str);
2658 	    str++;
2659 	} else if (*str != '$') {
2660 	    /*
2661 	     * Skip as many characters as possible -- either to the end of
2662 	     * the string or to the next dollar sign (variable invocation).
2663 	     */
2664 	    char  *cp;
2665 
2666 	    for (cp = str++; *str != '$' && *str != '\0'; str++)
2667 		continue;
2668 	    Buf_AddBytes(buf, str - cp, (Byte *)cp);
2669 	} else {
2670 	    if (var != NULL) {
2671 		int expand;
2672 		for (;;) {
2673 		    if (str[1] != '(' && str[1] != '{') {
2674 			if (str[1] != *var || strlen(var) > 1) {
2675 			    Buf_AddBytes(buf, 2, (Byte *) str);
2676 			    str += 2;
2677 			    expand = FALSE;
2678 			}
2679 			else
2680 			    expand = TRUE;
2681 			break;
2682 		    }
2683 		    else {
2684 			char *p;
2685 
2686 			/*
2687 			 * Scan up to the end of the variable name.
2688 			 */
2689 			for (p = &str[2]; *p &&
2690 			     *p != ':' && *p != ')' && *p != '}'; p++)
2691 			    if (*p == '$')
2692 				break;
2693 			/*
2694 			 * A variable inside the variable. We cannot expand
2695 			 * the external variable yet, so we try again with
2696 			 * the nested one
2697 			 */
2698 			if (*p == '$') {
2699 			    Buf_AddBytes(buf, p - str, (Byte *) str);
2700 			    str = p;
2701 			    continue;
2702 			}
2703 
2704 			if (strncmp(var, str + 2, p - str - 2) != 0 ||
2705 			    var[p - str - 2] != '\0') {
2706 			    /*
2707 			     * Not the variable we want to expand, scan
2708 			     * until the next variable
2709 			     */
2710 			    for (;*p != '$' && *p != '\0'; p++)
2711 				continue;
2712 			    Buf_AddBytes(buf, p - str, (Byte *) str);
2713 			    str = p;
2714 			    expand = FALSE;
2715 			}
2716 			else
2717 			    expand = TRUE;
2718 			break;
2719 		    }
2720 		}
2721 		if (!expand)
2722 		    continue;
2723 	    }
2724 
2725 	    val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
2726 
2727 	    /*
2728 	     * When we come down here, val should either point to the
2729 	     * value of this variable, suitably modified, or be NULL.
2730 	     * Length should be the total length of the potential
2731 	     * variable invocation (from $ to end character...)
2732 	     */
2733 	    if (val == var_Error || val == varNoError) {
2734 		/*
2735 		 * If performing old-time variable substitution, skip over
2736 		 * the variable and continue with the substitution. Otherwise,
2737 		 * store the dollar sign and advance str so we continue with
2738 		 * the string...
2739 		 */
2740 		if (oldVars) {
2741 		    str += length;
2742 		} else if (undefErr) {
2743 		    /*
2744 		     * If variable is undefined, complain and skip the
2745 		     * variable. The complaint will stop us from doing anything
2746 		     * when the file is parsed.
2747 		     */
2748 		    if (!errorReported) {
2749 			Parse_Error (PARSE_FATAL,
2750 				     "Undefined variable \"%.*s\"",length,str);
2751 		    }
2752 		    str += length;
2753 		    errorReported = TRUE;
2754 		} else {
2755 		    Buf_AddByte (buf, (Byte)*str);
2756 		    str += 1;
2757 		}
2758 	    } else {
2759 		/*
2760 		 * We've now got a variable structure to store in. But first,
2761 		 * advance the string pointer.
2762 		 */
2763 		str += length;
2764 
2765 		/*
2766 		 * Copy all the characters from the variable value straight
2767 		 * into the new string.
2768 		 */
2769 		Buf_AddBytes (buf, strlen (val), (Byte *)val);
2770 		if (doFree) {
2771 		    free ((Address)val);
2772 		}
2773 	    }
2774 	}
2775     }
2776 
2777     Buf_AddByte (buf, '\0');
2778     str = (char *)Buf_GetAll (buf, (int *)NULL);
2779     Buf_Destroy (buf, FALSE);
2780     return (str);
2781 }
2782 
2783 /*-
2784  *-----------------------------------------------------------------------
2785  * Var_GetTail --
2786  *	Return the tail from each of a list of words. Used to set the
2787  *	System V local variables.
2788  *
2789  * Results:
2790  *	The resulting string.
2791  *
2792  * Side Effects:
2793  *	None.
2794  *
2795  *-----------------------------------------------------------------------
2796  */
2797 char *
2798 Var_GetTail(file)
2799     char    	*file;	    /* Filename to modify */
2800 {
2801     return(VarModify(file, VarTail, (ClientData)0));
2802 }
2803 
2804 /*-
2805  *-----------------------------------------------------------------------
2806  * Var_GetHead --
2807  *	Find the leading components of a (list of) filename(s).
2808  *	XXX: VarHead does not replace foo by ., as (sun) System V make
2809  *	does.
2810  *
2811  * Results:
2812  *	The leading components.
2813  *
2814  * Side Effects:
2815  *	None.
2816  *
2817  *-----------------------------------------------------------------------
2818  */
2819 char *
2820 Var_GetHead(file)
2821     char    	*file;	    /* Filename to manipulate */
2822 {
2823     return(VarModify(file, VarHead, (ClientData)0));
2824 }
2825 
2826 /*-
2827  *-----------------------------------------------------------------------
2828  * Var_Init --
2829  *	Initialize the module
2830  *
2831  * Results:
2832  *	None
2833  *
2834  * Side Effects:
2835  *	The VAR_CMD and VAR_GLOBAL contexts are created
2836  *-----------------------------------------------------------------------
2837  */
2838 void
2839 Var_Init ()
2840 {
2841     VAR_GLOBAL = Targ_NewGN ("Global");
2842     VAR_CMD = Targ_NewGN ("Command");
2843 
2844 }
2845 
2846 
2847 void
2848 Var_End ()
2849 {
2850 }
2851 
2852 
2853 /****************** PRINT DEBUGGING INFO *****************/
2854 static void
2855 VarPrintVar (vp)
2856     ClientData vp;
2857 {
2858     Var    *v = (Var *) vp;
2859     printf ("%-16s = %s\n", v->name, (char *) Buf_GetAll(v->val, (int *)NULL));
2860 }
2861 
2862 /*-
2863  *-----------------------------------------------------------------------
2864  * Var_Dump --
2865  *	print all variables in a context
2866  *-----------------------------------------------------------------------
2867  */
2868 void
2869 Var_Dump (ctxt)
2870     GNode          *ctxt;
2871 {
2872     Hash_Search search;
2873     Hash_Entry *h;
2874 
2875     for (h = Hash_EnumFirst(&ctxt->context, &search);
2876 	 h != NULL;
2877 	 h = Hash_EnumNext(&search)) {
2878 	    VarPrintVar(Hash_GetValue(h));
2879     }
2880 }
2881