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