1 /* $NetBSD: var.c,v 1.196 2015/10/06 17:36:25 christos 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.196 2015/10/06 17:36:25 christos 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.196 2015/10/06 17:36:25 christos 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>
141 #include "metachar.h"
143 extern int makelevel
;
145 * This lets us tell if we have replaced the original environ
146 * (which we cannot free).
148 char **savedEnv
= NULL
;
151 * This is a harmless return value for Var_Parse that can be used by Var_Subst
152 * to determine if there was an error in parsing -- easier than returning
153 * a flag, as things outside this module don't give a hoot.
155 char var_Error
[] = "";
158 * Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
159 * set false. Why not just use a constant? Well, gcc likes to condense
160 * identical string instances...
162 static char varNoError
[] = "";
165 * Internally, variables are contained in four different contexts.
166 * 1) the environment. They may not be changed. If an environment
167 * variable is appended-to, the result is placed in the global
169 * 2) the global context. Variables set in the Makefile are located in
170 * the global context. It is the penultimate context searched when
172 * 3) the command-line context. All variables set on the command line
173 * are placed in this context. They are UNALTERABLE once placed here.
174 * 4) the local context. Each target has associated with it a context
175 * list. On this list are located the structures describing such
176 * local variables as $(@) and $(*)
177 * The four contexts are searched in the reverse order from which they are
180 GNode
*VAR_INTERNAL
; /* variables from make itself */
181 GNode
*VAR_GLOBAL
; /* variables from the makefile */
182 GNode
*VAR_CMD
; /* variables defined on the command-line */
184 #define FIND_CMD 0x1 /* look in VAR_CMD when searching */
185 #define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
186 #define FIND_ENV 0x4 /* look in the environment also */
189 char *name
; /* the variable's name */
190 Buffer val
; /* its value */
191 int flags
; /* miscellaneous status flags */
192 #define VAR_IN_USE 1 /* Variable's value currently being used.
193 * Used to avoid recursion */
194 #define VAR_FROM_ENV 2 /* Variable comes from the environment */
195 #define VAR_JUNK 4 /* Variable is a junk variable that
196 * should be destroyed when done with
197 * it. Used by Var_Parse for undefined,
198 * modified variables */
199 #define VAR_KEEP 8 /* Variable is VAR_JUNK, but we found
200 * a use for it in some modifier and
201 * the value is therefore valid */
202 #define VAR_EXPORTED 16 /* Variable is exported */
203 #define VAR_REEXPORT 32 /* Indicate if var needs re-export.
204 * This would be true if it contains $'s
206 #define VAR_FROM_CMD 64 /* Variable came from command line */
210 * Exporting vars is expensive so skip it if we can
212 #define VAR_EXPORTED_NONE 0
213 #define VAR_EXPORTED_YES 1
214 #define VAR_EXPORTED_ALL 2
215 static int var_exportedVars
= VAR_EXPORTED_NONE
;
217 * We pass this to Var_Export when doing the initial export
218 * or after updating an exported var.
220 #define VAR_EXPORT_PARENT 1
222 /* Var*Pattern flags */
223 #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
224 #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
225 #define VAR_SUB_MATCHED 0x04 /* There was a match */
226 #define VAR_MATCH_START 0x08 /* Match at start of word */
227 #define VAR_MATCH_END 0x10 /* Match at end of word */
228 #define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
231 #define VAR_NO_EXPORT 0x01 /* do not export */
235 * The following fields are set by Var_Parse() when it
236 * encounters modifiers that need to keep state for use by
237 * subsequent modifiers within the same variable expansion.
239 Byte varSpace
; /* Word separator in expansions */
240 Boolean oneBigWord
; /* TRUE if we will treat the variable as a
241 * single big word, even if it contains
242 * embedded spaces (as opposed to the
243 * usual behaviour of treating it as
244 * several space-separated words). */
247 /* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/",
248 * to VarSYSVMatch() for ":lhs=rhs". */
250 const char *lhs
; /* String to match */
251 int leftLen
; /* Length of string */
252 const char *rhs
; /* Replacement string (w/ &'s removed) */
253 int rightLen
; /* Length of replacement */
257 /* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */
259 GNode
*ctxt
; /* variable context */
260 char *tvar
; /* name of temp var */
262 char *str
; /* string to expand */
264 int errnum
; /* errnum for not defined */
268 /* struct passed as 'void *' to VarRESubstitute() for ":C///" */
278 /* struct passed to VarSelectWords() for ":[start..end]" */
280 int start
; /* first word to select */
281 int end
; /* last word to select */
284 static Var
*VarFind(const char *, GNode
*, int);
285 static void VarAdd(const char *, const char *, GNode
*);
286 static Boolean
VarHead(GNode
*, Var_Parse_State
*,
287 char *, Boolean
, Buffer
*, void *);
288 static Boolean
VarTail(GNode
*, Var_Parse_State
*,
289 char *, Boolean
, Buffer
*, void *);
290 static Boolean
VarSuffix(GNode
*, Var_Parse_State
*,
291 char *, Boolean
, Buffer
*, void *);
292 static Boolean
VarRoot(GNode
*, Var_Parse_State
*,
293 char *, Boolean
, Buffer
*, void *);
294 static Boolean
VarMatch(GNode
*, Var_Parse_State
*,
295 char *, Boolean
, Buffer
*, void *);
297 static Boolean
VarSYSVMatch(GNode
*, Var_Parse_State
*,
298 char *, Boolean
, Buffer
*, void *);
300 static Boolean
VarNoMatch(GNode
*, Var_Parse_State
*,
301 char *, Boolean
, Buffer
*, void *);
303 static void VarREError(int, regex_t
*, const char *);
304 static Boolean
VarRESubstitute(GNode
*, Var_Parse_State
*,
305 char *, Boolean
, Buffer
*, void *);
307 static Boolean
VarSubstitute(GNode
*, Var_Parse_State
*,
308 char *, Boolean
, Buffer
*, void *);
309 static Boolean
VarLoopExpand(GNode
*, Var_Parse_State
*,
310 char *, Boolean
, Buffer
*, void *);
311 static char *VarGetPattern(GNode
*, Var_Parse_State
*,
312 int, const char **, int, int *, int *,
314 static char *VarQuote(char *);
315 static char *VarHash(char *);
316 static char *VarModify(GNode
*, Var_Parse_State
*,
318 Boolean (*)(GNode
*, Var_Parse_State
*, char *, Boolean
, Buffer
*, void *),
320 static char *VarOrder(const char *, const char);
321 static char *VarUniq(const char *);
322 static int VarWordCompare(const void *, const void *);
323 static void VarPrintVar(void *);
331 *-----------------------------------------------------------------------
333 * Find the given variable in the given context and any other contexts
338 * ctxt context in which to find it
339 * flags FIND_GLOBAL set means to look in the
340 * VAR_GLOBAL context as well. FIND_CMD set means
341 * to look in the VAR_CMD context also. FIND_ENV
342 * set means to look in the environment
345 * A pointer to the structure describing the desired variable or
346 * NULL if the variable does not exist.
350 *-----------------------------------------------------------------------
353 VarFind(const char *name
, GNode
*ctxt
, int flags
)
359 * If the variable name begins with a '.', it could very well be one of
360 * the local ones. We check the name against all the local variables
361 * and substitute the short version in for 'name' if it matches one of
364 if (*name
== '.' && isupper((unsigned char) name
[1]))
367 if (!strcmp(name
, ".ALLSRC"))
369 if (!strcmp(name
, ".ARCHIVE"))
373 if (!strcmp(name
, ".IMPSRC"))
377 if (!strcmp(name
, ".MEMBER"))
381 if (!strcmp(name
, ".OODATE"))
385 if (!strcmp(name
, ".PREFIX"))
389 if (!strcmp(name
, ".TARGET"))
394 /* for compatibility with gmake */
395 if (name
[0] == '^' && name
[1] == '\0')
400 * First look for the variable in the given context. If it's not there,
401 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
402 * depending on the FIND_* flags in 'flags'
404 var
= Hash_FindEntry(&ctxt
->context
, name
);
406 if ((var
== NULL
) && (flags
& FIND_CMD
) && (ctxt
!= VAR_CMD
)) {
407 var
= Hash_FindEntry(&VAR_CMD
->context
, name
);
409 if (!checkEnvFirst
&& (var
== NULL
) && (flags
& FIND_GLOBAL
) &&
410 (ctxt
!= VAR_GLOBAL
))
412 var
= Hash_FindEntry(&VAR_GLOBAL
->context
, name
);
413 if ((var
== NULL
) && (ctxt
!= VAR_INTERNAL
)) {
414 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
415 var
= Hash_FindEntry(&VAR_INTERNAL
->context
, name
);
418 if ((var
== NULL
) && (flags
& FIND_ENV
)) {
421 if ((env
= getenv(name
)) != NULL
) {
424 v
= bmake_malloc(sizeof(Var
));
425 v
->name
= bmake_strdup(name
);
429 Buf_Init(&v
->val
, len
+ 1);
430 Buf_AddBytes(&v
->val
, len
, env
);
432 v
->flags
= VAR_FROM_ENV
;
434 } else if (checkEnvFirst
&& (flags
& FIND_GLOBAL
) &&
435 (ctxt
!= VAR_GLOBAL
))
437 var
= Hash_FindEntry(&VAR_GLOBAL
->context
, name
);
438 if ((var
== NULL
) && (ctxt
!= VAR_INTERNAL
)) {
439 var
= Hash_FindEntry(&VAR_INTERNAL
->context
, name
);
444 return ((Var
*)Hash_GetValue(var
));
449 } else if (var
== NULL
) {
452 return ((Var
*)Hash_GetValue(var
));
457 *-----------------------------------------------------------------------
459 * If the variable is an environment variable, free it
463 * destroy true if the value buffer should be destroyed.
466 * 1 if it is an environment variable 0 ow.
469 * The variable is free'ed if it is an environent variable.
470 *-----------------------------------------------------------------------
473 VarFreeEnv(Var
*v
, Boolean destroy
)
475 if ((v
->flags
& VAR_FROM_ENV
) == 0)
478 Buf_Destroy(&v
->val
, destroy
);
484 *-----------------------------------------------------------------------
486 * Add a new variable of name name and value val to the given context
489 * name name of variable to add
490 * val value to set it to
491 * ctxt context in which to set it
497 * The new variable is placed at the front of the given context
498 * The name and val arguments are duplicated so they may
500 *-----------------------------------------------------------------------
503 VarAdd(const char *name
, const char *val
, GNode
*ctxt
)
509 v
= bmake_malloc(sizeof(Var
));
511 len
= val
? strlen(val
) : 0;
512 Buf_Init(&v
->val
, len
+1);
513 Buf_AddBytes(&v
->val
, len
, val
);
517 h
= Hash_CreateEntry(&ctxt
->context
, name
, NULL
);
521 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
, val
);
526 *-----------------------------------------------------------------------
528 * Remove a variable from a context.
534 * The Var structure is removed and freed.
536 *-----------------------------------------------------------------------
539 Var_Delete(const char *name
, GNode
*ctxt
)
544 if (strchr(name
, '$')) {
545 cp
= Var_Subst(NULL
, name
, VAR_GLOBAL
, 0);
549 ln
= Hash_FindEntry(&ctxt
->context
, cp
);
551 fprintf(debug_file
, "%s:delete %s%s\n",
552 ctxt
->name
, cp
, ln
? "" : " (not found)");
560 v
= (Var
*)Hash_GetValue(ln
);
561 if ((v
->flags
& VAR_EXPORTED
)) {
564 if (strcmp(MAKE_EXPORTED
, v
->name
) == 0) {
565 var_exportedVars
= VAR_EXPORTED_NONE
;
567 if (v
->name
!= ln
->name
)
569 Hash_DeleteEntry(&ctxt
->context
, ln
);
570 Buf_Destroy(&v
->val
, TRUE
);
578 * We ignore make internal variables (those which start with '.')
579 * Also we jump through some hoops to avoid calling setenv
580 * more than necessary since it can leak.
581 * We only manipulate flags of vars if 'parent' is set.
584 Var_Export1(const char *name
, int parent
)
592 return 0; /* skip internals */
596 * If it is one of the vars that should only appear in
597 * local context, skip it, else we can get Var_Subst
608 v
= VarFind(name
, VAR_GLOBAL
, 0);
613 (v
->flags
& (VAR_EXPORTED
|VAR_REEXPORT
)) == VAR_EXPORTED
) {
614 return 0; /* nothing to do */
616 val
= Buf_GetAll(&v
->val
, NULL
);
617 if (strchr(val
, '$')) {
620 * Flag this as something we need to re-export.
621 * No point actually exporting it now though,
622 * the child can do it at the last minute.
624 v
->flags
|= (VAR_EXPORTED
|VAR_REEXPORT
);
627 if (v
->flags
& VAR_IN_USE
) {
629 * We recursed while exporting in a child.
630 * This isn't going to end well, just skip it.
634 n
= snprintf(tmp
, sizeof(tmp
), "${%s}", name
);
635 if (n
< (int)sizeof(tmp
)) {
636 val
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
637 setenv(name
, val
, 1);
642 v
->flags
&= ~VAR_REEXPORT
; /* once will do */
644 if (parent
|| !(v
->flags
& VAR_EXPORTED
)) {
645 setenv(name
, val
, 1);
649 * This is so Var_Set knows to call Var_Export again...
652 v
->flags
|= VAR_EXPORTED
;
658 * This gets called from our children.
671 * Several make's support this sort of mechanism for tracking
672 * recursion - but each uses a different name.
673 * We allow the makefiles to update MAKELEVEL and ensure
674 * children see a correctly incremented value.
676 snprintf(tmp
, sizeof(tmp
), "%d", makelevel
+ 1);
677 setenv(MAKE_LEVEL_ENV
, tmp
, 1);
679 if (VAR_EXPORTED_NONE
== var_exportedVars
)
682 if (VAR_EXPORTED_ALL
== var_exportedVars
) {
684 * Ouch! This is crazy...
686 for (var
= Hash_EnumFirst(&VAR_GLOBAL
->context
, &state
);
688 var
= Hash_EnumNext(&state
)) {
689 v
= (Var
*)Hash_GetValue(var
);
690 Var_Export1(v
->name
, 0);
695 * We have a number of exported vars,
697 n
= snprintf(tmp
, sizeof(tmp
), "${" MAKE_EXPORTED
":O:u}");
698 if (n
< (int)sizeof(tmp
)) {
704 val
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
705 av
= brk_string(val
, &ac
, FALSE
, &as
);
706 for (i
= 0; i
< ac
; i
++) {
707 Var_Export1(av
[i
], 0);
716 * This is called when .export is seen or
717 * .MAKE.EXPORTED is modified.
718 * It is also called when any exported var is modified.
721 Var_Export(char *str
, int isExport
)
731 if (isExport
&& (!str
|| !str
[0])) {
732 var_exportedVars
= VAR_EXPORTED_ALL
; /* use with caution! */
736 if (strncmp(str
, "-env", 4) == 0) {
740 track
= VAR_EXPORT_PARENT
;
742 val
= Var_Subst(NULL
, str
, VAR_GLOBAL
, 0);
743 av
= brk_string(val
, &ac
, FALSE
, &as
);
744 for (i
= 0; i
< ac
; i
++) {
749 * If it is one of the vars that should only appear in
750 * local context, skip it, else we can get Var_Subst
761 if (Var_Export1(name
, track
)) {
762 if (VAR_EXPORTED_ALL
!= var_exportedVars
)
763 var_exportedVars
= VAR_EXPORTED_YES
;
764 if (isExport
&& track
) {
765 Var_Append(MAKE_EXPORTED
, name
, VAR_GLOBAL
);
776 * This is called when .unexport[-env] is seen.
778 extern char **environ
;
781 Var_UnExport(char *str
)
786 Boolean unexport_env
;
789 if (!str
|| !str
[0]) {
790 return; /* assert? */
796 unexport_env
= (strncmp(str
, "-env", 4) == 0);
800 cp
= getenv(MAKE_LEVEL_ENV
); /* we should preserve this */
801 if (environ
== savedEnv
) {
802 /* we have been here before! */
803 newenv
= bmake_realloc(environ
, 2 * sizeof(char *));
809 newenv
= bmake_malloc(2 * sizeof(char *));
813 /* Note: we cannot safely free() the original environ. */
814 environ
= savedEnv
= newenv
;
817 setenv(MAKE_LEVEL_ENV
, cp
, 1);
819 for (; *str
!= '\n' && isspace((unsigned char) *str
); str
++)
821 if (str
[0] && str
[0] != '\n') {
827 /* Using .MAKE.EXPORTED */
828 n
= snprintf(tmp
, sizeof(tmp
), "${" MAKE_EXPORTED
":O:u}");
829 if (n
< (int)sizeof(tmp
)) {
830 vlist
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
840 av
= brk_string(vlist
, &ac
, FALSE
, &as
);
841 for (i
= 0; i
< ac
; i
++) {
842 v
= VarFind(av
[i
], VAR_GLOBAL
, 0);
846 (v
->flags
& (VAR_EXPORTED
|VAR_REEXPORT
)) == VAR_EXPORTED
) {
849 v
->flags
&= ~(VAR_EXPORTED
|VAR_REEXPORT
);
851 * If we are unexporting a list,
852 * remove each one from .MAKE.EXPORTED.
853 * If we are removing them all,
854 * just delete .MAKE.EXPORTED below.
857 n
= snprintf(tmp
, sizeof(tmp
),
858 "${" MAKE_EXPORTED
":N%s}", v
->name
);
859 if (n
< (int)sizeof(tmp
)) {
860 cp
= Var_Subst(NULL
, tmp
, VAR_GLOBAL
, 0);
861 Var_Set(MAKE_EXPORTED
, cp
, VAR_GLOBAL
, 0);
869 Var_Delete(MAKE_EXPORTED
, VAR_GLOBAL
);
876 *-----------------------------------------------------------------------
878 * Set the variable name to the value val in the given context.
881 * name name of variable to set
882 * val value to give to the variable
883 * ctxt context in which to set it
889 * If the variable doesn't yet exist, a new record is created for it.
890 * Else the old value is freed and the new one stuck in its place
893 * The variable is searched for only in its context before being
894 * created in that context. I.e. if the context is VAR_GLOBAL,
895 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
896 * VAR_CMD->context is searched. This is done to avoid the literally
897 * thousands of unnecessary strcmp's that used to be done to
898 * set, say, $(@) or $(<).
899 * If the context is VAR_GLOBAL though, we check if the variable
900 * was set in VAR_CMD from the command line and skip it if so.
901 *-----------------------------------------------------------------------
904 Var_Set(const char *name
, const char *val
, GNode
*ctxt
, int flags
)
907 char *expanded_name
= NULL
;
910 * We only look for a variable in the given context since anything set
911 * here will override anything in a lower context, so there's not much
912 * point in searching them all just to save a bit of memory...
914 if (strchr(name
, '$') != NULL
) {
915 expanded_name
= Var_Subst(NULL
, name
, ctxt
, 0);
916 if (expanded_name
[0] == 0) {
918 fprintf(debug_file
, "Var_Set(\"%s\", \"%s\", ...) "
919 "name expands to empty string - ignored\n",
925 name
= expanded_name
;
927 if (ctxt
== VAR_GLOBAL
) {
928 v
= VarFind(name
, VAR_CMD
, 0);
930 if ((v
->flags
& VAR_FROM_CMD
)) {
932 fprintf(debug_file
, "%s:%s = %s ignored!\n", ctxt
->name
, name
, val
);
939 v
= VarFind(name
, ctxt
, 0);
941 if (ctxt
== VAR_CMD
&& (flags
& VAR_NO_EXPORT
) == 0) {
943 * This var would normally prevent the same name being added
944 * to VAR_GLOBAL, so delete it from there if needed.
945 * Otherwise -V name may show the wrong value.
947 Var_Delete(name
, VAR_GLOBAL
);
949 VarAdd(name
, val
, ctxt
);
952 Buf_AddBytes(&v
->val
, strlen(val
), val
);
955 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
, val
);
957 if ((v
->flags
& VAR_EXPORTED
)) {
958 Var_Export1(name
, VAR_EXPORT_PARENT
);
962 * Any variables given on the command line are automatically exported
963 * to the environment (as per POSIX standard)
965 if (ctxt
== VAR_CMD
&& (flags
& VAR_NO_EXPORT
) == 0) {
967 /* we just added it */
968 v
= VarFind(name
, ctxt
, 0);
971 v
->flags
|= VAR_FROM_CMD
;
973 * If requested, don't export these in the environment
974 * individually. We still put them in MAKEOVERRIDES so
975 * that the command-line settings continue to override
978 if (varNoExportEnv
!= TRUE
)
979 setenv(name
, val
, 1);
981 Var_Append(MAKEOVERRIDES
, name
, VAR_GLOBAL
);
991 *-----------------------------------------------------------------------
993 * The variable of the given name has the given value appended to it in
997 * name name of variable to modify
998 * val String to append to it
999 * ctxt Context in which this should occur
1005 * If the variable doesn't exist, it is created. Else the strings
1006 * are concatenated (with a space in between).
1009 * Only if the variable is being sought in the global context is the
1010 * environment searched.
1011 * XXX: Knows its calling circumstances in that if called with ctxt
1012 * an actual target, it will only search that context since only
1013 * a local variable could be being appended to. This is actually
1014 * a big win and must be tolerated.
1015 *-----------------------------------------------------------------------
1018 Var_Append(const char *name
, const char *val
, GNode
*ctxt
)
1022 char *expanded_name
= NULL
;
1024 if (strchr(name
, '$') != NULL
) {
1025 expanded_name
= Var_Subst(NULL
, name
, ctxt
, 0);
1026 if (expanded_name
[0] == 0) {
1028 fprintf(debug_file
, "Var_Append(\"%s\", \"%s\", ...) "
1029 "name expands to empty string - ignored\n",
1032 free(expanded_name
);
1035 name
= expanded_name
;
1038 v
= VarFind(name
, ctxt
, (ctxt
== VAR_GLOBAL
) ? FIND_ENV
: 0);
1041 VarAdd(name
, val
, ctxt
);
1043 Buf_AddByte(&v
->val
, ' ');
1044 Buf_AddBytes(&v
->val
, strlen(val
), val
);
1047 fprintf(debug_file
, "%s:%s = %s\n", ctxt
->name
, name
,
1048 Buf_GetAll(&v
->val
, NULL
));
1051 if (v
->flags
& VAR_FROM_ENV
) {
1053 * If the original variable came from the environment, we
1054 * have to install it in the global context (we could place
1055 * it in the environment, but then we should provide a way to
1056 * export other variables...)
1058 v
->flags
&= ~VAR_FROM_ENV
;
1059 h
= Hash_CreateEntry(&ctxt
->context
, name
, NULL
);
1060 Hash_SetValue(h
, v
);
1063 free(expanded_name
);
1067 *-----------------------------------------------------------------------
1069 * See if the given variable exists.
1072 * name Variable to find
1073 * ctxt Context in which to start search
1076 * TRUE if it does, FALSE if it doesn't
1081 *-----------------------------------------------------------------------
1084 Var_Exists(const char *name
, GNode
*ctxt
)
1089 if ((cp
= strchr(name
, '$')) != NULL
) {
1090 cp
= Var_Subst(NULL
, name
, ctxt
, FALSE
);
1092 v
= VarFind(cp
? cp
: name
, ctxt
, FIND_CMD
|FIND_GLOBAL
|FIND_ENV
);
1097 (void)VarFreeEnv(v
, TRUE
);
1103 *-----------------------------------------------------------------------
1105 * Return the value of the named variable in the given context
1109 * ctxt context in which to search for it
1112 * The value if the variable exists, NULL if it doesn't
1116 *-----------------------------------------------------------------------
1119 Var_Value(const char *name
, GNode
*ctxt
, char **frp
)
1123 v
= VarFind(name
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
1126 char *p
= (Buf_GetAll(&v
->val
, NULL
));
1127 if (VarFreeEnv(v
, FALSE
))
1136 *-----------------------------------------------------------------------
1138 * Remove the tail of the given word and place the result in the given
1143 * addSpace True if need to add a space to the buffer
1144 * before sticking in the head
1145 * buf Buffer in which to store it
1148 * TRUE if characters were added to the buffer (a space needs to be
1149 * added to the buffer before the next word).
1152 * The trimmed word is added to the buffer.
1154 *-----------------------------------------------------------------------
1157 VarHead(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1158 char *word
, Boolean addSpace
, Buffer
*buf
,
1163 slash
= strrchr(word
, '/');
1164 if (slash
!= NULL
) {
1165 if (addSpace
&& vpstate
->varSpace
) {
1166 Buf_AddByte(buf
, vpstate
->varSpace
);
1169 Buf_AddBytes(buf
, strlen(word
), word
);
1174 * If no directory part, give . (q.v. the POSIX standard)
1176 if (addSpace
&& vpstate
->varSpace
)
1177 Buf_AddByte(buf
, vpstate
->varSpace
);
1178 Buf_AddByte(buf
, '.');
1180 return(dummy
? TRUE
: TRUE
);
1184 *-----------------------------------------------------------------------
1186 * Remove the head of the given word and place the result in the given
1191 * addSpace True if need to add a space to the buffer
1192 * before adding the tail
1193 * buf Buffer in which to store it
1196 * TRUE if characters were added to the buffer (a space needs to be
1197 * added to the buffer before the next word).
1200 * The trimmed word is added to the buffer.
1202 *-----------------------------------------------------------------------
1205 VarTail(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1206 char *word
, Boolean addSpace
, Buffer
*buf
,
1211 if (addSpace
&& vpstate
->varSpace
) {
1212 Buf_AddByte(buf
, vpstate
->varSpace
);
1215 slash
= strrchr(word
, '/');
1216 if (slash
!= NULL
) {
1218 Buf_AddBytes(buf
, strlen(slash
), slash
);
1221 Buf_AddBytes(buf
, strlen(word
), word
);
1223 return (dummy
? TRUE
: TRUE
);
1227 *-----------------------------------------------------------------------
1229 * Place the suffix of the given word in the given buffer.
1233 * addSpace TRUE if need to add a space before placing the
1234 * suffix in the buffer
1235 * buf Buffer in which to store it
1238 * TRUE if characters were added to the buffer (a space needs to be
1239 * added to the buffer before the next word).
1242 * The suffix from the word is placed in the buffer.
1244 *-----------------------------------------------------------------------
1247 VarSuffix(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1248 char *word
, Boolean addSpace
, Buffer
*buf
,
1253 dot
= strrchr(word
, '.');
1255 if (addSpace
&& vpstate
->varSpace
) {
1256 Buf_AddByte(buf
, vpstate
->varSpace
);
1259 Buf_AddBytes(buf
, strlen(dot
), dot
);
1263 return (dummy
? addSpace
: addSpace
);
1267 *-----------------------------------------------------------------------
1269 * Remove the suffix of the given word and place the result in the
1274 * addSpace TRUE if need to add a space to the buffer
1275 * before placing the root in it
1276 * buf Buffer in which to store it
1279 * TRUE if characters were added to the buffer (a space needs to be
1280 * added to the buffer before the next word).
1283 * The trimmed word is added to the buffer.
1285 *-----------------------------------------------------------------------
1288 VarRoot(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1289 char *word
, Boolean addSpace
, Buffer
*buf
,
1294 if (addSpace
&& vpstate
->varSpace
) {
1295 Buf_AddByte(buf
, vpstate
->varSpace
);
1298 dot
= strrchr(word
, '.');
1301 Buf_AddBytes(buf
, strlen(word
), word
);
1304 Buf_AddBytes(buf
, strlen(word
), word
);
1306 return (dummy
? TRUE
: TRUE
);
1310 *-----------------------------------------------------------------------
1312 * Place the word in the buffer if it matches the given pattern.
1313 * Callback function for VarModify to implement the :M modifier.
1316 * word Word to examine
1317 * addSpace TRUE if need to add a space to the buffer
1318 * before adding the word, if it matches
1319 * buf Buffer in which to store it
1320 * pattern Pattern the word must match
1323 * TRUE if a space should be placed in the buffer before the next
1327 * The word may be copied to the buffer.
1329 *-----------------------------------------------------------------------
1332 VarMatch(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1333 char *word
, Boolean addSpace
, Buffer
*buf
,
1337 fprintf(debug_file
, "VarMatch [%s] [%s]\n", word
, (char *)pattern
);
1338 if (Str_Match(word
, (char *)pattern
)) {
1339 if (addSpace
&& vpstate
->varSpace
) {
1340 Buf_AddByte(buf
, vpstate
->varSpace
);
1343 Buf_AddBytes(buf
, strlen(word
), word
);
1350 *-----------------------------------------------------------------------
1352 * Place the word in the buffer if it matches the given pattern.
1353 * Callback function for VarModify to implement the System V %
1357 * word Word to examine
1358 * addSpace TRUE if need to add a space to the buffer
1359 * before adding the word, if it matches
1360 * buf Buffer in which to store it
1361 * patp Pattern the word must match
1364 * TRUE if a space should be placed in the buffer before the next
1368 * The word may be copied to the buffer.
1370 *-----------------------------------------------------------------------
1373 VarSYSVMatch(GNode
*ctx
, Var_Parse_State
*vpstate
,
1374 char *word
, Boolean addSpace
, Buffer
*buf
,
1379 VarPattern
*pat
= (VarPattern
*)patp
;
1382 if (addSpace
&& vpstate
->varSpace
)
1383 Buf_AddByte(buf
, vpstate
->varSpace
);
1387 if ((ptr
= Str_SYSVMatch(word
, pat
->lhs
, &len
)) != NULL
) {
1388 varexp
= Var_Subst(NULL
, pat
->rhs
, ctx
, 0);
1389 Str_SYSVSubst(buf
, varexp
, ptr
, len
);
1392 Buf_AddBytes(buf
, strlen(word
), word
);
1401 *-----------------------------------------------------------------------
1403 * Place the word in the buffer if it doesn't match the given pattern.
1404 * Callback function for VarModify to implement the :N modifier.
1407 * word Word to examine
1408 * addSpace TRUE if need to add a space to the buffer
1409 * before adding the word, if it matches
1410 * buf Buffer in which to store it
1411 * pattern Pattern the word must match
1414 * TRUE if a space should be placed in the buffer before the next
1418 * The word may be copied to the buffer.
1420 *-----------------------------------------------------------------------
1423 VarNoMatch(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1424 char *word
, Boolean addSpace
, Buffer
*buf
,
1427 if (!Str_Match(word
, (char *)pattern
)) {
1428 if (addSpace
&& vpstate
->varSpace
) {
1429 Buf_AddByte(buf
, vpstate
->varSpace
);
1432 Buf_AddBytes(buf
, strlen(word
), word
);
1439 *-----------------------------------------------------------------------
1441 * Perform a string-substitution on the given word, placing the
1442 * result in the passed buffer.
1445 * word Word to modify
1446 * addSpace True if space should be added before
1448 * buf Buffer for result
1449 * patternp Pattern for substitution
1452 * TRUE if a space is needed before more characters are added.
1457 *-----------------------------------------------------------------------
1460 VarSubstitute(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1461 char *word
, Boolean addSpace
, Buffer
*buf
,
1464 int wordLen
; /* Length of word */
1465 char *cp
; /* General pointer */
1466 VarPattern
*pattern
= (VarPattern
*)patternp
;
1468 wordLen
= strlen(word
);
1469 if ((pattern
->flags
& (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) !=
1470 (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) {
1472 * Still substituting -- break it down into simple anchored cases
1473 * and if none of them fits, perform the general substitution case.
1475 if ((pattern
->flags
& VAR_MATCH_START
) &&
1476 (strncmp(word
, pattern
->lhs
, pattern
->leftLen
) == 0)) {
1478 * Anchored at start and beginning of word matches pattern
1480 if ((pattern
->flags
& VAR_MATCH_END
) &&
1481 (wordLen
== pattern
->leftLen
)) {
1483 * Also anchored at end and matches to the end (word
1484 * is same length as pattern) add space and rhs only
1485 * if rhs is non-null.
1487 if (pattern
->rightLen
!= 0) {
1488 if (addSpace
&& vpstate
->varSpace
) {
1489 Buf_AddByte(buf
, vpstate
->varSpace
);
1492 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1494 pattern
->flags
|= VAR_SUB_MATCHED
;
1495 } else if (pattern
->flags
& VAR_MATCH_END
) {
1497 * Doesn't match to end -- copy word wholesale
1502 * Matches at start but need to copy in trailing characters
1504 if ((pattern
->rightLen
+ wordLen
- pattern
->leftLen
) != 0){
1505 if (addSpace
&& vpstate
->varSpace
) {
1506 Buf_AddByte(buf
, vpstate
->varSpace
);
1510 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1511 Buf_AddBytes(buf
, wordLen
- pattern
->leftLen
,
1512 (word
+ pattern
->leftLen
));
1513 pattern
->flags
|= VAR_SUB_MATCHED
;
1515 } else if (pattern
->flags
& VAR_MATCH_START
) {
1517 * Had to match at start of word and didn't -- copy whole word.
1520 } else if (pattern
->flags
& VAR_MATCH_END
) {
1522 * Anchored at end, Find only place match could occur (leftLen
1523 * characters from the end of the word) and see if it does. Note
1524 * that because the $ will be left at the end of the lhs, we have
1527 cp
= word
+ (wordLen
- pattern
->leftLen
);
1529 (strncmp(cp
, pattern
->lhs
, pattern
->leftLen
) == 0)) {
1531 * Match found. If we will place characters in the buffer,
1532 * add a space before hand as indicated by addSpace, then
1533 * stuff in the initial, unmatched part of the word followed
1534 * by the right-hand-side.
1536 if (((cp
- word
) + pattern
->rightLen
) != 0) {
1537 if (addSpace
&& vpstate
->varSpace
) {
1538 Buf_AddByte(buf
, vpstate
->varSpace
);
1542 Buf_AddBytes(buf
, cp
- word
, word
);
1543 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1544 pattern
->flags
|= VAR_SUB_MATCHED
;
1547 * Had to match at end and didn't. Copy entire word.
1553 * Pattern is unanchored: search for the pattern in the word using
1554 * String_FindSubstring, copying unmatched portions and the
1555 * right-hand-side for each match found, handling non-global
1556 * substitutions correctly, etc. When the loop is done, any
1557 * remaining part of the word (word and wordLen are adjusted
1558 * accordingly through the loop) is copied straight into the
1560 * addSpace is set FALSE as soon as a space is added to the
1567 origSize
= Buf_Size(buf
);
1569 cp
= Str_FindSubstring(word
, pattern
->lhs
);
1571 if (addSpace
&& (((cp
- word
) + pattern
->rightLen
) != 0)){
1572 Buf_AddByte(buf
, vpstate
->varSpace
);
1575 Buf_AddBytes(buf
, cp
-word
, word
);
1576 Buf_AddBytes(buf
, pattern
->rightLen
, pattern
->rhs
);
1577 wordLen
-= (cp
- word
) + pattern
->leftLen
;
1578 word
= cp
+ pattern
->leftLen
;
1582 if ((pattern
->flags
& VAR_SUB_GLOBAL
) == 0) {
1585 pattern
->flags
|= VAR_SUB_MATCHED
;
1591 if (addSpace
&& vpstate
->varSpace
) {
1592 Buf_AddByte(buf
, vpstate
->varSpace
);
1594 Buf_AddBytes(buf
, wordLen
, word
);
1597 * If added characters to the buffer, need to add a space
1598 * before we add any more. If we didn't add any, just return
1599 * the previous value of addSpace.
1601 return ((Buf_Size(buf
) != origSize
) || addSpace
);
1606 if (addSpace
&& vpstate
->varSpace
) {
1607 Buf_AddByte(buf
, vpstate
->varSpace
);
1609 Buf_AddBytes(buf
, wordLen
, word
);
1615 *-----------------------------------------------------------------------
1617 * Print the error caused by a regcomp or regexec call.
1623 * An error gets printed.
1625 *-----------------------------------------------------------------------
1628 VarREError(int errnum
, regex_t
*pat
, const char *str
)
1633 errlen
= regerror(errnum
, pat
, 0, 0);
1634 errbuf
= bmake_malloc(errlen
);
1635 regerror(errnum
, pat
, errbuf
, errlen
);
1636 Error("%s: %s", str
, errbuf
);
1642 *-----------------------------------------------------------------------
1643 * VarRESubstitute --
1644 * Perform a regex substitution on the given word, placing the
1645 * result in the passed buffer.
1648 * TRUE if a space is needed before more characters are added.
1653 *-----------------------------------------------------------------------
1656 VarRESubstitute(GNode
*ctx MAKE_ATTR_UNUSED
,
1657 Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
1658 char *word
, Boolean addSpace
, Buffer
*buf
,
1668 #define MAYBE_ADD_SPACE() \
1669 if (addSpace && !added) \
1670 Buf_AddByte(buf, ' '); \
1677 if ((pat
->flags
& (VAR_SUB_ONE
|VAR_SUB_MATCHED
)) ==
1678 (VAR_SUB_ONE
|VAR_SUB_MATCHED
))
1682 xrv
= regexec(&pat
->re
, wp
, pat
->nsub
, pat
->matches
, flags
);
1687 pat
->flags
|= VAR_SUB_MATCHED
;
1688 if (pat
->matches
[0].rm_so
> 0) {
1690 Buf_AddBytes(buf
, pat
->matches
[0].rm_so
, wp
);
1693 for (rp
= pat
->replace
; *rp
; rp
++) {
1694 if ((*rp
== '\\') && ((rp
[1] == '&') || (rp
[1] == '\\'))) {
1696 Buf_AddByte(buf
,rp
[1]);
1699 else if ((*rp
== '&') ||
1700 ((*rp
== '\\') && isdigit((unsigned char)rp
[1]))) {
1718 if (n
> pat
->nsub
) {
1719 Error("No subexpression %s", &errstr
[0]);
1722 } else if ((pat
->matches
[n
].rm_so
== -1) &&
1723 (pat
->matches
[n
].rm_eo
== -1)) {
1724 Error("No match for subexpression %s", &errstr
[0]);
1728 subbuf
= wp
+ pat
->matches
[n
].rm_so
;
1729 sublen
= pat
->matches
[n
].rm_eo
- pat
->matches
[n
].rm_so
;
1734 Buf_AddBytes(buf
, sublen
, subbuf
);
1738 Buf_AddByte(buf
, *rp
);
1741 wp
+= pat
->matches
[0].rm_eo
;
1742 if (pat
->flags
& VAR_SUB_GLOBAL
) {
1743 flags
|= REG_NOTBOL
;
1744 if (pat
->matches
[0].rm_so
== 0 && pat
->matches
[0].rm_eo
== 0) {
1746 Buf_AddByte(buf
, *wp
);
1755 Buf_AddBytes(buf
, strlen(wp
), wp
);
1759 VarREError(xrv
, &pat
->re
, "Unexpected regex error");
1764 Buf_AddBytes(buf
,strlen(wp
),wp
);
1768 return(addSpace
||added
);
1775 *-----------------------------------------------------------------------
1777 * Implements the :@<temp>@<string>@ modifier of ODE make.
1778 * We set the temp variable named in pattern.lhs to word and expand
1779 * pattern.rhs storing the result in the passed buffer.
1782 * word Word to modify
1783 * addSpace True if space should be added before
1785 * buf Buffer for result
1786 * pattern Datafor substitution
1789 * TRUE if a space is needed before more characters are added.
1794 *-----------------------------------------------------------------------
1797 VarLoopExpand(GNode
*ctx MAKE_ATTR_UNUSED
,
1798 Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
1799 char *word
, Boolean addSpace
, Buffer
*buf
,
1802 VarLoop_t
*loop
= (VarLoop_t
*)loopp
;
1806 if (word
&& *word
) {
1807 Var_Set(loop
->tvar
, word
, loop
->ctxt
, VAR_NO_EXPORT
);
1808 s
= Var_Subst(NULL
, loop
->str
, loop
->ctxt
, loop
->errnum
);
1809 if (s
!= NULL
&& *s
!= '\0') {
1810 if (addSpace
&& *s
!= '\n')
1811 Buf_AddByte(buf
, ' ');
1812 Buf_AddBytes(buf
, (slen
= strlen(s
)), s
);
1813 addSpace
= (slen
> 0 && s
[slen
- 1] != '\n');
1822 *-----------------------------------------------------------------------
1824 * Implements the :[start..end] modifier.
1825 * This is a special case of VarModify since we want to be able
1826 * to scan the list backwards if start > end.
1829 * str String whose words should be trimmed
1830 * seldata words to select
1833 * A string of all the words selected.
1838 *-----------------------------------------------------------------------
1841 VarSelectWords(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1842 const char *str
, VarSelectWords_t
*seldata
)
1844 Buffer buf
; /* Buffer for the new string */
1845 Boolean addSpace
; /* TRUE if need to add a space to the
1846 * buffer before adding the trimmed
1848 char **av
; /* word list */
1849 char *as
; /* word list memory */
1851 int start
, end
, step
;
1856 if (vpstate
->oneBigWord
) {
1857 /* fake what brk_string() would do if there were only one word */
1859 av
= bmake_malloc((ac
+ 1) * sizeof(char *));
1860 as
= bmake_strdup(str
);
1864 av
= brk_string(str
, &ac
, FALSE
, &as
);
1868 * Now sanitize seldata.
1869 * If seldata->start or seldata->end are negative, convert them to
1870 * the positive equivalents (-1 gets converted to argc, -2 gets
1871 * converted to (argc-1), etc.).
1873 if (seldata
->start
< 0)
1874 seldata
->start
= ac
+ seldata
->start
+ 1;
1875 if (seldata
->end
< 0)
1876 seldata
->end
= ac
+ seldata
->end
+ 1;
1879 * We avoid scanning more of the list than we need to.
1881 if (seldata
->start
> seldata
->end
) {
1882 start
= MIN(ac
, seldata
->start
) - 1;
1883 end
= MAX(0, seldata
->end
- 1);
1886 start
= MAX(0, seldata
->start
- 1);
1887 end
= MIN(ac
, seldata
->end
);
1892 (step
< 0 && i
>= end
) || (step
> 0 && i
< end
);
1894 if (av
[i
] && *av
[i
]) {
1895 if (addSpace
&& vpstate
->varSpace
) {
1896 Buf_AddByte(&buf
, vpstate
->varSpace
);
1898 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
1906 return Buf_Destroy(&buf
, FALSE
);
1912 * Replace each word with the result of realpath()
1916 VarRealpath(GNode
*ctx MAKE_ATTR_UNUSED
, Var_Parse_State
*vpstate
,
1917 char *word
, Boolean addSpace
, Buffer
*buf
,
1918 void *patternp MAKE_ATTR_UNUSED
)
1921 char rbuf
[MAXPATHLEN
];
1924 if (addSpace
&& vpstate
->varSpace
) {
1925 Buf_AddByte(buf
, vpstate
->varSpace
);
1928 rp
= realpath(word
, rbuf
);
1929 if (rp
&& *rp
== '/' && stat(rp
, &st
) == 0)
1932 Buf_AddBytes(buf
, strlen(word
), word
);
1937 *-----------------------------------------------------------------------
1939 * Modify each of the words of the passed string using the given
1940 * function. Used to implement all modifiers.
1943 * str String whose words should be trimmed
1944 * modProc Function to use to modify them
1945 * datum Datum to pass it
1948 * A string of all the words modified appropriately.
1953 *-----------------------------------------------------------------------
1956 VarModify(GNode
*ctx
, Var_Parse_State
*vpstate
,
1958 Boolean (*modProc
)(GNode
*, Var_Parse_State
*, char *,
1959 Boolean
, Buffer
*, void *),
1962 Buffer buf
; /* Buffer for the new string */
1963 Boolean addSpace
; /* TRUE if need to add a space to the
1964 * buffer before adding the trimmed
1966 char **av
; /* word list */
1967 char *as
; /* word list memory */
1973 if (vpstate
->oneBigWord
) {
1974 /* fake what brk_string() would do if there were only one word */
1976 av
= bmake_malloc((ac
+ 1) * sizeof(char *));
1977 as
= bmake_strdup(str
);
1981 av
= brk_string(str
, &ac
, FALSE
, &as
);
1984 for (i
= 0; i
< ac
; i
++) {
1985 addSpace
= (*modProc
)(ctx
, vpstate
, av
[i
], addSpace
, &buf
, datum
);
1991 return Buf_Destroy(&buf
, FALSE
);
1996 VarWordCompare(const void *a
, const void *b
)
1998 int r
= strcmp(*(const char * const *)a
, *(const char * const *)b
);
2003 *-----------------------------------------------------------------------
2005 * Order the words in the string.
2008 * str String whose words should be sorted.
2009 * otype How to order: s - sort, x - random.
2012 * A string containing the words ordered.
2017 *-----------------------------------------------------------------------
2020 VarOrder(const char *str
, const char otype
)
2022 Buffer buf
; /* Buffer for the new string */
2023 char **av
; /* word list [first word does not count] */
2024 char *as
; /* word list memory */
2029 av
= brk_string(str
, &ac
, FALSE
, &as
);
2033 case 's': /* sort alphabetically */
2034 qsort(av
, ac
, sizeof(char *), VarWordCompare
);
2036 case 'x': /* randomize */
2042 * We will use [ac..2] range for mod factors. This will produce
2043 * random numbers in [(ac-1)..0] interval, and minimal
2044 * reasonable value for mod factor is 2 (the mod 1 will produce
2045 * 0 with probability 1).
2047 for (i
= ac
-1; i
> 0; i
--) {
2048 rndidx
= random() % (i
+ 1);
2056 } /* end of switch */
2058 for (i
= 0; i
< ac
; i
++) {
2059 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
2061 Buf_AddByte(&buf
, ' ');
2067 return Buf_Destroy(&buf
, FALSE
);
2072 *-----------------------------------------------------------------------
2074 * Remove adjacent duplicate words.
2077 * str String whose words should be sorted
2080 * A string containing the resulting words.
2085 *-----------------------------------------------------------------------
2088 VarUniq(const char *str
)
2090 Buffer buf
; /* Buffer for new string */
2091 char **av
; /* List of words to affect */
2092 char *as
; /* Word list memory */
2096 av
= brk_string(str
, &ac
, FALSE
, &as
);
2099 for (j
= 0, i
= 1; i
< ac
; i
++)
2100 if (strcmp(av
[i
], av
[j
]) != 0 && (++j
!= i
))
2105 for (i
= 0; i
< ac
; i
++) {
2106 Buf_AddBytes(&buf
, strlen(av
[i
]), av
[i
]);
2108 Buf_AddByte(&buf
, ' ');
2114 return Buf_Destroy(&buf
, FALSE
);
2119 *-----------------------------------------------------------------------
2121 * Pass through the tstr looking for 1) escaped delimiters,
2122 * '$'s and backslashes (place the escaped character in
2123 * uninterpreted) and 2) unescaped $'s that aren't before
2124 * the delimiter (expand the variable substitution unless flags
2125 * has VAR_NOSUBST set).
2126 * Return the expanded string or NULL if the delimiter was missing
2127 * If pattern is specified, handle escaped ampersands, and replace
2128 * unescaped ampersands with the lhs of the pattern.
2131 * A string of all the words modified appropriately.
2132 * If length is specified, return the string length of the buffer
2133 * If flags is specified and the last character of the pattern is a
2134 * $ set the VAR_MATCH_END bit of flags.
2138 *-----------------------------------------------------------------------
2141 VarGetPattern(GNode
*ctxt
, Var_Parse_State
*vpstate MAKE_ATTR_UNUSED
,
2142 int errnum
, const char **tstr
, int delim
, int *flags
,
2143 int *length
, VarPattern
*pattern
)
2154 #define IS_A_MATCH(cp, delim) \
2155 ((cp[0] == '\\') && ((cp[1] == delim) || \
2156 (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
2159 * Skim through until the matching delimiter is found;
2160 * pick up variable substitutions on the way. Also allow
2161 * backslashes to quote the delimiter, $, and \, but don't
2162 * touch other backslashes.
2164 for (cp
= *tstr
; *cp
&& (*cp
!= delim
); cp
++) {
2165 if (IS_A_MATCH(cp
, delim
)) {
2166 Buf_AddByte(&buf
, cp
[1]);
2168 } else if (*cp
== '$') {
2169 if (cp
[1] == delim
) {
2171 Buf_AddByte(&buf
, *cp
);
2174 * Unescaped $ at end of pattern => anchor
2177 *flags
|= VAR_MATCH_END
;
2179 if (flags
== NULL
|| (*flags
& VAR_NOSUBST
) == 0) {
2185 * If unescaped dollar sign not before the
2186 * delimiter, assume it's a variable
2187 * substitution and recurse.
2189 cp2
= Var_Parse(cp
, ctxt
, errnum
, &len
, &freeIt
);
2190 Buf_AddBytes(&buf
, strlen(cp2
), cp2
);
2194 const char *cp2
= &cp
[1];
2196 if (*cp2
== PROPEN
|| *cp2
== BROPEN
) {
2198 * Find the end of this variable reference
2199 * and suck it in without further ado.
2200 * It will be interperated later.
2203 int want
= (*cp2
== PROPEN
) ? PRCLOSE
: BRCLOSE
;
2206 for (++cp2
; *cp2
!= '\0' && depth
> 0; ++cp2
) {
2207 if (cp2
[-1] != '\\') {
2214 Buf_AddBytes(&buf
, cp2
- cp
, cp
);
2217 Buf_AddByte(&buf
, *cp
);
2221 else if (pattern
&& *cp
== '&')
2222 Buf_AddBytes(&buf
, pattern
->leftLen
, pattern
->lhs
);
2224 Buf_AddByte(&buf
, *cp
);
2234 *length
= Buf_Size(&buf
);
2235 rstr
= Buf_Destroy(&buf
, FALSE
);
2237 fprintf(debug_file
, "Modifier pattern: \"%s\"\n", rstr
);
2242 *-----------------------------------------------------------------------
2244 * Quote shell meta-characters and space characters in the string
2252 *-----------------------------------------------------------------------
2259 const char *newline
;
2262 if ((newline
= Shell_GetNewline()) == NULL
)
2264 nlen
= strlen(newline
);
2268 for (; *str
!= '\0'; str
++) {
2270 Buf_AddBytes(&buf
, nlen
, newline
);
2273 if (isspace((unsigned char)*str
) || ismeta((unsigned char)*str
))
2274 Buf_AddByte(&buf
, '\\');
2275 Buf_AddByte(&buf
, *str
);
2278 str
= Buf_Destroy(&buf
, FALSE
);
2280 fprintf(debug_file
, "QuoteMeta: [%s]\n", str
);
2285 *-----------------------------------------------------------------------
2287 * Hash the string using the MurmurHash3 algorithm.
2288 * Output is computed using 32bit Little Endian arithmetic.
2291 * str String to modify
2294 * Hash value of str, encoded as 8 hex digits.
2299 *-----------------------------------------------------------------------
2304 static const char hexdigits
[16] = "0123456789abcdef";
2307 unsigned char *ustr
= (unsigned char *)str
;
2308 uint32_t h
, k
, c1
, c2
;
2315 for (len
= len2
; len
; ) {
2319 k
= (ustr
[3] << 24) | (ustr
[2] << 16) | (ustr
[1] << 8) | ustr
[0];
2324 k
|= (ustr
[2] << 16);
2326 k
|= (ustr
[1] << 8);
2331 c1
= c1
* 5 + 0x7b7d159cU
;
2332 c2
= c2
* 5 + 0x6bce6396U
;
2334 k
= (k
<< 11) ^ (k
>> 21);
2336 h
= (h
<< 13) ^ (h
>> 19);
2337 h
= h
* 5 + 0x52dce729U
;
2347 for (len
= 0; len
< 8; ++len
) {
2348 Buf_AddByte(&buf
, hexdigits
[h
& 15]);
2352 return Buf_Destroy(&buf
, FALSE
);
2356 VarStrftime(const char *fmt
, int zulu
)
2364 strftime(buf
, sizeof(buf
), fmt
, zulu
? gmtime(&utc
) : localtime(&utc
));
2366 buf
[sizeof(buf
) - 1] = '\0';
2367 return bmake_strdup(buf
);
2371 * Now we need to apply any modifiers the user wants applied.
2373 * :M<pattern> words which match the given <pattern>.
2374 * <pattern> is of the standard file
2376 * :N<pattern> words which do not match the given <pattern>.
2377 * :S<d><pat1><d><pat2><d>[1gW]
2378 * Substitute <pat2> for <pat1> in the value
2379 * :C<d><pat1><d><pat2><d>[1gW]
2380 * Substitute <pat2> for regex <pat1> in the value
2381 * :H Substitute the head of each word
2382 * :T Substitute the tail of each word
2383 * :E Substitute the extension (minus '.') of
2385 * :R Substitute the root of each word
2386 * (pathname minus the suffix).
2387 * :O ("Order") Alphabeticaly sort words in variable.
2388 * :Ox ("intermiX") Randomize words in variable.
2389 * :u ("uniq") Remove adjacent duplicate words.
2390 * :tu Converts the variable contents to uppercase.
2391 * :tl Converts the variable contents to lowercase.
2392 * :ts[c] Sets varSpace - the char used to
2393 * separate words to 'c'. If 'c' is
2394 * omitted then no separation is used.
2395 * :tW Treat the variable contents as a single
2396 * word, even if it contains spaces.
2397 * (Mnemonic: one big 'W'ord.)
2398 * :tw Treat the variable contents as multiple
2399 * space-separated words.
2400 * (Mnemonic: many small 'w'ords.)
2401 * :[index] Select a single word from the value.
2402 * :[start..end] Select multiple words from the value.
2403 * :[*] or :[0] Select the entire value, as a single
2404 * word. Equivalent to :tW.
2405 * :[@] Select the entire value, as multiple
2406 * words. Undoes the effect of :[*].
2407 * Equivalent to :tw.
2408 * :[#] Returns the number of words in the value.
2410 * :?<true-value>:<false-value>
2411 * If the variable evaluates to true, return
2412 * true value, else return the second value.
2413 * :lhs=rhs Like :S, but the rhs goes to the end of
2415 * :sh Treat the current value as a command
2416 * to be run, new value is its output.
2417 * The following added so we can handle ODE makefiles.
2418 * :@<tmpvar>@<newval>@
2419 * Assign a temporary local variable <tmpvar>
2420 * to the current value of each word in turn
2421 * and replace each word with the result of
2422 * evaluating <newval>
2423 * :D<newval> Use <newval> as value if variable defined
2424 * :U<newval> Use <newval> as value if variable undefined
2425 * :L Use the name of the variable as the value.
2426 * :P Use the path of the node that has the same
2427 * name as the variable as the value. This
2428 * basically includes an implied :L so that
2429 * the common method of refering to the path
2430 * of your dependent 'x' in a rule is to use
2431 * the form '${x:P}'.
2432 * :!<cmd>! Run cmd much the same as :sh run's the
2433 * current value of the variable.
2434 * The ::= modifiers, actually assign a value to the variable.
2435 * Their main purpose is in supporting modifiers of .for loop
2436 * iterators and other obscure uses. They always expand to
2437 * nothing. In a target rule that would otherwise expand to an
2438 * empty line they can be preceded with @: to keep make happy.
2442 * .for i in ${.TARGET} ${.TARGET:R}.gz
2447 * ::=<str> Assigns <str> as the new value of variable.
2448 * ::?=<str> Assigns <str> as value of variable if
2449 * it was not already set.
2450 * ::+=<str> Appends <str> to variable.
2451 * ::!=<cmd> Assigns output of <cmd> as the new value of
2455 /* we now have some modifiers with long names */
2456 #define STRMOD_MATCH(s, want, n) \
2457 (strncmp(s, want, n) == 0 && (s[n] == endc || s[n] == ':'))
2460 ApplyModifiers(char *nstr
, const char *tstr
,
2461 int startc
, int endc
,
2462 Var
*v
, GNode
*ctxt
, Boolean errnum
,
2463 int *lengthPtr
, void **freePtr
)
2466 const char *cp
; /* Secondary pointer into str (place marker
2468 char *newStr
; /* New value to return */
2469 char termc
; /* Character which terminated scan */
2470 int cnt
; /* Used to count brace pairs when variable in
2471 * in parens or braces */
2473 int modifier
; /* that we are processing */
2474 Var_Parse_State parsestate
; /* Flags passed to helper functions */
2477 parsestate
.oneBigWord
= FALSE
;
2478 parsestate
.varSpace
= ' '; /* word separator */
2482 while (*tstr
&& *tstr
!= endc
) {
2486 * We may have some complex modifiers in a variable.
2493 rval
= Var_Parse(tstr
, ctxt
, errnum
, &rlen
, &freeIt
);
2496 * If we have not parsed up to endc or ':',
2497 * we are not interested.
2499 if (rval
!= NULL
&& *rval
&&
2500 (c
= tstr
[rlen
]) != '\0' &&
2508 fprintf(debug_file
, "Got '%s' from '%.*s'%.*s\n",
2509 rval
, rlen
, tstr
, rlen
, tstr
+ rlen
);
2514 if (rval
!= NULL
&& *rval
) {
2517 nstr
= ApplyModifiers(nstr
, rval
,
2519 v
, ctxt
, errnum
, &used
, freePtr
);
2520 if (nstr
== var_Error
2521 || (nstr
== varNoError
&& errnum
== 0)
2522 || strlen(rval
) != (size_t) used
) {
2524 goto out
; /* error already reported */
2530 else if (!*tstr
&& endc
) {
2531 Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc
, v
->name
);
2538 fprintf(debug_file
, "Applying[%s] :%c to \"%s\"\n", v
->name
,
2542 switch ((modifier
= *tstr
)) {
2545 if (tstr
[1] == '=' ||
2547 (tstr
[1] == '!' || tstr
[1] == '+' || tstr
[1] == '?'))) {
2549 * "::=", "::!=", "::+=", or "::?="
2551 GNode
*v_ctxt
; /* context where v belongs */
2557 if (v
->name
[0] == 0)
2563 if (v
->flags
& VAR_JUNK
) {
2565 * We need to bmake_strdup() it incase
2566 * VarGetPattern() recurses.
2569 v
->name
= bmake_strdup(v
->name
);
2570 } else if (ctxt
!= VAR_GLOBAL
) {
2571 Var
*gv
= VarFind(v
->name
, ctxt
, 0);
2573 v_ctxt
= VAR_GLOBAL
;
2575 VarFreeEnv(gv
, TRUE
);
2578 switch ((how
= *tstr
)) {
2588 delim
= startc
== PROPEN
? PRCLOSE
: BRCLOSE
;
2591 pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2595 if (v
->flags
& VAR_JUNK
) {
2596 /* restore original name */
2600 if (pattern
.rhs
== NULL
)
2608 Var_Append(v
->name
, pattern
.rhs
, v_ctxt
);
2611 newStr
= Cmd_Exec(pattern
.rhs
, &emsg
);
2615 Var_Set(v
->name
, newStr
, v_ctxt
, 0);
2619 if ((v
->flags
& VAR_JUNK
) == 0)
2623 Var_Set(v
->name
, pattern
.rhs
, v_ctxt
, 0);
2626 free(UNCONST(pattern
.rhs
));
2627 newStr
= varNoError
;
2630 goto default_case
; /* "::<unrecognised>" */
2635 int flags
= VAR_NOSUBST
;
2639 if ((loop
.tvar
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2641 &flags
, &loop
.tvarLen
,
2645 if ((loop
.str
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2647 &flags
, &loop
.strLen
,
2654 loop
.errnum
= errnum
;
2656 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarLoopExpand
,
2665 Buffer buf
; /* Buffer for patterns */
2666 int wantit
; /* want data in buffer */
2669 * Pass through tstr looking for 1) escaped delimiters,
2670 * '$'s and backslashes (place the escaped character in
2671 * uninterpreted) and 2) unescaped $'s that aren't before
2672 * the delimiter (expand the variable substitution).
2673 * The result is left in the Buffer buf.
2677 *cp
!= endc
&& *cp
!= ':' && *cp
!= '\0';
2679 if ((*cp
== '\\') &&
2685 Buf_AddByte(&buf
, cp
[1]);
2687 } else if (*cp
== '$') {
2689 * If unescaped dollar sign, assume it's a
2690 * variable substitution and recurse.
2696 cp2
= Var_Parse(cp
, ctxt
, errnum
, &len
, &freeIt
);
2697 Buf_AddBytes(&buf
, strlen(cp2
), cp2
);
2701 Buf_AddByte(&buf
, *cp
);
2708 wantit
= ((v
->flags
& VAR_JUNK
) != 0);
2710 wantit
= ((v
->flags
& VAR_JUNK
) == 0);
2711 if ((v
->flags
& VAR_JUNK
) != 0)
2712 v
->flags
|= VAR_KEEP
;
2714 newStr
= Buf_Destroy(&buf
, FALSE
);
2717 Buf_Destroy(&buf
, TRUE
);
2723 if ((v
->flags
& VAR_JUNK
) != 0)
2724 v
->flags
|= VAR_KEEP
;
2725 newStr
= bmake_strdup(v
->name
);
2734 if ((v
->flags
& VAR_JUNK
) != 0)
2735 v
->flags
|= VAR_KEEP
;
2736 gn
= Targ_FindNode(v
->name
, TARG_NOCREATE
);
2737 if (gn
== NULL
|| gn
->type
& OP_NOPATH
) {
2739 } else if (gn
->path
) {
2740 newStr
= bmake_strdup(gn
->path
);
2742 newStr
= Dir_FindFile(v
->name
, Suff_FindPath(gn
));
2745 newStr
= bmake_strdup(v
->name
);
2760 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
2762 NULL
, &pattern
.rightLen
,
2765 newStr
= Cmd_Exec(pattern
.rhs
, &emsg
);
2766 free(UNCONST(pattern
.rhs
));
2771 if (v
->flags
& VAR_JUNK
) {
2772 v
->flags
|= VAR_KEEP
;
2779 * Look for the closing ']', recursively
2780 * expanding any embedded variables.
2782 * estr is a pointer to the expanded result,
2783 * which we must free().
2787 cp
= tstr
+1; /* point to char after '[' */
2788 delim
= ']'; /* look for closing ']' */
2789 estr
= VarGetPattern(ctxt
, &parsestate
,
2793 goto cleanup
; /* report missing ']' */
2794 /* now cp points just after the closing ']' */
2796 if (cp
[0] != ':' && cp
[0] != endc
) {
2797 /* Found junk after ']' */
2801 if (estr
[0] == '\0') {
2802 /* Found empty square brackets in ":[]". */
2805 } else if (estr
[0] == '#' && estr
[1] == '\0') {
2809 * We will need enough space for the decimal
2810 * representation of an int. We calculate the
2811 * space needed for the octal representation,
2812 * and add enough slop to cope with a '-' sign
2813 * (which should never be needed) and a '\0'
2814 * string terminator.
2817 (sizeof(int) * CHAR_BIT
+ 2) / 3 + 2;
2819 newStr
= bmake_malloc(newStrSize
);
2820 if (parsestate
.oneBigWord
) {
2821 strncpy(newStr
, "1", newStrSize
);
2823 /* XXX: brk_string() is a rather expensive
2824 * way of counting words. */
2829 av
= brk_string(nstr
, &ac
, FALSE
, &as
);
2830 snprintf(newStr
, newStrSize
, "%d", ac
);
2837 } else if (estr
[0] == '*' && estr
[1] == '\0') {
2839 parsestate
.oneBigWord
= TRUE
;
2844 } else if (estr
[0] == '@' && estr
[1] == '\0') {
2846 parsestate
.oneBigWord
= FALSE
;
2853 * We expect estr to contain a single
2854 * integer for :[N], or two integers
2855 * separated by ".." for :[start..end].
2859 VarSelectWords_t seldata
= { 0, 0 };
2861 seldata
.start
= strtol(estr
, &ep
, 0);
2863 /* Found junk instead of a number */
2866 } else if (ep
[0] == '\0') {
2867 /* Found only one integer in :[N] */
2868 seldata
.end
= seldata
.start
;
2869 } else if (ep
[0] == '.' && ep
[1] == '.' &&
2871 /* Expecting another integer after ".." */
2873 seldata
.end
= strtol(ep
, &ep
, 0);
2874 if (ep
[0] != '\0') {
2875 /* Found junk after ".." */
2880 /* Found junk instead of ".." */
2885 * Now seldata is properly filled in,
2886 * but we still have to check for 0 as
2889 if (seldata
.start
== 0 && seldata
.end
== 0) {
2890 /* ":[0]" or perhaps ":[0..0]" */
2891 parsestate
.oneBigWord
= TRUE
;
2896 } else if (seldata
.start
== 0 ||
2898 /* ":[0..N]" or ":[N..0]" */
2903 * Normal case: select the words
2904 * described by seldata.
2906 newStr
= VarSelectWords(ctxt
, &parsestate
,
2916 cp
= tstr
+ 1; /* make sure it is set */
2917 if (STRMOD_MATCH(tstr
, "gmtime", 6)) {
2918 newStr
= VarStrftime(nstr
, 1);
2926 cp
= tstr
+ 1; /* make sure it is set */
2927 if (STRMOD_MATCH(tstr
, "hash", 4)) {
2928 newStr
= VarHash(nstr
);
2936 cp
= tstr
+ 1; /* make sure it is set */
2937 if (STRMOD_MATCH(tstr
, "localtime", 9)) {
2938 newStr
= VarStrftime(nstr
, 0);
2947 cp
= tstr
+ 1; /* make sure it is set */
2948 if (tstr
[1] != endc
&& tstr
[1] != ':') {
2949 if (tstr
[1] == 's') {
2951 * Use the char (if any) at tstr[2]
2952 * as the word separator.
2956 if (tstr
[2] != endc
&&
2957 (tstr
[3] == endc
|| tstr
[3] == ':')) {
2958 /* ":ts<unrecognised><endc>" or
2959 * ":ts<unrecognised>:" */
2960 parsestate
.varSpace
= tstr
[2];
2962 } else if (tstr
[2] == endc
|| tstr
[2] == ':') {
2963 /* ":ts<endc>" or ":ts:" */
2964 parsestate
.varSpace
= 0; /* no separator */
2966 } else if (tstr
[2] == '\\') {
2969 parsestate
.varSpace
= '\n';
2973 parsestate
.varSpace
= '\t';
2977 if (isdigit((unsigned char)tstr
[3])) {
2980 parsestate
.varSpace
=
2981 strtoul(&tstr
[3], &ep
, 0);
2982 if (*ep
!= ':' && *ep
!= endc
)
2987 * ":ts<backslash><unrecognised>".
2995 * Found ":ts<unrecognised><unrecognised>".
3003 * We cannot be certain that VarModify
3004 * will be used - even if there is a
3005 * subsequent modifier, so do a no-op
3006 * VarSubstitute now to for str to be
3007 * re-expanded without the spaces.
3009 pattern
.flags
= VAR_SUB_ONE
;
3010 pattern
.lhs
= pattern
.rhs
= "\032";
3011 pattern
.leftLen
= pattern
.rightLen
= 1;
3013 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3016 } else if (tstr
[2] == endc
|| tstr
[2] == ':') {
3018 * Check for two-character options:
3021 if (tstr
[1] == 'A') { /* absolute path */
3022 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3026 } else if (tstr
[1] == 'u') {
3027 char *dp
= bmake_strdup(nstr
);
3028 for (newStr
= dp
; *dp
; dp
++)
3029 *dp
= toupper((unsigned char)*dp
);
3032 } else if (tstr
[1] == 'l') {
3033 char *dp
= bmake_strdup(nstr
);
3034 for (newStr
= dp
; *dp
; dp
++)
3035 *dp
= tolower((unsigned char)*dp
);
3038 } else if (tstr
[1] == 'W' || tstr
[1] == 'w') {
3039 parsestate
.oneBigWord
= (tstr
[1] == 'W');
3044 /* Found ":t<unrecognised>:" or
3045 * ":t<unrecognised><endc>". */
3050 * Found ":t<unrecognised><unrecognised>".
3056 * Found ":t<endc>" or ":t:".
3066 const char *endpat
; /* points just after end of pattern */
3068 Boolean copy
; /* pattern should be, or has been, copied */
3076 * In the loop below, ignore ':' unless we are at
3077 * (or back to) the original brace level.
3078 * XXX This will likely not work right if $() and ${}
3082 *cp
!= '\0' && !(*cp
== ':' && nest
== 1);
3087 cp
[1] == endc
|| cp
[1] == startc
)) {
3097 if (*cp
== '(' || *cp
== '{')
3099 if (*cp
== ')' || *cp
== '}') {
3109 * Need to compress the \:'s out of the pattern, so
3110 * allocate enough room to hold the uncompressed
3111 * pattern (note that cp started at tstr+1, so
3112 * cp - tstr takes the null byte into account) and
3113 * compress the pattern into the space.
3115 pattern
= bmake_malloc(cp
- tstr
);
3116 for (cp2
= pattern
, cp
= tstr
+ 1;
3120 if ((*cp
== '\\') && (cp
+1 < endpat
) &&
3121 (cp
[1] == ':' || cp
[1] == endc
)) {
3130 * Either Var_Subst or VarModify will need a
3131 * nul-terminated string soon, so construct one now.
3133 pattern
= bmake_strndup(tstr
+1, endpat
- (tstr
+ 1));
3137 * pattern contains embedded '$', so use Var_Subst to
3141 pattern
= Var_Subst(NULL
, cp2
, ctxt
, errnum
);
3145 fprintf(debug_file
, "Pattern[%s] for [%s] is [%s]\n",
3146 v
->name
, nstr
, pattern
);
3148 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarMatch
,
3151 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarNoMatch
,
3160 Var_Parse_State tmpparsestate
;
3163 tmpparsestate
= parsestate
;
3168 * If pattern begins with '^', it is anchored to the
3169 * start of the word -- skip over it and flag pattern.
3172 pattern
.flags
|= VAR_MATCH_START
;
3177 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3184 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3191 * Check for global substitution. If 'g' after the final
3192 * delimiter, substitution is global and is marked that
3198 pattern
.flags
|= VAR_SUB_GLOBAL
;
3201 pattern
.flags
|= VAR_SUB_ONE
;
3204 tmpparsestate
.oneBigWord
= TRUE
;
3211 newStr
= VarModify(ctxt
, &tmpparsestate
, nstr
,
3216 * Free the two strings.
3218 free(UNCONST(pattern
.lhs
));
3219 free(UNCONST(pattern
.rhs
));
3228 /* find ':', and then substitute accordingly */
3234 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3240 /* BROPEN or PROPEN */
3242 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
, errnum
,
3250 if (Cond_EvalExpression(NULL
, v
->name
, &value
, 0, FALSE
)
3252 Error("Bad conditional expression `%s' in %s?%s:%s",
3253 v
->name
, v
->name
, pattern
.lhs
, pattern
.rhs
);
3258 newStr
= UNCONST(pattern
.lhs
);
3259 free(UNCONST(pattern
.rhs
));
3261 newStr
= UNCONST(pattern
.rhs
);
3262 free(UNCONST(pattern
.lhs
));
3264 if (v
->flags
& VAR_JUNK
) {
3265 v
->flags
|= VAR_KEEP
;
3272 VarREPattern pattern
;
3275 Var_Parse_State tmpparsestate
;
3278 tmpparsestate
= parsestate
;
3284 if ((re
= VarGetPattern(ctxt
, &parsestate
, errnum
, &cp
, delim
,
3285 NULL
, NULL
, NULL
)) == NULL
)
3288 if ((pattern
.replace
= VarGetPattern(ctxt
, &parsestate
,
3289 errnum
, &cp
, delim
, NULL
,
3290 NULL
, NULL
)) == NULL
){
3298 pattern
.flags
|= VAR_SUB_GLOBAL
;
3301 pattern
.flags
|= VAR_SUB_ONE
;
3304 tmpparsestate
.oneBigWord
= TRUE
;
3312 error
= regcomp(&pattern
.re
, re
, REG_EXTENDED
);
3315 *lengthPtr
= cp
- start
+ 1;
3316 VarREError(error
, &pattern
.re
, "RE substitution error");
3317 free(pattern
.replace
);
3321 pattern
.nsub
= pattern
.re
.re_nsub
+ 1;
3322 if (pattern
.nsub
< 1)
3324 if (pattern
.nsub
> 10)
3326 pattern
.matches
= bmake_malloc(pattern
.nsub
*
3327 sizeof(regmatch_t
));
3328 newStr
= VarModify(ctxt
, &tmpparsestate
, nstr
,
3331 regfree(&pattern
.re
);
3332 free(pattern
.replace
);
3333 free(pattern
.matches
);
3339 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3340 newStr
= VarQuote(nstr
);
3347 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3348 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarTail
,
3356 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3357 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarHead
,
3365 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3366 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarSuffix
,
3374 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3375 newStr
= VarModify(ctxt
, &parsestate
, nstr
, VarRoot
,
3386 cp
= tstr
+ 1; /* skip to the rest in any case */
3387 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3390 } else if ( (tstr
[1] == 'x') &&
3391 (tstr
[2] == endc
|| tstr
[2] == ':') ) {
3398 newStr
= VarOrder(nstr
, otype
);
3402 if (tstr
[1] == endc
|| tstr
[1] == ':') {
3403 newStr
= VarUniq(nstr
);
3411 if (tstr
[1] == 'h' && (tstr
[2] == endc
|| tstr
[2] == ':')) {
3413 newStr
= Cmd_Exec(nstr
, &emsg
);
3427 * This can either be a bogus modifier or a System-V
3428 * substitution command.
3436 * First we make a pass through the string trying
3437 * to verify it is a SYSV-make-style translation:
3438 * it must be: <string1>=<string2>)
3442 while (*cp
!= '\0' && cnt
) {
3445 /* continue looking for endc */
3447 else if (*cp
== endc
)
3449 else if (*cp
== startc
)
3454 if (*cp
== endc
&& eqFound
) {
3457 * Now we break this sucker into the lhs and
3458 * rhs. We must null terminate them of course.
3462 if ((pattern
.lhs
= VarGetPattern(ctxt
, &parsestate
,
3463 errnum
, &cp
, delim
, &pattern
.flags
,
3464 &pattern
.leftLen
, NULL
)) == NULL
)
3467 if ((pattern
.rhs
= VarGetPattern(ctxt
, &parsestate
,
3468 errnum
, &cp
, delim
, NULL
, &pattern
.rightLen
,
3473 * SYSV modifications happen through the whole
3474 * string. Note the pattern is anchored at the end.
3478 if (pattern
.leftLen
== 0 && *nstr
== '\0') {
3479 newStr
= nstr
; /* special case */
3481 newStr
= VarModify(ctxt
, &parsestate
, nstr
,
3485 free(UNCONST(pattern
.lhs
));
3486 free(UNCONST(pattern
.rhs
));
3490 Error("Unknown modifier '%c'", *tstr
);
3492 *cp
!= ':' && *cp
!= endc
&& *cp
!= '\0';
3501 fprintf(debug_file
, "Result[%s] of :%c is \"%s\"\n",
3502 v
->name
, modifier
, newStr
);
3505 if (newStr
!= nstr
) {
3511 if (nstr
!= var_Error
&& nstr
!= varNoError
) {
3515 if (termc
== '\0' && endc
!= '\0') {
3516 Error("Unclosed variable specification (expecting '%c') for \"%s\" (value \"%s\") modifier %c", endc
, v
->name
, nstr
, modifier
);
3517 } else if (termc
== ':') {
3523 *lengthPtr
= tstr
- start
;
3528 Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr
, ":)}"), tstr
,
3532 *lengthPtr
= cp
- start
;
3534 Error("Unclosed substitution for %s (%c missing)",
3542 *-----------------------------------------------------------------------
3544 * Given the start of a variable invocation, extract the variable
3545 * name and find its value, then modify it according to the
3549 * str The string to parse
3550 * ctxt The context for the variable
3551 * errnum TRUE if undefined variables are an error
3552 * lengthPtr OUT: The length of the specification
3553 * freePtr OUT: Non-NULL if caller should free *freePtr
3556 * The (possibly-modified) value of the variable or var_Error if the
3557 * specification is invalid. The length of the specification is
3558 * placed in *lengthPtr (for invalid specifications, this is just
3560 * If *freePtr is non-NULL then it's a pointer that the caller
3561 * should pass to free() to free memory used by the result.
3566 *-----------------------------------------------------------------------
3568 /* coverity[+alloc : arg-*4] */
3570 Var_Parse(const char *str
, GNode
*ctxt
, Boolean errnum
, int *lengthPtr
,
3573 const char *tstr
; /* Pointer into str */
3574 Var
*v
; /* Variable in invocation */
3575 Boolean haveModifier
;/* TRUE if have modifiers for the variable */
3576 char endc
; /* Ending character when variable in parens
3578 char startc
; /* Starting character when variable in parens
3580 int vlen
; /* Length of variable name */
3581 const char *start
; /* Points to original start of str */
3582 char *nstr
; /* New string, used during expansion */
3583 Boolean dynamic
; /* TRUE if the variable is local and we're
3584 * expanding it in a non-local context. This
3585 * is done to support dynamic sources. The
3586 * result is just the invocation, unaltered */
3587 const char *extramodifiers
; /* extra modifiers to apply first */
3591 extramodifiers
= NULL
;
3596 if (startc
!= PROPEN
&& startc
!= BROPEN
) {
3598 * If it's not bounded by braces of some sort, life is much simpler.
3599 * We just need to check for the first character and return the
3600 * value if it exists.
3603 /* Error out some really stupid names */
3604 if (startc
== '\0' || strchr(")}:$", startc
)) {
3611 v
= VarFind(name
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
3615 if ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)) {
3617 * If substituting a local variable in a non-local context,
3618 * assume it's for dynamic source stuff. We have to handle
3619 * this specially and return the longhand for the variable
3620 * with the dollar sign escaped so it makes it back to the
3621 * caller. Only four of the local variables are treated
3622 * specially as they are the only four that will be set
3623 * when dynamic sources are expanded.
3627 return UNCONST("$(.TARGET)");
3629 return UNCONST("$(.ARCHIVE)");
3631 return UNCONST("$(.PREFIX)");
3633 return UNCONST("$(.MEMBER)");
3639 return (errnum
? var_Error
: varNoError
);
3641 haveModifier
= FALSE
;
3646 Buffer buf
; /* Holds the variable name */
3649 endc
= startc
== PROPEN
? PRCLOSE
: BRCLOSE
;
3653 * Skip to the end character or a colon, whichever comes first.
3655 for (tstr
= str
+ 2; *tstr
!= '\0'; tstr
++)
3658 * Track depth so we can spot parse errors.
3660 if (*tstr
== startc
) {
3663 if (*tstr
== endc
) {
3667 if (depth
== 1 && *tstr
== ':') {
3671 * A variable inside a variable, expand
3676 char *rval
= Var_Parse(tstr
, ctxt
, errnum
, &rlen
, &freeIt
);
3678 Buf_AddBytes(&buf
, strlen(rval
), rval
);
3684 Buf_AddByte(&buf
, *tstr
);
3687 haveModifier
= TRUE
;
3688 } else if (*tstr
== endc
) {
3689 haveModifier
= FALSE
;
3692 * If we never did find the end character, return NULL
3693 * right now, setting the length to be the distance to
3694 * the end of the string, since that's what make does.
3696 *lengthPtr
= tstr
- str
;
3697 Buf_Destroy(&buf
, TRUE
);
3700 str
= Buf_GetAll(&buf
, &vlen
);
3703 * At this point, str points into newly allocated memory from
3704 * buf, containing only the name of the variable.
3706 * start and tstr point into the const string that was pointed
3707 * to by the original value of the str parameter. start points
3708 * to the '$' at the beginning of the string, while tstr points
3709 * to the char just after the end of the variable name -- this
3710 * will be '\0', ':', PRCLOSE, or BRCLOSE.
3713 v
= VarFind(str
, ctxt
, FIND_ENV
| FIND_GLOBAL
| FIND_CMD
);
3715 * Check also for bogus D and F forms of local variables since we're
3716 * in a local context and the name is the right length.
3718 if ((v
== NULL
) && (ctxt
!= VAR_CMD
) && (ctxt
!= VAR_GLOBAL
) &&
3719 (vlen
== 2) && (str
[1] == 'F' || str
[1] == 'D') &&
3720 strchr("@%?*!<>", str
[0]) != NULL
) {
3722 * Well, it's local -- go look for it.
3726 v
= VarFind(name
, ctxt
, 0);
3729 if (str
[1] == 'D') {
3730 extramodifiers
= "H:";
3733 extramodifiers
= "T:";
3740 (((vlen
== 2) && (str
[1] == 'F' || str
[1] == 'D')))) &&
3741 ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)))
3744 * If substituting a local variable in a non-local context,
3745 * assume it's for dynamic source stuff. We have to handle
3746 * this specially and return the longhand for the variable
3747 * with the dollar sign escaped so it makes it back to the
3748 * caller. Only four of the local variables are treated
3749 * specially as they are the only four that will be set
3750 * when dynamic sources are expanded.
3760 } else if ((vlen
> 2) && (*str
== '.') &&
3761 isupper((unsigned char) str
[1]) &&
3762 ((ctxt
== VAR_CMD
) || (ctxt
== VAR_GLOBAL
)))
3767 if ((strncmp(str
, ".TARGET", len
) == 0) ||
3768 (strncmp(str
, ".ARCHIVE", len
) == 0) ||
3769 (strncmp(str
, ".PREFIX", len
) == 0) ||
3770 (strncmp(str
, ".MEMBER", len
) == 0))
3776 if (!haveModifier
) {
3778 * No modifiers -- have specification length so we can return
3781 *lengthPtr
= tstr
- start
+ 1;
3783 char *pstr
= bmake_strndup(start
, *lengthPtr
);
3785 Buf_Destroy(&buf
, TRUE
);
3788 Buf_Destroy(&buf
, TRUE
);
3789 return (errnum
? var_Error
: varNoError
);
3793 * Still need to get to the end of the variable specification,
3794 * so kludge up a Var structure for the modifications
3796 v
= bmake_malloc(sizeof(Var
));
3797 v
->name
= UNCONST(str
);
3798 Buf_Init(&v
->val
, 1);
3799 v
->flags
= VAR_JUNK
;
3800 Buf_Destroy(&buf
, FALSE
);
3803 Buf_Destroy(&buf
, TRUE
);
3806 if (v
->flags
& VAR_IN_USE
) {
3807 Fatal("Variable %s is recursive.", v
->name
);
3810 v
->flags
|= VAR_IN_USE
;
3813 * Before doing any modification, we have to make sure the value
3814 * has been fully expanded. If it looks like recursion might be
3815 * necessary (there's a dollar sign somewhere in the variable's value)
3816 * we just call Var_Subst to do any other substitutions that are
3817 * necessary. Note that the value returned by Var_Subst will have
3818 * been dynamically-allocated, so it will need freeing when we
3821 nstr
= Buf_GetAll(&v
->val
, NULL
);
3822 if (strchr(nstr
, '$') != NULL
) {
3823 nstr
= Var_Subst(NULL
, nstr
, ctxt
, errnum
);
3827 v
->flags
&= ~VAR_IN_USE
;
3829 if ((nstr
!= NULL
) && (haveModifier
|| extramodifiers
!= NULL
)) {
3834 if (extramodifiers
!= NULL
) {
3835 nstr
= ApplyModifiers(nstr
, extramodifiers
, '(', ')',
3836 v
, ctxt
, errnum
, &used
, &extraFree
);
3840 /* Skip initial colon. */
3843 nstr
= ApplyModifiers(nstr
, tstr
, startc
, endc
,
3844 v
, ctxt
, errnum
, &used
, freePtr
);
3848 *freePtr
= extraFree
;
3852 *lengthPtr
= tstr
- start
+ 1;
3854 *lengthPtr
= tstr
- start
;
3857 if (v
->flags
& VAR_FROM_ENV
) {
3858 Boolean destroy
= FALSE
;
3860 if (nstr
!= Buf_GetAll(&v
->val
, NULL
)) {
3864 * Returning the value unmodified, so tell the caller to free
3869 VarFreeEnv(v
, destroy
);
3870 } else if (v
->flags
& VAR_JUNK
) {
3872 * Perform any free'ing needed and set *freePtr to NULL so the caller
3873 * doesn't try to free a static pointer.
3874 * If VAR_KEEP is also set then we want to keep str as is.
3876 if (!(v
->flags
& VAR_KEEP
)) {
3882 nstr
= bmake_strndup(start
, *lengthPtr
);
3885 nstr
= errnum
? var_Error
: varNoError
;
3888 if (nstr
!= Buf_GetAll(&v
->val
, NULL
))
3889 Buf_Destroy(&v
->val
, TRUE
);
3897 *-----------------------------------------------------------------------
3899 * Substitute for all variables in the given string in the given context
3900 * If undefErr is TRUE, Parse_Error will be called when an undefined
3901 * variable is encountered.
3904 * var Named variable || NULL for all
3905 * str the string which to substitute
3906 * ctxt the context wherein to find variables
3907 * undefErr TRUE if undefineds are an error
3910 * The resulting string.
3913 * None. The old string must be freed by the caller
3914 *-----------------------------------------------------------------------
3917 Var_Subst(const char *var
, const char *str
, GNode
*ctxt
, Boolean undefErr
)
3919 Buffer buf
; /* Buffer for forming things */
3920 char *val
; /* Value to substitute for a variable */
3921 int length
; /* Length of the variable invocation */
3922 Boolean trailingBslash
; /* variable ends in \ */
3923 void *freeIt
= NULL
; /* Set if it should be freed */
3924 static Boolean errorReported
; /* Set true if an error has already
3925 * been reported to prevent a plethora
3926 * of messages when recursing */
3929 errorReported
= FALSE
;
3930 trailingBslash
= FALSE
;
3933 if (*str
== '\n' && trailingBslash
)
3934 Buf_AddByte(&buf
, ' ');
3935 if (var
== NULL
&& (*str
== '$') && (str
[1] == '$')) {
3937 * A dollar sign may be escaped either with another dollar sign.
3938 * In such a case, we skip over the escape character and store the
3939 * dollar sign into the buffer directly.
3942 Buf_AddByte(&buf
, *str
);
3944 } else if (*str
!= '$') {
3946 * Skip as many characters as possible -- either to the end of
3947 * the string or to the next dollar sign (variable invocation).
3951 for (cp
= str
++; *str
!= '$' && *str
!= '\0'; str
++)
3953 Buf_AddBytes(&buf
, str
- cp
, cp
);
3958 if (str
[1] == '\0') {
3959 /* A trailing $ is kind of a special case */
3960 Buf_AddByte(&buf
, str
[0]);
3963 } else if (str
[1] != PROPEN
&& str
[1] != BROPEN
) {
3964 if (str
[1] != *var
|| strlen(var
) > 1) {
3965 Buf_AddBytes(&buf
, 2, str
);
3977 * Scan up to the end of the variable name.
3979 for (p
= &str
[2]; *p
&&
3980 *p
!= ':' && *p
!= PRCLOSE
&& *p
!= BRCLOSE
; p
++)
3984 * A variable inside the variable. We cannot expand
3985 * the external variable yet, so we try again with
3989 Buf_AddBytes(&buf
, p
- str
, str
);
3994 if (strncmp(var
, str
+ 2, p
- str
- 2) != 0 ||
3995 var
[p
- str
- 2] != '\0') {
3997 * Not the variable we want to expand, scan
3998 * until the next variable
4000 for (;*p
!= '$' && *p
!= '\0'; p
++)
4002 Buf_AddBytes(&buf
, p
- str
, str
);
4015 val
= Var_Parse(str
, ctxt
, undefErr
, &length
, &freeIt
);
4018 * When we come down here, val should either point to the
4019 * value of this variable, suitably modified, or be NULL.
4020 * Length should be the total length of the potential
4021 * variable invocation (from $ to end character...)
4023 if (val
== var_Error
|| val
== varNoError
) {
4025 * If performing old-time variable substitution, skip over
4026 * the variable and continue with the substitution. Otherwise,
4027 * store the dollar sign and advance str so we continue with
4032 } else if (undefErr
|| val
== var_Error
) {
4034 * If variable is undefined, complain and skip the
4035 * variable. The complaint will stop us from doing anything
4036 * when the file is parsed.
4038 if (!errorReported
) {
4039 Parse_Error(PARSE_FATAL
,
4040 "Undefined variable \"%.*s\"",length
,str
);
4043 errorReported
= TRUE
;
4045 Buf_AddByte(&buf
, *str
);
4050 * We've now got a variable structure to store in. But first,
4051 * advance the string pointer.
4056 * Copy all the characters from the variable value straight
4057 * into the new string.
4059 length
= strlen(val
);
4060 Buf_AddBytes(&buf
, length
, val
);
4061 trailingBslash
= length
> 0 && val
[length
- 1] == '\\';
4068 return Buf_DestroyCompact(&buf
);
4072 *-----------------------------------------------------------------------
4074 * Return the tail from each of a list of words. Used to set the
4075 * System V local variables.
4078 * file Filename to modify
4081 * The resulting string.
4086 *-----------------------------------------------------------------------
4090 Var_GetTail(char *file
)
4092 return(VarModify(file
, VarTail
, NULL
));
4096 *-----------------------------------------------------------------------
4098 * Find the leading components of a (list of) filename(s).
4099 * XXX: VarHead does not replace foo by ., as (sun) System V make
4103 * file Filename to manipulate
4106 * The leading components.
4111 *-----------------------------------------------------------------------
4114 Var_GetHead(char *file
)
4116 return(VarModify(file
, VarHead
, NULL
));
4121 *-----------------------------------------------------------------------
4123 * Initialize the module
4129 * The VAR_CMD and VAR_GLOBAL contexts are created
4130 *-----------------------------------------------------------------------
4135 VAR_INTERNAL
= Targ_NewGN("Internal");
4136 VAR_GLOBAL
= Targ_NewGN("Global");
4137 VAR_CMD
= Targ_NewGN("Command");
4148 /****************** PRINT DEBUGGING INFO *****************/
4150 VarPrintVar(void *vp
)
4153 fprintf(debug_file
, "%-16s = %s\n", v
->name
, Buf_GetAll(&v
->val
, NULL
));
4157 *-----------------------------------------------------------------------
4159 * print all variables in a context
4160 *-----------------------------------------------------------------------
4163 Var_Dump(GNode
*ctxt
)
4168 for (h
= Hash_EnumFirst(&ctxt
->context
, &search
);
4170 h
= Hash_EnumNext(&search
)) {
4171 VarPrintVar(Hash_GetValue(h
));