]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/make/var.c
This commit was generated by cvs2svn to compensate for changes in r108746,
[FreeBSD/FreeBSD.git] / usr.bin / make / var.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1989 by Berkeley Softworks
5  * 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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * @(#)var.c    8.3 (Berkeley) 3/19/94
39  */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 /*-
45  * var.c --
46  *      Variable-handling functions
47  *
48  * Interface:
49  *      Var_Set             Set the value of a variable in the given
50  *                          context. The variable is created if it doesn't
51  *                          yet exist. The value and variable name need not
52  *                          be preserved.
53  *
54  *      Var_Append          Append more characters to an existing variable
55  *                          in the given context. The variable needn't
56  *                          exist already -- it will be created if it doesn't.
57  *                          A space is placed between the old value and the
58  *                          new one.
59  *
60  *      Var_Exists          See if a variable exists.
61  *
62  *      Var_Value           Return the value of a variable in a context or
63  *                          NULL if the variable is undefined.
64  *
65  *      Var_Subst           Substitute named variable, or all variables if
66  *                          NULL in a string using
67  *                          the given context as the top-most one. If the
68  *                          third argument is non-zero, Parse_Error is
69  *                          called if any variables are undefined.
70  *
71  *      Var_Parse           Parse a variable expansion from a string and
72  *                          return the result and the number of characters
73  *                          consumed.
74  *
75  *      Var_Delete          Delete a variable in a context.
76  *
77  *      Var_Init            Initialize this module.
78  *
79  * Debugging:
80  *      Var_Dump            Print out all variables defined in the given
81  *                          context.
82  *
83  * XXX: There's a lot of duplication in these functions.
84  */
85
86 #include    <ctype.h>
87 #include    <sys/types.h>
88 #include    <regex.h>
89 #include    <stdlib.h>
90 #include    "make.h"
91 #include    "buf.h"
92 #include    "var.h"
93
94 /*
95  * This is a harmless return value for Var_Parse that can be used by Var_Subst
96  * to determine if there was an error in parsing -- easier than returning
97  * a flag, as things outside this module don't give a hoot.
98  */
99 char    var_Error[] = "";
100
101 /*
102  * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
103  * set false. Why not just use a constant? Well, gcc likes to condense
104  * identical string instances...
105  */
106 static char     varNoError[] = "";
107
108 /*
109  * Internally, variables are contained in four different contexts.
110  *      1) the environment. They may not be changed. If an environment
111  *          variable is appended-to, the result is placed in the global
112  *          context.
113  *      2) the global context. Variables set in the Makefile are located in
114  *          the global context. It is the penultimate context searched when
115  *          substituting.
116  *      3) the command-line context. All variables set on the command line
117  *         are placed in this context. They are UNALTERABLE once placed here.
118  *      4) the local context. Each target has associated with it a context
119  *         list. On this list are located the structures describing such
120  *         local variables as $(@) and $(*)
121  * The four contexts are searched in the reverse order from which they are
122  * listed.
123  */
124 GNode          *VAR_GLOBAL;   /* variables from the makefile */
125 GNode          *VAR_CMD;      /* variables defined on the command-line */
126
127 static Lst      allVars;      /* List of all variables */
128
129 #define FIND_CMD        0x1   /* look in VAR_CMD when searching */
130 #define FIND_GLOBAL     0x2   /* look in VAR_GLOBAL as well */
131 #define FIND_ENV        0x4   /* look in the environment also */
132
133 static int VarCmp(void *, void *);
134 static void VarPossiblyExpand(char **, GNode *);
135 static Var *VarFind(char *, GNode *, int);
136 static void VarAdd(char *, char *, GNode *);
137 static void VarDelete(void *);
138 static char *VarGetPattern(GNode *, int, char **, int, int *, int *, 
139                            VarPattern *);
140 static char *VarQuote(const char *);
141 static char *VarModify(char *,
142                        Boolean (*)(const char *, Boolean, Buffer, void *),
143                        void *);
144 static int VarPrintVar(void *, void *);
145
146 /*-
147  *-----------------------------------------------------------------------
148  * VarCmp  --
149  *      See if the given variable matches the named one. Called from
150  *      Lst_Find when searching for a variable of a given name.
151  *
152  * Results:
153  *      0 if they match. non-zero otherwise.
154  *
155  * Side Effects:
156  *      none
157  *-----------------------------------------------------------------------
158  */
159 static int
160 VarCmp (void *v, void *name)
161 {
162     return (strcmp ((char *) name, ((Var *) v)->name));
163 }
164
165 /*-
166  *-----------------------------------------------------------------------
167  * VarPossiblyExpand --
168  *      Expand a variable name's embedded variables in the given context.
169  *
170  * Results:
171  *      The contents of name, possibly expanded.
172  *
173  * Side Effects:
174  *      The caller must free the new contents or old contents of name.
175  *-----------------------------------------------------------------------
176  */
177 static void
178 VarPossiblyExpand(char **name, GNode *ctxt)
179 {
180     if (strchr(*name, '$') != NULL)
181         *name = Var_Subst(NULL, *name, ctxt, 0);
182     else
183         *name = estrdup(*name);
184 }
185
186 /*-
187  *-----------------------------------------------------------------------
188  * VarFind --
189  *      Find the given variable in the given context and any other contexts
190  *      indicated.
191  *
192  *      Flags:
193  *              FIND_GLOBAL     set means look in the VAR_GLOBAL context too
194  *              FIND_CMD        set means to look in the VAR_CMD context too
195  *              FIND_ENV        set means to look in the environment
196  *
197  * Results:
198  *      A pointer to the structure describing the desired variable or
199  *      NULL if the variable does not exist.
200  *
201  * Side Effects:
202  *      None
203  *-----------------------------------------------------------------------
204  */
205 static Var *
206 VarFind (char *name, GNode *ctxt, int flags)
207 {
208     Boolean             localCheckEnvFirst;
209     LstNode             var;
210     Var                 *v;
211
212         /*
213          * If the variable name begins with a '.', it could very well be one of
214          * the local ones.  We check the name against all the local variables
215          * and substitute the short version in for 'name' if it matches one of
216          * them.
217          */
218         if (*name == '.' && isupper((unsigned char) name[1]))
219                 switch (name[1]) {
220                 case 'A':
221                         if (!strcmp(name, ".ALLSRC"))
222                                 name = ALLSRC;
223                         if (!strcmp(name, ".ARCHIVE"))
224                                 name = ARCHIVE;
225                         break;
226                 case 'I':
227                         if (!strcmp(name, ".IMPSRC"))
228                                 name = IMPSRC;
229                         break;
230                 case 'M':
231                         if (!strcmp(name, ".MEMBER"))
232                                 name = MEMBER;
233                         break;
234                 case 'O':
235                         if (!strcmp(name, ".OODATE"))
236                                 name = OODATE;
237                         break;
238                 case 'P':
239                         if (!strcmp(name, ".PREFIX"))
240                                 name = PREFIX;
241                         break;
242                 case 'T':
243                         if (!strcmp(name, ".TARGET"))
244                                 name = TARGET;
245                         break;
246                 }
247
248     /*
249      * Note whether this is one of the specific variables we were told through
250      * the -E flag to use environment-variable-override for.
251      */
252     if (Lst_Find (envFirstVars, (void *)name,
253                   (int (*)(void *, void *)) strcmp) != NULL)
254     {
255         localCheckEnvFirst = TRUE;
256     } else {
257         localCheckEnvFirst = FALSE;
258     }
259
260     /*
261      * First look for the variable in the given context. If it's not there,
262      * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
263      * depending on the FIND_* flags in 'flags'
264      */
265     var = Lst_Find (ctxt->context, (void *)name, VarCmp);
266
267     if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
268         var = Lst_Find (VAR_CMD->context, (void *)name, VarCmp);
269     }
270     if ((var == NULL) && (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL) &&
271         !checkEnvFirst && !localCheckEnvFirst)
272     {
273         var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp);
274     }
275     if ((var == NULL) && (flags & FIND_ENV)) {
276         char *env;
277
278         if ((env = getenv (name)) != NULL) {
279             int         len;
280
281             v = (Var *) emalloc(sizeof(Var));
282             v->name = estrdup(name);
283
284             len = strlen(env);
285
286             v->val = Buf_Init(len);
287             Buf_AddBytes(v->val, len, (Byte *)env);
288
289             v->flags = VAR_FROM_ENV;
290             return (v);
291         } else if ((checkEnvFirst || localCheckEnvFirst) &&
292                    (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL))
293         {
294             var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp);
295             if (var == NULL) {
296                 return ((Var *) NULL);
297             } else {
298                 return ((Var *)Lst_Datum(var));
299             }
300         } else {
301             return((Var *)NULL);
302         }
303     } else if (var == NULL) {
304         return ((Var *) NULL);
305     } else {
306         return ((Var *) Lst_Datum (var));
307     }
308 }
309
310 /*-
311  *-----------------------------------------------------------------------
312  * VarAdd  --
313  *      Add a new variable of name name and value val to the given context.
314  *
315  * Results:
316  *      None
317  *
318  * Side Effects:
319  *      The new variable is placed at the front of the given context
320  *      The name and val arguments are duplicated so they may
321  *      safely be freed.
322  *-----------------------------------------------------------------------
323  */
324 static void
325 VarAdd (char *name, char *val, GNode *ctxt)
326 {
327     Var           *v;
328     int           len;
329
330     v = (Var *) emalloc (sizeof (Var));
331
332     v->name = estrdup (name);
333
334     len = val ? strlen(val) : 0;
335     v->val = Buf_Init(len+1);
336     Buf_AddBytes(v->val, len, (Byte *)val);
337
338     v->flags = 0;
339
340     (void) Lst_AtFront (ctxt->context, (void *)v);
341     (void) Lst_AtEnd (allVars, (void *) v);
342     DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val));
343 }
344
345
346 /*-
347  *-----------------------------------------------------------------------
348  * VarDelete  --
349  *      Delete a variable and all the space associated with it.
350  *
351  * Results:
352  *      None
353  *
354  * Side Effects:
355  *      None
356  *-----------------------------------------------------------------------
357  */
358 static void
359 VarDelete(void *vp)
360 {
361     Var *v = (Var *) vp;
362     free(v->name);
363     Buf_Destroy(v->val, TRUE);
364     free(v);
365 }
366
367
368
369 /*-
370  *-----------------------------------------------------------------------
371  * Var_Delete --
372  *      Remove a variable from a context.
373  *
374  * Results:
375  *      None.
376  *
377  * Side Effects:
378  *      The Var structure is removed and freed.
379  *
380  *-----------------------------------------------------------------------
381  */
382 void
383 Var_Delete(char *name, GNode *ctxt)
384 {
385     LstNode       ln;
386
387     DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name));
388     ln = Lst_Find(ctxt->context, (void *)name, VarCmp);
389     if (ln != NULL) {
390         Var       *v;
391
392         v = (Var *)Lst_Datum(ln);
393         Lst_Remove(ctxt->context, ln);
394         ln = Lst_Member(allVars, v);
395         Lst_Remove(allVars, ln);
396         VarDelete((void *) v);
397     }
398 }
399
400 /*-
401  *-----------------------------------------------------------------------
402  * Var_Set --
403  *      Set the variable name to the value val in the given context.
404  *
405  * Results:
406  *      None.
407  *
408  * Side Effects:
409  *      If the variable doesn't yet exist, a new record is created for it.
410  *      Else the old value is freed and the new one stuck in its place
411  *
412  * Notes:
413  *      The variable is searched for only in its context before being
414  *      created in that context. I.e. if the context is VAR_GLOBAL,
415  *      only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
416  *      VAR_CMD->context is searched. This is done to avoid the literally
417  *      thousands of unnecessary strcmp's that used to be done to
418  *      set, say, $(@) or $(<).
419  *-----------------------------------------------------------------------
420  */
421 void
422 Var_Set (char *name, char *val, GNode *ctxt)
423 {
424     Var            *v;
425
426     /*
427      * We only look for a variable in the given context since anything set
428      * here will override anything in a lower context, so there's not much
429      * point in searching them all just to save a bit of memory...
430      */
431     VarPossiblyExpand(&name, ctxt);
432     v = VarFind (name, ctxt, 0);
433     if (v == (Var *) NULL) {
434         VarAdd (name, val, ctxt);
435     } else {
436         Buf_Discard(v->val, Buf_Size(v->val));
437         Buf_AddBytes(v->val, strlen(val), (Byte *)val);
438
439         DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val));
440     }
441     /*
442      * Any variables given on the command line are automatically exported
443      * to the environment (as per POSIX standard)
444      */
445     if (ctxt == VAR_CMD) {
446         setenv(name, val, 1);
447     }
448     free(name);
449 }
450
451 /*-
452  *-----------------------------------------------------------------------
453  * Var_Append --
454  *      The variable of the given name has the given value appended to it in
455  *      the given context.
456  *
457  * Results:
458  *      None
459  *
460  * Side Effects:
461  *      If the variable doesn't exist, it is created. Else the strings
462  *      are concatenated (with a space in between).
463  *
464  * Notes:
465  *      Only if the variable is being sought in the global context is the
466  *      environment searched.
467  *      XXX: Knows its calling circumstances in that if called with ctxt
468  *      an actual target, it will only search that context since only
469  *      a local variable could be being appended to. This is actually
470  *      a big win and must be tolerated.
471  *-----------------------------------------------------------------------
472  */
473 void
474 Var_Append (char *name, char *val, GNode *ctxt)
475 {
476     Var            *v;
477
478     VarPossiblyExpand(&name, ctxt);
479     v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
480
481     if (v == (Var *) NULL) {
482         VarAdd (name, val, ctxt);
483     } else {
484         Buf_AddByte(v->val, (Byte)' ');
485         Buf_AddBytes(v->val, strlen(val), (Byte *)val);
486
487         DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, 
488                (char *) Buf_GetAll(v->val, (int *)NULL)));
489
490         if (v->flags & VAR_FROM_ENV) {
491             /*
492              * If the original variable came from the environment, we
493              * have to install it in the global context (we could place
494              * it in the environment, but then we should provide a way to
495              * export other variables...)
496              */
497             v->flags &= ~VAR_FROM_ENV;
498             Lst_AtFront(ctxt->context, (void *)v);
499         }
500     }
501     free(name);
502 }
503
504 /*-
505  *-----------------------------------------------------------------------
506  * Var_Exists --
507  *      See if the given variable exists.
508  *
509  * Results:
510  *      TRUE if it does, FALSE if it doesn't
511  *
512  * Side Effects:
513  *      None.
514  *
515  *-----------------------------------------------------------------------
516  */
517 Boolean
518 Var_Exists(char *name, GNode *ctxt)
519 {
520     Var           *v;
521
522     VarPossiblyExpand(&name, ctxt);
523     v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
524     free(name);
525
526     if (v == (Var *)NULL) {
527         return(FALSE);
528     } else if (v->flags & VAR_FROM_ENV) {
529         free(v->name);
530         Buf_Destroy(v->val, TRUE);
531         free((char *)v);
532     }
533     return(TRUE);
534 }
535
536 /*-
537  *-----------------------------------------------------------------------
538  * Var_Value --
539  *      Return the value of the named variable in the given context
540  *
541  * Results:
542  *      The value if the variable exists, NULL if it doesn't
543  *
544  * Side Effects:
545  *      None
546  *-----------------------------------------------------------------------
547  */
548 char *
549 Var_Value (char *name, GNode *ctxt, char **frp)
550 {
551     Var            *v;
552
553     VarPossiblyExpand(&name, ctxt);
554     v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
555     free(name);
556     *frp = NULL;
557     if (v != (Var *) NULL) {
558         char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
559         if (v->flags & VAR_FROM_ENV) {
560             Buf_Destroy(v->val, FALSE);
561             free(v);
562             *frp = p;
563         }
564         return p;
565     } else {
566         return ((char *) NULL);
567     }
568 }
569
570 /*-
571  *-----------------------------------------------------------------------
572  * VarModify --
573  *      Modify each of the words of the passed string using the given
574  *      function. Used to implement all modifiers.
575  *
576  * Results:
577  *      A string of all the words modified appropriately.
578  *
579  * Side Effects:
580  *      None.
581  *
582  *-----------------------------------------------------------------------
583  */
584 static char *
585 VarModify (char *str, Boolean (*modProc)(const char *, Boolean, Buffer, void *),
586     void *datum)
587 {
588     Buffer        buf;              /* Buffer for the new string */
589     Boolean       addSpace;         /* TRUE if need to add a space to the
590                                      * buffer before adding the trimmed
591                                      * word */
592     char **av;                      /* word list [first word does not count] */
593     int ac, i;
594
595     buf = Buf_Init (0);
596     addSpace = FALSE;
597
598     av = brk_string(str, &ac, FALSE);
599
600     for (i = 1; i < ac; i++)
601         addSpace = (*modProc)(av[i], addSpace, buf, datum);
602
603     Buf_AddByte (buf, '\0');
604     str = (char *)Buf_GetAll (buf, (int *)NULL);
605     Buf_Destroy (buf, FALSE);
606     return (str);
607 }
608
609 /*-
610  *-----------------------------------------------------------------------
611  * VarGetPattern --
612  *      Pass through the tstr looking for 1) escaped delimiters,
613  *      '$'s and backslashes (place the escaped character in
614  *      uninterpreted) and 2) unescaped $'s that aren't before
615  *      the delimiter (expand the variable substitution unless flags
616  *      has VAR_NOSUBST set).
617  *      Return the expanded string or NULL if the delimiter was missing
618  *      If pattern is specified, handle escaped ampersands, and replace
619  *      unescaped ampersands with the lhs of the pattern.
620  *
621  * Results:
622  *      A string of all the words modified appropriately.
623  *      If length is specified, return the string length of the buffer
624  *      If flags is specified and the last character of the pattern is a
625  *      $ set the VAR_MATCH_END bit of flags.
626  *
627  * Side Effects:
628  *      None.
629  *-----------------------------------------------------------------------
630  */
631 static char *
632 VarGetPattern(GNode *ctxt, int err, char **tstr, int delim, int *flags,
633     int *length, VarPattern *pattern)
634 {
635     char *cp;
636     Buffer buf = Buf_Init(0);
637     int junk;
638     if (length == NULL)
639         length = &junk;
640
641 #define IS_A_MATCH(cp, delim) \
642     ((cp[0] == '\\') && ((cp[1] == delim) ||  \
643      (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
644
645     /*
646      * Skim through until the matching delimiter is found;
647      * pick up variable substitutions on the way. Also allow
648      * backslashes to quote the delimiter, $, and \, but don't
649      * touch other backslashes.
650      */
651     for (cp = *tstr; *cp && (*cp != delim); cp++) {
652         if (IS_A_MATCH(cp, delim)) {
653             Buf_AddByte(buf, (Byte) cp[1]);
654             cp++;
655         } else if (*cp == '$') {
656             if (cp[1] == delim) {
657                 if (flags == NULL)
658                     Buf_AddByte(buf, (Byte) *cp);
659                 else
660                     /*
661                      * Unescaped $ at end of pattern => anchor
662                      * pattern at end.
663                      */
664                     *flags |= VAR_MATCH_END;
665             } else {
666                 if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
667                     char   *cp2;
668                     int     len;
669                     Boolean freeIt;
670
671                     /*
672                      * If unescaped dollar sign not before the
673                      * delimiter, assume it's a variable
674                      * substitution and recurse.
675                      */
676                     cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
677                     Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
678                     if (freeIt)
679                         free(cp2);
680                     cp += len - 1;
681                 } else {
682                     char *cp2 = &cp[1];
683
684                     if (*cp2 == '(' || *cp2 == '{') {
685                         /*
686                          * Find the end of this variable reference
687                          * and suck it in without further ado.
688                          * It will be interperated later.
689                          */
690                         int have = *cp2;
691                         int want = (*cp2 == '(') ? ')' : '}';
692                         int depth = 1;
693
694                         for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
695                             if (cp2[-1] != '\\') {
696                                 if (*cp2 == have)
697                                     ++depth;
698                                 if (*cp2 == want)
699                                     --depth;
700                             }
701                         }
702                         Buf_AddBytes(buf, cp2 - cp, (Byte *)cp);
703                         cp = --cp2;
704                     } else
705                         Buf_AddByte(buf, (Byte) *cp);
706                 }
707             }
708         }
709         else if (pattern && *cp == '&')
710             Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs);
711         else
712             Buf_AddByte(buf, (Byte) *cp);
713     }
714
715     Buf_AddByte(buf, (Byte) '\0');
716
717     if (*cp != delim) {
718         *tstr = cp;
719         *length = 0;
720         return NULL;
721     }
722     else {
723         *tstr = ++cp;
724         cp = (char *) Buf_GetAll(buf, length);
725         *length -= 1;   /* Don't count the NULL */
726         Buf_Destroy(buf, FALSE);
727         return cp;
728     }
729 }
730
731
732 /*-
733  *-----------------------------------------------------------------------
734  * VarQuote --
735  *      Quote shell meta-characters in the string
736  *
737  * Results:
738  *      The quoted string
739  *
740  * Side Effects:
741  *      None.
742  *
743  *-----------------------------------------------------------------------
744  */
745 static char *
746 VarQuote(const char *str)
747 {
748
749     Buffer        buf;
750     /* This should cover most shells :-( */
751     static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
752     char          *ret;
753
754     buf = Buf_Init (MAKE_BSIZE);
755     for (; *str; str++) {
756         if (strchr(meta, *str) != NULL)
757             Buf_AddByte(buf, (Byte)'\\');
758         Buf_AddByte(buf, (Byte)*str);
759     }
760     Buf_AddByte(buf, (Byte) '\0');
761     ret = Buf_GetAll (buf, NULL);
762     Buf_Destroy (buf, FALSE);
763     return ret;
764 }
765
766 /*-
767  *-----------------------------------------------------------------------
768  * VarREError --
769  *      Print the error caused by a regcomp or regexec call.
770  *
771  * Results:
772  *      None.
773  *
774  * Side Effects:
775  *      An error gets printed.
776  *
777  *-----------------------------------------------------------------------
778  */
779 void
780 VarREError(int err, regex_t *pat, const char *str)
781 {
782     char *errbuf;
783     int errlen;
784
785     errlen = regerror(err, pat, 0, 0);
786     errbuf = emalloc(errlen);
787     regerror(err, pat, errbuf, errlen);
788     Error("%s: %s", str, errbuf);
789     free(errbuf);
790 }
791
792
793 /*-
794  *-----------------------------------------------------------------------
795  * Var_Parse --
796  *      Given the start of a variable invocation, extract the variable
797  *      name and find its value, then modify it according to the
798  *      specification.
799  *
800  * Results:
801  *      The (possibly-modified) value of the variable or var_Error if the
802  *      specification is invalid. The length of the specification is
803  *      placed in *lengthPtr (for invalid specifications, this is just
804  *      2...?).
805  *      A Boolean in *freePtr telling whether the returned string should
806  *      be freed by the caller.
807  *
808  * Side Effects:
809  *      None.
810  *
811  *-----------------------------------------------------------------------
812  */
813 char *
814 Var_Parse(char *str, GNode *ctxt, Boolean err, int *lengthPtr, Boolean *freePtr)
815 {
816     char            *tstr;      /* Pointer into str */
817     Var             *v;         /* Variable in invocation */
818     char            *cp;        /* Secondary pointer into str (place marker
819                                  * for tstr) */
820     Boolean         haveModifier;/* TRUE if have modifiers for the variable */
821     char            endc;       /* Ending character when variable in parens
822                                  * or braces */
823     char            startc=0;   /* Starting character when variable in parens
824                                  * or braces */
825     int             cnt;        /* Used to count brace pairs when variable in
826                                  * in parens or braces */
827     char            *start;
828     char             delim;
829     Boolean         dynamic;    /* TRUE if the variable is local and we're
830                                  * expanding it in a non-local context. This
831                                  * is done to support dynamic sources. The
832                                  * result is just the invocation, unaltered */
833     int         vlen;           /* length of variable name, after embedded variable
834                                  * expansion */
835
836     *freePtr = FALSE;
837     dynamic = FALSE;
838     start = str;
839
840     if (str[1] != '(' && str[1] != '{') {
841         /*
842          * If it's not bounded by braces of some sort, life is much simpler.
843          * We just need to check for the first character and return the
844          * value if it exists.
845          */
846         char      name[2];
847
848         name[0] = str[1];
849         name[1] = '\0';
850
851         v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
852         if (v == (Var *)NULL) {
853             *lengthPtr = 2;
854
855             if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
856                 /*
857                  * If substituting a local variable in a non-local context,
858                  * assume it's for dynamic source stuff. We have to handle
859                  * this specially and return the longhand for the variable
860                  * with the dollar sign escaped so it makes it back to the
861                  * caller. Only four of the local variables are treated
862                  * specially as they are the only four that will be set
863                  * when dynamic sources are expanded.
864                  */
865                 /* XXX: It looks like $% and $! are reversed here */
866                 switch (str[1]) {
867                     case '@':
868                         return("$(.TARGET)");
869                     case '%':
870                         return("$(.ARCHIVE)");
871                     case '*':
872                         return("$(.PREFIX)");
873                     case '!':
874                         return("$(.MEMBER)");
875                     default:
876                         break;
877                 }
878             }
879             /*
880              * Error
881              */
882             return (err ? var_Error : varNoError);
883         } else {
884             haveModifier = FALSE;
885             tstr = &str[1];
886             endc = str[1];
887         }
888     } else {
889         /* build up expanded variable name in this buffer */
890         Buffer  buf = Buf_Init(MAKE_BSIZE);
891
892         startc = str[1];
893         endc = startc == '(' ? ')' : '}';
894
895         /*
896          * Skip to the end character or a colon, whichever comes first,
897          * replacing embedded variables as we go.
898          */
899         for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++)
900                 if (*tstr == '$') {
901                         int     rlen;
902                         Boolean rfree;
903                         char*   rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
904                 
905                         if (rval == var_Error) {
906                                 Fatal("Error expanding embedded variable.");
907                         } else if (rval != NULL) {
908                                 Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
909                                 if (rfree)
910                                         free(rval);
911                         }
912                         tstr += rlen - 1;
913                 } else
914                         Buf_AddByte(buf, (Byte) *tstr);
915         
916         if (*tstr == '\0') {
917             /*
918              * If we never did find the end character, return NULL
919              * right now, setting the length to be the distance to
920              * the end of the string, since that's what make does.
921              */
922             *lengthPtr = tstr - str;
923             return (var_Error);
924         }
925         
926         haveModifier = (*tstr == ':');
927         *tstr = '\0';
928
929         Buf_AddByte(buf, (Byte) '\0');
930         str = Buf_GetAll(buf, NULL);
931         vlen = strlen(str);
932
933         v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
934         if ((v == (Var *)NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
935             (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
936         {
937             /*
938              * Check for bogus D and F forms of local variables since we're
939              * in a local context and the name is the right length.
940              */
941             switch(str[0]) {
942                 case '@':
943                 case '%':
944                 case '*':
945                 case '!':
946                 case '>':
947                 case '<':
948                 {
949                     char    vname[2];
950                     char    *val;
951
952                     /*
953                      * Well, it's local -- go look for it.
954                      */
955                     vname[0] = str[0];
956                     vname[1] = '\0';
957                     v = VarFind(vname, ctxt, 0);
958
959                     if (v != (Var *)NULL && !haveModifier) {
960                         /*
961                          * No need for nested expansion or anything, as we're
962                          * the only one who sets these things and we sure don't
963                          * put nested invocations in them...
964                          */
965                         val = (char *)Buf_GetAll(v->val, (int *)NULL);
966
967                         if (str[1] == 'D') {
968                             val = VarModify(val, VarHead, (void *)0);
969                         } else {
970                             val = VarModify(val, VarTail, (void *)0);
971                         }
972                         /*
973                          * Resulting string is dynamically allocated, so
974                          * tell caller to free it.
975                          */
976                         *freePtr = TRUE;
977                         *lengthPtr = tstr-start+1;
978                         *tstr = endc;
979                         Buf_Destroy(buf, TRUE);
980                         return(val);
981                     }
982                     break;
983                 default:
984                     break;
985                 }
986             }
987         }
988
989         if (v == (Var *)NULL) {
990             if (((vlen == 1) ||
991                  (((vlen == 2) && (str[1] == 'F' ||
992                                          str[1] == 'D')))) &&
993                 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
994             {
995                 /*
996                  * If substituting a local variable in a non-local context,
997                  * assume it's for dynamic source stuff. We have to handle
998                  * this specially and return the longhand for the variable
999                  * with the dollar sign escaped so it makes it back to the
1000                  * caller. Only four of the local variables are treated
1001                  * specially as they are the only four that will be set
1002                  * when dynamic sources are expanded.
1003                  */
1004                 switch (str[0]) {
1005                     case '@':
1006                     case '%':
1007                     case '*':
1008                     case '!':
1009                         dynamic = TRUE;
1010                         break;
1011                     default:
1012                         break;
1013                 }
1014             } else if ((vlen > 2) && (str[0] == '.') &&
1015                        isupper((unsigned char) str[1]) &&
1016                        ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
1017             {
1018                 int     len;
1019
1020                 len = vlen - 1;
1021                 if ((strncmp(str, ".TARGET", len) == 0) ||
1022                     (strncmp(str, ".ARCHIVE", len) == 0) ||
1023                     (strncmp(str, ".PREFIX", len) == 0) ||
1024                     (strncmp(str, ".MEMBER", len) == 0))
1025                 {
1026                     dynamic = TRUE;
1027                 }
1028             }
1029
1030             if (!haveModifier) {
1031                 /*
1032                  * No modifiers -- have specification length so we can return
1033                  * now.
1034                  */
1035                 *lengthPtr = tstr - start + 1;
1036                 *tstr = endc;
1037                 if (dynamic) {
1038                     str = emalloc(*lengthPtr + 1);
1039                     strncpy(str, start, *lengthPtr);
1040                     str[*lengthPtr] = '\0';
1041                     *freePtr = TRUE;
1042                     Buf_Destroy(buf, TRUE);
1043                     return(str);
1044                 } else {
1045                     Buf_Destroy(buf, TRUE);
1046                     return (err ? var_Error : varNoError);
1047                 }
1048             } else {
1049                 /*
1050                  * Still need to get to the end of the variable specification,
1051                  * so kludge up a Var structure for the modifications
1052                  */
1053                 v = (Var *) emalloc(sizeof(Var));
1054                 v->name = estrdup(str);
1055                 v->val = Buf_Init(1);
1056                 v->flags = VAR_JUNK;
1057             }
1058         }
1059         Buf_Destroy(buf, TRUE);
1060     }
1061
1062     if (v->flags & VAR_IN_USE) {
1063         Fatal("Variable %s is recursive.", v->name);
1064         /*NOTREACHED*/
1065     } else {
1066         v->flags |= VAR_IN_USE;
1067     }
1068     /*
1069      * Before doing any modification, we have to make sure the value
1070      * has been fully expanded. If it looks like recursion might be
1071      * necessary (there's a dollar sign somewhere in the variable's value)
1072      * we just call Var_Subst to do any other substitutions that are
1073      * necessary. Note that the value returned by Var_Subst will have
1074      * been dynamically-allocated, so it will need freeing when we
1075      * return.
1076      */
1077     str = (char *)Buf_GetAll(v->val, (int *)NULL);
1078     if (strchr (str, '$') != (char *)NULL) {
1079         str = Var_Subst(NULL, str, ctxt, err);
1080         *freePtr = TRUE;
1081     }
1082
1083     v->flags &= ~VAR_IN_USE;
1084
1085     /*
1086      * Now we need to apply any modifiers the user wants applied.
1087      * These are:
1088      *            :M<pattern>   words which match the given <pattern>.
1089      *                          <pattern> is of the standard file
1090      *                          wildcarding form.
1091      *            :S<d><pat1><d><pat2><d>[g]
1092      *                          Substitute <pat2> for <pat1> in the value
1093      *            :C<d><pat1><d><pat2><d>[g]
1094      *                          Substitute <pat2> for regex <pat1> in the value
1095      *            :H            Substitute the head of each word
1096      *            :T            Substitute the tail of each word
1097      *            :E            Substitute the extension (minus '.') of
1098      *                          each word
1099      *            :R            Substitute the root of each word
1100      *                          (pathname minus the suffix).
1101      *            :lhs=rhs      Like :S, but the rhs goes to the end of
1102      *                          the invocation.
1103      *            :U            Converts variable to upper-case.
1104      *            :L            Converts variable to lower-case.
1105      */
1106     if ((str != (char *)NULL) && haveModifier) {
1107         /*
1108          * Skip initial colon while putting it back.
1109          */
1110         *tstr++ = ':';
1111         while (*tstr != endc) {
1112             char        *newStr;    /* New value to return */
1113             char        termc;      /* Character which terminated scan */
1114
1115             DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *tstr, str));
1116             switch (*tstr) {
1117                 case 'U':
1118                         if (tstr[1] == endc || tstr[1] == ':') {
1119                                 Buffer buf;
1120                                 buf = Buf_Init(MAKE_BSIZE);
1121                                 for (cp = str; *cp ; cp++)
1122                                         Buf_AddByte(buf, (Byte) toupper(*cp));
1123
1124                                 Buf_AddByte(buf, (Byte) '\0');
1125                                 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
1126                                 Buf_Destroy(buf, FALSE);
1127
1128                                 cp = tstr + 1;
1129                                 termc = *cp;
1130                                 break;
1131                         }
1132                         /* FALLTHROUGH */
1133                 case 'L':
1134                         if (tstr[1] == endc || tstr[1] == ':') {
1135                                 Buffer buf;
1136                                 buf = Buf_Init(MAKE_BSIZE);
1137                                 for (cp = str; *cp ; cp++)
1138                                         Buf_AddByte(buf, (Byte) tolower(*cp));
1139
1140                                 Buf_AddByte(buf, (Byte) '\0');
1141                                 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
1142                                 Buf_Destroy(buf, FALSE);
1143
1144                                 cp = tstr + 1;
1145                                 termc = *cp;
1146                                 break;
1147                         }
1148                         /* FALLTHROUGH */
1149                 case 'N':
1150                 case 'M':
1151                 {
1152                     char    *pattern;
1153                     char    *cp2;
1154                     Boolean copy;
1155
1156                     copy = FALSE;
1157                     for (cp = tstr + 1;
1158                          *cp != '\0' && *cp != ':' && *cp != endc;
1159                          cp++)
1160                     {
1161                         if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){
1162                             copy = TRUE;
1163                             cp++;
1164                         }
1165                     }
1166                     termc = *cp;
1167                     *cp = '\0';
1168                     if (copy) {
1169                         /*
1170                          * Need to compress the \:'s out of the pattern, so
1171                          * allocate enough room to hold the uncompressed
1172                          * pattern (note that cp started at tstr+1, so
1173                          * cp - tstr takes the null byte into account) and
1174                          * compress the pattern into the space.
1175                          */
1176                         pattern = emalloc(cp - tstr);
1177                         for (cp2 = pattern, cp = tstr + 1;
1178                              *cp != '\0';
1179                              cp++, cp2++)
1180                         {
1181                             if ((*cp == '\\') &&
1182                                 (cp[1] == ':' || cp[1] == endc)) {
1183                                     cp++;
1184                             }
1185                             *cp2 = *cp;
1186                         }
1187                         *cp2 = '\0';
1188                     } else {
1189                         pattern = &tstr[1];
1190                     }
1191                     if (*tstr == 'M' || *tstr == 'm') {
1192                         newStr = VarModify(str, VarMatch, (void *)pattern);
1193                     } else {
1194                         newStr = VarModify(str, VarNoMatch,
1195                                            (void *)pattern);
1196                     }
1197                     if (copy) {
1198                         free(pattern);
1199                     }
1200                     break;
1201                 }
1202                 case 'S':
1203                 {
1204                     VarPattern      pattern;
1205                     char            del;
1206                     Buffer          buf;        /* Buffer for patterns */
1207
1208                     pattern.flags = 0;
1209                     del = tstr[1];
1210                     tstr += 2;
1211
1212                     /*
1213                      * If pattern begins with '^', it is anchored to the
1214                      * start of the word -- skip over it and flag pattern.
1215                      */
1216                     if (*tstr == '^') {
1217                         pattern.flags |= VAR_MATCH_START;
1218                         tstr += 1;
1219                     }
1220
1221                     buf = Buf_Init(0);
1222
1223                     /*
1224                      * Pass through the lhs looking for 1) escaped delimiters,
1225                      * '$'s and backslashes (place the escaped character in
1226                      * uninterpreted) and 2) unescaped $'s that aren't before
1227                      * the delimiter (expand the variable substitution).
1228                      * The result is left in the Buffer buf.
1229                      */
1230                     for (cp = tstr; *cp != '\0' && *cp != del; cp++) {
1231                         if ((*cp == '\\') &&
1232                             ((cp[1] == del) ||
1233                              (cp[1] == '$') ||
1234                              (cp[1] == '\\')))
1235                         {
1236                             Buf_AddByte(buf, (Byte)cp[1]);
1237                             cp++;
1238                         } else if (*cp == '$') {
1239                             if (cp[1] != del) {
1240                                 /*
1241                                  * If unescaped dollar sign not before the
1242                                  * delimiter, assume it's a variable
1243                                  * substitution and recurse.
1244                                  */
1245                                 char        *cp2;
1246                                 int         len;
1247                                 Boolean     freeIt;
1248
1249                                 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1250                                 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
1251                                 if (freeIt) {
1252                                     free(cp2);
1253                                 }
1254                                 cp += len - 1;
1255                             } else {
1256                                 /*
1257                                  * Unescaped $ at end of pattern => anchor
1258                                  * pattern at end.
1259                                  */
1260                                 pattern.flags |= VAR_MATCH_END;
1261                             }
1262                         } else {
1263                             Buf_AddByte(buf, (Byte)*cp);
1264                         }
1265                     }
1266
1267                     Buf_AddByte(buf, (Byte)'\0');
1268
1269                     /*
1270                      * If lhs didn't end with the delimiter, complain and
1271                      * exit.
1272                      */
1273                     if (*cp != del) {
1274                         Fatal("Unclosed substitution for %s (%c missing)",
1275                               v->name, del);
1276                     }
1277
1278                     /*
1279                      * Fetch pattern and destroy buffer, but preserve the data
1280                      * in it, since that's our lhs. Note that Buf_GetAll
1281                      * will return the actual number of bytes, which includes
1282                      * the null byte, so we have to decrement the length by
1283                      * one.
1284                      */
1285                     pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen);
1286                     pattern.leftLen--;
1287                     Buf_Destroy(buf, FALSE);
1288
1289                     /*
1290                      * Now comes the replacement string. Three things need to
1291                      * be done here: 1) need to compress escaped delimiters and
1292                      * ampersands and 2) need to replace unescaped ampersands
1293                      * with the l.h.s. (since this isn't regexp, we can do
1294                      * it right here) and 3) expand any variable substitutions.
1295                      */
1296                     buf = Buf_Init(0);
1297
1298                     tstr = cp + 1;
1299                     for (cp = tstr; *cp != '\0' && *cp != del; cp++) {
1300                         if ((*cp == '\\') &&
1301                             ((cp[1] == del) ||
1302                              (cp[1] == '&') ||
1303                              (cp[1] == '\\') ||
1304                              (cp[1] == '$')))
1305                         {
1306                             Buf_AddByte(buf, (Byte)cp[1]);
1307                             cp++;
1308                         } else if ((*cp == '$') && (cp[1] != del)) {
1309                             char    *cp2;
1310                             int     len;
1311                             Boolean freeIt;
1312
1313                             cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1314                             Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
1315                             cp += len - 1;
1316                             if (freeIt) {
1317                                 free(cp2);
1318                             }
1319                         } else if (*cp == '&') {
1320                             Buf_AddBytes(buf, pattern.leftLen,
1321                                          (Byte *)pattern.lhs);
1322                         } else {
1323                             Buf_AddByte(buf, (Byte)*cp);
1324                         }
1325                     }
1326
1327                     Buf_AddByte(buf, (Byte)'\0');
1328
1329                     /*
1330                      * If didn't end in delimiter character, complain
1331                      */
1332                     if (*cp != del) {
1333                         Fatal("Unclosed substitution for %s (%c missing)",
1334                               v->name, del);
1335                     }
1336
1337                     pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen);
1338                     pattern.rightLen--;
1339                     Buf_Destroy(buf, FALSE);
1340
1341                     /*
1342                      * Check for global substitution. If 'g' after the final
1343                      * delimiter, substitution is global and is marked that
1344                      * way.
1345                      */
1346                     cp++;
1347                     if (*cp == 'g') {
1348                         pattern.flags |= VAR_SUB_GLOBAL;
1349                         cp++;
1350                     }
1351
1352                     termc = *cp;
1353                     newStr = VarModify(str, VarSubstitute,
1354                                        (void *)&pattern);
1355                     /*
1356                      * Free the two strings.
1357                      */
1358                     free(pattern.lhs);
1359                     free(pattern.rhs);
1360                     break;
1361                 }
1362                 case 'C':
1363                 {
1364                     VarREPattern    pattern;
1365                     char           *re;
1366                     int             error;
1367
1368                     pattern.flags = 0;
1369                     delim = tstr[1];
1370                     tstr += 2;
1371
1372                     cp = tstr;
1373
1374                     if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
1375                         NULL, NULL)) == NULL) {
1376                         /* was: goto cleanup */
1377                         *lengthPtr = cp - start + 1;
1378                         if (*freePtr)
1379                             free(str);
1380                         if (delim != '\0')
1381                             Fatal("Unclosed substitution for %s (%c missing)",
1382                                   v->name, delim);
1383                         return (var_Error);
1384                     }
1385
1386                     if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
1387                         delim, NULL, NULL, NULL)) == NULL){
1388                         free(re);
1389
1390                         /* was: goto cleanup */
1391                         *lengthPtr = cp - start + 1;
1392                         if (*freePtr)
1393                             free(str);
1394                         if (delim != '\0')
1395                             Fatal("Unclosed substitution for %s (%c missing)",
1396                                   v->name, delim);
1397                         return (var_Error);
1398                     }
1399
1400                     for (;; cp++) {
1401                         switch (*cp) {
1402                         case 'g':
1403                             pattern.flags |= VAR_SUB_GLOBAL;
1404                             continue;
1405                         case '1':
1406                             pattern.flags |= VAR_SUB_ONE;
1407                             continue;
1408                         default:
1409                             break;
1410                         }
1411                         break;
1412                     }
1413
1414                     termc = *cp;
1415
1416                     error = regcomp(&pattern.re, re, REG_EXTENDED);
1417                     free(re);
1418                     if (error)  {
1419                         *lengthPtr = cp - start + 1;
1420                         VarREError(error, &pattern.re, "RE substitution error");
1421                         free(pattern.replace);
1422                         return (var_Error);
1423                     }
1424
1425                     pattern.nsub = pattern.re.re_nsub + 1;
1426                     if (pattern.nsub < 1)
1427                         pattern.nsub = 1;
1428                     if (pattern.nsub > 10)
1429                         pattern.nsub = 10;
1430                     pattern.matches = emalloc(pattern.nsub *
1431                                               sizeof(regmatch_t));
1432                     newStr = VarModify(str, VarRESubstitute,
1433                                        (void *) &pattern);
1434                     regfree(&pattern.re);
1435                     free(pattern.replace);
1436                     free(pattern.matches);
1437                     break;
1438                 }
1439                 case 'Q':
1440                     if (tstr[1] == endc || tstr[1] == ':') {
1441                         newStr = VarQuote (str);
1442                         cp = tstr + 1;
1443                         termc = *cp;
1444                         break;
1445                     }
1446                     /*FALLTHRU*/
1447                 case 'T':
1448                     if (tstr[1] == endc || tstr[1] == ':') {
1449                         newStr = VarModify (str, VarTail, (void *)0);
1450                         cp = tstr + 1;
1451                         termc = *cp;
1452                         break;
1453                     }
1454                     /*FALLTHRU*/
1455                 case 'H':
1456                     if (tstr[1] == endc || tstr[1] == ':') {
1457                         newStr = VarModify (str, VarHead, (void *)0);
1458                         cp = tstr + 1;
1459                         termc = *cp;
1460                         break;
1461                     }
1462                     /*FALLTHRU*/
1463                 case 'E':
1464                     if (tstr[1] == endc || tstr[1] == ':') {
1465                         newStr = VarModify (str, VarSuffix, (void *)0);
1466                         cp = tstr + 1;
1467                         termc = *cp;
1468                         break;
1469                     }
1470                     /*FALLTHRU*/
1471                 case 'R':
1472                     if (tstr[1] == endc || tstr[1] == ':') {
1473                         newStr = VarModify (str, VarRoot, (void *)0);
1474                         cp = tstr + 1;
1475                         termc = *cp;
1476                         break;
1477                     }
1478                     /*FALLTHRU*/
1479 #ifdef SUNSHCMD
1480                 case 's':
1481                     if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
1482                         char *error;
1483                         newStr = Cmd_Exec (str, &error);
1484                         if (error)
1485                             Error (error, str);
1486                         cp = tstr + 2;
1487                         termc = *cp;
1488                         break;
1489                     }
1490                     /*FALLTHRU*/
1491 #endif
1492                 default:
1493                 {
1494 #ifdef SYSVVARSUB
1495                     /*
1496                      * This can either be a bogus modifier or a System-V
1497                      * substitution command.
1498                      */
1499                     VarPattern      pattern;
1500                     Boolean         eqFound;
1501
1502                     pattern.flags = 0;
1503                     eqFound = FALSE;
1504                     /*
1505                      * First we make a pass through the string trying
1506                      * to verify it is a SYSV-make-style translation:
1507                      * it must be: <string1>=<string2>)
1508                      */
1509                     cp = tstr;
1510                     cnt = 1;
1511                     while (*cp != '\0' && cnt) {
1512                         if (*cp == '=') {
1513                             eqFound = TRUE;
1514                             /* continue looking for endc */
1515                         }
1516                         else if (*cp == endc)
1517                             cnt--;
1518                         else if (*cp == startc)
1519                             cnt++;
1520                         if (cnt)
1521                             cp++;
1522                     }
1523                     if (*cp == endc && eqFound) {
1524
1525                         /*
1526                          * Now we break this sucker into the lhs and
1527                          * rhs. We must null terminate them of course.
1528                          */
1529                         for (cp = tstr; *cp != '='; cp++)
1530                             continue;
1531                         pattern.lhs = tstr;
1532                         pattern.leftLen = cp - tstr;
1533                         *cp++ = '\0';
1534
1535                         pattern.rhs = cp;
1536                         cnt = 1;
1537                         while (cnt) {
1538                             if (*cp == endc)
1539                                 cnt--;
1540                             else if (*cp == startc)
1541                                 cnt++;
1542                             if (cnt)
1543                                 cp++;
1544                         }
1545                         pattern.rightLen = cp - pattern.rhs;
1546                         *cp = '\0';
1547
1548                         /*
1549                          * SYSV modifications happen through the whole
1550                          * string. Note the pattern is anchored at the end.
1551                          */
1552                         newStr = VarModify(str, VarSYSVMatch,
1553                                            (void *)&pattern);
1554
1555                         /*
1556                          * Restore the nulled characters
1557                          */
1558                         pattern.lhs[pattern.leftLen] = '=';
1559                         pattern.rhs[pattern.rightLen] = endc;
1560                         termc = endc;
1561                     } else
1562 #endif
1563                     {
1564                         Error ("Unknown modifier '%c'\n", *tstr);
1565                         for (cp = tstr+1;
1566                              *cp != ':' && *cp != endc && *cp != '\0';
1567                              cp++)
1568                                  continue;
1569                         termc = *cp;
1570                         newStr = var_Error;
1571                     }
1572                 }
1573             }
1574             DEBUGF(VAR, ("Result is \"%s\"\n", newStr));
1575
1576             if (*freePtr) {
1577                 free (str);
1578             }
1579             str = newStr;
1580             if (str != var_Error) {
1581                 *freePtr = TRUE;
1582             } else {
1583                 *freePtr = FALSE;
1584             }
1585             if (termc == '\0') {
1586                 Error("Unclosed variable specification for %s", v->name);
1587             } else if (termc == ':') {
1588                 *cp++ = termc;
1589             } else {
1590                 *cp = termc;
1591             }
1592             tstr = cp;
1593         }
1594         *lengthPtr = tstr - start + 1;
1595     } else {
1596         *lengthPtr = tstr - start + 1;
1597         *tstr = endc;
1598     }
1599
1600     if (v->flags & VAR_FROM_ENV) {
1601         Boolean   destroy = FALSE;
1602
1603         if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) {
1604             destroy = TRUE;
1605         } else {
1606             /*
1607              * Returning the value unmodified, so tell the caller to free
1608              * the thing.
1609              */
1610             *freePtr = TRUE;
1611         }
1612         free(v->name);
1613         Buf_Destroy(v->val, destroy);
1614         free(v);
1615     } else if (v->flags & VAR_JUNK) {
1616         /*
1617          * Perform any free'ing needed and set *freePtr to FALSE so the caller
1618          * doesn't try to free a static pointer.
1619          */
1620         if (*freePtr) {
1621             free(str);
1622         }
1623         *freePtr = FALSE;
1624         free(v->name);
1625         Buf_Destroy(v->val, TRUE);
1626         free(v);
1627         if (dynamic) {
1628             str = emalloc(*lengthPtr + 1);
1629             strncpy(str, start, *lengthPtr);
1630             str[*lengthPtr] = '\0';
1631             *freePtr = TRUE;
1632         } else {
1633             str = err ? var_Error : varNoError;
1634         }
1635     }
1636     return (str);
1637 }
1638
1639 /*-
1640  *-----------------------------------------------------------------------
1641  * Var_Subst  --
1642  *      Substitute for all variables in the given string in the given context
1643  *      If undefErr is TRUE, Parse_Error will be called when an undefined
1644  *      variable is encountered.
1645  *
1646  * Results:
1647  *      The resulting string.
1648  *
1649  * Side Effects:
1650  *      None. The old string must be freed by the caller
1651  *-----------------------------------------------------------------------
1652  */
1653 char *
1654 Var_Subst (char *var, char *str, GNode *ctxt, Boolean undefErr)
1655 {
1656     Buffer        buf;              /* Buffer for forming things */
1657     char          *val;             /* Value to substitute for a variable */
1658     int           length;           /* Length of the variable invocation */
1659     Boolean       doFree;           /* Set true if val should be freed */
1660     static Boolean errorReported;   /* Set true if an error has already
1661                                      * been reported to prevent a plethora
1662                                      * of messages when recursing */
1663
1664     buf = Buf_Init (MAKE_BSIZE);
1665     errorReported = FALSE;
1666
1667     while (*str) {
1668         if (var == NULL && (*str == '$') && (str[1] == '$')) {
1669             /*
1670              * A dollar sign may be escaped either with another dollar sign.
1671              * In such a case, we skip over the escape character and store the
1672              * dollar sign into the buffer directly.
1673              */
1674             str++;
1675             Buf_AddByte(buf, (Byte)*str);
1676             str++;
1677         } else if (*str != '$') {
1678             /*
1679              * Skip as many characters as possible -- either to the end of
1680              * the string or to the next dollar sign (variable invocation).
1681              */
1682             char  *cp;
1683
1684             for (cp = str++; *str != '$' && *str != '\0'; str++)
1685                 continue;
1686             Buf_AddBytes(buf, str - cp, (Byte *)cp);
1687         } else {
1688             if (var != NULL) {
1689                 int expand;
1690                 for (;;) {
1691                     if (str[1] != '(' && str[1] != '{') {
1692                         if (str[1] != *var || var[1] != '\0') {
1693                             Buf_AddBytes(buf, 2, (Byte *) str);
1694                             str += 2;
1695                             expand = FALSE;
1696                         }
1697                         else
1698                             expand = TRUE;
1699                         break;
1700                     }
1701                     else {
1702                         char *p;
1703
1704                         /*
1705                          * Scan up to the end of the variable name.
1706                          */
1707                         for (p = &str[2]; *p &&
1708                              *p != ':' && *p != ')' && *p != '}'; p++)
1709                             if (*p == '$')
1710                                 break;
1711                         /*
1712                          * A variable inside the variable. We cannot expand
1713                          * the external variable yet, so we try again with
1714                          * the nested one
1715                          */
1716                         if (*p == '$') {
1717                             Buf_AddBytes(buf, p - str, (Byte *) str);
1718                             str = p;
1719                             continue;
1720                         }
1721
1722                         if (strncmp(var, str + 2, p - str - 2) != 0 ||
1723                             var[p - str - 2] != '\0') {
1724                             /*
1725                              * Not the variable we want to expand, scan
1726                              * until the next variable
1727                              */
1728                             for (;*p != '$' && *p != '\0'; p++)
1729                                 continue;
1730                             Buf_AddBytes(buf, p - str, (Byte *) str);
1731                             str = p;
1732                             expand = FALSE;
1733                         }
1734                         else
1735                             expand = TRUE;
1736                         break;
1737                     }
1738                 }
1739                 if (!expand)
1740                     continue;
1741             }
1742
1743             val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
1744
1745             /*
1746              * When we come down here, val should either point to the
1747              * value of this variable, suitably modified, or be NULL.
1748              * Length should be the total length of the potential
1749              * variable invocation (from $ to end character...)
1750              */
1751             if (val == var_Error || val == varNoError) {
1752                 /*
1753                  * If performing old-time variable substitution, skip over
1754                  * the variable and continue with the substitution. Otherwise,
1755                  * store the dollar sign and advance str so we continue with
1756                  * the string...
1757                  */
1758                 if (oldVars) {
1759                     str += length;
1760                 } else if (undefErr) {
1761                     /*
1762                      * If variable is undefined, complain and skip the
1763                      * variable. The complaint will stop us from doing anything
1764                      * when the file is parsed.
1765                      */
1766                     if (!errorReported) {
1767                         Parse_Error (PARSE_FATAL,
1768                                      "Undefined variable \"%.*s\"",length,str);
1769                     }
1770                     str += length;
1771                     errorReported = TRUE;
1772                 } else {
1773                     Buf_AddByte (buf, (Byte)*str);
1774                     str += 1;
1775                 }
1776             } else {
1777                 /*
1778                  * We've now got a variable structure to store in. But first,
1779                  * advance the string pointer.
1780                  */
1781                 str += length;
1782
1783                 /*
1784                  * Copy all the characters from the variable value straight
1785                  * into the new string.
1786                  */
1787                 Buf_AddBytes (buf, strlen (val), (Byte *)val);
1788                 if (doFree) {
1789                     free (val);
1790                 }
1791             }
1792         }
1793     }
1794
1795     Buf_AddByte (buf, '\0');
1796     str = (char *)Buf_GetAll (buf, (int *)NULL);
1797     Buf_Destroy (buf, FALSE);
1798     return (str);
1799 }
1800
1801 /*-
1802  *-----------------------------------------------------------------------
1803  * Var_GetTail --
1804  *      Return the tail from each of a list of words. Used to set the
1805  *      System V local variables.
1806  *
1807  * Results:
1808  *      The resulting string.
1809  *
1810  * Side Effects:
1811  *      None.
1812  *
1813  *-----------------------------------------------------------------------
1814  */
1815 char *
1816 Var_GetTail(char *file)
1817 {
1818     return(VarModify(file, VarTail, (void *)0));
1819 }
1820
1821 /*-
1822  *-----------------------------------------------------------------------
1823  * Var_GetHead --
1824  *      Find the leading components of a (list of) filename(s).
1825  *      XXX: VarHead does not replace foo by ., as (sun) System V make
1826  *      does.
1827  *
1828  * Results:
1829  *      The leading components.
1830  *
1831  * Side Effects:
1832  *      None.
1833  *
1834  *-----------------------------------------------------------------------
1835  */
1836 char *
1837 Var_GetHead(char *file)
1838 {
1839     return(VarModify(file, VarHead, (void *)0));
1840 }
1841
1842 /*-
1843  *-----------------------------------------------------------------------
1844  * Var_Init --
1845  *      Initialize the module
1846  *
1847  * Results:
1848  *      None
1849  *
1850  * Side Effects:
1851  *      The VAR_CMD and VAR_GLOBAL contexts are created
1852  *-----------------------------------------------------------------------
1853  */
1854 void
1855 Var_Init (void)
1856 {
1857     VAR_GLOBAL = Targ_NewGN ("Global");
1858     VAR_CMD = Targ_NewGN ("Command");
1859     allVars = Lst_Init(FALSE);
1860
1861 }
1862
1863
1864 void
1865 Var_End (void)
1866 {
1867     Lst_Destroy(allVars, VarDelete);
1868 }
1869
1870
1871 /****************** PRINT DEBUGGING INFO *****************/
1872 static int
1873 VarPrintVar (void *vp, void *dummy __unused)
1874 {
1875     Var    *v = (Var *) vp;
1876     printf ("%-16s = %s\n", v->name, (char *) Buf_GetAll(v->val, (int *)NULL));
1877     return (0);
1878 }
1879
1880 /*-
1881  *-----------------------------------------------------------------------
1882  * Var_Dump --
1883  *      print all variables in a context
1884  *-----------------------------------------------------------------------
1885  */
1886 void
1887 Var_Dump (GNode *ctxt)
1888 {
1889     Lst_ForEach (ctxt->context, VarPrintVar, (void *) 0);
1890 }