Sat Jul 4 10:19:39 2020 UTC ()
make(1): remove unnecessary forward declarations


(rillig)
diff -r1.247 -r1.248 src/usr.bin/make/var.c

cvs diff -r1.247 -r1.248 src/usr.bin/make/var.c (switch to unified diff)

--- src/usr.bin/make/var.c 2020/07/04 03:08:20 1.247
+++ src/usr.bin/make/var.c 2020/07/04 10:19:39 1.248
@@ -1,1327 +1,1300 @@ @@ -1,1327 +1,1300 @@
1/* $NetBSD: var.c,v 1.247 2020/07/04 03:08:20 lukem Exp $ */ 1/* $NetBSD: var.c,v 1.248 2020/07/04 10:19:39 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 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 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of 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 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: var.c,v 1.247 2020/07/04 03:08:20 lukem Exp $"; 72static char rcsid[] = "$NetBSD: var.c,v 1.248 2020/07/04 10:19:39 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; 77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
78#else 78#else
79__RCSID("$NetBSD: var.c,v 1.247 2020/07/04 03:08:20 lukem Exp $"); 79__RCSID("$NetBSD: var.c,v 1.248 2020/07/04 10:19:39 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * var.c -- 85 * var.c --
86 * Variable-handling functions 86 * Variable-handling functions
87 * 87 *
88 * Interface: 88 * Interface:
89 * Var_Set Set the value of a variable in the given 89 * Var_Set Set the value of a variable in the given
90 * context. The variable is created if it doesn't 90 * context. The variable is created if it doesn't
91 * yet exist. The value and variable name need not 91 * yet exist. The value and variable name need not
92 * be preserved. 92 * be preserved.
93 * 93 *
94 * Var_Append Append more characters to an existing variable 94 * Var_Append Append more characters to an existing variable
95 * in the given context. The variable needn't 95 * in the given context. The variable needn't
96 * exist already -- it will be created if it doesn't. 96 * exist already -- it will be created if it doesn't.
97 * A space is placed between the old value and the 97 * A space is placed between the old value and the
98 * new one. 98 * new one.
99 * 99 *
100 * Var_Exists See if a variable exists. 100 * Var_Exists See if a variable exists.
101 * 101 *
102 * Var_Value Return the value of a variable in a context or 102 * Var_Value Return the value of a variable in a context or
103 * NULL if the variable is undefined. 103 * NULL if the variable is undefined.
104 * 104 *
105 * Var_Subst Substitute named variable, or all variables if 105 * Var_Subst Substitute named variable, or all variables if
106 * NULL in a string using 106 * NULL in a string using
107 * the given context as the top-most one. If the 107 * the given context as the top-most one. If the
108 * third argument is non-zero, Parse_Error is 108 * third argument is non-zero, Parse_Error is
109 * called if any variables are undefined. 109 * called if any variables are undefined.
110 * 110 *
111 * Var_Parse Parse a variable expansion from a string and 111 * Var_Parse Parse a variable expansion from a string and
112 * return the result and the number of characters 112 * return the result and the number of characters
113 * consumed. 113 * consumed.
114 * 114 *
115 * Var_Delete Delete a variable in a context. 115 * Var_Delete Delete a variable in a context.
116 * 116 *
117 * Var_Init Initialize this module. 117 * Var_Init Initialize this module.
118 * 118 *
119 * Debugging: 119 * Debugging:
120 * Var_Dump Print out all variables defined in the given 120 * Var_Dump Print out all variables defined in the given
121 * context. 121 * context.
122 * 122 *
123 * XXX: There's a lot of duplication in these functions. 123 * XXX: There's a lot of duplication in these functions.
124 */ 124 */
125 125
126#include <sys/stat.h> 126#include <sys/stat.h>
127#ifndef NO_REGEX 127#ifndef NO_REGEX
128#include <sys/types.h> 128#include <sys/types.h>
129#include <regex.h> 129#include <regex.h>
130#endif 130#endif
131#include <ctype.h> 131#include <ctype.h>
132#include <inttypes.h> 132#include <inttypes.h>
133#include <stdlib.h> 133#include <stdlib.h>
134#include <limits.h> 134#include <limits.h>
135#include <time.h> 135#include <time.h>
136 136
137#include "make.h" 137#include "make.h"
138#include "buf.h" 138#include "buf.h"
139#include "dir.h" 139#include "dir.h"
140#include "job.h" 140#include "job.h"
141#include "metachar.h" 141#include "metachar.h"
142 142
143extern int makelevel; 143extern int makelevel;
144/* 144/*
145 * This lets us tell if we have replaced the original environ 145 * This lets us tell if we have replaced the original environ
146 * (which we cannot free). 146 * (which we cannot free).
147 */ 147 */
148char **savedEnv = NULL; 148char **savedEnv = NULL;
149 149
150/* 150/*
151 * This is a harmless return value for Var_Parse that can be used by Var_Subst 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 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. 153 * a flag, as things outside this module don't give a hoot.
154 */ 154 */
155char var_Error[] = ""; 155char var_Error[] = "";
156 156
157/* 157/*
158 * Similar to var_Error, but returned when the 'VARF_UNDEFERR' flag for 158 * Similar to var_Error, but returned when the 'VARF_UNDEFERR' flag for
159 * Var_Parse is not set. Why not just use a constant? Well, gcc likes 159 * Var_Parse is not set. Why not just use a constant? Well, gcc likes
160 * to condense identical string instances... 160 * to condense identical string instances...
161 */ 161 */
162static char varNoError[] = ""; 162static char varNoError[] = "";
163 163
164/* 164/*
165 * Traditionally we consume $$ during := like any other expansion. 165 * Traditionally we consume $$ during := like any other expansion.
166 * Other make's do not. 166 * Other make's do not.
167 * This knob allows controlling the behavior. 167 * This knob allows controlling the behavior.
168 * FALSE for old behavior. 168 * FALSE for old behavior.
169 * TRUE for new compatible. 169 * TRUE for new compatible.
170 */ 170 */
171#define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" 171#define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
172static Boolean save_dollars = TRUE; 172static Boolean save_dollars = TRUE;
173 173
174/* 174/*
175 * Internally, variables are contained in four different contexts. 175 * Internally, variables are contained in four different contexts.
176 * 1) the environment. They may not be changed. If an environment 176 * 1) the environment. They may not be changed. If an environment
177 * variable is appended-to, the result is placed in the global 177 * variable is appended-to, the result is placed in the global
178 * context. 178 * context.
179 * 2) the global context. Variables set in the Makefile are located in 179 * 2) the global context. Variables set in the Makefile are located in
180 * the global context. It is the penultimate context searched when 180 * the global context. It is the penultimate context searched when
181 * substituting. 181 * substituting.
182 * 3) the command-line context. All variables set on the command line 182 * 3) the command-line context. All variables set on the command line
183 * are placed in this context. They are UNALTERABLE once placed here. 183 * are placed in this context. They are UNALTERABLE once placed here.
184 * 4) the local context. Each target has associated with it a context 184 * 4) the local context. Each target has associated with it a context
185 * list. On this list are located the structures describing such 185 * list. On this list are located the structures describing such
186 * local variables as $(@) and $(*) 186 * local variables as $(@) and $(*)
187 * The four contexts are searched in the reverse order from which they are 187 * The four contexts are searched in the reverse order from which they are
188 * listed. 188 * listed.
189 */ 189 */
190GNode *VAR_INTERNAL; /* variables from make itself */ 190GNode *VAR_INTERNAL; /* variables from make itself */
191GNode *VAR_GLOBAL; /* variables from the makefile */ 191GNode *VAR_GLOBAL; /* variables from the makefile */
192GNode *VAR_CMD; /* variables defined on the command-line */ 192GNode *VAR_CMD; /* variables defined on the command-line */
193 193
194#define FIND_CMD 0x1 /* look in VAR_CMD when searching */ 194#define FIND_CMD 0x1 /* look in VAR_CMD when searching */
195#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */ 195#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
196#define FIND_ENV 0x4 /* look in the environment also */ 196#define FIND_ENV 0x4 /* look in the environment also */
197 197
198typedef enum { 198typedef enum {
199 VAR_IN_USE = 0x01, /* Variable's value is currently being used. 199 VAR_IN_USE = 0x01, /* Variable's value is currently being used.
200 * Used to avoid endless recursion */ 200 * Used to avoid endless recursion */
201 VAR_FROM_ENV = 0x02, /* Variable comes from the environment */ 201 VAR_FROM_ENV = 0x02, /* Variable comes from the environment */
202 VAR_JUNK = 0x04, /* Variable is a junk variable that 202 VAR_JUNK = 0x04, /* Variable is a junk variable that
203 * should be destroyed when done with 203 * should be destroyed when done with
204 * it. Used by Var_Parse for undefined, 204 * it. Used by Var_Parse for undefined,
205 * modified variables */ 205 * modified variables */
206 VAR_KEEP = 0x08, /* Variable is VAR_JUNK, but we found 206 VAR_KEEP = 0x08, /* Variable is VAR_JUNK, but we found
207 * a use for it in some modifier and 207 * a use for it in some modifier and
208 * the value is therefore valid */ 208 * the value is therefore valid */
209 VAR_EXPORTED = 0x10, /* Variable is exported */ 209 VAR_EXPORTED = 0x10, /* Variable is exported */
210 VAR_REEXPORT = 0x20, /* Indicate if var needs re-export. 210 VAR_REEXPORT = 0x20, /* Indicate if var needs re-export.
211 * This would be true if it contains $'s */ 211 * This would be true if it contains $'s */
212 VAR_FROM_CMD = 0x40 /* Variable came from command line */ 212 VAR_FROM_CMD = 0x40 /* Variable came from command line */
213} Var_Flags; 213} Var_Flags;
214 214
215typedef struct Var { 215typedef struct Var {
216 char *name; /* the variable's name */ 216 char *name; /* the variable's name */
217 Buffer val; /* its value */ 217 Buffer val; /* its value */
218 Var_Flags flags; /* miscellaneous status flags */ 218 Var_Flags flags; /* miscellaneous status flags */
219} Var; 219} Var;
220 220
221/* 221/*
222 * Exporting vars is expensive so skip it if we can 222 * Exporting vars is expensive so skip it if we can
223 */ 223 */
224#define VAR_EXPORTED_NONE 0 224#define VAR_EXPORTED_NONE 0
225#define VAR_EXPORTED_YES 1 225#define VAR_EXPORTED_YES 1
226#define VAR_EXPORTED_ALL 2 226#define VAR_EXPORTED_ALL 2
227static int var_exportedVars = VAR_EXPORTED_NONE; 227static int var_exportedVars = VAR_EXPORTED_NONE;
228/* 228/*
229 * We pass this to Var_Export when doing the initial export 229 * We pass this to Var_Export when doing the initial export
230 * or after updating an exported var. 230 * or after updating an exported var.
231 */ 231 */
232#define VAR_EXPORT_PARENT 1 232#define VAR_EXPORT_PARENT 1
233/* 233/*
234 * We pass this to Var_Export1 to tell it to leave the value alone. 234 * We pass this to Var_Export1 to tell it to leave the value alone.
235 */ 235 */
236#define VAR_EXPORT_LITERAL 2 236#define VAR_EXPORT_LITERAL 2
237 237
238typedef enum { 238typedef enum {
239 VAR_SUB_GLOBAL = 0x01, /* Apply substitution globally */ 239 VAR_SUB_GLOBAL = 0x01, /* Apply substitution globally */
240 VAR_SUB_ONE = 0x02, /* Apply substitution to one word */ 240 VAR_SUB_ONE = 0x02, /* Apply substitution to one word */
241 VAR_SUB_MATCHED = 0x04, /* There was a match */ 241 VAR_SUB_MATCHED = 0x04, /* There was a match */
242 VAR_MATCH_START = 0x08, /* Match at start of word */ 242 VAR_MATCH_START = 0x08, /* Match at start of word */
243 VAR_MATCH_END = 0x10, /* Match at end of word */ 243 VAR_MATCH_END = 0x10, /* Match at end of word */
244 VAR_NOSUBST = 0x20 /* don't expand vars in VarGetPattern */ 244 VAR_NOSUBST = 0x20 /* don't expand vars in VarGetPattern */
245} VarPattern_Flags; 245} VarPattern_Flags;
246 246
247typedef enum { 247typedef enum {
248 VAR_NO_EXPORT = 0x01 /* do not export */ 248 VAR_NO_EXPORT = 0x01 /* do not export */
249} VarSet_Flags; 249} VarSet_Flags;
250 250
251typedef struct { 251typedef struct {
252 /* 252 /*
253 * The following fields are set by Var_Parse() when it 253 * The following fields are set by Var_Parse() when it
254 * encounters modifiers that need to keep state for use by 254 * encounters modifiers that need to keep state for use by
255 * subsequent modifiers within the same variable expansion. 255 * subsequent modifiers within the same variable expansion.
256 */ 256 */
257 Byte varSpace; /* Word separator in expansions */ 257 Byte varSpace; /* Word separator in expansions */
258 Boolean oneBigWord; /* TRUE if we will treat the variable as a 258 Boolean oneBigWord; /* TRUE if we will treat the variable as a
259 * single big word, even if it contains 259 * single big word, even if it contains
260 * embedded spaces (as opposed to the 260 * embedded spaces (as opposed to the
261 * usual behaviour of treating it as 261 * usual behaviour of treating it as
262 * several space-separated words). */ 262 * several space-separated words). */
263} Var_Parse_State; 263} Var_Parse_State;
264 264
265/* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/", 265/* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/",
266 * to VarSYSVMatch() for ":lhs=rhs". */ 266 * to VarSYSVMatch() for ":lhs=rhs". */
267typedef struct { 267typedef struct {
268 const char *lhs; /* String to match */ 268 const char *lhs; /* String to match */
269 int leftLen; /* Length of string */ 269 int leftLen; /* Length of string */
270 const char *rhs; /* Replacement string (w/ &'s removed) */ 270 const char *rhs; /* Replacement string (w/ &'s removed) */
271 int rightLen; /* Length of replacement */ 271 int rightLen; /* Length of replacement */
272 VarPattern_Flags flags; 272 VarPattern_Flags flags;
273} VarPattern; 273} VarPattern;
274 274
275/* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */ 275/* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */
276typedef struct { 276typedef struct {
277 GNode *ctxt; /* variable context */ 277 GNode *ctxt; /* variable context */
278 char *tvar; /* name of temp var */ 278 char *tvar; /* name of temp var */
279 int tvarLen; 279 int tvarLen;
280 char *str; /* string to expand */ 280 char *str; /* string to expand */
281 int strLen; 281 int strLen;
282 Varf_Flags flags; 282 Varf_Flags flags;
283} VarLoop_t; 283} VarLoop_t;
284 284
285#ifndef NO_REGEX 285#ifndef NO_REGEX
286/* struct passed as 'void *' to VarRESubstitute() for ":C///" */ 286/* struct passed as 'void *' to VarRESubstitute() for ":C///" */
287typedef struct { 287typedef struct {
288 regex_t re; 288 regex_t re;
289 int nsub; 289 int nsub;
290 regmatch_t *matches; 290 regmatch_t *matches;
291 char *replace; 291 char *replace;
292 int flags; 292 int flags;
293} VarREPattern; 293} VarREPattern;
294#endif 294#endif
295 295
296/* struct passed to VarSelectWords() for ":[start..end]" */ 296/* struct passed to VarSelectWords() for ":[start..end]" */
297typedef struct { 297typedef struct {
298 int start; /* first word to select */ 298 int start; /* first word to select */
299 int end; /* last word to select */ 299 int end; /* last word to select */
300} VarSelectWords_t; 300} VarSelectWords_t;
301 301
302static Var *VarFind(const char *, GNode *, int); 
303static void VarAdd(const char *, const char *, GNode *); 
304static Boolean VarHead(GNode *, Var_Parse_State *, 
305 char *, Boolean, Buffer *, void *); 
306static Boolean VarTail(GNode *, Var_Parse_State *, 
307 char *, Boolean, Buffer *, void *); 
308static Boolean VarSuffix(GNode *, Var_Parse_State *, 
309 char *, Boolean, Buffer *, void *); 
310static Boolean VarRoot(GNode *, Var_Parse_State *, 
311 char *, Boolean, Buffer *, void *); 
312static Boolean VarMatch(GNode *, Var_Parse_State *, 
313 char *, Boolean, Buffer *, void *); 
314#ifdef SYSVVARSUB 
315static Boolean VarSYSVMatch(GNode *, Var_Parse_State *, 
316 char *, Boolean, Buffer *, void *); 
317#endif 
318static Boolean VarNoMatch(GNode *, Var_Parse_State *, 
319 char *, Boolean, Buffer *, void *); 
320#ifndef NO_REGEX 
321static void VarREError(int, regex_t *, const char *); 
322static Boolean VarRESubstitute(GNode *, Var_Parse_State *, 
323 char *, Boolean, Buffer *, void *); 
324#endif 
325static Boolean VarSubstitute(GNode *, Var_Parse_State *, 
326 char *, Boolean, Buffer *, void *); 
327static Boolean VarLoopExpand(GNode *, Var_Parse_State *, 
328 char *, Boolean, Buffer *, void *); 
329static char *VarGetPattern(GNode *, Var_Parse_State *, 302static char *VarGetPattern(GNode *, Var_Parse_State *,
330 VarPattern_Flags, const char **, int, 303 VarPattern_Flags, const char **, int,
331 VarPattern_Flags *, int *, VarPattern *); 304 VarPattern_Flags *, int *, VarPattern *);
332static char *VarQuote(char *, Boolean); 305static char *VarQuote(char *, Boolean);
333static char *VarHash(char *); 306static char *VarHash(char *);
334static char *VarModify(GNode *, Var_Parse_State *, 307static char *VarModify(GNode *, Var_Parse_State *,
335 const char *, 308 const char *,
336 Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer *, void *), 309 Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer *, void *),
337 void *); 310 void *);
338static char *VarOrder(const char *, const char); 311static char *VarOrder(const char *, const char);
339static char *VarUniq(const char *); 312static char *VarUniq(const char *);
340static int VarWordCompare(const void *, const void *); 313static int VarWordCompare(const void *, const void *);
341 314
342#define BROPEN '{' 315#define BROPEN '{'
343#define BRCLOSE '}' 316#define BRCLOSE '}'
344#define PROPEN '(' 317#define PROPEN '('
345#define PRCLOSE ')' 318#define PRCLOSE ')'
346 319
347/*- 320/*-
348 *----------------------------------------------------------------------- 321 *-----------------------------------------------------------------------
349 * VarFind -- 322 * VarFind --
350 * Find the given variable in the given context and any other contexts 323 * Find the given variable in the given context and any other contexts
351 * indicated. 324 * indicated.
352 * 325 *
353 * Input: 326 * Input:
354 * name name to find 327 * name name to find
355 * ctxt context in which to find it 328 * ctxt context in which to find it
356 * flags FIND_GLOBAL set means to look in the 329 * flags FIND_GLOBAL set means to look in the
357 * VAR_GLOBAL context as well. FIND_CMD set means 330 * VAR_GLOBAL context as well. FIND_CMD set means
358 * to look in the VAR_CMD context also. FIND_ENV 331 * to look in the VAR_CMD context also. FIND_ENV
359 * set means to look in the environment 332 * set means to look in the environment
360 * 333 *
361 * Results: 334 * Results:
362 * A pointer to the structure describing the desired variable or 335 * A pointer to the structure describing the desired variable or
363 * NULL if the variable does not exist. 336 * NULL if the variable does not exist.
364 * 337 *
365 * Side Effects: 338 * Side Effects:
366 * None 339 * None
367 *----------------------------------------------------------------------- 340 *-----------------------------------------------------------------------
368 */ 341 */
369static Var * 342static Var *
370VarFind(const char *name, GNode *ctxt, int flags) 343VarFind(const char *name, GNode *ctxt, int flags)
371{ 344{
372 Hash_Entry *var; 345 Hash_Entry *var;
373 Var *v; 346 Var *v;
374 347
375 /* 348 /*
376 * If the variable name begins with a '.', it could very well be one of 349 * If the variable name begins with a '.', it could very well be one of
377 * the local ones. We check the name against all the local variables 350 * the local ones. We check the name against all the local variables
378 * and substitute the short version in for 'name' if it matches one of 351 * and substitute the short version in for 'name' if it matches one of
379 * them. 352 * them.
380 */ 353 */
381 if (*name == '.' && isupper((unsigned char) name[1])) { 354 if (*name == '.' && isupper((unsigned char) name[1])) {
382 switch (name[1]) { 355 switch (name[1]) {
383 case 'A': 356 case 'A':
384 if (!strcmp(name, ".ALLSRC")) 357 if (!strcmp(name, ".ALLSRC"))
385 name = ALLSRC; 358 name = ALLSRC;
386 if (!strcmp(name, ".ARCHIVE")) 359 if (!strcmp(name, ".ARCHIVE"))
387 name = ARCHIVE; 360 name = ARCHIVE;
388 break; 361 break;
389 case 'I': 362 case 'I':
390 if (!strcmp(name, ".IMPSRC")) 363 if (!strcmp(name, ".IMPSRC"))
391 name = IMPSRC; 364 name = IMPSRC;
392 break; 365 break;
393 case 'M': 366 case 'M':
394 if (!strcmp(name, ".MEMBER")) 367 if (!strcmp(name, ".MEMBER"))
395 name = MEMBER; 368 name = MEMBER;
396 break; 369 break;
397 case 'O': 370 case 'O':
398 if (!strcmp(name, ".OODATE")) 371 if (!strcmp(name, ".OODATE"))
399 name = OODATE; 372 name = OODATE;
400 break; 373 break;
401 case 'P': 374 case 'P':
402 if (!strcmp(name, ".PREFIX")) 375 if (!strcmp(name, ".PREFIX"))
403 name = PREFIX; 376 name = PREFIX;
404 break; 377 break;
405 case 'T': 378 case 'T':
406 if (!strcmp(name, ".TARGET")) 379 if (!strcmp(name, ".TARGET"))
407 name = TARGET; 380 name = TARGET;
408 break; 381 break;
409 } 382 }
410 } 383 }
411 384
412#ifdef notyet 385#ifdef notyet
413 /* for compatibility with gmake */ 386 /* for compatibility with gmake */
414 if (name[0] == '^' && name[1] == '\0') 387 if (name[0] == '^' && name[1] == '\0')
415 name = ALLSRC; 388 name = ALLSRC;
416#endif 389#endif
417 390
418 /* 391 /*
419 * First look for the variable in the given context. If it's not there, 392 * First look for the variable in the given context. If it's not there,
420 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, 393 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
421 * depending on the FIND_* flags in 'flags' 394 * depending on the FIND_* flags in 'flags'
422 */ 395 */
423 var = Hash_FindEntry(&ctxt->context, name); 396 var = Hash_FindEntry(&ctxt->context, name);
424 397
425 if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) { 398 if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) {
426 var = Hash_FindEntry(&VAR_CMD->context, name); 399 var = Hash_FindEntry(&VAR_CMD->context, name);
427 } 400 }
428 if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) && 401 if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) &&
429 ctxt != VAR_GLOBAL) 402 ctxt != VAR_GLOBAL)
430 { 403 {
431 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 404 var = Hash_FindEntry(&VAR_GLOBAL->context, name);
432 if (var == NULL && ctxt != VAR_INTERNAL) { 405 if (var == NULL && ctxt != VAR_INTERNAL) {
433 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */ 406 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
434 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 407 var = Hash_FindEntry(&VAR_INTERNAL->context, name);
435 } 408 }
436 } 409 }
437 if (var == NULL && (flags & FIND_ENV)) { 410 if (var == NULL && (flags & FIND_ENV)) {
438 char *env; 411 char *env;
439 412
440 if ((env = getenv(name)) != NULL) { 413 if ((env = getenv(name)) != NULL) {
441 int len; 414 int len;
442 415
443 v = bmake_malloc(sizeof(Var)); 416 v = bmake_malloc(sizeof(Var));
444 v->name = bmake_strdup(name); 417 v->name = bmake_strdup(name);
445 418
446 len = strlen(env); 419 len = strlen(env);
447 420
448 Buf_Init(&v->val, len + 1); 421 Buf_Init(&v->val, len + 1);
449 Buf_AddBytes(&v->val, len, env); 422 Buf_AddBytes(&v->val, len, env);
450 423
451 v->flags = VAR_FROM_ENV; 424 v->flags = VAR_FROM_ENV;
452 return v; 425 return v;
453 } else if (checkEnvFirst && (flags & FIND_GLOBAL) && 426 } else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
454 ctxt != VAR_GLOBAL) 427 ctxt != VAR_GLOBAL)
455 { 428 {
456 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 429 var = Hash_FindEntry(&VAR_GLOBAL->context, name);
457 if (var == NULL && ctxt != VAR_INTERNAL) { 430 if (var == NULL && ctxt != VAR_INTERNAL) {
458 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 431 var = Hash_FindEntry(&VAR_INTERNAL->context, name);
459 } 432 }
460 if (var == NULL) { 433 if (var == NULL) {
461 return NULL; 434 return NULL;
462 } else { 435 } else {
463 return (Var *)Hash_GetValue(var); 436 return (Var *)Hash_GetValue(var);
464 } 437 }
465 } else { 438 } else {
466 return NULL; 439 return NULL;
467 } 440 }
468 } else if (var == NULL) { 441 } else if (var == NULL) {
469 return NULL; 442 return NULL;
470 } else { 443 } else {
471 return (Var *)Hash_GetValue(var); 444 return (Var *)Hash_GetValue(var);
472 } 445 }
473} 446}
474 447
475/*- 448/*-
476 *----------------------------------------------------------------------- 449 *-----------------------------------------------------------------------
477 * VarFreeEnv -- 450 * VarFreeEnv --
478 * If the variable is an environment variable, free it 451 * If the variable is an environment variable, free it
479 * 452 *
480 * Input: 453 * Input:
481 * v the variable 454 * v the variable
482 * destroy true if the value buffer should be destroyed. 455 * destroy true if the value buffer should be destroyed.
483 * 456 *
484 * Results: 457 * Results:
485 * 1 if it is an environment variable 0 ow. 458 * 1 if it is an environment variable 0 ow.
486 * 459 *
487 * Side Effects: 460 * Side Effects:
488 * The variable is free'ed if it is an environent variable. 461 * The variable is free'ed if it is an environent variable.
489 *----------------------------------------------------------------------- 462 *-----------------------------------------------------------------------
490 */ 463 */
491static Boolean 464static Boolean
492VarFreeEnv(Var *v, Boolean destroy) 465VarFreeEnv(Var *v, Boolean destroy)
493{ 466{
494 if ((v->flags & VAR_FROM_ENV) == 0) 467 if ((v->flags & VAR_FROM_ENV) == 0)
495 return FALSE; 468 return FALSE;
496 free(v->name); 469 free(v->name);
497 Buf_Destroy(&v->val, destroy); 470 Buf_Destroy(&v->val, destroy);
498 free(v); 471 free(v);
499 return TRUE; 472 return TRUE;
500} 473}
501 474
502/*- 475/*-
503 *----------------------------------------------------------------------- 476 *-----------------------------------------------------------------------
504 * VarAdd -- 477 * VarAdd --
505 * Add a new variable of name name and value val to the given context 478 * Add a new variable of name name and value val to the given context
506 * 479 *
507 * Input: 480 * Input:
508 * name name of variable to add 481 * name name of variable to add
509 * val value to set it to 482 * val value to set it to
510 * ctxt context in which to set it 483 * ctxt context in which to set it
511 * 484 *
512 * Results: 485 * Results:
513 * None 486 * None
514 * 487 *
515 * Side Effects: 488 * Side Effects:
516 * The new variable is placed at the front of the given context 489 * The new variable is placed at the front of the given context
517 * The name and val arguments are duplicated so they may 490 * The name and val arguments are duplicated so they may
518 * safely be freed. 491 * safely be freed.
519 *----------------------------------------------------------------------- 492 *-----------------------------------------------------------------------
520 */ 493 */
521static void 494static void
522VarAdd(const char *name, const char *val, GNode *ctxt) 495VarAdd(const char *name, const char *val, GNode *ctxt)
523{ 496{
524 Var *v; 497 Var *v;
525 int len; 498 int len;
526 Hash_Entry *h; 499 Hash_Entry *h;
527 500
528 v = bmake_malloc(sizeof(Var)); 501 v = bmake_malloc(sizeof(Var));
529 502
530 len = val ? strlen(val) : 0; 503 len = val ? strlen(val) : 0;
531 Buf_Init(&v->val, len + 1); 504 Buf_Init(&v->val, len + 1);
532 Buf_AddBytes(&v->val, len, val); 505 Buf_AddBytes(&v->val, len, val);
533 506
534 v->flags = 0; 507 v->flags = 0;
535 508
536 h = Hash_CreateEntry(&ctxt->context, name, NULL); 509 h = Hash_CreateEntry(&ctxt->context, name, NULL);
537 Hash_SetValue(h, v); 510 Hash_SetValue(h, v);
538 v->name = h->name; 511 v->name = h->name;
539 if (DEBUG(VAR) && (ctxt->flags & INTERNAL) == 0) { 512 if (DEBUG(VAR) && (ctxt->flags & INTERNAL) == 0) {
540 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val); 513 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
541 } 514 }
542} 515}
543 516
544/*- 517/*-
545 *----------------------------------------------------------------------- 518 *-----------------------------------------------------------------------
546 * Var_Delete -- 519 * Var_Delete --
547 * Remove a variable from a context. 520 * Remove a variable from a context.
548 * 521 *
549 * Results: 522 * Results:
550 * None. 523 * None.
551 * 524 *
552 * Side Effects: 525 * Side Effects:
553 * The Var structure is removed and freed. 526 * The Var structure is removed and freed.
554 * 527 *
555 *----------------------------------------------------------------------- 528 *-----------------------------------------------------------------------
556 */ 529 */
557void 530void
558Var_Delete(const char *name, GNode *ctxt) 531Var_Delete(const char *name, GNode *ctxt)
559{ 532{
560 Hash_Entry *ln; 533 Hash_Entry *ln;
561 char *cp; 534 char *cp;
562 535
563 if (strchr(name, '$')) { 536 if (strchr(name, '$')) {
564 cp = Var_Subst(NULL, name, VAR_GLOBAL, VARF_WANTRES); 537 cp = Var_Subst(NULL, name, VAR_GLOBAL, VARF_WANTRES);
565 } else { 538 } else {
566 cp = (char *)name; 539 cp = (char *)name;
567 } 540 }
568 ln = Hash_FindEntry(&ctxt->context, cp); 541 ln = Hash_FindEntry(&ctxt->context, cp);
569 if (DEBUG(VAR)) { 542 if (DEBUG(VAR)) {
570 fprintf(debug_file, "%s:delete %s%s\n", 543 fprintf(debug_file, "%s:delete %s%s\n",
571 ctxt->name, cp, ln ? "" : " (not found)"); 544 ctxt->name, cp, ln ? "" : " (not found)");
572 } 545 }
573 if (cp != name) { 546 if (cp != name) {
574 free(cp); 547 free(cp);
575 } 548 }
576 if (ln != NULL) { 549 if (ln != NULL) {
577 Var *v; 550 Var *v;
578 551
579 v = (Var *)Hash_GetValue(ln); 552 v = (Var *)Hash_GetValue(ln);
580 if ((v->flags & VAR_EXPORTED)) { 553 if ((v->flags & VAR_EXPORTED)) {
581 unsetenv(v->name); 554 unsetenv(v->name);
582 } 555 }
583 if (strcmp(MAKE_EXPORTED, v->name) == 0) { 556 if (strcmp(MAKE_EXPORTED, v->name) == 0) {
584 var_exportedVars = VAR_EXPORTED_NONE; 557 var_exportedVars = VAR_EXPORTED_NONE;
585 } 558 }
586 if (v->name != ln->name) 559 if (v->name != ln->name)
587 free(v->name); 560 free(v->name);
588 Hash_DeleteEntry(&ctxt->context, ln); 561 Hash_DeleteEntry(&ctxt->context, ln);
589 Buf_Destroy(&v->val, TRUE); 562 Buf_Destroy(&v->val, TRUE);
590 free(v); 563 free(v);
591 } 564 }
592} 565}
593 566
594 567
595/* 568/*
596 * Export a var. 569 * Export a var.
597 * We ignore make internal variables (those which start with '.') 570 * We ignore make internal variables (those which start with '.')
598 * Also we jump through some hoops to avoid calling setenv 571 * Also we jump through some hoops to avoid calling setenv
599 * more than necessary since it can leak. 572 * more than necessary since it can leak.
600 * We only manipulate flags of vars if 'parent' is set. 573 * We only manipulate flags of vars if 'parent' is set.
601 */ 574 */
602static int 575static int
603Var_Export1(const char *name, int flags) 576Var_Export1(const char *name, int flags)
604{ 577{
605 char tmp[BUFSIZ]; 578 char tmp[BUFSIZ];
606 Var *v; 579 Var *v;
607 char *val = NULL; 580 char *val = NULL;
608 int n; 581 int n;
609 int parent = (flags & VAR_EXPORT_PARENT); 582 int parent = (flags & VAR_EXPORT_PARENT);
610 583
611 if (*name == '.') 584 if (*name == '.')
612 return 0; /* skip internals */ 585 return 0; /* skip internals */
613 if (!name[1]) { 586 if (!name[1]) {
614 /* 587 /*
615 * A single char. 588 * A single char.
616 * If it is one of the vars that should only appear in 589 * If it is one of the vars that should only appear in
617 * local context, skip it, else we can get Var_Subst 590 * local context, skip it, else we can get Var_Subst
618 * into a loop. 591 * into a loop.
619 */ 592 */
620 switch (name[0]) { 593 switch (name[0]) {
621 case '@': 594 case '@':
622 case '%': 595 case '%':
623 case '*': 596 case '*':
624 case '!': 597 case '!':
625 return 0; 598 return 0;
626 } 599 }
627 } 600 }
628 v = VarFind(name, VAR_GLOBAL, 0); 601 v = VarFind(name, VAR_GLOBAL, 0);
629 if (v == NULL) { 602 if (v == NULL) {
630 return 0; 603 return 0;
631 } 604 }
632 if (!parent && 605 if (!parent &&
633 (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) { 606 (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
634 return 0; /* nothing to do */ 607 return 0; /* nothing to do */
635 } 608 }
636 val = Buf_GetAll(&v->val, NULL); 609 val = Buf_GetAll(&v->val, NULL);
637 if ((flags & VAR_EXPORT_LITERAL) == 0 && strchr(val, '$')) { 610 if ((flags & VAR_EXPORT_LITERAL) == 0 && strchr(val, '$')) {
638 if (parent) { 611 if (parent) {
639 /* 612 /*
640 * Flag this as something we need to re-export. 613 * Flag this as something we need to re-export.
641 * No point actually exporting it now though, 614 * No point actually exporting it now though,
642 * the child can do it at the last minute. 615 * the child can do it at the last minute.
643 */ 616 */
644 v->flags |= (VAR_EXPORTED|VAR_REEXPORT); 617 v->flags |= (VAR_EXPORTED|VAR_REEXPORT);
645 return 1; 618 return 1;
646 } 619 }
647 if (v->flags & VAR_IN_USE) { 620 if (v->flags & VAR_IN_USE) {
648 /* 621 /*
649 * We recursed while exporting in a child. 622 * We recursed while exporting in a child.
650 * This isn't going to end well, just skip it. 623 * This isn't going to end well, just skip it.
651 */ 624 */
652 return 0; 625 return 0;
653 } 626 }
654 n = snprintf(tmp, sizeof(tmp), "${%s}", name); 627 n = snprintf(tmp, sizeof(tmp), "${%s}", name);
655 if (n < (int)sizeof(tmp)) { 628 if (n < (int)sizeof(tmp)) {
656 val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES); 629 val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
657 setenv(name, val, 1); 630 setenv(name, val, 1);
658 free(val); 631 free(val);
659 } 632 }
660 } else { 633 } else {
661 if (parent) { 634 if (parent) {
662 v->flags &= ~VAR_REEXPORT; /* once will do */ 635 v->flags &= ~VAR_REEXPORT; /* once will do */
663 } 636 }
664 if (parent || !(v->flags & VAR_EXPORTED)) { 637 if (parent || !(v->flags & VAR_EXPORTED)) {
665 setenv(name, val, 1); 638 setenv(name, val, 1);
666 } 639 }
667 } 640 }
668 /* 641 /*
669 * This is so Var_Set knows to call Var_Export again... 642 * This is so Var_Set knows to call Var_Export again...
670 */ 643 */
671 if (parent) { 644 if (parent) {
672 v->flags |= VAR_EXPORTED; 645 v->flags |= VAR_EXPORTED;
673 } 646 }
674 return 1; 647 return 1;
675} 648}
676 649
677static void 650static void
678Var_ExportVars_callback(void *entry, void *unused MAKE_ATTR_UNUSED) 651Var_ExportVars_callback(void *entry, void *unused MAKE_ATTR_UNUSED)
679{ 652{
680 Var *var = entry; 653 Var *var = entry;
681 Var_Export1(var->name, 0); 654 Var_Export1(var->name, 0);
682} 655}
683 656
684/* 657/*
685 * This gets called from our children. 658 * This gets called from our children.
686 */ 659 */
687void 660void
688Var_ExportVars(void) 661Var_ExportVars(void)
689{ 662{
690 char tmp[BUFSIZ]; 663 char tmp[BUFSIZ];
691 char *val; 664 char *val;
692 int n; 665 int n;
693 666
694 /* 667 /*
695 * Several make's support this sort of mechanism for tracking 668 * Several make's support this sort of mechanism for tracking
696 * recursion - but each uses a different name. 669 * recursion - but each uses a different name.
697 * We allow the makefiles to update MAKELEVEL and ensure 670 * We allow the makefiles to update MAKELEVEL and ensure
698 * children see a correctly incremented value. 671 * children see a correctly incremented value.
699 */ 672 */
700 snprintf(tmp, sizeof(tmp), "%d", makelevel + 1); 673 snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
701 setenv(MAKE_LEVEL_ENV, tmp, 1); 674 setenv(MAKE_LEVEL_ENV, tmp, 1);
702 675
703 if (VAR_EXPORTED_NONE == var_exportedVars) 676 if (VAR_EXPORTED_NONE == var_exportedVars)
704 return; 677 return;
705 678
706 if (VAR_EXPORTED_ALL == var_exportedVars) { 679 if (VAR_EXPORTED_ALL == var_exportedVars) {
707 /* Ouch! This is crazy... */ 680 /* Ouch! This is crazy... */
708 Hash_ForEach(&VAR_GLOBAL->context, Var_ExportVars_callback, NULL); 681 Hash_ForEach(&VAR_GLOBAL->context, Var_ExportVars_callback, NULL);
709 return; 682 return;
710 } 683 }
711 /* 684 /*
712 * We have a number of exported vars, 685 * We have a number of exported vars,
713 */ 686 */
714 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}"); 687 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
715 if (n < (int)sizeof(tmp)) { 688 if (n < (int)sizeof(tmp)) {
716 char **av; 689 char **av;
717 char *as; 690 char *as;
718 int ac; 691 int ac;
719 int i; 692 int i;
720 693
721 val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES); 694 val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
722 if (*val) { 695 if (*val) {
723 av = brk_string(val, &ac, FALSE, &as); 696 av = brk_string(val, &ac, FALSE, &as);
724 for (i = 0; i < ac; i++) { 697 for (i = 0; i < ac; i++) {
725 Var_Export1(av[i], 0); 698 Var_Export1(av[i], 0);
726 } 699 }
727 free(as); 700 free(as);
728 free(av); 701 free(av);
729 } 702 }
730 free(val); 703 free(val);
731 } 704 }
732} 705}
733 706
734/* 707/*
735 * This is called when .export is seen or 708 * This is called when .export is seen or
736 * .MAKE.EXPORTED is modified. 709 * .MAKE.EXPORTED is modified.
737 * It is also called when any exported var is modified. 710 * It is also called when any exported var is modified.
738 */ 711 */
739void 712void
740Var_Export(char *str, int isExport) 713Var_Export(char *str, int isExport)
741{ 714{
742 char *name; 715 char *name;
743 char *val; 716 char *val;
744 char **av; 717 char **av;
745 char *as; 718 char *as;
746 int flags; 719 int flags;
747 int ac; 720 int ac;
748 int i; 721 int i;
749 722
750 if (isExport && (!str || !str[0])) { 723 if (isExport && (!str || !str[0])) {
751 var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */ 724 var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
752 return; 725 return;
753 } 726 }
754 727
755 flags = 0; 728 flags = 0;
756 if (strncmp(str, "-env", 4) == 0) { 729 if (strncmp(str, "-env", 4) == 0) {
757 str += 4; 730 str += 4;
758 } else if (strncmp(str, "-literal", 8) == 0) { 731 } else if (strncmp(str, "-literal", 8) == 0) {
759 str += 8; 732 str += 8;
760 flags |= VAR_EXPORT_LITERAL; 733 flags |= VAR_EXPORT_LITERAL;
761 } else { 734 } else {
762 flags |= VAR_EXPORT_PARENT; 735 flags |= VAR_EXPORT_PARENT;
763 } 736 }
764 val = Var_Subst(NULL, str, VAR_GLOBAL, VARF_WANTRES); 737 val = Var_Subst(NULL, str, VAR_GLOBAL, VARF_WANTRES);
765 if (*val) { 738 if (*val) {
766 av = brk_string(val, &ac, FALSE, &as); 739 av = brk_string(val, &ac, FALSE, &as);
767 for (i = 0; i < ac; i++) { 740 for (i = 0; i < ac; i++) {
768 name = av[i]; 741 name = av[i];
769 if (!name[1]) { 742 if (!name[1]) {
770 /* 743 /*
771 * A single char. 744 * A single char.
772 * If it is one of the vars that should only appear in 745 * If it is one of the vars that should only appear in
773 * local context, skip it, else we can get Var_Subst 746 * local context, skip it, else we can get Var_Subst
774 * into a loop. 747 * into a loop.
775 */ 748 */
776 switch (name[0]) { 749 switch (name[0]) {
777 case '@': 750 case '@':
778 case '%': 751 case '%':
779 case '*': 752 case '*':
780 case '!': 753 case '!':
781 continue; 754 continue;
782 } 755 }
783 } 756 }
784 if (Var_Export1(name, flags)) { 757 if (Var_Export1(name, flags)) {
785 if (VAR_EXPORTED_ALL != var_exportedVars) 758 if (VAR_EXPORTED_ALL != var_exportedVars)
786 var_exportedVars = VAR_EXPORTED_YES; 759 var_exportedVars = VAR_EXPORTED_YES;
787 if (isExport && (flags & VAR_EXPORT_PARENT)) { 760 if (isExport && (flags & VAR_EXPORT_PARENT)) {
788 Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL); 761 Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
789 } 762 }
790 } 763 }
791 } 764 }
792 free(as); 765 free(as);
793 free(av); 766 free(av);
794 } 767 }
795 free(val); 768 free(val);
796} 769}
797 770
798 771
799/* 772/*
800 * This is called when .unexport[-env] is seen. 773 * This is called when .unexport[-env] is seen.
801 */ 774 */
802extern char **environ; 775extern char **environ;
803 776
804void 777void
805Var_UnExport(char *str) 778Var_UnExport(char *str)
806{ 779{
807 char tmp[BUFSIZ]; 780 char tmp[BUFSIZ];
808 char *vlist; 781 char *vlist;
809 char *cp; 782 char *cp;
810 Boolean unexport_env; 783 Boolean unexport_env;
811 int n; 784 int n;
812 785
813 if (!str || !str[0]) { 786 if (!str || !str[0]) {
814 return; /* assert? */ 787 return; /* assert? */
815 } 788 }
816 789
817 vlist = NULL; 790 vlist = NULL;
818 791
819 str += 8; 792 str += 8;
820 unexport_env = (strncmp(str, "-env", 4) == 0); 793 unexport_env = (strncmp(str, "-env", 4) == 0);
821 if (unexport_env) { 794 if (unexport_env) {
822 char **newenv; 795 char **newenv;
823 796
824 cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */ 797 cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */
825 if (environ == savedEnv) { 798 if (environ == savedEnv) {
826 /* we have been here before! */ 799 /* we have been here before! */
827 newenv = bmake_realloc(environ, 2 * sizeof(char *)); 800 newenv = bmake_realloc(environ, 2 * sizeof(char *));
828 } else { 801 } else {
829 if (savedEnv) { 802 if (savedEnv) {
830 free(savedEnv); 803 free(savedEnv);
831 savedEnv = NULL; 804 savedEnv = NULL;
832 } 805 }
833 newenv = bmake_malloc(2 * sizeof(char *)); 806 newenv = bmake_malloc(2 * sizeof(char *));
834 } 807 }
835 if (!newenv) 808 if (!newenv)
836 return; 809 return;
837 /* Note: we cannot safely free() the original environ. */ 810 /* Note: we cannot safely free() the original environ. */
838 environ = savedEnv = newenv; 811 environ = savedEnv = newenv;
839 newenv[0] = NULL; 812 newenv[0] = NULL;
840 newenv[1] = NULL; 813 newenv[1] = NULL;
841 if (cp && *cp) 814 if (cp && *cp)
842 setenv(MAKE_LEVEL_ENV, cp, 1); 815 setenv(MAKE_LEVEL_ENV, cp, 1);
843 } else { 816 } else {
844 for (; *str != '\n' && isspace((unsigned char) *str); str++) 817 for (; *str != '\n' && isspace((unsigned char) *str); str++)
845 continue; 818 continue;
846 if (str[0] && str[0] != '\n') { 819 if (str[0] && str[0] != '\n') {
847 vlist = str; 820 vlist = str;
848 } 821 }
849 } 822 }
850 823
851 if (!vlist) { 824 if (!vlist) {
852 /* Using .MAKE.EXPORTED */ 825 /* Using .MAKE.EXPORTED */
853 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}"); 826 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
854 if (n < (int)sizeof(tmp)) { 827 if (n < (int)sizeof(tmp)) {
855 vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES); 828 vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
856 } 829 }
857 } 830 }
858 if (vlist) { 831 if (vlist) {
859 Var *v; 832 Var *v;
860 char **av; 833 char **av;
861 char *as; 834 char *as;
862 int ac; 835 int ac;
863 int i; 836 int i;
864 837
865 av = brk_string(vlist, &ac, FALSE, &as); 838 av = brk_string(vlist, &ac, FALSE, &as);
866 for (i = 0; i < ac; i++) { 839 for (i = 0; i < ac; i++) {
867 v = VarFind(av[i], VAR_GLOBAL, 0); 840 v = VarFind(av[i], VAR_GLOBAL, 0);
868 if (!v) 841 if (!v)
869 continue; 842 continue;
870 if (!unexport_env && 843 if (!unexport_env &&
871 (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) { 844 (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
872 unsetenv(v->name); 845 unsetenv(v->name);
873 } 846 }
874 v->flags &= ~(VAR_EXPORTED|VAR_REEXPORT); 847 v->flags &= ~(VAR_EXPORTED|VAR_REEXPORT);
875 /* 848 /*
876 * If we are unexporting a list, 849 * If we are unexporting a list,
877 * remove each one from .MAKE.EXPORTED. 850 * remove each one from .MAKE.EXPORTED.
878 * If we are removing them all, 851 * If we are removing them all,
879 * just delete .MAKE.EXPORTED below. 852 * just delete .MAKE.EXPORTED below.
880 */ 853 */
881 if (vlist == str) { 854 if (vlist == str) {
882 n = snprintf(tmp, sizeof(tmp), 855 n = snprintf(tmp, sizeof(tmp),
883 "${" MAKE_EXPORTED ":N%s}", v->name); 856 "${" MAKE_EXPORTED ":N%s}", v->name);
884 if (n < (int)sizeof(tmp)) { 857 if (n < (int)sizeof(tmp)) {
885 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES); 858 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
886 Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL); 859 Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL);
887 free(cp); 860 free(cp);
888 } 861 }
889 } 862 }
890 } 863 }
891 free(as); 864 free(as);
892 free(av); 865 free(av);
893 if (vlist != str) { 866 if (vlist != str) {
894 Var_Delete(MAKE_EXPORTED, VAR_GLOBAL); 867 Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
895 free(vlist); 868 free(vlist);
896 } 869 }
897 } 870 }
898} 871}
899 872
900static void 873static void
901Var_Set_with_flags(const char *name, const char *val, GNode *ctxt, 874Var_Set_with_flags(const char *name, const char *val, GNode *ctxt,
902 VarSet_Flags flags) 875 VarSet_Flags flags)
903{ 876{
904 Var *v; 877 Var *v;
905 char *expanded_name = NULL; 878 char *expanded_name = NULL;
906 879
907 /* 880 /*
908 * We only look for a variable in the given context since anything set 881 * We only look for a variable in the given context since anything set
909 * here will override anything in a lower context, so there's not much 882 * here will override anything in a lower context, so there's not much
910 * point in searching them all just to save a bit of memory... 883 * point in searching them all just to save a bit of memory...
911 */ 884 */
912 if (strchr(name, '$') != NULL) { 885 if (strchr(name, '$') != NULL) {
913 expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES); 886 expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
914 if (expanded_name[0] == 0) { 887 if (expanded_name[0] == 0) {
915 if (DEBUG(VAR)) { 888 if (DEBUG(VAR)) {
916 fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) " 889 fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
917 "name expands to empty string - ignored\n", 890 "name expands to empty string - ignored\n",
918 name, val); 891 name, val);
919 } 892 }
920 free(expanded_name); 893 free(expanded_name);
921 return; 894 return;
922 } 895 }
923 name = expanded_name; 896 name = expanded_name;
924 } 897 }
925 if (ctxt == VAR_GLOBAL) { 898 if (ctxt == VAR_GLOBAL) {
926 v = VarFind(name, VAR_CMD, 0); 899 v = VarFind(name, VAR_CMD, 0);
927 if (v != NULL) { 900 if (v != NULL) {
928 if ((v->flags & VAR_FROM_CMD)) { 901 if ((v->flags & VAR_FROM_CMD)) {
929 if (DEBUG(VAR)) { 902 if (DEBUG(VAR)) {
930 fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val); 903 fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val);
931 } 904 }
932 goto out; 905 goto out;
933 } 906 }
934 VarFreeEnv(v, TRUE); 907 VarFreeEnv(v, TRUE);
935 } 908 }
936 } 909 }
937 v = VarFind(name, ctxt, 0); 910 v = VarFind(name, ctxt, 0);
938 if (v == NULL) { 911 if (v == NULL) {
939 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) { 912 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
940 /* 913 /*
941 * This var would normally prevent the same name being added 914 * This var would normally prevent the same name being added
942 * to VAR_GLOBAL, so delete it from there if needed. 915 * to VAR_GLOBAL, so delete it from there if needed.
943 * Otherwise -V name may show the wrong value. 916 * Otherwise -V name may show the wrong value.
944 */ 917 */
945 Var_Delete(name, VAR_GLOBAL); 918 Var_Delete(name, VAR_GLOBAL);
946 } 919 }
947 VarAdd(name, val, ctxt); 920 VarAdd(name, val, ctxt);
948 } else { 921 } else {
949 Buf_Empty(&v->val); 922 Buf_Empty(&v->val);
950 if (val) 923 if (val)
951 Buf_AddBytes(&v->val, strlen(val), val); 924 Buf_AddBytes(&v->val, strlen(val), val);
952 925
953 if (DEBUG(VAR)) { 926 if (DEBUG(VAR)) {
954 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val); 927 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
955 } 928 }
956 if ((v->flags & VAR_EXPORTED)) { 929 if ((v->flags & VAR_EXPORTED)) {
957 Var_Export1(name, VAR_EXPORT_PARENT); 930 Var_Export1(name, VAR_EXPORT_PARENT);
958 } 931 }
959 } 932 }
960 /* 933 /*
961 * Any variables given on the command line are automatically exported 934 * Any variables given on the command line are automatically exported
962 * to the environment (as per POSIX standard) 935 * to the environment (as per POSIX standard)
963 */ 936 */
964 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) { 937 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
965 if (v == NULL) { 938 if (v == NULL) {
966 /* we just added it */ 939 /* we just added it */
967 v = VarFind(name, ctxt, 0); 940 v = VarFind(name, ctxt, 0);
968 } 941 }
969 if (v != NULL) 942 if (v != NULL)
970 v->flags |= VAR_FROM_CMD; 943 v->flags |= VAR_FROM_CMD;
971 /* 944 /*
972 * If requested, don't export these in the environment 945 * If requested, don't export these in the environment
973 * individually. We still put them in MAKEOVERRIDES so 946 * individually. We still put them in MAKEOVERRIDES so
974 * that the command-line settings continue to override 947 * that the command-line settings continue to override
975 * Makefile settings. 948 * Makefile settings.
976 */ 949 */
977 if (varNoExportEnv != TRUE) 950 if (varNoExportEnv != TRUE)
978 setenv(name, val ? val : "", 1); 951 setenv(name, val ? val : "", 1);
979 952
980 Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL); 953 Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
981 } 954 }
982 if (*name == '.') { 955 if (*name == '.') {
983 if (strcmp(name, SAVE_DOLLARS) == 0) 956 if (strcmp(name, SAVE_DOLLARS) == 0)
984 save_dollars = s2Boolean(val, save_dollars); 957 save_dollars = s2Boolean(val, save_dollars);
985 } 958 }
986 959
987out: 960out:
988 free(expanded_name); 961 free(expanded_name);
989 if (v != NULL) 962 if (v != NULL)
990 VarFreeEnv(v, TRUE); 963 VarFreeEnv(v, TRUE);
991} 964}
992 965
993/*- 966/*-
994 *----------------------------------------------------------------------- 967 *-----------------------------------------------------------------------
995 * Var_Set -- 968 * Var_Set --
996 * Set the variable name to the value val in the given context. 969 * Set the variable name to the value val in the given context.
997 * 970 *
998 * Input: 971 * Input:
999 * name name of variable to set 972 * name name of variable to set
1000 * val value to give to the variable 973 * val value to give to the variable
1001 * ctxt context in which to set it 974 * ctxt context in which to set it
1002 * 975 *
1003 * Results: 976 * Results:
1004 * None. 977 * None.
1005 * 978 *
1006 * Side Effects: 979 * Side Effects:
1007 * If the variable doesn't yet exist, a new record is created for it. 980 * If the variable doesn't yet exist, a new record is created for it.
1008 * Else the old value is freed and the new one stuck in its place 981 * Else the old value is freed and the new one stuck in its place
1009 * 982 *
1010 * Notes: 983 * Notes:
1011 * The variable is searched for only in its context before being 984 * The variable is searched for only in its context before being
1012 * created in that context. I.e. if the context is VAR_GLOBAL, 985 * created in that context. I.e. if the context is VAR_GLOBAL,
1013 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only 986 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
1014 * VAR_CMD->context is searched. This is done to avoid the literally 987 * VAR_CMD->context is searched. This is done to avoid the literally
1015 * thousands of unnecessary strcmp's that used to be done to 988 * thousands of unnecessary strcmp's that used to be done to
1016 * set, say, $(@) or $(<). 989 * set, say, $(@) or $(<).
1017 * If the context is VAR_GLOBAL though, we check if the variable 990 * If the context is VAR_GLOBAL though, we check if the variable
1018 * was set in VAR_CMD from the command line and skip it if so. 991 * was set in VAR_CMD from the command line and skip it if so.
1019 *----------------------------------------------------------------------- 992 *-----------------------------------------------------------------------
1020 */ 993 */
1021void 994void
1022Var_Set(const char *name, const char *val, GNode *ctxt) 995Var_Set(const char *name, const char *val, GNode *ctxt)
1023{ 996{
1024 Var_Set_with_flags(name, val, ctxt, 0); 997 Var_Set_with_flags(name, val, ctxt, 0);
1025} 998}
1026 999
1027/*- 1000/*-
1028 *----------------------------------------------------------------------- 1001 *-----------------------------------------------------------------------
1029 * Var_Append -- 1002 * Var_Append --
1030 * The variable of the given name has the given value appended to it in 1003 * The variable of the given name has the given value appended to it in
1031 * the given context. 1004 * the given context.
1032 * 1005 *
1033 * Input: 1006 * Input:
1034 * name name of variable to modify 1007 * name name of variable to modify
1035 * val String to append to it 1008 * val String to append to it
1036 * ctxt Context in which this should occur 1009 * ctxt Context in which this should occur
1037 * 1010 *
1038 * Results: 1011 * Results:
1039 * None 1012 * None
1040 * 1013 *
1041 * Side Effects: 1014 * Side Effects:
1042 * If the variable doesn't exist, it is created. Else the strings 1015 * If the variable doesn't exist, it is created. Else the strings
1043 * are concatenated (with a space in between). 1016 * are concatenated (with a space in between).
1044 * 1017 *
1045 * Notes: 1018 * Notes:
1046 * Only if the variable is being sought in the global context is the 1019 * Only if the variable is being sought in the global context is the
1047 * environment searched. 1020 * environment searched.
1048 * XXX: Knows its calling circumstances in that if called with ctxt 1021 * XXX: Knows its calling circumstances in that if called with ctxt
1049 * an actual target, it will only search that context since only 1022 * an actual target, it will only search that context since only
1050 * a local variable could be being appended to. This is actually 1023 * a local variable could be being appended to. This is actually
1051 * a big win and must be tolerated. 1024 * a big win and must be tolerated.
1052 *----------------------------------------------------------------------- 1025 *-----------------------------------------------------------------------
1053 */ 1026 */
1054void 1027void
1055Var_Append(const char *name, const char *val, GNode *ctxt) 1028Var_Append(const char *name, const char *val, GNode *ctxt)
1056{ 1029{
1057 Var *v; 1030 Var *v;
1058 Hash_Entry *h; 1031 Hash_Entry *h;
1059 char *expanded_name = NULL; 1032 char *expanded_name = NULL;
1060 1033
1061 if (strchr(name, '$') != NULL) { 1034 if (strchr(name, '$') != NULL) {
1062 expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES); 1035 expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
1063 if (expanded_name[0] == 0) { 1036 if (expanded_name[0] == 0) {
1064 if (DEBUG(VAR)) { 1037 if (DEBUG(VAR)) {
1065 fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) " 1038 fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
1066 "name expands to empty string - ignored\n", 1039 "name expands to empty string - ignored\n",
1067 name, val); 1040 name, val);
1068 } 1041 }
1069 free(expanded_name); 1042 free(expanded_name);
1070 return; 1043 return;
1071 } 1044 }
1072 name = expanded_name; 1045 name = expanded_name;
1073 } 1046 }
1074 1047
1075 v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD|FIND_ENV) : 0); 1048 v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD|FIND_ENV) : 0);
1076 1049
1077 if (v == NULL) { 1050 if (v == NULL) {
1078 Var_Set(name, val, ctxt); 1051 Var_Set(name, val, ctxt);
1079 } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) { 1052 } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) {
1080 Buf_AddByte(&v->val, ' '); 1053 Buf_AddByte(&v->val, ' ');
1081 Buf_AddBytes(&v->val, strlen(val), val); 1054 Buf_AddBytes(&v->val, strlen(val), val);
1082 1055
1083 if (DEBUG(VAR)) { 1056 if (DEBUG(VAR)) {
1084 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, 1057 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name,
1085 Buf_GetAll(&v->val, NULL)); 1058 Buf_GetAll(&v->val, NULL));
1086 } 1059 }
1087 1060
1088 if (v->flags & VAR_FROM_ENV) { 1061 if (v->flags & VAR_FROM_ENV) {
1089 /* 1062 /*
1090 * If the original variable came from the environment, we 1063 * If the original variable came from the environment, we
1091 * have to install it in the global context (we could place 1064 * have to install it in the global context (we could place
1092 * it in the environment, but then we should provide a way to 1065 * it in the environment, but then we should provide a way to
1093 * export other variables...) 1066 * export other variables...)
1094 */ 1067 */
1095 v->flags &= ~VAR_FROM_ENV; 1068 v->flags &= ~VAR_FROM_ENV;
1096 h = Hash_CreateEntry(&ctxt->context, name, NULL); 1069 h = Hash_CreateEntry(&ctxt->context, name, NULL);
1097 Hash_SetValue(h, v); 1070 Hash_SetValue(h, v);
1098 } 1071 }
1099 } 1072 }
1100 free(expanded_name); 1073 free(expanded_name);
1101} 1074}
1102 1075
1103/*- 1076/*-
1104 *----------------------------------------------------------------------- 1077 *-----------------------------------------------------------------------
1105 * Var_Exists -- 1078 * Var_Exists --
1106 * See if the given variable exists. 1079 * See if the given variable exists.
1107 * 1080 *
1108 * Input: 1081 * Input:
1109 * name Variable to find 1082 * name Variable to find
1110 * ctxt Context in which to start search 1083 * ctxt Context in which to start search
1111 * 1084 *
1112 * Results: 1085 * Results:
1113 * TRUE if it does, FALSE if it doesn't 1086 * TRUE if it does, FALSE if it doesn't
1114 * 1087 *
1115 * Side Effects: 1088 * Side Effects:
1116 * None. 1089 * None.
1117 * 1090 *
1118 *----------------------------------------------------------------------- 1091 *-----------------------------------------------------------------------
1119 */ 1092 */
1120Boolean 1093Boolean
1121Var_Exists(const char *name, GNode *ctxt) 1094Var_Exists(const char *name, GNode *ctxt)
1122{ 1095{
1123 Var *v; 1096 Var *v;
1124 char *cp; 1097 char *cp;
1125 1098
1126 if ((cp = strchr(name, '$')) != NULL) { 1099 if ((cp = strchr(name, '$')) != NULL) {
1127 cp = Var_Subst(NULL, name, ctxt, VARF_WANTRES); 1100 cp = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
1128 } 1101 }
1129 v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV); 1102 v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
1130 free(cp); 1103 free(cp);
1131 if (v == NULL) { 1104 if (v == NULL) {
1132 return FALSE; 1105 return FALSE;
1133 } 1106 }
1134 1107
1135 (void)VarFreeEnv(v, TRUE); 1108 (void)VarFreeEnv(v, TRUE);
1136 return TRUE; 1109 return TRUE;
1137} 1110}
1138 1111
1139/*- 1112/*-
1140 *----------------------------------------------------------------------- 1113 *-----------------------------------------------------------------------
1141 * Var_Value -- 1114 * Var_Value --
1142 * Return the value of the named variable in the given context 1115 * Return the value of the named variable in the given context
1143 * 1116 *
1144 * Input: 1117 * Input:
1145 * name name to find 1118 * name name to find
1146 * ctxt context in which to search for it 1119 * ctxt context in which to search for it
1147 * 1120 *
1148 * Results: 1121 * Results:
1149 * The value if the variable exists, NULL if it doesn't 1122 * The value if the variable exists, NULL if it doesn't
1150 * 1123 *
1151 * Side Effects: 1124 * Side Effects:
1152 * None 1125 * None
1153 *----------------------------------------------------------------------- 1126 *-----------------------------------------------------------------------
1154 */ 1127 */
1155char * 1128char *
1156Var_Value(const char *name, GNode *ctxt, char **frp) 1129Var_Value(const char *name, GNode *ctxt, char **frp)
1157{ 1130{
1158 Var *v; 1131 Var *v;
1159 1132
1160 v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 1133 v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1161 *frp = NULL; 1134 *frp = NULL;
1162 if (v == NULL) 1135 if (v == NULL)
1163 return NULL; 1136 return NULL;
1164 1137
1165 char *p = (Buf_GetAll(&v->val, NULL)); 1138 char *p = (Buf_GetAll(&v->val, NULL));
1166 if (VarFreeEnv(v, FALSE)) 1139 if (VarFreeEnv(v, FALSE))
1167 *frp = p; 1140 *frp = p;
1168 return p; 1141 return p;
1169} 1142}
1170 1143
1171 1144
1172/* This callback for VarModify gets a single word from an expression and 1145/* This callback for VarModify gets a single word from an expression and
1173 * typically adds a modification of this word to the buffer. It may also do 1146 * typically adds a modification of this word to the buffer. It may also do
1174 * nothing or add several words. 1147 * nothing or add several words.
1175 * 1148 *
1176 * If addSpaces is TRUE, it must add a space before adding anything else to 1149 * If addSpaces is TRUE, it must add a space before adding anything else to
1177 * the buffer. 1150 * the buffer.
1178 * 1151 *
1179 * It returns the addSpace value for the next call of this callback. Typical 1152 * It returns the addSpace value for the next call of this callback. Typical
1180 * return values are the current addSpaces or TRUE. */ 1153 * return values are the current addSpaces or TRUE. */
1181typedef Boolean (*VarModifyCallback)(GNode *ctxt, Var_Parse_State *vpstate, 1154typedef Boolean (*VarModifyCallback)(GNode *ctxt, Var_Parse_State *vpstate,
1182 char *word, Boolean addSpace, Buffer *buf, void *data); 1155 char *word, Boolean addSpace, Buffer *buf, void *data);
1183 1156
1184 1157
1185/* Callback function for VarModify to implement the :H modifier. 1158/* Callback function for VarModify to implement the :H modifier.
1186 * Add the dirname of the given word to the buffer. */ 1159 * Add the dirname of the given word to the buffer. */
1187static Boolean 1160static Boolean
1188VarHead(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1161VarHead(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1189 char *word, Boolean addSpace, Buffer *buf, 1162 char *word, Boolean addSpace, Buffer *buf,
1190 void *dummy MAKE_ATTR_UNUSED) 1163 void *dummy MAKE_ATTR_UNUSED)
1191{ 1164{
1192 const char *slash = strrchr(word, '/'); 1165 const char *slash = strrchr(word, '/');
1193 1166
1194 if (addSpace && vpstate->varSpace) 1167 if (addSpace && vpstate->varSpace)
1195 Buf_AddByte(buf, vpstate->varSpace); 1168 Buf_AddByte(buf, vpstate->varSpace);
1196 if (slash != NULL) 1169 if (slash != NULL)
1197 Buf_AddBytes(buf, slash - word, word); 1170 Buf_AddBytes(buf, slash - word, word);
1198 else 1171 else
1199 Buf_AddByte(buf, '.'); 1172 Buf_AddByte(buf, '.');
1200 1173
1201 return TRUE; 1174 return TRUE;
1202} 1175}
1203 1176
1204/* Callback function for VarModify to implement the :T modifier. 1177/* Callback function for VarModify to implement the :T modifier.
1205 * Add the basename of the given word to the buffer. */ 1178 * Add the basename of the given word to the buffer. */
1206static Boolean 1179static Boolean
1207VarTail(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1180VarTail(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1208 char *word, Boolean addSpace, Buffer *buf, 1181 char *word, Boolean addSpace, Buffer *buf,
1209 void *dummy MAKE_ATTR_UNUSED) 1182 void *dummy MAKE_ATTR_UNUSED)
1210{ 1183{
1211 const char *slash = strrchr(word, '/'); 1184 const char *slash = strrchr(word, '/');
1212 const char *base = slash != NULL ? slash + 1 : word; 1185 const char *base = slash != NULL ? slash + 1 : word;
1213 1186
1214 if (addSpace && vpstate->varSpace) 1187 if (addSpace && vpstate->varSpace)
1215 Buf_AddByte(buf, vpstate->varSpace); 1188 Buf_AddByte(buf, vpstate->varSpace);
1216 Buf_AddBytes(buf, strlen(base), base); 1189 Buf_AddBytes(buf, strlen(base), base);
1217 return TRUE; 1190 return TRUE;
1218} 1191}
1219 1192
1220/* Callback function for VarModify to implement the :E modifier. 1193/* Callback function for VarModify to implement the :E modifier.
1221 * Add the filename suffix of the given word to the buffer, if it exists. */ 1194 * Add the filename suffix of the given word to the buffer, if it exists. */
1222static Boolean 1195static Boolean
1223VarSuffix(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1196VarSuffix(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1224 char *word, Boolean addSpace, Buffer *buf, 1197 char *word, Boolean addSpace, Buffer *buf,
1225 void *dummy MAKE_ATTR_UNUSED) 1198 void *dummy MAKE_ATTR_UNUSED)
1226{ 1199{
1227 const char *dot = strrchr(word, '.'); 1200 const char *dot = strrchr(word, '.');
1228 if (dot == NULL) 1201 if (dot == NULL)
1229 return addSpace; 1202 return addSpace;
1230 1203
1231 if (addSpace && vpstate->varSpace) 1204 if (addSpace && vpstate->varSpace)
1232 Buf_AddByte(buf, vpstate->varSpace); 1205 Buf_AddByte(buf, vpstate->varSpace);
1233 Buf_AddBytes(buf, strlen(dot + 1), dot + 1); 1206 Buf_AddBytes(buf, strlen(dot + 1), dot + 1);
1234 return TRUE; 1207 return TRUE;
1235} 1208}
1236 1209
1237/* Callback function for VarModify to implement the :R modifier. 1210/* Callback function for VarModify to implement the :R modifier.
1238 * Add the filename basename of the given word to the buffer. */ 1211 * Add the filename basename of the given word to the buffer. */
1239static Boolean 1212static Boolean
1240VarRoot(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1213VarRoot(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1241 char *word, Boolean addSpace, Buffer *buf, 1214 char *word, Boolean addSpace, Buffer *buf,
1242 void *dummy MAKE_ATTR_UNUSED) 1215 void *dummy MAKE_ATTR_UNUSED)
1243{ 1216{
1244 char *dot = strrchr(word, '.'); 1217 char *dot = strrchr(word, '.');
1245 size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word); 1218 size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1246 1219
1247 if (addSpace && vpstate->varSpace) 1220 if (addSpace && vpstate->varSpace)
1248 Buf_AddByte(buf, vpstate->varSpace); 1221 Buf_AddByte(buf, vpstate->varSpace);
1249 Buf_AddBytes(buf, len, word); 1222 Buf_AddBytes(buf, len, word);
1250 return TRUE; 1223 return TRUE;
1251} 1224}
1252 1225
1253/* Callback function for VarModify to implement the :M modifier. 1226/* Callback function for VarModify to implement the :M modifier.
1254 * Place the word in the buffer if it matches the given pattern. */ 1227 * Place the word in the buffer if it matches the given pattern. */
1255static Boolean 1228static Boolean
1256VarMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1229VarMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1257 char *word, Boolean addSpace, Buffer *buf, 1230 char *word, Boolean addSpace, Buffer *buf,
1258 void *data) 1231 void *data)
1259{ 1232{
1260 const char *pattern = data; 1233 const char *pattern = data;
1261 if (DEBUG(VAR)) 1234 if (DEBUG(VAR))
1262 fprintf(debug_file, "VarMatch [%s] [%s]\n", word, pattern); 1235 fprintf(debug_file, "VarMatch [%s] [%s]\n", word, pattern);
1263 if (!Str_Match(word, pattern)) 1236 if (!Str_Match(word, pattern))
1264 return addSpace; 1237 return addSpace;
1265 if (addSpace && vpstate->varSpace) 1238 if (addSpace && vpstate->varSpace)
1266 Buf_AddByte(buf, vpstate->varSpace); 1239 Buf_AddByte(buf, vpstate->varSpace);
1267 Buf_AddBytes(buf, strlen(word), word); 1240 Buf_AddBytes(buf, strlen(word), word);
1268 return TRUE; 1241 return TRUE;
1269} 1242}
1270 1243
1271#ifdef SYSVVARSUB 1244#ifdef SYSVVARSUB
1272/* Callback function for VarModify to implement the :%.from=%.to modifier. */ 1245/* Callback function for VarModify to implement the :%.from=%.to modifier. */
1273static Boolean 1246static Boolean
1274VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate, 1247VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
1275 char *word, Boolean addSpace, Buffer *buf, 1248 char *word, Boolean addSpace, Buffer *buf,
1276 void *data) 1249 void *data)
1277{ 1250{
1278 size_t len; 1251 size_t len;
1279 char *ptr; 1252 char *ptr;
1280 Boolean hasPercent; 1253 Boolean hasPercent;
1281 VarPattern *pat = data; 1254 VarPattern *pat = data;
1282 1255
1283 if (addSpace && vpstate->varSpace) 1256 if (addSpace && vpstate->varSpace)
1284 Buf_AddByte(buf, vpstate->varSpace); 1257 Buf_AddByte(buf, vpstate->varSpace);
1285 1258
1286 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len, &hasPercent)) != NULL) { 1259 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len, &hasPercent)) != NULL) {
1287 char *varexp = Var_Subst(NULL, pat->rhs, ctx, VARF_WANTRES); 1260 char *varexp = Var_Subst(NULL, pat->rhs, ctx, VARF_WANTRES);
1288 Str_SYSVSubst(buf, varexp, ptr, len, hasPercent); 1261 Str_SYSVSubst(buf, varexp, ptr, len, hasPercent);
1289 free(varexp); 1262 free(varexp);
1290 } else { 1263 } else {
1291 Buf_AddBytes(buf, strlen(word), word); 1264 Buf_AddBytes(buf, strlen(word), word);
1292 } 1265 }
1293 1266
1294 return TRUE; 1267 return TRUE;
1295} 1268}
1296#endif 1269#endif
1297 1270
1298/* Callback function for VarModify to implement the :N modifier. 1271/* Callback function for VarModify to implement the :N modifier.
1299 * Place the word in the buffer if it doesn't match the given pattern. */ 1272 * Place the word in the buffer if it doesn't match the given pattern. */
1300static Boolean 1273static Boolean
1301VarNoMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1274VarNoMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1302 char *word, Boolean addSpace, Buffer *buf, 1275 char *word, Boolean addSpace, Buffer *buf,
1303 void *data) 1276 void *data)
1304{ 1277{
1305 const char *pattern = data; 1278 const char *pattern = data;
1306 if (Str_Match(word, pattern)) 1279 if (Str_Match(word, pattern))
1307 return addSpace; 1280 return addSpace;
1308 if (addSpace && vpstate->varSpace) 1281 if (addSpace && vpstate->varSpace)
1309 Buf_AddByte(buf, vpstate->varSpace); 1282 Buf_AddByte(buf, vpstate->varSpace);
1310 Buf_AddBytes(buf, strlen(word), word); 1283 Buf_AddBytes(buf, strlen(word), word);
1311 return TRUE; 1284 return TRUE;
1312} 1285}
1313 1286
1314/* Callback function for VarModify to implement the :S,from,to, modifier. 1287/* Callback function for VarModify to implement the :S,from,to, modifier.
1315 * Perform a string substitution on the given word. */ 1288 * Perform a string substitution on the given word. */
1316static Boolean 1289static Boolean
1317VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate, 1290VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
1318 char *word, Boolean addSpace, Buffer *buf, 1291 char *word, Boolean addSpace, Buffer *buf,
1319 void *data) 1292 void *data)
1320{ 1293{
1321 int wordLen = strlen(word); 1294 int wordLen = strlen(word);
1322 char *cp; /* General pointer */ 1295 char *cp; /* General pointer */
1323 VarPattern *pattern = data; 1296 VarPattern *pattern = data;
1324 1297
1325 if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) != 1298 if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) !=
1326 (VAR_SUB_ONE|VAR_SUB_MATCHED)) { 1299 (VAR_SUB_ONE|VAR_SUB_MATCHED)) {
1327 /* 1300 /*