Sun Mar 14 15:43:31 2021 UTC ()
make: separate parsing from evaluating for several modifiers

This aligns the implementation of these modifiers with the requirements
in the long comment starting with 'The ApplyModifier functions'.

No functional change.


(rillig)
diff -r1.863 -r1.864 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2021/03/14 15:24:37 1.863
+++ src/usr.bin/make/var.c 2021/03/14 15:43:31 1.864
@@ -1,1142 +1,1142 @@ @@ -1,1142 +1,1142 @@
1/* $NetBSD: var.c,v 1.863 2021/03/14 15:24:37 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.864 2021/03/14 15:43:31 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/* 71/*
72 * Handling of variables and the expressions formed from them. 72 * Handling of variables and the expressions formed from them.
73 * 73 *
74 * Variables are set using lines of the form VAR=value. Both the variable 74 * Variables are set using lines of the form VAR=value. Both the variable
75 * name and the value can contain references to other variables, by using 75 * name and the value can contain references to other variables, by using
76 * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}. 76 * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
77 * 77 *
78 * Interface: 78 * Interface:
79 * Var_Init Initialize this module. 79 * Var_Init Initialize this module.
80 * 80 *
81 * Var_End Clean up the module. 81 * Var_End Clean up the module.
82 * 82 *
83 * Var_Set 83 * Var_Set
84 * Var_SetExpand 84 * Var_SetExpand
85 * Set the value of the variable, creating it if 85 * Set the value of the variable, creating it if
86 * necessary. 86 * necessary.
87 * 87 *
88 * Var_Append 88 * Var_Append
89 * Var_AppendExpand 89 * Var_AppendExpand
90 * Append more characters to the variable, creating it if 90 * Append more characters to the variable, creating it if
91 * necessary. A space is placed between the old value and 91 * necessary. A space is placed between the old value and
92 * the new one. 92 * the new one.
93 * 93 *
94 * Var_Exists 94 * Var_Exists
95 * Var_ExistsExpand 95 * Var_ExistsExpand
96 * See if a variable exists. 96 * See if a variable exists.
97 * 97 *
98 * Var_Value Return the unexpanded value of a variable, or NULL if 98 * Var_Value Return the unexpanded value of a variable, or NULL if
99 * the variable is undefined. 99 * the variable is undefined.
100 * 100 *
101 * Var_Subst Substitute all variable expressions in a string. 101 * Var_Subst Substitute all variable expressions in a string.
102 * 102 *
103 * Var_Parse Parse a variable expression such as ${VAR:Mpattern}. 103 * Var_Parse Parse a variable expression such as ${VAR:Mpattern}.
104 * 104 *
105 * Var_Delete 105 * Var_Delete
106 * Var_DeleteExpand 106 * Var_DeleteExpand
107 * Delete a variable. 107 * Delete a variable.
108 * 108 *
109 * Var_ReexportVars 109 * Var_ReexportVars
110 * Export some or even all variables to the environment 110 * Export some or even all variables to the environment
111 * of this process and its child processes. 111 * of this process and its child processes.
112 * 112 *
113 * Var_Export Export the variable to the environment of this process 113 * Var_Export Export the variable to the environment of this process
114 * and its child processes. 114 * and its child processes.
115 * 115 *
116 * Var_UnExport Don't export the variable anymore. 116 * Var_UnExport Don't export the variable anymore.
117 * 117 *
118 * Debugging: 118 * Debugging:
119 * Var_Stats Print out hashing statistics if in -dh mode. 119 * Var_Stats Print out hashing statistics if in -dh mode.
120 * 120 *
121 * Var_Dump Print out all variables defined in the given scope. 121 * Var_Dump Print out all variables defined in the given scope.
122 * 122 *
123 * XXX: There's a lot of almost duplicate code in these functions that only 123 * XXX: There's a lot of almost duplicate code in these functions that only
124 * differs in subtle details that are not mentioned in the manual page. 124 * differs in subtle details that are not mentioned in the manual page.
125 */ 125 */
126 126
127#include <sys/stat.h> 127#include <sys/stat.h>
128#ifndef NO_REGEX 128#ifndef NO_REGEX
129#include <sys/types.h> 129#include <sys/types.h>
130#include <regex.h> 130#include <regex.h>
131#endif 131#endif
132#include <errno.h> 132#include <errno.h>
133#include <inttypes.h> 133#include <inttypes.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 "dir.h" 138#include "dir.h"
139#include "job.h" 139#include "job.h"
140#include "metachar.h" 140#include "metachar.h"
141 141
142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
143MAKE_RCSID("$NetBSD: var.c,v 1.863 2021/03/14 15:24:37 rillig Exp $"); 143MAKE_RCSID("$NetBSD: var.c,v 1.864 2021/03/14 15:43:31 rillig Exp $");
144 144
145typedef enum VarFlags { 145typedef enum VarFlags {
146 VFL_NONE = 0, 146 VFL_NONE = 0,
147 147
148 /* 148 /*
149 * The variable's value is currently being used by Var_Parse or 149 * The variable's value is currently being used by Var_Parse or
150 * Var_Subst. This marker is used to avoid endless recursion. 150 * Var_Subst. This marker is used to avoid endless recursion.
151 */ 151 */
152 VFL_IN_USE = 1 << 0, 152 VFL_IN_USE = 1 << 0,
153 153
154 /* 154 /*
155 * The variable comes from the environment. 155 * The variable comes from the environment.
156 * These variables are not registered in any GNode, therefore they 156 * These variables are not registered in any GNode, therefore they
157 * must be freed as soon as they are not used anymore. 157 * must be freed as soon as they are not used anymore.
158 */ 158 */
159 VFL_FROM_ENV = 1 << 1, 159 VFL_FROM_ENV = 1 << 1,
160 160
161 /* 161 /*
162 * The variable is exported to the environment, to be used by child 162 * The variable is exported to the environment, to be used by child
163 * processes. 163 * processes.
164 */ 164 */
165 VFL_EXPORTED = 1 << 2, 165 VFL_EXPORTED = 1 << 2,
166 166
167 /* 167 /*
168 * At the point where this variable was exported, it contained an 168 * At the point where this variable was exported, it contained an
169 * unresolved reference to another variable. Before any child 169 * unresolved reference to another variable. Before any child
170 * process is started, it needs to be exported again, in the hope 170 * process is started, it needs to be exported again, in the hope
171 * that the referenced variable can then be resolved. 171 * that the referenced variable can then be resolved.
172 */ 172 */
173 VFL_REEXPORT = 1 << 3, 173 VFL_REEXPORT = 1 << 3,
174 174
175 /* The variable came from the command line. */ 175 /* The variable came from the command line. */
176 VFL_FROM_CMD = 1 << 4, 176 VFL_FROM_CMD = 1 << 4,
177 177
178 /* 178 /*
179 * The variable value cannot be changed anymore, and the variable 179 * The variable value cannot be changed anymore, and the variable
180 * cannot be deleted. Any attempts to do so are silently ignored, 180 * cannot be deleted. Any attempts to do so are silently ignored,
181 * they are logged with -dv though. 181 * they are logged with -dv though.
182 * 182 *
183 * See VAR_SET_READONLY. 183 * See VAR_SET_READONLY.
184 */ 184 */
185 VFL_READONLY = 1 << 5 185 VFL_READONLY = 1 << 5
186} VarFlags; 186} VarFlags;
187 187
188/* 188/*
189 * Variables are defined using one of the VAR=value assignments. Their 189 * Variables are defined using one of the VAR=value assignments. Their
190 * value can be queried by expressions such as $V, ${VAR}, or with modifiers 190 * value can be queried by expressions such as $V, ${VAR}, or with modifiers
191 * such as ${VAR:S,from,to,g:Q}. 191 * such as ${VAR:S,from,to,g:Q}.
192 * 192 *
193 * There are 3 kinds of variables: scope variables, environment variables, 193 * There are 3 kinds of variables: scope variables, environment variables,
194 * undefined variables. 194 * undefined variables.
195 * 195 *
196 * Scope variables are stored in a GNode.scope. The only way to undefine 196 * Scope variables are stored in a GNode.scope. The only way to undefine
197 * a scope variable is using the .undef directive. In particular, it must 197 * a scope variable is using the .undef directive. In particular, it must
198 * not be possible to undefine a variable during the evaluation of an 198 * not be possible to undefine a variable during the evaluation of an
199 * expression, or Var.name might point nowhere. 199 * expression, or Var.name might point nowhere.
200 * 200 *
201 * Environment variables are temporary. They are returned by VarFind, and 201 * Environment variables are temporary. They are returned by VarFind, and
202 * after using them, they must be freed using VarFreeEnv. 202 * after using them, they must be freed using VarFreeEnv.
203 * 203 *
204 * Undefined variables occur during evaluation of variable expressions such 204 * Undefined variables occur during evaluation of variable expressions such
205 * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers. 205 * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
206 */ 206 */
207typedef struct Var { 207typedef struct Var {
208 /* 208 /*
209 * The name of the variable, once set, doesn't change anymore. 209 * The name of the variable, once set, doesn't change anymore.
210 * For scope variables, it aliases the corresponding HashEntry name. 210 * For scope variables, it aliases the corresponding HashEntry name.
211 * For environment and undefined variables, it is allocated. 211 * For environment and undefined variables, it is allocated.
212 */ 212 */
213 FStr name; 213 FStr name;
214 214
215 /* The unexpanded value of the variable. */ 215 /* The unexpanded value of the variable. */
216 Buffer val; 216 Buffer val;
217 /* Miscellaneous status flags. */ 217 /* Miscellaneous status flags. */
218 VarFlags flags; 218 VarFlags flags;
219} Var; 219} Var;
220 220
221/* 221/*
222 * Exporting variables is expensive and may leak memory, so skip it if we 222 * Exporting variables is expensive and may leak memory, so skip it if we
223 * can. 223 * can.
224 * 224 *
225 * To avoid this, it might be worth encapsulating the environment variables 225 * To avoid this, it might be worth encapsulating the environment variables
226 * in a separate data structure called EnvVars. 226 * in a separate data structure called EnvVars.
227 */ 227 */
228typedef enum VarExportedMode { 228typedef enum VarExportedMode {
229 VAR_EXPORTED_NONE, 229 VAR_EXPORTED_NONE,
230 VAR_EXPORTED_SOME, 230 VAR_EXPORTED_SOME,
231 VAR_EXPORTED_ALL 231 VAR_EXPORTED_ALL
232} VarExportedMode; 232} VarExportedMode;
233 233
234typedef enum UnexportWhat { 234typedef enum UnexportWhat {
235 /* Unexport the variables given by name. */ 235 /* Unexport the variables given by name. */
236 UNEXPORT_NAMED, 236 UNEXPORT_NAMED,
237 /* 237 /*
238 * Unexport all globals previously exported, but keep the environment 238 * Unexport all globals previously exported, but keep the environment
239 * inherited from the parent. 239 * inherited from the parent.
240 */ 240 */
241 UNEXPORT_ALL, 241 UNEXPORT_ALL,
242 /* 242 /*
243 * Unexport all globals previously exported and clear the environment 243 * Unexport all globals previously exported and clear the environment
244 * inherited from the parent. 244 * inherited from the parent.
245 */ 245 */
246 UNEXPORT_ENV 246 UNEXPORT_ENV
247} UnexportWhat; 247} UnexportWhat;
248 248
249/* Flags for pattern matching in the :S and :C modifiers */ 249/* Flags for pattern matching in the :S and :C modifiers */
250typedef struct VarPatternFlags { 250typedef struct VarPatternFlags {
251 251
252 /* Replace as often as possible ('g') */ 252 /* Replace as often as possible ('g') */
253 Boolean subGlobal: 1; 253 Boolean subGlobal: 1;
254 /* Replace only once ('1') */ 254 /* Replace only once ('1') */
255 Boolean subOnce: 1; 255 Boolean subOnce: 1;
256 /* Match at start of word ('^') */ 256 /* Match at start of word ('^') */
257 Boolean anchorStart: 1; 257 Boolean anchorStart: 1;
258 /* Match at end of word ('$') */ 258 /* Match at end of word ('$') */
259 Boolean anchorEnd: 1; 259 Boolean anchorEnd: 1;
260} VarPatternFlags; 260} VarPatternFlags;
261 261
262/* SepBuf builds a string from words interleaved with separators. */ 262/* SepBuf builds a string from words interleaved with separators. */
263typedef struct SepBuf { 263typedef struct SepBuf {
264 Buffer buf; 264 Buffer buf;
265 Boolean needSep; 265 Boolean needSep;
266 /* Usually ' ', but see the ':ts' modifier. */ 266 /* Usually ' ', but see the ':ts' modifier. */
267 char sep; 267 char sep;
268} SepBuf; 268} SepBuf;
269 269
270 270
271ENUM_FLAGS_RTTI_4(VarEvalFlags, 271ENUM_FLAGS_RTTI_4(VarEvalFlags,
272 VARE_UNDEFERR, VARE_WANTRES, VARE_KEEP_DOLLAR, 272 VARE_UNDEFERR, VARE_WANTRES, VARE_KEEP_DOLLAR,
273 VARE_KEEP_UNDEF); 273 VARE_KEEP_UNDEF);
274 274
275/* 275/*
276 * This lets us tell if we have replaced the original environ 276 * This lets us tell if we have replaced the original environ
277 * (which we cannot free). 277 * (which we cannot free).
278 */ 278 */
279char **savedEnv = NULL; 279char **savedEnv = NULL;
280 280
281/* 281/*
282 * Special return value for Var_Parse, indicating a parse error. It may be 282 * Special return value for Var_Parse, indicating a parse error. It may be
283 * caused by an undefined variable, a syntax error in a modifier or 283 * caused by an undefined variable, a syntax error in a modifier or
284 * something entirely different. 284 * something entirely different.
285 */ 285 */
286char var_Error[] = ""; 286char var_Error[] = "";
287 287
288/* 288/*
289 * Special return value for Var_Parse, indicating an undefined variable in 289 * Special return value for Var_Parse, indicating an undefined variable in
290 * a case where VARE_UNDEFERR is not set. This undefined variable is 290 * a case where VARE_UNDEFERR is not set. This undefined variable is
291 * typically a dynamic variable such as ${.TARGET}, whose expansion needs to 291 * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
292 * be deferred until it is defined in an actual target. 292 * be deferred until it is defined in an actual target.
293 * 293 *
294 * See VARE_KEEP_UNDEF. 294 * See VARE_KEEP_UNDEF.
295 */ 295 */
296static char varUndefined[] = ""; 296static char varUndefined[] = "";
297 297
298/* 298/*
299 * Traditionally this make consumed $$ during := like any other expansion. 299 * Traditionally this make consumed $$ during := like any other expansion.
300 * Other make's do not, and this make follows straight since 2016-01-09. 300 * Other make's do not, and this make follows straight since 2016-01-09.
301 * 301 *
302 * This knob allows controlling the behavior. 302 * This knob allows controlling the behavior.
303 * FALSE to consume $$ during := assignment. 303 * FALSE to consume $$ during := assignment.
304 * TRUE to preserve $$ during := assignment. 304 * TRUE to preserve $$ during := assignment.
305 */ 305 */
306#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" 306#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
307static Boolean save_dollars = TRUE; 307static Boolean save_dollars = TRUE;
308 308
309/* 309/*
310 * A scope collects variable names and their values. 310 * A scope collects variable names and their values.
311 * 311 *
312 * The main scope is SCOPE_GLOBAL, which contains the variables that are set 312 * The main scope is SCOPE_GLOBAL, which contains the variables that are set
313 * in the makefiles. SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and 313 * in the makefiles. SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and
314 * contains some internal make variables. These internal variables can thus 314 * contains some internal make variables. These internal variables can thus
315 * be overridden, they can also be restored by undefining the overriding 315 * be overridden, they can also be restored by undefining the overriding
316 * variable. 316 * variable.
317 * 317 *
318 * SCOPE_CMDLINE contains variables from the command line arguments. These 318 * SCOPE_CMDLINE contains variables from the command line arguments. These
319 * override variables from SCOPE_GLOBAL. 319 * override variables from SCOPE_GLOBAL.
320 * 320 *
321 * There is no scope for environment variables, these are generated on-the-fly 321 * There is no scope for environment variables, these are generated on-the-fly
322 * whenever they are referenced. If there were such a scope, each change to 322 * whenever they are referenced. If there were such a scope, each change to
323 * environment variables would have to be reflected in that scope, which may 323 * environment variables would have to be reflected in that scope, which may
324 * be simpler or more complex than the current implementation. 324 * be simpler or more complex than the current implementation.
325 * 325 *
326 * Each target has its own scope, containing the 7 target-local variables 326 * Each target has its own scope, containing the 7 target-local variables
327 * .TARGET, .ALLSRC, etc. No other variables are in these scopes. 327 * .TARGET, .ALLSRC, etc. No other variables are in these scopes.
328 */ 328 */
329 329
330GNode *SCOPE_CMDLINE; 330GNode *SCOPE_CMDLINE;
331GNode *SCOPE_GLOBAL; 331GNode *SCOPE_GLOBAL;
332GNode *SCOPE_INTERNAL; 332GNode *SCOPE_INTERNAL;
333 333
334ENUM_FLAGS_RTTI_6(VarFlags, 334ENUM_FLAGS_RTTI_6(VarFlags,
335 VFL_IN_USE, VFL_FROM_ENV, 335 VFL_IN_USE, VFL_FROM_ENV,
336 VFL_EXPORTED, VFL_REEXPORT, VFL_FROM_CMD, VFL_READONLY); 336 VFL_EXPORTED, VFL_REEXPORT, VFL_FROM_CMD, VFL_READONLY);
337 337
338static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE; 338static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
339 339
340 340
341static Var * 341static Var *
342VarNew(FStr name, const char *value, VarFlags flags) 342VarNew(FStr name, const char *value, VarFlags flags)
343{ 343{
344 size_t value_len = strlen(value); 344 size_t value_len = strlen(value);
345 Var *var = bmake_malloc(sizeof *var); 345 Var *var = bmake_malloc(sizeof *var);
346 var->name = name; 346 var->name = name;
347 Buf_InitSize(&var->val, value_len + 1); 347 Buf_InitSize(&var->val, value_len + 1);
348 Buf_AddBytes(&var->val, value, value_len); 348 Buf_AddBytes(&var->val, value, value_len);
349 var->flags = flags; 349 var->flags = flags;
350 return var; 350 return var;
351} 351}
352 352
353static const char * 353static const char *
354CanonicalVarname(const char *name) 354CanonicalVarname(const char *name)
355{ 355{
356 if (*name == '.' && ch_isupper(name[1])) { 356 if (*name == '.' && ch_isupper(name[1])) {
357 switch (name[1]) { 357 switch (name[1]) {
358 case 'A': 358 case 'A':
359 if (strcmp(name, ".ALLSRC") == 0) 359 if (strcmp(name, ".ALLSRC") == 0)
360 name = ALLSRC; 360 name = ALLSRC;
361 if (strcmp(name, ".ARCHIVE") == 0) 361 if (strcmp(name, ".ARCHIVE") == 0)
362 name = ARCHIVE; 362 name = ARCHIVE;
363 break; 363 break;
364 case 'I': 364 case 'I':
365 if (strcmp(name, ".IMPSRC") == 0) 365 if (strcmp(name, ".IMPSRC") == 0)
366 name = IMPSRC; 366 name = IMPSRC;
367 break; 367 break;
368 case 'M': 368 case 'M':
369 if (strcmp(name, ".MEMBER") == 0) 369 if (strcmp(name, ".MEMBER") == 0)
370 name = MEMBER; 370 name = MEMBER;
371 break; 371 break;
372 case 'O': 372 case 'O':
373 if (strcmp(name, ".OODATE") == 0) 373 if (strcmp(name, ".OODATE") == 0)
374 name = OODATE; 374 name = OODATE;
375 break; 375 break;
376 case 'P': 376 case 'P':
377 if (strcmp(name, ".PREFIX") == 0) 377 if (strcmp(name, ".PREFIX") == 0)
378 name = PREFIX; 378 name = PREFIX;
379 break; 379 break;
380 case 'S': 380 case 'S':
381 if (strcmp(name, ".SHELL") == 0) { 381 if (strcmp(name, ".SHELL") == 0) {
382 if (shellPath == NULL) 382 if (shellPath == NULL)
383 Shell_Init(); 383 Shell_Init();
384 } 384 }
385 break; 385 break;
386 case 'T': 386 case 'T':
387 if (strcmp(name, ".TARGET") == 0) 387 if (strcmp(name, ".TARGET") == 0)
388 name = TARGET; 388 name = TARGET;
389 break; 389 break;
390 } 390 }
391 } 391 }
392 392
393 /* GNU make has an additional alias $^ == ${.ALLSRC}. */ 393 /* GNU make has an additional alias $^ == ${.ALLSRC}. */
394 394
395 return name; 395 return name;
396} 396}
397 397
398static Var * 398static Var *
399GNode_FindVar(GNode *scope, const char *varname, unsigned int hash) 399GNode_FindVar(GNode *scope, const char *varname, unsigned int hash)
400{ 400{
401 return HashTable_FindValueHash(&scope->vars, varname, hash); 401 return HashTable_FindValueHash(&scope->vars, varname, hash);
402} 402}
403 403
404/* 404/*
405 * Find the variable in the scope, and maybe in other scopes as well. 405 * Find the variable in the scope, and maybe in other scopes as well.
406 * 406 *
407 * Input: 407 * Input:
408 * name name to find, is not expanded any further 408 * name name to find, is not expanded any further
409 * scope scope in which to look first 409 * scope scope in which to look first
410 * elsewhere TRUE to look in other scopes as well 410 * elsewhere TRUE to look in other scopes as well
411 * 411 *
412 * Results: 412 * Results:
413 * The found variable, or NULL if the variable does not exist. 413 * The found variable, or NULL if the variable does not exist.
414 * If the variable is an environment variable, it must be freed using 414 * If the variable is an environment variable, it must be freed using
415 * VarFreeEnv after use. 415 * VarFreeEnv after use.
416 */ 416 */
417static Var * 417static Var *
418VarFind(const char *name, GNode *scope, Boolean elsewhere) 418VarFind(const char *name, GNode *scope, Boolean elsewhere)
419{ 419{
420 Var *var; 420 Var *var;
421 unsigned int nameHash; 421 unsigned int nameHash;
422 422
423 /* Replace '.TARGET' with '@', likewise for other local variables. */ 423 /* Replace '.TARGET' with '@', likewise for other local variables. */
424 name = CanonicalVarname(name); 424 name = CanonicalVarname(name);
425 nameHash = Hash_Hash(name); 425 nameHash = Hash_Hash(name);
426 426
427 var = GNode_FindVar(scope, name, nameHash); 427 var = GNode_FindVar(scope, name, nameHash);
428 if (!elsewhere) 428 if (!elsewhere)
429 return var; 429 return var;
430 430
431 if (var == NULL && scope != SCOPE_CMDLINE) 431 if (var == NULL && scope != SCOPE_CMDLINE)
432 var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash); 432 var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
433 433
434 if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) { 434 if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
435 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash); 435 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
436 if (var == NULL && scope != SCOPE_INTERNAL) { 436 if (var == NULL && scope != SCOPE_INTERNAL) {
437 /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */ 437 /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
438 var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash); 438 var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
439 } 439 }
440 } 440 }
441 441
442 if (var == NULL) { 442 if (var == NULL) {
443 char *env; 443 char *env;
444 444
445 if ((env = getenv(name)) != NULL) { 445 if ((env = getenv(name)) != NULL) {
446 char *varname = bmake_strdup(name); 446 char *varname = bmake_strdup(name);
447 return VarNew(FStr_InitOwn(varname), env, VFL_FROM_ENV); 447 return VarNew(FStr_InitOwn(varname), env, VFL_FROM_ENV);
448 } 448 }
449 449
450 if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) { 450 if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
451 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash); 451 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
452 if (var == NULL && scope != SCOPE_INTERNAL) 452 if (var == NULL && scope != SCOPE_INTERNAL)
453 var = GNode_FindVar(SCOPE_INTERNAL, name, 453 var = GNode_FindVar(SCOPE_INTERNAL, name,
454 nameHash); 454 nameHash);
455 return var; 455 return var;
456 } 456 }
457 457
458 return NULL; 458 return NULL;
459 } 459 }
460 460
461 return var; 461 return var;
462} 462}
463 463
464/* 464/*
465 * If the variable is an environment variable, free it, including its value. 465 * If the variable is an environment variable, free it, including its value.
466 * 466 *
467 * Results: 467 * Results:
468 * TRUE if it was an environment variable, 468 * TRUE if it was an environment variable,
469 * FALSE if it is still a regular variable. 469 * FALSE if it is still a regular variable.
470 */ 470 */
471static void 471static void
472VarFreeEnv(Var *v) 472VarFreeEnv(Var *v)
473{ 473{
474 if (!(v->flags & VFL_FROM_ENV)) 474 if (!(v->flags & VFL_FROM_ENV))
475 return; 475 return;
476 476
477 FStr_Done(&v->name); 477 FStr_Done(&v->name);
478 Buf_Done(&v->val); 478 Buf_Done(&v->val);
479 free(v); 479 free(v);
480} 480}
481 481
482/* Add a new variable of the given name and value to the given scope. */ 482/* Add a new variable of the given name and value to the given scope. */
483static Var * 483static Var *
484VarAdd(const char *name, const char *value, GNode *scope, VarSetFlags flags) 484VarAdd(const char *name, const char *value, GNode *scope, VarSetFlags flags)
485{ 485{
486 HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL); 486 HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
487 Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value, 487 Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value,
488 flags & VAR_SET_READONLY ? VFL_READONLY : VFL_NONE); 488 flags & VAR_SET_READONLY ? VFL_READONLY : VFL_NONE);
489 HashEntry_Set(he, v); 489 HashEntry_Set(he, v);
490 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, value); 490 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, value);
491 return v; 491 return v;
492} 492}
493 493
494/* 494/*
495 * Remove a variable from a scope, freeing all related memory as well. 495 * Remove a variable from a scope, freeing all related memory as well.
496 * The variable name is kept as-is, it is not expanded. 496 * The variable name is kept as-is, it is not expanded.
497 */ 497 */
498void 498void
499Var_Delete(GNode *scope, const char *varname) 499Var_Delete(GNode *scope, const char *varname)
500{ 500{
501 HashEntry *he = HashTable_FindEntry(&scope->vars, varname); 501 HashEntry *he = HashTable_FindEntry(&scope->vars, varname);
502 Var *v; 502 Var *v;
503 503
504 if (he == NULL) { 504 if (he == NULL) {
505 DEBUG2(VAR, "%s:delete %s (not found)\n", scope->name, varname); 505 DEBUG2(VAR, "%s:delete %s (not found)\n", scope->name, varname);
506 return; 506 return;
507 } 507 }
508 508
509 DEBUG2(VAR, "%s:delete %s\n", scope->name, varname); 509 DEBUG2(VAR, "%s:delete %s\n", scope->name, varname);
510 v = he->value; 510 v = he->value;
511 if (v->flags & VFL_EXPORTED) 511 if (v->flags & VFL_EXPORTED)
512 unsetenv(v->name.str); 512 unsetenv(v->name.str);
513 if (strcmp(v->name.str, MAKE_EXPORTED) == 0) 513 if (strcmp(v->name.str, MAKE_EXPORTED) == 0)
514 var_exportedVars = VAR_EXPORTED_NONE; 514 var_exportedVars = VAR_EXPORTED_NONE;
515 assert(v->name.freeIt == NULL); 515 assert(v->name.freeIt == NULL);
516 HashTable_DeleteEntry(&scope->vars, he); 516 HashTable_DeleteEntry(&scope->vars, he);
517 Buf_Done(&v->val); 517 Buf_Done(&v->val);
518 free(v); 518 free(v);
519} 519}
520 520
521/* 521/*
522 * Remove a variable from a scope, freeing all related memory as well. 522 * Remove a variable from a scope, freeing all related memory as well.
523 * The variable name is expanded once. 523 * The variable name is expanded once.
524 */ 524 */
525void 525void
526Var_DeleteExpand(GNode *scope, const char *name) 526Var_DeleteExpand(GNode *scope, const char *name)
527{ 527{
528 FStr varname = FStr_InitRefer(name); 528 FStr varname = FStr_InitRefer(name);
529 529
530 if (strchr(varname.str, '$') != NULL) { 530 if (strchr(varname.str, '$') != NULL) {
531 char *expanded; 531 char *expanded;
532 (void)Var_Subst(varname.str, SCOPE_GLOBAL, VARE_WANTRES, 532 (void)Var_Subst(varname.str, SCOPE_GLOBAL, VARE_WANTRES,
533 &expanded); 533 &expanded);
534 /* TODO: handle errors */ 534 /* TODO: handle errors */
535 varname = FStr_InitOwn(expanded); 535 varname = FStr_InitOwn(expanded);
536 } 536 }
537 537
538 Var_Delete(scope, varname.str); 538 Var_Delete(scope, varname.str);
539 FStr_Done(&varname); 539 FStr_Done(&varname);
540} 540}
541 541
542/* 542/*
543 * Undefine one or more variables from the global scope. 543 * Undefine one or more variables from the global scope.
544 * The argument is expanded exactly once and then split into words. 544 * The argument is expanded exactly once and then split into words.
545 */ 545 */
546void 546void
547Var_Undef(const char *arg) 547Var_Undef(const char *arg)
548{ 548{
549 VarParseResult vpr; 549 VarParseResult vpr;
550 char *expanded; 550 char *expanded;
551 Words varnames; 551 Words varnames;
552 size_t i; 552 size_t i;
553 553
554 if (arg[0] == '\0') { 554 if (arg[0] == '\0') {
555 Parse_Error(PARSE_FATAL, 555 Parse_Error(PARSE_FATAL,
556 "The .undef directive requires an argument"); 556 "The .undef directive requires an argument");
557 return; 557 return;
558 } 558 }
559 559
560 vpr = Var_Subst(arg, SCOPE_GLOBAL, VARE_WANTRES, &expanded); 560 vpr = Var_Subst(arg, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
561 if (vpr != VPR_OK) { 561 if (vpr != VPR_OK) {
562 Parse_Error(PARSE_FATAL, 562 Parse_Error(PARSE_FATAL,
563 "Error in variable names to be undefined"); 563 "Error in variable names to be undefined");
564 return; 564 return;
565 } 565 }
566 566
567 varnames = Str_Words(expanded, FALSE); 567 varnames = Str_Words(expanded, FALSE);
568 if (varnames.len == 1 && varnames.words[0][0] == '\0') 568 if (varnames.len == 1 && varnames.words[0][0] == '\0')
569 varnames.len = 0; 569 varnames.len = 0;
570 570
571 for (i = 0; i < varnames.len; i++) { 571 for (i = 0; i < varnames.len; i++) {
572 const char *varname = varnames.words[i]; 572 const char *varname = varnames.words[i];
573 Global_Delete(varname); 573 Global_Delete(varname);
574 } 574 }
575 575
576 Words_Free(varnames); 576 Words_Free(varnames);
577 free(expanded); 577 free(expanded);
578} 578}
579 579
580static Boolean 580static Boolean
581MayExport(const char *name) 581MayExport(const char *name)
582{ 582{
583 if (name[0] == '.') 583 if (name[0] == '.')
584 return FALSE; /* skip internals */ 584 return FALSE; /* skip internals */
585 if (name[0] == '-') 585 if (name[0] == '-')
586 return FALSE; /* skip misnamed variables */ 586 return FALSE; /* skip misnamed variables */
587 if (name[1] == '\0') { 587 if (name[1] == '\0') {
588 /* 588 /*
589 * A single char. 589 * A single char.
590 * If it is one of the variables that should only appear in 590 * If it is one of the variables that should only appear in
591 * local scope, skip it, else we can get Var_Subst 591 * local scope, skip it, else we can get Var_Subst
592 * into a loop. 592 * into a loop.
593 */ 593 */
594 switch (name[0]) { 594 switch (name[0]) {
595 case '@': 595 case '@':
596 case '%': 596 case '%':
597 case '*': 597 case '*':
598 case '!': 598 case '!':
599 return FALSE; 599 return FALSE;
600 } 600 }
601 } 601 }
602 return TRUE; 602 return TRUE;
603} 603}
604 604
605static Boolean 605static Boolean
606ExportVarEnv(Var *v) 606ExportVarEnv(Var *v)
607{ 607{
608 const char *name = v->name.str; 608 const char *name = v->name.str;
609 char *val = v->val.data; 609 char *val = v->val.data;
610 char *expr; 610 char *expr;
611 611
612 if ((v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT)) 612 if ((v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT))
613 return FALSE; /* nothing to do */ 613 return FALSE; /* nothing to do */
614 614
615 if (strchr(val, '$') == NULL) { 615 if (strchr(val, '$') == NULL) {
616 if (!(v->flags & VFL_EXPORTED)) 616 if (!(v->flags & VFL_EXPORTED))
617 setenv(name, val, 1); 617 setenv(name, val, 1);
618 return TRUE; 618 return TRUE;
619 } 619 }
620 620
621 if (v->flags & VFL_IN_USE) { 621 if (v->flags & VFL_IN_USE) {
622 /* 622 /*
623 * We recursed while exporting in a child. 623 * We recursed while exporting in a child.
624 * This isn't going to end well, just skip it. 624 * This isn't going to end well, just skip it.
625 */ 625 */
626 return FALSE; 626 return FALSE;
627 } 627 }
628 628
629 /* XXX: name is injected without escaping it */ 629 /* XXX: name is injected without escaping it */
630 expr = str_concat3("${", name, "}"); 630 expr = str_concat3("${", name, "}");
631 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &val); 631 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &val);
632 /* TODO: handle errors */ 632 /* TODO: handle errors */
633 setenv(name, val, 1); 633 setenv(name, val, 1);
634 free(val); 634 free(val);
635 free(expr); 635 free(expr);
636 return TRUE; 636 return TRUE;
637} 637}
638 638
639static Boolean 639static Boolean
640ExportVarPlain(Var *v) 640ExportVarPlain(Var *v)
641{ 641{
642 if (strchr(v->val.data, '$') == NULL) { 642 if (strchr(v->val.data, '$') == NULL) {
643 setenv(v->name.str, v->val.data, 1); 643 setenv(v->name.str, v->val.data, 1);
644 v->flags |= VFL_EXPORTED; 644 v->flags |= VFL_EXPORTED;
645 v->flags &= ~(unsigned)VFL_REEXPORT; 645 v->flags &= ~(unsigned)VFL_REEXPORT;
646 return TRUE; 646 return TRUE;
647 } 647 }
648 648
649 /* 649 /*
650 * Flag the variable as something we need to re-export. 650 * Flag the variable as something we need to re-export.
651 * No point actually exporting it now though, 651 * No point actually exporting it now though,
652 * the child process can do it at the last minute. 652 * the child process can do it at the last minute.
653 * Avoid calling setenv more often than necessary since it can leak. 653 * Avoid calling setenv more often than necessary since it can leak.
654 */ 654 */
655 v->flags |= VFL_EXPORTED | VFL_REEXPORT; 655 v->flags |= VFL_EXPORTED | VFL_REEXPORT;
656 return TRUE; 656 return TRUE;
657} 657}
658 658
659static Boolean 659static Boolean
660ExportVarLiteral(Var *v) 660ExportVarLiteral(Var *v)
661{ 661{
662 if ((v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT)) 662 if ((v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT))
663 return FALSE; 663 return FALSE;
664 664
665 if (!(v->flags & VFL_EXPORTED)) 665 if (!(v->flags & VFL_EXPORTED))
666 setenv(v->name.str, v->val.data, 1); 666 setenv(v->name.str, v->val.data, 1);
667 667
668 return TRUE; 668 return TRUE;
669} 669}
670 670
671/* 671/*
672 * Mark a single variable to be exported later for subprocesses. 672 * Mark a single variable to be exported later for subprocesses.
673 * 673 *
674 * Internal variables (those starting with '.') are not exported. 674 * Internal variables (those starting with '.') are not exported.
675 */ 675 */
676static Boolean 676static Boolean
677ExportVar(const char *name, VarExportMode mode) 677ExportVar(const char *name, VarExportMode mode)
678{ 678{
679 Var *v; 679 Var *v;
680 680
681 if (!MayExport(name)) 681 if (!MayExport(name))
682 return FALSE; 682 return FALSE;
683 683
684 v = VarFind(name, SCOPE_GLOBAL, FALSE); 684 v = VarFind(name, SCOPE_GLOBAL, FALSE);
685 if (v == NULL) 685 if (v == NULL)
686 return FALSE; 686 return FALSE;
687 687
688 if (mode == VEM_ENV) 688 if (mode == VEM_ENV)
689 return ExportVarEnv(v); 689 return ExportVarEnv(v);
690 else if (mode == VEM_PLAIN) 690 else if (mode == VEM_PLAIN)
691 return ExportVarPlain(v); 691 return ExportVarPlain(v);
692 else 692 else
693 return ExportVarLiteral(v); 693 return ExportVarLiteral(v);
694} 694}
695 695
696/* 696/*
697 * Actually export the variables that have been marked as needing to be 697 * Actually export the variables that have been marked as needing to be
698 * re-exported. 698 * re-exported.
699 */ 699 */
700void 700void
701Var_ReexportVars(void) 701Var_ReexportVars(void)
702{ 702{
703 char *xvarnames; 703 char *xvarnames;
704 704
705 /* 705 /*
706 * Several make implementations support this sort of mechanism for 706 * Several make implementations support this sort of mechanism for
707 * tracking recursion - but each uses a different name. 707 * tracking recursion - but each uses a different name.
708 * We allow the makefiles to update MAKELEVEL and ensure 708 * We allow the makefiles to update MAKELEVEL and ensure
709 * children see a correctly incremented value. 709 * children see a correctly incremented value.
710 */ 710 */
711 char tmp[21]; 711 char tmp[21];
712 snprintf(tmp, sizeof tmp, "%d", makelevel + 1); 712 snprintf(tmp, sizeof tmp, "%d", makelevel + 1);
713 setenv(MAKE_LEVEL_ENV, tmp, 1); 713 setenv(MAKE_LEVEL_ENV, tmp, 1);
714 714
715 if (var_exportedVars == VAR_EXPORTED_NONE) 715 if (var_exportedVars == VAR_EXPORTED_NONE)
716 return; 716 return;
717 717
718 if (var_exportedVars == VAR_EXPORTED_ALL) { 718 if (var_exportedVars == VAR_EXPORTED_ALL) {
719 HashIter hi; 719 HashIter hi;
720 720
721 /* Ouch! Exporting all variables at once is crazy. */ 721 /* Ouch! Exporting all variables at once is crazy. */
722 HashIter_Init(&hi, &SCOPE_GLOBAL->vars); 722 HashIter_Init(&hi, &SCOPE_GLOBAL->vars);
723 while (HashIter_Next(&hi) != NULL) { 723 while (HashIter_Next(&hi) != NULL) {
724 Var *var = hi.entry->value; 724 Var *var = hi.entry->value;
725 ExportVar(var->name.str, VEM_ENV); 725 ExportVar(var->name.str, VEM_ENV);
726 } 726 }
727 return; 727 return;
728 } 728 }
729 729
730 (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL, VARE_WANTRES, 730 (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL, VARE_WANTRES,
731 &xvarnames); 731 &xvarnames);
732 /* TODO: handle errors */ 732 /* TODO: handle errors */
733 if (xvarnames[0] != '\0') { 733 if (xvarnames[0] != '\0') {
734 Words varnames = Str_Words(xvarnames, FALSE); 734 Words varnames = Str_Words(xvarnames, FALSE);
735 size_t i; 735 size_t i;
736 736
737 for (i = 0; i < varnames.len; i++) 737 for (i = 0; i < varnames.len; i++)
738 ExportVar(varnames.words[i], VEM_ENV); 738 ExportVar(varnames.words[i], VEM_ENV);
739 Words_Free(varnames); 739 Words_Free(varnames);
740 } 740 }
741 free(xvarnames); 741 free(xvarnames);
742} 742}
743 743
744static void 744static void
745ExportVars(const char *varnames, Boolean isExport, VarExportMode mode) 745ExportVars(const char *varnames, Boolean isExport, VarExportMode mode)
746/* TODO: try to combine the parameters 'isExport' and 'mode'. */ 746/* TODO: try to combine the parameters 'isExport' and 'mode'. */
747{ 747{
748 Words words = Str_Words(varnames, FALSE); 748 Words words = Str_Words(varnames, FALSE);
749 size_t i; 749 size_t i;
750 750
751 if (words.len == 1 && words.words[0][0] == '\0') 751 if (words.len == 1 && words.words[0][0] == '\0')
752 words.len = 0; 752 words.len = 0;
753 753
754 for (i = 0; i < words.len; i++) { 754 for (i = 0; i < words.len; i++) {
755 const char *varname = words.words[i]; 755 const char *varname = words.words[i];
756 if (!ExportVar(varname, mode)) 756 if (!ExportVar(varname, mode))
757 continue; 757 continue;
758 758
759 if (var_exportedVars == VAR_EXPORTED_NONE) 759 if (var_exportedVars == VAR_EXPORTED_NONE)
760 var_exportedVars = VAR_EXPORTED_SOME; 760 var_exportedVars = VAR_EXPORTED_SOME;
761 761
762 if (isExport && mode == VEM_PLAIN) 762 if (isExport && mode == VEM_PLAIN)
763 Global_Append(MAKE_EXPORTED, varname); 763 Global_Append(MAKE_EXPORTED, varname);
764 } 764 }
765 Words_Free(words); 765 Words_Free(words);
766} 766}
767 767
768static void 768static void
769ExportVarsExpand(const char *uvarnames, Boolean isExport, VarExportMode mode) 769ExportVarsExpand(const char *uvarnames, Boolean isExport, VarExportMode mode)
770{ 770{
771 char *xvarnames; 771 char *xvarnames;
772 772
773 (void)Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_WANTRES, &xvarnames); 773 (void)Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_WANTRES, &xvarnames);
774 /* TODO: handle errors */ 774 /* TODO: handle errors */
775 ExportVars(xvarnames, isExport, mode); 775 ExportVars(xvarnames, isExport, mode);
776 free(xvarnames); 776 free(xvarnames);
777} 777}
778 778
779/* Export the named variables, or all variables. */ 779/* Export the named variables, or all variables. */
780void 780void
781Var_Export(VarExportMode mode, const char *varnames) 781Var_Export(VarExportMode mode, const char *varnames)
782{ 782{
783 if (mode == VEM_PLAIN && varnames[0] == '\0') { 783 if (mode == VEM_PLAIN && varnames[0] == '\0') {
784 var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */ 784 var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
785 return; 785 return;
786 } 786 }
787 787
788 ExportVarsExpand(varnames, TRUE, mode); 788 ExportVarsExpand(varnames, TRUE, mode);
789} 789}
790 790
791void 791void
792Var_ExportVars(const char *varnames) 792Var_ExportVars(const char *varnames)
793{ 793{
794 ExportVarsExpand(varnames, FALSE, VEM_PLAIN); 794 ExportVarsExpand(varnames, FALSE, VEM_PLAIN);
795} 795}
796 796
797 797
798extern char **environ; 798extern char **environ;
799 799
800static void 800static void
801ClearEnv(void) 801ClearEnv(void)
802{ 802{
803 const char *cp; 803 const char *cp;
804 char **newenv; 804 char **newenv;
805 805
806 cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */ 806 cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */
807 if (environ == savedEnv) { 807 if (environ == savedEnv) {
808 /* we have been here before! */ 808 /* we have been here before! */
809 newenv = bmake_realloc(environ, 2 * sizeof(char *)); 809 newenv = bmake_realloc(environ, 2 * sizeof(char *));
810 } else { 810 } else {
811 if (savedEnv != NULL) { 811 if (savedEnv != NULL) {
812 free(savedEnv); 812 free(savedEnv);
813 savedEnv = NULL; 813 savedEnv = NULL;
814 } 814 }
815 newenv = bmake_malloc(2 * sizeof(char *)); 815 newenv = bmake_malloc(2 * sizeof(char *));
816 } 816 }
817 817
818 /* Note: we cannot safely free() the original environ. */ 818 /* Note: we cannot safely free() the original environ. */
819 environ = savedEnv = newenv; 819 environ = savedEnv = newenv;
820 newenv[0] = NULL; 820 newenv[0] = NULL;
821 newenv[1] = NULL; 821 newenv[1] = NULL;
822 if (cp != NULL && *cp != '\0') 822 if (cp != NULL && *cp != '\0')
823 setenv(MAKE_LEVEL_ENV, cp, 1); 823 setenv(MAKE_LEVEL_ENV, cp, 1);
824} 824}
825 825
826static void 826static void
827GetVarnamesToUnexport(Boolean isEnv, const char *arg, 827GetVarnamesToUnexport(Boolean isEnv, const char *arg,
828 FStr *out_varnames, UnexportWhat *out_what) 828 FStr *out_varnames, UnexportWhat *out_what)
829{ 829{
830 UnexportWhat what; 830 UnexportWhat what;
831 FStr varnames = FStr_InitRefer(""); 831 FStr varnames = FStr_InitRefer("");
832 832
833 if (isEnv) { 833 if (isEnv) {
834 if (arg[0] != '\0') { 834 if (arg[0] != '\0') {
835 Parse_Error(PARSE_FATAL, 835 Parse_Error(PARSE_FATAL,
836 "The directive .unexport-env does not take " 836 "The directive .unexport-env does not take "
837 "arguments"); 837 "arguments");
838 /* continue anyway */ 838 /* continue anyway */
839 } 839 }
840 what = UNEXPORT_ENV; 840 what = UNEXPORT_ENV;
841 841
842 } else { 842 } else {
843 what = arg[0] != '\0' ? UNEXPORT_NAMED : UNEXPORT_ALL; 843 what = arg[0] != '\0' ? UNEXPORT_NAMED : UNEXPORT_ALL;
844 if (what == UNEXPORT_NAMED) 844 if (what == UNEXPORT_NAMED)
845 varnames = FStr_InitRefer(arg); 845 varnames = FStr_InitRefer(arg);
846 } 846 }
847 847
848 if (what != UNEXPORT_NAMED) { 848 if (what != UNEXPORT_NAMED) {
849 char *expanded; 849 char *expanded;
850 /* Using .MAKE.EXPORTED */ 850 /* Using .MAKE.EXPORTED */
851 (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL, 851 (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL,
852 VARE_WANTRES, &expanded); 852 VARE_WANTRES, &expanded);
853 /* TODO: handle errors */ 853 /* TODO: handle errors */
854 varnames = FStr_InitOwn(expanded); 854 varnames = FStr_InitOwn(expanded);
855 } 855 }
856 856
857 *out_varnames = varnames; 857 *out_varnames = varnames;
858 *out_what = what; 858 *out_what = what;
859} 859}
860 860
861static void 861static void
862UnexportVar(const char *varname, UnexportWhat what) 862UnexportVar(const char *varname, UnexportWhat what)
863{ 863{
864 Var *v = VarFind(varname, SCOPE_GLOBAL, FALSE); 864 Var *v = VarFind(varname, SCOPE_GLOBAL, FALSE);
865 if (v == NULL) { 865 if (v == NULL) {
866 DEBUG1(VAR, "Not unexporting \"%s\" (not found)\n", varname); 866 DEBUG1(VAR, "Not unexporting \"%s\" (not found)\n", varname);
867 return; 867 return;
868 } 868 }
869 869
870 DEBUG1(VAR, "Unexporting \"%s\"\n", varname); 870 DEBUG1(VAR, "Unexporting \"%s\"\n", varname);
871 if (what != UNEXPORT_ENV && 871 if (what != UNEXPORT_ENV &&
872 (v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT)) 872 (v->flags & VFL_EXPORTED) && !(v->flags & VFL_REEXPORT))
873 unsetenv(v->name.str); 873 unsetenv(v->name.str);
874 v->flags &= ~(unsigned)(VFL_EXPORTED | VFL_REEXPORT); 874 v->flags &= ~(unsigned)(VFL_EXPORTED | VFL_REEXPORT);
875 875
876 if (what == UNEXPORT_NAMED) { 876 if (what == UNEXPORT_NAMED) {
877 /* Remove the variable names from .MAKE.EXPORTED. */ 877 /* Remove the variable names from .MAKE.EXPORTED. */
878 /* XXX: v->name is injected without escaping it */ 878 /* XXX: v->name is injected without escaping it */
879 char *expr = str_concat3("${" MAKE_EXPORTED ":N", 879 char *expr = str_concat3("${" MAKE_EXPORTED ":N",
880 v->name.str, "}"); 880 v->name.str, "}");
881 char *cp; 881 char *cp;
882 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &cp); 882 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &cp);
883 /* TODO: handle errors */ 883 /* TODO: handle errors */
884 Global_Set(MAKE_EXPORTED, cp); 884 Global_Set(MAKE_EXPORTED, cp);
885 free(cp); 885 free(cp);
886 free(expr); 886 free(expr);
887 } 887 }
888} 888}
889 889
890static void 890static void
891UnexportVars(FStr *varnames, UnexportWhat what) 891UnexportVars(FStr *varnames, UnexportWhat what)
892{ 892{
893 size_t i; 893 size_t i;
894 Words words; 894 Words words;
895 895
896 if (what == UNEXPORT_ENV) 896 if (what == UNEXPORT_ENV)
897 ClearEnv(); 897 ClearEnv();
898 898
899 words = Str_Words(varnames->str, FALSE); 899 words = Str_Words(varnames->str, FALSE);
900 for (i = 0; i < words.len; i++) { 900 for (i = 0; i < words.len; i++) {
901 const char *varname = words.words[i]; 901 const char *varname = words.words[i];
902 UnexportVar(varname, what); 902 UnexportVar(varname, what);
903 } 903 }
904 Words_Free(words); 904 Words_Free(words);
905 905
906 if (what != UNEXPORT_NAMED) 906 if (what != UNEXPORT_NAMED)
907 Global_Delete(MAKE_EXPORTED); 907 Global_Delete(MAKE_EXPORTED);
908} 908}
909 909
910/* 910/*
911 * This is called when .unexport[-env] is seen. 911 * This is called when .unexport[-env] is seen.
912 * 912 *
913 * str must have the form "unexport[-env] varname...". 913 * str must have the form "unexport[-env] varname...".
914 */ 914 */
915void 915void
916Var_UnExport(Boolean isEnv, const char *arg) 916Var_UnExport(Boolean isEnv, const char *arg)
917{ 917{
918 UnexportWhat what; 918 UnexportWhat what;
919 FStr varnames; 919 FStr varnames;
920 920
921 GetVarnamesToUnexport(isEnv, arg, &varnames, &what); 921 GetVarnamesToUnexport(isEnv, arg, &varnames, &what);
922 UnexportVars(&varnames, what); 922 UnexportVars(&varnames, what);
923 FStr_Done(&varnames); 923 FStr_Done(&varnames);
924} 924}
925 925
926/* 926/*
927 * When there is a variable of the same name in the command line scope, the 927 * When there is a variable of the same name in the command line scope, the
928 * global variable would not be visible anywhere. Therefore there is no 928 * global variable would not be visible anywhere. Therefore there is no
929 * point in setting it at all. 929 * point in setting it at all.
930 * 930 *
931 * See 'scope == SCOPE_CMDLINE' in Var_SetWithFlags. 931 * See 'scope == SCOPE_CMDLINE' in Var_SetWithFlags.
932 */ 932 */
933static Boolean 933static Boolean
934ExistsInCmdline(const char *name, const char *val) 934ExistsInCmdline(const char *name, const char *val)
935{ 935{
936 Var *v; 936 Var *v;
937 937
938 v = VarFind(name, SCOPE_CMDLINE, FALSE); 938 v = VarFind(name, SCOPE_CMDLINE, FALSE);
939 if (v == NULL) 939 if (v == NULL)
940 return FALSE; 940 return FALSE;
941 941
942 if (v->flags & VFL_FROM_CMD) { 942 if (v->flags & VFL_FROM_CMD) {
943 DEBUG3(VAR, "%s:%s = %s ignored!\n", 943 DEBUG3(VAR, "%s:%s = %s ignored!\n",
944 SCOPE_GLOBAL->name, name, val); 944 SCOPE_GLOBAL->name, name, val);
945 return TRUE; 945 return TRUE;
946 } 946 }
947 947
948 VarFreeEnv(v); 948 VarFreeEnv(v);
949 return FALSE; 949 return FALSE;
950} 950}
951 951
952/* Set the variable to the value; the name is not expanded. */ 952/* Set the variable to the value; the name is not expanded. */
953void 953void
954Var_SetWithFlags(GNode *scope, const char *name, const char *val, 954Var_SetWithFlags(GNode *scope, const char *name, const char *val,
955 VarSetFlags flags) 955 VarSetFlags flags)
956{ 956{
957 Var *v; 957 Var *v;
958 958
959 assert(val != NULL); 959 assert(val != NULL);
960 if (name[0] == '\0') { 960 if (name[0] == '\0') {
961 DEBUG0(VAR, "SetVar: variable name is empty - ignored\n"); 961 DEBUG0(VAR, "SetVar: variable name is empty - ignored\n");
962 return; 962 return;
963 } 963 }
964 964
965 if (scope == SCOPE_GLOBAL && ExistsInCmdline(name, val)) 965 if (scope == SCOPE_GLOBAL && ExistsInCmdline(name, val))
966 return; 966 return;
967 967
968 /* 968 /*
969 * Only look for a variable in the given scope since anything set 969 * Only look for a variable in the given scope since anything set
970 * here will override anything in a lower scope, so there's not much 970 * here will override anything in a lower scope, so there's not much
971 * point in searching them all. 971 * point in searching them all.
972 */ 972 */
973 v = VarFind(name, scope, FALSE); 973 v = VarFind(name, scope, FALSE);
974 if (v == NULL) { 974 if (v == NULL) {
975 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) { 975 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
976 /* 976 /*
977 * This var would normally prevent the same name being 977 * This var would normally prevent the same name being
978 * added to SCOPE_GLOBAL, so delete it from there if 978 * added to SCOPE_GLOBAL, so delete it from there if
979 * needed. Otherwise -V name may show the wrong value. 979 * needed. Otherwise -V name may show the wrong value.
980 * 980 *
981 * See ExistsInCmdline. 981 * See ExistsInCmdline.
982 */ 982 */
983 Var_Delete(SCOPE_GLOBAL, name); 983 Var_Delete(SCOPE_GLOBAL, name);
984 } 984 }
985 v = VarAdd(name, val, scope, flags); 985 v = VarAdd(name, val, scope, flags);
986 } else { 986 } else {
987 if ((v->flags & VFL_READONLY) && !(flags & VAR_SET_READONLY)) { 987 if ((v->flags & VFL_READONLY) && !(flags & VAR_SET_READONLY)) {
988 DEBUG3(VAR, "%s:%s = %s ignored (read-only)\n", 988 DEBUG3(VAR, "%s:%s = %s ignored (read-only)\n",
989 scope->name, name, val); 989 scope->name, name, val);
990 return; 990 return;
991 } 991 }
992 Buf_Empty(&v->val); 992 Buf_Empty(&v->val);
993 Buf_AddStr(&v->val, val); 993 Buf_AddStr(&v->val, val);
994 994
995 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, val); 995 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, val);
996 if (v->flags & VFL_EXPORTED) 996 if (v->flags & VFL_EXPORTED)
997 ExportVar(name, VEM_PLAIN); 997 ExportVar(name, VEM_PLAIN);
998 } 998 }
999 999
1000 /* 1000 /*
1001 * Any variables given on the command line are automatically exported 1001 * Any variables given on the command line are automatically exported
1002 * to the environment (as per POSIX standard), except for internals. 1002 * to the environment (as per POSIX standard), except for internals.
1003 */ 1003 */
1004 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT) && 1004 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT) &&
1005 name[0] != '.') { 1005 name[0] != '.') {
1006 v->flags |= VFL_FROM_CMD; 1006 v->flags |= VFL_FROM_CMD;
1007 1007
1008 /* 1008 /*
1009 * If requested, don't export these in the environment 1009 * If requested, don't export these in the environment
1010 * individually. We still put them in MAKEOVERRIDES so 1010 * individually. We still put them in MAKEOVERRIDES so
1011 * that the command-line settings continue to override 1011 * that the command-line settings continue to override
1012 * Makefile settings. 1012 * Makefile settings.
1013 */ 1013 */
1014 if (!opts.varNoExportEnv) 1014 if (!opts.varNoExportEnv)
1015 setenv(name, val, 1); 1015 setenv(name, val, 1);
1016 /* XXX: What about .MAKE.EXPORTED? */ 1016 /* XXX: What about .MAKE.EXPORTED? */
1017 /* XXX: Why not just mark the variable for needing export, 1017 /* XXX: Why not just mark the variable for needing export,
1018 * as in ExportVarPlain? */ 1018 * as in ExportVarPlain? */
1019 1019
1020 Global_Append(MAKEOVERRIDES, name); 1020 Global_Append(MAKEOVERRIDES, name);
1021 } 1021 }
1022 1022
1023 if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0) 1023 if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
1024 save_dollars = ParseBoolean(val, save_dollars); 1024 save_dollars = ParseBoolean(val, save_dollars);
1025 1025
1026 if (v != NULL) 1026 if (v != NULL)
1027 VarFreeEnv(v); 1027 VarFreeEnv(v);
1028} 1028}
1029 1029
1030/* See Var_Set for documentation. */ 1030/* See Var_Set for documentation. */
1031void 1031void
1032Var_SetExpandWithFlags(GNode *scope, const char *name, const char *val, 1032Var_SetExpandWithFlags(GNode *scope, const char *name, const char *val,
1033 VarSetFlags flags) 1033 VarSetFlags flags)
1034{ 1034{
1035 const char *unexpanded_name = name; 1035 const char *unexpanded_name = name;
1036 FStr varname = FStr_InitRefer(name); 1036 FStr varname = FStr_InitRefer(name);
1037 1037
1038 assert(val != NULL); 1038 assert(val != NULL);
1039 1039
1040 if (strchr(varname.str, '$') != NULL) { 1040 if (strchr(varname.str, '$') != NULL) {
1041 char *expanded; 1041 char *expanded;
1042 (void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded); 1042 (void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded);
1043 /* TODO: handle errors */ 1043 /* TODO: handle errors */
1044 varname = FStr_InitOwn(expanded); 1044 varname = FStr_InitOwn(expanded);
1045 } 1045 }
1046 1046
1047 if (varname.str[0] == '\0') { 1047 if (varname.str[0] == '\0') {
1048 DEBUG2(VAR, "Var_Set(\"%s\", \"%s\", ...) " 1048 DEBUG2(VAR, "Var_Set(\"%s\", \"%s\", ...) "
1049 "name expands to empty string - ignored\n", 1049 "name expands to empty string - ignored\n",
1050 unexpanded_name, val); 1050 unexpanded_name, val);
1051 } else 1051 } else
1052 Var_SetWithFlags(scope, varname.str, val, flags); 1052 Var_SetWithFlags(scope, varname.str, val, flags);
1053 1053
1054 FStr_Done(&varname); 1054 FStr_Done(&varname);
1055} 1055}
1056 1056
1057void 1057void
1058Var_Set(GNode *scope, const char *name, const char *val) 1058Var_Set(GNode *scope, const char *name, const char *val)
1059{ 1059{
1060 Var_SetWithFlags(scope, name, val, VAR_SET_NONE); 1060 Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1061} 1061}
1062 1062
1063/* 1063/*
1064 * Set the variable name to the value val in the given scope. 1064 * Set the variable name to the value val in the given scope.
1065 * 1065 *
1066 * If the variable doesn't yet exist, it is created. 1066 * If the variable doesn't yet exist, it is created.
1067 * Otherwise the new value overwrites and replaces the old value. 1067 * Otherwise the new value overwrites and replaces the old value.
1068 * 1068 *
1069 * Input: 1069 * Input:
1070 * name name of the variable to set, is expanded once 1070 * name name of the variable to set, is expanded once
1071 * val value to give to the variable 1071 * val value to give to the variable
1072 * scope scope in which to set it 1072 * scope scope in which to set it
1073 */ 1073 */
1074void 1074void
1075Var_SetExpand(GNode *scope, const char *name, const char *val) 1075Var_SetExpand(GNode *scope, const char *name, const char *val)
1076{ 1076{
1077 Var_SetExpandWithFlags(scope, name, val, VAR_SET_NONE); 1077 Var_SetExpandWithFlags(scope, name, val, VAR_SET_NONE);
1078} 1078}
1079 1079
1080void 1080void
1081Global_Set(const char *name, const char *value) 1081Global_Set(const char *name, const char *value)
1082{ 1082{
1083 Var_Set(SCOPE_GLOBAL, name, value); 1083 Var_Set(SCOPE_GLOBAL, name, value);
1084} 1084}
1085 1085
1086void 1086void
1087Global_SetExpand(const char *name, const char *value) 1087Global_SetExpand(const char *name, const char *value)
1088{ 1088{
1089 Var_SetExpand(SCOPE_GLOBAL, name, value); 1089 Var_SetExpand(SCOPE_GLOBAL, name, value);
1090} 1090}
1091 1091
1092void 1092void
1093Global_Delete(const char *name) 1093Global_Delete(const char *name)
1094{ 1094{
1095 Var_Delete(SCOPE_GLOBAL, name); 1095 Var_Delete(SCOPE_GLOBAL, name);
1096} 1096}
1097 1097
1098/* 1098/*
1099 * Append the value to the named variable. 1099 * Append the value to the named variable.
1100 * 1100 *
1101 * If the variable doesn't exist, it is created. Otherwise a single space 1101 * If the variable doesn't exist, it is created. Otherwise a single space
1102 * and the given value are appended. 1102 * and the given value are appended.
1103 */ 1103 */
1104void 1104void
1105Var_Append(GNode *scope, const char *name, const char *val) 1105Var_Append(GNode *scope, const char *name, const char *val)
1106{ 1106{
1107 Var *v; 1107 Var *v;
1108 1108
1109 v = VarFind(name, scope, scope == SCOPE_GLOBAL); 1109 v = VarFind(name, scope, scope == SCOPE_GLOBAL);
1110 1110
1111 if (v == NULL) { 1111 if (v == NULL) {
1112 Var_SetWithFlags(scope, name, val, VAR_SET_NONE); 1112 Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1113 } else if (v->flags & VFL_READONLY) { 1113 } else if (v->flags & VFL_READONLY) {
1114 DEBUG1(VAR, "Ignoring append to %s since it is read-only\n", 1114 DEBUG1(VAR, "Ignoring append to %s since it is read-only\n",
1115 name); 1115 name);
1116 } else if (scope == SCOPE_CMDLINE || !(v->flags & VFL_FROM_CMD)) { 1116 } else if (scope == SCOPE_CMDLINE || !(v->flags & VFL_FROM_CMD)) {
1117 Buf_AddByte(&v->val, ' '); 1117 Buf_AddByte(&v->val, ' ');
1118 Buf_AddStr(&v->val, val); 1118 Buf_AddStr(&v->val, val);
1119 1119
1120 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, v->val.data); 1120 DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, v->val.data);
1121 1121
1122 if (v->flags & VFL_FROM_ENV) { 1122 if (v->flags & VFL_FROM_ENV) {
1123 /* 1123 /*
1124 * If the original variable came from the environment, 1124 * If the original variable came from the environment,
1125 * we have to install it in the global scope (we 1125 * we have to install it in the global scope (we
1126 * could place it in the environment, but then we 1126 * could place it in the environment, but then we
1127 * should provide a way to export other variables...) 1127 * should provide a way to export other variables...)
1128 */ 1128 */
1129 v->flags &= ~(unsigned)VFL_FROM_ENV; 1129 v->flags &= ~(unsigned)VFL_FROM_ENV;
1130 /* 1130 /*
1131 * This is the only place where a variable is 1131 * This is the only place where a variable is
1132 * created whose v->name is not the same as 1132 * created whose v->name is not the same as
1133 * scope->vars->key. 1133 * scope->vars->key.
1134 */ 1134 */
1135 HashTable_Set(&scope->vars, name, v); 1135 HashTable_Set(&scope->vars, name, v);
1136 } 1136 }
1137 } 1137 }
1138} 1138}
1139 1139
1140/* 1140/*
1141 * The variable of the given name has the given value appended to it in the 1141 * The variable of the given name has the given value appended to it in the
1142 * given scope. 1142 * given scope.
@@ -1510,3027 +1510,3048 @@ ModifyWord_SYSVSubst(const char *word, S @@ -1510,3027 +1510,3048 @@ ModifyWord_SYSVSubst(const char *word, S
1510 1510
1511 free(rhs_expanded); 1511 free(rhs_expanded);
1512} 1512}
1513#endif 1513#endif
1514 1514
1515 1515
1516struct ModifyWord_SubstArgs { 1516struct ModifyWord_SubstArgs {
1517 const char *lhs; 1517 const char *lhs;
1518 size_t lhsLen; 1518 size_t lhsLen;
1519 const char *rhs; 1519 const char *rhs;
1520 size_t rhsLen; 1520 size_t rhsLen;
1521 VarPatternFlags pflags; 1521 VarPatternFlags pflags;
1522 Boolean matched; 1522 Boolean matched;
1523}; 1523};
1524 1524
1525/* 1525/*
1526 * Callback for ModifyWords to implement the :S,from,to, modifier. 1526 * Callback for ModifyWords to implement the :S,from,to, modifier.
1527 * Perform a string substitution on the given word. 1527 * Perform a string substitution on the given word.
1528 */ 1528 */
1529static void 1529static void
1530ModifyWord_Subst(const char *word, SepBuf *buf, void *data) 1530ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
1531{ 1531{
1532 size_t wordLen = strlen(word); 1532 size_t wordLen = strlen(word);
1533 struct ModifyWord_SubstArgs *args = data; 1533 struct ModifyWord_SubstArgs *args = data;
1534 const char *match; 1534 const char *match;
1535 1535
1536 if (args->pflags.subOnce && args->matched) 1536 if (args->pflags.subOnce && args->matched)
1537 goto nosub; 1537 goto nosub;
1538 1538
1539 if (args->pflags.anchorStart) { 1539 if (args->pflags.anchorStart) {
1540 if (wordLen < args->lhsLen || 1540 if (wordLen < args->lhsLen ||
1541 memcmp(word, args->lhs, args->lhsLen) != 0) 1541 memcmp(word, args->lhs, args->lhsLen) != 0)
1542 goto nosub; 1542 goto nosub;
1543 1543
1544 if (args->pflags.anchorEnd && wordLen != args->lhsLen) 1544 if (args->pflags.anchorEnd && wordLen != args->lhsLen)
1545 goto nosub; 1545 goto nosub;
1546 1546
1547 /* :S,^prefix,replacement, or :S,^whole$,replacement, */ 1547 /* :S,^prefix,replacement, or :S,^whole$,replacement, */
1548 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1548 SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1549 SepBuf_AddBytesBetween(buf, 1549 SepBuf_AddBytesBetween(buf,
1550 word + args->lhsLen, word + wordLen); 1550 word + args->lhsLen, word + wordLen);
1551 args->matched = TRUE; 1551 args->matched = TRUE;
1552 return; 1552 return;
1553 } 1553 }
1554 1554
1555 if (args->pflags.anchorEnd) { 1555 if (args->pflags.anchorEnd) {
1556 const char *start; 1556 const char *start;
1557 1557
1558 if (wordLen < args->lhsLen) 1558 if (wordLen < args->lhsLen)
1559 goto nosub; 1559 goto nosub;
1560 1560
1561 start = word + (wordLen - args->lhsLen); 1561 start = word + (wordLen - args->lhsLen);
1562 if (memcmp(start, args->lhs, args->lhsLen) != 0) 1562 if (memcmp(start, args->lhs, args->lhsLen) != 0)
1563 goto nosub; 1563 goto nosub;
1564 1564
1565 /* :S,suffix$,replacement, */ 1565 /* :S,suffix$,replacement, */
1566 SepBuf_AddBytesBetween(buf, word, start); 1566 SepBuf_AddBytesBetween(buf, word, start);
1567 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1567 SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1568 args->matched = TRUE; 1568 args->matched = TRUE;
1569 return; 1569 return;
1570 } 1570 }
1571 1571
1572 if (args->lhs[0] == '\0') 1572 if (args->lhs[0] == '\0')
1573 goto nosub; 1573 goto nosub;
1574 1574
1575 /* unanchored case, may match more than once */ 1575 /* unanchored case, may match more than once */
1576 while ((match = strstr(word, args->lhs)) != NULL) { 1576 while ((match = strstr(word, args->lhs)) != NULL) {
1577 SepBuf_AddBytesBetween(buf, word, match); 1577 SepBuf_AddBytesBetween(buf, word, match);
1578 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1578 SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1579 args->matched = TRUE; 1579 args->matched = TRUE;
1580 wordLen -= (size_t)(match - word) + args->lhsLen; 1580 wordLen -= (size_t)(match - word) + args->lhsLen;
1581 word += (size_t)(match - word) + args->lhsLen; 1581 word += (size_t)(match - word) + args->lhsLen;
1582 if (wordLen == 0 || !args->pflags.subGlobal) 1582 if (wordLen == 0 || !args->pflags.subGlobal)
1583 break; 1583 break;
1584 } 1584 }
1585nosub: 1585nosub:
1586 SepBuf_AddBytes(buf, word, wordLen); 1586 SepBuf_AddBytes(buf, word, wordLen);
1587} 1587}
1588 1588
1589#ifndef NO_REGEX 1589#ifndef NO_REGEX
1590/* Print the error caused by a regcomp or regexec call. */ 1590/* Print the error caused by a regcomp or regexec call. */
1591static void 1591static void
1592VarREError(int reerr, const regex_t *pat, const char *str) 1592VarREError(int reerr, const regex_t *pat, const char *str)
1593{ 1593{
1594 size_t errlen = regerror(reerr, pat, NULL, 0); 1594 size_t errlen = regerror(reerr, pat, NULL, 0);
1595 char *errbuf = bmake_malloc(errlen); 1595 char *errbuf = bmake_malloc(errlen);
1596 regerror(reerr, pat, errbuf, errlen); 1596 regerror(reerr, pat, errbuf, errlen);
1597 Error("%s: %s", str, errbuf); 1597 Error("%s: %s", str, errbuf);
1598 free(errbuf); 1598 free(errbuf);
1599} 1599}
1600 1600
1601struct ModifyWord_SubstRegexArgs { 1601struct ModifyWord_SubstRegexArgs {
1602 regex_t re; 1602 regex_t re;
1603 size_t nsub; 1603 size_t nsub;
1604 char *replace; 1604 char *replace;
1605 VarPatternFlags pflags; 1605 VarPatternFlags pflags;
1606 Boolean matched; 1606 Boolean matched;
1607}; 1607};
1608 1608
1609/* 1609/*
1610 * Callback for ModifyWords to implement the :C/from/to/ modifier. 1610 * Callback for ModifyWords to implement the :C/from/to/ modifier.
1611 * Perform a regex substitution on the given word. 1611 * Perform a regex substitution on the given word.
1612 */ 1612 */
1613static void 1613static void
1614ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data) 1614ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data)
1615{ 1615{
1616 struct ModifyWord_SubstRegexArgs *args = data; 1616 struct ModifyWord_SubstRegexArgs *args = data;
1617 int xrv; 1617 int xrv;
1618 const char *wp = word; 1618 const char *wp = word;
1619 char *rp; 1619 char *rp;
1620 int flags = 0; 1620 int flags = 0;
1621 regmatch_t m[10]; 1621 regmatch_t m[10];
1622 1622
1623 if (args->pflags.subOnce && args->matched) 1623 if (args->pflags.subOnce && args->matched)
1624 goto nosub; 1624 goto nosub;
1625 1625
1626tryagain: 1626tryagain:
1627 xrv = regexec(&args->re, wp, args->nsub, m, flags); 1627 xrv = regexec(&args->re, wp, args->nsub, m, flags);
1628 1628
1629 switch (xrv) { 1629 switch (xrv) {
1630 case 0: 1630 case 0:
1631 args->matched = TRUE; 1631 args->matched = TRUE;
1632 SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so); 1632 SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1633 1633
1634 /* 1634 /*
1635 * Replacement of regular expressions is not specified by 1635 * Replacement of regular expressions is not specified by
1636 * POSIX, therefore implement it here. 1636 * POSIX, therefore implement it here.
1637 */ 1637 */
1638 1638
1639 for (rp = args->replace; *rp != '\0'; rp++) { 1639 for (rp = args->replace; *rp != '\0'; rp++) {
1640 if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) { 1640 if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
1641 SepBuf_AddBytes(buf, rp + 1, 1); 1641 SepBuf_AddBytes(buf, rp + 1, 1);
1642 rp++; 1642 rp++;
1643 continue; 1643 continue;
1644 } 1644 }
1645 1645
1646 if (*rp == '&') { 1646 if (*rp == '&') {
1647 SepBuf_AddBytesBetween(buf, 1647 SepBuf_AddBytesBetween(buf,
1648 wp + m[0].rm_so, wp + m[0].rm_eo); 1648 wp + m[0].rm_so, wp + m[0].rm_eo);
1649 continue; 1649 continue;
1650 } 1650 }
1651 1651
1652 if (*rp != '\\' || !ch_isdigit(rp[1])) { 1652 if (*rp != '\\' || !ch_isdigit(rp[1])) {
1653 SepBuf_AddBytes(buf, rp, 1); 1653 SepBuf_AddBytes(buf, rp, 1);
1654 continue; 1654 continue;
1655 } 1655 }
1656 1656
1657 { /* \0 to \9 backreference */ 1657 { /* \0 to \9 backreference */
1658 size_t n = (size_t)(rp[1] - '0'); 1658 size_t n = (size_t)(rp[1] - '0');
1659 rp++; 1659 rp++;
1660 1660
1661 if (n >= args->nsub) { 1661 if (n >= args->nsub) {
1662 Error("No subexpression \\%u", 1662 Error("No subexpression \\%u",
1663 (unsigned)n); 1663 (unsigned)n);
1664 } else if (m[n].rm_so == -1) { 1664 } else if (m[n].rm_so == -1) {
1665 Error( 1665 Error(
1666 "No match for subexpression \\%u", 1666 "No match for subexpression \\%u",
1667 (unsigned)n); 1667 (unsigned)n);
1668 } else { 1668 } else {
1669 SepBuf_AddBytesBetween(buf, 1669 SepBuf_AddBytesBetween(buf,
1670 wp + m[n].rm_so, wp + m[n].rm_eo); 1670 wp + m[n].rm_so, wp + m[n].rm_eo);
1671 } 1671 }
1672 } 1672 }
1673 } 1673 }
1674 1674
1675 wp += m[0].rm_eo; 1675 wp += m[0].rm_eo;
1676 if (args->pflags.subGlobal) { 1676 if (args->pflags.subGlobal) {
1677 flags |= REG_NOTBOL; 1677 flags |= REG_NOTBOL;
1678 if (m[0].rm_so == 0 && m[0].rm_eo == 0) { 1678 if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1679 SepBuf_AddBytes(buf, wp, 1); 1679 SepBuf_AddBytes(buf, wp, 1);
1680 wp++; 1680 wp++;
1681 } 1681 }
1682 if (*wp != '\0') 1682 if (*wp != '\0')
1683 goto tryagain; 1683 goto tryagain;
1684 } 1684 }
1685 if (*wp != '\0') 1685 if (*wp != '\0')
1686 SepBuf_AddStr(buf, wp); 1686 SepBuf_AddStr(buf, wp);
1687 break; 1687 break;
1688 default: 1688 default:
1689 VarREError(xrv, &args->re, "Unexpected regex error"); 1689 VarREError(xrv, &args->re, "Unexpected regex error");
1690 /* FALLTHROUGH */ 1690 /* FALLTHROUGH */
1691 case REG_NOMATCH: 1691 case REG_NOMATCH:
1692 nosub: 1692 nosub:
1693 SepBuf_AddStr(buf, wp); 1693 SepBuf_AddStr(buf, wp);
1694 break; 1694 break;
1695 } 1695 }
1696} 1696}
1697#endif 1697#endif
1698 1698
1699 1699
1700struct ModifyWord_LoopArgs { 1700struct ModifyWord_LoopArgs {
1701 GNode *scope; 1701 GNode *scope;
1702 char *tvar; /* name of temporary variable */ 1702 char *tvar; /* name of temporary variable */
1703 char *str; /* string to expand */ 1703 char *str; /* string to expand */
1704 VarEvalFlags eflags; 1704 VarEvalFlags eflags;
1705}; 1705};
1706 1706
1707/* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */ 1707/* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1708static void 1708static void
1709ModifyWord_Loop(const char *word, SepBuf *buf, void *data) 1709ModifyWord_Loop(const char *word, SepBuf *buf, void *data)
1710{ 1710{
1711 const struct ModifyWord_LoopArgs *args; 1711 const struct ModifyWord_LoopArgs *args;
1712 char *s; 1712 char *s;
1713 1713
1714 if (word[0] == '\0') 1714 if (word[0] == '\0')
1715 return; 1715 return;
1716 1716
1717 args = data; 1717 args = data;
1718 /* XXX: The variable name should not be expanded here. */ 1718 /* XXX: The variable name should not be expanded here. */
1719 Var_SetExpandWithFlags(args->scope, args->tvar, word, 1719 Var_SetExpandWithFlags(args->scope, args->tvar, word,
1720 VAR_SET_NO_EXPORT); 1720 VAR_SET_NO_EXPORT);
1721 (void)Var_Subst(args->str, args->scope, args->eflags, &s); 1721 (void)Var_Subst(args->str, args->scope, args->eflags, &s);
1722 /* TODO: handle errors */ 1722 /* TODO: handle errors */
1723 1723
1724 DEBUG4(VAR, "ModifyWord_Loop: " 1724 DEBUG4(VAR, "ModifyWord_Loop: "
1725 "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n", 1725 "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n",
1726 word, args->tvar, args->str, s); 1726 word, args->tvar, args->str, s);
1727 1727
1728 if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n')) 1728 if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1729 buf->needSep = FALSE; 1729 buf->needSep = FALSE;
1730 SepBuf_AddStr(buf, s); 1730 SepBuf_AddStr(buf, s);
1731 free(s); 1731 free(s);
1732} 1732}
1733 1733
1734 1734
1735/* 1735/*
1736 * The :[first..last] modifier selects words from the expression. 1736 * The :[first..last] modifier selects words from the expression.
1737 * It can also reverse the words. 1737 * It can also reverse the words.
1738 */ 1738 */
1739static char * 1739static char *
1740VarSelectWords(const char *str, int first, int last, 1740VarSelectWords(const char *str, int first, int last,
1741 char sep, Boolean oneBigWord) 1741 char sep, Boolean oneBigWord)
1742{ 1742{
1743 Words words; 1743 Words words;
1744 int len, start, end, step; 1744 int len, start, end, step;
1745 int i; 1745 int i;
1746 1746
1747 SepBuf buf; 1747 SepBuf buf;
1748 SepBuf_Init(&buf, sep); 1748 SepBuf_Init(&buf, sep);
1749 1749
1750 if (oneBigWord) { 1750 if (oneBigWord) {
1751 /* fake what Str_Words() would do if there were only one word */ 1751 /* fake what Str_Words() would do if there were only one word */
1752 words.len = 1; 1752 words.len = 1;
1753 words.words = bmake_malloc( 1753 words.words = bmake_malloc(
1754 (words.len + 1) * sizeof(words.words[0])); 1754 (words.len + 1) * sizeof(words.words[0]));
1755 words.freeIt = bmake_strdup(str); 1755 words.freeIt = bmake_strdup(str);
1756 words.words[0] = words.freeIt; 1756 words.words[0] = words.freeIt;
1757 words.words[1] = NULL; 1757 words.words[1] = NULL;
1758 } else { 1758 } else {
1759 words = Str_Words(str, FALSE); 1759 words = Str_Words(str, FALSE);
1760 } 1760 }
1761 1761
1762 /* 1762 /*
1763 * Now sanitize the given range. If first or last are negative, 1763 * Now sanitize the given range. If first or last are negative,
1764 * convert them to the positive equivalents (-1 gets converted to len, 1764 * convert them to the positive equivalents (-1 gets converted to len,
1765 * -2 gets converted to (len - 1), etc.). 1765 * -2 gets converted to (len - 1), etc.).
1766 */ 1766 */
1767 len = (int)words.len; 1767 len = (int)words.len;
1768 if (first < 0) 1768 if (first < 0)
1769 first += len + 1; 1769 first += len + 1;
1770 if (last < 0) 1770 if (last < 0)
1771 last += len + 1; 1771 last += len + 1;
1772 1772
1773 /* We avoid scanning more of the list than we need to. */ 1773 /* We avoid scanning more of the list than we need to. */
1774 if (first > last) { 1774 if (first > last) {
1775 start = (first > len ? len : first) - 1; 1775 start = (first > len ? len : first) - 1;
1776 end = last < 1 ? 0 : last - 1; 1776 end = last < 1 ? 0 : last - 1;
1777 step = -1; 1777 step = -1;
1778 } else { 1778 } else {
1779 start = first < 1 ? 0 : first - 1; 1779 start = first < 1 ? 0 : first - 1;
1780 end = last > len ? len : last; 1780 end = last > len ? len : last;
1781 step = 1; 1781 step = 1;
1782 } 1782 }
1783 1783
1784 for (i = start; (step < 0) == (i >= end); i += step) { 1784 for (i = start; (step < 0) == (i >= end); i += step) {
1785 SepBuf_AddStr(&buf, words.words[i]); 1785 SepBuf_AddStr(&buf, words.words[i]);
1786 SepBuf_Sep(&buf); 1786 SepBuf_Sep(&buf);
1787 } 1787 }
1788 1788
1789 Words_Free(words); 1789 Words_Free(words);
1790 1790
1791 return SepBuf_DoneData(&buf); 1791 return SepBuf_DoneData(&buf);
1792} 1792}
1793 1793
1794 1794
1795/* 1795/*
1796 * Callback for ModifyWords to implement the :tA modifier. 1796 * Callback for ModifyWords to implement the :tA modifier.
1797 * Replace each word with the result of realpath() if successful. 1797 * Replace each word with the result of realpath() if successful.
1798 */ 1798 */
1799/*ARGSUSED*/ 1799/*ARGSUSED*/
1800static void 1800static void
1801ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 1801ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1802{ 1802{
1803 struct stat st; 1803 struct stat st;
1804 char rbuf[MAXPATHLEN]; 1804 char rbuf[MAXPATHLEN];
1805 1805
1806 const char *rp = cached_realpath(word, rbuf); 1806 const char *rp = cached_realpath(word, rbuf);
1807 if (rp != NULL && *rp == '/' && stat(rp, &st) == 0) 1807 if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1808 word = rp; 1808 word = rp;
1809 1809
1810 SepBuf_AddStr(buf, word); 1810 SepBuf_AddStr(buf, word);
1811} 1811}
1812 1812
1813 1813
1814static char * 1814static char *
1815Words_JoinFree(Words words) 1815Words_JoinFree(Words words)
1816{ 1816{
1817 Buffer buf; 1817 Buffer buf;
1818 size_t i; 1818 size_t i;
1819 1819
1820 Buf_Init(&buf); 1820 Buf_Init(&buf);
1821 1821
1822 for (i = 0; i < words.len; i++) { 1822 for (i = 0; i < words.len; i++) {
1823 if (i != 0) { 1823 if (i != 0) {
1824 /* XXX: Use st->sep instead of ' ', for consistency. */ 1824 /* XXX: Use st->sep instead of ' ', for consistency. */
1825 Buf_AddByte(&buf, ' '); 1825 Buf_AddByte(&buf, ' ');
1826 } 1826 }
1827 Buf_AddStr(&buf, words.words[i]); 1827 Buf_AddStr(&buf, words.words[i]);
1828 } 1828 }
1829 1829
1830 Words_Free(words); 1830 Words_Free(words);
1831 1831
1832 return Buf_DoneData(&buf); 1832 return Buf_DoneData(&buf);
1833} 1833}
1834 1834
1835/* Remove adjacent duplicate words. */ 1835/* Remove adjacent duplicate words. */
1836static char * 1836static char *
1837VarUniq(const char *str) 1837VarUniq(const char *str)
1838{ 1838{
1839 Words words = Str_Words(str, FALSE); 1839 Words words = Str_Words(str, FALSE);
1840 1840
1841 if (words.len > 1) { 1841 if (words.len > 1) {
1842 size_t i, j; 1842 size_t i, j;
1843 for (j = 0, i = 1; i < words.len; i++) 1843 for (j = 0, i = 1; i < words.len; i++)
1844 if (strcmp(words.words[i], words.words[j]) != 0 && 1844 if (strcmp(words.words[i], words.words[j]) != 0 &&
1845 (++j != i)) 1845 (++j != i))
1846 words.words[j] = words.words[i]; 1846 words.words[j] = words.words[i];
1847 words.len = j + 1; 1847 words.len = j + 1;
1848 } 1848 }
1849 1849
1850 return Words_JoinFree(words); 1850 return Words_JoinFree(words);
1851} 1851}
1852 1852
1853 1853
1854/* 1854/*
1855 * Quote shell meta-characters and space characters in the string. 1855 * Quote shell meta-characters and space characters in the string.
1856 * If quoteDollar is set, also quote and double any '$' characters. 1856 * If quoteDollar is set, also quote and double any '$' characters.
1857 */ 1857 */
1858static char * 1858static char *
1859VarQuote(const char *str, Boolean quoteDollar) 1859VarQuote(const char *str, Boolean quoteDollar)
1860{ 1860{
1861 Buffer buf; 1861 Buffer buf;
1862 Buf_Init(&buf); 1862 Buf_Init(&buf);
1863 1863
1864 for (; *str != '\0'; str++) { 1864 for (; *str != '\0'; str++) {
1865 if (*str == '\n') { 1865 if (*str == '\n') {
1866 const char *newline = Shell_GetNewline(); 1866 const char *newline = Shell_GetNewline();
1867 if (newline == NULL) 1867 if (newline == NULL)
1868 newline = "\\\n"; 1868 newline = "\\\n";
1869 Buf_AddStr(&buf, newline); 1869 Buf_AddStr(&buf, newline);
1870 continue; 1870 continue;
1871 } 1871 }
1872 if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str)) 1872 if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str))
1873 Buf_AddByte(&buf, '\\'); 1873 Buf_AddByte(&buf, '\\');
1874 Buf_AddByte(&buf, *str); 1874 Buf_AddByte(&buf, *str);
1875 if (quoteDollar && *str == '$') 1875 if (quoteDollar && *str == '$')
1876 Buf_AddStr(&buf, "\\$"); 1876 Buf_AddStr(&buf, "\\$");
1877 } 1877 }
1878 1878
1879 return Buf_DoneData(&buf); 1879 return Buf_DoneData(&buf);
1880} 1880}
1881 1881
1882/* 1882/*
1883 * Compute the 32-bit hash of the given string, using the MurmurHash3 1883 * Compute the 32-bit hash of the given string, using the MurmurHash3
1884 * algorithm. Output is encoded as 8 hex digits, in Little Endian order. 1884 * algorithm. Output is encoded as 8 hex digits, in Little Endian order.
1885 */ 1885 */
1886static char * 1886static char *
1887VarHash(const char *str) 1887VarHash(const char *str)
1888{ 1888{
1889 static const char hexdigits[16] = "0123456789abcdef"; 1889 static const char hexdigits[16] = "0123456789abcdef";
1890 const unsigned char *ustr = (const unsigned char *)str; 1890 const unsigned char *ustr = (const unsigned char *)str;
1891 1891
1892 uint32_t h = 0x971e137bU; 1892 uint32_t h = 0x971e137bU;
1893 uint32_t c1 = 0x95543787U; 1893 uint32_t c1 = 0x95543787U;
1894 uint32_t c2 = 0x2ad7eb25U; 1894 uint32_t c2 = 0x2ad7eb25U;
1895 size_t len2 = strlen(str); 1895 size_t len2 = strlen(str);
1896 1896
1897 char *buf; 1897 char *buf;
1898 size_t i; 1898 size_t i;
1899 1899
1900 size_t len; 1900 size_t len;
1901 for (len = len2; len != 0;) { 1901 for (len = len2; len != 0;) {
1902 uint32_t k = 0; 1902 uint32_t k = 0;
1903 switch (len) { 1903 switch (len) {
1904 default: 1904 default:
1905 k = ((uint32_t)ustr[3] << 24) | 1905 k = ((uint32_t)ustr[3] << 24) |
1906 ((uint32_t)ustr[2] << 16) | 1906 ((uint32_t)ustr[2] << 16) |
1907 ((uint32_t)ustr[1] << 8) | 1907 ((uint32_t)ustr[1] << 8) |
1908 (uint32_t)ustr[0]; 1908 (uint32_t)ustr[0];
1909 len -= 4; 1909 len -= 4;
1910 ustr += 4; 1910 ustr += 4;
1911 break; 1911 break;
1912 case 3: 1912 case 3:
1913 k |= (uint32_t)ustr[2] << 16; 1913 k |= (uint32_t)ustr[2] << 16;
1914 /* FALLTHROUGH */ 1914 /* FALLTHROUGH */
1915 case 2: 1915 case 2:
1916 k |= (uint32_t)ustr[1] << 8; 1916 k |= (uint32_t)ustr[1] << 8;
1917 /* FALLTHROUGH */ 1917 /* FALLTHROUGH */
1918 case 1: 1918 case 1:
1919 k |= (uint32_t)ustr[0]; 1919 k |= (uint32_t)ustr[0];
1920 len = 0; 1920 len = 0;
1921 } 1921 }
1922 c1 = c1 * 5 + 0x7b7d159cU; 1922 c1 = c1 * 5 + 0x7b7d159cU;
1923 c2 = c2 * 5 + 0x6bce6396U; 1923 c2 = c2 * 5 + 0x6bce6396U;
1924 k *= c1; 1924 k *= c1;
1925 k = (k << 11) ^ (k >> 21); 1925 k = (k << 11) ^ (k >> 21);
1926 k *= c2; 1926 k *= c2;
1927 h = (h << 13) ^ (h >> 19); 1927 h = (h << 13) ^ (h >> 19);
1928 h = h * 5 + 0x52dce729U; 1928 h = h * 5 + 0x52dce729U;
1929 h ^= k; 1929 h ^= k;
1930 } 1930 }
1931 h ^= (uint32_t)len2; 1931 h ^= (uint32_t)len2;
1932 h *= 0x85ebca6b; 1932 h *= 0x85ebca6b;
1933 h ^= h >> 13; 1933 h ^= h >> 13;
1934 h *= 0xc2b2ae35; 1934 h *= 0xc2b2ae35;
1935 h ^= h >> 16; 1935 h ^= h >> 16;
1936 1936
1937 buf = bmake_malloc(9); 1937 buf = bmake_malloc(9);
1938 for (i = 0; i < 8; i++) { 1938 for (i = 0; i < 8; i++) {
1939 buf[i] = hexdigits[h & 0x0f]; 1939 buf[i] = hexdigits[h & 0x0f];
1940 h >>= 4; 1940 h >>= 4;
1941 } 1941 }
1942 buf[8] = '\0'; 1942 buf[8] = '\0';
1943 return buf; 1943 return buf;
1944} 1944}
1945 1945
1946static char * 1946static char *
1947VarStrftime(const char *fmt, Boolean zulu, time_t tim) 1947VarStrftime(const char *fmt, Boolean zulu, time_t tim)
1948{ 1948{
1949 char buf[BUFSIZ]; 1949 char buf[BUFSIZ];
1950 1950
1951 if (tim == 0) 1951 if (tim == 0)
1952 time(&tim); 1952 time(&tim);
1953 if (*fmt == '\0') 1953 if (*fmt == '\0')
1954 fmt = "%c"; 1954 fmt = "%c";
1955 strftime(buf, sizeof buf, fmt, zulu ? gmtime(&tim) : localtime(&tim)); 1955 strftime(buf, sizeof buf, fmt, zulu ? gmtime(&tim) : localtime(&tim));
1956 1956
1957 buf[sizeof buf - 1] = '\0'; 1957 buf[sizeof buf - 1] = '\0';
1958 return bmake_strdup(buf); 1958 return bmake_strdup(buf);
1959} 1959}
1960 1960
1961/* 1961/*
1962 * The ApplyModifier functions take an expression that is being evaluated. 1962 * The ApplyModifier functions take an expression that is being evaluated.
1963 * Their task is to apply a single modifier to the expression. This involves 1963 * Their task is to apply a single modifier to the expression. This involves
1964 * parsing the modifier, evaluating it and finally updating the value of the 1964 * parsing the modifier, evaluating it and finally updating the value of the
1965 * expression. 1965 * expression.
1966 * 1966 *
1967 * Parsing the modifier 1967 * Parsing the modifier
1968 * 1968 *
1969 * If parsing succeeds, the parsing position *pp is updated to point to the 1969 * If parsing succeeds, the parsing position *pp is updated to point to the
1970 * first character following the modifier, which typically is either ':' or 1970 * first character following the modifier, which typically is either ':' or
1971 * st->endc. The modifier doesn't have to check for this delimiter character, 1971 * st->endc. The modifier doesn't have to check for this delimiter character,
1972 * this is done by ApplyModifiers. 1972 * this is done by ApplyModifiers.
1973 * 1973 *
1974 * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not 1974 * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not
1975 * need to be followed by a ':' or endc; this was an unintended mistake. 1975 * need to be followed by a ':' or endc; this was an unintended mistake.
1976 * 1976 *
1977 * If parsing fails because of a missing delimiter (as in the :S, :C or :@ 1977 * If parsing fails because of a missing delimiter (as in the :S, :C or :@
1978 * modifiers), return AMR_CLEANUP. 1978 * modifiers), return AMR_CLEANUP.
1979 * 1979 *
1980 * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to 1980 * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
1981 * try the SysV modifier ${VAR:from=to} as fallback. This should only be 1981 * try the SysV modifier ${VAR:from=to} as fallback. This should only be
1982 * done as long as there have been no side effects from evaluating nested 1982 * done as long as there have been no side effects from evaluating nested
1983 * variables, to avoid evaluating them more than once. In this case, the 1983 * variables, to avoid evaluating them more than once. In this case, the
1984 * parsing position may or may not be updated. (XXX: Why not? The original 1984 * parsing position may or may not be updated. (XXX: Why not? The original
1985 * parsing position is well-known in ApplyModifiers.) 1985 * parsing position is well-known in ApplyModifiers.)
1986 * 1986 *
1987 * If parsing fails and the SysV modifier ${VAR:from=to} should not be used 1987 * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
1988 * as a fallback, either issue an error message using Error or Parse_Error 1988 * as a fallback, either issue an error message using Error or Parse_Error
1989 * and then return AMR_CLEANUP, or return AMR_BAD for the default error 1989 * and then return AMR_CLEANUP, or return AMR_BAD for the default error
1990 * message. Both of these return values will stop processing the variable 1990 * message. Both of these return values will stop processing the variable
1991 * expression. (XXX: As of 2020-08-23, evaluation of the whole string 1991 * expression. (XXX: As of 2020-08-23, evaluation of the whole string
1992 * continues nevertheless after skipping a few bytes, which essentially is 1992 * continues nevertheless after skipping a few bytes, which essentially is
1993 * undefined behavior. Not in the sense of C, but still the resulting string 1993 * undefined behavior. Not in the sense of C, but still the resulting string
1994 * is garbage.) 1994 * is garbage.)
1995 * 1995 *
1996 * Evaluating the modifier 1996 * Evaluating the modifier
1997 * 1997 *
1998 * After parsing, the modifier is evaluated. The side effects from evaluating 1998 * After parsing, the modifier is evaluated. The side effects from evaluating
1999 * nested variable expressions in the modifier text often already happen 1999 * nested variable expressions in the modifier text often already happen
2000 * during parsing though. For most modifiers this doesn't matter since their 2000 * during parsing though. For most modifiers this doesn't matter since their
2001 * only noticeable effect is that the update the value of the expression. 2001 * only noticeable effect is that the update the value of the expression.
2002 * Some modifiers such as ':sh' or '::=' have noticeable side effects though. 2002 * Some modifiers such as ':sh' or '::=' have noticeable side effects though.
2003 * 2003 *
2004 * Evaluating the modifier usually takes the current value of the variable 2004 * Evaluating the modifier usually takes the current value of the variable
2005 * expression from st->expr->value, or the variable name from st->var->name 2005 * expression from st->expr->value, or the variable name from st->var->name
2006 * and stores the result back in expr->value via Expr_SetValueOwn or 2006 * and stores the result back in expr->value via Expr_SetValueOwn or
2007 * Expr_SetValueRefer. 2007 * Expr_SetValueRefer.
2008 * 2008 *
2009 * If evaluating fails (as of 2020-08-23), an error message is printed using 2009 * If evaluating fails (as of 2020-08-23), an error message is printed using
2010 * Error. This function has no side-effects, it really just prints the error 2010 * Error. This function has no side-effects, it really just prints the error
2011 * message. Processing the expression continues as if everything were ok. 2011 * message. Processing the expression continues as if everything were ok.
2012 * XXX: This should be fixed by adding proper error handling to Var_Subst, 2012 * XXX: This should be fixed by adding proper error handling to Var_Subst,
2013 * Var_Parse, ApplyModifiers and ModifyWords. 2013 * Var_Parse, ApplyModifiers and ModifyWords.
2014 * 2014 *
2015 * Housekeeping 2015 * Housekeeping
2016 * 2016 *
2017 * Some modifiers such as :D and :U turn undefined expressions into defined 2017 * Some modifiers such as :D and :U turn undefined expressions into defined
2018 * expressions (see Expr_Define). 2018 * expressions (see Expr_Define).
2019 * 2019 *
2020 * Some modifiers need to free some memory. 2020 * Some modifiers need to free some memory.
2021 */ 2021 */
2022 2022
2023typedef enum ExprDefined { 2023typedef enum ExprDefined {
2024 /* The variable expression is based on a regular, defined variable. */ 2024 /* The variable expression is based on a regular, defined variable. */
2025 DEF_REGULAR, 2025 DEF_REGULAR,
2026 /* The variable expression is based on an undefined variable. */ 2026 /* The variable expression is based on an undefined variable. */
2027 DEF_UNDEF, 2027 DEF_UNDEF,
2028 /* 2028 /*
2029 * The variable expression started as an undefined expression, but one 2029 * The variable expression started as an undefined expression, but one
2030 * of the modifiers (such as ':D' or ':U') has turned the expression 2030 * of the modifiers (such as ':D' or ':U') has turned the expression
2031 * from undefined to defined. 2031 * from undefined to defined.
2032 */ 2032 */
2033 DEF_DEFINED 2033 DEF_DEFINED
2034} ExprDefined; 2034} ExprDefined;
2035 2035
2036static const char *const ExprDefined_Name[] = { 2036static const char *const ExprDefined_Name[] = {
2037 "regular", 2037 "regular",
2038 "undefined", 2038 "undefined",
2039 "defined" 2039 "defined"
2040}; 2040};
2041 2041
2042/* A variable expression such as $@ or ${VAR:Mpattern:Q}. */ 2042/* A variable expression such as $@ or ${VAR:Mpattern:Q}. */
2043typedef struct Expr { 2043typedef struct Expr {
2044 Var *var; 2044 Var *var;
2045 FStr value; 2045 FStr value;
2046 VarEvalFlags const eflags; 2046 VarEvalFlags const eflags;
2047 GNode *const scope; 2047 GNode *const scope;
2048 ExprDefined defined; 2048 ExprDefined defined;
2049} Expr; 2049} Expr;
2050 2050
2051/* 2051/*
2052 * Data that is used when applying a chain of modifiers to an expression. 2052 * Data that is used when applying a chain of modifiers to an expression.
2053 * For indirect modifiers, the effects of this data stops after the indirect 2053 * For indirect modifiers, the effects of this data stops after the indirect
2054 * modifiers have been applies. 2054 * modifiers have been applies.
2055 * 2055 *
2056 * It may or may not be intended that 'status' has scope Expr while 'sep' and 2056 * It may or may not be intended that 'status' has scope Expr while 'sep' and
2057 * 'oneBigWord' have smaller scope, terminating at the end of a chain of 2057 * 'oneBigWord' have smaller scope, terminating at the end of a chain of
2058 * indirect modifiers. 2058 * indirect modifiers.
2059 * 2059 *
2060 * See varmod-indirect.mk. 2060 * See varmod-indirect.mk.
2061 */ 2061 */
2062typedef struct ApplyModifiersState { 2062typedef struct ApplyModifiersState {
2063 Expr *expr; 2063 Expr *expr;
2064 /* '\0' or '{' or '(' */ 2064 /* '\0' or '{' or '(' */
2065 const char startc; 2065 const char startc;
2066 /* '\0' or '}' or ')' */ 2066 /* '\0' or '}' or ')' */
2067 const char endc; 2067 const char endc;
2068 /* Word separator in expansions (see the :ts modifier). */ 2068 /* Word separator in expansions (see the :ts modifier). */
2069 char sep; 2069 char sep;
2070 /* 2070 /*
2071 * TRUE if some modifiers that otherwise split the variable value 2071 * TRUE if some modifiers that otherwise split the variable value
2072 * into words, like :S and :C, treat the variable value as a single 2072 * into words, like :S and :C, treat the variable value as a single
2073 * big word, possibly containing spaces. 2073 * big word, possibly containing spaces.
2074 */ 2074 */
2075 Boolean oneBigWord; 2075 Boolean oneBigWord;
2076} ApplyModifiersState; 2076} ApplyModifiersState;
2077 2077
2078static void 2078static void
2079Expr_Define(Expr *expr) 2079Expr_Define(Expr *expr)
2080{ 2080{
2081 if (expr->defined == DEF_UNDEF) 2081 if (expr->defined == DEF_UNDEF)
2082 expr->defined = DEF_DEFINED; 2082 expr->defined = DEF_DEFINED;
2083} 2083}
2084 2084
2085static void 2085static void
2086Expr_SetValueOwn(Expr *expr, char *value) 2086Expr_SetValueOwn(Expr *expr, char *value)
2087{ 2087{
2088 FStr_Done(&expr->value); 2088 FStr_Done(&expr->value);
2089 expr->value = FStr_InitOwn(value); 2089 expr->value = FStr_InitOwn(value);
2090} 2090}
2091 2091
2092static void 2092static void
2093Expr_SetValueRefer(Expr *expr, const char *value) 2093Expr_SetValueRefer(Expr *expr, const char *value)
2094{ 2094{
2095 FStr_Done(&expr->value); 2095 FStr_Done(&expr->value);
2096 expr->value = FStr_InitRefer(value); 2096 expr->value = FStr_InitRefer(value);
2097} 2097}
2098 2098
2099typedef enum ApplyModifierResult { 2099typedef enum ApplyModifierResult {
2100 /* Continue parsing */ 2100 /* Continue parsing */
2101 AMR_OK, 2101 AMR_OK,
2102 /* Not a match, try other modifiers as well. */ 2102 /* Not a match, try other modifiers as well. */
2103 AMR_UNKNOWN, 2103 AMR_UNKNOWN,
2104 /* Error out with "Bad modifier" message. */ 2104 /* Error out with "Bad modifier" message. */
2105 AMR_BAD, 2105 AMR_BAD,
2106 /* Error out without the standard error message. */ 2106 /* Error out without the standard error message. */
2107 AMR_CLEANUP 2107 AMR_CLEANUP
2108} ApplyModifierResult; 2108} ApplyModifierResult;
2109 2109
2110/* 2110/*
2111 * Allow backslashes to escape the delimiter, $, and \, but don't touch other 2111 * Allow backslashes to escape the delimiter, $, and \, but don't touch other
2112 * backslashes. 2112 * backslashes.
2113 */ 2113 */
2114static Boolean 2114static Boolean
2115IsEscapedModifierPart(const char *p, char delim, 2115IsEscapedModifierPart(const char *p, char delim,
2116 struct ModifyWord_SubstArgs *subst) 2116 struct ModifyWord_SubstArgs *subst)
2117{ 2117{
2118 if (p[0] != '\\') 2118 if (p[0] != '\\')
2119 return FALSE; 2119 return FALSE;
2120 if (p[1] == delim || p[1] == '\\' || p[1] == '$') 2120 if (p[1] == delim || p[1] == '\\' || p[1] == '$')
2121 return TRUE; 2121 return TRUE;
2122 return p[1] == '&' && subst != NULL; 2122 return p[1] == '&' && subst != NULL;
2123} 2123}
2124 2124
2125/* See ParseModifierPart */ 2125/* See ParseModifierPart */
2126static VarParseResult 2126static VarParseResult
2127ParseModifierPartSubst( 2127ParseModifierPartSubst(
2128 const char **pp, 2128 const char **pp,
2129 char delim, 2129 char delim,
2130 VarEvalFlags eflags, 2130 VarEvalFlags eflags,
2131 ApplyModifiersState *st, 2131 ApplyModifiersState *st,
2132 char **out_part, 2132 char **out_part,
2133 /* Optionally stores the length of the returned string, just to save 2133 /* Optionally stores the length of the returned string, just to save
2134 * another strlen call. */ 2134 * another strlen call. */
2135 size_t *out_length, 2135 size_t *out_length,
2136 /* For the first part of the :S modifier, sets the VARP_ANCHOR_END flag 2136 /* For the first part of the :S modifier, sets the VARP_ANCHOR_END flag
2137 * if the last character of the pattern is a $. */ 2137 * if the last character of the pattern is a $. */
2138 VarPatternFlags *out_pflags, 2138 VarPatternFlags *out_pflags,
2139 /* For the second part of the :S modifier, allow ampersands to be 2139 /* For the second part of the :S modifier, allow ampersands to be
2140 * escaped and replace unescaped ampersands with subst->lhs. */ 2140 * escaped and replace unescaped ampersands with subst->lhs. */
2141 struct ModifyWord_SubstArgs *subst 2141 struct ModifyWord_SubstArgs *subst
2142) 2142)
2143{ 2143{
2144 Buffer buf; 2144 Buffer buf;
2145 const char *p; 2145 const char *p;
2146 2146
2147 Buf_Init(&buf); 2147 Buf_Init(&buf);
2148 2148
2149 /* 2149 /*
2150 * Skim through until the matching delimiter is found; pick up 2150 * Skim through until the matching delimiter is found; pick up
2151 * variable expressions on the way. 2151 * variable expressions on the way.
2152 */ 2152 */
2153 p = *pp; 2153 p = *pp;
2154 while (*p != '\0' && *p != delim) { 2154 while (*p != '\0' && *p != delim) {
2155 const char *varstart; 2155 const char *varstart;
2156 2156
2157 if (IsEscapedModifierPart(p, delim, subst)) { 2157 if (IsEscapedModifierPart(p, delim, subst)) {
2158 Buf_AddByte(&buf, p[1]); 2158 Buf_AddByte(&buf, p[1]);
2159 p += 2; 2159 p += 2;
2160 continue; 2160 continue;
2161 } 2161 }
2162 2162
2163 if (*p != '$') { /* Unescaped, simple text */ 2163 if (*p != '$') { /* Unescaped, simple text */
2164 if (subst != NULL && *p == '&') 2164 if (subst != NULL && *p == '&')
2165 Buf_AddBytes(&buf, subst->lhs, subst->lhsLen); 2165 Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
2166 else 2166 else
2167 Buf_AddByte(&buf, *p); 2167 Buf_AddByte(&buf, *p);
2168 p++; 2168 p++;
2169 continue; 2169 continue;
2170 } 2170 }
2171 2171
2172 if (p[1] == delim) { /* Unescaped $ at end of pattern */ 2172 if (p[1] == delim) { /* Unescaped $ at end of pattern */
2173 if (out_pflags != NULL) 2173 if (out_pflags != NULL)
2174 out_pflags->anchorEnd = TRUE; 2174 out_pflags->anchorEnd = TRUE;
2175 else 2175 else
2176 Buf_AddByte(&buf, *p); 2176 Buf_AddByte(&buf, *p);
2177 p++; 2177 p++;
2178 continue; 2178 continue;
2179 } 2179 }
2180 2180
2181 if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ 2181 if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */
2182 const char *nested_p = p; 2182 const char *nested_p = p;
2183 FStr nested_val; 2183 FStr nested_val;
2184 VarEvalFlags nested_eflags = 2184 VarEvalFlags nested_eflags =
2185 eflags & ~(unsigned)VARE_KEEP_DOLLAR; 2185 eflags & ~(unsigned)VARE_KEEP_DOLLAR;
2186 2186
2187 (void)Var_Parse(&nested_p, st->expr->scope, 2187 (void)Var_Parse(&nested_p, st->expr->scope,
2188 nested_eflags, &nested_val); 2188 nested_eflags, &nested_val);
2189 /* TODO: handle errors */ 2189 /* TODO: handle errors */
2190 Buf_AddStr(&buf, nested_val.str); 2190 Buf_AddStr(&buf, nested_val.str);
2191 FStr_Done(&nested_val); 2191 FStr_Done(&nested_val);
2192 p += nested_p - p; 2192 p += nested_p - p;
2193 continue; 2193 continue;
2194 } 2194 }
2195 2195
2196 /* 2196 /*
2197 * XXX: This whole block is very similar to Var_Parse without 2197 * XXX: This whole block is very similar to Var_Parse without
2198 * VARE_WANTRES. There may be subtle edge cases though that 2198 * VARE_WANTRES. There may be subtle edge cases though that
2199 * are not yet covered in the unit tests and that are parsed 2199 * are not yet covered in the unit tests and that are parsed
2200 * differently, depending on whether they are evaluated or 2200 * differently, depending on whether they are evaluated or
2201 * not. 2201 * not.
2202 * 2202 *
2203 * This subtle difference is not documented in the manual 2203 * This subtle difference is not documented in the manual
2204 * page, neither is the difference between parsing :D and 2204 * page, neither is the difference between parsing :D and
2205 * :M documented. No code should ever depend on these 2205 * :M documented. No code should ever depend on these
2206 * details, but who knows. 2206 * details, but who knows.
2207 */ 2207 */
2208 2208
2209 varstart = p; /* Nested variable, only parsed */ 2209 varstart = p; /* Nested variable, only parsed */
2210 if (p[1] == '(' || p[1] == '{') { 2210 if (p[1] == '(' || p[1] == '{') {
2211 /* 2211 /*
2212 * Find the end of this variable reference 2212 * Find the end of this variable reference
2213 * and suck it in without further ado. 2213 * and suck it in without further ado.
2214 * It will be interpreted later. 2214 * It will be interpreted later.
2215 */ 2215 */
2216 char startc = p[1]; 2216 char startc = p[1];
2217 int endc = startc == '(' ? ')' : '}'; 2217 int endc = startc == '(' ? ')' : '}';
2218 int depth = 1; 2218 int depth = 1;
2219 2219
2220 for (p += 2; *p != '\0' && depth > 0; p++) { 2220 for (p += 2; *p != '\0' && depth > 0; p++) {
2221 if (p[-1] != '\\') { 2221 if (p[-1] != '\\') {
2222 if (*p == startc) 2222 if (*p == startc)
2223 depth++; 2223 depth++;
2224 if (*p == endc) 2224 if (*p == endc)
2225 depth--; 2225 depth--;
2226 } 2226 }
2227 } 2227 }
2228 Buf_AddBytesBetween(&buf, varstart, p); 2228 Buf_AddBytesBetween(&buf, varstart, p);
2229 } else { 2229 } else {
2230 Buf_AddByte(&buf, *varstart); 2230 Buf_AddByte(&buf, *varstart);
2231 p++; 2231 p++;
2232 } 2232 }
2233 } 2233 }
2234 2234
2235 if (*p != delim) { 2235 if (*p != delim) {
2236 *pp = p; 2236 *pp = p;
2237 Error("Unfinished modifier for \"%s\" ('%c' missing)", 2237 Error("Unfinished modifier for \"%s\" ('%c' missing)",
2238 st->expr->var->name.str, delim); 2238 st->expr->var->name.str, delim);
2239 *out_part = NULL; 2239 *out_part = NULL;
2240 return VPR_ERR; 2240 return VPR_ERR;
2241 } 2241 }
2242 2242
2243 *pp = p + 1; 2243 *pp = p + 1;
2244 if (out_length != NULL) 2244 if (out_length != NULL)
2245 *out_length = buf.len; 2245 *out_length = buf.len;
2246 2246
2247 *out_part = Buf_DoneData(&buf); 2247 *out_part = Buf_DoneData(&buf);
2248 DEBUG1(VAR, "Modifier part: \"%s\"\n", *out_part); 2248 DEBUG1(VAR, "Modifier part: \"%s\"\n", *out_part);
2249 return VPR_OK; 2249 return VPR_OK;
2250} 2250}
2251 2251
2252/* 2252/*
2253 * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or 2253 * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
2254 * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and 2254 * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
2255 * including the next unescaped delimiter. The delimiter, as well as the 2255 * including the next unescaped delimiter. The delimiter, as well as the
2256 * backslash or the dollar, can be escaped with a backslash. 2256 * backslash or the dollar, can be escaped with a backslash.
2257 * 2257 *
2258 * Return the parsed (and possibly expanded) string, or NULL if no delimiter 2258 * Return the parsed (and possibly expanded) string, or NULL if no delimiter
2259 * was found. On successful return, the parsing position pp points right 2259 * was found. On successful return, the parsing position pp points right
2260 * after the delimiter. The delimiter is not included in the returned 2260 * after the delimiter. The delimiter is not included in the returned
2261 * value though. 2261 * value though.
2262 */ 2262 */
2263static VarParseResult 2263static VarParseResult
2264ParseModifierPart( 2264ParseModifierPart(
2265 /* The parsing position, updated upon return */ 2265 /* The parsing position, updated upon return */
2266 const char **pp, 2266 const char **pp,
2267 /* Parsing stops at this delimiter */ 2267 /* Parsing stops at this delimiter */
2268 char delim, 2268 char delim,
2269 /* Flags for evaluating nested variables; if VARE_WANTRES is not set, 2269 /* Flags for evaluating nested variables; if VARE_WANTRES is not set,
2270 * the text is only parsed. */ 2270 * the text is only parsed. */
2271 VarEvalFlags eflags, 2271 VarEvalFlags eflags,
2272 ApplyModifiersState *st, 2272 ApplyModifiersState *st,
2273 char **out_part 2273 char **out_part
2274) 2274)
2275{ 2275{
2276 return ParseModifierPartSubst(pp, delim, eflags, st, out_part, 2276 return ParseModifierPartSubst(pp, delim, eflags, st, out_part,
2277 NULL, NULL, NULL); 2277 NULL, NULL, NULL);
2278} 2278}
2279 2279
2280MAKE_INLINE Boolean 2280MAKE_INLINE Boolean
2281IsDelimiter(char ch, const ApplyModifiersState *st) 2281IsDelimiter(char ch, const ApplyModifiersState *st)
2282{ 2282{
2283 return ch == ':' || ch == st->endc; 2283 return ch == ':' || ch == st->endc;
2284} 2284}
2285 2285
2286/* Test whether mod starts with modname, followed by a delimiter. */ 2286/* Test whether mod starts with modname, followed by a delimiter. */
2287MAKE_INLINE Boolean 2287MAKE_INLINE Boolean
2288ModMatch(const char *mod, const char *modname, const ApplyModifiersState *st) 2288ModMatch(const char *mod, const char *modname, const ApplyModifiersState *st)
2289{ 2289{
2290 size_t n = strlen(modname); 2290 size_t n = strlen(modname);
2291 return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], st); 2291 return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], st);
2292} 2292}
2293 2293
2294/* Test whether mod starts with modname, followed by a delimiter or '='. */ 2294/* Test whether mod starts with modname, followed by a delimiter or '='. */
2295MAKE_INLINE Boolean 2295MAKE_INLINE Boolean
2296ModMatchEq(const char *mod, const char *modname, const ApplyModifiersState *st) 2296ModMatchEq(const char *mod, const char *modname, const ApplyModifiersState *st)
2297{ 2297{
2298 size_t n = strlen(modname); 2298 size_t n = strlen(modname);
2299 return strncmp(mod, modname, n) == 0 && 2299 return strncmp(mod, modname, n) == 0 &&
2300 (IsDelimiter(mod[n], st) || mod[n] == '='); 2300 (IsDelimiter(mod[n], st) || mod[n] == '=');
2301} 2301}
2302 2302
2303static Boolean 2303static Boolean
2304TryParseIntBase0(const char **pp, int *out_num) 2304TryParseIntBase0(const char **pp, int *out_num)
2305{ 2305{
2306 char *end; 2306 char *end;
2307 long n; 2307 long n;
2308 2308
2309 errno = 0; 2309 errno = 0;
2310 n = strtol(*pp, &end, 0); 2310 n = strtol(*pp, &end, 0);
2311 if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE) 2311 if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
2312 return FALSE; 2312 return FALSE;
2313 if (n < INT_MIN || n > INT_MAX) 2313 if (n < INT_MIN || n > INT_MAX)
2314 return FALSE; 2314 return FALSE;
2315 2315
2316 *pp = end; 2316 *pp = end;
2317 *out_num = (int)n; 2317 *out_num = (int)n;
2318 return TRUE; 2318 return TRUE;
2319} 2319}
2320 2320
2321static Boolean 2321static Boolean
2322TryParseSize(const char **pp, size_t *out_num) 2322TryParseSize(const char **pp, size_t *out_num)
2323{ 2323{
2324 char *end; 2324 char *end;
2325 unsigned long n; 2325 unsigned long n;
2326 2326
2327 if (!ch_isdigit(**pp)) 2327 if (!ch_isdigit(**pp))
2328 return FALSE; 2328 return FALSE;
2329 2329
2330 errno = 0; 2330 errno = 0;
2331 n = strtoul(*pp, &end, 10); 2331 n = strtoul(*pp, &end, 10);
2332 if (n == ULONG_MAX && errno == ERANGE) 2332 if (n == ULONG_MAX && errno == ERANGE)
2333 return FALSE; 2333 return FALSE;
2334 if (n > SIZE_MAX) 2334 if (n > SIZE_MAX)
2335 return FALSE; 2335 return FALSE;
2336 2336
2337 *pp = end; 2337 *pp = end;
2338 *out_num = (size_t)n; 2338 *out_num = (size_t)n;
2339 return TRUE; 2339 return TRUE;
2340} 2340}
2341 2341
2342static Boolean 2342static Boolean
2343TryParseChar(const char **pp, int base, char *out_ch) 2343TryParseChar(const char **pp, int base, char *out_ch)
2344{ 2344{
2345 char *end; 2345 char *end;
2346 unsigned long n; 2346 unsigned long n;
2347 2347
2348 if (!ch_isalnum(**pp)) 2348 if (!ch_isalnum(**pp))
2349 return FALSE; 2349 return FALSE;
2350 2350
2351 errno = 0; 2351 errno = 0;
2352 n = strtoul(*pp, &end, base); 2352 n = strtoul(*pp, &end, base);
2353 if (n == ULONG_MAX && errno == ERANGE) 2353 if (n == ULONG_MAX && errno == ERANGE)
2354 return FALSE; 2354 return FALSE;
2355 if (n > UCHAR_MAX) 2355 if (n > UCHAR_MAX)
2356 return FALSE; 2356 return FALSE;
2357 2357
2358 *pp = end; 2358 *pp = end;
2359 *out_ch = (char)n; 2359 *out_ch = (char)n;
2360 return TRUE; 2360 return TRUE;
2361} 2361}
2362 2362
2363/* 2363/*
2364 * Modify each word of the expression using the given function and place the 2364 * Modify each word of the expression using the given function and place the
2365 * result back in the expression. 2365 * result back in the expression.
2366 */ 2366 */
2367static void 2367static void
2368ModifyWords(ApplyModifiersState *st, 2368ModifyWords(ApplyModifiersState *st,
2369 ModifyWordProc modifyWord, void *modifyWord_args, 2369 ModifyWordProc modifyWord, void *modifyWord_args,
2370 Boolean oneBigWord) 2370 Boolean oneBigWord)
2371{ 2371{
2372 Expr *expr = st->expr; 2372 Expr *expr = st->expr;
2373 const char *val = expr->value.str; 2373 const char *val = expr->value.str;
2374 SepBuf result; 2374 SepBuf result;
2375 Words words; 2375 Words words;
2376 size_t i; 2376 size_t i;
2377 2377
2378 if (oneBigWord) { 2378 if (oneBigWord) {
2379 SepBuf_Init(&result, st->sep); 2379 SepBuf_Init(&result, st->sep);
2380 modifyWord(val, &result, modifyWord_args); 2380 modifyWord(val, &result, modifyWord_args);
2381 goto done; 2381 goto done;
2382 } 2382 }
2383 2383
2384 words = Str_Words(val, FALSE); 2384 words = Str_Words(val, FALSE);
2385 2385
2386 DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n", 2386 DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n",
2387 val, (unsigned)words.len); 2387 val, (unsigned)words.len);
2388 2388
2389 SepBuf_Init(&result, st->sep); 2389 SepBuf_Init(&result, st->sep);
2390 for (i = 0; i < words.len; i++) { 2390 for (i = 0; i < words.len; i++) {
2391 modifyWord(words.words[i], &result, modifyWord_args); 2391 modifyWord(words.words[i], &result, modifyWord_args);
2392 if (result.buf.len > 0) 2392 if (result.buf.len > 0)
2393 SepBuf_Sep(&result); 2393 SepBuf_Sep(&result);
2394 } 2394 }
2395 2395
2396 Words_Free(words); 2396 Words_Free(words);
2397 2397
2398done: 2398done:
2399 Expr_SetValueOwn(expr, SepBuf_DoneData(&result)); 2399 Expr_SetValueOwn(expr, SepBuf_DoneData(&result));
2400} 2400}
2401 2401
2402/* :@var@...${var}...@ */ 2402/* :@var@...${var}...@ */
2403static ApplyModifierResult 2403static ApplyModifierResult
2404ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) 2404ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
2405{ 2405{
2406 Expr *expr = st->expr; 2406 Expr *expr = st->expr;
2407 struct ModifyWord_LoopArgs args; 2407 struct ModifyWord_LoopArgs args;
2408 char prev_sep; 2408 char prev_sep;
2409 VarParseResult res; 2409 VarParseResult res;
2410 2410
2411 args.scope = expr->scope; 2411 args.scope = expr->scope;
2412 2412
2413 (*pp)++; /* Skip the first '@' */ 2413 (*pp)++; /* Skip the first '@' */
2414 res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.tvar); 2414 res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.tvar);
2415 if (res != VPR_OK) 2415 if (res != VPR_OK)
2416 return AMR_CLEANUP; 2416 return AMR_CLEANUP;
2417 if (opts.strict && strchr(args.tvar, '$') != NULL) { 2417 if (opts.strict && strchr(args.tvar, '$') != NULL) {
2418 Parse_Error(PARSE_FATAL, 2418 Parse_Error(PARSE_FATAL,
2419 "In the :@ modifier of \"%s\", the variable name \"%s\" " 2419 "In the :@ modifier of \"%s\", the variable name \"%s\" "
2420 "must not contain a dollar.", 2420 "must not contain a dollar.",
2421 expr->var->name.str, args.tvar); 2421 expr->var->name.str, args.tvar);
2422 return AMR_CLEANUP; 2422 return AMR_CLEANUP;
2423 } 2423 }
2424 2424
2425 res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.str); 2425 res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.str);
2426 if (res != VPR_OK) 2426 if (res != VPR_OK)
2427 return AMR_CLEANUP; 2427 return AMR_CLEANUP;
2428 2428
2429 args.eflags = expr->eflags & ~(unsigned)VARE_KEEP_DOLLAR; 2429 args.eflags = expr->eflags & ~(unsigned)VARE_KEEP_DOLLAR;
2430 prev_sep = st->sep; 2430 prev_sep = st->sep;
2431 st->sep = ' '; /* XXX: should be st->sep for consistency */ 2431 st->sep = ' '; /* XXX: should be st->sep for consistency */
2432 ModifyWords(st, ModifyWord_Loop, &args, st->oneBigWord); 2432 ModifyWords(st, ModifyWord_Loop, &args, st->oneBigWord);
2433 st->sep = prev_sep; 2433 st->sep = prev_sep;
2434 /* XXX: Consider restoring the previous variable instead of deleting. */ 2434 /* XXX: Consider restoring the previous variable instead of deleting. */
2435 /* 2435 /*
2436 * XXX: The variable name should not be expanded here, see 2436 * XXX: The variable name should not be expanded here, see
2437 * ModifyWord_Loop. 2437 * ModifyWord_Loop.
2438 */ 2438 */
2439 Var_DeleteExpand(expr->scope, args.tvar); 2439 Var_DeleteExpand(expr->scope, args.tvar);
2440 free(args.tvar); 2440 free(args.tvar);
2441 free(args.str); 2441 free(args.str);
2442 return AMR_OK; 2442 return AMR_OK;
2443} 2443}
2444 2444
2445/* :Ddefined or :Uundefined */ 2445/* :Ddefined or :Uundefined */
2446static ApplyModifierResult 2446static ApplyModifierResult
2447ApplyModifier_Defined(const char **pp, ApplyModifiersState *st) 2447ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
2448{ 2448{
2449 Expr *expr = st->expr; 2449 Expr *expr = st->expr;
2450 Buffer buf; 2450 Buffer buf;
2451 const char *p; 2451 const char *p;
2452 2452
2453 VarEvalFlags eflags = VARE_NONE; 2453 VarEvalFlags eflags = VARE_NONE;
2454 if (expr->eflags & VARE_WANTRES) 2454 if (expr->eflags & VARE_WANTRES)
2455 if ((**pp == 'D') == (expr->defined == DEF_REGULAR)) 2455 if ((**pp == 'D') == (expr->defined == DEF_REGULAR))
2456 eflags = expr->eflags; 2456 eflags = expr->eflags;
2457 2457
2458 Buf_Init(&buf); 2458 Buf_Init(&buf);
2459 p = *pp + 1; 2459 p = *pp + 1;
2460 while (!IsDelimiter(*p, st) && *p != '\0') { 2460 while (!IsDelimiter(*p, st) && *p != '\0') {
2461 2461
2462 /* XXX: This code is similar to the one in Var_Parse. 2462 /* XXX: This code is similar to the one in Var_Parse.
2463 * See if the code can be merged. 2463 * See if the code can be merged.
2464 * See also ApplyModifier_Match and ParseModifierPart. */ 2464 * See also ApplyModifier_Match and ParseModifierPart. */
2465 2465
2466 /* Escaped delimiter or other special character */ 2466 /* Escaped delimiter or other special character */
2467 /* See Buf_AddEscaped in for.c. */ 2467 /* See Buf_AddEscaped in for.c. */
2468 if (*p == '\\') { 2468 if (*p == '\\') {
2469 char c = p[1]; 2469 char c = p[1];
2470 if (IsDelimiter(c, st) || c == '$' || c == '\\') { 2470 if (IsDelimiter(c, st) || c == '$' || c == '\\') {
2471 Buf_AddByte(&buf, c); 2471 Buf_AddByte(&buf, c);
2472 p += 2; 2472 p += 2;
2473 continue; 2473 continue;
2474 } 2474 }
2475 } 2475 }
2476 2476
2477 /* Nested variable expression */ 2477 /* Nested variable expression */
2478 if (*p == '$') { 2478 if (*p == '$') {
2479 FStr nested_val; 2479 FStr nested_val;
2480 2480
2481 (void)Var_Parse(&p, expr->scope, eflags, &nested_val); 2481 (void)Var_Parse(&p, expr->scope, eflags, &nested_val);
2482 /* TODO: handle errors */ 2482 /* TODO: handle errors */
2483 Buf_AddStr(&buf, nested_val.str); 2483 Buf_AddStr(&buf, nested_val.str);
2484 FStr_Done(&nested_val); 2484 FStr_Done(&nested_val);
2485 continue; 2485 continue;
2486 } 2486 }
2487 2487
2488 /* Ordinary text */ 2488 /* Ordinary text */
2489 Buf_AddByte(&buf, *p); 2489 Buf_AddByte(&buf, *p);
2490 p++; 2490 p++;
2491 } 2491 }
2492 *pp = p; 2492 *pp = p;
2493 2493
2494 Expr_Define(expr); 2494 Expr_Define(expr);
2495 2495
2496 if (eflags & VARE_WANTRES) 2496 if (eflags & VARE_WANTRES)
2497 Expr_SetValueOwn(expr, Buf_DoneData(&buf)); 2497 Expr_SetValueOwn(expr, Buf_DoneData(&buf));
2498 else 2498 else
2499 Buf_Done(&buf); 2499 Buf_Done(&buf);
2500 2500
2501 return AMR_OK; 2501 return AMR_OK;
2502} 2502}
2503 2503
2504/* :L */ 2504/* :L */
2505static ApplyModifierResult 2505static ApplyModifierResult
2506ApplyModifier_Literal(const char **pp, ApplyModifiersState *st) 2506ApplyModifier_Literal(const char **pp, ApplyModifiersState *st)
2507{ 2507{
2508 Expr *expr = st->expr; 2508 Expr *expr = st->expr;
 2509
 2510 (*pp)++;
 2511
2509 Expr_Define(expr); 2512 Expr_Define(expr);
2510 Expr_SetValueOwn(expr, bmake_strdup(expr->var->name.str)); 2513 Expr_SetValueOwn(expr, bmake_strdup(expr->var->name.str));
2511 (*pp)++; 2514
2512 return AMR_OK; 2515 return AMR_OK;
2513} 2516}
2514 2517
2515static Boolean 2518static Boolean
2516TryParseTime(const char **pp, time_t *out_time) 2519TryParseTime(const char **pp, time_t *out_time)
2517{ 2520{
2518 char *end; 2521 char *end;
2519 unsigned long n; 2522 unsigned long n;
2520 2523
2521 if (!ch_isdigit(**pp)) 2524 if (!ch_isdigit(**pp))
2522 return FALSE; 2525 return FALSE;
2523 2526
2524 errno = 0; 2527 errno = 0;
2525 n = strtoul(*pp, &end, 10); 2528 n = strtoul(*pp, &end, 10);
2526 if (n == ULONG_MAX && errno == ERANGE) 2529 if (n == ULONG_MAX && errno == ERANGE)
2527 return FALSE; 2530 return FALSE;
2528 2531
2529 *pp = end; 2532 *pp = end;
2530 *out_time = (time_t)n; /* ignore possible truncation for now */ 2533 *out_time = (time_t)n; /* ignore possible truncation for now */
2531 return TRUE; 2534 return TRUE;
2532} 2535}
2533 2536
2534/* :gmtime */ 2537/* :gmtime */
2535static ApplyModifierResult 2538static ApplyModifierResult
2536ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st) 2539ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st)
2537{ 2540{
2538 time_t utc; 2541 time_t utc;
2539 2542
2540 const char *mod = *pp; 2543 const char *mod = *pp;
2541 if (!ModMatchEq(mod, "gmtime", st)) 2544 if (!ModMatchEq(mod, "gmtime", st))
2542 return AMR_UNKNOWN; 2545 return AMR_UNKNOWN;
2543 2546
2544 if (mod[6] == '=') { 2547 if (mod[6] == '=') {
2545 const char *p = mod + 7; 2548 const char *p = mod + 7;
2546 if (!TryParseTime(&p, &utc)) { 2549 if (!TryParseTime(&p, &utc)) {
2547 Parse_Error(PARSE_FATAL, 2550 Parse_Error(PARSE_FATAL,
2548 "Invalid time value: %s", mod + 7); 2551 "Invalid time value: %s", mod + 7);
2549 return AMR_CLEANUP; 2552 return AMR_CLEANUP;
2550 } 2553 }
2551 *pp = p; 2554 *pp = p;
2552 } else { 2555 } else {
2553 utc = 0; 2556 utc = 0;
2554 *pp = mod + 6; 2557 *pp = mod + 6;
2555 } 2558 }
 2559
2556 Expr_SetValueOwn(st->expr, 2560 Expr_SetValueOwn(st->expr,
2557 VarStrftime(st->expr->value.str, TRUE, utc)); 2561 VarStrftime(st->expr->value.str, TRUE, utc));
 2562
2558 return AMR_OK; 2563 return AMR_OK;
2559} 2564}
2560 2565
2561/* :localtime */ 2566/* :localtime */
2562static ApplyModifierResult 2567static ApplyModifierResult
2563ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st) 2568ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st)
2564{ 2569{
2565 time_t utc; 2570 time_t utc;
2566 2571
2567 const char *mod = *pp; 2572 const char *mod = *pp;
2568 if (!ModMatchEq(mod, "localtime", st)) 2573 if (!ModMatchEq(mod, "localtime", st))
2569 return AMR_UNKNOWN; 2574 return AMR_UNKNOWN;
2570 2575
2571 if (mod[9] == '=') { 2576 if (mod[9] == '=') {
2572 const char *p = mod + 10; 2577 const char *p = mod + 10;
2573 if (!TryParseTime(&p, &utc)) { 2578 if (!TryParseTime(&p, &utc)) {
2574 Parse_Error(PARSE_FATAL, 2579 Parse_Error(PARSE_FATAL,
2575 "Invalid time value: %s", mod + 10); 2580 "Invalid time value: %s", mod + 10);
2576 return AMR_CLEANUP; 2581 return AMR_CLEANUP;
2577 } 2582 }
2578 *pp = p; 2583 *pp = p;
2579 } else { 2584 } else {
2580 utc = 0; 2585 utc = 0;
2581 *pp = mod + 9; 2586 *pp = mod + 9;
2582 } 2587 }
 2588
2583 Expr_SetValueOwn(st->expr, 2589 Expr_SetValueOwn(st->expr,
2584 VarStrftime(st->expr->value.str, FALSE, utc)); 2590 VarStrftime(st->expr->value.str, FALSE, utc));
 2591
2585 return AMR_OK; 2592 return AMR_OK;
2586} 2593}
2587 2594
2588/* :hash */ 2595/* :hash */
2589static ApplyModifierResult 2596static ApplyModifierResult
2590ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) 2597ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
2591{ 2598{
2592 if (!ModMatch(*pp, "hash", st)) 2599 if (!ModMatch(*pp, "hash", st))
2593 return AMR_UNKNOWN; 2600 return AMR_UNKNOWN;
 2601 *pp += 4;
2594 2602
2595 Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str)); 2603 Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str));
2596 *pp += 4; 2604
2597 return AMR_OK; 2605 return AMR_OK;
2598} 2606}
2599 2607
2600/* :P */ 2608/* :P */
2601static ApplyModifierResult 2609static ApplyModifierResult
2602ApplyModifier_Path(const char **pp, ApplyModifiersState *st) 2610ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
2603{ 2611{
2604 Expr *expr = st->expr; 2612 Expr *expr = st->expr;
2605 GNode *gn; 2613 GNode *gn;
2606 char *path; 2614 char *path;
2607 2615
 2616 (*pp)++;
 2617
2608 Expr_Define(expr); 2618 Expr_Define(expr);
2609 2619
2610 gn = Targ_FindNode(expr->var->name.str); 2620 gn = Targ_FindNode(expr->var->name.str);
2611 if (gn == NULL || gn->type & OP_NOPATH) { 2621 if (gn == NULL || gn->type & OP_NOPATH) {
2612 path = NULL; 2622 path = NULL;
2613 } else if (gn->path != NULL) { 2623 } else if (gn->path != NULL) {
2614 path = bmake_strdup(gn->path); 2624 path = bmake_strdup(gn->path);
2615 } else { 2625 } else {
2616 SearchPath *searchPath = Suff_FindPath(gn); 2626 SearchPath *searchPath = Suff_FindPath(gn);
2617 path = Dir_FindFile(expr->var->name.str, searchPath); 2627 path = Dir_FindFile(expr->var->name.str, searchPath);
2618 } 2628 }
2619 if (path == NULL) 2629 if (path == NULL)
2620 path = bmake_strdup(expr->var->name.str); 2630 path = bmake_strdup(expr->var->name.str);
2621 Expr_SetValueOwn(expr, path); 2631 Expr_SetValueOwn(expr, path);
2622 2632
2623 (*pp)++; 
2624 return AMR_OK; 2633 return AMR_OK;
2625} 2634}
2626 2635
2627/* :!cmd! */ 2636/* :!cmd! */
2628static ApplyModifierResult 2637static ApplyModifierResult
2629ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st) 2638ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st)
2630{ 2639{
2631 Expr *expr = st->expr; 2640 Expr *expr = st->expr;
2632 char *cmd; 2641 char *cmd;
2633 const char *errfmt; 2642 const char *errfmt;
2634 VarParseResult res; 2643 VarParseResult res;
2635 2644
2636 (*pp)++; 2645 (*pp)++;
2637 res = ParseModifierPart(pp, '!', expr->eflags, st, &cmd); 2646 res = ParseModifierPart(pp, '!', expr->eflags, st, &cmd);
2638 if (res != VPR_OK) 2647 if (res != VPR_OK)
2639 return AMR_CLEANUP; 2648 return AMR_CLEANUP;
2640 2649
2641 errfmt = NULL; 2650 errfmt = NULL;
2642 if (expr->eflags & VARE_WANTRES) 2651 if (expr->eflags & VARE_WANTRES)
2643 Expr_SetValueOwn(expr, Cmd_Exec(cmd, &errfmt)); 2652 Expr_SetValueOwn(expr, Cmd_Exec(cmd, &errfmt));
2644 else 2653 else
2645 Expr_SetValueRefer(expr, ""); 2654 Expr_SetValueRefer(expr, "");
2646 if (errfmt != NULL) 2655 if (errfmt != NULL)
2647 Error(errfmt, cmd); /* XXX: why still return AMR_OK? */ 2656 Error(errfmt, cmd); /* XXX: why still return AMR_OK? */
2648 free(cmd); 2657 free(cmd);
2649 
2650 Expr_Define(expr); 2658 Expr_Define(expr);
 2659
2651 return AMR_OK; 2660 return AMR_OK;
2652} 2661}
2653 2662
2654/* 2663/*
2655 * The :range modifier generates an integer sequence as long as the words. 2664 * The :range modifier generates an integer sequence as long as the words.
2656 * The :range=7 modifier generates an integer sequence from 1 to 7. 2665 * The :range=7 modifier generates an integer sequence from 1 to 7.
2657 */ 2666 */
2658static ApplyModifierResult 2667static ApplyModifierResult
2659ApplyModifier_Range(const char **pp, ApplyModifiersState *st) 2668ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
2660{ 2669{
2661 size_t n; 2670 size_t n;
2662 Buffer buf; 2671 Buffer buf;
2663 size_t i; 2672 size_t i;
2664 2673
2665 const char *mod = *pp; 2674 const char *mod = *pp;
2666 if (!ModMatchEq(mod, "range", st)) 2675 if (!ModMatchEq(mod, "range", st))
2667 return AMR_UNKNOWN; 2676 return AMR_UNKNOWN;
2668 2677
2669 if (mod[5] == '=') { 2678 if (mod[5] == '=') {
2670 const char *p = mod + 6; 2679 const char *p = mod + 6;
2671 if (!TryParseSize(&p, &n)) { 2680 if (!TryParseSize(&p, &n)) {
2672 Parse_Error(PARSE_FATAL, 2681 Parse_Error(PARSE_FATAL,
2673 "Invalid number \"%s\" for ':range' modifier", 2682 "Invalid number \"%s\" for ':range' modifier",
2674 mod + 6); 2683 mod + 6);
2675 return AMR_CLEANUP; 2684 return AMR_CLEANUP;
2676 } 2685 }
2677 *pp = p; 2686 *pp = p;
2678 } else { 2687 } else {
2679 n = 0; 2688 n = 0;
2680 *pp = mod + 5; 2689 *pp = mod + 5;
2681 } 2690 }
2682 2691
2683 if (n == 0) { 2692 if (n == 0) {
2684 Words words = Str_Words(st->expr->value.str, FALSE); 2693 Words words = Str_Words(st->expr->value.str, FALSE);
2685 n = words.len; 2694 n = words.len;
2686 Words_Free(words); 2695 Words_Free(words);
2687 } 2696 }
2688 2697
2689 Buf_Init(&buf); 2698 Buf_Init(&buf);
2690 2699
2691 for (i = 0; i < n; i++) { 2700 for (i = 0; i < n; i++) {
2692 if (i != 0) { 2701 if (i != 0) {
2693 /* XXX: Use st->sep instead of ' ', for consistency. */ 2702 /* XXX: Use st->sep instead of ' ', for consistency. */
2694 Buf_AddByte(&buf, ' '); 2703 Buf_AddByte(&buf, ' ');
2695 } 2704 }
2696 Buf_AddInt(&buf, 1 + (int)i); 2705 Buf_AddInt(&buf, 1 + (int)i);
2697 } 2706 }
2698 2707
2699 Expr_SetValueOwn(st->expr, Buf_DoneData(&buf)); 2708 Expr_SetValueOwn(st->expr, Buf_DoneData(&buf));
2700 return AMR_OK; 2709 return AMR_OK;
2701} 2710}
2702 2711
2703/* Parse a ':M' or ':N' modifier. */ 2712/* Parse a ':M' or ':N' modifier. */
2704static void 2713static void
2705ParseModifier_Match(const char **pp, const ApplyModifiersState *st, 2714ParseModifier_Match(const char **pp, const ApplyModifiersState *st,
2706 char **out_pattern) 2715 char **out_pattern)
2707{ 2716{
2708 const char *mod = *pp; 2717 const char *mod = *pp;
2709 Expr *expr = st->expr; 2718 Expr *expr = st->expr;
2710 Boolean copy = FALSE; /* pattern should be, or has been, copied */ 2719 Boolean copy = FALSE; /* pattern should be, or has been, copied */
2711 Boolean needSubst = FALSE; 2720 Boolean needSubst = FALSE;
2712 const char *endpat; 2721 const char *endpat;
2713 char *pattern; 2722 char *pattern;
2714 2723
2715 /* 2724 /*
2716 * In the loop below, ignore ':' unless we are at (or back to) the 2725 * In the loop below, ignore ':' unless we are at (or back to) the
2717 * original brace level. 2726 * original brace level.
2718 * XXX: This will likely not work right if $() and ${} are intermixed. 2727 * XXX: This will likely not work right if $() and ${} are intermixed.
2719 */ 2728 */
2720 /* 2729 /*
2721 * XXX: This code is similar to the one in Var_Parse. 2730 * XXX: This code is similar to the one in Var_Parse.
2722 * See if the code can be merged. 2731 * See if the code can be merged.
2723 * See also ApplyModifier_Defined. 2732 * See also ApplyModifier_Defined.
2724 */ 2733 */
2725 int nest = 0; 2734 int nest = 0;
2726 const char *p; 2735 const char *p;
2727 for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) { 2736 for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) {
2728 if (*p == '\\' && 2737 if (*p == '\\' &&
2729 (IsDelimiter(p[1], st) || p[1] == st->startc)) { 2738 (IsDelimiter(p[1], st) || p[1] == st->startc)) {
2730 if (!needSubst) 2739 if (!needSubst)
2731 copy = TRUE; 2740 copy = TRUE;
2732 p++; 2741 p++;
2733 continue; 2742 continue;
2734 } 2743 }
2735 if (*p == '$') 2744 if (*p == '$')
2736 needSubst = TRUE; 2745 needSubst = TRUE;
2737 if (*p == '(' || *p == '{') 2746 if (*p == '(' || *p == '{')
2738 nest++; 2747 nest++;
2739 if (*p == ')' || *p == '}') { 2748 if (*p == ')' || *p == '}') {
2740 nest--; 2749 nest--;
2741 if (nest < 0) 2750 if (nest < 0)
2742 break; 2751 break;
2743 } 2752 }
2744 } 2753 }
2745 *pp = p; 2754 *pp = p;
2746 endpat = p; 2755 endpat = p;
2747 2756
2748 if (copy) { 2757 if (copy) {
2749 char *dst; 2758 char *dst;
2750 const char *src; 2759 const char *src;
2751 2760
2752 /* Compress the \:'s out of the pattern. */ 2761 /* Compress the \:'s out of the pattern. */
2753 pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1); 2762 pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
2754 dst = pattern; 2763 dst = pattern;
2755 src = mod + 1; 2764 src = mod + 1;
2756 for (; src < endpat; src++, dst++) { 2765 for (; src < endpat; src++, dst++) {
2757 if (src[0] == '\\' && src + 1 < endpat && 2766 if (src[0] == '\\' && src + 1 < endpat &&
2758 /* XXX: st->startc is missing here; see above */ 2767 /* XXX: st->startc is missing here; see above */
2759 IsDelimiter(src[1], st)) 2768 IsDelimiter(src[1], st))
2760 src++; 2769 src++;
2761 *dst = *src; 2770 *dst = *src;
2762 } 2771 }
2763 *dst = '\0'; 2772 *dst = '\0';
2764 } else { 2773 } else {
2765 pattern = bmake_strsedup(mod + 1, endpat); 2774 pattern = bmake_strsedup(mod + 1, endpat);
2766 } 2775 }
2767 2776
2768 if (needSubst) { 2777 if (needSubst) {
2769 char *old_pattern = pattern; 2778 char *old_pattern = pattern;
2770 (void)Var_Subst(pattern, expr->scope, expr->eflags, &pattern); 2779 (void)Var_Subst(pattern, expr->scope, expr->eflags, &pattern);
2771 /* TODO: handle errors */ 2780 /* TODO: handle errors */
2772 free(old_pattern); 2781 free(old_pattern);
2773 } 2782 }
2774 2783
2775 DEBUG3(VAR, "Pattern[%s] for [%s] is [%s]\n", 2784 DEBUG3(VAR, "Pattern[%s] for [%s] is [%s]\n",
2776 expr->var->name.str, expr->value.str, pattern); 2785 expr->var->name.str, expr->value.str, pattern);
2777 2786
2778 *out_pattern = pattern; 2787 *out_pattern = pattern;
2779} 2788}
2780 2789
2781/* :Mpattern or :Npattern */ 2790/* :Mpattern or :Npattern */
2782static ApplyModifierResult 2791static ApplyModifierResult
2783ApplyModifier_Match(const char **pp, ApplyModifiersState *st) 2792ApplyModifier_Match(const char **pp, ApplyModifiersState *st)
2784{ 2793{
2785 const char *mod = *pp; 2794 const char *mod = *pp;
2786 char *pattern; 2795 char *pattern;
2787 ModifyWordProc modifyWord; 2796 ModifyWordProc modifyWord;
2788 2797
2789 ParseModifier_Match(pp, st, &pattern); 2798 ParseModifier_Match(pp, st, &pattern);
2790 2799
2791 modifyWord = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; 2800 modifyWord = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
2792 ModifyWords(st, modifyWord, pattern, st->oneBigWord); 2801 ModifyWords(st, modifyWord, pattern, st->oneBigWord);
2793 free(pattern); 2802 free(pattern);
2794 return AMR_OK; 2803 return AMR_OK;
2795} 2804}
2796 2805
2797static void 2806static void
2798ParsePatternFlags(const char **pp, VarPatternFlags *pflags, Boolean *oneBigWord) 2807ParsePatternFlags(const char **pp, VarPatternFlags *pflags, Boolean *oneBigWord)
2799{ 2808{
2800 for (;; (*pp)++) { 2809 for (;; (*pp)++) {
2801 if (**pp == 'g') 2810 if (**pp == 'g')
2802 pflags->subGlobal = TRUE; 2811 pflags->subGlobal = TRUE;
2803 else if (**pp == '1') 2812 else if (**pp == '1')
2804 pflags->subOnce = TRUE; 2813 pflags->subOnce = TRUE;
2805 else if (**pp == 'W') 2814 else if (**pp == 'W')
2806 *oneBigWord = TRUE; 2815 *oneBigWord = TRUE;
2807 else 2816 else
2808 break; 2817 break;
2809 } 2818 }
2810} 2819}
2811 2820
2812/* :S,from,to, */ 2821/* :S,from,to, */
2813static ApplyModifierResult 2822static ApplyModifierResult
2814ApplyModifier_Subst(const char **pp, ApplyModifiersState *st) 2823ApplyModifier_Subst(const char **pp, ApplyModifiersState *st)
2815{ 2824{
2816 struct ModifyWord_SubstArgs args; 2825 struct ModifyWord_SubstArgs args;
2817 char *lhs, *rhs; 2826 char *lhs, *rhs;
2818 Boolean oneBigWord; 2827 Boolean oneBigWord;
2819 VarParseResult res; 2828 VarParseResult res;
2820 2829
2821 char delim = (*pp)[1]; 2830 char delim = (*pp)[1];
2822 if (delim == '\0') { 2831 if (delim == '\0') {
2823 Error("Missing delimiter for modifier ':S'"); 2832 Error("Missing delimiter for modifier ':S'");
2824 (*pp)++; 2833 (*pp)++;
2825 return AMR_CLEANUP; 2834 return AMR_CLEANUP;
2826 } 2835 }
2827 2836
2828 *pp += 2; 2837 *pp += 2;
2829 2838
2830 args.pflags = (VarPatternFlags){ FALSE, FALSE, FALSE, FALSE }; 2839 args.pflags = (VarPatternFlags){ FALSE, FALSE, FALSE, FALSE };
2831 args.matched = FALSE; 2840 args.matched = FALSE;
2832 2841
2833 if (**pp == '^') { 2842 if (**pp == '^') {
2834 args.pflags.anchorStart = TRUE; 2843 args.pflags.anchorStart = TRUE;
2835 (*pp)++; 2844 (*pp)++;
2836 } 2845 }
2837 2846
2838 res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &lhs, 2847 res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &lhs,
2839 &args.lhsLen, &args.pflags, NULL); 2848 &args.lhsLen, &args.pflags, NULL);
2840 if (res != VPR_OK) 2849 if (res != VPR_OK)
2841 return AMR_CLEANUP; 2850 return AMR_CLEANUP;
2842 args.lhs = lhs; 2851 args.lhs = lhs;
2843 2852
2844 res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &rhs, 2853 res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &rhs,
2845 &args.rhsLen, NULL, &args); 2854 &args.rhsLen, NULL, &args);
2846 if (res != VPR_OK) 2855 if (res != VPR_OK)
2847 return AMR_CLEANUP; 2856 return AMR_CLEANUP;
2848 args.rhs = rhs; 2857 args.rhs = rhs;
2849 2858
2850 oneBigWord = st->oneBigWord; 2859 oneBigWord = st->oneBigWord;
2851 ParsePatternFlags(pp, &args.pflags, &oneBigWord); 2860 ParsePatternFlags(pp, &args.pflags, &oneBigWord);
2852 2861
2853 ModifyWords(st, ModifyWord_Subst, &args, oneBigWord); 2862 ModifyWords(st, ModifyWord_Subst, &args, oneBigWord);
2854 2863
2855 free(lhs); 2864 free(lhs);
2856 free(rhs); 2865 free(rhs);
2857 return AMR_OK; 2866 return AMR_OK;
2858} 2867}
2859 2868
2860#ifndef NO_REGEX 2869#ifndef NO_REGEX
2861 2870
2862/* :C,from,to, */ 2871/* :C,from,to, */
2863static ApplyModifierResult 2872static ApplyModifierResult
2864ApplyModifier_Regex(const char **pp, ApplyModifiersState *st) 2873ApplyModifier_Regex(const char **pp, ApplyModifiersState *st)
2865{ 2874{
2866 char *re; 2875 char *re;
2867 struct ModifyWord_SubstRegexArgs args; 2876 struct ModifyWord_SubstRegexArgs args;
2868 Boolean oneBigWord; 2877 Boolean oneBigWord;
2869 int error; 2878 int error;
2870 VarParseResult res; 2879 VarParseResult res;
2871 2880
2872 char delim = (*pp)[1]; 2881 char delim = (*pp)[1];
2873 if (delim == '\0') { 2882 if (delim == '\0') {
2874 Error("Missing delimiter for :C modifier"); 2883 Error("Missing delimiter for :C modifier");
2875 (*pp)++; 2884 (*pp)++;
2876 return AMR_CLEANUP; 2885 return AMR_CLEANUP;
2877 } 2886 }
2878 2887
2879 *pp += 2; 2888 *pp += 2;
2880 2889
2881 res = ParseModifierPart(pp, delim, st->expr->eflags, st, &re); 2890 res = ParseModifierPart(pp, delim, st->expr->eflags, st, &re);
2882 if (res != VPR_OK) 2891 if (res != VPR_OK)
2883 return AMR_CLEANUP; 2892 return AMR_CLEANUP;
2884 2893
2885 res = ParseModifierPart(pp, delim, st->expr->eflags, st, &args.replace); 2894 res = ParseModifierPart(pp, delim, st->expr->eflags, st, &args.replace);
2886 if (args.replace == NULL) { 2895 if (args.replace == NULL) {
2887 free(re); 2896 free(re);
2888 return AMR_CLEANUP; 2897 return AMR_CLEANUP;
2889 } 2898 }
2890 2899
2891 args.pflags = (VarPatternFlags){ FALSE, FALSE, FALSE, FALSE }; 2900 args.pflags = (VarPatternFlags){ FALSE, FALSE, FALSE, FALSE };
2892 args.matched = FALSE; 2901 args.matched = FALSE;
2893 oneBigWord = st->oneBigWord; 2902 oneBigWord = st->oneBigWord;
2894 ParsePatternFlags(pp, &args.pflags, &oneBigWord); 2903 ParsePatternFlags(pp, &args.pflags, &oneBigWord);
2895 2904
2896 if (!(st->expr->eflags & VARE_WANTRES)) { 2905 if (!(st->expr->eflags & VARE_WANTRES)) {
2897 free(args.replace); 2906 free(args.replace);
2898 free(re); 2907 free(re);
2899 return AMR_OK; 2908 return AMR_OK;
2900 } 2909 }
2901 2910
2902 error = regcomp(&args.re, re, REG_EXTENDED); 2911 error = regcomp(&args.re, re, REG_EXTENDED);
2903 free(re); 2912 free(re);
2904 if (error != 0) { 2913 if (error != 0) {
2905 VarREError(error, &args.re, "Regex compilation error"); 2914 VarREError(error, &args.re, "Regex compilation error");
2906 free(args.replace); 2915 free(args.replace);
2907 return AMR_CLEANUP; 2916 return AMR_CLEANUP;
2908 } 2917 }
2909 2918
2910 args.nsub = args.re.re_nsub + 1; 2919 args.nsub = args.re.re_nsub + 1;
2911 if (args.nsub > 10) 2920 if (args.nsub > 10)
2912 args.nsub = 10; 2921 args.nsub = 10;
2913 2922
2914 ModifyWords(st, ModifyWord_SubstRegex, &args, oneBigWord); 2923 ModifyWords(st, ModifyWord_SubstRegex, &args, oneBigWord);
2915 2924
2916 regfree(&args.re); 2925 regfree(&args.re);
2917 free(args.replace); 2926 free(args.replace);
2918 return AMR_OK; 2927 return AMR_OK;
2919} 2928}
2920 2929
2921#endif 2930#endif
2922 2931
2923/* :Q, :q */ 2932/* :Q, :q */
2924static ApplyModifierResult 2933static ApplyModifierResult
2925ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) 2934ApplyModifier_Quote(const char **pp, ApplyModifiersState *st)
2926{ 2935{
2927 Boolean quoteDollar = **pp == 'q'; 2936 Boolean quoteDollar = **pp == 'q';
2928 if (!IsDelimiter((*pp)[1], st)) 2937 if (!IsDelimiter((*pp)[1], st))
2929 return AMR_UNKNOWN; 2938 return AMR_UNKNOWN;
2930 (*pp)++; 2939 (*pp)++;
2931 2940
2932 Expr_SetValueOwn(st->expr, VarQuote(st->expr->value.str, quoteDollar)); 2941 Expr_SetValueOwn(st->expr, VarQuote(st->expr->value.str, quoteDollar));
2933 2942
2934 return AMR_OK; 2943 return AMR_OK;
2935} 2944}
2936 2945
2937/*ARGSUSED*/ 2946/*ARGSUSED*/
2938static void 2947static void
2939ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 2948ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
2940{ 2949{
2941 SepBuf_AddStr(buf, word); 2950 SepBuf_AddStr(buf, word);
2942} 2951}
2943 2952
2944/* :ts<separator> */ 2953/* :ts<separator> */
2945static ApplyModifierResult 2954static ApplyModifierResult
2946ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) 2955ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
2947{ 2956{
2948 const char *sep = *pp + 2; 2957 const char *sep = *pp + 2;
2949 2958
2950 /* ":ts<any><endc>" or ":ts<any>:" */ 2959 /* ":ts<any><endc>" or ":ts<any>:" */
2951 if (sep[0] != st->endc && IsDelimiter(sep[1], st)) { 2960 if (sep[0] != st->endc && IsDelimiter(sep[1], st)) {
2952 st->sep = sep[0]; 
2953 *pp = sep + 1; 2961 *pp = sep + 1;
 2962 st->sep = sep[0];
2954 goto ok; 2963 goto ok;
2955 } 2964 }
2956 2965
2957 /* ":ts<endc>" or ":ts:" */ 2966 /* ":ts<endc>" or ":ts:" */
2958 if (IsDelimiter(sep[0], st)) { 2967 if (IsDelimiter(sep[0], st)) {
2959 st->sep = '\0'; /* no separator */ 
2960 *pp = sep; 2968 *pp = sep;
 2969 st->sep = '\0'; /* no separator */
2961 goto ok; 2970 goto ok;
2962 } 2971 }
2963 2972
2964 /* ":ts<unrecognised><unrecognised>". */ 2973 /* ":ts<unrecognised><unrecognised>". */
2965 if (sep[0] != '\\') { 2974 if (sep[0] != '\\') {
2966 (*pp)++; /* just for backwards compatibility */ 2975 (*pp)++; /* just for backwards compatibility */
2967 return AMR_BAD; 2976 return AMR_BAD;
2968 } 2977 }
2969 2978
2970 /* ":ts\n" */ 2979 /* ":ts\n" */
2971 if (sep[1] == 'n') { 2980 if (sep[1] == 'n') {
2972 st->sep = '\n'; 
2973 *pp = sep + 2; 2981 *pp = sep + 2;
 2982 st->sep = '\n';
2974 goto ok; 2983 goto ok;
2975 } 2984 }
2976 2985
2977 /* ":ts\t" */ 2986 /* ":ts\t" */
2978 if (sep[1] == 't') { 2987 if (sep[1] == 't') {
2979 st->sep = '\t'; 
2980 *pp = sep + 2; 2988 *pp = sep + 2;
 2989 st->sep = '\t';
2981 goto ok; 2990 goto ok;
2982 } 2991 }
2983 2992
2984 /* ":ts\x40" or ":ts\100" */ 2993 /* ":ts\x40" or ":ts\100" */
2985 { 2994 {
2986 const char *p = sep + 1; 2995 const char *p = sep + 1;
2987 int base = 8; /* assume octal */ 2996 int base = 8; /* assume octal */
2988 2997
2989 if (sep[1] == 'x') { 2998 if (sep[1] == 'x') {
2990 base = 16; 2999 base = 16;
2991 p++; 3000 p++;
2992 } else if (!ch_isdigit(sep[1])) { 3001 } else if (!ch_isdigit(sep[1])) {
2993 (*pp)++; /* just for backwards compatibility */ 3002 (*pp)++; /* just for backwards compatibility */
2994 return AMR_BAD; /* ":ts<backslash><unrecognised>". */ 3003 return AMR_BAD; /* ":ts<backslash><unrecognised>". */
2995 } 3004 }
2996 3005
2997 if (!TryParseChar(&p, base, &st->sep)) { 3006 if (!TryParseChar(&p, base, &st->sep)) {
2998 Parse_Error(PARSE_FATAL, 3007 Parse_Error(PARSE_FATAL,
2999 "Invalid character number: %s", p); 3008 "Invalid character number: %s", p);
3000 return AMR_CLEANUP; 3009 return AMR_CLEANUP;
3001 } 3010 }
3002 if (!IsDelimiter(*p, st)) { 3011 if (!IsDelimiter(*p, st)) {
3003 (*pp)++; /* just for backwards compatibility */ 3012 (*pp)++; /* just for backwards compatibility */
3004 return AMR_BAD; 3013 return AMR_BAD;
3005 } 3014 }
3006 3015
3007 *pp = p; 3016 *pp = p;
3008 } 3017 }
3009 3018
3010ok: 3019ok:
3011 ModifyWords(st, ModifyWord_Copy, NULL, st->oneBigWord); 3020 ModifyWords(st, ModifyWord_Copy, NULL, st->oneBigWord);
3012 return AMR_OK; 3021 return AMR_OK;
3013} 3022}
3014 3023
3015static char * 3024static char *
3016str_toupper(const char *str) 3025str_toupper(const char *str)
3017{ 3026{
3018 char *res; 3027 char *res;
3019 size_t i, len; 3028 size_t i, len;
3020 3029
3021 len = strlen(str); 3030 len = strlen(str);
3022 res = bmake_malloc(len + 1); 3031 res = bmake_malloc(len + 1);
3023 for (i = 0; i < len + 1; i++) 3032 for (i = 0; i < len + 1; i++)
3024 res[i] = ch_toupper(str[i]); 3033 res[i] = ch_toupper(str[i]);
3025 3034
3026 return res; 3035 return res;
3027} 3036}
3028 3037
3029static char * 3038static char *
3030str_tolower(const char *str) 3039str_tolower(const char *str)
3031{ 3040{
3032 char *res; 3041 char *res;
3033 size_t i, len; 3042 size_t i, len;
3034 3043
3035 len = strlen(str); 3044 len = strlen(str);
3036 res = bmake_malloc(len + 1); 3045 res = bmake_malloc(len + 1);
3037 for (i = 0; i < len + 1; i++) 3046 for (i = 0; i < len + 1; i++)
3038 res[i] = ch_tolower(str[i]); 3047 res[i] = ch_tolower(str[i]);
3039 3048
3040 return res; 3049 return res;
3041} 3050}
3042 3051
3043/* :tA, :tu, :tl, :ts<separator>, etc. */ 3052/* :tA, :tu, :tl, :ts<separator>, etc. */
3044static ApplyModifierResult 3053static ApplyModifierResult
3045ApplyModifier_To(const char **pp, ApplyModifiersState *st) 3054ApplyModifier_To(const char **pp, ApplyModifiersState *st)
3046{ 3055{
3047 Expr *expr = st->expr; 3056 Expr *expr = st->expr;
3048 const char *mod = *pp; 3057 const char *mod = *pp;
3049 assert(mod[0] == 't'); 3058 assert(mod[0] == 't');
3050 3059
3051 if (IsDelimiter(mod[1], st) || mod[1] == '\0') { 3060 if (IsDelimiter(mod[1], st) || mod[1] == '\0') {
3052 *pp = mod + 1; 3061 *pp = mod + 1;
3053 return AMR_BAD; /* Found ":t<endc>" or ":t:". */ 3062 return AMR_BAD; /* Found ":t<endc>" or ":t:". */
3054 } 3063 }
3055 3064
3056 if (mod[1] == 's') 3065 if (mod[1] == 's')
3057 return ApplyModifier_ToSep(pp, st); 3066 return ApplyModifier_ToSep(pp, st);
3058 3067
3059 if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */ 3068 if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */
3060 *pp = mod + 1; 3069 *pp = mod + 1;
3061 return AMR_BAD; 3070 return AMR_BAD;
3062 } 3071 }
3063 3072
3064 if (mod[1] == 'A') { /* :tA */ 3073 if (mod[1] == 'A') { /* :tA */
3065 ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord); 
3066 *pp = mod + 2; 3074 *pp = mod + 2;
 3075 ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord);
