Sat Jul 4 10:35:30 2020 UTC ()
make(1): remove unnecessary forward declarations, fix indentation


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

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

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