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