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