3067 return AMR_OK; 3076 return AMR_OK;
3068 } 3077 }
3069 3078
3070 if (mod[1] == 'u') { /* :tu */ 3079 if (mod[1] == 'u') { /* :tu */
3071 Expr_SetValueOwn(expr, str_toupper(expr->value.str)); 
3072 *pp = mod + 2; 3080 *pp = mod + 2;
 3081 Expr_SetValueOwn(expr, str_toupper(expr->value.str));
3073 return AMR_OK; 3082 return AMR_OK;
3074 } 3083 }
3075 3084
3076 if (mod[1] == 'l') { /* :tl */ 3085 if (mod[1] == 'l') { /* :tl */
3077 Expr_SetValueOwn(expr, str_tolower(expr->value.str)); 
3078 *pp = mod + 2; 3086 *pp = mod + 2;
 3087 Expr_SetValueOwn(expr, str_tolower(expr->value.str));
3079 return AMR_OK; 3088 return AMR_OK;
3080 } 3089 }
3081 3090
3082 if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ 3091 if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
3083 st->oneBigWord = mod[1] == 'W'; 
3084 *pp = mod + 2; 3092 *pp = mod + 2;
 3093 st->oneBigWord = mod[1] == 'W';
3085 return AMR_OK; 3094 return AMR_OK;
3086 } 3095 }
3087 3096
3088 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ 3097 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
3089 *pp = mod + 1; 3098 *pp = mod + 1; /* XXX: unnecessary but observable */
3090 return AMR_BAD; 3099 return AMR_BAD;
3091} 3100}
3092 3101
3093/* :[#], :[1], :[-1..1], etc. */ 3102/* :[#], :[1], :[-1..1], etc. */
3094static ApplyModifierResult 3103static ApplyModifierResult
3095ApplyModifier_Words(const char **pp, ApplyModifiersState *st) 3104ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
3096{ 3105{
3097 Expr *expr = st->expr; 3106 Expr *expr = st->expr;
3098 char *estr; 3107 char *estr;
3099 int first, last; 3108 int first, last;
3100 VarParseResult res; 3109 VarParseResult res;
3101 const char *p; 3110 const char *p;
3102 3111
3103 (*pp)++; /* skip the '[' */ 3112 (*pp)++; /* skip the '[' */
3104 res = ParseModifierPart(pp, ']', expr->eflags, st, &estr); 3113 res = ParseModifierPart(pp, ']', expr->eflags, st, &estr);
3105 if (res != VPR_OK) 3114 if (res != VPR_OK)
3106 return AMR_CLEANUP; 3115 return AMR_CLEANUP;
3107 3116
3108 if (!IsDelimiter(**pp, st)) 3117 if (!IsDelimiter(**pp, st))
3109 goto bad_modifier; /* Found junk after ']' */ 3118 goto bad_modifier; /* Found junk after ']' */
3110 3119
3111 if (estr[0] == '\0') 3120 if (estr[0] == '\0')
3112 goto bad_modifier; /* Found ":[]". */ 3121 goto bad_modifier; /* Found ":[]". */
3113 3122
3114 if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ 3123 if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
3115 if (st->oneBigWord) { 3124 if (st->oneBigWord) {
3116 Expr_SetValueRefer(expr, "1"); 3125 Expr_SetValueRefer(expr, "1");
3117 } else { 3126 } else {
3118 Buffer buf; 3127 Buffer buf;
3119 3128
3120 Words words = Str_Words(expr->value.str, FALSE); 3129 Words words = Str_Words(expr->value.str, FALSE);
3121 size_t ac = words.len; 3130 size_t ac = words.len;
3122 Words_Free(words); 3131 Words_Free(words);
3123 3132
3124 /* 3 digits + '\0' is usually enough */ 3133 /* 3 digits + '\0' is usually enough */
3125 Buf_InitSize(&buf, 4); 3134 Buf_InitSize(&buf, 4);
3126 Buf_AddInt(&buf, (int)ac); 3135 Buf_AddInt(&buf, (int)ac);
3127 Expr_SetValueOwn(expr, Buf_DoneData(&buf)); 3136 Expr_SetValueOwn(expr, Buf_DoneData(&buf));
3128 } 3137 }
3129 goto ok; 3138 goto ok;
3130 } 3139 }
3131 3140
3132 if (estr[0] == '*' && estr[1] == '\0') { /* Found ":[*]" */ 3141 if (estr[0] == '*' && estr[1] == '\0') { /* Found ":[*]" */
3133 st->oneBigWord = TRUE; 3142 st->oneBigWord = TRUE;
3134 goto ok; 3143 goto ok;
3135 } 3144 }
3136 3145
3137 if (estr[0] == '@' && estr[1] == '\0') { /* Found ":[@]" */ 3146 if (estr[0] == '@' && estr[1] == '\0') { /* Found ":[@]" */
3138 st->oneBigWord = FALSE; 3147 st->oneBigWord = FALSE;
3139 goto ok; 3148 goto ok;
3140 } 3149 }
3141 3150
3142 /* 3151 /*
3143 * We expect estr to contain a single integer for :[N], or two 3152 * We expect estr to contain a single integer for :[N], or two
3144 * integers separated by ".." for :[start..end]. 3153 * integers separated by ".." for :[start..end].
3145 */ 3154 */
3146 p = estr; 3155 p = estr;
3147 if (!TryParseIntBase0(&p, &first)) 3156 if (!TryParseIntBase0(&p, &first))
3148 goto bad_modifier; /* Found junk instead of a number */ 3157 goto bad_modifier; /* Found junk instead of a number */
3149 3158
3150 if (p[0] == '\0') { /* Found only one integer in :[N] */ 3159 if (p[0] == '\0') { /* Found only one integer in :[N] */
3151 last = first; 3160 last = first;
3152 } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') { 3161 } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') {
3153 /* Expecting another integer after ".." */ 3162 /* Expecting another integer after ".." */
3154 p += 2; 3163 p += 2;
3155 if (!TryParseIntBase0(&p, &last) || *p != '\0') 3164 if (!TryParseIntBase0(&p, &last) || *p != '\0')
3156 goto bad_modifier; /* Found junk after ".." */ 3165 goto bad_modifier; /* Found junk after ".." */
3157 } else 3166 } else
3158 goto bad_modifier; /* Found junk instead of ".." */ 3167 goto bad_modifier; /* Found junk instead of ".." */
3159 3168
3160 /* 3169 /*
3161 * Now first and last are properly filled in, but we still have to 3170 * Now first and last are properly filled in, but we still have to
3162 * check for 0 as a special case. 3171 * check for 0 as a special case.
3163 */ 3172 */
3164 if (first == 0 && last == 0) { 3173 if (first == 0 && last == 0) {
3165 /* ":[0]" or perhaps ":[0..0]" */ 3174 /* ":[0]" or perhaps ":[0..0]" */
3166 st->oneBigWord = TRUE; 3175 st->oneBigWord = TRUE;
3167 goto ok; 3176 goto ok;
3168 } 3177 }
3169 3178
3170 /* ":[0..N]" or ":[N..0]" */ 3179 /* ":[0..N]" or ":[N..0]" */
3171 if (first == 0 || last == 0) 3180 if (first == 0 || last == 0)
3172 goto bad_modifier; 3181 goto bad_modifier;
3173 3182
3174 /* Normal case: select the words described by first and last. */ 3183 /* Normal case: select the words described by first and last. */
3175 Expr_SetValueOwn(expr, 3184 Expr_SetValueOwn(expr,
3176 VarSelectWords(expr->value.str, first, last, 3185 VarSelectWords(expr->value.str, first, last,
3177 st->sep, st->oneBigWord)); 3186 st->sep, st->oneBigWord));
3178 3187
3179ok: 3188ok:
3180 free(estr); 3189 free(estr);
3181 return AMR_OK; 3190 return AMR_OK;
3182 3191
3183bad_modifier: 3192bad_modifier:
3184 free(estr); 3193 free(estr);
3185 return AMR_BAD; 3194 return AMR_BAD;
3186} 3195}
3187 3196
3188static int 3197static int
3189str_cmp_asc(const void *a, const void *b) 3198str_cmp_asc(const void *a, const void *b)
3190{ 3199{
3191 return strcmp(*(const char *const *)a, *(const char *const *)b); 3200 return strcmp(*(const char *const *)a, *(const char *const *)b);
3192} 3201}
3193 3202
3194static int 3203static int
3195str_cmp_desc(const void *a, const void *b) 3204str_cmp_desc(const void *a, const void *b)
3196{ 3205{
3197 return strcmp(*(const char *const *)b, *(const char *const *)a); 3206 return strcmp(*(const char *const *)b, *(const char *const *)a);
3198} 3207}
3199 3208
3200static void 3209static void
3201ShuffleStrings(char **strs, size_t n) 3210ShuffleStrings(char **strs, size_t n)
3202{ 3211{
3203 size_t i; 3212 size_t i;
3204 3213
3205 for (i = n - 1; i > 0; i--) { 3214 for (i = n - 1; i > 0; i--) {
3206 size_t rndidx = (size_t)random() % (i + 1); 3215 size_t rndidx = (size_t)random() % (i + 1);
3207 char *t = strs[i]; 3216 char *t = strs[i];
3208 strs[i] = strs[rndidx]; 3217 strs[i] = strs[rndidx];
3209 strs[rndidx] = t; 3218 strs[rndidx] = t;
3210 } 3219 }
3211} 3220}
3212 3221
3213/* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */ 3222/* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
3214static ApplyModifierResult 3223static ApplyModifierResult
3215ApplyModifier_Order(const char **pp, ApplyModifiersState *st) 3224ApplyModifier_Order(const char **pp, ApplyModifiersState *st)
3216{ 3225{
3217 const char *mod = (*pp)++; /* skip past the 'O' in any case */ 3226 const char *mod = (*pp)++; /* skip past the 'O' in any case */
3218 3227
 3228 /* TODO: separate parsing from evaluating */
 3229
