1 /* $NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $ */
4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved.
39 * This code is derived from software contributed to Berkeley by
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
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.
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
72 static char rcsid
[] = "$NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $";
74 #include <sys/cdefs.h>
77 static char sccsid
[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
79 __RCSID("$NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $");
86 * Variable-handling functions
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
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
100 * Var_Exists See if a variable exists.
102 * Var_Value Return the value of a variable in a context or
103 * NULL if the variable is undefined.
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.
111 * Var_Parse Parse a variable expansion from a string and
112 * return the result and the number of characters
115 * Var_Delete Delete a variable in a context.
117 * Var_Init Initialize this module.
120 * Var_Dump Print out all variables defined in the given
123 * XXX: There's a lot of duplication in these functions.
126 #include <sys/stat.h>
128 #include <sys/types.h>
132 #include <inttypes.h>
143 * This lets us tell if we have replaced the original environ
144 * (which we cannot free).
146 char **savedEnv
= NULL
;
149 * This is a harmless return value for Var_Parse that can be used by Var_Subst
150 * to determine if there was an error in parsing -- easier than returning
151 * a flag, as things outside this module don't give a hoot.
153 char var_Error
[] = "";
156 * Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
157 * set false. Why not just use a constant? Well, gcc likes to condense
158 * identical string instances...
160 static char varNoError
[] = "";
163 * Internally, variables are contained in four different contexts.
164 * 1) the environment. They may not be changed. If an environment
165 * variable is appended-to, the result is placed in the global
167 * 2) the global context. Variables set in the Makefile are located in
168 * the global context. It is the penultimate context searched when
170 * 3) the command-line context. All variables set on the command line
171 * are placed in this context. They are UNALTERABLE once placed here.
172 * 4) the local context. Each target has associated with it a context
173 * list. On this list are located the structures describing such
174 * local variables as $(@) and $(*)
175 * The four contexts are searched in the reverse order from which they are
178 GNode
*VAR_GLOBAL
; /* variables from the makefile */
179 GNode
*VAR_CMD
; /* variables defined on the command-line */
181 #define FIND_CMD 0x1 /* look in VAR_CMD when searching */
182 #define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
183 #define FIND_ENV 0x4 /* look in the environment also */
186 char *name
; /* the variable's name */
187 Buffer val
; /* its value */
188 int flags
; /* miscellaneous status flags */
189 #define VAR_IN_USE 1 /* Variable's value currently being used.
190 * Used to avoid recursion */
191 #define VAR_FROM_ENV 2 /* Variable comes from the environment */
192 #define VAR_JUNK 4 /* Variable is a junk variable that
193 * should be destroyed when done with
194 * it. Used by Var_Parse for undefined,
195 * modified variables */
196 #define VAR_KEEP 8 /* Variable is VAR_JUNK, but we found
197 * a use for it in some modifier and
198 * the value is therefore valid */
199 #define VAR_EXPORTED 16 /* Variable is exported */
200 #define VAR_REEXPORT 32 /* Indicate if var needs re-export.
201 * This would be true if it contains $'s
203 #define VAR_FROM_CMD 64 /* Variable came from command line */
207 * Exporting vars is expensive so skip it if we can
209 #define VAR_EXPORTED_NONE 0
210 #define VAR_EXPORTED_YES 1
211 #define VAR_EXPORTED_ALL 2
212 static int var_exportedVars
= VAR_EXPORTED_NONE
;
214 * We pass this to Var_Export when doing the initial export
215 * or after updating an exported var.
217 #define VAR_EXPORT_PARENT 1
219 /* Var*Pattern flags */
220 #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
221 #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
222 #define VAR_SUB_MATCHED 0x04 /* There was a match */
223 #define VAR_MATCH_START 0x08 /* Match at start of word */
224 #define VAR_MATCH_END 0x10 /* Match at end of word */
225 #define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
228 #define VAR_NO_EXPORT 0x01 /* do not export */
232 * The following fields are set by Var_Parse() when it
233 * encounters modifiers that need to keep state for use by
234 * subsequent modifiers within the same variable expansion.
236 Byte varSpace
; /* Word separator in expansions */
237 Boolean oneBigWord
; /* TRUE if we will treat the variable as a
238 * single big word, even if it contains
239 * embedded spaces (as opposed to the
240 * usual behaviour of treating it as
241 * several space-separated words). */
244 /* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/",
245 * to VarSYSVMatch() for ":lhs=rhs". */
247 const char *lhs
; /* String to match */
248 int leftLen
; /* Length of string */
249 const char *rhs
; /* Replacement string (w/ &'s removed) */
250 int rightLen
; /* Length of replacement */
254 /* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */
256 GNode
*ctxt
; /* variable context */
257 char *tvar
; /* name of temp var */
259 char *str
; /* string to expand */
261 int errnum
; /* errnum for not defined */
265 /* struct passed as 'void *' to VarRESubstitute() for ":C///" */
275 /* struct passed to VarSelectWords() for ":[start..end]" */
277 int start
; /* first word to select */
278 int end
; /* last word to select */
281 static Var
*VarFind(const char *, GNode
*, int);
282 static void VarAdd(const char *, const char *, GNode
*);
283 static Boolean
VarHead(GNode
*, Var_Parse_State
*,
284 char *, Boolean
, Buffer
*, void *);
285 static Boolean
VarTail(GNode
*, Var_Parse_State
*,
286 char *, Boolean
, Buffer
*, void *);
287 static Boolean
VarSuffix(GNode
*, Var_Parse_State
*,
288 char *, Boolean
, Buffer
*, void *);
289 static Boolean
VarRoot(GNode
*, Var_Parse_State
*,
290 char *, Boolean
, Buffer
*, void *);
291 static Boolean
VarMatch(GNode
*, Var_Parse_State
*,
292 char *, Boolean
, Buffer
*, void *);
294 static Boolean
VarSYSVMatch(GNode
*, Var_Parse_State
*,
295 char *, Boolean
, Buffer
*, void *);
297 static Boolean
VarNoMatch(GNode
*, Var_Parse_State
*,
298 char *, Boolean
, Buffer
*, void *);
300 static void VarREError(int, regex_t
*, const char *);
301 static Boolean
VarRESubstitute(GNode
*, Var_Parse_State
*,
302 char *, Boolean
, Buffer
*, void *);
304 static Boolean
VarSubstitute(GNode
*, Var_Parse_State
*,
305 char *, Boolean
, Buffer
*, void *);
306 static Boolean
VarLoopExpand(GNode
*, Var_Parse_State
*,
307 char *, Boolean
, Buffer
*, void *);
308 static char *VarGetPattern(GNode
*, Var_Parse_State
*,
309 int, const char **, int, int *, int *,
311 static char *VarQuote(char *);
312 static char *VarChangeCase(char *, int);
313 static char *VarHash(char *);
314 static char *VarModify(GNode
*, Var_Parse_State
*,
316 Boolean (*)(GNode
*, Var_Parse_State
*, char *, Boolean
, Buffer
*, void *),
318 static char *VarOrder(const char *, const char);
319 static char *VarUniq(const char *);
320 static int VarWordCompare(const void *, const void *);
321 static void VarPrintVar(void *);
329 *-----------------------------------------------------------------------
331 * Find the given variable in the given context and any other contexts
336 * ctxt context in which to find it
337 * flags FIND_GLOBAL set means to look in the
338 * VAR_GLOBAL context as well. FIND_CMD set means
339 * to look in the VAR_CMD context also. FIND_ENV
340 * set means to look in the environment
343 * A pointer to the structure describing the desired variable or
344 * NULL if the variable does not exist.
348 *-----------------------------------------------------------------------
351 VarFind(const char *name
, GNode
*ctxt
, int flags
)
357 * If the variable name begins with a '.', it could very well be one of
358 * the local ones. We check the name against all the local variables
359 * and substitute the short version in for 'name' if it matches one of
362 if (*name
== '.' && isupper((unsigned char) name
[1]))
365 if (!strcmp(name
, ".ALLSRC"))
367 if (!strcmp(name
, ".ARCHIVE"))
371 if (!strcmp(name
, ".IMPSRC"))
375 if (!strcmp(name
, ".MEMBER"))
379 if (!strcmp(name
, ".OODATE"))
383 if (!strcmp(name
, ".PREFIX"))
387 if (!strcmp(name
, ".TARGET"))
392 /* for compatibility with gmake */
393 if (name
[0] == '^' && name
[1] == '\0')
398 * First look for the variable in the given context. If it's not there,
399 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
400 * depending on the FIND_* flags in 'flags'
402 var
= Hash_FindEntry(&ctxt
->context
, name
);
404 if ((var
== NULL
) && (flags
& FIND_CMD
) && (ctxt
!= VAR_CMD
)) {
405 var
= Hash_FindEntry(&VAR_CMD
->context
, name
);
407 if (!checkEnvFirst
&& (var
== NULL
) && (flags
& FIND_GLOBAL
) &&
408 (ctxt
!= VAR_GLOBAL
))
410 var
= Hash_FindEntry(&VAR_GLOBAL
->context
, name
);
412 if ((var
== NULL
) && (flags
& FIND_ENV
)) {
415 if ((env
= getenv(name
)) != NULL
) {
418 v
= bmake_malloc(sizeof(Var
));
419 v
->name
= bmake_strdup(name
);
423 Buf_Init(&v
->val
, len
+ 1);
424 Buf_AddBytes(&v
->val
, len
, env
);
426 v
->flags
= VAR_FROM_ENV
;
428 } else if (checkEnvFirst
&& (flags
& FIND_GLOBAL
) &&
429 (ctxt
!= VAR_GLOBAL
))
431 var
= Hash_FindEntry(&VAR_GLOBAL
->context
, name
);
435 return ((Var
*)Hash_GetValue(var
));
440 } else if (var
== NULL
) {
443 return ((Var
*)Hash_GetValue(var
));
448 *-----------------------------------------------------------------------
450 * If the variable is an environment variable, free it
454 * destroy true if the value buffer should be destroyed.
457 * 1 if it is an environment variable 0 ow.
460 * The variable is free'ed if it is an environent variable.
461 *-----------------------------------------------------------------------
464 VarFreeEnv(Var
*v
, Boolean destroy
)
466 if ((v
->flags
& VAR_FROM_ENV
) == 0)
469 Buf_Destroy(&v
->val
, destroy
);
475 *-----------------------------------------------------------------------
477 * Add a new variable of name name and value val to the given context
480 * name name of variable to add
481 * val value to set it to
482 * ctxt context in which to set it
488 * The new variable is placed at the front of the given context
489 * The name and val arguments are duplicated so they may
491 *-----------------------------------------------------------------------
494 VarAdd(const char *name
, const char *val
, GNode
*ctxt
)
500 v
= bmake_malloc(sizeof(Var
));
502 len
= val
? strlen(val
) : 0;
503 Buf_Init(&v
->val
, len
+1);
504 Buf_AddBytes(&v
->val
, len
, val
);
508 h
= Hash_CreateEntry(&ctxt
->context
, name
, NULL
);
512 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
, val
);
517 *-----------------------------------------------------------------------
519 * Remove a variable from a context.
525 * The Var structure is removed and freed.
527 *-----------------------------------------------------------------------
530 Var_Delete(const char *name
, GNode
*ctxt
)
534 ln
= Hash_FindEntry(&ctxt
->context
, name
);
536 fprintf(debug_file
, "%s:delete %s%s\n",
537 ctxt
->name
, name
, ln
? "" : " (not found)");
542 v
= (Var
*)Hash_GetValue(ln
);
543 if ((v
->flags
& VAR_EXPORTED
)) {
546 if (strcmp(MAKE_EXPORTED
, v
->name
) == 0) {
547 var_exportedVars
= VAR_EXPORTED_NONE
;
549 if (v
->name
!= ln
->name
)
551 Hash_DeleteEntry(&ctxt
->context
, ln
);
552 Buf_Destroy(&v
->val
, TRUE
);
560 * We ignore make internal variables (those which start with '.')
561 * Also we jump through some hoops to avoid calling setenv
562 * more than necessary since it can leak.
563 * We only manipulate flags of vars if 'parent' is set.
566 Var_Export1(const char *name
, int parent
)
574 return 0; /* skip internals */
578 * If it is one of the vars that should only appear in
579 * local context, skip it, else we can get Var_Subst
590 v
= VarFind(name
, VAR_GLOBAL
, 0);
595 (v
->flags
& (VAR_EXPORTED
|VAR_REEXPORT
)) == VAR_EXPORTED
) {
596 return 0; /* nothing to do */
598 val
= Buf_GetAll(&v
->val
, NULL
);
599 if (strchr(val
, '$')) {
602 * Flag this as something we need to re-export.
603 * No point actually exporting it now though,
604 * the child can do it at the last minute.
606 v
->flags
|= (VAR_EXPORTED
|VAR_REEXPORT
);
609 if (v
->flags
& VAR_IN_USE
) {
611 * We recursed while exporting in a child.
612 * This isn't going to end well, just skip it.
616 n
= snprintf(tmp
, sizeof(tmp
), "${%s}", name
);
617 if (n
< (int)sizeof(tmp
)) {
618 val
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
619 setenv(name
, val
, 1);
624 v
->flags
&= ~VAR_REEXPORT
; /* once will do */
626 if (parent
|| !(v
->flags
& VAR_EXPORTED
)) {
627 setenv(name
, val
, 1);
631 * This is so Var_Set knows to call Var_Export again...
634 v
->flags
|= VAR_EXPORTED
;
640 * This gets called from our children.
652 if (VAR_EXPORTED_NONE
== var_exportedVars
)
655 if (VAR_EXPORTED_ALL
== var_exportedVars
) {
657 * Ouch! This is crazy...
659 for (var
= Hash_EnumFirst(&VAR_GLOBAL
->context
, &state
);
661 var
= Hash_EnumNext(&state
)) {
662 v
= (Var
*)Hash_GetValue(var
);
663 Var_Export1(v
->name
, 0);
668 * We have a number of exported vars,
670 n
= snprintf(tmp
, sizeof(tmp
), "${" MAKE_EXPORTED
":O:u}");
671 if (n
< (int)sizeof(tmp
)) {
677 val
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
678 av
= brk_string(val
, &ac
, FALSE
, &as
);
679 for (i
= 0; i
< ac
; i
++) {
680 Var_Export1(av
[i
], 0);
689 * This is called when .export is seen or
690 * .MAKE.EXPORTED is modified.
691 * It is also called when any exported var is modified.
694 Var_Export(char *str
, int isExport
)
704 if (isExport
&& (!str
|| !str
[0])) {
705 var_exportedVars
= VAR_EXPORTED_ALL
; /* use with caution! */
709 if (strncmp(str
, "-env", 4) == 0) {
713 track
= VAR_EXPORT_PARENT
;
715 val
= Var_Subst(NULL
, str
, VAR_GLOBAL
, 0);
716 av
= brk_string(val
, &ac
, FALSE
, &as
);
717 for (i
= 0; i
< ac
; i
++) {
722 * If it is one of the vars that should only appear in
723 * local context, skip it, else we can get Var_Subst
734 if (Var_Export1(name
, track
)) {
735 if (VAR_EXPORTED_ALL
!= var_exportedVars
)
736 var_exportedVars
= VAR_EXPORTED_YES
;
737 if (isExport
&& track
) {
738 Var_Append(MAKE_EXPORTED
, name
, VAR_GLOBAL
);
749 * This is called when .unexport[-env] is seen.
751 extern char **environ
;
754 Var_UnExport(char *str
)
759 Boolean unexport_env
;
762 if (!str
|| !str
[0]) {
763 return; /* assert? */
769 unexport_env
= (strncmp(str
, "-env", 4) == 0);
773 cp
= getenv(MAKE_LEVEL
); /* we should preserve this */
774 if (environ
== savedEnv
) {
775 /* we have been here before! */
776 newenv
= bmake_realloc(environ
, 2 * sizeof(char *));
782 newenv
= bmake_malloc(2 * sizeof(char *));
786 /* Note: we cannot safely free() the original environ. */
787 environ
= savedEnv
= newenv
;
790 setenv(MAKE_LEVEL
, cp
, 1);
792 for (; *str
!= '\n' && isspace((unsigned char) *str
); str
++)
794 if (str
[0] && str
[0] != '\n') {
800 /* Using .MAKE.EXPORTED */
801 n
= snprintf(tmp
, sizeof(tmp
), "${" MAKE_EXPORTED
":O:u}");
802 if (n
< (int)sizeof(tmp
)) {
803 vlist
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
813 av
= brk_string(vlist
, &ac
, FALSE
, &as
);
814 for (i
= 0; i
< ac
; i
++) {
815 v
= VarFind(av
[i
], VAR_GLOBAL
, 0);
819 (v
->flags
& (VAR_EXPORTED
|VAR_REEXPORT
)) == VAR_EXPORTED
) {
822 v
->flags
&= ~(VAR_EXPORTED
|VAR_REEXPORT
);
824 * If we are unexporting a list,
825 * remove each one from .MAKE.EXPORTED.
826 * If we are removing them all,
827 * just delete .MAKE.EXPORTED below.
830 n
= snprintf(tmp
, sizeof(tmp
),
831 "${" MAKE_EXPORTED
":N%s}", v
->name
);
832 if (n
< (int)sizeof(tmp
)) {
833 cp
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
834 Var_Set(MAKE_EXPORTED
, cp
, VAR_GLOBAL
, 0);
842 Var_Delete(MAKE_EXPORTED
, VAR_GLOBAL
);
849 *-----------------------------------------------------------------------
851 * Set the variable name to the value val in the given context.
854 * name name of variable to set
855 * val value to give to the variable
856 * ctxt context in which to set it
862 * If the variable doesn't yet exist, a new record is created for it.
863 * Else the old value is freed and the new one stuck in its place
866 * The variable is searched for only in its context before being
867 * created in that context. I.e. if the context is VAR_GLOBAL,
868 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
869 * VAR_CMD->context is searched. This is done to avoid the literally
870 * thousands of unnecessary strcmp's that used to be done to
871 * set, say, $(@) or $(<).
872 * If the context is VAR_GLOBAL though, we check if the variable
873 * was set in VAR_CMD from the command line and skip it if so.
874 *-----------------------------------------------------------------------
877 Var_Set(const char *name
, const char *val
, GNode
*ctxt
, int flags
)
880 char *expanded_name
= NULL
;
883 * We only look for a variable in the given context since anything set
884 * here will override anything in a lower context, so there's not much
885 * point in searching them all just to save a bit of memory...
887 if (strchr(name
, '$') != NULL
) {
888 expanded_name
= Var_Subst(NULL
, name
, ctxt
, 0);
889 if (expanded_name
[0] == 0) {
891 fprintf(debug_file
, "Var_Set(\"%s\", \"%s\", ...) "
892 "name expands to empty string - ignored\n",
898 name
= expanded_name
;
900 if (ctxt
== VAR_GLOBAL
) {
901 v
= VarFind(name
, VAR_CMD
, 0);
903 if ((v
->flags
& VAR_FROM_CMD
)) {
905 fprintf(debug_file
, "%s:%s = %s ignored!\n", ctxt
->name
, name
, val
);
912 v
= VarFind(name
, ctxt
, 0);
914 VarAdd(name
, val
, ctxt
);
917 Buf_AddBytes(&v
->val
, strlen(val
), val
);
920 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
, val
);
922 if ((v
->flags
& VAR_EXPORTED
)) {
923 Var_Export1(name
, VAR_EXPORT_PARENT
);
927 * Any variables given on the command line are automatically exported
928 * to the environment (as per POSIX standard)
930 if (ctxt
== VAR_CMD
&& (flags
& VAR_NO_EXPORT
) == 0) {
932 /* we just added it */
933 v
= VarFind(name
, ctxt
, 0);
936 v
->flags
|= VAR_FROM_CMD
;
938 * If requested, don't export these in the environment
939 * individually. We still put them in MAKEOVERRIDES so
940 * that the command-line settings continue to override
943 if (varNoExportEnv
!= TRUE
)
944 setenv(name
, val
, 1);
946 Var_Append(MAKEOVERRIDES
, name
, VAR_GLOBAL
);
949 * Another special case.
950 * Several make's support this sort of mechanism for tracking
951 * recursion - but each uses a different name.
952 * We allow the makefiles to update .MAKE.LEVEL and ensure
953 * children see a correctly incremented value.
955 if (ctxt
== VAR_GLOBAL
&& strcmp(MAKE_LEVEL
, name
) == 0) {
960 snprintf(tmp
, sizeof(tmp
), "%u", level
+ 1);
961 setenv(MAKE_LEVEL
, tmp
, 1);
966 if (expanded_name
!= NULL
)
973 *-----------------------------------------------------------------------
975 * The variable of the given name has the given value appended to it in
979 * name name of variable to modify
980 * val String to append to it
981 * ctxt Context in which this should occur
987 * If the variable doesn't exist, it is created. Else the strings
988 * are concatenated (with a space in between).
991 * Only if the variable is being sought in the global context is the
992 * environment searched.
993 * XXX: Knows its calling circumstances in that if called with ctxt
994 * an actual target, it will only search that context since only
995 * a local variable could be being appended to. This is actually
996 * a big win and must be tolerated.
997 *-----------------------------------------------------------------------
1000 Var_Append(const char *name
, const char *val
, GNode
*ctxt
)
1004 char *expanded_name
= NULL
;
1006 if (strchr(name
, '$') != NULL
) {
1007 expanded_name
= Var_Subst(NULL
, name
, ctxt
, 0);
1008 if (expanded_name
[0] == 0) {
1010 fprintf(debug_file
, "Var_Append(\"%s\", \"%s\", ...) "
1011 "name expands to empty string - ignored\n",
1014 free(expanded_name
);
1017 name
= expanded_name
;
1020 v
= VarFind(name
, ctxt
, (ctxt
== VAR_GLOBAL
) ? FIND_ENV
: 0);
1023 VarAdd(name
, val
, ctxt
);
1025 Buf_AddByte(&v
->val
, ' ');
1026 Buf_AddBytes(&v
->val
, strlen(val
), val
);
1029 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
,
1030 Buf_GetAll(&v
->val
, NULL
));
1033 if (v
->flags
& VAR_FROM_ENV
) {
1035 * If the original variable came from the environment, we
1036 * have to install it in the global context (we could place
1037 * it in the environment, but then we should provide a way to
1038 * export other variables...)
1040 v
->flags
&= ~VAR_FROM_ENV
;
1041 h
= Hash_CreateEntry(&ctxt
->context
, name
, NULL
);
1042 Hash_SetValue(h
, v
);
1045 if (expanded_name
!= NULL
)
1046 free(expanded_name
);
1050 *-----------------------------------------------------------------------
1052 * See if the given variable exists.
1055 * name Variable to find
1056 * ctxt Context in which to start search
1059 * TRUE if it does, FALSE if it doesn't
1064 *-----------------------------------------------------------------------
1067 Var_Exists(const char *name
, GNode
*ctxt
)
1072 if ((cp
= strchr(name
, '$')) != NULL
) {
1073 cp
= Var_Subst(NULL
, name
, ctxt
, FALSE
);
1075 v
= VarFind(cp
? cp
: name
, ctxt
, FIND_CMD
|FIND_GLOBAL
|FIND_ENV
);
1082 (void)VarFreeEnv(v
, TRUE
);
1088 *-----------------------------------------------------------------------
1090 * Return the value of the named variable in the given context
1094 * ctxt context in which to search for it
1097 * The value if the variable exists, NULL if it doesn't
1101 *-----------------------------------------------------------------------
1104 Var_Value(const char *name
, GNode
*ctxt
, char **frp
)
1108 v
= VarFind(name
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
1111 char *p
= (Buf_GetAll(&v
->val
, NULL
));
1112 if (VarFreeEnv(v
, FALSE
))
1121 *-----------------------------------------------------------------------
1123 * Remove the tail of the given word and place the result in the given
1128 * addSpace True if need to add a space to the buffer
1129 * before sticking in the head
1130 * buf Buffer in which to store it
1133 * TRUE if characters were added to the buffer (a space needs to be
1134 * added to the buffer before the next word).
1137 * The trimmed word is added to the buffer.
1139 *-----------------------------------------------------------------------
1142 VarHead(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1143 char *word
, Boolean addSpace
, Buffer
*buf
,
1148 slash
= strrchr(word
, '/');
1149 if (slash
!= NULL
) {
1150 if (addSpace
&& vpstate
->varSpace
) {
1151 Buf_AddByte(buf
, vpstate
->varSpace
);
1154 Buf_AddBytes(buf
, strlen(word
), word
);
1159 * If no directory part, give . (q.v. the POSIX standard)
1161 if (addSpace
&& vpstate
->varSpace
)
1162 Buf_AddByte(buf
, vpstate
->varSpace
);
1163 Buf_AddByte(buf
, '.');
1165 return(dummy
? TRUE
: TRUE
);
1169 *-----------------------------------------------------------------------
1171 * Remove the head of the given word and place the result in the given
1176 * addSpace True if need to add a space to the buffer
1177 * before adding the tail
1178 * buf Buffer in which to store it
1181 * TRUE if characters were added to the buffer (a space needs to be
1182 * added to the buffer before the next word).
1185 * The trimmed word is added to the buffer.
1187 *-----------------------------------------------------------------------
1190 VarTail(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1191 char *word
, Boolean addSpace
, Buffer
*buf
,
1196 if (addSpace
&& vpstate
->varSpace
) {
1197 Buf_AddByte(buf
, vpstate
->varSpace
);
1200 slash
= strrchr(word
, '/');
1201 if (slash
!= NULL
) {
1203 Buf_AddBytes(buf
, strlen(slash
), slash
);
1206 Buf_AddBytes(buf
, strlen(word
), word
);
1208 return (dummy
? TRUE
: TRUE
);
1212 *-----------------------------------------------------------------------
1214 * Place the suffix of the given word in the given buffer.
1218 * addSpace TRUE if need to add a space before placing the
1219 * suffix in the buffer
1220 * buf Buffer in which to store it
1223 * TRUE if characters were added to the buffer (a space needs to be
1224 * added to the buffer before the next word).
1227 * The suffix from the word is placed in the buffer.
1229 *-----------------------------------------------------------------------
1232 VarSuffix(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1233 char *word
, Boolean addSpace
, Buffer
*buf
,
1238 dot
= strrchr(word
, '.');
1240 if (addSpace
&& vpstate
->varSpace
) {
1241 Buf_AddByte(buf
, vpstate
->varSpace
);
1244 Buf_AddBytes(buf
, strlen(dot
), dot
);
1248 return (dummy
? addSpace
: addSpace
);
1252 *-----------------------------------------------------------------------
1254 * Remove the suffix of the given word and place the result in the
1259 * addSpace TRUE if need to add a space to the buffer
1260 * before placing the root in it
1261 * buf Buffer in which to store it
1264 * TRUE if characters were added to the buffer (a space needs to be
1265 * added to the buffer before the next word).
1268 * The trimmed word is added to the buffer.
1270 *-----------------------------------------------------------------------
1273 VarRoot(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1274 char *word
, Boolean addSpace
, Buffer
*buf
,
1279 if (addSpace
&& vpstate
->varSpace
) {
1280 Buf_AddByte(buf
, vpstate
->varSpace
);
1283 dot
= strrchr(word
, '.');
1286 Buf_AddBytes(buf
, strlen(word
), word
);
1289 Buf_AddBytes(buf
, strlen(word
), word
);
1291 return (dummy
? TRUE
: TRUE
);
1295 *-----------------------------------------------------------------------
1297 * Place the word in the buffer if it matches the given pattern.
1298 * Callback function for VarModify to implement the :M modifier.
1301 * word Word to examine
1302 * addSpace TRUE if need to add a space to the buffer
1303 * before adding the word, if it matches
1304 * buf Buffer in which to store it
1305 * pattern Pattern the word must match
1308 * TRUE if a space should be placed in the buffer before the next
1312 * The word may be copied to the buffer.
1314 *-----------------------------------------------------------------------
1317 VarMatch(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1318 char *word
, Boolean addSpace
, Buffer
*buf
,
1322 fprintf(debug_file
, "VarMatch [%s] [%s]\n", word
, (char *)pattern
);
1323 if (Str_Match(word
, (char *)pattern
)) {
1324 if (addSpace
&& vpstate
->varSpace
) {
1325 Buf_AddByte(buf
, vpstate
->varSpace
);
1328 Buf_AddBytes(buf
, strlen(word
), word
);
1335 *-----------------------------------------------------------------------
1337 * Place the word in the buffer if it matches the given pattern.
1338 * Callback function for VarModify to implement the System V %
1342 * word Word to examine
1343 * addSpace TRUE if need to add a space to the buffer
1344 * before adding the word, if it matches
1345 * buf Buffer in which to store it
1346 * patp Pattern the word must match
1349 * TRUE if a space should be placed in the buffer before the next
1353 * The word may be copied to the buffer.
1355 *-----------------------------------------------------------------------
1358 VarSYSVMatch(GNode
*ctx
, Var_Parse_State
*vpstate
,
1359 char *word
, Boolean addSpace
, Buffer
*buf
,
1364 VarPattern
*pat
= (VarPattern
*)patp
;
1367 if (addSpace
&& vpstate
->varSpace
)
1368 Buf_AddByte(buf
, vpstate
->varSpace
);
1372 if ((ptr
= Str_SYSVMatch(word
, pat
->lhs
, &len
)) != NULL
) {
1373 varexp
= Var_Subst(NULL
, pat
->rhs
, ctx
, 0);
1374 Str_SYSVSubst(buf
, varexp
, ptr
, len
);
1377 Buf_AddBytes(buf
, strlen(word
), word
);
1386 *-----------------------------------------------------------------------
1388 * Place the word in the buffer if it doesn't match the given pattern.
1389 * Callback function for VarModify to implement the :N modifier.
1392 * word Word to examine
1393 * addSpace TRUE if need to add a space to the buffer
1394 * before adding the word, if it matches
1395 * buf Buffer in which to store it
1396 * pattern Pattern the word must match
1399 * TRUE if a space should be placed in the buffer before the next
1403 * The word may be copied to the buffer.
1405 *-----------------------------------------------------------------------
1408 VarNoMatch(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1409 char *word
, Boolean addSpace
, Buffer
*buf
,
1412 if (!Str_Match(word
, (char *)pattern
)) {
1413 if (addSpace
&& vpstate
->varSpace
) {
1414 Buf_AddByte(buf
, vpstate
->varSpace
);
1417 Buf_AddBytes(buf
, strlen(word
), word
);
1424 *-----------------------------------------------------------------------
1426 * Perform a string-substitution on the given word, placing the
1427 * result in the passed buffer.
1430 * word Word to modify
1431 * addSpace True if space should be added before
1433 * buf Buffer for result
1434 * patternp Pattern for substitution
1437 * TRUE if a space is needed before more characters are added.
1442 *-----------------------------------------------------------------------
1445 VarSubstitute(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1446 char *word
, Boolean addSpace
, Buffer
*buf
,
1449 int wordLen
; /* Length of word */
1450 char *cp
; /* General pointer */
1451 VarPattern
*pattern
= (VarPattern
*)patternp
;
1453 wordLen
= strlen(word
);
1454 if ((pattern
->flags
& (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) !=
1455 (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) {
1457 * Still substituting -- break it down into simple anchored cases
1458 * and if none of them fits, perform the general substitution case.
1460 if ((pattern
->flags
& VAR_MATCH_START
) &&
1461 (strncmp(word
, pattern
->lhs
, pattern
->leftLen
) == 0)) {
1463 * Anchored at start and beginning of word matches pattern
1465 if ((pattern
->flags
& VAR_MATCH_END
) &&
1466 (wordLen
== pattern
->leftLen
)) {
1468 * Also anchored at end and matches to the end (word
1469 * is same length as pattern) add space and rhs only
1470 * if rhs is non-null.
1472 if (pattern
->rightLen
!= 0) {
1473 if (addSpace
&& vpstate
->varSpace
) {
1474 Buf_AddByte(buf
, vpstate
->varSpace
);
1477 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1479 pattern
->flags
|= VAR_SUB_MATCHED
;
1480 } else if (pattern
->flags
& VAR_MATCH_END
) {
1482 * Doesn't match to end -- copy word wholesale
1487 * Matches at start but need to copy in trailing characters
1489 if ((pattern
->rightLen
+ wordLen
- pattern
->leftLen
) != 0){
1490 if (addSpace
&& vpstate
->varSpace
) {
1491 Buf_AddByte(buf
, vpstate
->varSpace
);
1495 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1496 Buf_AddBytes(buf
, wordLen
- pattern
->leftLen
,
1497 (word
+ pattern
->leftLen
));
1498 pattern
->flags
|= VAR_SUB_MATCHED
;
1500 } else if (pattern
->flags
& VAR_MATCH_START
) {
1502 * Had to match at start of word and didn't -- copy whole word.
1505 } else if (pattern
->flags
& VAR_MATCH_END
) {
1507 * Anchored at end, Find only place match could occur (leftLen
1508 * characters from the end of the word) and see if it does. Note
1509 * that because the $ will be left at the end of the lhs, we have
1512 cp
= word
+ (wordLen
- pattern
->leftLen
);
1514 (strncmp(cp
, pattern
->lhs
, pattern
->leftLen
) == 0)) {
1516 * Match found. If we will place characters in the buffer,
1517 * add a space before hand as indicated by addSpace, then
1518 * stuff in the initial, unmatched part of the word followed
1519 * by the right-hand-side.
1521 if (((cp
- word
) + pattern
->rightLen
) != 0) {
1522 if (addSpace
&& vpstate
->varSpace
) {
1523 Buf_AddByte(buf
, vpstate
->varSpace
);
1527 Buf_AddBytes(buf
, cp
- word
, word
);
1528 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1529 pattern
->flags
|= VAR_SUB_MATCHED
;
1532 * Had to match at end and didn't. Copy entire word.
1538 * Pattern is unanchored: search for the pattern in the word using
1539 * String_FindSubstring, copying unmatched portions and the
1540 * right-hand-side for each match found, handling non-global
1541 * substitutions correctly, etc. When the loop is done, any
1542 * remaining part of the word (word and wordLen are adjusted
1543 * accordingly through the loop) is copied straight into the
1545 * addSpace is set FALSE as soon as a space is added to the
1552 origSize
= Buf_Size(buf
);
1554 cp
= Str_FindSubstring(word
, pattern
->lhs
);
1556 if (addSpace
&& (((cp
- word
) + pattern
->rightLen
) != 0)){
1557 Buf_AddByte(buf
, vpstate
->varSpace
);
1560 Buf_AddBytes(buf
, cp
-word
, word
);
1561 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1562 wordLen
-= (cp
- word
) + pattern
->leftLen
;
1563 word
= cp
+ pattern
->leftLen
;
1567 if ((pattern
->flags
& VAR_SUB_GLOBAL
) == 0) {
1570 pattern
->flags
|= VAR_SUB_MATCHED
;
1576 if (addSpace
&& vpstate
->varSpace
) {
1577 Buf_AddByte(buf
, vpstate
->varSpace
);
1579 Buf_AddBytes(buf
, wordLen
, word
);
1582 * If added characters to the buffer, need to add a space
1583 * before we add any more. If we didn't add any, just return
1584 * the previous value of addSpace.
1586 return ((Buf_Size(buf
) != origSize
) || addSpace
);
1591 if (addSpace
&& vpstate
->varSpace
) {
1592 Buf_AddByte(buf
, vpstate
->varSpace
);
1594 Buf_AddBytes(buf
, wordLen
, word
);
1600 *-----------------------------------------------------------------------
1602 * Print the error caused by a regcomp or regexec call.
1608 * An error gets printed.
1610 *-----------------------------------------------------------------------
1613 VarREError(int errnum
, regex_t
*pat
, const char *str
)
1618 errlen
= regerror(errnum
, pat
, 0, 0);
1619 errbuf
= bmake_malloc(errlen
);
1620 regerror(errnum
, pat
, errbuf
, errlen
);
1621 Error("%s: %s", str
, errbuf
);
1627 *-----------------------------------------------------------------------
1628 * VarRESubstitute --
1629 * Perform a regex substitution on the given word, placing the
1630 * result in the passed buffer.
1633 * TRUE if a space is needed before more characters are added.
1638 *-----------------------------------------------------------------------
1641 VarRESubstitute(GNode
*ctx MAKE_ATTR_UNUSED
,
1642 Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
1643 char *word
, Boolean addSpace
, Buffer
*buf
,
1653 #define MAYBE_ADD_SPACE() \
1654 if (addSpace && !added) \
1655 Buf_AddByte(buf, ' '); \
1662 if ((pat
->flags
& (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) ==
1663 (VAR_SUB_ONE
|VAR_SUB_MATCHED
))
1667 xrv
= regexec(&pat
->re
, wp
, pat
->nsub
, pat
->matches
, flags
);
1672 pat
->flags
|= VAR_SUB_MATCHED
;
1673 if (pat
->matches
[0].rm_so
> 0) {
1675 Buf_AddBytes(buf
, pat
->matches
[0].rm_so
, wp
);
1678 for (rp
= pat
->replace
; *rp
; rp
++) {
1679 if ((*rp
== '\\') && ((rp
[1] == '&') || (rp
[1] == '\\'))) {
1681 Buf_AddByte(buf
,rp
[1]);
1684 else if ((*rp
== '&') ||
1685 ((*rp
== '\\') && isdigit((unsigned char)rp
[1]))) {
1703 if (n
> pat
->nsub
) {
1704 Error("No subexpression %s", &errstr
[0]);
1707 } else if ((pat
->matches
[n
].rm_so
== -1) &&
1708 (pat
->matches
[n
].rm_eo
== -1)) {
1709 Error("No match for subexpression %s", &errstr
[0]);
1713 subbuf
= wp
+ pat
->matches
[n
].rm_so
;
1714 sublen
= pat
->matches
[n
].rm_eo
- pat
->matches
[n
].rm_so
;
1719 Buf_AddBytes(buf
, sublen
, subbuf
);
1723 Buf_AddByte(buf
, *rp
);
1726 wp
+= pat
->matches
[0].rm_eo
;
1727 if (pat
->flags
& VAR_SUB_GLOBAL
) {
1728 flags
|= REG_NOTBOL
;
1729 if (pat
->matches
[0].rm_so
== 0 && pat
->matches
[0].rm_eo
== 0) {
1731 Buf_AddByte(buf
, *wp
);
1740 Buf_AddBytes(buf
, strlen(wp
), wp
);
1744 VarREError(xrv
, &pat
->re
, "Unexpected regex error");
1749 Buf_AddBytes(buf
,strlen(wp
),wp
);
1753 return(addSpace
||added
);
1760 *-----------------------------------------------------------------------
1762 * Implements the :@<temp>@<string>@ modifier of ODE make.
1763 * We set the temp variable named in pattern.lhs to word and expand
1764 * pattern.rhs storing the result in the passed buffer.
1767 * word Word to modify
1768 * addSpace True if space should be added before
1770 * buf Buffer for result
1771 * pattern Datafor substitution
1774 * TRUE if a space is needed before more characters are added.
1779 *-----------------------------------------------------------------------
1782 VarLoopExpand(GNode
*ctx MAKE_ATTR_UNUSED
,
1783 Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
1784 char *word
, Boolean addSpace
, Buffer
*buf
,
1787 VarLoop_t
*loop
= (VarLoop_t
*)loopp
;
1791 if (word
&& *word
) {
1792 Var_Set(loop
->tvar
, word
, loop
->ctxt
, VAR_NO_EXPORT
);
1793 s
= Var_Subst(NULL
, loop
->str
, loop
->ctxt
, loop
->errnum
);
1794 if (s
!= NULL
&& *s
!= '\0') {
1795 if (addSpace
&& *s
!= '\n')
1796 Buf_AddByte(buf
, ' ');
1797 Buf_AddBytes(buf
, (slen
= strlen(s
)), s
);
1798 addSpace
= (slen
> 0 && s
[slen
- 1] != '\n');
1807 *-----------------------------------------------------------------------
1809 * Implements the :[start..end] modifier.
1810 * This is a special case of VarModify since we want to be able
1811 * to scan the list backwards if start > end.
1814 * str String whose words should be trimmed
1815 * seldata words to select
1818 * A string of all the words selected.
1823 *-----------------------------------------------------------------------
1826 VarSelectWords(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1827 const char *str
, VarSelectWords_t
*seldata
)
1829 Buffer buf
; /* Buffer for the new string */
1830 Boolean addSpace
; /* TRUE if need to add a space to the
1831 * buffer before adding the trimmed
1833 char **av
; /* word list */
1834 char *as
; /* word list memory */
1836 int start
, end
, step
;
1841 if (vpstate
->oneBigWord
) {
1842 /* fake what brk_string() would do if there were only one word */
1844 av
= bmake_malloc((ac
+ 1) * sizeof(char *));
1845 as
= bmake_strdup(str
);
1849 av
= brk_string(str
, &ac
, FALSE
, &as
);
1853 * Now sanitize seldata.
1854 * If seldata->start or seldata->end are negative, convert them to
1855 * the positive equivalents (-1 gets converted to argc, -2 gets
1856 * converted to (argc-1), etc.).
1858 if (seldata
->start
< 0)
1859 seldata
->start
= ac
+ seldata
->start
+ 1;
1860 if (seldata
->end
< 0)
1861 seldata
->end
= ac
+ seldata
->end
+ 1;
1864 * We avoid scanning more of the list than we need to.
1866 if (seldata
->start
> seldata
->end
) {
1867 start
= MIN(ac
, seldata
->start
) - 1;
1868 end
= MAX(0, seldata
->end
- 1);
1871 start
= MAX(0, seldata
->start
- 1);
1872 end
= MIN(ac
, seldata
->end
);
1877 (step
< 0 && i
>= end
) || (step
> 0 && i
< end
);
1879 if (av
[i
] && *av
[i
]) {
1880 if (addSpace
&& vpstate
->varSpace
) {
1881 Buf_AddByte(&buf
, vpstate
->varSpace
);
1883 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
1891 return Buf_Destroy(&buf
, FALSE
);
1897 * Replace each word with the result of realpath()
1901 VarRealpath(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1902 char *word
, Boolean addSpace
, Buffer
*buf
,
1903 void *patternp MAKE_ATTR_UNUSED
)
1906 char rbuf
[MAXPATHLEN
];
1909 if (addSpace
&& vpstate
->varSpace
) {
1910 Buf_AddByte(buf
, vpstate
->varSpace
);
1913 rp
= realpath(word
, rbuf
);
1914 if (rp
&& *rp
== '/' && stat(rp
, &st
) == 0)
1917 Buf_AddBytes(buf
, strlen(word
), word
);
1922 *-----------------------------------------------------------------------
1924 * Modify each of the words of the passed string using the given
1925 * function. Used to implement all modifiers.
1928 * str String whose words should be trimmed
1929 * modProc Function to use to modify them
1930 * datum Datum to pass it
1933 * A string of all the words modified appropriately.
1938 *-----------------------------------------------------------------------
1941 VarModify(GNode
*ctx
, Var_Parse_State
*vpstate
,
1943 Boolean (*modProc
)(GNode
*, Var_Parse_State
*, char *,
1944 Boolean
, Buffer
*, void *),
1947 Buffer buf
; /* Buffer for the new string */
1948 Boolean addSpace
; /* TRUE if need to add a space to the
1949 * buffer before adding the trimmed
1951 char **av
; /* word list */
1952 char *as
; /* word list memory */
1958 if (vpstate
->oneBigWord
) {
1959 /* fake what brk_string() would do if there were only one word */
1961 av
= bmake_malloc((ac
+ 1) * sizeof(char *));
1962 as
= bmake_strdup(str
);
1966 av
= brk_string(str
, &ac
, FALSE
, &as
);
1969 for (i
= 0; i
< ac
; i
++) {
1970 addSpace
= (*modProc
)(ctx
, vpstate
, av
[i
], addSpace
, &buf
, datum
);
1976 return Buf_Destroy(&buf
, FALSE
);
1981 VarWordCompare(const void *a
, const void *b
)
1983 int r
= strcmp(*(const char * const *)a
, *(const char * const *)b
);
1988 *-----------------------------------------------------------------------
1990 * Order the words in the string.
1993 * str String whose words should be sorted.
1994 * otype How to order: s - sort, x - random.
1997 * A string containing the words ordered.
2002 *-----------------------------------------------------------------------
2005 VarOrder(const char *str
, const char otype
)
2007 Buffer buf
; /* Buffer for the new string */
2008 char **av
; /* word list [first word does not count] */
2009 char *as
; /* word list memory */
2014 av
= brk_string(str
, &ac
, FALSE
, &as
);
2018 case 's': /* sort alphabetically */
2019 qsort(av
, ac
, sizeof(char *), VarWordCompare
);
2021 case 'x': /* randomize */
2027 * We will use [ac..2] range for mod factors. This will produce
2028 * random numbers in [(ac-1)..0] interval, and minimal
2029 * reasonable value for mod factor is 2 (the mod 1 will produce
2030 * 0 with probability 1).
2032 for (i
= ac
-1; i
> 0; i
--) {
2033 rndidx
= random() % (i
+ 1);
2041 } /* end of switch */
2043 for (i
= 0; i
< ac
; i
++) {
2044 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
2046 Buf_AddByte(&buf
, ' ');
2052 return Buf_Destroy(&buf
, FALSE
);
2057 *-----------------------------------------------------------------------
2059 * Remove adjacent duplicate words.
2062 * str String whose words should be sorted
2065 * A string containing the resulting words.
2070 *-----------------------------------------------------------------------
2073 VarUniq(const char *str
)
2075 Buffer buf
; /* Buffer for new string */
2076 char **av
; /* List of words to affect */
2077 char *as
; /* Word list memory */
2081 av
= brk_string(str
, &ac
, FALSE
, &as
);
2084 for (j
= 0, i
= 1; i
< ac
; i
++)
2085 if (strcmp(av
[i
], av
[j
]) != 0 && (++j
!= i
))
2090 for (i
= 0; i
< ac
; i
++) {
2091 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
2093 Buf_AddByte(&buf
, ' ');
2099 return Buf_Destroy(&buf
, FALSE
);
2104 *-----------------------------------------------------------------------
2106 * Pass through the tstr looking for 1) escaped delimiters,
2107 * '$'s and backslashes (place the escaped character in
2108 * uninterpreted) and 2) unescaped $'s that aren't before
2109 * the delimiter (expand the variable substitution unless flags
2110 * has VAR_NOSUBST set).
2111 * Return the expanded string or NULL if the delimiter was missing
2112 * If pattern is specified, handle escaped ampersands, and replace
2113 * unescaped ampersands with the lhs of the pattern.
2116 * A string of all the words modified appropriately.
2117 * If length is specified, return the string length of the buffer
2118 * If flags is specified and the last character of the pattern is a
2119 * $ set the VAR_MATCH_END bit of flags.
2123 *-----------------------------------------------------------------------
2126 VarGetPattern(GNode
*ctxt
, Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
2127 int errnum
, const char **tstr
, int delim
, int *flags
,
2128 int *length
, VarPattern
*pattern
)
2139 #define IS_A_MATCH(cp, delim) \
2140 ((cp[0] == '\\') && ((cp[1] == delim) || \
2141 (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
2144 * Skim through until the matching delimiter is found;
2145 * pick up variable substitutions on the way. Also allow
2146 * backslashes to quote the delimiter, $, and \, but don't
2147 * touch other backslashes.
2149 for (cp
= *tstr
; *cp
&& (*cp
!= delim
); cp
++) {
2150 if (IS_A_MATCH(cp
, delim
)) {
2151 Buf_AddByte(&buf
, cp
[1]);
2153 } else if (*cp
== '$') {
2154 if (cp
[1] == delim
) {
2156 Buf_AddByte(&buf
, *cp
);
2159 * Unescaped $ at end of pattern => anchor
2162 *flags
|= VAR_MATCH_END
;
2164 if (flags
== NULL
|| (*flags
& VAR_NOSUBST
) == 0) {
2170 * If unescaped dollar sign not before the
2171 * delimiter, assume it's a variable
2172 * substitution and recurse.
2174 cp2
= Var_Parse(cp
, ctxt
, errnum
, &len
, &freeIt
);
2175 Buf_AddBytes(&buf
, strlen(cp2
), cp2
);
2180 const char *cp2
= &cp
[1];
2182 if (*cp2
== PROPEN
|| *cp2
== BROPEN
) {
2184 * Find the end of this variable reference
2185 * and suck it in without further ado.
2186 * It will be interperated later.
2189 int want
= (*cp2
== PROPEN
) ? PRCLOSE
: BRCLOSE
;
2192 for (++cp2
; *cp2
!= '\0' && depth
> 0; ++cp2
) {
2193 if (cp2
[-1] != '\\') {
2200 Buf_AddBytes(&buf
, cp2
- cp
, cp
);
2203 Buf_AddByte(&buf
, *cp
);
2207 else if (pattern
&& *cp
== '&')
2208 Buf_AddBytes(&buf
, pattern
->leftLen
, pattern
->lhs
);
2210 Buf_AddByte(&buf
, *cp
);
2220 *length
= Buf_Size(&buf
);
2221 rstr
= Buf_Destroy(&buf
, FALSE
);
2223 fprintf(debug_file
, "Modifier pattern: \"%s\"\n", rstr
);
2228 *-----------------------------------------------------------------------
2230 * Quote shell meta-characters in the string
2238 *-----------------------------------------------------------------------
2245 /* This should cover most shells :-( */
2246 static const char meta
[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
2247 const char *newline
;
2250 if ((newline
= Shell_GetNewline()) == NULL
)
2252 nlen
= strlen(newline
);
2255 while (*str
!= '\0') {
2256 if ((len
= strcspn(str
, meta
)) != 0) {
2257 Buf_AddBytes(&buf
, len
, str
);
2259 } else if (*str
== '\n') {
2260 Buf_AddBytes(&buf
, nlen
, newline
);
2263 Buf_AddByte(&buf
, '\\');
2264 Buf_AddByte(&buf
, *str
);
2268 str
= Buf_Destroy(&buf
, FALSE
);
2270 fprintf(debug_file
, "QuoteMeta: [%s]\n", str
);
2275 *-----------------------------------------------------------------------
2277 * Hash the string using the MurmurHash3 algorithm.
2278 * Output is computed using 32bit Little Endian arithmetic.
2281 * str String to modify
2284 * Hash value of str, encoded as 8 hex digits.
2289 *-----------------------------------------------------------------------
2294 static const char hexdigits
[16] = "0123456789abcdef";
2297 unsigned char *ustr
= (unsigned char *)str
;
2298 uint32_t h
, k
, c1
, c2
;
2307 for (len
= len2
; len
; ) {
2311 k
= (ustr
[3] << 24) | (ustr
[2] << 16) | (ustr
[1] << 8) | ustr
[0];
2316 k
|= (ustr
[2] << 16);
2318 k
|= (ustr
[1] << 8);
2323 c1
= c1
* 5 + 0x7b7d159cU
;
2324 c2
= c2
* 5 + 0x6bce6396U
;
2326 k
= (k
<< 11) ^ (k
>> 21);
2328 h
= (h
<< 13) ^ (h
>> 19);
2329 h
= h
* 5 + 0x52dce729U
;
2339 for (len
= 0; len
< 8; ++len
) {
2340 Buf_AddByte(&buf
, hexdigits
[h
& 15]);
2344 return Buf_Destroy(&buf
, FALSE
);
2348 *-----------------------------------------------------------------------
2350 * Change the string to all uppercase or all lowercase
2353 * str String to modify
2354 * upper TRUE -> uppercase, else lowercase
2357 * The string with case changed
2362 *-----------------------------------------------------------------------
2365 VarChangeCase(char *str
, int upper
)
2368 int (*modProc
)(int);
2370 modProc
= (upper
? toupper
: tolower
);
2372 for (; *str
; str
++) {
2373 Buf_AddByte(&buf
, modProc(*str
));
2375 return Buf_Destroy(&buf
, FALSE
);
2379 VarStrftime(const char *fmt
, int zulu
)
2387 strftime(buf
, sizeof(buf
), fmt
, zulu
? gmtime(&utc
) : localtime(&utc
));
2389 buf
[sizeof(buf
) - 1] = '\0';
2390 return bmake_strdup(buf
);
2394 * Now we need to apply any modifiers the user wants applied.
2396 * :M<pattern> words which match the given <pattern>.
2397 * <pattern> is of the standard file
2399 * :N<pattern> words which do not match the given <pattern>.
2400 * :S<d><pat1><d><pat2><d>[1gW]
2401 * Substitute <pat2> for <pat1> in the value
2402 * :C<d><pat1><d><pat2><d>[1gW]
2403 * Substitute <pat2> for regex <pat1> in the value
2404 * :H Substitute the head of each word
2405 * :T Substitute the tail of each word
2406 * :E Substitute the extension (minus '.') of
2408 * :R Substitute the root of each word
2409 * (pathname minus the suffix).
2410 * :O ("Order") Alphabeticaly sort words in variable.
2411 * :Ox ("intermiX") Randomize words in variable.
2412 * :u ("uniq") Remove adjacent duplicate words.
2413 * :tu Converts the variable contents to uppercase.
2414 * :tl Converts the variable contents to lowercase.
2415 * :ts[c] Sets varSpace - the char used to
2416 * separate words to 'c'. If 'c' is
2417 * omitted then no separation is used.
2418 * :tW Treat the variable contents as a single
2419 * word, even if it contains spaces.
2420 * (Mnemonic: one big 'W'ord.)
2421 * :tw Treat the variable contents as multiple
2422 * space-separated words.
2423 * (Mnemonic: many small 'w'ords.)
2424 * :[index] Select a single word from the value.
2425 * :[start..end] Select multiple words from the value.
2426 * :[*] or :[0] Select the entire value, as a single
2427 * word. Equivalent to :tW.
2428 * :[@] Select the entire value, as multiple
2429 * words. Undoes the effect of :[*].
2430 * Equivalent to :tw.
2431 * :[#] Returns the number of words in the value.
2433 * :?<true-value>:<false-value>
2434 * If the variable evaluates to true, return
2435 * true value, else return the second value.
2436 * :lhs=rhs Like :S, but the rhs goes to the end of
2438 * :sh Treat the current value as a command
2439 * to be run, new value is its output.
2440 * The following added so we can handle ODE makefiles.
2441 * :@<tmpvar>@<newval>@
2442 * Assign a temporary local variable <tmpvar>
2443 * to the current value of each word in turn
2444 * and replace each word with the result of
2445 * evaluating <newval>
2446 * :D<newval> Use <newval> as value if variable defined
2447 * :U<newval> Use <newval> as value if variable undefined
2448 * :L Use the name of the variable as the value.
2449 * :P Use the path of the node that has the same
2450 * name as the variable as the value. This
2451 * basically includes an implied :L so that
2452 * the common method of refering to the path
2453 * of your dependent 'x' in a rule is to use
2454 * the form '${x:P}'.
2455 * :!<cmd>! Run cmd much the same as :sh run's the
2456 * current value of the variable.
2457 * The ::= modifiers, actually assign a value to the variable.
2458 * Their main purpose is in supporting modifiers of .for loop
2459 * iterators and other obscure uses. They always expand to
2460 * nothing. In a target rule that would otherwise expand to an
2461 * empty line they can be preceded with @: to keep make happy.
2465 * .for i in ${.TARGET} ${.TARGET:R}.gz
2470 * ::=<str> Assigns <str> as the new value of variable.
2471 * ::?=<str> Assigns <str> as value of variable if
2472 * it was not already set.
2473 * ::+=<str> Appends <str> to variable.
2474 * ::!=<cmd> Assigns output of <cmd> as the new value of
2478 /* we now have some modifiers with long names */
2479 #define STRMOD_MATCH(s, want, n) \
2480 (strncmp(s, want, n) == 0 && (s[n] == endc || s[n] == ':'))
2483 ApplyModifiers(char *nstr
, const char *tstr
,
2484 int startc
, int endc
,
2485 Var
*v
, GNode
*ctxt
, Boolean errnum
,
2486 int *lengthPtr
, void **freePtr
)
2489 const char *cp
; /* Secondary pointer into str (place marker
2491 char *newStr
; /* New value to return */
2492 char termc
; /* Character which terminated scan */
2493 int cnt
; /* Used to count brace pairs when variable in
2494 * in parens or braces */
2496 int modifier
; /* that we are processing */
2497 Var_Parse_State parsestate
; /* Flags passed to helper functions */
2500 parsestate
.oneBigWord
= FALSE
;
2501 parsestate
.varSpace
= ' '; /* word separator */
2505 while (*tstr
&& *tstr
!= endc
) {
2509 * We may have some complex modifiers in a variable.
2516 rval
= Var_Parse(tstr
, ctxt
, errnum
, &rlen
, &freeIt
);
2519 * If we have not parsed up to endc or ':',
2520 * we are not interested.
2522 if (rval
!= NULL
&& *rval
&&
2523 (c
= tstr
[rlen
]) != '\0' &&
2532 fprintf(debug_file
, "Got '%s' from '%.*s'%.*s\n",
2533 rval
, rlen
, tstr
, rlen
, tstr
+ rlen
);
2538 if (rval
!= NULL
&& *rval
) {
2541 nstr
= ApplyModifiers(nstr
, rval
,
2543 v
, ctxt
, errnum
, &used
, freePtr
);
2544 if (nstr
== var_Error
2545 || (nstr
== varNoError
&& errnum
== 0)
2546 || strlen(rval
) != (size_t) used
) {
2549 goto out
; /* error already reported */
2556 else if (!*tstr
&& endc
) {
2557 Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc
, v
->name
);
2564 fprintf(debug_file
, "Applying :%c to \"%s\"\n", *tstr
, nstr
);
2567 switch ((modifier
= *tstr
)) {
2570 if (tstr
[1] == '=' ||
2572 (tstr
[1] == '!' || tstr
[1] == '+' || tstr
[1] == '?'))) {
2574 * "::=", "::!=", "::+=", or "::?="
2576 GNode
*v_ctxt
; /* context where v belongs */
2582 if (v
->name
[0] == 0)
2588 if (v
->flags
& VAR_JUNK
) {
2590 * We need to bmake_strdup() it incase
2591 * VarGetPattern() recurses.
2594 v
->name
= bmake_strdup(v
->name
);
2595 } else if (ctxt
!= VAR_GLOBAL
) {
2596 Var
*gv
= VarFind(v
->name
, ctxt
, 0);
2598 v_ctxt
= VAR_GLOBAL
;
2600 VarFreeEnv(gv
, TRUE
);
2603 switch ((how
= *tstr
)) {
2613 delim
= startc
== PROPEN
? PRCLOSE
: BRCLOSE
;
2616 pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2620 if (v
->flags
& VAR_JUNK
) {
2621 /* restore original name */
2625 if (pattern
.rhs
== NULL
)
2633 Var_Append(v
->name
, pattern
.rhs
, v_ctxt
);
2636 newStr
= Cmd_Exec(pattern
.rhs
, &emsg
);
2640 Var_Set(v
->name
, newStr
, v_ctxt
, 0);
2645 if ((v
->flags
& VAR_JUNK
) == 0)
2649 Var_Set(v
->name
, pattern
.rhs
, v_ctxt
, 0);
2652 free(UNCONST(pattern
.rhs
));
2656 goto default_case
; /* "::<unrecognised>" */
2661 int flags
= VAR_NOSUBST
;
2665 if ((loop
.tvar
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2667 &flags
, &loop
.tvarLen
,
2671 if ((loop
.str
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2673 &flags
, &loop
.strLen
,
2680 loop
.errnum
= errnum
;
2682 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarLoopExpand
,
2691 Buffer buf
; /* Buffer for patterns */
2692 int wantit
; /* want data in buffer */
2695 * Pass through tstr looking for 1) escaped delimiters,
2696 * '$'s and backslashes (place the escaped character in
2697 * uninterpreted) and 2) unescaped $'s that aren't before
2698 * the delimiter (expand the variable substitution).
2699 * The result is left in the Buffer buf.
2703 *cp
!= endc
&& *cp
!= ':' && *cp
!= '\0';
2705 if ((*cp
== '\\') &&
2711 Buf_AddByte(&buf
, cp
[1]);
2713 } else if (*cp
== '$') {
2715 * If unescaped dollar sign, assume it's a
2716 * variable substitution and recurse.
2722 cp2
= Var_Parse(cp
, ctxt
, errnum
, &len
, &freeIt
);
2723 Buf_AddBytes(&buf
, strlen(cp2
), cp2
);
2728 Buf_AddByte(&buf
, *cp
);
2735 wantit
= ((v
->flags
& VAR_JUNK
) != 0);
2737 wantit
= ((v
->flags
& VAR_JUNK
) == 0);
2738 if ((v
->flags
& VAR_JUNK
) != 0)
2739 v
->flags
|= VAR_KEEP
;
2741 newStr
= Buf_Destroy(&buf
, FALSE
);
2744 Buf_Destroy(&buf
, TRUE
);
2750 if ((v
->flags
& VAR_JUNK
) != 0)
2751 v
->flags
|= VAR_KEEP
;
2752 newStr
= bmake_strdup(v
->name
);
2761 if ((v
->flags
& VAR_JUNK
) != 0)
2762 v
->flags
|= VAR_KEEP
;
2763 gn
= Targ_FindNode(v
->name
, TARG_NOCREATE
);
2764 if (gn
== NULL
|| gn
->type
& OP_NOPATH
) {
2766 } else if (gn
->path
) {
2767 newStr
= bmake_strdup(gn
->path
);
2769 newStr
= Dir_FindFile(v
->name
, Suff_FindPath(gn
));
2772 newStr
= bmake_strdup(v
->name
);
2787 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2789 NULL
, &pattern
.rightLen
,
2792 newStr
= Cmd_Exec(pattern
.rhs
, &emsg
);
2793 free(UNCONST(pattern
.rhs
));
2798 if (v
->flags
& VAR_JUNK
) {
2799 v
->flags
|= VAR_KEEP
;
2806 * Look for the closing ']', recursively
2807 * expanding any embedded variables.
2809 * estr is a pointer to the expanded result,
2810 * which we must free().
2814 cp
= tstr
+1; /* point to char after '[' */
2815 delim
= ']'; /* look for closing ']' */
2816 estr
= VarGetPattern(ctxt
, &parsestate
,
2820 goto cleanup
; /* report missing ']' */
2821 /* now cp points just after the closing ']' */
2823 if (cp
[0] != ':' && cp
[0] != endc
) {
2824 /* Found junk after ']' */
2828 if (estr
[0] == '\0') {
2829 /* Found empty square brackets in ":[]". */
2832 } else if (estr
[0] == '#' && estr
[1] == '\0') {
2836 * We will need enough space for the decimal
2837 * representation of an int. We calculate the
2838 * space needed for the octal representation,
2839 * and add enough slop to cope with a '-' sign
2840 * (which should never be needed) and a '\0'
2841 * string terminator.
2844 (sizeof(int) * CHAR_BIT
+ 2) / 3 + 2;
2846 newStr
= bmake_malloc(newStrSize
);
2847 if (parsestate
.oneBigWord
) {
2848 strncpy(newStr
, "1", newStrSize
);
2850 /* XXX: brk_string() is a rather expensive
2851 * way of counting words. */
2856 av
= brk_string(nstr
, &ac
, FALSE
, &as
);
2857 snprintf(newStr
, newStrSize
, "%d", ac
);
2864 } else if (estr
[0] == '*' && estr
[1] == '\0') {
2866 parsestate
.oneBigWord
= TRUE
;
2871 } else if (estr
[0] == '@' && estr
[1] == '\0') {
2873 parsestate
.oneBigWord
= FALSE
;
2880 * We expect estr to contain a single
2881 * integer for :[N], or two integers
2882 * separated by ".." for :[start..end].
2886 VarSelectWords_t seldata
= { 0, 0 };
2888 seldata
.start
= strtol(estr
, &ep
, 0);
2890 /* Found junk instead of a number */
2893 } else if (ep
[0] == '\0') {
2894 /* Found only one integer in :[N] */
2895 seldata
.end
= seldata
.start
;
2896 } else if (ep
[0] == '.' && ep
[1] == '.' &&
2898 /* Expecting another integer after ".." */
2900 seldata
.end
= strtol(ep
, &ep
, 0);
2901 if (ep
[0] != '\0') {
2902 /* Found junk after ".." */
2907 /* Found junk instead of ".." */
2912 * Now seldata is properly filled in,
2913 * but we still have to check for 0 as
2916 if (seldata
.start
== 0 && seldata
.end
== 0) {
2917 /* ":[0]" or perhaps ":[0..0]" */
2918 parsestate
.oneBigWord
= TRUE
;
2923 } else if (seldata
.start
== 0 ||
2925 /* ":[0..N]" or ":[N..0]" */
2930 * Normal case: select the words
2931 * described by seldata.
2933 newStr
= VarSelectWords(ctxt
, &parsestate
,
2943 cp
= tstr
+ 1; /* make sure it is set */
2944 if (STRMOD_MATCH(tstr
, "gmtime", 6)) {
2945 newStr
= VarStrftime(nstr
, 1);
2953 cp
= tstr
+ 1; /* make sure it is set */
2954 if (STRMOD_MATCH(tstr
, "hash", 4)) {
2955 newStr
= VarHash(nstr
);
2963 cp
= tstr
+ 1; /* make sure it is set */
2964 if (STRMOD_MATCH(tstr
, "localtime", 9)) {
2965 newStr
= VarStrftime(nstr
, 0);
2974 cp
= tstr
+ 1; /* make sure it is set */
2975 if (tstr
[1] != endc
&& tstr
[1] != ':') {
2976 if (tstr
[1] == 's') {
2978 * Use the char (if any) at tstr[2]
2979 * as the word separator.
2983 if (tstr
[2] != endc
&&
2984 (tstr
[3] == endc
|| tstr
[3] == ':')) {
2985 /* ":ts<unrecognised><endc>" or
2986 * ":ts<unrecognised>:" */
2987 parsestate
.varSpace
= tstr
[2];
2989 } else if (tstr
[2] == endc
|| tstr
[2] == ':') {
2990 /* ":ts<endc>" or ":ts:" */
2991 parsestate
.varSpace
= 0; /* no separator */
2993 } else if (tstr
[2] == '\\') {
2996 parsestate
.varSpace
= '\n';
3000 parsestate
.varSpace
= '\t';
3004 if (isdigit((unsigned char)tstr
[3])) {
3007 parsestate
.varSpace
=
3008 strtoul(&tstr
[3], &ep
, 0);
3009 if (*ep
!= ':' && *ep
!= endc
)
3014 * ":ts<backslash><unrecognised>".
3022 * Found ":ts<unrecognised><unrecognised>".
3030 * We cannot be certain that VarModify
3031 * will be used - even if there is a
3032 * subsequent modifier, so do a no-op
3033 * VarSubstitute now to for str to be
3034 * re-expanded without the spaces.
3036 pattern
.flags
= VAR_SUB_ONE
;
3037 pattern
.lhs
= pattern
.rhs
= "\032";
3038 pattern
.leftLen
= pattern
.rightLen
= 1;
3040 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3043 } else if (tstr
[2] == endc
|| tstr
[2] == ':') {
3045 * Check for two-character options:
3048 if (tstr
[1] == 'A') { /* absolute path */
3049 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3053 } else if (tstr
[1] == 'u' || tstr
[1] == 'l') {
3054 newStr
= VarChangeCase(nstr
, (tstr
[1] == 'u'));
3057 } else if (tstr
[1] == 'W' || tstr
[1] == 'w') {
3058 parsestate
.oneBigWord
= (tstr
[1] == 'W');
3063 /* Found ":t<unrecognised>:" or
3064 * ":t<unrecognised><endc>". */
3069 * Found ":t<unrecognised><unrecognised>".
3075 * Found ":t<endc>" or ":t:".
3085 const char *endpat
; /* points just after end of pattern */
3087 Boolean copy
; /* pattern should be, or has been, copied */
3095 * In the loop below, ignore ':' unless we are at
3096 * (or back to) the original brace level.
3097 * XXX This will likely not work right if $() and ${}
3101 *cp
!= '\0' && !(*cp
== ':' && nest
== 1);
3106 cp
[1] == endc
|| cp
[1] == startc
)) {
3116 if (*cp
== '(' || *cp
== '{')
3118 if (*cp
== ')' || *cp
== '}') {
3128 * Need to compress the \:'s out of the pattern, so
3129 * allocate enough room to hold the uncompressed
3130 * pattern (note that cp started at tstr+1, so
3131 * cp - tstr takes the null byte into account) and
3132 * compress the pattern into the space.
3134 pattern
= bmake_malloc(cp
- tstr
);
3135 for (cp2
= pattern
, cp
= tstr
+ 1;
3139 if ((*cp
== '\\') && (cp
+1 < endpat
) &&
3140 (cp
[1] == ':' || cp
[1] == endc
)) {
3149 * Either Var_Subst or VarModify will need a
3150 * nul-terminated string soon, so construct one now.
3152 pattern
= bmake_strndup(tstr
+1, endpat
- (tstr
+ 1));
3156 * pattern contains embedded '$', so use Var_Subst to
3160 pattern
= Var_Subst(NULL
, cp2
, ctxt
, errnum
);
3164 fprintf(debug_file
, "Pattern for [%s] is [%s]\n", nstr
,
3167 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarMatch
,
3170 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarNoMatch
,
3179 Var_Parse_State tmpparsestate
;
3182 tmpparsestate
= parsestate
;
3187 * If pattern begins with '^', it is anchored to the
3188 * start of the word -- skip over it and flag pattern.
3191 pattern
.flags
|= VAR_MATCH_START
;
3196 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3203 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3210 * Check for global substitution. If 'g' after the final
3211 * delimiter, substitution is global and is marked that
3217 pattern
.flags
|= VAR_SUB_GLOBAL
;
3220 pattern
.flags
|= VAR_SUB_ONE
;
3223 tmpparsestate
.oneBigWord
= TRUE
;
3230 newStr
= VarModify(ctxt
, &tmpparsestate
, nstr
,
3235 * Free the two strings.
3237 free(UNCONST(pattern
.lhs
));
3238 free(UNCONST(pattern
.rhs
));
3247 /* find ':', and then substitute accordingly */
3253 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3259 /* BROPEN or PROPEN */
3261 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3269 if (Cond_EvalExpression(NULL
, v
->name
, &value
, 0)
3271 Error("Bad conditional expression `%s' in %s?%s:%s",
3272 v
->name
, v
->name
, pattern
.lhs
, pattern
.rhs
);
3277 newStr
= UNCONST(pattern
.lhs
);
3278 free(UNCONST(pattern
.rhs
));
3280 newStr
= UNCONST(pattern
.rhs
);
3281 free(UNCONST(pattern
.lhs
));
3283 if (v
->flags
& VAR_JUNK
) {
3284 v
->flags
|= VAR_KEEP
;
3291 VarREPattern pattern
;
3294 Var_Parse_State tmpparsestate
;
3297 tmpparsestate
= parsestate
;
3303 if ((re
= VarGetPattern(ctxt
, &parsestate
, errnum
, &cp
, delim
,
3304 NULL
, NULL
, NULL
)) == NULL
)
3307 if ((pattern
.replace
= VarGetPattern(ctxt
, &parsestate
,
3308 errnum
, &cp
, delim
, NULL
,
3309 NULL
, NULL
)) == NULL
){
3317 pattern
.flags
|= VAR_SUB_GLOBAL
;
3320 pattern
.flags
|= VAR_SUB_ONE
;
3323 tmpparsestate
.oneBigWord
= TRUE
;
3331 error
= regcomp(&pattern
.re
, re
, REG_EXTENDED
);
3334 *lengthPtr
= cp
- start
+ 1;
3335 VarREError(error
, &pattern
.re
, "RE substitution error");
3336 free(pattern
.replace
);
3340 pattern
.nsub
= pattern
.re
.re_nsub
+ 1;
3341 if (pattern
.nsub
< 1)
3343 if (pattern
.nsub
> 10)
3345 pattern
.matches
= bmake_malloc(pattern
.nsub
*
3346 sizeof(regmatch_t
));
3347 newStr
= VarModify(ctxt
, &tmpparsestate
, nstr
,
3350 regfree(&pattern
.re
);
3351 free(pattern
.replace
);
3352 free(pattern
.matches
);
3358 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3359 newStr
= VarQuote(nstr
);
3366 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3367 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarTail
,
3375 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3376 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarHead
,
3384 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3385 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarSuffix
,
3393 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3394 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarRoot
,
3405 cp
= tstr
+ 1; /* skip to the rest in any case */
3406 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3409 } else if ( (tstr
[1] == 'x') &&
3410 (tstr
[2] == endc
|| tstr
[2] == ':') ) {
3417 newStr
= VarOrder(nstr
, otype
);
3421 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3422 newStr
= VarUniq(nstr
);
3430 if (tstr
[1] == 'h' && (tstr
[2] == endc
|| tstr
[2] == ':')) {
3432 newStr
= Cmd_Exec(nstr
, &emsg
);
3446 * This can either be a bogus modifier or a System-V
3447 * substitution command.
3455 * First we make a pass through the string trying
3456 * to verify it is a SYSV-make-style translation:
3457 * it must be: <string1>=<string2>)
3461 while (*cp
!= '\0' && cnt
) {
3464 /* continue looking for endc */
3466 else if (*cp
== endc
)
3468 else if (*cp
== startc
)
3473 if (*cp
== endc
&& eqFound
) {
3476 * Now we break this sucker into the lhs and
3477 * rhs. We must null terminate them of course.
3481 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
,
3482 errnum
, &cp
, delim
, &pattern
.flags
,
3483 &pattern
.leftLen
, NULL
)) == NULL
)
3486 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
,
3487 errnum
, &cp
, delim
, NULL
, &pattern
.rightLen
,
3492 * SYSV modifications happen through the whole
3493 * string. Note the pattern is anchored at the end.
3497 if (pattern
.leftLen
== 0 && *nstr
== '\0') {
3498 newStr
= nstr
; /* special case */
3500 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3504 free(UNCONST(pattern
.lhs
));
3505 free(UNCONST(pattern
.rhs
));
3509 Error("Unknown modifier '%c'", *tstr
);
3511 *cp
!= ':' && *cp
!= endc
&& *cp
!= '\0';
3520 fprintf(debug_file
, "Result of :%c is \"%s\"\n", modifier
, newStr
);
3523 if (newStr
!= nstr
) {
3529 if (nstr
!= var_Error
&& nstr
!= varNoError
) {
3533 if (termc
== '\0' && endc
!= '\0') {
3534 Error("Unclosed variable specification (expecting '%c') for \"%s\" (value \"%s\") modifier %c", endc
, v
->name
, nstr
, modifier
);
3535 } else if (termc
== ':') {
3541 *lengthPtr
= tstr
- start
;
3546 Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr
, ":)}"), tstr
,
3550 *lengthPtr
= cp
- start
;
3552 Error("Unclosed substitution for %s (%c missing)",
3562 *-----------------------------------------------------------------------
3564 * Given the start of a variable invocation, extract the variable
3565 * name and find its value, then modify it according to the
3569 * str The string to parse
3570 * ctxt The context for the variable
3571 * errnum TRUE if undefined variables are an error
3572 * lengthPtr OUT: The length of the specification
3573 * freePtr OUT: Non-NULL if caller should free *freePtr
3576 * The (possibly-modified) value of the variable or var_Error if the
3577 * specification is invalid. The length of the specification is
3578 * placed in *lengthPtr (for invalid specifications, this is just
3580 * If *freePtr is non-NULL then it's a pointer that the caller
3581 * should pass to free() to free memory used by the result.
3586 *-----------------------------------------------------------------------
3588 /* coverity[+alloc : arg-*4] */
3590 Var_Parse(const char *str
, GNode
*ctxt
, Boolean errnum
, int *lengthPtr
,
3593 const char *tstr
; /* Pointer into str */
3594 Var
*v
; /* Variable in invocation */
3595 Boolean haveModifier
;/* TRUE if have modifiers for the variable */
3596 char endc
; /* Ending character when variable in parens
3598 char startc
; /* Starting character when variable in parens
3600 int vlen
; /* Length of variable name */
3601 const char *start
; /* Points to original start of str */
3602 char *nstr
; /* New string, used during expansion */
3603 Boolean dynamic
; /* TRUE if the variable is local and we're
3604 * expanding it in a non-local context. This
3605 * is done to support dynamic sources. The
3606 * result is just the invocation, unaltered */
3607 Var_Parse_State parsestate
; /* Flags passed to helper functions */
3613 parsestate
.oneBigWord
= FALSE
;
3614 parsestate
.varSpace
= ' '; /* word separator */
3617 if (startc
!= PROPEN
&& startc
!= BROPEN
) {
3619 * If it's not bounded by braces of some sort, life is much simpler.
3620 * We just need to check for the first character and return the
3621 * value if it exists.
3624 /* Error out some really stupid names */
3625 if (startc
== '\0' || strchr(")}:$", startc
)) {
3632 v
= VarFind(name
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
3636 if ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)) {
3638 * If substituting a local variable in a non-local context,
3639 * assume it's for dynamic source stuff. We have to handle
3640 * this specially and return the longhand for the variable
3641 * with the dollar sign escaped so it makes it back to the
3642 * caller. Only four of the local variables are treated
3643 * specially as they are the only four that will be set
3644 * when dynamic sources are expanded.
3648 return UNCONST("$(.TARGET)");
3650 return UNCONST("$(.ARCHIVE)");
3652 return UNCONST("$(.PREFIX)");
3654 return UNCONST("$(.MEMBER)");
3660 return (errnum
? var_Error
: varNoError
);
3662 haveModifier
= FALSE
;
3667 Buffer buf
; /* Holds the variable name */
3669 endc
= startc
== PROPEN
? PRCLOSE
: BRCLOSE
;
3673 * Skip to the end character or a colon, whichever comes first.
3675 for (tstr
= str
+ 2;
3676 *tstr
!= '\0' && *tstr
!= endc
&& *tstr
!= ':';
3680 * A variable inside a variable, expand
3685 char *rval
= Var_Parse(tstr
, ctxt
, errnum
, &rlen
, &freeIt
);
3687 Buf_AddBytes(&buf
, strlen(rval
), rval
);
3694 Buf_AddByte(&buf
, *tstr
);
3697 haveModifier
= TRUE
;
3698 } else if (*tstr
!= '\0') {
3699 haveModifier
= FALSE
;
3702 * If we never did find the end character, return NULL
3703 * right now, setting the length to be the distance to
3704 * the end of the string, since that's what make does.
3706 *lengthPtr
= tstr
- str
;
3707 Buf_Destroy(&buf
, TRUE
);
3710 str
= Buf_GetAll(&buf
, &vlen
);
3713 * At this point, str points into newly allocated memory from
3714 * buf, containing only the name of the variable.
3716 * start and tstr point into the const string that was pointed
3717 * to by the original value of the str parameter. start points
3718 * to the '$' at the beginning of the string, while tstr points
3719 * to the char just after the end of the variable name -- this
3720 * will be '\0', ':', PRCLOSE, or BRCLOSE.
3723 v
= VarFind(str
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
3725 * Check also for bogus D and F forms of local variables since we're
3726 * in a local context and the name is the right length.
3728 if ((v
== NULL
) && (ctxt
!= VAR_CMD
) && (ctxt
!= VAR_GLOBAL
) &&
3729 (vlen
== 2) && (str
[1] == 'F' || str
[1] == 'D') &&
3730 strchr("@%*!<>", str
[0]) != NULL
) {
3732 * Well, it's local -- go look for it.
3736 v
= VarFind(name
, ctxt
, 0);
3740 * No need for nested expansion or anything, as we're
3741 * the only one who sets these things and we sure don't
3742 * but nested invocations in them...
3744 nstr
= Buf_GetAll(&v
->val
, NULL
);
3746 if (str
[1] == 'D') {
3747 nstr
= VarModify(ctxt
, &parsestate
, nstr
, VarHead
,
3750 nstr
= VarModify(ctxt
, &parsestate
, nstr
, VarTail
,
3754 * Resulting string is dynamically allocated, so
3755 * tell caller to free it.
3758 *lengthPtr
= tstr
-start
+1;
3759 Buf_Destroy(&buf
, TRUE
);
3760 VarFreeEnv(v
, TRUE
);
3767 (((vlen
== 2) && (str
[1] == 'F' || str
[1] == 'D')))) &&
3768 ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)))
3771 * If substituting a local variable in a non-local context,
3772 * assume it's for dynamic source stuff. We have to handle
3773 * this specially and return the longhand for the variable
3774 * with the dollar sign escaped so it makes it back to the
3775 * caller. Only four of the local variables are treated
3776 * specially as they are the only four that will be set
3777 * when dynamic sources are expanded.
3787 } else if ((vlen
> 2) && (*str
== '.') &&
3788 isupper((unsigned char) str
[1]) &&
3789 ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)))
3794 if ((strncmp(str
, ".TARGET", len
) == 0) ||
3795 (strncmp(str
, ".ARCHIVE", len
) == 0) ||
3796 (strncmp(str
, ".PREFIX", len
) == 0) ||
3797 (strncmp(str
, ".MEMBER", len
) == 0))
3803 if (!haveModifier
) {
3805 * No modifiers -- have specification length so we can return
3808 *lengthPtr
= tstr
- start
+ 1;
3810 char *pstr
= bmake_strndup(start
, *lengthPtr
);
3812 Buf_Destroy(&buf
, TRUE
);
3815 Buf_Destroy(&buf
, TRUE
);
3816 return (errnum
? var_Error
: varNoError
);
3820 * Still need to get to the end of the variable specification,
3821 * so kludge up a Var structure for the modifications
3823 v
= bmake_malloc(sizeof(Var
));
3824 v
->name
= UNCONST(str
);
3825 Buf_Init(&v
->val
, 1);
3826 v
->flags
= VAR_JUNK
;
3827 Buf_Destroy(&buf
, FALSE
);
3830 Buf_Destroy(&buf
, TRUE
);
3833 if (v
->flags
& VAR_IN_USE
) {
3834 Fatal("Variable %s is recursive.", v
->name
);
3837 v
->flags
|= VAR_IN_USE
;
3840 * Before doing any modification, we have to make sure the value
3841 * has been fully expanded. If it looks like recursion might be
3842 * necessary (there's a dollar sign somewhere in the variable's value)
3843 * we just call Var_Subst to do any other substitutions that are
3844 * necessary. Note that the value returned by Var_Subst will have
3845 * been dynamically-allocated, so it will need freeing when we
3848 nstr
= Buf_GetAll(&v
->val
, NULL
);
3849 if (strchr(nstr
, '$') != NULL
) {
3850 nstr
= Var_Subst(NULL
, nstr
, ctxt
, errnum
);
3854 v
->flags
&= ~VAR_IN_USE
;
3856 if ((nstr
!= NULL
) && haveModifier
) {
3859 * Skip initial colon.
3863 nstr
= ApplyModifiers(nstr
, tstr
, startc
, endc
,
3864 v
, ctxt
, errnum
, &used
, freePtr
);
3868 *lengthPtr
= tstr
- start
+ 1;
3870 *lengthPtr
= tstr
- start
;
3873 if (v
->flags
& VAR_FROM_ENV
) {
3874 Boolean destroy
= FALSE
;
3876 if (nstr
!= Buf_GetAll(&v
->val
, NULL
)) {
3880 * Returning the value unmodified, so tell the caller to free
3885 VarFreeEnv(v
, destroy
);
3886 } else if (v
->flags
& VAR_JUNK
) {
3888 * Perform any free'ing needed and set *freePtr to NULL so the caller
3889 * doesn't try to free a static pointer.
3890 * If VAR_KEEP is also set then we want to keep str as is.
3892 if (!(v
->flags
& VAR_KEEP
)) {
3898 nstr
= bmake_strndup(start
, *lengthPtr
);
3901 nstr
= errnum
? var_Error
: varNoError
;
3904 if (nstr
!= Buf_GetAll(&v
->val
, NULL
))
3905 Buf_Destroy(&v
->val
, TRUE
);
3913 *-----------------------------------------------------------------------
3915 * Substitute for all variables in the given string in the given context
3916 * If undefErr is TRUE, Parse_Error will be called when an undefined
3917 * variable is encountered.
3920 * var Named variable || NULL for all
3921 * str the string which to substitute
3922 * ctxt the context wherein to find variables
3923 * undefErr TRUE if undefineds are an error
3926 * The resulting string.
3929 * None. The old string must be freed by the caller
3930 *-----------------------------------------------------------------------
3933 Var_Subst(const char *var
, const char *str
, GNode
*ctxt
, Boolean undefErr
)
3935 Buffer buf
; /* Buffer for forming things */
3936 char *val
; /* Value to substitute for a variable */
3937 int length
; /* Length of the variable invocation */
3938 Boolean trailingBslash
; /* variable ends in \ */
3939 void *freeIt
= NULL
; /* Set if it should be freed */
3940 static Boolean errorReported
; /* Set true if an error has already
3941 * been reported to prevent a plethora
3942 * of messages when recursing */
3945 errorReported
= FALSE
;
3946 trailingBslash
= FALSE
;
3949 if (*str
== '\n' && trailingBslash
)
3950 Buf_AddByte(&buf
, ' ');
3951 if (var
== NULL
&& (*str
== '$') && (str
[1] == '$')) {
3953 * A dollar sign may be escaped either with another dollar sign.
3954 * In such a case, we skip over the escape character and store the
3955 * dollar sign into the buffer directly.
3958 Buf_AddByte(&buf
, *str
);
3960 } else if (*str
!= '$') {
3962 * Skip as many characters as possible -- either to the end of
3963 * the string or to the next dollar sign (variable invocation).
3967 for (cp
= str
++; *str
!= '$' && *str
!= '\0'; str
++)
3969 Buf_AddBytes(&buf
, str
- cp
, cp
);
3974 if (str
[1] == '\0') {
3975 /* A trailing $ is kind of a special case */
3976 Buf_AddByte(&buf
, str
[0]);
3979 } else if (str
[1] != PROPEN
&& str
[1] != BROPEN
) {
3980 if (str
[1] != *var
|| strlen(var
) > 1) {
3981 Buf_AddBytes(&buf
, 2, str
);
3993 * Scan up to the end of the variable name.
3995 for (p
= &str
[2]; *p
&&
3996 *p
!= ':' && *p
!= PRCLOSE
&& *p
!= BRCLOSE
; p
++)
4000 * A variable inside the variable. We cannot expand
4001 * the external variable yet, so we try again with
4005 Buf_AddBytes(&buf
, p
- str
, str
);
4010 if (strncmp(var
, str
+ 2, p
- str
- 2) != 0 ||
4011 var
[p
- str
- 2] != '\0') {
4013 * Not the variable we want to expand, scan
4014 * until the next variable
4016 for (;*p
!= '$' && *p
!= '\0'; p
++)
4018 Buf_AddBytes(&buf
, p
- str
, str
);
4031 val
= Var_Parse(str
, ctxt
, undefErr
, &length
, &freeIt
);
4034 * When we come down here, val should either point to the
4035 * value of this variable, suitably modified, or be NULL.
4036 * Length should be the total length of the potential
4037 * variable invocation (from $ to end character...)
4039 if (val
== var_Error
|| val
== varNoError
) {
4041 * If performing old-time variable substitution, skip over
4042 * the variable and continue with the substitution. Otherwise,
4043 * store the dollar sign and advance str so we continue with
4048 } else if (undefErr
) {
4050 * If variable is undefined, complain and skip the
4051 * variable. The complaint will stop us from doing anything
4052 * when the file is parsed.
4054 if (!errorReported
) {
4055 Parse_Error(PARSE_FATAL
,
4056 "Undefined variable \"%.*s\"",length
,str
);
4059 errorReported
= TRUE
;
4061 Buf_AddByte(&buf
, *str
);
4066 * We've now got a variable structure to store in. But first,
4067 * advance the string pointer.
4072 * Copy all the characters from the variable value straight
4073 * into the new string.
4075 length
= strlen(val
);
4076 Buf_AddBytes(&buf
, length
, val
);
4077 trailingBslash
= length
> 0 && val
[length
- 1] == '\\';
4086 return Buf_DestroyCompact(&buf
);
4090 *-----------------------------------------------------------------------
4092 * Return the tail from each of a list of words. Used to set the
4093 * System V local variables.
4096 * file Filename to modify
4099 * The resulting string.
4104 *-----------------------------------------------------------------------
4108 Var_GetTail(char *file
)
4110 return(VarModify(file
, VarTail
, NULL
));
4114 *-----------------------------------------------------------------------
4116 * Find the leading components of a (list of) filename(s).
4117 * XXX: VarHead does not replace foo by ., as (sun) System V make
4121 * file Filename to manipulate
4124 * The leading components.
4129 *-----------------------------------------------------------------------
4132 Var_GetHead(char *file
)
4134 return(VarModify(file
, VarHead
, NULL
));
4139 *-----------------------------------------------------------------------
4141 * Initialize the module
4147 * The VAR_CMD and VAR_GLOBAL contexts are created
4148 *-----------------------------------------------------------------------
4153 VAR_GLOBAL
= Targ_NewGN("Global");
4154 VAR_CMD
= Targ_NewGN("Command");
4165 /****************** PRINT DEBUGGING INFO *****************/
4167 VarPrintVar(void *vp
)
4170 fprintf(debug_file
, "%-16s = %s\n", v
->name
, Buf_GetAll(&v
->val
, NULL
));
4174 *-----------------------------------------------------------------------
4176 * print all variables in a context
4177 *-----------------------------------------------------------------------
4180 Var_Dump(GNode
*ctxt
)
4185 for (h
= Hash_EnumFirst(&ctxt
->context
, &search
);
4187 h
= Hash_EnumNext(&search
)) {
4188 VarPrintVar(Hash_GetValue(h
));