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