3219 Words words = Str_Words(st->expr->value.str, FALSE); 3230 Words words = Str_Words(st->expr->value.str, FALSE);
3220 3231
3221 if (IsDelimiter(mod[1], st)) { 3232 if (IsDelimiter(mod[1], st)) {
3222 /* :O sorts ascending */ 3233 /* :O sorts ascending */
3223 qsort(words.words, words.len, sizeof words.words[0], 3234 qsort(words.words, words.len, sizeof words.words[0],
3224 str_cmp_asc); 3235 str_cmp_asc);
3225 3236
3226 } else if ((mod[1] == 'r' || mod[1] == 'x') && 3237 } else if ((mod[1] == 'r' || mod[1] == 'x') &&
3227 IsDelimiter(mod[2], st)) { 3238 IsDelimiter(mod[2], st)) {
3228 (*pp)++; 3239 (*pp)++;
3229 3240
3230 if (mod[1] == 'r') { /* :Or sorts descending */ 3241 if (mod[1] == 'r') { /* :Or sorts descending */
3231 qsort(words.words, words.len, sizeof words.words[0], 3242 qsort(words.words, words.len, sizeof words.words[0],
3232 str_cmp_desc); 3243 str_cmp_desc);
3233 } else 3244 } else
3234 ShuffleStrings(words.words, words.len); 3245 ShuffleStrings(words.words, words.len);
3235 } else { 3246 } else {
3236 Words_Free(words); 3247 Words_Free(words);
3237 return AMR_BAD; 3248 return AMR_BAD;
3238 } 3249 }
3239 3250
3240 Expr_SetValueOwn(st->expr, Words_JoinFree(words)); 3251 Expr_SetValueOwn(st->expr, Words_JoinFree(words));
3241 return AMR_OK; 3252 return AMR_OK;
3242} 3253}
3243 3254
3244/* :? then : else */ 3255/* :? then : else */
3245static ApplyModifierResult 3256static ApplyModifierResult
3246ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st) 3257ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
3247{ 3258{
3248 Expr *expr = st->expr; 3259 Expr *expr = st->expr;
3249 char *then_expr, *else_expr; 3260 char *then_expr, *else_expr;
3250 VarParseResult res; 3261 VarParseResult res;
3251 3262
3252 Boolean value = FALSE; 3263 Boolean value = FALSE;
3253 VarEvalFlags then_eflags = VARE_NONE; 3264 VarEvalFlags then_eflags = VARE_NONE;
3254 VarEvalFlags else_eflags = VARE_NONE; 3265 VarEvalFlags else_eflags = VARE_NONE;
3255 3266
3256 int cond_rc = COND_PARSE; /* anything other than COND_INVALID */ 3267 int cond_rc = COND_PARSE; /* anything other than COND_INVALID */
3257 if (expr->eflags & VARE_WANTRES) { 3268 if (expr->eflags & VARE_WANTRES) {
3258 cond_rc = Cond_EvalCondition(expr->var->name.str, &value); 3269 cond_rc = Cond_EvalCondition(expr->var->name.str, &value);
3259 if (cond_rc != COND_INVALID && value) 3270 if (cond_rc != COND_INVALID && value)
3260 then_eflags = expr->eflags; 3271 then_eflags = expr->eflags;
3261 if (cond_rc != COND_INVALID && !value) 3272 if (cond_rc != COND_INVALID && !value)
3262 else_eflags = expr->eflags; 3273 else_eflags = expr->eflags;
3263 } 3274 }
3264 3275
3265 (*pp)++; /* skip past the '?' */ 3276 (*pp)++; /* skip past the '?' */
3266 res = ParseModifierPart(pp, ':', then_eflags, st, &then_expr); 3277 res = ParseModifierPart(pp, ':', then_eflags, st, &then_expr);
3267 if (res != VPR_OK) 3278 if (res != VPR_OK)
3268 return AMR_CLEANUP; 3279 return AMR_CLEANUP;
3269 3280
3270 res = ParseModifierPart(pp, st->endc, else_eflags, st, &else_expr); 3281 res = ParseModifierPart(pp, st->endc, else_eflags, st, &else_expr);
3271 if (res != VPR_OK) 3282 if (res != VPR_OK)
3272 return AMR_CLEANUP; 3283 return AMR_CLEANUP;
3273 3284
3274 (*pp)--; /* Go back to the st->endc. */ 3285 (*pp)--; /* Go back to the st->endc. */
3275 3286
3276 if (cond_rc == COND_INVALID) { 3287 if (cond_rc == COND_INVALID) {
3277 Error("Bad conditional expression `%s' in %s?%s:%s", 3288 Error("Bad conditional expression `%s' in %s?%s:%s",
3278 expr->var->name.str, expr->var->name.str, 3289 expr->var->name.str, expr->var->name.str,
3279 then_expr, else_expr); 3290 then_expr, else_expr);
3280 return AMR_CLEANUP; 3291 return AMR_CLEANUP;
3281 } 3292 }
3282 3293
3283 if (value) { 3294 if (value) {
3284 Expr_SetValueOwn(expr, then_expr); 3295 Expr_SetValueOwn(expr, then_expr);
3285 free(else_expr); 3296 free(else_expr);
3286 } else { 3297 } else {
3287 Expr_SetValueOwn(expr, else_expr); 3298 Expr_SetValueOwn(expr, else_expr);
3288 free(then_expr); 3299 free(then_expr);
3289 } 3300 }
3290 Expr_Define(expr); 3301 Expr_Define(expr);
3291 return AMR_OK; 3302 return AMR_OK;
3292} 3303}
3293 3304
3294/* 3305/*
3295 * The ::= modifiers are special in that they do not read the variable value 3306 * The ::= modifiers are special in that they do not read the variable value
3296 * but instead assign to that variable. They always expand to an empty 3307 * but instead assign to that variable. They always expand to an empty
3297 * string. 3308 * string.
3298 * 3309 *
3299 * Their main purpose is in supporting .for loops that generate shell commands 3310 * Their main purpose is in supporting .for loops that generate shell commands
3300 * since an ordinary variable assignment at that point would terminate the 3311 * since an ordinary variable assignment at that point would terminate the
3301 * dependency group for these targets. For example: 3312 * dependency group for these targets. For example:
3302 * 3313 *
3303 * list-targets: .USE 3314 * list-targets: .USE
3304 * .for i in ${.TARGET} ${.TARGET:R}.gz 3315 * .for i in ${.TARGET} ${.TARGET:R}.gz
3305 * @${t::=$i} 3316 * @${t::=$i}
3306 * @echo 'The target is ${t:T}.' 3317 * @echo 'The target is ${t:T}.'
3307 * .endfor 3318 * .endfor
3308 * 3319 *
3309 * ::=<str> Assigns <str> as the new value of variable. 3320 * ::=<str> Assigns <str> as the new value of variable.
3310 * ::?=<str> Assigns <str> as value of variable if 3321 * ::?=<str> Assigns <str> as value of variable if
3311 * it was not already set. 3322 * it was not already set.
3312 * ::+=<str> Appends <str> to variable. 3323 * ::+=<str> Appends <str> to variable.
3313 * ::!=<cmd> Assigns output of <cmd> as the new value of 3324 * ::!=<cmd> Assigns output of <cmd> as the new value of
3314 * variable. 3325 * variable.
3315 */ 3326 */
3316static ApplyModifierResult 3327static ApplyModifierResult
3317ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) 3328ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
3318{ 3329{
3319 Expr *expr = st->expr; 3330 Expr *expr = st->expr;
3320 GNode *scope; 3331 GNode *scope;
3321 char *val; 3332 char *val;
3322 VarParseResult res; 3333 VarParseResult res;
3323 3334
 3335 /* TODO: separate parsing from evaluating */
 3336
3324 const char *mod = *pp; 3337 const char *mod = *pp;
3325 const char *op = mod + 1; 3338 const char *op = mod + 1;
3326 3339
3327 if (op[0] == '=') 3340 if (op[0] == '=')
3328 goto ok; 3341 goto ok;
3329 if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=') 3342 if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=')
3330 goto ok; 3343 goto ok;
3331 return AMR_UNKNOWN; /* "::<unrecognised>" */ 3344 return AMR_UNKNOWN; /* "::<unrecognised>" */
3332 3345
3333ok: 3346ok:
3334 if (expr->var->name.str[0] == '\0') { 3347 if (expr->var->name.str[0] == '\0') {
3335 *pp = mod + 1; 3348 *pp = mod + 1;
3336 return AMR_BAD; 3349 return AMR_BAD;
3337 } 3350 }
3338 3351
3339 scope = expr->scope; /* scope where v belongs */ 3352 scope = expr->scope; /* scope where v belongs */
3340 if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL) { 3353 if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL) {
3341 Var *gv = VarFind(expr->var->name.str, expr->scope, FALSE); 3354 Var *gv = VarFind(expr->var->name.str, expr->scope, FALSE);
3342 if (gv == NULL) 3355 if (gv == NULL)
3343 scope = SCOPE_GLOBAL; 3356 scope = SCOPE_GLOBAL;
3344 else 3357 else
3345 VarFreeEnv(gv); 3358 VarFreeEnv(gv);
3346 } 3359 }
3347 3360
3348 switch (op[0]) { 3361 switch (op[0]) {
3349 case '+': 3362 case '+':
3350 case '?': 3363 case '?':
3351 case '!': 3364 case '!':
3352 *pp = mod + 3; 3365 *pp = mod + 3;
3353 break; 3366 break;
3354 default: 3367 default:
3355 *pp = mod + 2; 3368 *pp = mod + 2;
3356 break; 3369 break;
3357 } 3370 }
3358 3371
3359 res = ParseModifierPart(pp, st->endc, expr->eflags, st, &val); 3372 res = ParseModifierPart(pp, st->endc, expr->eflags, st, &val);
3360 if (res != VPR_OK) 3373 if (res != VPR_OK)
3361 return AMR_CLEANUP; 3374 return AMR_CLEANUP;
3362 3375
3363 (*pp)--; /* Go back to the st->endc. */ 3376 (*pp)--; /* Go back to the st->endc. */
3364 3377
3365 /* XXX: Expanding the variable name at this point sounds wrong. */ 3378 /* XXX: Expanding the variable name at this point sounds wrong. */
3366 if (expr->eflags & VARE_WANTRES) { 3379 if (expr->eflags & VARE_WANTRES) {
3367 switch (op[0]) { 3380 switch (op[0]) {
3368 case '+': 3381 case '+':
3369 Var_AppendExpand(scope, expr->var->name.str, val); 3382 Var_AppendExpand(scope, expr->var->name.str, val);
3370 break; 3383 break;
3371 case '!': { 3384 case '!': {
3372 const char *errfmt; 3385 const char *errfmt;
3373 char *cmd_output = Cmd_Exec(val, &errfmt); 3386 char *cmd_output = Cmd_Exec(val, &errfmt);
3374 if (errfmt != NULL) 3387 if (errfmt != NULL)
3375 Error(errfmt, val); 3388 Error(errfmt, val);
3376 else 3389 else
3377 Var_SetExpand(scope, 3390 Var_SetExpand(scope,
3378 expr->var->name.str, cmd_output); 3391 expr->var->name.str, cmd_output);
3379 free(cmd_output); 3392 free(cmd_output);
3380 break; 3393 break;
3381 } 3394 }
3382 case '?': 3395 case '?':
3383 if (expr->defined == DEF_REGULAR) 3396 if (expr->defined == DEF_REGULAR)
3384 break; 3397 break;
3385 /* FALLTHROUGH */ 3398 /* FALLTHROUGH */
3386 default: 3399 default:
3387 Var_SetExpand(scope, expr->var->name.str, val); 3400 Var_SetExpand(scope, expr->var->name.str, val);
3388 break; 3401 break;
3389 } 3402 }
3390 } 3403 }
3391 free(val); 3404 free(val);
3392 Expr_SetValueRefer(expr, ""); 3405 Expr_SetValueRefer(expr, "");
3393 return AMR_OK; 3406 return AMR_OK;
3394} 3407}
3395 3408
3396/* 3409/*
3397 * :_=... 3410 * :_=...
3398 * remember current value 3411 * remember current value
3399 */ 3412 */
3400static ApplyModifierResult 3413static ApplyModifierResult
3401ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) 3414ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
3402{ 3415{
3403 Expr *expr = st->expr; 3416 Expr *expr = st->expr;
3404 const char *mod = *pp; 3417 const char *mod = *pp;
3405 if (!ModMatchEq(mod, "_", st)) 3418 if (!ModMatchEq(mod, "_", st))
3406 return AMR_UNKNOWN; 3419 return AMR_UNKNOWN;
3407 3420
3408 if (mod[1] == '=') { 3421 if (mod[1] == '=') {
3409 /* 3422 /*
3410 * XXX: This ad-hoc call to strcspn deviates from the usual 3423 * XXX: This ad-hoc call to strcspn deviates from the usual
3411 * behavior defined in ParseModifierPart. This creates an 3424 * behavior defined in ParseModifierPart. This creates an
3412 * unnecessary, undocumented inconsistency in make. 3425 * unnecessary, undocumented inconsistency in make.
3413 */ 3426 */
3414 size_t n = strcspn(mod + 2, ":)}"); 3427 size_t n = strcspn(mod + 2, ":)}");
3415 char *name = bmake_strldup(mod + 2, n); 3428 char *name = bmake_strldup(mod + 2, n);
 3429 *pp = mod + 2 + n;
 3430
 3431 /*
 3432 * FIXME: do not expand the variable name here; it would only
 3433 * work for single-character variable names anyway.
 3434 */
3416 Var_SetExpand(expr->scope, name, expr->value.str); 3435 Var_SetExpand(expr->scope, name, expr->value.str);
3417 free(name); 3436 free(name);
3418 *pp = mod + 2 + n; 
3419 } else { 3437 } else {
3420 Var_Set(expr->scope, "_", expr->value.str); 
3421 *pp = mod + 1; 3438 *pp = mod + 1;
 3439
 3440 Var_Set(expr->scope, "_", expr->value.str);
3422 } 3441 }
3423 return AMR_OK; 3442 return AMR_OK;
3424} 3443}
3425 3444
3426/* 3445/*
3427 * Apply the given function to each word of the variable value, 3446 * Apply the given function to each word of the variable value,
3428 * for a single-letter modifier such as :H, :T. 3447 * for a single-letter modifier such as :H, :T.
3429 */ 3448 */
3430static ApplyModifierResult 3449static ApplyModifierResult
3431ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, 3450ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
3432 ModifyWordProc modifyWord) 3451 ModifyWordProc modifyWord)
3433{ 3452{
3434 if (!IsDelimiter((*pp)[1], st)) 3453 if (!IsDelimiter((*pp)[1], st))
3435 return AMR_UNKNOWN; 3454 return AMR_UNKNOWN;
 3455 (*pp)++;
3436 3456
3437 ModifyWords(st, modifyWord, NULL, st->oneBigWord); 3457 ModifyWords(st, modifyWord, NULL, st->oneBigWord);
3438 (*pp)++; 3458
3439 return AMR_OK; 3459 return AMR_OK;
3440} 3460}
3441 3461
3442static ApplyModifierResult 3462static ApplyModifierResult
3443ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) 3463ApplyModifier_Unique(const char **pp, ApplyModifiersState *st)
3444{ 3464{
3445 if (!IsDelimiter((*pp)[1], st)) 3465 if (!IsDelimiter((*pp)[1], st))
3446 return AMR_UNKNOWN; 3466 return AMR_UNKNOWN;
3447 (*pp)++; 3467 (*pp)++;
3448 3468
3449 Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str)); 3469 Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str));
3450 3470
3451 return AMR_OK; 3471 return AMR_OK;
3452} 3472}
3453 3473
3454#ifdef SYSVVARSUB 3474#ifdef SYSVVARSUB
3455/* :from=to */ 3475/* :from=to */
3456static ApplyModifierResult 3476static ApplyModifierResult
3457ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) 3477ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
3458{ 3478{
3459 Expr *expr = st->expr; 3479 Expr *expr = st->expr;
3460 char *lhs, *rhs; 3480 char *lhs, *rhs;
3461 VarParseResult res; 3481 VarParseResult res;
3462 3482
3463 const char *mod = *pp; 3483 const char *mod = *pp;
3464 Boolean eqFound = FALSE; 3484 Boolean eqFound = FALSE;
3465 3485
3466 /* 3486 /*
3467 * First we make a pass through the string trying to verify it is a 3487 * First we make a pass through the string trying to verify it is a
3468 * SysV-make-style translation. It must be: <lhs>=<rhs> 3488 * SysV-make-style translation. It must be: <lhs>=<rhs>
3469 */ 3489 */
3470 int depth = 1; 3490 int depth = 1;
3471 const char *p = mod; 3491 const char *p = mod;
3472 while (*p != '\0' && depth > 0) { 3492 while (*p != '\0' && depth > 0) {
3473 if (*p == '=') { /* XXX: should also test depth == 1 */ 3493 if (*p == '=') { /* XXX: should also test depth == 1 */
3474 eqFound = TRUE; 3494 eqFound = TRUE;
3475 /* continue looking for st->endc */ 3495 /* continue looking for st->endc */
3476 } else if (*p == st->endc) 3496 } else if (*p == st->endc)
3477 depth--; 3497 depth--;
3478 else if (*p == st->startc) 3498 else if (*p == st->startc)
3479 depth++; 3499 depth++;
3480 if (depth > 0) 3500 if (depth > 0)
3481 p++; 3501 p++;
3482 } 3502 }
3483 if (*p != st->endc || !eqFound) 3503 if (*p != st->endc || !eqFound)
3484 return AMR_UNKNOWN; 3504 return AMR_UNKNOWN;
3485 3505
3486 res = ParseModifierPart(pp, '=', expr->eflags, st, &lhs); 3506 res = ParseModifierPart(pp, '=', expr->eflags, st, &lhs);
3487 if (res != VPR_OK) 3507 if (res != VPR_OK)
3488 return AMR_CLEANUP; 3508 return AMR_CLEANUP;
3489 3509
3490 /* The SysV modifier lasts until the end of the variable expression. */ 3510 /* The SysV modifier lasts until the end of the variable expression. */
3491 res = ParseModifierPart(pp, st->endc, expr->eflags, st, &rhs); 3511 res = ParseModifierPart(pp, st->endc, expr->eflags, st, &rhs);
3492 if (res != VPR_OK) 3512 if (res != VPR_OK)
3493 return AMR_CLEANUP; 3513 return AMR_CLEANUP;
3494 3514
3495 (*pp)--; /* Go back to the st->endc. */ 3515 (*pp)--; /* Go back to the st->endc. */
3496 3516
3497 if (lhs[0] == '\0' && expr->value.str[0] == '\0') { 3517 if (lhs[0] == '\0' && expr->value.str[0] == '\0') {
3498 /* Do not turn an empty expression into non-empty. */ 3518 /* Do not turn an empty expression into non-empty. */
3499 } else { 3519 } else {
3500 struct ModifyWord_SYSVSubstArgs args = { 3520 struct ModifyWord_SYSVSubstArgs args = {
3501 expr->scope, lhs, rhs 3521 expr->scope, lhs, rhs
3502 }; 3522 };
3503 ModifyWords(st, ModifyWord_SYSVSubst, &args, st->oneBigWord); 3523 ModifyWords(st, ModifyWord_SYSVSubst, &args, st->oneBigWord);
3504 } 3524 }
3505 free(lhs); 3525 free(lhs);
3506 free(rhs); 3526 free(rhs);
3507 return AMR_OK; 3527 return AMR_OK;
3508} 3528}
3509#endif 3529#endif
3510 3530
3511#ifdef SUNSHCMD 3531#ifdef SUNSHCMD
3512/* :sh */ 3532/* :sh */
3513static ApplyModifierResult 3533static ApplyModifierResult
3514ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) 3534ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st)
3515{ 3535{
3516 Expr *expr = st->expr; 3536 Expr *expr = st->expr;
3517 const char *p = *pp; 3537 const char *p = *pp;
3518 if (!(p[1] == 'h' && IsDelimiter(p[2], st))) 3538 if (!(p[1] == 'h' && IsDelimiter(p[2], st)))
3519 return AMR_UNKNOWN; 3539 return AMR_UNKNOWN;
 3540 *pp = p + 2;
3520 3541
3521 if (expr->eflags & VARE_WANTRES) { 3542 if (expr->eflags & VARE_WANTRES) {
3522 const char *errfmt; 3543 const char *errfmt;
3523 char *output = Cmd_Exec(expr->value.str, &errfmt); 3544 char *output = Cmd_Exec(expr->value.str, &errfmt);
3524 if (errfmt != NULL) 3545 if (errfmt != NULL)
3525 Error(errfmt, expr->value.str); 3546 Error(errfmt, expr->value.str);
3526 Expr_SetValueOwn(expr, output); 3547 Expr_SetValueOwn(expr, output);
3527 } else { 3548 } else {
3528 /* 3549 /*
3529 * TODO: Check whether returning ":sh" would be 3550 * TODO: Check whether returning ":sh" would be
3530 * more consistent with the other modifiers. 3551 * more consistent with the other modifiers.
3531 * 3552 *
3532 * TODO: Add a unit test demonstrating that the 3553 * TODO: Add a unit test demonstrating that the
3533 * actual value of this expression has any effect. 3554 * actual value of this expression has any effect.
3534 */ 3555 */
3535 Expr_SetValueRefer(expr, ""); 3556 Expr_SetValueRefer(expr, "");
3536 } 3557 }
3537 *pp = p + 2; 3558
3538 return AMR_OK; 3559 return AMR_OK;
3539} 3560}
3540#endif 3561#endif
3541 3562
3542static void 3563static void
3543LogBeforeApply(const ApplyModifiersState *st, const char *mod) 3564LogBeforeApply(const ApplyModifiersState *st, const char *mod)
3544{ 3565{
3545 const Expr *expr = st->expr; 3566 const Expr *expr = st->expr;
3546 char eflags_str[VarEvalFlags_ToStringSize]; 3567 char eflags_str[VarEvalFlags_ToStringSize];
3547 char vflags_str[VarFlags_ToStringSize]; 3568 char vflags_str[VarFlags_ToStringSize];
3548 Boolean is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], st); 3569 Boolean is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], st);
3549 3570
3550 /* At this point, only the first character of the modifier can 3571 /* At this point, only the first character of the modifier can
3551 * be used since the end of the modifier is not yet known. */ 3572 * be used since the end of the modifier is not yet known. */
3552 debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n", 3573 debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n",
3553 expr->var->name.str, mod[0], is_single_char ? "" : "...", 3574 expr->var->name.str, mod[0], is_single_char ? "" : "...",
3554 expr->value.str, 3575 expr->value.str,
3555 VarEvalFlags_ToString(eflags_str, expr->eflags), 3576 VarEvalFlags_ToString(eflags_str, expr->eflags),
3556 VarFlags_ToString(vflags_str, expr->var->flags), 3577 VarFlags_ToString(vflags_str, expr->var->flags),
3557 ExprDefined_Name[expr->defined]); 3578 ExprDefined_Name[expr->defined]);
3558} 3579}
3559 3580
3560static void 3581static void
3561LogAfterApply(const ApplyModifiersState *st, const char *p, const char *mod) 3582LogAfterApply(const ApplyModifiersState *st, const char *p, const char *mod)
3562{ 3583{
3563 const Expr *expr = st->expr; 3584 const Expr *expr = st->expr;
3564 const char *value = expr->value.str; 3585 const char *value = expr->value.str;
3565 char eflags_str[VarEvalFlags_ToStringSize]; 3586 char eflags_str[VarEvalFlags_ToStringSize];
3566 char vflags_str[VarFlags_ToStringSize]; 3587 char vflags_str[VarFlags_ToStringSize];
3567 const char *quot = value == var_Error ? "" : "\""; 3588 const char *quot = value == var_Error ? "" : "\"";
3568 3589
3569 debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n", 3590 debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n",
3570 expr->var->name.str, (int)(p - mod), mod, 3591 expr->var->name.str, (int)(p - mod), mod,
3571 quot, value == var_Error ? "error" : value, quot, 3592 quot, value == var_Error ? "error" : value, quot,
3572 VarEvalFlags_ToString(eflags_str, expr->eflags), 3593 VarEvalFlags_ToString(eflags_str, expr->eflags),
3573 VarFlags_ToString(vflags_str, expr->var->flags), 3594 VarFlags_ToString(vflags_str, expr->var->flags),
3574 ExprDefined_Name[expr->defined]); 3595 ExprDefined_Name[expr->defined]);
3575} 3596}
3576 3597
3577static ApplyModifierResult 3598static ApplyModifierResult
3578ApplyModifier(const char **pp, ApplyModifiersState *st) 3599ApplyModifier(const char **pp, ApplyModifiersState *st)
3579{ 3600{
3580 switch (**pp) { 3601 switch (**pp) {
3581 case '!': 3602 case '!':
3582 return ApplyModifier_ShellCommand(pp, st); 3603 return ApplyModifier_ShellCommand(pp, st);
3583 case ':': 3604 case ':':
3584 return ApplyModifier_Assign(pp, st); 3605 return ApplyModifier_Assign(pp, st);
3585 case '?': 3606 case '?':
3586 return ApplyModifier_IfElse(pp, st); 3607 return ApplyModifier_IfElse(pp, st);
3587 case '@': 3608 case '@':
3588 return ApplyModifier_Loop(pp, st); 3609 return ApplyModifier_Loop(pp, st);
3589 case '[': 3610 case '[':
3590 return ApplyModifier_Words(pp, st); 3611 return ApplyModifier_Words(pp, st);
3591 case '_': 3612 case '_':
3592 return ApplyModifier_Remember(pp, st); 3613 return ApplyModifier_Remember(pp, st);
3593#ifndef NO_REGEX 3614#ifndef NO_REGEX
3594 case 'C': 3615 case 'C':
3595 return ApplyModifier_Regex(pp, st); 3616 return ApplyModifier_Regex(pp, st);
3596#endif 3617#endif
3597 case 'D': 3618 case 'D':
3598 return ApplyModifier_Defined(pp, st); 3619 return ApplyModifier_Defined(pp, st);
3599 case 'E': 3620 case 'E':
3600 return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix); 3621 return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix);
3601 case 'g': 3622 case 'g':
3602 return ApplyModifier_Gmtime(pp, st); 3623 return ApplyModifier_Gmtime(pp, st);
3603 case 'H': 3624 case 'H':
3604 return ApplyModifier_WordFunc(pp, st, ModifyWord_Head); 3625 return ApplyModifier_WordFunc(pp, st, ModifyWord_Head);
3605 case 'h': 3626 case 'h':
3606 return ApplyModifier_Hash(pp, st); 3627 return ApplyModifier_Hash(pp, st);
3607 case 'L': 3628 case 'L':
3608 return ApplyModifier_Literal(pp, st); 3629 return ApplyModifier_Literal(pp, st);
3609 case 'l': 3630 case 'l':
3610 return ApplyModifier_Localtime(pp, st); 3631 return ApplyModifier_Localtime(pp, st);
3611 case 'M': 3632 case 'M':
3612 case 'N': 3633 case 'N':
3613 return ApplyModifier_Match(pp, st); 3634 return ApplyModifier_Match(pp, st);
3614 case 'O': 3635 case 'O':
3615 return ApplyModifier_Order(pp, st); 3636 return ApplyModifier_Order(pp, st);
3616 case 'P': 3637 case 'P':
3617 return ApplyModifier_Path(pp, st); 3638 return ApplyModifier_Path(pp, st);
3618 case 'Q': 3639 case 'Q':
3619 case 'q': 3640 case 'q':
3620 return ApplyModifier_Quote(pp, st); 3641 return ApplyModifier_Quote(pp, st);
3621 case 'R': 3642 case 'R':
3622 return ApplyModifier_WordFunc(pp, st, ModifyWord_Root); 3643 return ApplyModifier_WordFunc(pp, st, ModifyWord_Root);
3623 case 'r': 3644 case 'r':
3624 return ApplyModifier_Range(pp, st); 3645 return ApplyModifier_Range(pp, st);
3625 case 'S': 3646 case 'S':
3626 return ApplyModifier_Subst(pp, st); 3647 return ApplyModifier_Subst(pp, st);
3627#ifdef SUNSHCMD 3648#ifdef SUNSHCMD
3628 case 's': 3649 case 's':
3629 return ApplyModifier_SunShell(pp, st); 3650 return ApplyModifier_SunShell(pp, st);
3630#endif 3651#endif
3631 case 'T': 3652 case 'T':
3632 return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail); 3653 return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail);
3633 case 't': 3654 case 't':
3634 return ApplyModifier_To(pp, st); 3655 return ApplyModifier_To(pp, st);
3635 case 'U': 3656 case 'U':
3636 return ApplyModifier_Defined(pp, st); 3657 return ApplyModifier_Defined(pp, st);
3637 case 'u': 3658 case 'u':
3638 return ApplyModifier_Unique(pp, st); 3659 return ApplyModifier_Unique(pp, st);
3639 default: 3660 default:
3640 return AMR_UNKNOWN; 3661 return AMR_UNKNOWN;
3641 } 3662 }
3642} 3663}
3643 3664
3644static void ApplyModifiers(Expr *, const char **, char, char); 3665static void ApplyModifiers(Expr *, const char **, char, char);
3645 3666
3646typedef enum ApplyModifiersIndirectResult { 3667typedef enum ApplyModifiersIndirectResult {
3647 /* The indirect modifiers have been applied successfully. */ 3668 /* The indirect modifiers have been applied successfully. */
3648 AMIR_CONTINUE, 3669 AMIR_CONTINUE,
3649 /* Fall back to the SysV modifier. */ 3670 /* Fall back to the SysV modifier. */
3650 AMIR_SYSV, 3671 AMIR_SYSV,
3651 /* Error out. */ 3672 /* Error out. */
3652 AMIR_OUT 3673 AMIR_OUT
3653} ApplyModifiersIndirectResult; 3674} ApplyModifiersIndirectResult;
3654 3675
3655/* 3676/*
3656 * While expanding a variable expression, expand and apply indirect modifiers, 3677 * While expanding a variable expression, expand and apply indirect modifiers,
3657 * such as in ${VAR:${M_indirect}}. 3678 * such as in ${VAR:${M_indirect}}.
3658 * 3679 *
3659 * All indirect modifiers of a group must come from a single variable 3680 * All indirect modifiers of a group must come from a single variable
3660 * expression. ${VAR:${M1}} is valid but ${VAR:${M1}${M2}} is not. 3681 * expression. ${VAR:${M1}} is valid but ${VAR:${M1}${M2}} is not.
3661 * 3682 *
3662 * Multiple groups of indirect modifiers can be chained by separating them 3683 * Multiple groups of indirect modifiers can be chained by separating them
3663 * with colons. ${VAR:${M1}:${M2}} contains 2 indirect modifiers. 3684 * with colons. ${VAR:${M1}:${M2}} contains 2 indirect modifiers.
3664 * 3685 *
3665 * If the variable expression is not followed by st->endc or ':', fall 3686 * If the variable expression is not followed by st->endc or ':', fall
3666 * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}. 3687 * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}.
3667 */ 3688 */
3668static ApplyModifiersIndirectResult 3689static ApplyModifiersIndirectResult
3669ApplyModifiersIndirect(ApplyModifiersState *st, const char **pp) 3690ApplyModifiersIndirect(ApplyModifiersState *st, const char **pp)
3670{ 3691{
3671 Expr *expr = st->expr; 3692 Expr *expr = st->expr;
3672 const char *p = *pp; 3693 const char *p = *pp;
3673 FStr mods; 3694 FStr mods;
3674 3695
3675 (void)Var_Parse(&p, expr->scope, expr->eflags, &mods); 3696 (void)Var_Parse(&p, expr->scope, expr->eflags, &mods);
3676 /* TODO: handle errors */ 3697 /* TODO: handle errors */
3677 3698
3678 if (mods.str[0] != '\0' && *p != '\0' && !IsDelimiter(*p, st)) { 3699 if (mods.str[0] != '\0' && *p != '\0' && !IsDelimiter(*p, st)) {
3679 FStr_Done(&mods); 3700 FStr_Done(&mods);
3680 return AMIR_SYSV; 3701 return AMIR_SYSV;
3681 } 3702 }
3682 3703
3683 DEBUG3(VAR, "Indirect modifier \"%s\" from \"%.*s\"\n", 3704 DEBUG3(VAR, "Indirect modifier \"%s\" from \"%.*s\"\n",
3684 mods.str, (int)(p - *pp), *pp); 3705 mods.str, (int)(p - *pp), *pp);
3685 3706
3686 if (mods.str[0] != '\0') { 3707 if (mods.str[0] != '\0') {
3687 const char *modsp = mods.str; 3708 const char *modsp = mods.str;
3688 ApplyModifiers(expr, &modsp, '\0', '\0'); 3709 ApplyModifiers(expr, &modsp, '\0', '\0');
3689 if (expr->value.str == var_Error || *modsp != '\0') { 3710 if (expr->value.str == var_Error || *modsp != '\0') {
3690 FStr_Done(&mods); 3711 FStr_Done(&mods);
3691 *pp = p; 3712 *pp = p;
3692 return AMIR_OUT; /* error already reported */ 3713 return AMIR_OUT; /* error already reported */
3693 } 3714 }
3694 } 3715 }
3695 FStr_Done(&mods); 3716 FStr_Done(&mods);
3696 3717
3697 if (*p == ':') 3718 if (*p == ':')
3698 p++; 3719 p++;
3699 else if (*p == '\0' && st->endc != '\0') { 3720 else if (*p == '\0' && st->endc != '\0') {
3700 Error("Unclosed variable expression after indirect " 3721 Error("Unclosed variable expression after indirect "
3701 "modifier, expecting '%c' for variable \"%s\"", 3722 "modifier, expecting '%c' for variable \"%s\"",
3702 st->endc, expr->var->name.str); 3723 st->endc, expr->var->name.str);
3703 *pp = p; 3724 *pp = p;
3704 return AMIR_OUT; 3725 return AMIR_OUT;
3705 } 3726 }
3706 3727
3707 *pp = p; 3728 *pp = p;
3708 return AMIR_CONTINUE; 3729 return AMIR_CONTINUE;
3709} 3730}
3710 3731
3711static ApplyModifierResult 3732static ApplyModifierResult
3712ApplySingleModifier(const char **pp, ApplyModifiersState *st) 3733ApplySingleModifier(const char **pp, ApplyModifiersState *st)
3713{ 3734{
3714 ApplyModifierResult res; 3735 ApplyModifierResult res;
3715 const char *mod = *pp; 3736 const char *mod = *pp;
3716 const char *p = *pp; 3737 const char *p = *pp;
3717 3738
3718 if (DEBUG(VAR)) 3739 if (DEBUG(VAR))
3719 LogBeforeApply(st, mod); 3740 LogBeforeApply(st, mod);
3720 3741
3721 res = ApplyModifier(&p, st); 3742 res = ApplyModifier(&p, st);
3722 3743
3723#ifdef SYSVVARSUB 3744#ifdef SYSVVARSUB
3724 if (res == AMR_UNKNOWN) { 3745 if (res == AMR_UNKNOWN) {
3725 assert(p == mod); 3746 assert(p == mod);
3726 res = ApplyModifier_SysV(&p, st); 3747 res = ApplyModifier_SysV(&p, st);
3727 } 3748 }
3728#endif 3749#endif
3729 3750
3730 if (res == AMR_UNKNOWN) { 3751 if (res == AMR_UNKNOWN) {
3731 /* 3752 /*
3732 * Guess the end of the current modifier. 3753 * Guess the end of the current modifier.
3733 * XXX: Skipping the rest of the modifier hides 3754 * XXX: Skipping the rest of the modifier hides
3734 * errors and leads to wrong results. 3755 * errors and leads to wrong results.
3735 * Parsing should rather stop here. 3756 * Parsing should rather stop here.
3736 */ 3757 */
3737 for (p++; !IsDelimiter(*p, st) && *p != '\0'; p++) 3758 for (p++; !IsDelimiter(*p, st) && *p != '\0'; p++)
3738 continue; 3759 continue;
3739 Parse_Error(PARSE_FATAL, "Unknown modifier \"%.*s\"", 3760 Parse_Error(PARSE_FATAL, "Unknown modifier \"%.*s\"",
3740 (int)(p - mod), mod); 3761 (int)(p - mod), mod);
3741 Expr_SetValueRefer(st->expr, var_Error); 3762 Expr_SetValueRefer(st->expr, var_Error);
3742 } 3763 }
3743 if (res == AMR_CLEANUP || res == AMR_BAD) { 3764 if (res == AMR_CLEANUP || res == AMR_BAD) {
3744 *pp = p; 3765 *pp = p;
3745 return res; 3766 return res;
3746 } 3767 }
3747 3768
3748 if (DEBUG(VAR)) 3769 if (DEBUG(VAR))
3749 LogAfterApply(st, p, mod); 3770 LogAfterApply(st, p, mod);
3750 3771
3751 if (*p == '\0' && st->endc != '\0') { 3772 if (*p == '\0' && st->endc != '\0') {
3752 Error( 3773 Error(
3753 "Unclosed variable expression, expecting '%c' for " 3774 "Unclosed variable expression, expecting '%c' for "
3754 "modifier \"%.*s\" of variable \"%s\" with value \"%s\"", 3775 "modifier \"%.*s\" of variable \"%s\" with value \"%s\"",
3755 st->endc, 3776 st->endc,
3756 (int)(p - mod), mod, 3777 (int)(p - mod), mod,
3757 st->expr->var->name.str, st->expr->value.str); 3778 st->expr->var->name.str, st->expr->value.str);
3758 } else if (*p == ':') { 3779 } else if (*p == ':') {
3759 p++; 3780 p++;
3760 } else if (opts.strict && *p != '\0' && *p != st->endc) { 3781 } else if (opts.strict && *p != '\0' && *p != st->endc) {
3761 Parse_Error(PARSE_FATAL, 3782 Parse_Error(PARSE_FATAL,
3762 "Missing delimiter ':' after modifier \"%.*s\"", 3783 "Missing delimiter ':' after modifier \"%.*s\"",
3763 (int)(p - mod), mod); 3784 (int)(p - mod), mod);
3764 /* 3785 /*
3765 * TODO: propagate parse error to the enclosing 3786 * TODO: propagate parse error to the enclosing
3766 * expression 3787 * expression
3767 */ 3788 */
3768 } 3789 }
3769 *pp = p; 3790 *pp = p;
3770 return AMR_OK; 3791 return AMR_OK;
3771} 3792}
3772 3793
3773/* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ 3794/* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
3774static void 3795static void
3775ApplyModifiers( 3796ApplyModifiers(
3776 Expr *expr, 3797 Expr *expr,
3777 const char **pp, /* the parsing position, updated upon return */ 3798 const char **pp, /* the parsing position, updated upon return */
3778 char startc, /* '(' or '{'; or '\0' for indirect modifiers */ 3799 char startc, /* '(' or '{'; or '\0' for indirect modifiers */
3779 char endc /* ')' or '}'; or '\0' for indirect modifiers */ 3800 char endc /* ')' or '}'; or '\0' for indirect modifiers */
3780) 3801)
3781{ 3802{
3782 ApplyModifiersState st = { 3803 ApplyModifiersState st = {
3783 expr, 3804 expr,
3784 startc, 3805 startc,
3785 endc, 3806 endc,
3786 ' ', /* .sep */ 3807 ' ', /* .sep */
3787 FALSE /* .oneBigWord */ 3808 FALSE /* .oneBigWord */
3788 }; 3809 };
3789 const char *p; 3810 const char *p;
3790 const char *mod; 3811 const char *mod;
3791 3812
3792 assert(startc == '(' || startc == '{' || startc == '\0'); 3813 assert(startc == '(' || startc == '{' || startc == '\0');
3793 assert(endc == ')' || endc == '}' || endc == '\0'); 3814 assert(endc == ')' || endc == '}' || endc == '\0');
3794 assert(expr->value.str != NULL); 3815 assert(expr->value.str != NULL);
3795 3816
3796 p = *pp; 3817 p = *pp;
3797 3818
3798 if (*p == '\0' && endc != '\0') { 3819 if (*p == '\0' && endc != '\0') {
3799 Error( 3820 Error(
3800 "Unclosed variable expression (expecting '%c') for \"%s\"", 3821 "Unclosed variable expression (expecting '%c') for \"%s\"",
3801 st.endc, expr->var->name.str); 3822 st.endc, expr->var->name.str);
3802 goto cleanup; 3823 goto cleanup;
3803 } 3824 }
3804 3825
3805 while (*p != '\0' && *p != endc) { 3826 while (*p != '\0' && *p != endc) {
3806 ApplyModifierResult res; 3827 ApplyModifierResult res;
3807 3828
3808 if (*p == '$') { 3829 if (*p == '$') {
3809 ApplyModifiersIndirectResult amir = 3830 ApplyModifiersIndirectResult amir =
3810 ApplyModifiersIndirect(&st, &p); 3831 ApplyModifiersIndirect(&st, &p);
3811 if (amir == AMIR_CONTINUE) 3832 if (amir == AMIR_CONTINUE)
3812 continue; 3833 continue;
3813 if (amir == AMIR_OUT) 3834 if (amir == AMIR_OUT)
3814 break; 3835 break;
3815 /* 3836 /*
3816 * It's neither '${VAR}:' nor '${VAR}}'. Try to parse 3837 * It's neither '${VAR}:' nor '${VAR}}'. Try to parse
3817 * it as a SysV modifier, as that is the only modifier 3838 * it as a SysV modifier, as that is the only modifier
3818 * that can start with '$'. 3839 * that can start with '$'.
3819 */ 3840 */
3820 } 3841 }
3821 3842
3822 mod = p; 3843 mod = p;
3823 3844
3824 res = ApplySingleModifier(&p, &st); 3845 res = ApplySingleModifier(&p, &st);
3825 if (res == AMR_CLEANUP) 3846 if (res == AMR_CLEANUP)
3826 goto cleanup; 3847 goto cleanup;
3827 if (res == AMR_BAD) 3848 if (res == AMR_BAD)
3828 goto bad_modifier; 3849 goto bad_modifier;
3829 } 3850 }
3830 3851
3831 *pp = p; 3852 *pp = p;
3832 assert(expr->value.str != NULL); /* Use var_Error or varUndefined. */ 3853 assert(expr->value.str != NULL); /* Use var_Error or varUndefined. */
3833 return; 3854 return;
3834 3855
3835bad_modifier: 3856bad_modifier:
3836 /* XXX: The modifier end is only guessed. */ 3857 /* XXX: The modifier end is only guessed. */
3837 Error("Bad modifier \":%.*s\" for variable \"%s\"", 3858 Error("Bad modifier \":%.*s\" for variable \"%s\"",
3838 (int)strcspn(mod, ":)}"), mod, expr->var->name.str); 3859 (int)strcspn(mod, ":)}"), mod, expr->var->name.str);
3839 3860
3840cleanup: 3861cleanup:
3841 /* 3862 /*
3842 * TODO: Use p + strlen(p) instead, to stop parsing immediately. 3863 * TODO: Use p + strlen(p) instead, to stop parsing immediately.
3843 * 3864 *
3844 * In the unit tests, this generates a few unterminated strings in the 3865 * In the unit tests, this generates a few unterminated strings in the
3845 * shell commands though. Instead of producing these unfinished 3866 * shell commands though. Instead of producing these unfinished
3846 * strings, commands with evaluation errors should not be run at all. 3867 * strings, commands with evaluation errors should not be run at all.
3847 * 3868 *
3848 * To make that happen, Var_Subst must report the actual errors 3869 * To make that happen, Var_Subst must report the actual errors
3849 * instead of returning VPR_OK unconditionally. 3870 * instead of returning VPR_OK unconditionally.
3850 */ 3871 */
3851 *pp = p; 3872 *pp = p;
3852 Expr_SetValueRefer(expr, var_Error); 3873 Expr_SetValueRefer(expr, var_Error);
3853} 3874}
3854 3875
3855/* 3876/*
3856 * Only four of the local variables are treated specially as they are the 3877 * Only four of the local variables are treated specially as they are the
3857 * only four that will be set when dynamic sources are expanded. 3878 * only four that will be set when dynamic sources are expanded.
3858 */ 3879 */
3859static Boolean 3880static Boolean
3860VarnameIsDynamic(const char *name, size_t len) 3881VarnameIsDynamic(const char *name, size_t len)
3861{ 3882{
3862 if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) { 3883 if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
3863 switch (name[0]) { 3884 switch (name[0]) {
3864 case '@': 3885 case '@':
3865 case '%': 3886 case '%':
3866 case '*': 3887 case '*':
3867 case '!': 3888 case '!':
3868 return TRUE; 3889 return TRUE;
3869 } 3890 }
3870 return FALSE; 3891 return FALSE;
3871 } 3892 }
3872 3893
3873 if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) { 3894 if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
3874 return strcmp(name, ".TARGET") == 0 || 3895 return strcmp(name, ".TARGET") == 0 ||
3875 strcmp(name, ".ARCHIVE") == 0 || 3896 strcmp(name, ".ARCHIVE") == 0 ||
3876 strcmp(name, ".PREFIX") == 0 || 3897 strcmp(name, ".PREFIX") == 0 ||
3877 strcmp(name, ".MEMBER") == 0; 3898 strcmp(name, ".MEMBER") == 0;
3878 } 3899 }
3879 3900
3880 return FALSE; 3901 return FALSE;
3881} 3902}
3882 3903
3883static const char * 3904static const char *
3884UndefinedShortVarValue(char varname, const GNode *scope) 3905UndefinedShortVarValue(char varname, const GNode *scope)
3885{ 3906{
3886 if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) { 3907 if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) {
3887 /* 3908 /*
3888 * If substituting a local variable in a non-local scope, 3909 * If substituting a local variable in a non-local scope,
3889 * assume it's for dynamic source stuff. We have to handle 3910 * assume it's for dynamic source stuff. We have to handle
3890 * this specially and return the longhand for the variable 3911 * this specially and return the longhand for the variable
3891 * with the dollar sign escaped so it makes it back to the 3912 * with the dollar sign escaped so it makes it back to the
3892 * caller. Only four of the local variables are treated 3913 * caller. Only four of the local variables are treated
3893 * specially as they are the only four that will be set 3914 * specially as they are the only four that will be set
3894 * when dynamic sources are expanded. 3915 * when dynamic sources are expanded.
3895 */ 3916 */
3896 switch (varname) { 3917 switch (varname) {
3897 case '@': 3918 case '@':
3898 return "$(.TARGET)"; 3919 return "$(.TARGET)";
3899 case '%': 3920 case '%':
3900 return "$(.MEMBER)"; 3921 return "$(.MEMBER)";
3901 case '*': 3922 case '*':
3902 return "$(.PREFIX)"; 3923 return "$(.PREFIX)";
3903 case '!': 3924 case '!':
3904 return "$(.ARCHIVE)"; 3925 return "$(.ARCHIVE)";
3905 } 3926 }
3906 } 3927 }
3907 return NULL; 3928 return NULL;
3908} 3929}
3909 3930
3910/* 3931/*
3911 * Parse a variable name, until the end character or a colon, whichever 3932 * Parse a variable name, until the end character or a colon, whichever
3912 * comes first. 3933 * comes first.
3913 */ 3934 */
3914static char * 3935static char *
3915ParseVarname(const char **pp, char startc, char endc, 3936ParseVarname(const char **pp, char startc, char endc,
3916 GNode *scope, VarEvalFlags eflags, 3937 GNode *scope, VarEvalFlags eflags,
3917 size_t *out_varname_len) 3938 size_t *out_varname_len)
3918{ 3939{
3919 Buffer buf; 3940 Buffer buf;
3920 const char *p = *pp; 3941 const char *p = *pp;
3921 int depth = 0; /* Track depth so we can spot parse errors. */ 3942 int depth = 0; /* Track depth so we can spot parse errors. */
3922 3943
3923 Buf_Init(&buf); 3944 Buf_Init(&buf);
3924 3945
3925 while (*p != '\0') { 3946 while (*p != '\0') {
3926 if ((*p == endc || *p == ':') && depth == 0) 3947 if ((*p == endc || *p == ':') && depth == 0)
3927 break; 3948 break;
3928 if (*p == startc) 3949 if (*p == startc)
3929 depth++; 3950 depth++;
3930 if (*p == endc) 3951 if (*p == endc)
3931 depth--; 3952 depth--;
3932 3953
3933 /* A variable inside a variable, expand. */ 3954 /* A variable inside a variable, expand. */
3934 if (*p == '$') { 3955 if (*p == '$') {
3935 FStr nested_val; 3956 FStr nested_val;
3936 (void)Var_Parse(&p, scope, eflags, &nested_val); 3957 (void)Var_Parse(&p, scope, eflags, &nested_val);
3937 /* TODO: handle errors */ 3958 /* TODO: handle errors */
3938 Buf_AddStr(&buf, nested_val.str); 3959 Buf_AddStr(&buf, nested_val.str);
3939 FStr_Done(&nested_val); 3960 FStr_Done(&nested_val);
3940 } else { 3961 } else {
3941 Buf_AddByte(&buf, *p); 3962 Buf_AddByte(&buf, *p);
3942 p++; 3963 p++;
3943 } 3964 }
3944 } 3965 }
3945 *pp = p; 3966 *pp = p;
3946 *out_varname_len = buf.len; 3967 *out_varname_len = buf.len;
3947 return Buf_DoneData(&buf); 3968 return Buf_DoneData(&buf);
3948} 3969}
3949 3970
3950static VarParseResult 3971static VarParseResult
3951ValidShortVarname(char varname, const char *start) 3972ValidShortVarname(char varname, const char *start)
3952{ 3973{
3953 if (varname != '$' && varname != ':' && varname != '}' && 3974 if (varname != '$' && varname != ':' && varname != '}' &&
3954 varname != ')' && varname != '\0') 3975 varname != ')' && varname != '\0')
3955 return VPR_OK; 3976 return VPR_OK;
3956 3977
3957 if (!opts.strict) 3978 if (!opts.strict)
3958 return VPR_ERR; /* XXX: Missing error message */ 3979 return VPR_ERR; /* XXX: Missing error message */
3959 3980
3960 if (varname == '$') 3981 if (varname == '$')
3961 Parse_Error(PARSE_FATAL, 3982 Parse_Error(PARSE_FATAL,
3962 "To escape a dollar, use \\$, not $$, at \"%s\"", start); 3983 "To escape a dollar, use \\$, not $$, at \"%s\"", start);
3963 else if (varname == '\0') 3984 else if (varname == '\0')
3964 Parse_Error(PARSE_FATAL, "Dollar followed by nothing"); 3985 Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
3965 else 3986 else
3966 Parse_Error(PARSE_FATAL, 3987 Parse_Error(PARSE_FATAL,
3967 "Invalid variable name '%c', at \"%s\"", varname, start); 3988 "Invalid variable name '%c', at \"%s\"", varname, start);
3968 3989
3969 return VPR_ERR; 3990 return VPR_ERR;
3970} 3991}
3971 3992
3972/* 3993/*
3973 * Parse a single-character variable name such as in $V or $@. 3994 * Parse a single-character variable name such as in $V or $@.
3974 * Return whether to continue parsing. 3995 * Return whether to continue parsing.
3975 */ 3996 */
3976static Boolean 3997static Boolean
3977ParseVarnameShort(char varname, const char **pp, GNode *scope, 3998ParseVarnameShort(char varname, const char **pp, GNode *scope,
3978 VarEvalFlags eflags, 3999 VarEvalFlags eflags,
3979 VarParseResult *out_FALSE_res, const char **out_FALSE_val, 4000 VarParseResult *out_FALSE_res, const char **out_FALSE_val,
3980 Var **out_TRUE_var) 4001 Var **out_TRUE_var)
3981{ 4002{
3982 char name[2]; 4003 char name[2];
3983 Var *v; 4004 Var *v;
3984 VarParseResult vpr; 4005 VarParseResult vpr;
3985 4006
3986 vpr = ValidShortVarname(varname, *pp); 4007 vpr = ValidShortVarname(varname, *pp);
3987 if (vpr != VPR_OK) { 4008 if (vpr != VPR_OK) {
3988 (*pp)++; 4009 (*pp)++;
3989 *out_FALSE_res = vpr; 4010 *out_FALSE_res = vpr;
3990 *out_FALSE_val = var_Error; 4011 *out_FALSE_val = var_Error;
3991 return FALSE; 4012 return FALSE;
3992 } 4013 }
3993 4014
3994 name[0] = varname; 4015 name[0] = varname;
3995 name[1] = '\0'; 4016 name[1] = '\0';
3996 v = VarFind(name, scope, TRUE); 4017 v = VarFind(name, scope, TRUE);
3997 if (v == NULL) { 4018 if (v == NULL) {
3998 const char *val; 4019 const char *val;
3999 *pp += 2; 4020 *pp += 2;
4000 4021
4001 val = UndefinedShortVarValue(varname, scope); 4022 val = UndefinedShortVarValue(varname, scope);
4002 if (val == NULL) 4023 if (val == NULL)
4003 val = eflags & VARE_UNDEFERR ? var_Error : varUndefined; 4024 val = eflags & VARE_UNDEFERR ? var_Error : varUndefined;
4004 4025
4005 if (opts.strict && val == var_Error) { 4026 if (opts.strict && val == var_Error) {
4006 Parse_Error(PARSE_FATAL, 4027 Parse_Error(PARSE_FATAL,
4007 "Variable \"%s\" is undefined", name); 4028 "Variable \"%s\" is undefined", name);
4008 *out_FALSE_res = VPR_ERR; 4029 *out_FALSE_res = VPR_ERR;
4009 *out_FALSE_val = val; 4030 *out_FALSE_val = val;
4010 return FALSE; 4031 return FALSE;
4011 } 4032 }
4012 4033
4013 /* 4034 /*
4014 * XXX: This looks completely wrong. 4035 * XXX: This looks completely wrong.
4015 * 4036 *
4016 * If undefined expressions are not allowed, this should 4037 * If undefined expressions are not allowed, this should
4017 * rather be VPR_ERR instead of VPR_UNDEF, together with an 4038 * rather be VPR_ERR instead of VPR_UNDEF, together with an
4018 * error message. 4039 * error message.
4019 * 4040 *
4020 * If undefined expressions are allowed, this should rather 4041 * If undefined expressions are allowed, this should rather
4021 * be VPR_UNDEF instead of VPR_OK. 4042 * be VPR_UNDEF instead of VPR_OK.
4022 */ 4043 */
4023 *out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF : VPR_OK; 4044 *out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF : VPR_OK;
4024 *out_FALSE_val = val; 4045 *out_FALSE_val = val;
4025 return FALSE; 4046 return FALSE;
4026 } 4047 }
4027 4048
4028 *out_TRUE_var = v; 4049 *out_TRUE_var = v;
4029 return TRUE; 4050 return TRUE;
4030} 4051}
4031 4052
4032/* Find variables like @F or <D. */ 4053/* Find variables like @F or <D. */
4033static Var * 4054static Var *
4034FindLocalLegacyVar(const char *varname, size_t namelen, GNode *scope, 4055FindLocalLegacyVar(const char *varname, size_t namelen, GNode *scope,
4035 const char **out_extraModifiers) 4056 const char **out_extraModifiers)
4036{ 4057{
4037 /* Only resolve these variables if scope is a "real" target. */ 4058 /* Only resolve these variables if scope is a "real" target. */
4038 if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) 4059 if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL)
4039 return NULL; 4060 return NULL;
4040 4061
4041 if (namelen != 2) 4062 if (namelen != 2)
4042 return NULL; 4063 return NULL;
4043 if (varname[1] != 'F' && varname[1] != 'D') 4064 if (varname[1] != 'F' && varname[1] != 'D')
4044 return NULL; 4065 return NULL;
4045 if (strchr("@%?*!<>", varname[0]) == NULL) 4066 if (strchr("@%?*!<>", varname[0]) == NULL)
4046 return NULL; 4067 return NULL;
4047 4068
4048 { 4069 {
4049 char name[] = { varname[0], '\0' }; 4070 char name[] = { varname[0], '\0' };
4050 Var *v = VarFind(name, scope, FALSE); 4071 Var *v = VarFind(name, scope, FALSE);
4051 4072
4052 if (v != NULL) { 4073 if (v != NULL) {
4053 if (varname[1] == 'D') { 4074 if (varname[1] == 'D') {
4054 *out_extraModifiers = "H:"; 4075 *out_extraModifiers = "H:";
4055 } else { /* F */ 4076 } else { /* F */
4056 *out_extraModifiers = "T:"; 4077 *out_extraModifiers = "T:";
4057 } 4078 }
4058 } 4079 }
4059 return v; 4080 return v;
4060 } 4081 }
4061} 4082}
4062 4083
4063static VarParseResult 4084static VarParseResult
4064EvalUndefined(Boolean dynamic, const char *start, const char *p, char *varname, 4085EvalUndefined(Boolean dynamic, const char *start, const char *p, char *varname,
4065 VarEvalFlags eflags, 4086 VarEvalFlags eflags,
4066 FStr *out_val) 4087 FStr *out_val)
4067{ 4088{
4068 if (dynamic) { 4089 if (dynamic) {
4069 *out_val = FStr_InitOwn(bmake_strsedup(start, p)); 4090 *out_val = FStr_InitOwn(bmake_strsedup(start, p));
4070 free(varname); 4091 free(varname);
4071 return VPR_OK; 4092 return VPR_OK;
4072 } 4093 }
4073 4094
4074 if ((eflags & VARE_UNDEFERR) && opts.strict) { 4095 if ((eflags & VARE_UNDEFERR) && opts.strict) {
4075 Parse_Error(PARSE_FATAL, 4096 Parse_Error(PARSE_FATAL,
4076 "Variable \"%s\" is undefined", varname); 4097 "Variable \"%s\" is undefined", varname);
4077 free(varname); 4098 free(varname);
4078 *out_val = FStr_InitRefer(var_Error); 4099 *out_val = FStr_InitRefer(var_Error);
4079 return VPR_ERR; 4100 return VPR_ERR;
4080 } 4101 }
4081 4102
4082 if (eflags & VARE_UNDEFERR) { 4103 if (eflags & VARE_UNDEFERR) {
4083 free(varname); 4104 free(varname);
4084 *out_val = FStr_InitRefer(var_Error); 4105 *out_val = FStr_InitRefer(var_Error);
4085 return VPR_UNDEF; /* XXX: Should be VPR_ERR instead. */ 4106 return VPR_UNDEF; /* XXX: Should be VPR_ERR instead. */
4086 } 4107 }
4087 4108
4088 free(varname); 4109 free(varname);
4089 *out_val = FStr_InitRefer(varUndefined); 4110 *out_val = FStr_InitRefer(varUndefined);
4090 return VPR_OK; 4111 return VPR_OK;
4091} 4112}
4092 4113
4093/* 4114/*
4094 * Parse a long variable name enclosed in braces or parentheses such as $(VAR) 4115 * Parse a long variable name enclosed in braces or parentheses such as $(VAR)
4095 * or ${VAR}, up to the closing brace or parenthesis, or in the case of 4116 * or ${VAR}, up to the closing brace or parenthesis, or in the case of
4096 * ${VAR:Modifiers}, up to the ':' that starts the modifiers. 4117 * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
4097 * Return whether to continue parsing. 4118 * Return whether to continue parsing.
4098 */ 4119 */
4099static Boolean 4120static Boolean
4100ParseVarnameLong( 4121ParseVarnameLong(
4101 const char *p, 4122 const char *p,
4102 char startc, 4123 char startc,
4103 GNode *scope, 4124 GNode *scope,
4104 VarEvalFlags eflags, 4125 VarEvalFlags eflags,
4105 4126
4106 const char **out_FALSE_pp, 4127 const char **out_FALSE_pp,
4107 VarParseResult *out_FALSE_res, 4128 VarParseResult *out_FALSE_res,
4108 FStr *out_FALSE_val, 4129 FStr *out_FALSE_val,
4109 4130
4110 char *out_TRUE_endc, 4131 char *out_TRUE_endc,
4111 const char **out_TRUE_p, 4132 const char **out_TRUE_p,
4112 Var **out_TRUE_v, 4133 Var **out_TRUE_v,
4113 Boolean *out_TRUE_haveModifier, 4134 Boolean *out_TRUE_haveModifier,
4114 const char **out_TRUE_extraModifiers, 4135 const char **out_TRUE_extraModifiers,
4115 Boolean *out_TRUE_dynamic, 4136 Boolean *out_TRUE_dynamic,
4116 ExprDefined *out_TRUE_exprDefined 4137 ExprDefined *out_TRUE_exprDefined
4117) 4138)
4118{ 4139{
4119 size_t namelen; 4140 size_t namelen;
4120 char *varname; 4141 char *varname;
4121 Var *v; 4142 Var *v;
4122 Boolean haveModifier; 4143 Boolean haveModifier;
4123 Boolean dynamic = FALSE; 4144 Boolean dynamic = FALSE;
4124 4145
4125 const char *const start = p; 4146 const char *const start = p;
4126 char endc = startc == '(' ? ')' : '}'; 4147 char endc = startc == '(' ? ')' : '}';
4127 4148
4128 p += 2; /* skip "${" or "$(" or "y(" */ 4149 p += 2; /* skip "${" or "$(" or "y(" */
4129 varname = ParseVarname(&p, startc, endc, scope, eflags, &namelen); 4150 varname = ParseVarname(&p, startc, endc, scope, eflags, &namelen);
4130 4151
4131 if (*p == ':') { 4152 if (*p == ':') {
4132 haveModifier = TRUE; 4153 haveModifier = TRUE;
4133 } else if (*p == endc) { 4154 } else if (*p == endc) {
4134 haveModifier = FALSE; 4155 haveModifier = FALSE;
4135 } else { 4156 } else {
4136 Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname); 4157 Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname);
4137 free(varname); 4158 free(varname);
4138 *out_FALSE_pp = p; 4159 *out_FALSE_pp = p;
4139 *out_FALSE_val = FStr_InitRefer(var_Error); 4160 *out_FALSE_val = FStr_InitRefer(var_Error);
4140 *out_FALSE_res = VPR_ERR; 4161 *out_FALSE_res = VPR_ERR;
4141 return FALSE; 4162 return FALSE;
4142 } 4163 }
4143 4164
4144 v = VarFind(varname, scope, TRUE); 4165 v = VarFind(varname, scope, TRUE);
4145 4166
4146 /* At this point, p points just after the variable name, 4167 /* At this point, p points just after the variable name,
4147 * either at ':' or at endc. */ 4168 * either at ':' or at endc. */
4148 4169
4149 if (v == NULL) { 4170 if (v == NULL) {
4150 v = FindLocalLegacyVar(varname, namelen, scope, 4171 v = FindLocalLegacyVar(varname, namelen, scope,
4151 out_TRUE_extraModifiers); 4172 out_TRUE_extraModifiers);
4152 } 4173 }
4153 4174
4154 if (v == NULL) { 4175 if (v == NULL) {
4155 /* 4176 /*
4156 * Defer expansion of dynamic variables if they appear in 4177 * Defer expansion of dynamic variables if they appear in
4157 * non-local scope since they are not defined there. 4178 * non-local scope since they are not defined there.
4158 */ 4179 */
4159 dynamic = VarnameIsDynamic(varname, namelen) && 4180 dynamic = VarnameIsDynamic(varname, namelen) &&
4160 (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL); 4181 (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL);
4161 4182
4162 if (!haveModifier) { 4183 if (!haveModifier) {
4163 p++; /* skip endc */ 4184 p++; /* skip endc */
4164 *out_FALSE_pp = p; 4185 *out_FALSE_pp = p;
4165 *out_FALSE_res = EvalUndefined(dynamic, start, p, 4186 *out_FALSE_res = EvalUndefined(dynamic, start, p,
4166 varname, eflags, out_FALSE_val); 4187 varname, eflags, out_FALSE_val);
4167 return FALSE; 4188 return FALSE;
4168 } 4189 }
4169 4190
4170 /* 4191 /*
4171 * The variable expression is based on an undefined variable. 4192 * The variable expression is based on an undefined variable.
4172 * Nevertheless it needs a Var, for modifiers that access the 4193 * Nevertheless it needs a Var, for modifiers that access the
4173 * variable name, such as :L or :?. 4194 * variable name, such as :L or :?.
4174 * 4195 *
4175 * Most modifiers leave this expression in the "undefined" 4196 * Most modifiers leave this expression in the "undefined"
4176 * state (VES_UNDEF), only a few modifiers like :D, :U, :L, 4197 * state (VES_UNDEF), only a few modifiers like :D, :U, :L,
4177 * :P turn this undefined expression into a defined 4198 * :P turn this undefined expression into a defined
4178 * expression (VES_DEF). 4199 * expression (VES_DEF).
4179 * 4200 *
4180 * In the end, after applying all modifiers, if the expression 4201 * In the end, after applying all modifiers, if the expression
4181 * is still undefined, Var_Parse will return an empty string 4202 * is still undefined, Var_Parse will return an empty string
4182 * instead of the actually computed value. 4203 * instead of the actually computed value.
4183 */ 4204 */
4184 v = VarNew(FStr_InitOwn(varname), "", VFL_NONE); 4205 v = VarNew(FStr_InitOwn(varname), "", VFL_NONE);
4185 *out_TRUE_exprDefined = DEF_UNDEF; 4206 *out_TRUE_exprDefined = DEF_UNDEF;
4186 } else 4207 } else
4187 free(varname); 4208 free(varname);
4188 4209
4189 *out_TRUE_endc = endc; 4210 *out_TRUE_endc = endc;
4190 *out_TRUE_p = p; 4211 *out_TRUE_p = p;
4191 *out_TRUE_v = v; 4212 *out_TRUE_v = v;
4192 *out_TRUE_haveModifier = haveModifier; 4213 *out_TRUE_haveModifier = haveModifier;
4193 *out_TRUE_dynamic = dynamic; 4214 *out_TRUE_dynamic = dynamic;
4194 return TRUE; 4215 return TRUE;
4195} 4216}
4196 4217
4197/* Free the environment variable now since we own it. */ 4218/* Free the environment variable now since we own it. */
4198static void 4219static void
4199FreeEnvVar(Var *v, FStr *inout_val) 4220FreeEnvVar(Var *v, FStr *inout_val)
4200{ 4221{
4201 char *varValue = Buf_DoneData(&v->val); 4222 char *varValue = Buf_DoneData(&v->val);
4202 if (inout_val->str == varValue) 4223 if (inout_val->str == varValue)
4203 inout_val->freeIt = varValue; 4224 inout_val->freeIt = varValue;
4204 else 4225 else
4205 free(varValue); 4226 free(varValue);
4206 4227
4207 FStr_Done(&v->name); 4228 FStr_Done(&v->name);
4208 free(v); 4229 free(v);
4209} 4230}
4210 4231
4211/* 4232/*
4212 * Given the start of a variable expression (such as $v, $(VAR), 4233 * Given the start of a variable expression (such as $v, $(VAR),
4213 * ${VAR:Mpattern}), extract the variable name and value, and the modifiers, 4234 * ${VAR:Mpattern}), extract the variable name and value, and the modifiers,
4214 * if any. While doing that, apply the modifiers to the value of the 4235 * if any. While doing that, apply the modifiers to the value of the
4215 * expression, forming its final value. A few of the modifiers such as :!cmd! 4236 * expression, forming its final value. A few of the modifiers such as :!cmd!
4216 * or ::= have side effects. 4237 * or ::= have side effects.
4217 * 4238 *
4218 * Input: 4239 * Input:
4219 * *pp The string to parse. 4240 * *pp The string to parse.
4220 * When parsing a condition in ParseEmptyArg, it may also 4241 * When parsing a condition in ParseEmptyArg, it may also
4221 * point to the "y" of "empty(VARNAME:Modifiers)", which 4242 * point to the "y" of "empty(VARNAME:Modifiers)", which
4222 * is syntactically the same. 4243 * is syntactically the same.
4223 * scope The scope for finding variables 4244 * scope The scope for finding variables
4224 * eflags Control the exact details of parsing 4245 * eflags Control the exact details of parsing
4225 * 4246 *
4226 * Output: 4247 * Output:
4227 * *pp The position where to continue parsing. 4248 * *pp The position where to continue parsing.
4228 * TODO: After a parse error, the value of *pp is 4249 * TODO: After a parse error, the value of *pp is
4229 * unspecified. It may not have been updated at all, 4250 * unspecified. It may not have been updated at all,
4230 * point to some random character in the string, to the 4251 * point to some random character in the string, to the
4231 * location of the parse error, or at the end of the 4252 * location of the parse error, or at the end of the
4232 * string. 4253 * string.
4233 * *out_val The value of the variable expression, never NULL. 4254 * *out_val The value of the variable expression, never NULL.
4234 * *out_val var_Error if there was a parse error. 4255 * *out_val var_Error if there was a parse error.
4235 * *out_val var_Error if the base variable of the expression was 4256 * *out_val var_Error if the base variable of the expression was
4236 * undefined, eflags contains VARE_UNDEFERR, and none of 4257 * undefined, eflags contains VARE_UNDEFERR, and none of
4237 * the modifiers turned the undefined expression into a 4258 * the modifiers turned the undefined expression into a
4238 * defined expression. 4259 * defined expression.
4239 * XXX: It is not guaranteed that an error message has 4260 * XXX: It is not guaranteed that an error message has
4240 * been printed. 4261 * been printed.
4241 * *out_val varUndefined if the base variable of the expression 4262 * *out_val varUndefined if the base variable of the expression
4242 * was undefined, eflags did not contain VARE_UNDEFERR, 4263 * was undefined, eflags did not contain VARE_UNDEFERR,
4243 * and none of the modifiers turned the undefined 4264 * and none of the modifiers turned the undefined
4244 * expression into a defined expression. 4265 * expression into a defined expression.
4245 * XXX: It is not guaranteed that an error message has 4266 * XXX: It is not guaranteed that an error message has
4246 * been printed. 4267 * been printed.
4247 */ 4268 */
4248VarParseResult 4269VarParseResult
4249Var_Parse(const char **pp, GNode *scope, VarEvalFlags eflags, FStr *out_val) 4270Var_Parse(const char **pp, GNode *scope, VarEvalFlags eflags, FStr *out_val)
4250{ 4271{
4251 const char *p = *pp; 4272 const char *p = *pp;
4252 const char *const start = p; 4273 const char *const start = p;
4253 /* TRUE if have modifiers for the variable. */ 4274 /* TRUE if have modifiers for the variable. */
4254 Boolean haveModifier; 4275 Boolean haveModifier;
4255 /* Starting character if variable in parens or braces. */ 4276 /* Starting character if variable in parens or braces. */
4256 char startc; 4277 char startc;
4257 /* Ending character if variable in parens or braces. */ 4278 /* Ending character if variable in parens or braces. */
4258 char endc; 4279 char endc;
4259 /* 4280 /*
4260 * TRUE if the variable is local and we're expanding it in a 4281 * TRUE if the variable is local and we're expanding it in a
4261 * non-local scope. This is done to support dynamic sources. 4282 * non-local scope. This is done to support dynamic sources.
4262 * The result is just the expression, unaltered. 4283 * The result is just the expression, unaltered.
4263 */ 4284 */
4264 Boolean dynamic; 4285 Boolean dynamic;
4265 const char *extramodifiers; 4286 const char *extramodifiers;
4266 char eflags_str[VarEvalFlags_ToStringSize]; 4287 char eflags_str[VarEvalFlags_ToStringSize];
4267 Var *v; 4288 Var *v;
4268 4289
4269 Expr expr = { 4290 Expr expr = {
4270 NULL, 4291 NULL,
4271#if defined(lint) 4292#if defined(lint)
4272 /* NetBSD lint cannot fully parse C99 struct initializers. */ 4293 /* NetBSD lint cannot fully parse C99 struct initializers. */
4273 { NULL, NULL }, 4294 { NULL, NULL },
4274#else 4295#else
4275 FStr_InitRefer(NULL), 4296 FStr_InitRefer(NULL),
4276#endif 4297#endif
4277 eflags, 4298 eflags,
4278 scope, 4299 scope,
4279 DEF_REGULAR 4300 DEF_REGULAR
4280 }; 4301 };
4281 4302
4282 DEBUG2(VAR, "Var_Parse: %s with %s\n", start, 4303 DEBUG2(VAR, "Var_Parse: %s with %s\n", start,
4283 VarEvalFlags_ToString(eflags_str, eflags)); 4304 VarEvalFlags_ToString(eflags_str, eflags));
4284 4305
4285 *out_val = FStr_InitRefer(NULL); 4306 *out_val = FStr_InitRefer(NULL);
4286 extramodifiers = NULL; /* extra modifiers to apply first */ 4307 extramodifiers = NULL; /* extra modifiers to apply first */
4287 dynamic = FALSE; 4308 dynamic = FALSE;
4288 4309
4289 /* 4310 /*
4290 * Appease GCC, which thinks that the variable might not be 4311 * Appease GCC, which thinks that the variable might not be
4291 * initialized. 4312 * initialized.
4292 */ 4313 */
4293 endc = '\0'; 4314 endc = '\0';
4294 4315
4295 startc = p[1]; 4316 startc = p[1];
4296 if (startc != '(' && startc != '{') { 4317 if (startc != '(' && startc != '{') {
4297 VarParseResult res; 4318 VarParseResult res;
4298 if (!ParseVarnameShort(startc, pp, scope, eflags, &res, 4319 if (!ParseVarnameShort(startc, pp, scope, eflags, &res,
4299 &out_val->str, &expr.var)) 4320 &out_val->str, &expr.var))
4300 return res; 4321 return res;
4301 haveModifier = FALSE; 4322 haveModifier = FALSE;
4302 p++; 4323 p++;
4303 } else { 4324 } else {
4304 VarParseResult res; 4325 VarParseResult res;
4305 if (!ParseVarnameLong(p, startc, scope, eflags, 4326 if (!ParseVarnameLong(p, startc, scope, eflags,
4306 pp, &res, out_val, 4327 pp, &res, out_val,
4307 &endc, &p, &expr.var, &haveModifier, &extramodifiers, 4328 &endc, &p, &expr.var, &haveModifier, &extramodifiers,
4308 &dynamic, &expr.defined)) 4329 &dynamic, &expr.defined))
4309 return res; 4330 return res;
4310 } 4331 }
4311 4332
4312 v = expr.var; 4333 v = expr.var;
4313 if (v->flags & VFL_IN_USE) 4334 if (v->flags & VFL_IN_USE)
4314 Fatal("Variable %s is recursive.", v->name.str); 4335 Fatal("Variable %s is recursive.", v->name.str);
4315 4336
4316 /* 4337 /*
4317 * XXX: This assignment creates an alias to the current value of the 4338 * XXX: This assignment creates an alias to the current value of the
4318 * variable. This means that as long as the value of the expression 4339 * variable. This means that as long as the value of the expression
4319 * stays the same, the value of the variable must not change. 4340 * stays the same, the value of the variable must not change.
4320 * Using the '::=' modifier, it could be possible to do exactly this. 4341 * Using the '::=' modifier, it could be possible to do exactly this.
4321 * At the bottom of this function, the resulting value is compared to 4342 * At the bottom of this function, the resulting value is compared to
4322 * the then-current value of the variable. This might also invoke 4343 * the then-current value of the variable. This might also invoke
4323 * undefined behavior. 4344 * undefined behavior.
4324 */ 4345 */
4325 expr.value = FStr_InitRefer(v->val.data); 4346 expr.value = FStr_InitRefer(v->val.data);
4326 4347
4327 /* 4348 /*
4328 * Before applying any modifiers, expand any nested expressions from 4349 * Before applying any modifiers, expand any nested expressions from
4329 * the variable value. 4350 * the variable value.
4330 */ 4351 */
4331 if (strchr(expr.value.str, '$') != NULL && (eflags & VARE_WANTRES)) { 4352 if (strchr(expr.value.str, '$') != NULL && (eflags & VARE_WANTRES)) {
4332 char *expanded; 4353 char *expanded;
4333 VarEvalFlags nested_eflags = eflags; 4354 VarEvalFlags nested_eflags = eflags;
4334 if (opts.strict) 4355 if (opts.strict)
4335 nested_eflags &= ~(unsigned)VARE_UNDEFERR; 4356 nested_eflags &= ~(unsigned)VARE_UNDEFERR;
4336 v->flags |= VFL_IN_USE; 4357 v->flags |= VFL_IN_USE;
4337 (void)Var_Subst(expr.value.str, scope, nested_eflags, 4358 (void)Var_Subst(expr.value.str, scope, nested_eflags,
4338 &expanded); 4359 &expanded);
4339 v->flags &= ~(unsigned)VFL_IN_USE; 4360 v->flags &= ~(unsigned)VFL_IN_USE;
4340 /* TODO: handle errors */ 4361 /* TODO: handle errors */
4341 Expr_SetValueOwn(&expr, expanded); 4362 Expr_SetValueOwn(&expr, expanded);
4342 } 4363 }
4343 4364
4344 if (extramodifiers != NULL) { 4365 if (extramodifiers != NULL) {
4345 const char *em = extramodifiers; 4366 const char *em = extramodifiers;
4346 ApplyModifiers(&expr, &em, '\0', '\0'); 4367 ApplyModifiers(&expr, &em, '\0', '\0');
4347 } 4368 }
4348 4369
4349 if (haveModifier) { 4370 if (haveModifier) {
4350 p++; /* Skip initial colon. */ 4371 p++; /* Skip initial colon. */
4351 ApplyModifiers(&expr, &p, startc, endc); 4372 ApplyModifiers(&expr, &p, startc, endc);
4352 } 4373 }
4353 4374
4354 if (*p != '\0') /* Skip past endc if possible. */ 4375 if (*p != '\0') /* Skip past endc if possible. */
4355 p++; 4376 p++;
4356 4377
4357 *pp = p; 4378 *pp = p;
4358 4379
4359 if (v->flags & VFL_FROM_ENV) { 4380 if (v->flags & VFL_FROM_ENV) {
4360 FreeEnvVar(v, &expr.value); 4381 FreeEnvVar(v, &expr.value);
4361 4382
4362 } else if (expr.defined != DEF_REGULAR) { 4383 } else if (expr.defined != DEF_REGULAR) {
4363 if (expr.defined == DEF_UNDEF) { 4384 if (expr.defined == DEF_UNDEF) {
4364 if (dynamic) { 4385 if (dynamic) {
4365 Expr_SetValueOwn(&expr, 4386 Expr_SetValueOwn(&expr,
4366 bmake_strsedup(start, p)); 4387 bmake_strsedup(start, p));
4367 } else { 4388 } else {
4368 /* 4389 /*
4369 * The expression is still undefined, 4390 * The expression is still undefined,
4370 * therefore discard the actual value and 4391 * therefore discard the actual value and
4371 * return an error marker instead. 4392 * return an error marker instead.
4372 */ 4393 */
4373 Expr_SetValueRefer(&expr, 4394 Expr_SetValueRefer(&expr,
4374 eflags & VARE_UNDEFERR 4395 eflags & VARE_UNDEFERR
4375 ? var_Error : varUndefined); 4396 ? var_Error : varUndefined);
4376 } 4397 }
4377 } 4398 }
4378 /* XXX: This is not standard memory management. */ 4399 /* XXX: This is not standard memory management. */
4379 if (expr.value.str != v->val.data) 4400 if (expr.value.str != v->val.data)
4380 Buf_Done(&v->val); 4401 Buf_Done(&v->val);
4381 FStr_Done(&v->name); 4402 FStr_Done(&v->name);
4382 free(v); 4403 free(v);
4383 } 4404 }
4384 *out_val = expr.value; 4405 *out_val = expr.value;
4385 return VPR_OK; /* XXX: Is not correct in all cases */ 4406 return VPR_OK; /* XXX: Is not correct in all cases */
4386} 4407}
4387 4408
4388static void 4409static void
4389VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags) 4410VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags)
4390{ 4411{
4391 /* A dollar sign may be escaped with another dollar sign. */ 4412 /* A dollar sign may be escaped with another dollar sign. */
4392 if (save_dollars && (eflags & VARE_KEEP_DOLLAR)) 4413 if (save_dollars && (eflags & VARE_KEEP_DOLLAR))
4393 Buf_AddByte(res, '$'); 4414 Buf_AddByte(res, '$');
4394 Buf_AddByte(res, '$'); 4415 Buf_AddByte(res, '$');
4395 *pp += 2; 4416 *pp += 2;
4396} 4417}
4397 4418
4398static void 4419static void
4399VarSubstExpr(const char **pp, Buffer *buf, GNode *scope, 4420VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
4400 VarEvalFlags eflags, Boolean *inout_errorReported) 4421 VarEvalFlags eflags, Boolean *inout_errorReported)
4401{ 4422{
4402 const char *p = *pp; 4423 const char *p = *pp;
4403 const char *nested_p = p; 4424 const char *nested_p = p;
4404 FStr val; 4425 FStr val;
4405 4426
4406 (void)Var_Parse(&nested_p, scope, eflags, &val); 4427 (void)Var_Parse(&nested_p, scope, eflags, &val);
4407 /* TODO: handle errors */ 4428 /* TODO: handle errors */
4408 4429
4409 if (val.str == var_Error || val.str == varUndefined) { 4430 if (val.str == var_Error || val.str == varUndefined) {
4410 if (!(eflags & VARE_KEEP_UNDEF)) { 4431 if (!(eflags & VARE_KEEP_UNDEF)) {
4411 p = nested_p; 4432 p = nested_p;
4412 } else if ((eflags & VARE_UNDEFERR) || val.str == var_Error) { 4433 } else if ((eflags & VARE_UNDEFERR) || val.str == var_Error) {
4413 4434
4414 /* 4435 /*
4415 * XXX: This condition is wrong. If val == var_Error, 4436 * XXX: This condition is wrong. If val == var_Error,
4416 * this doesn't necessarily mean there was an undefined 4437 * this doesn't necessarily mean there was an undefined
4417 * variable. It could equally well be a parse error; 4438 * variable. It could equally well be a parse error;
4418 * see unit-tests/varmod-order.exp. 4439 * see unit-tests/varmod-order.exp.
4419 */ 4440 */
4420 4441
4421 /* 4442 /*
4422 * If variable is undefined, complain and skip the 4443 * If variable is undefined, complain and skip the
4423 * variable. The complaint will stop us from doing 4444 * variable. The complaint will stop us from doing
4424 * anything when the file is parsed. 4445 * anything when the file is parsed.
4425 */ 4446 */
4426 if (!*inout_errorReported) { 4447 if (!*inout_errorReported) {
4427 Parse_Error(PARSE_FATAL, 4448 Parse_Error(PARSE_FATAL,
4428 "Undefined variable \"%.*s\"", 4449 "Undefined variable \"%.*s\"",
4429 (int)(size_t)(nested_p - p), p); 4450 (int)(size_t)(nested_p - p), p);
4430 } 4451 }
4431 p = nested_p; 4452 p = nested_p;
4432 *inout_errorReported = TRUE; 4453 *inout_errorReported = TRUE;
4433 } else { 4454 } else {
4434 /* Copy the initial '$' of the undefined expression, 4455 /* Copy the initial '$' of the undefined expression,
4435 * thereby deferring expansion of the expression, but 4456 * thereby deferring expansion of the expression, but
4436 * expand nested expressions if already possible. 4457 * expand nested expressions if already possible.
4437 * See unit-tests/varparse-undef-partial.mk. */ 4458 * See unit-tests/varparse-undef-partial.mk. */
4438 Buf_AddByte(buf, *p); 4459 Buf_AddByte(buf, *p);
4439 p++; 4460 p++;
4440 } 4461 }
4441 } else { 4462 } else {
4442 p = nested_p; 4463 p = nested_p;
4443 Buf_AddStr(buf, val.str); 4464 Buf_AddStr(buf, val.str);
4444 } 4465 }
4445 4466
4446 FStr_Done(&val); 4467 FStr_Done(&val);
4447 4468
4448 *pp = p; 4469 *pp = p;
4449} 4470}
4450 4471
4451/* 4472/*
4452 * Skip as many characters as possible -- either to the end of the string 4473 * Skip as many characters as possible -- either to the end of the string
4453 * or to the next dollar sign (variable expression). 4474 * or to the next dollar sign (variable expression).
4454 */ 4475 */
4455static void 4476static void
4456VarSubstPlain(const char **pp, Buffer *res) 4477VarSubstPlain(const char **pp, Buffer *res)
4457{ 4478{
4458 const char *p = *pp; 4479 const char *p = *pp;
4459 const char *start = p; 4480 const char *start = p;
4460 4481
4461 for (p++; *p != '$' && *p != '\0'; p++) 4482 for (p++; *p != '$' && *p != '\0'; p++)
4462 continue; 4483 continue;
4463 Buf_AddBytesBetween(res, start, p); 4484 Buf_AddBytesBetween(res, start, p);
4464 *pp = p; 4485 *pp = p;
4465} 4486}
4466 4487
4467/* 4488/*
4468 * Expand all variable expressions like $V, ${VAR}, $(VAR:Modifiers) in the 4489 * Expand all variable expressions like $V, ${VAR}, $(VAR:Modifiers) in the
4469 * given string. 4490 * given string.
4470 * 4491 *
4471 * Input: 4492 * Input:
4472 * str The string in which the variable expressions are 4493 * str The string in which the variable expressions are
4473 * expanded. 4494 * expanded.
4474 * scope The scope in which to start searching for 4495 * scope The scope in which to start searching for
4475 * variables. The other scopes are searched as well. 4496 * variables. The other scopes are searched as well.
4476 * eflags Special effects during expansion. 4497 * eflags Special effects during expansion.
4477 */ 4498 */
4478VarParseResult 4499VarParseResult
4479Var_Subst(const char *str, GNode *scope, VarEvalFlags eflags, char **out_res) 4500Var_Subst(const char *str, GNode *scope, VarEvalFlags eflags, char **out_res)
4480{ 4501{
4481 const char *p = str; 4502 const char *p = str;
4482 Buffer res; 4503 Buffer res;
4483 4504
4484 /* Set true if an error has already been reported, 4505 /* Set true if an error has already been reported,
4485 * to prevent a plethora of messages when recursing */ 4506 * to prevent a plethora of messages when recursing */
4486 /* XXX: Why is the 'static' necessary here? */ 4507 /* XXX: Why is the 'static' necessary here? */
4487 static Boolean errorReported; 4508 static Boolean errorReported;
4488 4509
4489 Buf_Init(&res); 4510 Buf_Init(&res);
4490 errorReported = FALSE; 4511 errorReported = FALSE;
4491 4512
4492 while (*p != '\0') { 4513 while (*p != '\0') {
4493 if (p[0] == '$' && p[1] == '$') 4514 if (p[0] == '$' && p[1] == '$')
4494 VarSubstDollarDollar(&p, &res, eflags); 4515 VarSubstDollarDollar(&p, &res, eflags);
4495 else if (p[0] == '$') 4516 else if (p[0] == '$')
4496 VarSubstExpr(&p, &res, scope, eflags, &errorReported); 4517 VarSubstExpr(&p, &res, scope, eflags, &errorReported);
4497 else 4518 else
4498 VarSubstPlain(&p, &res); 4519 VarSubstPlain(&p, &res);
4499 } 4520 }
4500 4521
4501 *out_res = Buf_DoneDataCompact(&res); 4522 *out_res = Buf_DoneDataCompact(&res);
4502 return VPR_OK; 4523 return VPR_OK;
4503} 4524}
4504 4525
4505/* Initialize the variables module. */ 4526/* Initialize the variables module. */
4506void 4527void
4507Var_Init(void) 4528Var_Init(void)
4508{ 4529{
4509 SCOPE_INTERNAL = GNode_New("Internal"); 4530 SCOPE_INTERNAL = GNode_New("Internal");
4510 SCOPE_GLOBAL = GNode_New("Global"); 4531 SCOPE_GLOBAL = GNode_New("Global");
4511 SCOPE_CMDLINE = GNode_New("Command"); 4532 SCOPE_CMDLINE = GNode_New("Command");
4512} 4533}
4513 4534
4514/* Clean up the variables module. */ 4535/* Clean up the variables module. */
4515void 4536void
4516Var_End(void) 4537Var_End(void)
4517{ 4538{
4518 Var_Stats(); 4539 Var_Stats();
4519} 4540}
4520 4541
4521void 4542void
4522Var_Stats(void) 4543Var_Stats(void)
4523{ 4544{
4524 HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables"); 4545 HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables");
4525} 4546}
4526 4547
4527/* Print all variables in a scope, sorted by name. */ 4548/* Print all variables in a scope, sorted by name. */
4528void 4549void
4529Var_Dump(GNode *scope) 4550Var_Dump(GNode *scope)
4530{ 4551{
4531 Vector /* of const char * */ vec; 4552 Vector /* of const char * */ vec;
4532 HashIter hi; 4553 HashIter hi;
4533 size_t i; 4554 size_t i;
4534 const char **varnames; 4555 const char **varnames;
4535 4556
4536 Vector_Init(&vec, sizeof(const char *)); 4557 Vector_Init(&vec, sizeof(const char *));