var.c revision 1.1161 1 1.1161 rillig /* $NetBSD: var.c,v 1.1161 2025/04/30 06:01:07 rillig Exp $ */
2 1.11 christos
3 1.1 cgd /*
4 1.15 christos * Copyright (c) 1988, 1989, 1990, 1993
5 1.15 christos * The Regents of the University of California. All rights reserved.
6 1.80 agc *
7 1.80 agc * This code is derived from software contributed to Berkeley by
8 1.80 agc * Adam de Boor.
9 1.80 agc *
10 1.80 agc * Redistribution and use in source and binary forms, with or without
11 1.80 agc * modification, are permitted provided that the following conditions
12 1.80 agc * are met:
13 1.80 agc * 1. Redistributions of source code must retain the above copyright
14 1.80 agc * notice, this list of conditions and the following disclaimer.
15 1.80 agc * 2. Redistributions in binary form must reproduce the above copyright
16 1.80 agc * notice, this list of conditions and the following disclaimer in the
17 1.80 agc * documentation and/or other materials provided with the distribution.
18 1.80 agc * 3. Neither the name of the University nor the names of its contributors
19 1.80 agc * may be used to endorse or promote products derived from this software
20 1.80 agc * without specific prior written permission.
21 1.80 agc *
22 1.80 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.80 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.80 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.80 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.80 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.80 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.80 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.80 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.80 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.80 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.80 agc * SUCH DAMAGE.
33 1.80 agc */
34 1.80 agc
35 1.80 agc /*
36 1.1 cgd * Copyright (c) 1989 by Berkeley Softworks
37 1.1 cgd * All rights reserved.
38 1.1 cgd *
39 1.1 cgd * This code is derived from software contributed to Berkeley by
40 1.1 cgd * Adam de Boor.
41 1.1 cgd *
42 1.1 cgd * Redistribution and use in source and binary forms, with or without
43 1.1 cgd * modification, are permitted provided that the following conditions
44 1.1 cgd * are met:
45 1.1 cgd * 1. Redistributions of source code must retain the above copyright
46 1.1 cgd * notice, this list of conditions and the following disclaimer.
47 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
48 1.1 cgd * notice, this list of conditions and the following disclaimer in the
49 1.1 cgd * documentation and/or other materials provided with the distribution.
50 1.1 cgd * 3. All advertising materials mentioning features or use of this software
51 1.1 cgd * must display the following acknowledgement:
52 1.1 cgd * This product includes software developed by the University of
53 1.1 cgd * California, Berkeley and its contributors.
54 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
55 1.1 cgd * may be used to endorse or promote products derived from this software
56 1.1 cgd * without specific prior written permission.
57 1.1 cgd *
58 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.1 cgd * SUCH DAMAGE.
69 1.1 cgd */
70 1.1 cgd
71 1.592 rillig /*
72 1.592 rillig * Handling of variables and the expressions formed from them.
73 1.592 rillig *
74 1.592 rillig * Variables are set using lines of the form VAR=value. Both the variable
75 1.592 rillig * name and the value can contain references to other variables, by using
76 1.592 rillig * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
77 1.1 cgd *
78 1.1 cgd * Interface:
79 1.798 rillig * Var_Set
80 1.1105 rillig * Var_SetExpand Set the value of the variable, creating it if
81 1.592 rillig * necessary.
82 1.592 rillig *
83 1.794 rillig * Var_Append
84 1.794 rillig * Var_AppendExpand
85 1.794 rillig * Append more characters to the variable, creating it if
86 1.592 rillig * necessary. A space is placed between the old value and
87 1.592 rillig * the new one.
88 1.1 cgd *
89 1.796 rillig * Var_Exists
90 1.796 rillig * Var_ExistsExpand
91 1.796 rillig * See if a variable exists.
92 1.1 cgd *
93 1.592 rillig * Var_Value Return the unexpanded value of a variable, or NULL if
94 1.592 rillig * the variable is undefined.
95 1.592 rillig *
96 1.1075 rillig * Var_Subst Substitute all expressions in a string.
97 1.592 rillig *
98 1.1075 rillig * Var_Parse Parse an expression such as ${VAR:Mpattern}.
99 1.1 cgd *
100 1.1105 rillig * Var_Delete Delete a variable.
101 1.1 cgd *
102 1.725 rillig * Var_ReexportVars
103 1.725 rillig * Export some or even all variables to the environment
104 1.592 rillig * of this process and its child processes.
105 1.1 cgd *
106 1.592 rillig * Var_Export Export the variable to the environment of this process
107 1.592 rillig * and its child processes.
108 1.1 cgd *
109 1.592 rillig * Var_UnExport Don't export the variable anymore.
110 1.1 cgd *
111 1.1 cgd * Debugging:
112 1.592 rillig * Var_Stats Print out hashing statistics if in -dh mode.
113 1.592 rillig *
114 1.802 rillig * Var_Dump Print out all variables defined in the given scope.
115 1.1 cgd */
116 1.1 cgd
117 1.630 rillig #include <sys/stat.h>
118 1.630 rillig #include <sys/types.h>
119 1.630 rillig #include <regex.h>
120 1.631 rillig #include <errno.h>
121 1.630 rillig #include <inttypes.h>
122 1.630 rillig #include <limits.h>
123 1.630 rillig #include <time.h>
124 1.630 rillig
125 1.630 rillig #include "make.h"
126 1.630 rillig #include "dir.h"
127 1.630 rillig #include "job.h"
128 1.630 rillig #include "metachar.h"
129 1.1 cgd
130 1.512 rillig /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
131 1.1161 rillig MAKE_RCSID("$NetBSD: var.c,v 1.1161 2025/04/30 06:01:07 rillig Exp $");
132 1.228 rillig
133 1.778 rillig /*
134 1.778 rillig * Variables are defined using one of the VAR=value assignments. Their
135 1.570 rillig * value can be queried by expressions such as $V, ${VAR}, or with modifiers
136 1.570 rillig * such as ${VAR:S,from,to,g:Q}.
137 1.570 rillig *
138 1.802 rillig * There are 3 kinds of variables: scope variables, environment variables,
139 1.570 rillig * undefined variables.
140 1.570 rillig *
141 1.1105 rillig * Scope variables are stored in GNode.vars. The only way to undefine
142 1.802 rillig * a scope variable is using the .undef directive. In particular, it must
143 1.570 rillig * not be possible to undefine a variable during the evaluation of an
144 1.996 rillig * expression, or Var.name might point nowhere. (There is another,
145 1.996 rillig * unintended way to undefine a scope variable, see varmod-loop-delete.mk.)
146 1.570 rillig *
147 1.977 rillig * Environment variables are short-lived. They are returned by VarFind, and
148 1.977 rillig * after using them, they must be freed using VarFreeShortLived.
149 1.570 rillig *
150 1.1075 rillig * Undefined variables occur during evaluation of expressions such
151 1.570 rillig * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
152 1.570 rillig */
153 1.1 cgd typedef struct Var {
154 1.703 rillig /*
155 1.703 rillig * The name of the variable, once set, doesn't change anymore.
156 1.802 rillig * For scope variables, it aliases the corresponding HashEntry name.
157 1.703 rillig * For environment and undefined variables, it is allocated.
158 1.703 rillig */
159 1.711 rillig FStr name;
160 1.570 rillig
161 1.703 rillig /* The unexpanded value of the variable. */
162 1.703 rillig Buffer val;
163 1.902 rillig
164 1.902 rillig /* The variable came from the command line. */
165 1.987 rillig bool fromCmd:1;
166 1.902 rillig
167 1.902 rillig /*
168 1.978 rillig * The variable is short-lived.
169 1.978 rillig * These variables are not registered in any GNode, therefore they
170 1.978 rillig * must be freed after use.
171 1.978 rillig */
172 1.987 rillig bool shortLived:1;
173 1.978 rillig
174 1.978 rillig /*
175 1.902 rillig * The variable comes from the environment.
176 1.1105 rillig * Appending to its value depends on the scope, see var-op-append.mk.
177 1.902 rillig */
178 1.987 rillig bool fromEnvironment:1;
179 1.902 rillig
180 1.902 rillig /*
181 1.902 rillig * The variable value cannot be changed anymore, and the variable
182 1.902 rillig * cannot be deleted. Any attempts to do so are silently ignored,
183 1.902 rillig * they are logged with -dv though.
184 1.1038 sjg * Use .[NO]READONLY: to adjust.
185 1.902 rillig *
186 1.902 rillig * See VAR_SET_READONLY.
187 1.902 rillig */
188 1.987 rillig bool readOnly:1;
189 1.902 rillig
190 1.902 rillig /*
191 1.1121 rillig * The variable is read-only and immune to the .NOREADONLY special
192 1.1121 rillig * target. Any attempt to modify it results in an error.
193 1.1121 rillig */
194 1.1121 rillig bool readOnlyLoud:1;
195 1.1121 rillig
196 1.1121 rillig /*
197 1.1035 rillig * The variable is currently being accessed by Var_Parse or Var_Subst.
198 1.1035 rillig * This temporary marker is used to avoid endless recursion.
199 1.1035 rillig */
200 1.987 rillig bool inUse:1;
201 1.902 rillig
202 1.902 rillig /*
203 1.902 rillig * The variable is exported to the environment, to be used by child
204 1.902 rillig * processes.
205 1.902 rillig */
206 1.987 rillig bool exported:1;
207 1.902 rillig
208 1.902 rillig /*
209 1.902 rillig * At the point where this variable was exported, it contained an
210 1.902 rillig * unresolved reference to another variable. Before any child
211 1.1066 rillig * process is started, it needs to be actually exported, resolving
212 1.1066 rillig * the referenced variable just in time.
213 1.902 rillig */
214 1.987 rillig bool reexport:1;
215 1.417 rillig } Var;
216 1.1 cgd
217 1.710 rillig /*
218 1.830 rillig * Exporting variables is expensive and may leak memory, so skip it if we
219 1.830 rillig * can.
220 1.710 rillig */
221 1.710 rillig typedef enum VarExportedMode {
222 1.710 rillig VAR_EXPORTED_NONE,
223 1.710 rillig VAR_EXPORTED_SOME,
224 1.710 rillig VAR_EXPORTED_ALL
225 1.710 rillig } VarExportedMode;
226 1.710 rillig
227 1.713 rillig typedef enum UnexportWhat {
228 1.830 rillig /* Unexport the variables given by name. */
229 1.713 rillig UNEXPORT_NAMED,
230 1.830 rillig /*
231 1.830 rillig * Unexport all globals previously exported, but keep the environment
232 1.830 rillig * inherited from the parent.
233 1.830 rillig */
234 1.713 rillig UNEXPORT_ALL,
235 1.830 rillig /*
236 1.830 rillig * Unexport all globals previously exported and clear the environment
237 1.830 rillig * inherited from the parent.
238 1.830 rillig */
239 1.713 rillig UNEXPORT_ENV
240 1.713 rillig } UnexportWhat;
241 1.713 rillig
242 1.261 rillig /* Flags for pattern matching in the :S and :C modifiers */
243 1.927 rillig typedef struct PatternFlags {
244 1.987 rillig bool subGlobal:1; /* 'g': replace as often as possible */
245 1.987 rillig bool subOnce:1; /* '1': replace only once */
246 1.987 rillig bool anchorStart:1; /* '^': match only at start of word */
247 1.987 rillig bool anchorEnd:1; /* '$': match only at end of word */
248 1.927 rillig } PatternFlags;
249 1.16 christos
250 1.830 rillig /* SepBuf builds a string from words interleaved with separators. */
251 1.710 rillig typedef struct SepBuf {
252 1.710 rillig Buffer buf;
253 1.895 rillig bool needSep;
254 1.710 rillig /* Usually ' ', but see the ':ts' modifier. */
255 1.710 rillig char sep;
256 1.710 rillig } SepBuf;
257 1.710 rillig
258 1.1120 rillig typedef enum {
259 1.1120 rillig VSK_TARGET,
260 1.1146 rillig VSK_COMMAND,
261 1.1120 rillig VSK_VARNAME,
262 1.1147 rillig VSK_INDIRECT_MODIFIERS,
263 1.1124 rillig VSK_COND,
264 1.1124 rillig VSK_COND_THEN,
265 1.1124 rillig VSK_COND_ELSE,
266 1.1133 rillig VSK_EXPR,
267 1.1133 rillig VSK_EXPR_PARSE
268 1.1120 rillig } EvalStackElementKind;
269 1.1120 rillig
270 1.1102 rillig typedef struct {
271 1.1120 rillig EvalStackElementKind kind;
272 1.1120 rillig const char *str;
273 1.1128 rillig const FStr *value;
274 1.1102 rillig } EvalStackElement;
275 1.1102 rillig
276 1.1102 rillig typedef struct {
277 1.1102 rillig EvalStackElement *elems;
278 1.1102 rillig size_t len;
279 1.1102 rillig size_t cap;
280 1.1102 rillig } EvalStack;
281 1.710 rillig
282 1.1088 rillig /* Whether we have replaced the original environ (which we cannot free). */
283 1.710 rillig char **savedEnv = NULL;
284 1.710 rillig
285 1.778 rillig /*
286 1.778 rillig * Special return value for Var_Parse, indicating a parse error. It may be
287 1.710 rillig * caused by an undefined variable, a syntax error in a modifier or
288 1.778 rillig * something entirely different.
289 1.778 rillig */
290 1.710 rillig char var_Error[] = "";
291 1.710 rillig
292 1.778 rillig /*
293 1.778 rillig * Special return value for Var_Parse, indicating an undefined variable in
294 1.1119 rillig * a case where VARE_EVAL_DEFINED is not set. This undefined variable is
295 1.710 rillig * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
296 1.778 rillig * be deferred until it is defined in an actual target.
297 1.830 rillig *
298 1.1119 rillig * See VARE_EVAL_KEEP_UNDEFINED.
299 1.778 rillig */
300 1.710 rillig static char varUndefined[] = "";
301 1.710 rillig
302 1.710 rillig /*
303 1.710 rillig * Traditionally this make consumed $$ during := like any other expansion.
304 1.710 rillig * Other make's do not, and this make follows straight since 2016-01-09.
305 1.710 rillig *
306 1.895 rillig * This knob allows controlling the behavior:
307 1.895 rillig * false to consume $$ during := assignment.
308 1.895 rillig * true to preserve $$ during := assignment.
309 1.710 rillig */
310 1.710 rillig #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
311 1.895 rillig static bool save_dollars = true;
312 1.710 rillig
313 1.710 rillig /*
314 1.807 rillig * A scope collects variable names and their values.
315 1.807 rillig *
316 1.807 rillig * The main scope is SCOPE_GLOBAL, which contains the variables that are set
317 1.807 rillig * in the makefiles. SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and
318 1.807 rillig * contains some internal make variables. These internal variables can thus
319 1.807 rillig * be overridden, they can also be restored by undefining the overriding
320 1.807 rillig * variable.
321 1.807 rillig *
322 1.807 rillig * SCOPE_CMDLINE contains variables from the command line arguments. These
323 1.807 rillig * override variables from SCOPE_GLOBAL.
324 1.807 rillig *
325 1.807 rillig * There is no scope for environment variables, these are generated on-the-fly
326 1.1088 rillig * whenever they are referenced.
327 1.807 rillig *
328 1.807 rillig * Each target has its own scope, containing the 7 target-local variables
329 1.1006 sjg * .TARGET, .ALLSRC, etc. Variables set on dependency lines also go in
330 1.1006 sjg * this scope.
331 1.807 rillig */
332 1.807 rillig
333 1.807 rillig GNode *SCOPE_CMDLINE;
334 1.807 rillig GNode *SCOPE_GLOBAL;
335 1.807 rillig GNode *SCOPE_INTERNAL;
336 1.710 rillig
337 1.710 rillig static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
338 1.710 rillig
339 1.951 rillig static const char VarEvalMode_Name[][32] = {
340 1.1119 rillig "parse",
341 1.1047 rillig "parse-balanced",
342 1.906 rillig "eval",
343 1.1144 rillig "eval-defined-loud",
344 1.906 rillig "eval-defined",
345 1.906 rillig "eval-keep-undefined",
346 1.906 rillig "eval-keep-dollar-and-undefined",
347 1.906 rillig };
348 1.711 rillig
349 1.1102 rillig static EvalStack evalStack;
350 1.1102 rillig
351 1.1102 rillig
352 1.1120 rillig static void
353 1.1128 rillig EvalStack_Push(EvalStackElementKind kind, const char *str, const FStr *value)
354 1.1102 rillig {
355 1.1102 rillig if (evalStack.len >= evalStack.cap) {
356 1.1102 rillig evalStack.cap = 16 + 2 * evalStack.cap;
357 1.1102 rillig evalStack.elems = bmake_realloc(evalStack.elems,
358 1.1102 rillig evalStack.cap * sizeof(*evalStack.elems));
359 1.1102 rillig }
360 1.1120 rillig evalStack.elems[evalStack.len].kind = kind;
361 1.1120 rillig evalStack.elems[evalStack.len].str = str;
362 1.1128 rillig evalStack.elems[evalStack.len].value = value;
363 1.1102 rillig evalStack.len++;
364 1.1102 rillig }
365 1.1102 rillig
366 1.1120 rillig static void
367 1.1102 rillig EvalStack_Pop(void)
368 1.1102 rillig {
369 1.1102 rillig assert(evalStack.len > 0);
370 1.1102 rillig evalStack.len--;
371 1.1102 rillig }
372 1.1102 rillig
373 1.1152 rillig bool
374 1.1139 rillig EvalStack_PrintDetails(void)
375 1.1102 rillig {
376 1.1102 rillig size_t i;
377 1.1102 rillig
378 1.1139 rillig for (i = evalStack.len; i > 0; i--) {
379 1.1124 rillig static const char descr[][42] = {
380 1.1124 rillig "in target",
381 1.1146 rillig "in command",
382 1.1124 rillig "while evaluating variable",
383 1.1147 rillig "while evaluating indirect modifiers",
384 1.1124 rillig "while evaluating condition",
385 1.1124 rillig "while evaluating then-branch of condition",
386 1.1124 rillig "while evaluating else-branch of condition",
387 1.1124 rillig "while evaluating",
388 1.1133 rillig "while parsing",
389 1.1124 rillig };
390 1.1139 rillig EvalStackElement *elem = evalStack.elems + i - 1;
391 1.1132 rillig EvalStackElementKind kind = elem->kind;
392 1.1140 rillig const char* value = elem->value != NULL
393 1.1140 rillig && (kind == VSK_VARNAME || kind == VSK_EXPR)
394 1.1140 rillig ? elem->value->str : NULL;
395 1.1140 rillig
396 1.1140 rillig debug_printf("\t%s \"%s%s%s\"\n", descr[kind], elem->str,
397 1.1140 rillig value != NULL ? "\" with value \"" : "",
398 1.1140 rillig value != NULL ? value : "");
399 1.1102 rillig }
400 1.1152 rillig return evalStack.len > 0;
401 1.1102 rillig }
402 1.904 rillig
403 1.569 rillig static Var *
404 1.978 rillig VarNew(FStr name, const char *value,
405 1.978 rillig bool shortLived, bool fromEnvironment, bool readOnly)
406 1.569 rillig {
407 1.703 rillig size_t value_len = strlen(value);
408 1.703 rillig Var *var = bmake_malloc(sizeof *var);
409 1.744 rillig var->name = name;
410 1.703 rillig Buf_InitSize(&var->val, value_len + 1);
411 1.703 rillig Buf_AddBytes(&var->val, value, value_len);
412 1.902 rillig var->fromCmd = false;
413 1.978 rillig var->shortLived = shortLived;
414 1.978 rillig var->fromEnvironment = fromEnvironment;
415 1.902 rillig var->readOnly = readOnly;
416 1.1121 rillig var->readOnlyLoud = false;
417 1.902 rillig var->inUse = false;
418 1.902 rillig var->exported = false;
419 1.902 rillig var->reexport = false;
420 1.703 rillig return var;
421 1.569 rillig }
422 1.569 rillig
423 1.916 rillig static Substring
424 1.916 rillig CanonicalVarname(Substring name)
425 1.1 cgd {
426 1.916 rillig
427 1.916 rillig if (!(Substring_Length(name) > 0 && name.start[0] == '.'))
428 1.916 rillig return name;
429 1.916 rillig
430 1.916 rillig if (Substring_Equals(name, ".ALLSRC"))
431 1.916 rillig return Substring_InitStr(ALLSRC);
432 1.916 rillig if (Substring_Equals(name, ".ARCHIVE"))
433 1.916 rillig return Substring_InitStr(ARCHIVE);
434 1.916 rillig if (Substring_Equals(name, ".IMPSRC"))
435 1.916 rillig return Substring_InitStr(IMPSRC);
436 1.916 rillig if (Substring_Equals(name, ".MEMBER"))
437 1.916 rillig return Substring_InitStr(MEMBER);
438 1.916 rillig if (Substring_Equals(name, ".OODATE"))
439 1.916 rillig return Substring_InitStr(OODATE);
440 1.916 rillig if (Substring_Equals(name, ".PREFIX"))
441 1.916 rillig return Substring_InitStr(PREFIX);
442 1.916 rillig if (Substring_Equals(name, ".TARGET"))
443 1.916 rillig return Substring_InitStr(TARGET);
444 1.916 rillig
445 1.1079 rillig /* GNU make has an additional alias $^ == ${.ALLSRC}. */
446 1.1079 rillig
447 1.916 rillig if (Substring_Equals(name, ".SHELL") && shellPath == NULL)
448 1.916 rillig Shell_Init();
449 1.242 rillig
450 1.703 rillig return name;
451 1.580 rillig }
452 1.580 rillig
453 1.587 rillig static Var *
454 1.1160 rillig GNode_FindVar(GNode *scope, Substring varname, unsigned hash)
455 1.587 rillig {
456 1.916 rillig return HashTable_FindValueBySubstringHash(&scope->vars, varname, hash);
457 1.587 rillig }
458 1.587 rillig
459 1.778 rillig /*
460 1.802 rillig * Find the variable in the scope, and maybe in other scopes as well.
461 1.580 rillig *
462 1.580 rillig * Input:
463 1.607 rillig * name name to find, is not expanded any further
464 1.802 rillig * scope scope in which to look first
465 1.895 rillig * elsewhere true to look in other scopes as well
466 1.580 rillig *
467 1.580 rillig * Results:
468 1.605 rillig * The found variable, or NULL if the variable does not exist.
469 1.977 rillig * If the variable is short-lived (such as environment variables), it
470 1.977 rillig * must be freed using VarFreeShortLived after use.
471 1.580 rillig */
472 1.580 rillig static Var *
473 1.916 rillig VarFindSubstring(Substring name, GNode *scope, bool elsewhere)
474 1.580 rillig {
475 1.703 rillig Var *var;
476 1.1160 rillig unsigned nameHash;
477 1.703 rillig
478 1.830 rillig /* Replace '.TARGET' with '@', likewise for other local variables. */
479 1.703 rillig name = CanonicalVarname(name);
480 1.916 rillig nameHash = Hash_Substring(name);
481 1.580 rillig
482 1.802 rillig var = GNode_FindVar(scope, name, nameHash);
483 1.703 rillig if (!elsewhere)
484 1.703 rillig return var;
485 1.160 christos
486 1.802 rillig if (var == NULL && scope != SCOPE_CMDLINE)
487 1.801 rillig var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
488 1.1 cgd
489 1.802 rillig if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
490 1.801 rillig var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
491 1.802 rillig if (var == NULL && scope != SCOPE_INTERNAL) {
492 1.801 rillig /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
493 1.801 rillig var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
494 1.703 rillig }
495 1.184 sjg }
496 1.399 rillig
497 1.703 rillig if (var == NULL) {
498 1.1105 rillig FStr envName = Substring_Str(name);
499 1.1105 rillig const char *envValue = getenv(envName.str);
500 1.916 rillig if (envValue != NULL)
501 1.978 rillig return VarNew(envName, envValue, true, true, false);
502 1.916 rillig FStr_Done(&envName);
503 1.1 cgd
504 1.802 rillig if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
505 1.801 rillig var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
506 1.802 rillig if (var == NULL && scope != SCOPE_INTERNAL)
507 1.801 rillig var = GNode_FindVar(SCOPE_INTERNAL, name,
508 1.703 rillig nameHash);
509 1.703 rillig return var;
510 1.703 rillig }
511 1.399 rillig
512 1.703 rillig return NULL;
513 1.1 cgd }
514 1.399 rillig
515 1.703 rillig return var;
516 1.1 cgd }
517 1.1 cgd
518 1.916 rillig static Var *
519 1.916 rillig VarFind(const char *name, GNode *scope, bool elsewhere)
520 1.916 rillig {
521 1.916 rillig return VarFindSubstring(Substring_InitStr(name), scope, elsewhere);
522 1.916 rillig }
523 1.916 rillig
524 1.977 rillig /* If the variable is short-lived, free it, including its value. */
525 1.837 rillig static void
526 1.977 rillig VarFreeShortLived(Var *v)
527 1.105 christos {
528 1.978 rillig if (!v->shortLived)
529 1.837 rillig return;
530 1.605 rillig
531 1.711 rillig FStr_Done(&v->name);
532 1.837 rillig Buf_Done(&v->val);
533 1.703 rillig free(v);
534 1.105 christos }
535 1.105 christos
536 1.1018 rillig static const char *
537 1.1018 rillig ValueDescription(const char *value)
538 1.1018 rillig {
539 1.1018 rillig if (value[0] == '\0')
540 1.1018 rillig return "# (empty)";
541 1.1019 rillig if (ch_isspace(value[strlen(value) - 1]))
542 1.1018 rillig return "# (ends with space)";
543 1.1018 rillig return "";
544 1.1018 rillig }
545 1.1018 rillig
546 1.831 rillig /* Add a new variable of the given name and value to the given scope. */
547 1.833 rillig static Var *
548 1.831 rillig VarAdd(const char *name, const char *value, GNode *scope, VarSetFlags flags)
549 1.1 cgd {
550 1.802 rillig HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
551 1.831 rillig Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value,
552 1.978 rillig false, false, (flags & VAR_SET_READONLY) != 0);
553 1.703 rillig HashEntry_Set(he, v);
554 1.1018 rillig DEBUG4(VAR, "%s: %s = %s%s\n",
555 1.1018 rillig scope->name, name, value, ValueDescription(value));
556 1.833 rillig return v;
557 1.1 cgd }
558 1.1 cgd
559 1.736 rillig /*
560 1.802 rillig * Remove a variable from a scope, freeing all related memory as well.
561 1.736 rillig * The variable name is kept as-is, it is not expanded.
562 1.736 rillig */
563 1.736 rillig void
564 1.805 rillig Var_Delete(GNode *scope, const char *varname)
565 1.736 rillig {
566 1.802 rillig HashEntry *he = HashTable_FindEntry(&scope->vars, varname);
567 1.736 rillig Var *v;
568 1.736 rillig
569 1.736 rillig if (he == NULL) {
570 1.1085 rillig DEBUG2(VAR, "%s: ignoring delete '%s' as it is not found\n",
571 1.1017 rillig scope->name, varname);
572 1.736 rillig return;
573 1.736 rillig }
574 1.736 rillig
575 1.831 rillig v = he->value;
576 1.1121 rillig if (v->readOnlyLoud) {
577 1.1121 rillig Parse_Error(PARSE_FATAL,
578 1.1121 rillig "Cannot delete \"%s\" as it is read-only",
579 1.1121 rillig v->name.str);
580 1.1121 rillig return;
581 1.1121 rillig }
582 1.1056 sjg if (v->readOnly) {
583 1.1085 rillig DEBUG2(VAR, "%s: ignoring delete '%s' as it is read-only\n",
584 1.1056 sjg scope->name, varname);
585 1.1056 sjg return;
586 1.1056 sjg }
587 1.963 rillig if (v->inUse) {
588 1.963 rillig Parse_Error(PARSE_FATAL,
589 1.969 rillig "Cannot delete variable \"%s\" while it is used",
590 1.963 rillig v->name.str);
591 1.963 rillig return;
592 1.963 rillig }
593 1.1017 rillig
594 1.1085 rillig DEBUG2(VAR, "%s: delete %s\n", scope->name, varname);
595 1.902 rillig if (v->exported)
596 1.736 rillig unsetenv(v->name.str);
597 1.1045 rillig if (strcmp(v->name.str, ".MAKE.EXPORTED") == 0)
598 1.736 rillig var_exportedVars = VAR_EXPORTED_NONE;
599 1.1017 rillig
600 1.736 rillig assert(v->name.freeIt == NULL);
601 1.802 rillig HashTable_DeleteEntry(&scope->vars, he);
602 1.784 rillig Buf_Done(&v->val);
603 1.736 rillig free(v);
604 1.736 rillig }
605 1.736 rillig
606 1.1111 rillig #ifdef CLEANUP
607 1.1111 rillig void
608 1.1111 rillig Var_DeleteAll(GNode *scope)
609 1.1111 rillig {
610 1.1113 rillig HashIter hi;
611 1.1113 rillig HashIter_Init(&hi, &scope->vars);
612 1.1114 rillig while (HashIter_Next(&hi)) {
613 1.1113 rillig Var *v = hi.entry->value;
614 1.1113 rillig Buf_Done(&v->val);
615 1.1113 rillig free(v);
616 1.1111 rillig }
617 1.1111 rillig }
618 1.1111 rillig #endif
619 1.1111 rillig
620 1.778 rillig /*
621 1.762 rillig * Undefine one or more variables from the global scope.
622 1.762 rillig * The argument is expanded exactly once and then split into words.
623 1.737 rillig */
624 1.735 rillig void
625 1.762 rillig Var_Undef(const char *arg)
626 1.735 rillig {
627 1.762 rillig char *expanded;
628 1.762 rillig Words varnames;
629 1.762 rillig size_t i;
630 1.762 rillig
631 1.762 rillig if (arg[0] == '\0') {
632 1.762 rillig Parse_Error(PARSE_FATAL,
633 1.762 rillig "The .undef directive requires an argument");
634 1.762 rillig return;
635 1.762 rillig }
636 1.735 rillig
637 1.1119 rillig expanded = Var_Subst(arg, SCOPE_GLOBAL, VARE_EVAL);
638 1.1043 rillig if (expanded == var_Error) {
639 1.1043 rillig /* TODO: Make this part of the code reachable. */
640 1.737 rillig Parse_Error(PARSE_FATAL,
641 1.762 rillig "Error in variable names to be undefined");
642 1.762 rillig return;
643 1.762 rillig }
644 1.762 rillig
645 1.895 rillig varnames = Str_Words(expanded, false);
646 1.762 rillig if (varnames.len == 1 && varnames.words[0][0] == '\0')
647 1.762 rillig varnames.len = 0;
648 1.762 rillig
649 1.762 rillig for (i = 0; i < varnames.len; i++) {
650 1.762 rillig const char *varname = varnames.words[i];
651 1.804 rillig Global_Delete(varname);
652 1.737 rillig }
653 1.735 rillig
654 1.762 rillig Words_Free(varnames);
655 1.763 rillig free(expanded);
656 1.735 rillig }
657 1.735 rillig
658 1.895 rillig static bool
659 1.598 rillig MayExport(const char *name)
660 1.118 sjg {
661 1.703 rillig if (name[0] == '.')
662 1.895 rillig return false; /* skip internals */
663 1.703 rillig if (name[0] == '-')
664 1.895 rillig return false; /* skip misnamed variables */
665 1.703 rillig if (name[1] == '\0') {
666 1.703 rillig /*
667 1.703 rillig * A single char.
668 1.802 rillig * If it is one of the variables that should only appear in
669 1.802 rillig * local scope, skip it, else we can get Var_Subst
670 1.703 rillig * into a loop.
671 1.703 rillig */
672 1.703 rillig switch (name[0]) {
673 1.703 rillig case '@':
674 1.703 rillig case '%':
675 1.703 rillig case '*':
676 1.703 rillig case '!':
677 1.895 rillig return false;
678 1.703 rillig }
679 1.118 sjg }
680 1.895 rillig return true;
681 1.598 rillig }
682 1.598 rillig
683 1.895 rillig static bool
684 1.1100 sjg ExportVarEnv(Var *v, GNode *scope)
685 1.776 rillig {
686 1.776 rillig const char *name = v->name.str;
687 1.777 rillig char *val = v->val.data;
688 1.777 rillig char *expr;
689 1.776 rillig
690 1.902 rillig if (v->exported && !v->reexport)
691 1.895 rillig return false; /* nothing to do */
692 1.776 rillig
693 1.777 rillig if (strchr(val, '$') == NULL) {
694 1.902 rillig if (!v->exported)
695 1.776 rillig setenv(name, val, 1);
696 1.895 rillig return true;
697 1.776 rillig }
698 1.776 rillig
699 1.1070 rillig if (v->inUse)
700 1.1070 rillig return false; /* see EMPTY_SHELL in directive-export.mk */
701 1.776 rillig
702 1.777 rillig /* XXX: name is injected without escaping it */
703 1.777 rillig expr = str_concat3("${", name, "}");
704 1.1119 rillig val = Var_Subst(expr, scope, VARE_EVAL);
705 1.1100 sjg if (scope != SCOPE_GLOBAL) {
706 1.1101 rillig /* we will need to re-export the global version */
707 1.1100 sjg v = VarFind(name, SCOPE_GLOBAL, false);
708 1.1101 rillig if (v != NULL)
709 1.1100 sjg v->exported = false;
710 1.1100 sjg }
711 1.777 rillig /* TODO: handle errors */
712 1.777 rillig setenv(name, val, 1);
713 1.777 rillig free(val);
714 1.777 rillig free(expr);
715 1.895 rillig return true;
716 1.776 rillig }
717 1.776 rillig
718 1.895 rillig static bool
719 1.776 rillig ExportVarPlain(Var *v)
720 1.598 rillig {
721 1.777 rillig if (strchr(v->val.data, '$') == NULL) {
722 1.777 rillig setenv(v->name.str, v->val.data, 1);
723 1.902 rillig v->exported = true;
724 1.902 rillig v->reexport = false;
725 1.895 rillig return true;
726 1.776 rillig }
727 1.776 rillig
728 1.777 rillig /*
729 1.777 rillig * Flag the variable as something we need to re-export.
730 1.777 rillig * No point actually exporting it now though,
731 1.777 rillig * the child process can do it at the last minute.
732 1.830 rillig * Avoid calling setenv more often than necessary since it can leak.
733 1.777 rillig */
734 1.902 rillig v->exported = true;
735 1.902 rillig v->reexport = true;
736 1.895 rillig return true;
737 1.776 rillig }
738 1.401 rillig
739 1.895 rillig static bool
740 1.776 rillig ExportVarLiteral(Var *v)
741 1.776 rillig {
742 1.902 rillig if (v->exported && !v->reexport)
743 1.895 rillig return false;
744 1.401 rillig
745 1.902 rillig if (!v->exported)
746 1.777 rillig setenv(v->name.str, v->val.data, 1);
747 1.605 rillig
748 1.895 rillig return true;
749 1.118 sjg }
750 1.118 sjg
751 1.118 sjg /*
752 1.830 rillig * Mark a single variable to be exported later for subprocesses.
753 1.776 rillig *
754 1.1088 rillig * Internal variables are not exported.
755 1.776 rillig */
756 1.895 rillig static bool
757 1.1100 sjg ExportVar(const char *name, GNode *scope, VarExportMode mode)
758 1.776 rillig {
759 1.776 rillig Var *v;
760 1.776 rillig
761 1.776 rillig if (!MayExport(name))
762 1.895 rillig return false;
763 1.776 rillig
764 1.1100 sjg v = VarFind(name, scope, false);
765 1.1100 sjg if (v == NULL && scope != SCOPE_GLOBAL)
766 1.1100 sjg v = VarFind(name, SCOPE_GLOBAL, false);
767 1.776 rillig if (v == NULL)
768 1.895 rillig return false;
769 1.776 rillig
770 1.776 rillig if (mode == VEM_ENV)
771 1.1100 sjg return ExportVarEnv(v, scope);
772 1.776 rillig else if (mode == VEM_PLAIN)
773 1.776 rillig return ExportVarPlain(v);
774 1.776 rillig else
775 1.776 rillig return ExportVarLiteral(v);
776 1.776 rillig }
777 1.776 rillig
778 1.776 rillig /*
779 1.765 rillig * Actually export the variables that have been marked as needing to be
780 1.765 rillig * re-exported.
781 1.118 sjg */
782 1.118 sjg void
783 1.1100 sjg Var_ReexportVars(GNode *scope)
784 1.118 sjg {
785 1.775 rillig char *xvarnames;
786 1.412 rillig
787 1.703 rillig /*
788 1.703 rillig * Several make implementations support this sort of mechanism for
789 1.703 rillig * tracking recursion - but each uses a different name.
790 1.703 rillig * We allow the makefiles to update MAKELEVEL and ensure
791 1.703 rillig * children see a correctly incremented value.
792 1.703 rillig */
793 1.1067 rillig char level_buf[21];
794 1.1067 rillig snprintf(level_buf, sizeof level_buf, "%d", makelevel + 1);
795 1.1067 rillig setenv(MAKE_LEVEL_ENV, level_buf, 1);
796 1.182 christos
797 1.703 rillig if (var_exportedVars == VAR_EXPORTED_NONE)
798 1.703 rillig return;
799 1.118 sjg
800 1.703 rillig if (var_exportedVars == VAR_EXPORTED_ALL) {
801 1.703 rillig HashIter hi;
802 1.575 rillig
803 1.831 rillig /* Ouch! Exporting all variables at once is crazy. */
804 1.801 rillig HashIter_Init(&hi, &SCOPE_GLOBAL->vars);
805 1.1114 rillig while (HashIter_Next(&hi)) {
806 1.703 rillig Var *var = hi.entry->value;
807 1.1100 sjg ExportVar(var->name.str, scope, VEM_ENV);
808 1.703 rillig }
809 1.703 rillig return;
810 1.575 rillig }
811 1.369 rillig
812 1.1045 rillig xvarnames = Var_Subst("${.MAKE.EXPORTED:O:u}", SCOPE_GLOBAL,
813 1.1119 rillig VARE_EVAL);
814 1.703 rillig /* TODO: handle errors */
815 1.775 rillig if (xvarnames[0] != '\0') {
816 1.895 rillig Words varnames = Str_Words(xvarnames, false);
817 1.703 rillig size_t i;
818 1.703 rillig
819 1.775 rillig for (i = 0; i < varnames.len; i++)
820 1.1100 sjg ExportVar(varnames.words[i], scope, VEM_ENV);
821 1.775 rillig Words_Free(varnames);
822 1.703 rillig }
823 1.775 rillig free(xvarnames);
824 1.118 sjg }
825 1.118 sjg
826 1.726 rillig static void
827 1.895 rillig ExportVars(const char *varnames, bool isExport, VarExportMode mode)
828 1.831 rillig /* TODO: try to combine the parameters 'isExport' and 'mode'. */
829 1.726 rillig {
830 1.895 rillig Words words = Str_Words(varnames, false);
831 1.727 rillig size_t i;
832 1.727 rillig
833 1.727 rillig if (words.len == 1 && words.words[0][0] == '\0')
834 1.727 rillig words.len = 0;
835 1.727 rillig
836 1.727 rillig for (i = 0; i < words.len; i++) {
837 1.727 rillig const char *varname = words.words[i];
838 1.1100 sjg if (!ExportVar(varname, SCOPE_GLOBAL, mode))
839 1.727 rillig continue;
840 1.727 rillig
841 1.727 rillig if (var_exportedVars == VAR_EXPORTED_NONE)
842 1.727 rillig var_exportedVars = VAR_EXPORTED_SOME;
843 1.726 rillig
844 1.765 rillig if (isExport && mode == VEM_PLAIN)
845 1.1045 rillig Global_Append(".MAKE.EXPORTED", varname);
846 1.726 rillig }
847 1.727 rillig Words_Free(words);
848 1.726 rillig }
849 1.726 rillig
850 1.728 rillig static void
851 1.895 rillig ExportVarsExpand(const char *uvarnames, bool isExport, VarExportMode mode)
852 1.728 rillig {
853 1.1119 rillig char *xvarnames = Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_EVAL);
854 1.728 rillig /* TODO: handle errors */
855 1.730 rillig ExportVars(xvarnames, isExport, mode);
856 1.728 rillig free(xvarnames);
857 1.728 rillig }
858 1.728 rillig
859 1.731 rillig /* Export the named variables, or all variables. */
860 1.118 sjg void
861 1.731 rillig Var_Export(VarExportMode mode, const char *varnames)
862 1.118 sjg {
863 1.1117 sjg if (mode == VEM_ALL) {
864 1.703 rillig var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
865 1.703 rillig return;
866 1.1117 sjg } else if (mode == VEM_PLAIN && varnames[0] == '\0') {
867 1.1117 sjg Parse_Error(PARSE_WARNING, ".export requires an argument.");
868 1.1117 sjg return;
869 1.703 rillig }
870 1.118 sjg
871 1.895 rillig ExportVarsExpand(varnames, true, mode);
872 1.729 rillig }
873 1.729 rillig
874 1.729 rillig void
875 1.729 rillig Var_ExportVars(const char *varnames)
876 1.729 rillig {
877 1.895 rillig ExportVarsExpand(varnames, false, VEM_PLAIN);
878 1.118 sjg }
879 1.118 sjg
880 1.155 sjg
881 1.700 rillig static void
882 1.714 rillig ClearEnv(void)
883 1.701 rillig {
884 1.1083 rillig const char *level;
885 1.701 rillig char **newenv;
886 1.701 rillig
887 1.1083 rillig level = getenv(MAKE_LEVEL_ENV); /* we should preserve this */
888 1.701 rillig if (environ == savedEnv) {
889 1.701 rillig /* we have been here before! */
890 1.701 rillig newenv = bmake_realloc(environ, 2 * sizeof(char *));
891 1.701 rillig } else {
892 1.701 rillig if (savedEnv != NULL) {
893 1.701 rillig free(savedEnv);
894 1.701 rillig savedEnv = NULL;
895 1.701 rillig }
896 1.701 rillig newenv = bmake_malloc(2 * sizeof(char *));
897 1.701 rillig }
898 1.701 rillig
899 1.701 rillig /* Note: we cannot safely free() the original environ. */
900 1.701 rillig environ = savedEnv = newenv;
901 1.701 rillig newenv[0] = NULL;
902 1.701 rillig newenv[1] = NULL;
903 1.1083 rillig if (level != NULL && *level != '\0')
904 1.1083 rillig setenv(MAKE_LEVEL_ENV, level, 1);
905 1.701 rillig }
906 1.701 rillig
907 1.701 rillig static void
908 1.895 rillig GetVarnamesToUnexport(bool isEnv, const char *arg,
909 1.715 rillig FStr *out_varnames, UnexportWhat *out_what)
910 1.714 rillig {
911 1.714 rillig UnexportWhat what;
912 1.739 rillig FStr varnames = FStr_InitRefer("");
913 1.714 rillig
914 1.732 rillig if (isEnv) {
915 1.732 rillig if (arg[0] != '\0') {
916 1.723 rillig Parse_Error(PARSE_FATAL,
917 1.723 rillig "The directive .unexport-env does not take "
918 1.723 rillig "arguments");
919 1.830 rillig /* continue anyway */
920 1.723 rillig }
921 1.714 rillig what = UNEXPORT_ENV;
922 1.723 rillig
923 1.732 rillig } else {
924 1.732 rillig what = arg[0] != '\0' ? UNEXPORT_NAMED : UNEXPORT_ALL;
925 1.714 rillig if (what == UNEXPORT_NAMED)
926 1.739 rillig varnames = FStr_InitRefer(arg);
927 1.714 rillig }
928 1.714 rillig
929 1.714 rillig if (what != UNEXPORT_NAMED) {
930 1.1045 rillig char *expanded = Var_Subst("${.MAKE.EXPORTED:O:u}",
931 1.1119 rillig SCOPE_GLOBAL, VARE_EVAL);
932 1.714 rillig /* TODO: handle errors */
933 1.739 rillig varnames = FStr_InitOwn(expanded);
934 1.714 rillig }
935 1.714 rillig
936 1.714 rillig *out_varnames = varnames;
937 1.714 rillig *out_what = what;
938 1.714 rillig }
939 1.714 rillig
940 1.714 rillig static void
941 1.959 rillig UnexportVar(Substring varname, UnexportWhat what)
942 1.700 rillig {
943 1.959 rillig Var *v = VarFindSubstring(varname, SCOPE_GLOBAL, false);
944 1.700 rillig if (v == NULL) {
945 1.959 rillig DEBUG2(VAR, "Not unexporting \"%.*s\" (not found)\n",
946 1.959 rillig (int)Substring_Length(varname), varname.start);
947 1.700 rillig return;
948 1.700 rillig }
949 1.700 rillig
950 1.959 rillig DEBUG2(VAR, "Unexporting \"%.*s\"\n",
951 1.959 rillig (int)Substring_Length(varname), varname.start);
952 1.902 rillig if (what != UNEXPORT_ENV && v->exported && !v->reexport)
953 1.711 rillig unsetenv(v->name.str);
954 1.902 rillig v->exported = false;
955 1.902 rillig v->reexport = false;
956 1.700 rillig
957 1.713 rillig if (what == UNEXPORT_NAMED) {
958 1.713 rillig /* Remove the variable names from .MAKE.EXPORTED. */
959 1.700 rillig /* XXX: v->name is injected without escaping it */
960 1.1083 rillig char *expr = str_concat3(
961 1.1083 rillig "${.MAKE.EXPORTED:N", v->name.str, "}");
962 1.1119 rillig char *filtered = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL);
963 1.700 rillig /* TODO: handle errors */
964 1.1083 rillig Global_Set(".MAKE.EXPORTED", filtered);
965 1.1083 rillig free(filtered);
966 1.700 rillig free(expr);
967 1.700 rillig }
968 1.700 rillig }
969 1.700 rillig
970 1.716 rillig static void
971 1.1142 rillig UnexportVars(const char *varnames, UnexportWhat what)
972 1.716 rillig {
973 1.716 rillig size_t i;
974 1.959 rillig SubstringWords words;
975 1.717 rillig
976 1.717 rillig if (what == UNEXPORT_ENV)
977 1.717 rillig ClearEnv();
978 1.716 rillig
979 1.1142 rillig words = Substring_Words(varnames, false);
980 1.959 rillig for (i = 0; i < words.len; i++)
981 1.959 rillig UnexportVar(words.words[i], what);
982 1.959 rillig SubstringWords_Free(words);
983 1.716 rillig
984 1.716 rillig if (what != UNEXPORT_NAMED)
985 1.1045 rillig Global_Delete(".MAKE.EXPORTED");
986 1.716 rillig }
987 1.716 rillig
988 1.1088 rillig /* Handle the .unexport and .unexport-env directives. */
989 1.155 sjg void
990 1.895 rillig Var_UnExport(bool isEnv, const char *arg)
991 1.155 sjg {
992 1.713 rillig UnexportWhat what;
993 1.714 rillig FStr varnames;
994 1.155 sjg
995 1.732 rillig GetVarnamesToUnexport(isEnv, arg, &varnames, &what);
996 1.1142 rillig UnexportVars(varnames.str, what);
997 1.712 rillig FStr_Done(&varnames);
998 1.155 sjg }
999 1.155 sjg
1000 1.747 rillig /* Set the variable to the value; the name is not expanded. */
1001 1.800 rillig void
1002 1.805 rillig Var_SetWithFlags(GNode *scope, const char *name, const char *val,
1003 1.800 rillig VarSetFlags flags)
1004 1.1 cgd {
1005 1.704 rillig Var *v;
1006 1.142 dsl
1007 1.793 rillig assert(val != NULL);
1008 1.793 rillig if (name[0] == '\0') {
1009 1.1086 rillig DEBUG3(VAR,
1010 1.1086 rillig "%s: ignoring '%s = %s' as the variable name is empty\n",
1011 1.1086 rillig scope->name, name, val);
1012 1.793 rillig return;
1013 1.793 rillig }
1014 1.793 rillig
1015 1.1089 rillig if (scope == SCOPE_GLOBAL
1016 1.1089 rillig && VarFind(name, SCOPE_CMDLINE, false) != NULL) {
1017 1.1089 rillig /*
1018 1.1089 rillig * The global variable would not be visible anywhere.
1019 1.1089 rillig * Therefore, there is no point in setting it at all.
1020 1.1089 rillig */
1021 1.1082 rillig DEBUG3(VAR,
1022 1.1086 rillig "%s: ignoring '%s = %s' "
1023 1.1082 rillig "due to a command line variable of the same name\n",
1024 1.1086 rillig scope->name, name, val);
1025 1.834 rillig return;
1026 1.1080 rillig }
1027 1.400 rillig
1028 1.704 rillig /*
1029 1.802 rillig * Only look for a variable in the given scope since anything set
1030 1.802 rillig * here will override anything in a lower scope, so there's not much
1031 1.830 rillig * point in searching them all.
1032 1.704 rillig */
1033 1.895 rillig v = VarFind(name, scope, false);
1034 1.704 rillig if (v == NULL) {
1035 1.802 rillig if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
1036 1.704 rillig /*
1037 1.1105 rillig * This variable would normally prevent the same name
1038 1.1105 rillig * being added to SCOPE_GLOBAL, so delete it from
1039 1.1105 rillig * there if needed. Otherwise -V name may show the
1040 1.1105 rillig * wrong value.
1041 1.832 rillig *
1042 1.835 rillig * See ExistsInCmdline.
1043 1.704 rillig */
1044 1.1141 rillig Var *gl = VarFind(name, SCOPE_GLOBAL, false);
1045 1.1145 rillig if (gl != NULL && strcmp(gl->val.data, val) == 0) {
1046 1.1145 rillig DEBUG3(VAR,
1047 1.1145 rillig "%s: ignoring to override the global "
1048 1.1145 rillig "'%s = %s' from a command line variable "
1049 1.1145 rillig "as the value wouldn't change\n",
1050 1.1145 rillig scope->name, name, val);
1051 1.1145 rillig } else if (gl != NULL && gl->readOnlyLoud)
1052 1.1141 rillig Parse_Error(PARSE_FATAL,
1053 1.1141 rillig "Cannot override "
1054 1.1141 rillig "read-only global variable \"%s\" "
1055 1.1141 rillig "with a command line variable", name);
1056 1.1141 rillig else
1057 1.1141 rillig Var_Delete(SCOPE_GLOBAL, name);
1058 1.704 rillig }
1059 1.973 sjg if (strcmp(name, ".SUFFIXES") == 0) {
1060 1.1079 rillig /* special: treat as read-only */
1061 1.1086 rillig DEBUG3(VAR,
1062 1.1086 rillig "%s: ignoring '%s = %s' as it is read-only\n",
1063 1.973 sjg scope->name, name, val);
1064 1.973 sjg return;
1065 1.973 sjg }
1066 1.833 rillig v = VarAdd(name, val, scope, flags);
1067 1.704 rillig } else {
1068 1.1121 rillig if (v->readOnlyLoud) {
1069 1.1121 rillig Parse_Error(PARSE_FATAL,
1070 1.1121 rillig "Cannot overwrite \"%s\" as it is read-only",
1071 1.1121 rillig name);
1072 1.1121 rillig return;
1073 1.1121 rillig }
1074 1.902 rillig if (v->readOnly && !(flags & VAR_SET_READONLY)) {
1075 1.1086 rillig DEBUG3(VAR,
1076 1.1086 rillig "%s: ignoring '%s = %s' as it is read-only\n",
1077 1.802 rillig scope->name, name, val);
1078 1.747 rillig return;
1079 1.704 rillig }
1080 1.998 rillig Buf_Clear(&v->val);
1081 1.704 rillig Buf_AddStr(&v->val, val);
1082 1.704 rillig
1083 1.1018 rillig DEBUG4(VAR, "%s: %s = %s%s\n",
1084 1.1018 rillig scope->name, name, val, ValueDescription(val));
1085 1.902 rillig if (v->exported)
1086 1.1100 sjg ExportVar(name, scope, VEM_PLAIN);
1087 1.183 sjg }
1088 1.833 rillig
1089 1.1076 sjg if (scope == SCOPE_CMDLINE) {
1090 1.902 rillig v->fromCmd = true;
1091 1.1079 rillig
1092 1.1079 rillig /*
1093 1.1079 rillig * Any variables given on the command line are automatically
1094 1.1079 rillig * exported to the environment (as per POSIX standard), except
1095 1.1079 rillig * for internals.
1096 1.1079 rillig */
1097 1.1109 sjg if (!(flags & VAR_SET_NO_EXPORT)) {
1098 1.704 rillig
1099 1.1076 sjg /*
1100 1.1076 sjg * If requested, don't export these in the
1101 1.1076 sjg * environment individually. We still put
1102 1.1076 sjg * them in .MAKEOVERRIDES so that the
1103 1.1077 rillig * command-line settings continue to override
1104 1.1076 sjg * Makefile settings.
1105 1.1076 sjg */
1106 1.1109 sjg if (!opts.varNoExportEnv && name[0] != '.')
1107 1.1076 sjg setenv(name, val, 1);
1108 1.1109 sjg
1109 1.1109 sjg if (!(flags & VAR_SET_INTERNAL))
1110 1.1109 sjg Global_Append(".MAKEOVERRIDES", name);
1111 1.1076 sjg }
1112 1.704 rillig }
1113 1.833 rillig
1114 1.704 rillig if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
1115 1.704 rillig save_dollars = ParseBoolean(val, save_dollars);
1116 1.205 sjg
1117 1.704 rillig if (v != NULL)
1118 1.977 rillig VarFreeShortLived(v);
1119 1.1 cgd }
1120 1.1 cgd
1121 1.798 rillig void
1122 1.805 rillig Var_Set(GNode *scope, const char *name, const char *val)
1123 1.798 rillig {
1124 1.805 rillig Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1125 1.798 rillig }
1126 1.798 rillig
1127 1.718 rillig /*
1128 1.1079 rillig * In the scope, expand the variable name once, then create the variable or
1129 1.1079 rillig * replace its value.
1130 1.230 rillig */
1131 1.230 rillig void
1132 1.805 rillig Var_SetExpand(GNode *scope, const char *name, const char *val)
1133 1.230 rillig {
1134 1.1007 rillig FStr varname = FStr_InitRefer(name);
1135 1.1007 rillig
1136 1.1007 rillig assert(val != NULL);
1137 1.1007 rillig
1138 1.1119 rillig Var_Expand(&varname, scope, VARE_EVAL);
1139 1.1007 rillig
1140 1.1007 rillig if (varname.str[0] == '\0') {
1141 1.1086 rillig DEBUG4(VAR,
1142 1.1086 rillig "%s: ignoring '%s = %s' "
1143 1.1086 rillig "as the variable name '%s' expands to empty\n",
1144 1.1089 rillig scope->name, varname.str, val, name);
1145 1.1007 rillig } else
1146 1.1007 rillig Var_SetWithFlags(scope, varname.str, val, VAR_SET_NONE);
1147 1.1007 rillig
1148 1.1007 rillig FStr_Done(&varname);
1149 1.230 rillig }
1150 1.230 rillig
1151 1.791 rillig void
1152 1.792 rillig Global_Set(const char *name, const char *value)
1153 1.792 rillig {
1154 1.805 rillig Var_Set(SCOPE_GLOBAL, name, value);
1155 1.792 rillig }
1156 1.792 rillig
1157 1.792 rillig void
1158 1.804 rillig Global_Delete(const char *name)
1159 1.804 rillig {
1160 1.805 rillig Var_Delete(SCOPE_GLOBAL, name);
1161 1.804 rillig }
1162 1.804 rillig
1163 1.1039 sjg void
1164 1.1039 sjg Global_Set_ReadOnly(const char *name, const char *value)
1165 1.1039 sjg {
1166 1.1121 rillig Var_SetWithFlags(SCOPE_GLOBAL, name, value, VAR_SET_NONE);
1167 1.1121 rillig VarFind(name, SCOPE_GLOBAL, false)->readOnlyLoud = true;
1168 1.1039 sjg }
1169 1.1039 sjg
1170 1.718 rillig /*
1171 1.794 rillig * Append the value to the named variable.
1172 1.794 rillig *
1173 1.794 rillig * If the variable doesn't exist, it is created. Otherwise a single space
1174 1.794 rillig * and the given value are appended.
1175 1.794 rillig */
1176 1.794 rillig void
1177 1.805 rillig Var_Append(GNode *scope, const char *name, const char *val)
1178 1.794 rillig {
1179 1.794 rillig Var *v;
1180 1.794 rillig
1181 1.802 rillig v = VarFind(name, scope, scope == SCOPE_GLOBAL);
1182 1.794 rillig
1183 1.794 rillig if (v == NULL) {
1184 1.805 rillig Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1185 1.1121 rillig } else if (v->readOnlyLoud) {
1186 1.1121 rillig Parse_Error(PARSE_FATAL,
1187 1.1121 rillig "Cannot append to \"%s\" as it is read-only", name);
1188 1.1121 rillig return;
1189 1.902 rillig } else if (v->readOnly) {
1190 1.1086 rillig DEBUG3(VAR, "%s: ignoring '%s += %s' as it is read-only\n",
1191 1.1086 rillig scope->name, name, val);
1192 1.902 rillig } else if (scope == SCOPE_CMDLINE || !v->fromCmd) {
1193 1.794 rillig Buf_AddByte(&v->val, ' ');
1194 1.794 rillig Buf_AddStr(&v->val, val);
1195 1.794 rillig
1196 1.911 rillig DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, v->val.data);
1197 1.794 rillig
1198 1.978 rillig if (v->fromEnvironment) {
1199 1.1014 rillig /* See VarAdd. */
1200 1.1014 rillig HashEntry *he =
1201 1.1014 rillig HashTable_CreateEntry(&scope->vars, name, NULL);
1202 1.1014 rillig HashEntry_Set(he, v);
1203 1.1014 rillig FStr_Done(&v->name);
1204 1.1014 rillig v->name = FStr_InitRefer(/* aliased to */ he->key);
1205 1.1014 rillig v->shortLived = false;
1206 1.978 rillig v->fromEnvironment = false;
1207 1.794 rillig }
1208 1.794 rillig }
1209 1.794 rillig }
1210 1.794 rillig
1211 1.794 rillig /*
1212 1.1088 rillig * In the scope, expand the variable name once. If the variable exists in the
1213 1.1088 rillig * scope, add a space and the value, otherwise set the variable to the value.
1214 1.483 rillig *
1215 1.1088 rillig * Appending to an environment variable only works in the global scope, that
1216 1.1088 rillig * is, for variable assignments in makefiles, but not inside conditions or the
1217 1.1088 rillig * commands of a target.
1218 1.1 cgd */
1219 1.1 cgd void
1220 1.805 rillig Var_AppendExpand(GNode *scope, const char *name, const char *val)
1221 1.1 cgd {
1222 1.838 rillig FStr xname = FStr_InitRefer(name);
1223 1.1 cgd
1224 1.704 rillig assert(val != NULL);
1225 1.460 rillig
1226 1.1119 rillig Var_Expand(&xname, scope, VARE_EVAL);
1227 1.1001 rillig if (xname.str != name && xname.str[0] == '\0')
1228 1.1086 rillig DEBUG4(VAR,
1229 1.1086 rillig "%s: ignoring '%s += %s' "
1230 1.1086 rillig "as the variable name '%s' expands to empty\n",
1231 1.1086 rillig scope->name, xname.str, val, name);
1232 1.1001 rillig else
1233 1.1001 rillig Var_Append(scope, xname.str, val);
1234 1.1 cgd
1235 1.838 rillig FStr_Done(&xname);
1236 1.1 cgd }
1237 1.1 cgd
1238 1.791 rillig void
1239 1.795 rillig Global_Append(const char *name, const char *value)
1240 1.791 rillig {
1241 1.805 rillig Var_Append(SCOPE_GLOBAL, name, value);
1242 1.791 rillig }
1243 1.791 rillig
1244 1.895 rillig bool
1245 1.805 rillig Var_Exists(GNode *scope, const char *name)
1246 1.796 rillig {
1247 1.895 rillig Var *v = VarFind(name, scope, true);
1248 1.796 rillig if (v == NULL)
1249 1.895 rillig return false;
1250 1.796 rillig
1251 1.977 rillig VarFreeShortLived(v);
1252 1.895 rillig return true;
1253 1.796 rillig }
1254 1.796 rillig
1255 1.778 rillig /*
1256 1.802 rillig * See if the given variable exists, in the given scope or in other
1257 1.802 rillig * fallback scopes.
1258 1.1 cgd *
1259 1.70 wiz * Input:
1260 1.953 rillig * scope scope in which to start search
1261 1.953 rillig * name name of the variable to find, is expanded once
1262 1.1 cgd */
1263 1.895 rillig bool
1264 1.805 rillig Var_ExistsExpand(GNode *scope, const char *name)
1265 1.1 cgd {
1266 1.747 rillig FStr varname = FStr_InitRefer(name);
1267 1.895 rillig bool exists;
1268 1.412 rillig
1269 1.1119 rillig Var_Expand(&varname, scope, VARE_EVAL);
1270 1.805 rillig exists = Var_Exists(scope, varname.str);
1271 1.747 rillig FStr_Done(&varname);
1272 1.796 rillig return exists;
1273 1.1 cgd }
1274 1.1 cgd
1275 1.718 rillig /*
1276 1.802 rillig * Return the unexpanded value of the given variable in the given scope,
1277 1.1066 rillig * falling back to the command, global and environment scopes, in this order,
1278 1.1066 rillig * but see the -e option.
1279 1.1 cgd *
1280 1.70 wiz * Input:
1281 1.1066 rillig * name the name to find, is not expanded any further
1282 1.70 wiz *
1283 1.1 cgd * Results:
1284 1.337 rillig * The value if the variable exists, NULL if it doesn't.
1285 1.830 rillig * The value is valid until the next modification to any variable.
1286 1.1 cgd */
1287 1.745 rillig FStr
1288 1.805 rillig Var_Value(GNode *scope, const char *name)
1289 1.1 cgd {
1290 1.895 rillig Var *v = VarFind(name, scope, true);
1291 1.703 rillig char *value;
1292 1.703 rillig
1293 1.703 rillig if (v == NULL)
1294 1.745 rillig return FStr_InitRefer(NULL);
1295 1.412 rillig
1296 1.978 rillig if (!v->shortLived)
1297 1.837 rillig return FStr_InitRefer(v->val.data);
1298 1.837 rillig
1299 1.978 rillig value = v->val.data;
1300 1.978 rillig v->val.data = NULL;
1301 1.978 rillig VarFreeShortLived(v);
1302 1.978 rillig
1303 1.837 rillig return FStr_InitOwn(value);
1304 1.1 cgd }
1305 1.1 cgd
1306 1.1088 rillig /* Set or clear the read-only attribute of the variable if it exists. */
1307 1.1037 sjg void
1308 1.1037 sjg Var_ReadOnly(const char *name, bool bf)
1309 1.1037 sjg {
1310 1.1037 sjg Var *v;
1311 1.1037 sjg
1312 1.1037 sjg v = VarFind(name, SCOPE_GLOBAL, false);
1313 1.1037 sjg if (v == NULL) {
1314 1.1037 sjg DEBUG1(VAR, "Var_ReadOnly: %s not found\n", name);
1315 1.1037 sjg return;
1316 1.1037 sjg }
1317 1.1037 sjg v->readOnly = bf;
1318 1.1038 sjg DEBUG2(VAR, "Var_ReadOnly: %s %s\n", name, bf ? "true" : "false");
1319 1.1037 sjg }
1320 1.1037 sjg
1321 1.1037 sjg /*
1322 1.778 rillig * Return the unexpanded variable value from this node, without trying to look
1323 1.802 rillig * up the variable in any other scope.
1324 1.778 rillig */
1325 1.616 rillig const char *
1326 1.803 rillig GNode_ValueDirect(GNode *gn, const char *name)
1327 1.616 rillig {
1328 1.895 rillig Var *v = VarFind(name, gn, false);
1329 1.785 rillig return v != NULL ? v->val.data : NULL;
1330 1.616 rillig }
1331 1.616 rillig
1332 1.906 rillig static VarEvalMode
1333 1.906 rillig VarEvalMode_WithoutKeepDollar(VarEvalMode emode)
1334 1.906 rillig {
1335 1.1119 rillig return emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED
1336 1.1119 rillig ? VARE_EVAL_KEEP_UNDEFINED : emode;
1337 1.906 rillig }
1338 1.906 rillig
1339 1.905 rillig static bool
1340 1.906 rillig VarEvalMode_ShouldEval(VarEvalMode emode)
1341 1.905 rillig {
1342 1.1119 rillig return emode != VARE_PARSE;
1343 1.906 rillig }
1344 1.906 rillig
1345 1.906 rillig static bool
1346 1.906 rillig VarEvalMode_ShouldKeepUndef(VarEvalMode emode)
1347 1.906 rillig {
1348 1.1119 rillig return emode == VARE_EVAL_KEEP_UNDEFINED ||
1349 1.1119 rillig emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED;
1350 1.906 rillig }
1351 1.906 rillig
1352 1.906 rillig static bool
1353 1.906 rillig VarEvalMode_ShouldKeepDollar(VarEvalMode emode)
1354 1.906 rillig {
1355 1.1119 rillig return emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED;
1356 1.905 rillig }
1357 1.905 rillig
1358 1.905 rillig
1359 1.278 rillig static void
1360 1.278 rillig SepBuf_Init(SepBuf *buf, char sep)
1361 1.278 rillig {
1362 1.703 rillig Buf_InitSize(&buf->buf, 32);
1363 1.895 rillig buf->needSep = false;
1364 1.703 rillig buf->sep = sep;
1365 1.278 rillig }
1366 1.278 rillig
1367 1.278 rillig static void
1368 1.278 rillig SepBuf_Sep(SepBuf *buf)
1369 1.278 rillig {
1370 1.895 rillig buf->needSep = true;
1371 1.278 rillig }
1372 1.278 rillig
1373 1.278 rillig static void
1374 1.314 rillig SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1375 1.278 rillig {
1376 1.703 rillig if (mem_size == 0)
1377 1.703 rillig return;
1378 1.703 rillig if (buf->needSep && buf->sep != '\0') {
1379 1.703 rillig Buf_AddByte(&buf->buf, buf->sep);
1380 1.895 rillig buf->needSep = false;
1381 1.703 rillig }
1382 1.703 rillig Buf_AddBytes(&buf->buf, mem, mem_size);
1383 1.278 rillig }
1384 1.278 rillig
1385 1.314 rillig static void
1386 1.1055 rillig SepBuf_AddRange(SepBuf *buf, const char *start, const char *end)
1387 1.314 rillig {
1388 1.703 rillig SepBuf_AddBytes(buf, start, (size_t)(end - start));
1389 1.314 rillig }
1390 1.314 rillig
1391 1.314 rillig static void
1392 1.314 rillig SepBuf_AddStr(SepBuf *buf, const char *str)
1393 1.314 rillig {
1394 1.703 rillig SepBuf_AddBytes(buf, str, strlen(str));
1395 1.314 rillig }
1396 1.314 rillig
1397 1.919 rillig static void
1398 1.919 rillig SepBuf_AddSubstring(SepBuf *buf, Substring sub)
1399 1.919 rillig {
1400 1.1055 rillig SepBuf_AddRange(buf, sub.start, sub.end);
1401 1.919 rillig }
1402 1.919 rillig
1403 1.278 rillig static char *
1404 1.784 rillig SepBuf_DoneData(SepBuf *buf)
1405 1.278 rillig {
1406 1.784 rillig return Buf_DoneData(&buf->buf);
1407 1.278 rillig }
1408 1.278 rillig
1409 1.278 rillig
1410 1.778 rillig /*
1411 1.1075 rillig * This callback for ModifyWords gets a single word from an expression
1412 1.609 rillig * and typically adds a modification of this word to the buffer. It may also
1413 1.609 rillig * do nothing or add several words.
1414 1.609 rillig *
1415 1.822 rillig * For example, when evaluating the modifier ':M*b' in ${:Ua b c:M*b}, the
1416 1.822 rillig * callback is called 3 times, once for "a", "b" and "c".
1417 1.919 rillig *
1418 1.919 rillig * Some ModifyWord functions assume that they are always passed a
1419 1.919 rillig * null-terminated substring, which is currently guaranteed but may change in
1420 1.919 rillig * the future.
1421 1.778 rillig */
1422 1.919 rillig typedef void (*ModifyWordProc)(Substring word, SepBuf *buf, void *data);
1423 1.244 rillig
1424 1.244 rillig
1425 1.278 rillig static void
1426 1.919 rillig ModifyWord_Head(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1427 1.1 cgd {
1428 1.919 rillig SepBuf_AddSubstring(buf, Substring_Dirname(word));
1429 1.1 cgd }
1430 1.1 cgd
1431 1.278 rillig static void
1432 1.919 rillig ModifyWord_Tail(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1433 1.1 cgd {
1434 1.919 rillig SepBuf_AddSubstring(buf, Substring_Basename(word));
1435 1.1 cgd }
1436 1.1 cgd
1437 1.278 rillig static void
1438 1.919 rillig ModifyWord_Suffix(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1439 1.1 cgd {
1440 1.1092 rillig const char *lastDot = Substring_FindLast(word, '.');
1441 1.703 rillig if (lastDot != NULL)
1442 1.1055 rillig SepBuf_AddRange(buf, lastDot + 1, word.end);
1443 1.1 cgd }
1444 1.1 cgd
1445 1.278 rillig static void
1446 1.919 rillig ModifyWord_Root(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1447 1.1 cgd {
1448 1.919 rillig const char *lastDot, *end;
1449 1.919 rillig
1450 1.1092 rillig lastDot = Substring_FindLast(word, '.');
1451 1.919 rillig end = lastDot != NULL ? lastDot : word.end;
1452 1.1055 rillig SepBuf_AddRange(buf, word.start, end);
1453 1.1 cgd }
1454 1.1 cgd
1455 1.926 rillig struct ModifyWord_SysVSubstArgs {
1456 1.806 rillig GNode *scope;
1457 1.925 rillig Substring lhsPrefix;
1458 1.925 rillig bool lhsPercent;
1459 1.925 rillig Substring lhsSuffix;
1460 1.703 rillig const char *rhs;
1461 1.541 rillig };
1462 1.276 rillig
1463 1.278 rillig static void
1464 1.926 rillig ModifyWord_SysVSubst(Substring word, SepBuf *buf, void *data)
1465 1.5 cgd {
1466 1.926 rillig const struct ModifyWord_SysVSubstArgs *args = data;
1467 1.925 rillig FStr rhs;
1468 1.703 rillig const char *percent;
1469 1.919 rillig
1470 1.925 rillig if (Substring_IsEmpty(word))
1471 1.703 rillig return;
1472 1.925 rillig
1473 1.1011 rillig if (!Substring_HasPrefix(word, args->lhsPrefix) ||
1474 1.1011 rillig !Substring_HasSuffix(word, args->lhsSuffix)) {
1475 1.1011 rillig SepBuf_AddSubstring(buf, word);
1476 1.1011 rillig return;
1477 1.1011 rillig }
1478 1.925 rillig
1479 1.925 rillig rhs = FStr_InitRefer(args->rhs);
1480 1.1119 rillig Var_Expand(&rhs, args->scope, VARE_EVAL);
1481 1.379 rillig
1482 1.925 rillig percent = args->lhsPercent ? strchr(rhs.str, '%') : NULL;
1483 1.379 rillig
1484 1.925 rillig if (percent != NULL)
1485 1.1055 rillig SepBuf_AddRange(buf, rhs.str, percent);
1486 1.925 rillig if (percent != NULL || !args->lhsPercent)
1487 1.1055 rillig SepBuf_AddRange(buf,
1488 1.925 rillig word.start + Substring_Length(args->lhsPrefix),
1489 1.925 rillig word.end - Substring_Length(args->lhsSuffix));
1490 1.925 rillig SepBuf_AddStr(buf, percent != NULL ? percent + 1 : rhs.str);
1491 1.379 rillig
1492 1.925 rillig FStr_Done(&rhs);
1493 1.5 cgd }
1494 1.5 cgd
1495 1.918 rillig static const char *
1496 1.918 rillig Substring_Find(Substring haystack, Substring needle)
1497 1.918 rillig {
1498 1.918 rillig size_t len, needleLen, i;
1499 1.918 rillig
1500 1.918 rillig len = Substring_Length(haystack);
1501 1.918 rillig needleLen = Substring_Length(needle);
1502 1.918 rillig for (i = 0; i + needleLen <= len; i++)
1503 1.918 rillig if (memcmp(haystack.start + i, needle.start, needleLen) == 0)
1504 1.918 rillig return haystack.start + i;
1505 1.918 rillig return NULL;
1506 1.918 rillig }
1507 1.918 rillig
1508 1.1079 rillig struct ModifyWord_SubstArgs {
1509 1.1079 rillig Substring lhs;
1510 1.1079 rillig Substring rhs;
1511 1.1079 rillig PatternFlags pflags;
1512 1.1079 rillig bool matched;
1513 1.1079 rillig };
1514 1.1079 rillig
1515 1.278 rillig static void
1516 1.919 rillig ModifyWord_Subst(Substring word, SepBuf *buf, void *data)
1517 1.1 cgd {
1518 1.703 rillig struct ModifyWord_SubstArgs *args = data;
1519 1.918 rillig size_t wordLen, lhsLen;
1520 1.1089 rillig const char *match;
1521 1.703 rillig
1522 1.919 rillig wordLen = Substring_Length(word);
1523 1.788 rillig if (args->pflags.subOnce && args->matched)
1524 1.703 rillig goto nosub;
1525 1.703 rillig
1526 1.918 rillig lhsLen = Substring_Length(args->lhs);
1527 1.788 rillig if (args->pflags.anchorStart) {
1528 1.918 rillig if (wordLen < lhsLen ||
1529 1.919 rillig memcmp(word.start, args->lhs.start, lhsLen) != 0)
1530 1.703 rillig goto nosub;
1531 1.703 rillig
1532 1.918 rillig if (args->pflags.anchorEnd && wordLen != lhsLen)
1533 1.703 rillig goto nosub;
1534 1.703 rillig
1535 1.703 rillig /* :S,^prefix,replacement, or :S,^whole$,replacement, */
1536 1.919 rillig SepBuf_AddSubstring(buf, args->rhs);
1537 1.1089 rillig SepBuf_AddRange(buf, word.start + lhsLen, word.end);
1538 1.895 rillig args->matched = true;
1539 1.703 rillig return;
1540 1.703 rillig }
1541 1.1 cgd
1542 1.788 rillig if (args->pflags.anchorEnd) {
1543 1.918 rillig if (wordLen < lhsLen)
1544 1.703 rillig goto nosub;
1545 1.1089 rillig if (memcmp(word.end - lhsLen, args->lhs.start, lhsLen) != 0)
1546 1.703 rillig goto nosub;
1547 1.703 rillig
1548 1.703 rillig /* :S,suffix$,replacement, */
1549 1.1089 rillig SepBuf_AddRange(buf, word.start, word.end - lhsLen);
1550 1.919 rillig SepBuf_AddSubstring(buf, args->rhs);
1551 1.895 rillig args->matched = true;
1552 1.703 rillig return;
1553 1.703 rillig }
1554 1.315 rillig
1555 1.921 rillig if (Substring_IsEmpty(args->lhs))
1556 1.703 rillig goto nosub;
1557 1.279 rillig
1558 1.703 rillig /* unanchored case, may match more than once */
1559 1.919 rillig while ((match = Substring_Find(word, args->lhs)) != NULL) {
1560 1.1055 rillig SepBuf_AddRange(buf, word.start, match);
1561 1.919 rillig SepBuf_AddSubstring(buf, args->rhs);
1562 1.895 rillig args->matched = true;
1563 1.921 rillig word.start = match + lhsLen;
1564 1.919 rillig if (Substring_IsEmpty(word) || !args->pflags.subGlobal)
1565 1.703 rillig break;
1566 1.703 rillig }
1567 1.242 rillig nosub:
1568 1.919 rillig SepBuf_AddSubstring(buf, word);
1569 1.1 cgd }
1570 1.1 cgd
1571 1.400 rillig /* Print the error caused by a regcomp or regexec call. */
1572 1.16 christos static void
1573 1.1059 rillig RegexError(int reerr, const regex_t *pat, const char *str)
1574 1.16 christos {
1575 1.703 rillig size_t errlen = regerror(reerr, pat, NULL, 0);
1576 1.703 rillig char *errbuf = bmake_malloc(errlen);
1577 1.703 rillig regerror(reerr, pat, errbuf, errlen);
1578 1.1125 rillig Parse_Error(PARSE_FATAL, "%s: %s", str, errbuf);
1579 1.703 rillig free(errbuf);
1580 1.16 christos }
1581 1.16 christos
1582 1.981 rillig /* In the modifier ':C', replace a backreference from \0 to \9. */
1583 1.981 rillig static void
1584 1.981 rillig RegexReplaceBackref(char ref, SepBuf *buf, const char *wp,
1585 1.981 rillig const regmatch_t *m, size_t nsub)
1586 1.981 rillig {
1587 1.1160 rillig unsigned n = (unsigned)ref - '0';
1588 1.981 rillig
1589 1.981 rillig if (n >= nsub)
1590 1.1125 rillig Parse_Error(PARSE_FATAL, "No subexpression \\%u", n);
1591 1.981 rillig else if (m[n].rm_so == -1) {
1592 1.981 rillig if (opts.strict)
1593 1.981 rillig Error("No match for subexpression \\%u", n);
1594 1.981 rillig } else {
1595 1.1055 rillig SepBuf_AddRange(buf,
1596 1.981 rillig wp + (size_t)m[n].rm_so,
1597 1.981 rillig wp + (size_t)m[n].rm_eo);
1598 1.981 rillig }
1599 1.981 rillig }
1600 1.981 rillig
1601 1.937 rillig /*
1602 1.983 rillig * The regular expression matches the word; now add the replacement to the
1603 1.983 rillig * buffer, taking back-references from 'wp'.
1604 1.937 rillig */
1605 1.937 rillig static void
1606 1.984 rillig RegexReplace(Substring replace, SepBuf *buf, const char *wp,
1607 1.937 rillig const regmatch_t *m, size_t nsub)
1608 1.937 rillig {
1609 1.937 rillig const char *rp;
1610 1.937 rillig
1611 1.984 rillig for (rp = replace.start; rp != replace.end; rp++) {
1612 1.984 rillig if (*rp == '\\' && rp + 1 != replace.end &&
1613 1.984 rillig (rp[1] == '&' || rp[1] == '\\'))
1614 1.983 rillig SepBuf_AddBytes(buf, ++rp, 1);
1615 1.984 rillig else if (*rp == '\\' && rp + 1 != replace.end &&
1616 1.984 rillig ch_isdigit(rp[1]))
1617 1.983 rillig RegexReplaceBackref(*++rp, buf, wp, m, nsub);
1618 1.983 rillig else if (*rp == '&') {
1619 1.1055 rillig SepBuf_AddRange(buf,
1620 1.948 rillig wp + (size_t)m[0].rm_so,
1621 1.948 rillig wp + (size_t)m[0].rm_eo);
1622 1.983 rillig } else
1623 1.937 rillig SepBuf_AddBytes(buf, rp, 1);
1624 1.937 rillig }
1625 1.937 rillig }
1626 1.937 rillig
1627 1.541 rillig struct ModifyWord_SubstRegexArgs {
1628 1.703 rillig regex_t re;
1629 1.703 rillig size_t nsub;
1630 1.984 rillig Substring replace;
1631 1.927 rillig PatternFlags pflags;
1632 1.895 rillig bool matched;
1633 1.541 rillig };
1634 1.291 rillig
1635 1.278 rillig static void
1636 1.919 rillig ModifyWord_SubstRegex(Substring word, SepBuf *buf, void *data)
1637 1.16 christos {
1638 1.704 rillig struct ModifyWord_SubstRegexArgs *args = data;
1639 1.704 rillig int xrv;
1640 1.919 rillig const char *wp;
1641 1.704 rillig int flags = 0;
1642 1.704 rillig regmatch_t m[10];
1643 1.16 christos
1644 1.919 rillig assert(word.end[0] == '\0'); /* assume null-terminated word */
1645 1.919 rillig wp = word.start;
1646 1.936 rillig if (args->pflags.subOnce && args->matched)
1647 1.936 rillig goto no_match;
1648 1.307 rillig
1649 1.935 rillig again:
1650 1.704 rillig xrv = regexec(&args->re, wp, args->nsub, m, flags);
1651 1.935 rillig if (xrv == 0)
1652 1.935 rillig goto ok;
1653 1.935 rillig if (xrv != REG_NOMATCH)
1654 1.1059 rillig RegexError(xrv, &args->re, "Unexpected regex error");
1655 1.936 rillig no_match:
1656 1.1055 rillig SepBuf_AddRange(buf, wp, word.end);
1657 1.936 rillig return;
1658 1.16 christos
1659 1.935 rillig ok:
1660 1.935 rillig args->matched = true;
1661 1.935 rillig SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1662 1.704 rillig
1663 1.937 rillig RegexReplace(args->replace, buf, wp, m, args->nsub);
1664 1.445 rillig
1665 1.948 rillig wp += (size_t)m[0].rm_eo;
1666 1.935 rillig if (args->pflags.subGlobal) {
1667 1.935 rillig flags |= REG_NOTBOL;
1668 1.1077 rillig if (m[0].rm_so == 0 && m[0].rm_eo == 0 && *wp != '\0') {
1669 1.935 rillig SepBuf_AddBytes(buf, wp, 1);
1670 1.935 rillig wp++;
1671 1.704 rillig }
1672 1.704 rillig if (*wp != '\0')
1673 1.935 rillig goto again;
1674 1.935 rillig }
1675 1.935 rillig if (*wp != '\0')
1676 1.704 rillig SepBuf_AddStr(buf, wp);
1677 1.16 christos }
1678 1.16 christos
1679 1.16 christos
1680 1.541 rillig struct ModifyWord_LoopArgs {
1681 1.806 rillig GNode *scope;
1682 1.928 rillig const char *var; /* name of the temporary variable */
1683 1.928 rillig const char *body; /* string to expand */
1684 1.906 rillig VarEvalMode emode;
1685 1.541 rillig };
1686 1.291 rillig
1687 1.278 rillig static void
1688 1.919 rillig ModifyWord_Loop(Substring word, SepBuf *buf, void *data)
1689 1.40 sjg {
1690 1.703 rillig const struct ModifyWord_LoopArgs *args;
1691 1.703 rillig char *s;
1692 1.412 rillig
1693 1.919 rillig if (Substring_IsEmpty(word))
1694 1.703 rillig return;
1695 1.278 rillig
1696 1.703 rillig args = data;
1697 1.919 rillig assert(word.end[0] == '\0'); /* assume null-terminated word */
1698 1.928 rillig Var_SetWithFlags(args->scope, args->var, word.start,
1699 1.919 rillig VAR_SET_NO_EXPORT);
1700 1.1043 rillig s = Var_Subst(args->body, args->scope, args->emode);
1701 1.703 rillig /* TODO: handle errors */
1702 1.64 sjg
1703 1.1090 rillig DEBUG2(VAR, "ModifyWord_Loop: expand \"%s\" to \"%s\"\n",
1704 1.1090 rillig args->body, s);
1705 1.703 rillig
1706 1.703 rillig if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1707 1.895 rillig buf->needSep = false;
1708 1.703 rillig SepBuf_AddStr(buf, s);
1709 1.703 rillig free(s);
1710 1.40 sjg }
1711 1.40 sjg
1712 1.81 sjg
1713 1.778 rillig /*
1714 1.778 rillig * The :[first..last] modifier selects words from the expression.
1715 1.778 rillig * It can also reverse the words.
1716 1.778 rillig */
1717 1.81 sjg static char *
1718 1.840 rillig VarSelectWords(const char *str, int first, int last,
1719 1.895 rillig char sep, bool oneBigWord)
1720 1.81 sjg {
1721 1.960 rillig SubstringWords words;
1722 1.703 rillig int len, start, end, step;
1723 1.703 rillig int i;
1724 1.703 rillig
1725 1.703 rillig SepBuf buf;
1726 1.703 rillig SepBuf_Init(&buf, sep);
1727 1.703 rillig
1728 1.703 rillig if (oneBigWord) {
1729 1.960 rillig /* fake what Substring_Words() would do */
1730 1.703 rillig words.len = 1;
1731 1.960 rillig words.words = bmake_malloc(sizeof(words.words[0]));
1732 1.960 rillig words.freeIt = NULL;
1733 1.960 rillig words.words[0] = Substring_InitStr(str); /* no need to copy */
1734 1.703 rillig } else {
1735 1.960 rillig words = Substring_Words(str, false);
1736 1.703 rillig }
1737 1.81 sjg
1738 1.1088 rillig /* Convert -1 to len, -2 to (len - 1), etc. */
1739 1.703 rillig len = (int)words.len;
1740 1.703 rillig if (first < 0)
1741 1.703 rillig first += len + 1;
1742 1.703 rillig if (last < 0)
1743 1.703 rillig last += len + 1;
1744 1.703 rillig
1745 1.703 rillig if (first > last) {
1746 1.703 rillig start = (first > len ? len : first) - 1;
1747 1.703 rillig end = last < 1 ? 0 : last - 1;
1748 1.703 rillig step = -1;
1749 1.703 rillig } else {
1750 1.703 rillig start = first < 1 ? 0 : first - 1;
1751 1.703 rillig end = last > len ? len : last;
1752 1.703 rillig step = 1;
1753 1.703 rillig }
1754 1.81 sjg
1755 1.703 rillig for (i = start; (step < 0) == (i >= end); i += step) {
1756 1.960 rillig SepBuf_AddSubstring(&buf, words.words[i]);
1757 1.703 rillig SepBuf_Sep(&buf);
1758 1.703 rillig }
1759 1.81 sjg
1760 1.960 rillig SubstringWords_Free(words);
1761 1.81 sjg
1762 1.784 rillig return SepBuf_DoneData(&buf);
1763 1.81 sjg }
1764 1.81 sjg
1765 1.156 sjg
1766 1.278 rillig static void
1767 1.919 rillig ModifyWord_Realpath(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1768 1.156 sjg {
1769 1.703 rillig struct stat st;
1770 1.703 rillig char rbuf[MAXPATHLEN];
1771 1.919 rillig const char *rp;
1772 1.231 rillig
1773 1.919 rillig assert(word.end[0] == '\0'); /* assume null-terminated word */
1774 1.919 rillig rp = cached_realpath(word.start, rbuf);
1775 1.703 rillig if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1776 1.919 rillig SepBuf_AddStr(buf, rp);
1777 1.919 rillig else
1778 1.919 rillig SepBuf_AddSubstring(buf, word);
1779 1.156 sjg }
1780 1.156 sjg
1781 1.35 christos
1782 1.403 rillig static char *
1783 1.962 rillig SubstringWords_JoinFree(SubstringWords words)
1784 1.403 rillig {
1785 1.703 rillig Buffer buf;
1786 1.703 rillig size_t i;
1787 1.412 rillig
1788 1.703 rillig Buf_Init(&buf);
1789 1.403 rillig
1790 1.703 rillig for (i = 0; i < words.len; i++) {
1791 1.703 rillig if (i != 0) {
1792 1.988 rillig /*
1793 1.988 rillig * XXX: Use ch->sep instead of ' ', for consistency.
1794 1.988 rillig */
1795 1.703 rillig Buf_AddByte(&buf, ' ');
1796 1.703 rillig }
1797 1.1055 rillig Buf_AddRange(&buf, words.words[i].start, words.words[i].end);
1798 1.703 rillig }
1799 1.403 rillig
1800 1.962 rillig SubstringWords_Free(words);
1801 1.403 rillig
1802 1.784 rillig return Buf_DoneData(&buf);
1803 1.403 rillig }
1804 1.403 rillig
1805 1.55 christos
1806 1.778 rillig /*
1807 1.778 rillig * Quote shell meta-characters and space characters in the string.
1808 1.778 rillig * If quoteDollar is set, also quote and double any '$' characters.
1809 1.778 rillig */
1810 1.924 rillig static void
1811 1.1059 rillig QuoteShell(const char *str, bool quoteDollar, LazyBuf *buf)
1812 1.16 christos {
1813 1.924 rillig const char *p;
1814 1.193 christos
1815 1.924 rillig LazyBuf_Init(buf, str);
1816 1.924 rillig for (p = str; *p != '\0'; p++) {
1817 1.924 rillig if (*p == '\n') {
1818 1.703 rillig const char *newline = Shell_GetNewline();
1819 1.703 rillig if (newline == NULL)
1820 1.703 rillig newline = "\\\n";
1821 1.924 rillig LazyBuf_AddStr(buf, newline);
1822 1.703 rillig continue;
1823 1.703 rillig }
1824 1.997 rillig if (ch_isspace(*p) || ch_is_shell_meta(*p))
1825 1.924 rillig LazyBuf_Add(buf, '\\');
1826 1.924 rillig LazyBuf_Add(buf, *p);
1827 1.924 rillig if (quoteDollar && *p == '$')
1828 1.924 rillig LazyBuf_AddStr(buf, "\\$");
1829 1.193 christos }
1830 1.16 christos }
1831 1.16 christos
1832 1.778 rillig /*
1833 1.778 rillig * Compute the 32-bit hash of the given string, using the MurmurHash3
1834 1.778 rillig * algorithm. Output is encoded as 8 hex digits, in Little Endian order.
1835 1.778 rillig */
1836 1.163 joerg static char *
1837 1.1059 rillig Hash(const char *str)
1838 1.163 joerg {
1839 1.703 rillig static const char hexdigits[16] = "0123456789abcdef";
1840 1.703 rillig const unsigned char *ustr = (const unsigned char *)str;
1841 1.703 rillig
1842 1.703 rillig uint32_t h = 0x971e137bU;
1843 1.703 rillig uint32_t c1 = 0x95543787U;
1844 1.703 rillig uint32_t c2 = 0x2ad7eb25U;
1845 1.703 rillig size_t len2 = strlen(str);
1846 1.163 joerg
1847 1.703 rillig char *buf;
1848 1.703 rillig size_t i;
1849 1.703 rillig
1850 1.703 rillig size_t len;
1851 1.781 rillig for (len = len2; len != 0;) {
1852 1.703 rillig uint32_t k = 0;
1853 1.703 rillig switch (len) {
1854 1.703 rillig default:
1855 1.703 rillig k = ((uint32_t)ustr[3] << 24) |
1856 1.703 rillig ((uint32_t)ustr[2] << 16) |
1857 1.703 rillig ((uint32_t)ustr[1] << 8) |
1858 1.703 rillig (uint32_t)ustr[0];
1859 1.703 rillig len -= 4;
1860 1.703 rillig ustr += 4;
1861 1.703 rillig break;
1862 1.703 rillig case 3:
1863 1.703 rillig k |= (uint32_t)ustr[2] << 16;
1864 1.703 rillig /* FALLTHROUGH */
1865 1.703 rillig case 2:
1866 1.703 rillig k |= (uint32_t)ustr[1] << 8;
1867 1.703 rillig /* FALLTHROUGH */
1868 1.703 rillig case 1:
1869 1.703 rillig k |= (uint32_t)ustr[0];
1870 1.703 rillig len = 0;
1871 1.703 rillig }
1872 1.703 rillig c1 = c1 * 5 + 0x7b7d159cU;
1873 1.703 rillig c2 = c2 * 5 + 0x6bce6396U;
1874 1.703 rillig k *= c1;
1875 1.703 rillig k = (k << 11) ^ (k >> 21);
1876 1.703 rillig k *= c2;
1877 1.703 rillig h = (h << 13) ^ (h >> 19);
1878 1.703 rillig h = h * 5 + 0x52dce729U;
1879 1.703 rillig h ^= k;
1880 1.703 rillig }
1881 1.703 rillig h ^= (uint32_t)len2;
1882 1.703 rillig h *= 0x85ebca6b;
1883 1.703 rillig h ^= h >> 13;
1884 1.703 rillig h *= 0xc2b2ae35;
1885 1.703 rillig h ^= h >> 16;
1886 1.703 rillig
1887 1.703 rillig buf = bmake_malloc(9);
1888 1.703 rillig for (i = 0; i < 8; i++) {
1889 1.703 rillig buf[i] = hexdigits[h & 0x0f];
1890 1.703 rillig h >>= 4;
1891 1.703 rillig }
1892 1.703 rillig buf[8] = '\0';
1893 1.703 rillig return buf;
1894 1.163 joerg }
1895 1.163 joerg
1896 1.164 sjg static char *
1897 1.1059 rillig FormatTime(const char *fmt, time_t t, bool gmt)
1898 1.164 sjg {
1899 1.703 rillig char buf[BUFSIZ];
1900 1.164 sjg
1901 1.993 rillig if (t == 0)
1902 1.993 rillig time(&t);
1903 1.703 rillig if (*fmt == '\0')
1904 1.703 rillig fmt = "%c";
1905 1.1064 rillig if (gmt && strchr(fmt, 's') != NULL) {
1906 1.1064 rillig /* strftime "%s" only works with localtime, not with gmtime. */
1907 1.1062 rillig const char *prev_tz_env = getenv("TZ");
1908 1.1062 rillig char *prev_tz = prev_tz_env != NULL
1909 1.1062 rillig ? bmake_strdup(prev_tz_env) : NULL;
1910 1.1062 rillig setenv("TZ", "UTC", 1);
1911 1.1062 rillig strftime(buf, sizeof buf, fmt, localtime(&t));
1912 1.1062 rillig if (prev_tz != NULL) {
1913 1.1062 rillig setenv("TZ", prev_tz, 1);
1914 1.1062 rillig free(prev_tz);
1915 1.1062 rillig } else
1916 1.1062 rillig unsetenv("TZ");
1917 1.1062 rillig } else
1918 1.1064 rillig strftime(buf, sizeof buf, fmt, (gmt ? gmtime : localtime)(&t));
1919 1.235 rillig
1920 1.703 rillig buf[sizeof buf - 1] = '\0';
1921 1.703 rillig return bmake_strdup(buf);
1922 1.164 sjg }
1923 1.164 sjg
1924 1.687 rillig /*
1925 1.687 rillig * The ApplyModifier functions take an expression that is being evaluated.
1926 1.830 rillig * Their task is to apply a single modifier to the expression. This involves
1927 1.830 rillig * parsing the modifier, evaluating it and finally updating the value of the
1928 1.830 rillig * expression.
1929 1.467 rillig *
1930 1.467 rillig * Parsing the modifier
1931 1.467 rillig *
1932 1.467 rillig * If parsing succeeds, the parsing position *pp is updated to point to the
1933 1.467 rillig * first character following the modifier, which typically is either ':' or
1934 1.891 rillig * ch->endc. The modifier doesn't have to check for this delimiter character,
1935 1.687 rillig * this is done by ApplyModifiers.
1936 1.687 rillig *
1937 1.687 rillig * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not
1938 1.687 rillig * need to be followed by a ':' or endc; this was an unintended mistake.
1939 1.467 rillig *
1940 1.1079 rillig * If parsing fails because of a missing delimiter after a modifier part (as
1941 1.1079 rillig * in the :S, :C or :@ modifiers), return AMR_CLEANUP.
1942 1.467 rillig *
1943 1.467 rillig * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
1944 1.1088 rillig * try the SysV modifier ':from=to' as fallback. This should only be
1945 1.467 rillig * done as long as there have been no side effects from evaluating nested
1946 1.467 rillig * variables, to avoid evaluating them more than once. In this case, the
1947 1.687 rillig * parsing position may or may not be updated. (XXX: Why not? The original
1948 1.687 rillig * parsing position is well-known in ApplyModifiers.)
1949 1.467 rillig *
1950 1.467 rillig * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
1951 1.1066 rillig * as a fallback, issue an error message using Parse_Error (preferred over
1952 1.1088 rillig * Error) and then return AMR_CLEANUP, which stops processing the expression.
1953 1.1088 rillig * (XXX: As of 2020-08-23, evaluation of the string continues nevertheless
1954 1.1088 rillig * after skipping a few bytes, which results in garbage.)
1955 1.467 rillig *
1956 1.467 rillig * Evaluating the modifier
1957 1.467 rillig *
1958 1.467 rillig * After parsing, the modifier is evaluated. The side effects from evaluating
1959 1.1075 rillig * nested expressions in the modifier text often already happen
1960 1.830 rillig * during parsing though. For most modifiers this doesn't matter since their
1961 1.949 rillig * only noticeable effect is that they update the value of the expression.
1962 1.830 rillig * Some modifiers such as ':sh' or '::=' have noticeable side effects though.
1963 1.467 rillig *
1964 1.1075 rillig * Evaluating the modifier usually takes the current value of the
1965 1.1094 rillig * expression from ch->expr->value, or the variable name from ch->var->name,
1966 1.1066 rillig * and stores the result back in ch->expr->value via Expr_SetValueOwn or
1967 1.821 rillig * Expr_SetValueRefer.
1968 1.467 rillig *
1969 1.528 rillig * Some modifiers such as :D and :U turn undefined expressions into defined
1970 1.1066 rillig * expressions using Expr_Define.
1971 1.350 rillig */
1972 1.409 rillig
1973 1.825 rillig typedef enum ExprDefined {
1974 1.1075 rillig /* The expression is based on a regular, defined variable. */
1975 1.825 rillig DEF_REGULAR,
1976 1.1075 rillig /* The expression is based on an undefined variable. */
1977 1.825 rillig DEF_UNDEF,
1978 1.703 rillig /*
1979 1.1075 rillig * The expression started as an undefined expression, but one
1980 1.825 rillig * of the modifiers (such as ':D' or ':U') has turned the expression
1981 1.825 rillig * from undefined to defined.
1982 1.703 rillig */
1983 1.825 rillig DEF_DEFINED
1984 1.825 rillig } ExprDefined;
1985 1.527 rillig
1986 1.951 rillig static const char ExprDefined_Name[][10] = {
1987 1.826 rillig "regular",
1988 1.826 rillig "undefined",
1989 1.826 rillig "defined"
1990 1.789 rillig };
1991 1.527 rillig
1992 1.897 rillig #if __STDC_VERSION__ >= 199901L
1993 1.989 rillig #define const_member const
1994 1.897 rillig #else
1995 1.989 rillig #define const_member /* no const possible */
1996 1.897 rillig #endif
1997 1.897 rillig
1998 1.966 rillig /* An expression based on a variable, such as $@ or ${VAR:Mpattern:Q}. */
1999 1.823 rillig typedef struct Expr {
2000 1.898 rillig const char *name;
2001 1.823 rillig FStr value;
2002 1.906 rillig VarEvalMode const_member emode;
2003 1.897 rillig GNode *const_member scope;
2004 1.825 rillig ExprDefined defined;
2005 1.823 rillig } Expr;
2006 1.823 rillig
2007 1.823 rillig /*
2008 1.890 rillig * The status of applying a chain of modifiers to an expression.
2009 1.823 rillig *
2010 1.890 rillig * The modifiers of an expression are broken into chains of modifiers,
2011 1.892 rillig * starting a new nested chain whenever an indirect modifier starts. There
2012 1.892 rillig * are at most 2 nesting levels: the outer one for the direct modifiers, and
2013 1.892 rillig * the inner one for the indirect modifiers.
2014 1.890 rillig *
2015 1.892 rillig * For example, the expression ${VAR:M*:${IND1}:${IND2}:O:u} has 3 chains of
2016 1.889 rillig * modifiers:
2017 1.889 rillig *
2018 1.892 rillig * Chain 1 starts with the single modifier ':M*'.
2019 1.892 rillig * Chain 2 starts with all modifiers from ${IND1}.
2020 1.892 rillig * Chain 2 ends at the ':' between ${IND1} and ${IND2}.
2021 1.893 rillig * Chain 3 starts with all modifiers from ${IND2}.
2022 1.893 rillig * Chain 3 ends at the ':' after ${IND2}.
2023 1.942 rillig * Chain 1 continues with the 2 modifiers ':O' and ':u'.
2024 1.892 rillig * Chain 1 ends at the final '}' of the expression.
2025 1.890 rillig *
2026 1.892 rillig * After such a chain ends, its properties no longer have any effect.
2027 1.889 rillig *
2028 1.823 rillig * See varmod-indirect.mk.
2029 1.823 rillig */
2030 1.891 rillig typedef struct ModChain {
2031 1.823 rillig Expr *expr;
2032 1.703 rillig /* '\0' or '{' or '(' */
2033 1.897 rillig char const_member startc;
2034 1.703 rillig /* '\0' or '}' or ')' */
2035 1.897 rillig char const_member endc;
2036 1.1094 rillig /* Separator when joining words (see the :ts modifier). */
2037 1.703 rillig char sep;
2038 1.703 rillig /*
2039 1.1066 rillig * Whether some modifiers that otherwise split the variable value
2040 1.703 rillig * into words, like :S and :C, treat the variable value as a single
2041 1.703 rillig * big word, possibly containing spaces.
2042 1.703 rillig */
2043 1.895 rillig bool oneBigWord;
2044 1.891 rillig } ModChain;
2045 1.236 rillig
2046 1.525 rillig static void
2047 1.812 rillig Expr_Define(Expr *expr)
2048 1.525 rillig {
2049 1.825 rillig if (expr->defined == DEF_UNDEF)
2050 1.825 rillig expr->defined = DEF_DEFINED;
2051 1.525 rillig }
2052 1.525 rillig
2053 1.965 rillig static const char *
2054 1.965 rillig Expr_Str(const Expr *expr)
2055 1.965 rillig {
2056 1.965 rillig return expr->value.str;
2057 1.965 rillig }
2058 1.965 rillig
2059 1.967 rillig static SubstringWords
2060 1.967 rillig Expr_Words(const Expr *expr)
2061 1.967 rillig {
2062 1.967 rillig return Substring_Words(Expr_Str(expr), false);
2063 1.967 rillig }
2064 1.967 rillig
2065 1.813 rillig static void
2066 1.921 rillig Expr_SetValue(Expr *expr, FStr value)
2067 1.921 rillig {
2068 1.921 rillig FStr_Done(&expr->value);
2069 1.921 rillig expr->value = value;
2070 1.921 rillig }
2071 1.921 rillig
2072 1.921 rillig static void
2073 1.813 rillig Expr_SetValueOwn(Expr *expr, char *value)
2074 1.813 rillig {
2075 1.921 rillig Expr_SetValue(expr, FStr_InitOwn(value));
2076 1.813 rillig }
2077 1.813 rillig
2078 1.813 rillig static void
2079 1.813 rillig Expr_SetValueRefer(Expr *expr, const char *value)
2080 1.813 rillig {
2081 1.921 rillig Expr_SetValue(expr, FStr_InitRefer(value));
2082 1.813 rillig }
2083 1.813 rillig
2084 1.905 rillig static bool
2085 1.905 rillig Expr_ShouldEval(const Expr *expr)
2086 1.905 rillig {
2087 1.906 rillig return VarEvalMode_ShouldEval(expr->emode);
2088 1.905 rillig }
2089 1.905 rillig
2090 1.905 rillig static bool
2091 1.905 rillig ModChain_ShouldEval(const ModChain *ch)
2092 1.905 rillig {
2093 1.905 rillig return Expr_ShouldEval(ch->expr);
2094 1.905 rillig }
2095 1.905 rillig
2096 1.905 rillig
2097 1.578 rillig typedef enum ApplyModifierResult {
2098 1.703 rillig /* Continue parsing */
2099 1.703 rillig AMR_OK,
2100 1.1093 rillig /* Not a match, try the ':from=to' modifier as well. */
2101 1.703 rillig AMR_UNKNOWN,
2102 1.1155 rillig /* Error out without further error message. */
2103 1.703 rillig AMR_CLEANUP
2104 1.356 rillig } ApplyModifierResult;
2105 1.356 rillig
2106 1.703 rillig /*
2107 1.703 rillig * Allow backslashes to escape the delimiter, $, and \, but don't touch other
2108 1.703 rillig * backslashes.
2109 1.703 rillig */
2110 1.895 rillig static bool
2111 1.620 rillig IsEscapedModifierPart(const char *p, char delim,
2112 1.620 rillig struct ModifyWord_SubstArgs *subst)
2113 1.620 rillig {
2114 1.1118 rillig if (p[0] != '\\' || p[1] == '\0')
2115 1.895 rillig return false;
2116 1.703 rillig if (p[1] == delim || p[1] == '\\' || p[1] == '$')
2117 1.895 rillig return true;
2118 1.703 rillig return p[1] == '&' && subst != NULL;
2119 1.620 rillig }
2120 1.620 rillig
2121 1.956 rillig /*
2122 1.957 rillig * In a part of a modifier, parse a subexpression and evaluate it.
2123 1.957 rillig */
2124 1.957 rillig static void
2125 1.957 rillig ParseModifierPartExpr(const char **pp, LazyBuf *part, const ModChain *ch,
2126 1.957 rillig VarEvalMode emode)
2127 1.957 rillig {
2128 1.957 rillig const char *p = *pp;
2129 1.1042 rillig FStr nested_val = Var_Parse(&p, ch->expr->scope,
2130 1.1042 rillig VarEvalMode_WithoutKeepDollar(emode));
2131 1.957 rillig /* TODO: handle errors */
2132 1.1047 rillig if (VarEvalMode_ShouldEval(emode))
2133 1.1047 rillig LazyBuf_AddStr(part, nested_val.str);
2134 1.1047 rillig else
2135 1.1047 rillig LazyBuf_AddSubstring(part, Substring_Init(*pp, p));
2136 1.957 rillig FStr_Done(&nested_val);
2137 1.957 rillig *pp = p;
2138 1.957 rillig }
2139 1.957 rillig
2140 1.1029 rillig /*
2141 1.1047 rillig * In a part of a modifier, parse some text that looks like a subexpression.
2142 1.1047 rillig * If the text starts with '$(', any '(' and ')' must be balanced.
2143 1.1047 rillig * If the text starts with '${', any '{' and '}' must be balanced.
2144 1.1066 rillig * If the text starts with '$', that '$' is copied verbatim, it is not parsed
2145 1.1075 rillig * as a short-name expression.
2146 1.1029 rillig */
2147 1.956 rillig static void
2148 1.1047 rillig ParseModifierPartBalanced(const char **pp, LazyBuf *part)
2149 1.956 rillig {
2150 1.956 rillig const char *p = *pp;
2151 1.956 rillig
2152 1.956 rillig if (p[1] == '(' || p[1] == '{') {
2153 1.1029 rillig char startc = p[1];
2154 1.1029 rillig int endc = startc == '(' ? ')' : '}';
2155 1.1029 rillig int depth = 1;
2156 1.1029 rillig
2157 1.1029 rillig for (p += 2; *p != '\0' && depth > 0; p++) {
2158 1.1029 rillig if (p[-1] != '\\') {
2159 1.1029 rillig if (*p == startc)
2160 1.1029 rillig depth++;
2161 1.1029 rillig if (*p == endc)
2162 1.1029 rillig depth--;
2163 1.1029 rillig }
2164 1.1029 rillig }
2165 1.1089 rillig LazyBuf_AddSubstring(part, Substring_Init(*pp, p));
2166 1.1029 rillig *pp = p;
2167 1.956 rillig } else {
2168 1.1089 rillig LazyBuf_Add(part, *p);
2169 1.1029 rillig *pp = p + 1;
2170 1.956 rillig }
2171 1.956 rillig }
2172 1.956 rillig
2173 1.1115 rillig /*
2174 1.1115 rillig * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
2175 1.1115 rillig * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
2176 1.1115 rillig * including the next unescaped delimiter. The delimiter, as well as the
2177 1.1115 rillig * backslash or the dollar, can be escaped with a backslash.
2178 1.1115 rillig *
2179 1.1115 rillig * Return true if parsing succeeded, together with the parsed (and possibly
2180 1.1115 rillig * expanded) part. In that case, pp points right after the delimiter. The
2181 1.1115 rillig * delimiter is not included in the part though.
2182 1.1115 rillig */
2183 1.1044 rillig static bool
2184 1.1115 rillig ParseModifierPart(
2185 1.1115 rillig /* The parsing position, updated upon return */
2186 1.703 rillig const char **pp,
2187 1.1115 rillig char end1,
2188 1.1115 rillig char end2,
2189 1.1115 rillig /* Mode for evaluating nested expressions. */
2190 1.906 rillig VarEvalMode emode,
2191 1.891 rillig ModChain *ch,
2192 1.921 rillig LazyBuf *part,
2193 1.988 rillig /*
2194 1.1066 rillig * For the first part of the ':S' modifier, set anchorEnd if the last
2195 1.988 rillig * character of the pattern is a $.
2196 1.988 rillig */
2197 1.927 rillig PatternFlags *out_pflags,
2198 1.988 rillig /*
2199 1.1066 rillig * For the second part of the ':S' modifier, allow ampersands to be
2200 1.1066 rillig * escaped and replace unescaped ampersands with subst->lhs.
2201 1.988 rillig */
2202 1.541 rillig struct ModifyWord_SubstArgs *subst
2203 1.704 rillig )
2204 1.704 rillig {
2205 1.1115 rillig const char *p = *pp;
2206 1.704 rillig
2207 1.923 rillig LazyBuf_Init(part, p);
2208 1.1050 rillig while (*p != '\0' && *p != end1 && *p != end2) {
2209 1.1115 rillig if (IsEscapedModifierPart(p, end2, subst)) {
2210 1.921 rillig LazyBuf_Add(part, p[1]);
2211 1.704 rillig p += 2;
2212 1.958 rillig } else if (*p != '$') { /* Unescaped, simple text */
2213 1.704 rillig if (subst != NULL && *p == '&')
2214 1.921 rillig LazyBuf_AddSubstring(part, subst->lhs);
2215 1.704 rillig else
2216 1.921 rillig LazyBuf_Add(part, *p);
2217 1.704 rillig p++;
2218 1.1115 rillig } else if (p[1] == end2) { /* Unescaped '$' at end */
2219 1.704 rillig if (out_pflags != NULL)
2220 1.895 rillig out_pflags->anchorEnd = true;
2221 1.704 rillig else
2222 1.921 rillig LazyBuf_Add(part, *p);
2223 1.704 rillig p++;
2224 1.1047 rillig } else if (emode == VARE_PARSE_BALANCED)
2225 1.1047 rillig ParseModifierPartBalanced(&p, part);
2226 1.1047 rillig else
2227 1.957 rillig ParseModifierPartExpr(&p, part, ch, emode);
2228 1.529 rillig }
2229 1.529 rillig
2230 1.1050 rillig if (*p != end1 && *p != end2) {
2231 1.1125 rillig Parse_Error(PARSE_FATAL,
2232 1.1148 rillig "Unfinished modifier after \"%.*s\", expecting \"%c\"",
2233 1.1148 rillig (int)(p - *pp), *pp, end2);
2234 1.921 rillig LazyBuf_Done(part);
2235 1.1148 rillig *pp = p;
2236 1.1044 rillig return false;
2237 1.704 rillig }
2238 1.1148 rillig *pp = p;
2239 1.1115 rillig if (end1 == end2)
2240 1.1050 rillig (*pp)++;
2241 1.529 rillig
2242 1.921 rillig {
2243 1.921 rillig Substring sub = LazyBuf_Get(part);
2244 1.921 rillig DEBUG2(VAR, "Modifier part: \"%.*s\"\n",
2245 1.921 rillig (int)Substring_Length(sub), sub.start);
2246 1.921 rillig }
2247 1.921 rillig
2248 1.1044 rillig return true;
2249 1.529 rillig }
2250 1.529 rillig
2251 1.895 rillig MAKE_INLINE bool
2252 1.891 rillig IsDelimiter(char c, const ModChain *ch)
2253 1.859 rillig {
2254 1.1032 rillig return c == ':' || c == ch->endc || c == '\0';
2255 1.859 rillig }
2256 1.859 rillig
2257 1.400 rillig /* Test whether mod starts with modname, followed by a delimiter. */
2258 1.895 rillig MAKE_INLINE bool
2259 1.891 rillig ModMatch(const char *mod, const char *modname, const ModChain *ch)
2260 1.340 rillig {
2261 1.703 rillig size_t n = strlen(modname);
2262 1.891 rillig return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], ch);
2263 1.340 rillig }
2264 1.340 rillig
2265 1.400 rillig /* Test whether mod starts with modname, followed by a delimiter or '='. */
2266 1.895 rillig MAKE_INLINE bool
2267 1.891 rillig ModMatchEq(const char *mod, const char *modname, const ModChain *ch)
2268 1.340 rillig {
2269 1.703 rillig size_t n = strlen(modname);
2270 1.703 rillig return strncmp(mod, modname, n) == 0 &&
2271 1.891 rillig (IsDelimiter(mod[n], ch) || mod[n] == '=');
2272 1.340 rillig }
2273 1.236 rillig
2274 1.895 rillig static bool
2275 1.635 rillig TryParseIntBase0(const char **pp, int *out_num)
2276 1.635 rillig {
2277 1.703 rillig char *end;
2278 1.703 rillig long n;
2279 1.635 rillig
2280 1.703 rillig errno = 0;
2281 1.703 rillig n = strtol(*pp, &end, 0);
2282 1.865 rillig
2283 1.865 rillig if (end == *pp)
2284 1.895 rillig return false;
2285 1.703 rillig if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
2286 1.895 rillig return false;
2287 1.703 rillig if (n < INT_MIN || n > INT_MAX)
2288 1.895 rillig return false;
2289 1.635 rillig
2290 1.703 rillig *pp = end;
2291 1.703 rillig *out_num = (int)n;
2292 1.895 rillig return true;
2293 1.635 rillig }
2294 1.635 rillig
2295 1.895 rillig static bool
2296 1.635 rillig TryParseSize(const char **pp, size_t *out_num)
2297 1.635 rillig {
2298 1.703 rillig char *end;
2299 1.703 rillig unsigned long n;
2300 1.635 rillig
2301 1.703 rillig if (!ch_isdigit(**pp))
2302 1.895 rillig return false;
2303 1.635 rillig
2304 1.703 rillig errno = 0;
2305 1.703 rillig n = strtoul(*pp, &end, 10);
2306 1.703 rillig if (n == ULONG_MAX && errno == ERANGE)
2307 1.895 rillig return false;
2308 1.703 rillig if (n > SIZE_MAX)
2309 1.895 rillig return false;
2310 1.635 rillig
2311 1.703 rillig *pp = end;
2312 1.703 rillig *out_num = (size_t)n;
2313 1.895 rillig return true;
2314 1.635 rillig }
2315 1.635 rillig
2316 1.895 rillig static bool
2317 1.635 rillig TryParseChar(const char **pp, int base, char *out_ch)
2318 1.635 rillig {
2319 1.703 rillig char *end;
2320 1.703 rillig unsigned long n;
2321 1.635 rillig
2322 1.703 rillig if (!ch_isalnum(**pp))
2323 1.895 rillig return false;
2324 1.635 rillig
2325 1.703 rillig errno = 0;
2326 1.703 rillig n = strtoul(*pp, &end, base);
2327 1.703 rillig if (n == ULONG_MAX && errno == ERANGE)
2328 1.895 rillig return false;
2329 1.703 rillig if (n > UCHAR_MAX)
2330 1.895 rillig return false;
2331 1.635 rillig
2332 1.703 rillig *pp = end;
2333 1.703 rillig *out_ch = (char)n;
2334 1.895 rillig return true;
2335 1.635 rillig }
2336 1.635 rillig
2337 1.820 rillig /*
2338 1.822 rillig * Modify each word of the expression using the given function and place the
2339 1.822 rillig * result back in the expression.
2340 1.820 rillig */
2341 1.820 rillig static void
2342 1.891 rillig ModifyWords(ModChain *ch,
2343 1.822 rillig ModifyWordProc modifyWord, void *modifyWord_args,
2344 1.895 rillig bool oneBigWord)
2345 1.820 rillig {
2346 1.891 rillig Expr *expr = ch->expr;
2347 1.965 rillig const char *val = Expr_Str(expr);
2348 1.820 rillig SepBuf result;
2349 1.920 rillig SubstringWords words;
2350 1.820 rillig size_t i;
2351 1.919 rillig Substring word;
2352 1.820 rillig
2353 1.1097 rillig if (!ModChain_ShouldEval(ch))
2354 1.1097 rillig return;
2355 1.1097 rillig
2356 1.820 rillig if (oneBigWord) {
2357 1.891 rillig SepBuf_Init(&result, ch->sep);
2358 1.919 rillig /* XXX: performance: Substring_InitStr calls strlen */
2359 1.919 rillig word = Substring_InitStr(val);
2360 1.919 rillig modifyWord(word, &result, modifyWord_args);
2361 1.820 rillig goto done;
2362 1.820 rillig }
2363 1.820 rillig
2364 1.920 rillig words = Substring_Words(val, false);
2365 1.820 rillig
2366 1.954 rillig DEBUG3(VAR, "ModifyWords: split \"%s\" into %u %s\n",
2367 1.954 rillig val, (unsigned)words.len, words.len != 1 ? "words" : "word");
2368 1.820 rillig
2369 1.891 rillig SepBuf_Init(&result, ch->sep);
2370 1.820 rillig for (i = 0; i < words.len; i++) {
2371 1.920 rillig modifyWord(words.words[i], &result, modifyWord_args);
2372 1.820 rillig if (result.buf.len > 0)
2373 1.820 rillig SepBuf_Sep(&result);
2374 1.820 rillig }
2375 1.820 rillig
2376 1.920 rillig SubstringWords_Free(words);
2377 1.820 rillig
2378 1.820 rillig done:
2379 1.823 rillig Expr_SetValueOwn(expr, SepBuf_DoneData(&result));
2380 1.820 rillig }
2381 1.820 rillig
2382 1.236 rillig /* :@var (at) ...${var}...@ */
2383 1.356 rillig static ApplyModifierResult
2384 1.891 rillig ApplyModifier_Loop(const char **pp, ModChain *ch)
2385 1.417 rillig {
2386 1.891 rillig Expr *expr = ch->expr;
2387 1.703 rillig struct ModifyWord_LoopArgs args;
2388 1.703 rillig char prev_sep;
2389 1.921 rillig LazyBuf tvarBuf, strBuf;
2390 1.921 rillig FStr tvar, str;
2391 1.703 rillig
2392 1.823 rillig args.scope = expr->scope;
2393 1.703 rillig
2394 1.703 rillig (*pp)++; /* Skip the first '@' */
2395 1.1119 rillig if (!ParseModifierPart(pp, '@', '@', VARE_PARSE,
2396 1.1115 rillig ch, &tvarBuf, NULL, NULL))
2397 1.703 rillig return AMR_CLEANUP;
2398 1.921 rillig tvar = LazyBuf_DoneGet(&tvarBuf);
2399 1.928 rillig args.var = tvar.str;
2400 1.928 rillig if (strchr(args.var, '$') != NULL) {
2401 1.703 rillig Parse_Error(PARSE_FATAL,
2402 1.1102 rillig "In the :@ modifier, the variable name \"%s\" "
2403 1.969 rillig "must not contain a dollar",
2404 1.1102 rillig args.var);
2405 1.1112 rillig goto cleanup_tvar;
2406 1.703 rillig }
2407 1.236 rillig
2408 1.1115 rillig if (!ParseModifierPart(pp, '@', '@', VARE_PARSE_BALANCED,
2409 1.1115 rillig ch, &strBuf, NULL, NULL))
2410 1.1112 rillig goto cleanup_tvar;
2411 1.921 rillig str = LazyBuf_DoneGet(&strBuf);
2412 1.928 rillig args.body = str.str;
2413 1.703 rillig
2414 1.906 rillig if (!Expr_ShouldEval(expr))
2415 1.870 rillig goto done;
2416 1.870 rillig
2417 1.906 rillig args.emode = VarEvalMode_WithoutKeepDollar(expr->emode);
2418 1.891 rillig prev_sep = ch->sep;
2419 1.891 rillig ch->sep = ' '; /* XXX: should be ch->sep for consistency */
2420 1.891 rillig ModifyWords(ch, ModifyWord_Loop, &args, ch->oneBigWord);
2421 1.891 rillig ch->sep = prev_sep;
2422 1.928 rillig /* XXX: Consider restoring the previous value instead of deleting. */
2423 1.928 rillig Var_Delete(expr->scope, args.var);
2424 1.870 rillig
2425 1.870 rillig done:
2426 1.921 rillig FStr_Done(&tvar);
2427 1.921 rillig FStr_Done(&str);
2428 1.703 rillig return AMR_OK;
2429 1.1112 rillig
2430 1.1112 rillig cleanup_tvar:
2431 1.1112 rillig FStr_Done(&tvar);
2432 1.1112 rillig return AMR_CLEANUP;
2433 1.236 rillig }
2434 1.236 rillig
2435 1.1026 rillig static void
2436 1.1027 rillig ParseModifier_Defined(const char **pp, ModChain *ch, bool shouldEval,
2437 1.1026 rillig LazyBuf *buf)
2438 1.236 rillig {
2439 1.703 rillig const char *p;
2440 1.412 rillig
2441 1.703 rillig p = *pp + 1;
2442 1.1026 rillig LazyBuf_Init(buf, p);
2443 1.1032 rillig while (!IsDelimiter(*p, ch)) {
2444 1.703 rillig
2445 1.988 rillig /*
2446 1.988 rillig * XXX: This code is similar to the one in Var_Parse. See if
2447 1.1065 rillig * the code can be merged. See also ParseModifier_Match and
2448 1.988 rillig * ParseModifierPart.
2449 1.988 rillig */
2450 1.703 rillig
2451 1.1066 rillig /* See Buf_AddEscaped in for.c for the counterpart. */
2452 1.703 rillig if (*p == '\\') {
2453 1.703 rillig char c = p[1];
2454 1.1030 rillig if ((IsDelimiter(c, ch) && c != '\0') ||
2455 1.1030 rillig c == '$' || c == '\\') {
2456 1.1027 rillig if (shouldEval)
2457 1.1027 rillig LazyBuf_Add(buf, c);
2458 1.703 rillig p += 2;
2459 1.703 rillig continue;
2460 1.703 rillig }
2461 1.703 rillig }
2462 1.236 rillig
2463 1.703 rillig if (*p == '$') {
2464 1.1042 rillig FStr val = Var_Parse(&p, ch->expr->scope,
2465 1.1119 rillig shouldEval ? ch->expr->emode : VARE_PARSE);
2466 1.703 rillig /* TODO: handle errors */
2467 1.1027 rillig if (shouldEval)
2468 1.1027 rillig LazyBuf_AddStr(buf, val.str);
2469 1.1027 rillig FStr_Done(&val);
2470 1.703 rillig continue;
2471 1.703 rillig }
2472 1.687 rillig
2473 1.1027 rillig if (shouldEval)
2474 1.1027 rillig LazyBuf_Add(buf, *p);
2475 1.703 rillig p++;
2476 1.466 rillig }
2477 1.703 rillig *pp = p;
2478 1.1026 rillig }
2479 1.1026 rillig
2480 1.1026 rillig /* :Ddefined or :Uundefined */
2481 1.1026 rillig static ApplyModifierResult
2482 1.1026 rillig ApplyModifier_Defined(const char **pp, ModChain *ch)
2483 1.1026 rillig {
2484 1.1026 rillig Expr *expr = ch->expr;
2485 1.1026 rillig LazyBuf buf;
2486 1.1027 rillig bool shouldEval =
2487 1.1027 rillig Expr_ShouldEval(expr) &&
2488 1.1027 rillig (**pp == 'D') == (expr->defined == DEF_REGULAR);
2489 1.1026 rillig
2490 1.1027 rillig ParseModifier_Defined(pp, ch, shouldEval, &buf);
2491 1.466 rillig
2492 1.823 rillig Expr_Define(expr);
2493 1.1027 rillig if (shouldEval)
2494 1.929 rillig Expr_SetValue(expr, Substring_Str(LazyBuf_Get(&buf)));
2495 1.1111 rillig LazyBuf_Done(&buf);
2496 1.821 rillig
2497 1.703 rillig return AMR_OK;
2498 1.236 rillig }
2499 1.236 rillig
2500 1.567 rillig /* :L */
2501 1.567 rillig static ApplyModifierResult
2502 1.891 rillig ApplyModifier_Literal(const char **pp, ModChain *ch)
2503 1.567 rillig {
2504 1.891 rillig Expr *expr = ch->expr;
2505 1.864 rillig
2506 1.864 rillig (*pp)++;
2507 1.864 rillig
2508 1.905 rillig if (Expr_ShouldEval(expr)) {
2509 1.872 rillig Expr_Define(expr);
2510 1.898 rillig Expr_SetValueOwn(expr, bmake_strdup(expr->name));
2511 1.872 rillig }
2512 1.864 rillig
2513 1.703 rillig return AMR_OK;
2514 1.567 rillig }
2515 1.567 rillig
2516 1.895 rillig static bool
2517 1.633 rillig TryParseTime(const char **pp, time_t *out_time)
2518 1.631 rillig {
2519 1.703 rillig char *end;
2520 1.703 rillig unsigned long n;
2521 1.631 rillig
2522 1.703 rillig if (!ch_isdigit(**pp))
2523 1.895 rillig return false;
2524 1.631 rillig
2525 1.703 rillig errno = 0;
2526 1.703 rillig n = strtoul(*pp, &end, 10);
2527 1.703 rillig if (n == ULONG_MAX && errno == ERANGE)
2528 1.895 rillig return false;
2529 1.631 rillig
2530 1.703 rillig *pp = end;
2531 1.703 rillig *out_time = (time_t)n; /* ignore possible truncation for now */
2532 1.895 rillig return true;
2533 1.631 rillig }
2534 1.631 rillig
2535 1.994 rillig /* :gmtime and :localtime */
2536 1.356 rillig static ApplyModifierResult
2537 1.995 rillig ApplyModifier_Time(const char **pp, ModChain *ch)
2538 1.236 rillig {
2539 1.950 rillig Expr *expr;
2540 1.993 rillig time_t t;
2541 1.994 rillig const char *args;
2542 1.995 rillig const char *mod = *pp;
2543 1.995 rillig bool gmt = mod[0] == 'g';
2544 1.412 rillig
2545 1.994 rillig if (!ModMatchEq(mod, gmt ? "gmtime" : "localtime", ch))
2546 1.703 rillig return AMR_UNKNOWN;
2547 1.994 rillig args = mod + (gmt ? 6 : 9);
2548 1.703 rillig
2549 1.994 rillig if (args[0] == '=') {
2550 1.994 rillig const char *p = args + 1;
2551 1.1050 rillig LazyBuf buf;
2552 1.1104 rillig FStr arg;
2553 1.1115 rillig if (!ParseModifierPart(&p, ':', ch->endc, ch->expr->emode,
2554 1.1050 rillig ch, &buf, NULL, NULL))
2555 1.703 rillig return AMR_CLEANUP;
2556 1.1104 rillig arg = LazyBuf_DoneGet(&buf);
2557 1.1050 rillig if (ModChain_ShouldEval(ch)) {
2558 1.1104 rillig const char *arg_p = arg.str;
2559 1.1104 rillig if (!TryParseTime(&arg_p, &t) || *arg_p != '\0') {
2560 1.1050 rillig Parse_Error(PARSE_FATAL,
2561 1.1104 rillig "Invalid time value \"%s\"", arg.str);
2562 1.1104 rillig FStr_Done(&arg);
2563 1.1050 rillig return AMR_CLEANUP;
2564 1.1050 rillig }
2565 1.1050 rillig } else
2566 1.1050 rillig t = 0;
2567 1.1104 rillig FStr_Done(&arg);
2568 1.843 rillig *pp = p;
2569 1.703 rillig } else {
2570 1.993 rillig t = 0;
2571 1.994 rillig *pp = args;
2572 1.631 rillig }
2573 1.864 rillig
2574 1.950 rillig expr = ch->expr;
2575 1.950 rillig if (Expr_ShouldEval(expr))
2576 1.1059 rillig Expr_SetValueOwn(expr, FormatTime(Expr_Str(expr), t, gmt));
2577 1.864 rillig
2578 1.703 rillig return AMR_OK;
2579 1.236 rillig }
2580 1.236 rillig
2581 1.236 rillig /* :hash */
2582 1.356 rillig static ApplyModifierResult
2583 1.891 rillig ApplyModifier_Hash(const char **pp, ModChain *ch)
2584 1.236 rillig {
2585 1.891 rillig if (!ModMatch(*pp, "hash", ch))
2586 1.703 rillig return AMR_UNKNOWN;
2587 1.864 rillig *pp += 4;
2588 1.340 rillig
2589 1.905 rillig if (ModChain_ShouldEval(ch))
2590 1.1059 rillig Expr_SetValueOwn(ch->expr, Hash(Expr_Str(ch->expr)));
2591 1.864 rillig
2592 1.703 rillig return AMR_OK;
2593 1.236 rillig }
2594 1.236 rillig
2595 1.236 rillig /* :P */
2596 1.356 rillig static ApplyModifierResult
2597 1.891 rillig ApplyModifier_Path(const char **pp, ModChain *ch)
2598 1.236 rillig {
2599 1.891 rillig Expr *expr = ch->expr;
2600 1.703 rillig GNode *gn;
2601 1.703 rillig char *path;
2602 1.412 rillig
2603 1.864 rillig (*pp)++;
2604 1.864 rillig
2605 1.950 rillig if (!Expr_ShouldEval(expr))
2606 1.873 rillig return AMR_OK;
2607 1.873 rillig
2608 1.823 rillig Expr_Define(expr);
2609 1.409 rillig
2610 1.898 rillig gn = Targ_FindNode(expr->name);
2611 1.1067 rillig if (gn == NULL || gn->type & OP_NOPATH)
2612 1.703 rillig path = NULL;
2613 1.1067 rillig else if (gn->path != NULL)
2614 1.703 rillig path = bmake_strdup(gn->path);
2615 1.1067 rillig else {
2616 1.703 rillig SearchPath *searchPath = Suff_FindPath(gn);
2617 1.898 rillig path = Dir_FindFile(expr->name, searchPath);
2618 1.703 rillig }
2619 1.703 rillig if (path == NULL)
2620 1.898 rillig path = bmake_strdup(expr->name);
2621 1.823 rillig Expr_SetValueOwn(expr, path);
2622 1.409 rillig
2623 1.703 rillig return AMR_OK;
2624 1.236 rillig }
2625 1.236 rillig
2626 1.236 rillig /* :!cmd! */
2627 1.356 rillig static ApplyModifierResult
2628 1.891 rillig ApplyModifier_ShellCommand(const char **pp, ModChain *ch)
2629 1.236 rillig {
2630 1.891 rillig Expr *expr = ch->expr;
2631 1.921 rillig LazyBuf cmdBuf;
2632 1.921 rillig FStr cmd;
2633 1.703 rillig
2634 1.703 rillig (*pp)++;
2635 1.1115 rillig if (!ParseModifierPart(pp, '!', '!', expr->emode,
2636 1.1115 rillig ch, &cmdBuf, NULL, NULL))
2637 1.703 rillig return AMR_CLEANUP;
2638 1.921 rillig cmd = LazyBuf_DoneGet(&cmdBuf);
2639 1.921 rillig
2640 1.1000 rillig if (Expr_ShouldEval(expr)) {
2641 1.1000 rillig char *output, *error;
2642 1.1000 rillig output = Cmd_Exec(cmd.str, &error);
2643 1.1000 rillig Expr_SetValueOwn(expr, output);
2644 1.1000 rillig if (error != NULL) {
2645 1.1122 rillig Parse_Error(PARSE_WARNING, "%s", error);
2646 1.1000 rillig free(error);
2647 1.1000 rillig }
2648 1.1000 rillig } else
2649 1.1000 rillig Expr_SetValueRefer(expr, "");
2650 1.703 rillig
2651 1.921 rillig FStr_Done(&cmd);
2652 1.864 rillig Expr_Define(expr);
2653 1.274 rillig
2654 1.703 rillig return AMR_OK;
2655 1.236 rillig }
2656 1.236 rillig
2657 1.778 rillig /*
2658 1.778 rillig * The :range modifier generates an integer sequence as long as the words.
2659 1.778 rillig * The :range=7 modifier generates an integer sequence from 1 to 7.
2660 1.778 rillig */
2661 1.356 rillig static ApplyModifierResult
2662 1.891 rillig ApplyModifier_Range(const char **pp, ModChain *ch)
2663 1.236 rillig {
2664 1.703 rillig size_t n;
2665 1.703 rillig Buffer buf;
2666 1.703 rillig size_t i;
2667 1.412 rillig
2668 1.703 rillig const char *mod = *pp;
2669 1.891 rillig if (!ModMatchEq(mod, "range", ch))
2670 1.703 rillig return AMR_UNKNOWN;
2671 1.703 rillig
2672 1.703 rillig if (mod[5] == '=') {
2673 1.703 rillig const char *p = mod + 6;
2674 1.703 rillig if (!TryParseSize(&p, &n)) {
2675 1.703 rillig Parse_Error(PARSE_FATAL,
2676 1.844 rillig "Invalid number \"%s\" for ':range' modifier",
2677 1.844 rillig mod + 6);
2678 1.703 rillig return AMR_CLEANUP;
2679 1.703 rillig }
2680 1.703 rillig *pp = p;
2681 1.703 rillig } else {
2682 1.703 rillig n = 0;
2683 1.703 rillig *pp = mod + 5;
2684 1.635 rillig }
2685 1.386 rillig
2686 1.905 rillig if (!ModChain_ShouldEval(ch))
2687 1.873 rillig return AMR_OK;
2688 1.873 rillig
2689 1.703 rillig if (n == 0) {
2690 1.967 rillig SubstringWords words = Expr_Words(ch->expr);
2691 1.703 rillig n = words.len;
2692 1.961 rillig SubstringWords_Free(words);
2693 1.703 rillig }
2694 1.386 rillig
2695 1.703 rillig Buf_Init(&buf);
2696 1.386 rillig
2697 1.703 rillig for (i = 0; i < n; i++) {
2698 1.703 rillig if (i != 0) {
2699 1.988 rillig /*
2700 1.988 rillig * XXX: Use ch->sep instead of ' ', for consistency.
2701 1.988 rillig */
2702 1.703 rillig Buf_AddByte(&buf, ' ');
2703 1.703 rillig }
2704 1.703 rillig Buf_AddInt(&buf, 1 + (int)i);
2705 1.703 rillig }
2706 1.386 rillig
2707 1.891 rillig Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf));
2708 1.703 rillig return AMR_OK;
2709 1.236 rillig }
2710 1.236 rillig
2711 1.845 rillig /* Parse a ':M' or ':N' modifier. */
2712 1.1013 rillig static char *
2713 1.1013 rillig ParseModifier_Match(const char **pp, const ModChain *ch)
2714 1.236 rillig {
2715 1.845 rillig const char *mod = *pp;
2716 1.891 rillig Expr *expr = ch->expr;
2717 1.895 rillig bool copy = false; /* pattern should be, or has been, copied */
2718 1.895 rillig bool needSubst = false;
2719 1.703 rillig const char *endpat;
2720 1.703 rillig char *pattern;
2721 1.412 rillig
2722 1.703 rillig /*
2723 1.703 rillig * In the loop below, ignore ':' unless we are at (or back to) the
2724 1.703 rillig * original brace level.
2725 1.703 rillig * XXX: This will likely not work right if $() and ${} are intermixed.
2726 1.703 rillig */
2727 1.845 rillig /*
2728 1.845 rillig * XXX: This code is similar to the one in Var_Parse.
2729 1.703 rillig * See if the code can be merged.
2730 1.845 rillig * See also ApplyModifier_Defined.
2731 1.845 rillig */
2732 1.1083 rillig int depth = 0;
2733 1.703 rillig const char *p;
2734 1.1083 rillig for (p = mod + 1; *p != '\0' && !(*p == ':' && depth == 0); p++) {
2735 1.1031 rillig if (*p == '\\' && p[1] != '\0' &&
2736 1.891 rillig (IsDelimiter(p[1], ch) || p[1] == ch->startc)) {
2737 1.703 rillig if (!needSubst)
2738 1.895 rillig copy = true;
2739 1.703 rillig p++;
2740 1.703 rillig continue;
2741 1.703 rillig }
2742 1.703 rillig if (*p == '$')
2743 1.895 rillig needSubst = true;
2744 1.703 rillig if (*p == '(' || *p == '{')
2745 1.1083 rillig depth++;
2746 1.703 rillig if (*p == ')' || *p == '}') {
2747 1.1083 rillig depth--;
2748 1.1083 rillig if (depth < 0)
2749 1.703 rillig break;
2750 1.703 rillig }
2751 1.236 rillig }
2752 1.703 rillig *pp = p;
2753 1.703 rillig endpat = p;
2754 1.703 rillig
2755 1.703 rillig if (copy) {
2756 1.703 rillig char *dst;
2757 1.703 rillig const char *src;
2758 1.703 rillig
2759 1.703 rillig /* Compress the \:'s out of the pattern. */
2760 1.703 rillig pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
2761 1.703 rillig dst = pattern;
2762 1.703 rillig src = mod + 1;
2763 1.703 rillig for (; src < endpat; src++, dst++) {
2764 1.703 rillig if (src[0] == '\\' && src + 1 < endpat &&
2765 1.891 rillig /* XXX: ch->startc is missing here; see above */
2766 1.891 rillig IsDelimiter(src[1], ch))
2767 1.703 rillig src++;
2768 1.703 rillig *dst = *src;
2769 1.703 rillig }
2770 1.703 rillig *dst = '\0';
2771 1.703 rillig } else {
2772 1.703 rillig pattern = bmake_strsedup(mod + 1, endpat);
2773 1.236 rillig }
2774 1.288 rillig
2775 1.703 rillig if (needSubst) {
2776 1.703 rillig char *old_pattern = pattern;
2777 1.1013 rillig /*
2778 1.1013 rillig * XXX: Contrary to ParseModifierPart, a dollar in a ':M' or
2779 1.1013 rillig * ':N' modifier must be escaped as '$$', not as '\$'.
2780 1.1013 rillig */
2781 1.1043 rillig pattern = Var_Subst(pattern, expr->scope, expr->emode);
2782 1.703 rillig /* TODO: handle errors */
2783 1.703 rillig free(old_pattern);
2784 1.236 rillig }
2785 1.346 rillig
2786 1.908 rillig DEBUG2(VAR, "Pattern for ':%c' is \"%s\"\n", mod[0], pattern);
2787 1.346 rillig
2788 1.1013 rillig return pattern;
2789 1.845 rillig }
2790 1.845 rillig
2791 1.1057 rillig struct ModifyWord_MatchArgs {
2792 1.1057 rillig const char *pattern;
2793 1.1057 rillig bool neg;
2794 1.1058 rillig bool error_reported;
2795 1.1057 rillig };
2796 1.1057 rillig
2797 1.1057 rillig static void
2798 1.1057 rillig ModifyWord_Match(Substring word, SepBuf *buf, void *data)
2799 1.1057 rillig {
2800 1.1057 rillig struct ModifyWord_MatchArgs *args = data;
2801 1.1058 rillig StrMatchResult res;
2802 1.1057 rillig assert(word.end[0] == '\0'); /* assume null-terminated word */
2803 1.1058 rillig res = Str_Match(word.start, args->pattern);
2804 1.1058 rillig if (res.error != NULL && !args->error_reported) {
2805 1.1058 rillig args->error_reported = true;
2806 1.1135 rillig Parse_Error(PARSE_FATAL,
2807 1.1058 rillig "%s in pattern '%s' of modifier '%s'",
2808 1.1058 rillig res.error, args->pattern, args->neg ? ":N" : ":M");
2809 1.1058 rillig }
2810 1.1058 rillig if (res.matched != args->neg)
2811 1.1057 rillig SepBuf_AddSubstring(buf, word);
2812 1.1057 rillig }
2813 1.1057 rillig
2814 1.845 rillig /* :Mpattern or :Npattern */
2815 1.845 rillig static ApplyModifierResult
2816 1.891 rillig ApplyModifier_Match(const char **pp, ModChain *ch)
2817 1.845 rillig {
2818 1.996 rillig char mod = **pp;
2819 1.845 rillig char *pattern;
2820 1.845 rillig
2821 1.1013 rillig pattern = ParseModifier_Match(pp, ch);
2822 1.845 rillig
2823 1.905 rillig if (ModChain_ShouldEval(ch)) {
2824 1.1057 rillig struct ModifyWord_MatchArgs args;
2825 1.1057 rillig args.pattern = pattern;
2826 1.1057 rillig args.neg = mod == 'N';
2827 1.1058 rillig args.error_reported = false;
2828 1.1057 rillig ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord);
2829 1.876 rillig }
2830 1.876 rillig
2831 1.703 rillig free(pattern);
2832 1.703 rillig return AMR_OK;
2833 1.236 rillig }
2834 1.236 rillig
2835 1.1054 sjg struct ModifyWord_MtimeArgs {
2836 1.1054 sjg bool error;
2837 1.1060 rillig bool use_fallback;
2838 1.1054 sjg ApplyModifierResult rc;
2839 1.1060 rillig time_t fallback;
2840 1.1054 sjg };
2841 1.1054 sjg
2842 1.1054 sjg static void
2843 1.1054 sjg ModifyWord_Mtime(Substring word, SepBuf *buf, void *data)
2844 1.1054 sjg {
2845 1.1060 rillig struct ModifyWord_MtimeArgs *args = data;
2846 1.1054 sjg struct stat st;
2847 1.1060 rillig char tbuf[21];
2848 1.1054 sjg
2849 1.1054 sjg if (Substring_IsEmpty(word))
2850 1.1054 sjg return;
2851 1.1054 sjg assert(word.end[0] == '\0'); /* assume null-terminated word */
2852 1.1054 sjg if (stat(word.start, &st) < 0) {
2853 1.1054 sjg if (args->error) {
2854 1.1054 sjg Parse_Error(PARSE_FATAL,
2855 1.1054 sjg "Cannot determine mtime for '%s': %s",
2856 1.1054 sjg word.start, strerror(errno));
2857 1.1054 sjg args->rc = AMR_CLEANUP;
2858 1.1054 sjg return;
2859 1.1054 sjg }
2860 1.1060 rillig if (args->use_fallback)
2861 1.1060 rillig st.st_mtime = args->fallback;
2862 1.1054 sjg else
2863 1.1054 sjg time(&st.st_mtime);
2864 1.1054 sjg }
2865 1.1054 sjg snprintf(tbuf, sizeof(tbuf), "%u", (unsigned)st.st_mtime);
2866 1.1054 sjg SepBuf_AddStr(buf, tbuf);
2867 1.1054 sjg }
2868 1.1054 sjg
2869 1.1051 sjg /* :mtime */
2870 1.1051 sjg static ApplyModifierResult
2871 1.1051 sjg ApplyModifier_Mtime(const char **pp, ModChain *ch)
2872 1.1051 sjg {
2873 1.1054 sjg const char *p, *mod = *pp;
2874 1.1054 sjg struct ModifyWord_MtimeArgs args;
2875 1.1051 sjg
2876 1.1051 sjg if (!ModMatchEq(mod, "mtime", ch))
2877 1.1051 sjg return AMR_UNKNOWN;
2878 1.1051 sjg *pp += 5;
2879 1.1054 sjg p = *pp;
2880 1.1060 rillig args.error = false;
2881 1.1060 rillig args.use_fallback = p[0] == '=';
2882 1.1054 sjg args.rc = AMR_OK;
2883 1.1060 rillig if (args.use_fallback) {
2884 1.1054 sjg p++;
2885 1.1060 rillig if (TryParseTime(&p, &args.fallback)) {
2886 1.1072 rillig } else if (strncmp(p, "error", 5) == 0) {
2887 1.1060 rillig p += 5;
2888 1.1060 rillig args.error = true;
2889 1.1072 rillig } else
2890 1.1072 rillig goto invalid_argument;
2891 1.1072 rillig if (!IsDelimiter(*p, ch))
2892 1.1072 rillig goto invalid_argument;
2893 1.1054 sjg *pp = p;
2894 1.1051 sjg }
2895 1.1097 rillig ModifyWords(ch, ModifyWord_Mtime, &args, ch->oneBigWord);
2896 1.1054 sjg return args.rc;
2897 1.1072 rillig
2898 1.1072 rillig invalid_argument:
2899 1.1072 rillig Parse_Error(PARSE_FATAL,
2900 1.1072 rillig "Invalid argument '%.*s' for modifier ':mtime'",
2901 1.1072 rillig (int)strcspn(*pp + 1, ":{}()"), *pp + 1);
2902 1.1072 rillig return AMR_CLEANUP;
2903 1.1051 sjg }
2904 1.1051 sjg
2905 1.860 rillig static void
2906 1.927 rillig ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord)
2907 1.860 rillig {
2908 1.860 rillig for (;; (*pp)++) {
2909 1.860 rillig if (**pp == 'g')
2910 1.895 rillig pflags->subGlobal = true;
2911 1.860 rillig else if (**pp == '1')
2912 1.895 rillig pflags->subOnce = true;
2913 1.860 rillig else if (**pp == 'W')
2914 1.895 rillig *oneBigWord = true;
2915 1.860 rillig else
2916 1.860 rillig break;
2917 1.860 rillig }
2918 1.860 rillig }
2919 1.860 rillig
2920 1.927 rillig MAKE_INLINE PatternFlags
2921 1.927 rillig PatternFlags_None(void)
2922 1.897 rillig {
2923 1.927 rillig PatternFlags pflags = { false, false, false, false };
2924 1.897 rillig return pflags;
2925 1.897 rillig }
2926 1.897 rillig
2927 1.236 rillig /* :S,from,to, */
2928 1.356 rillig static ApplyModifierResult
2929 1.891 rillig ApplyModifier_Subst(const char **pp, ModChain *ch)
2930 1.236 rillig {
2931 1.703 rillig struct ModifyWord_SubstArgs args;
2932 1.895 rillig bool oneBigWord;
2933 1.921 rillig LazyBuf lhsBuf, rhsBuf;
2934 1.299 rillig
2935 1.703 rillig char delim = (*pp)[1];
2936 1.703 rillig if (delim == '\0') {
2937 1.1125 rillig Parse_Error(PARSE_FATAL,
2938 1.1125 rillig "Missing delimiter for modifier ':S'");
2939 1.703 rillig (*pp)++;
2940 1.703 rillig return AMR_CLEANUP;
2941 1.703 rillig }
2942 1.236 rillig
2943 1.703 rillig *pp += 2;
2944 1.236 rillig
2945 1.927 rillig args.pflags = PatternFlags_None();
2946 1.895 rillig args.matched = false;
2947 1.236 rillig
2948 1.703 rillig if (**pp == '^') {
2949 1.895 rillig args.pflags.anchorStart = true;
2950 1.703 rillig (*pp)++;
2951 1.703 rillig }
2952 1.703 rillig
2953 1.1115 rillig if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
2954 1.1115 rillig ch, &lhsBuf, &args.pflags, NULL))
2955 1.703 rillig return AMR_CLEANUP;
2956 1.921 rillig args.lhs = LazyBuf_Get(&lhsBuf);
2957 1.703 rillig
2958 1.1115 rillig if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
2959 1.1115 rillig ch, &rhsBuf, NULL, &args)) {
2960 1.921 rillig LazyBuf_Done(&lhsBuf);
2961 1.703 rillig return AMR_CLEANUP;
2962 1.921 rillig }
2963 1.921 rillig args.rhs = LazyBuf_Get(&rhsBuf);
2964 1.703 rillig
2965 1.891 rillig oneBigWord = ch->oneBigWord;
2966 1.860 rillig ParsePatternFlags(pp, &args.pflags, &oneBigWord);
2967 1.236 rillig
2968 1.891 rillig ModifyWords(ch, ModifyWord_Subst, &args, oneBigWord);
2969 1.236 rillig
2970 1.921 rillig LazyBuf_Done(&lhsBuf);
2971 1.921 rillig LazyBuf_Done(&rhsBuf);
2972 1.703 rillig return AMR_OK;
2973 1.236 rillig }
2974 1.236 rillig
2975 1.236 rillig /* :C,from,to, */
2976 1.356 rillig static ApplyModifierResult
2977 1.891 rillig ApplyModifier_Regex(const char **pp, ModChain *ch)
2978 1.236 rillig {
2979 1.703 rillig struct ModifyWord_SubstRegexArgs args;
2980 1.895 rillig bool oneBigWord;
2981 1.703 rillig int error;
2982 1.921 rillig LazyBuf reBuf, replaceBuf;
2983 1.984 rillig FStr re;
2984 1.703 rillig
2985 1.703 rillig char delim = (*pp)[1];
2986 1.703 rillig if (delim == '\0') {
2987 1.1125 rillig Parse_Error(PARSE_FATAL,
2988 1.1125 rillig "Missing delimiter for modifier ':C'");
2989 1.703 rillig (*pp)++;
2990 1.703 rillig return AMR_CLEANUP;
2991 1.703 rillig }
2992 1.703 rillig
2993 1.703 rillig *pp += 2;
2994 1.236 rillig
2995 1.1115 rillig if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
2996 1.1115 rillig ch, &reBuf, NULL, NULL))
2997 1.703 rillig return AMR_CLEANUP;
2998 1.921 rillig re = LazyBuf_DoneGet(&reBuf);
2999 1.703 rillig
3000 1.1115 rillig if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
3001 1.1115 rillig ch, &replaceBuf, NULL, NULL)) {
3002 1.921 rillig FStr_Done(&re);
3003 1.703 rillig return AMR_CLEANUP;
3004 1.703 rillig }
3005 1.984 rillig args.replace = LazyBuf_Get(&replaceBuf);
3006 1.703 rillig
3007 1.927 rillig args.pflags = PatternFlags_None();
3008 1.895 rillig args.matched = false;
3009 1.891 rillig oneBigWord = ch->oneBigWord;
3010 1.860 rillig ParsePatternFlags(pp, &args.pflags, &oneBigWord);
3011 1.236 rillig
3012 1.1034 rillig if (!ModChain_ShouldEval(ch))
3013 1.1034 rillig goto done;
3014 1.856 rillig
3015 1.921 rillig error = regcomp(&args.re, re.str, REG_EXTENDED);
3016 1.703 rillig if (error != 0) {
3017 1.1059 rillig RegexError(error, &args.re, "Regex compilation error");
3018 1.984 rillig LazyBuf_Done(&replaceBuf);
3019 1.921 rillig FStr_Done(&re);
3020 1.703 rillig return AMR_CLEANUP;
3021 1.236 rillig }
3022 1.236 rillig
3023 1.703 rillig args.nsub = args.re.re_nsub + 1;
3024 1.703 rillig if (args.nsub > 10)
3025 1.703 rillig args.nsub = 10;
3026 1.820 rillig
3027 1.891 rillig ModifyWords(ch, ModifyWord_SubstRegex, &args, oneBigWord);
3028 1.820 rillig
3029 1.703 rillig regfree(&args.re);
3030 1.1034 rillig done:
3031 1.984 rillig LazyBuf_Done(&replaceBuf);
3032 1.921 rillig FStr_Done(&re);
3033 1.703 rillig return AMR_OK;
3034 1.703 rillig }
3035 1.236 rillig
3036 1.555 rillig /* :Q, :q */
3037 1.555 rillig static ApplyModifierResult
3038 1.891 rillig ApplyModifier_Quote(const char **pp, ModChain *ch)
3039 1.555 rillig {
3040 1.924 rillig LazyBuf buf;
3041 1.924 rillig bool quoteDollar;
3042 1.924 rillig
3043 1.924 rillig quoteDollar = **pp == 'q';
3044 1.891 rillig if (!IsDelimiter((*pp)[1], ch))
3045 1.703 rillig return AMR_UNKNOWN;
3046 1.861 rillig (*pp)++;
3047 1.861 rillig
3048 1.924 rillig if (!ModChain_ShouldEval(ch))
3049 1.924 rillig return AMR_OK;
3050 1.924 rillig
3051 1.1059 rillig QuoteShell(Expr_Str(ch->expr), quoteDollar, &buf);
3052 1.924 rillig if (buf.data != NULL)
3053 1.924 rillig Expr_SetValue(ch->expr, LazyBuf_DoneGet(&buf));
3054 1.924 rillig else
3055 1.924 rillig LazyBuf_Done(&buf);
3056 1.861 rillig
3057 1.861 rillig return AMR_OK;
3058 1.555 rillig }
3059 1.555 rillig
3060 1.278 rillig static void
3061 1.919 rillig ModifyWord_Copy(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
3062 1.278 rillig {
3063 1.919 rillig SepBuf_AddSubstring(buf, word);
3064 1.275 rillig }
3065 1.275 rillig
3066 1.289 rillig /* :ts<separator> */
3067 1.356 rillig static ApplyModifierResult
3068 1.891 rillig ApplyModifier_ToSep(const char **pp, ModChain *ch)
3069 1.289 rillig {
3070 1.703 rillig const char *sep = *pp + 2;
3071 1.703 rillig
3072 1.873 rillig /*
3073 1.1079 rillig * Even in parse-only mode, apply the side effects, since the side
3074 1.1079 rillig * effects are neither observable nor is there a performance penalty.
3075 1.1119 rillig * Checking for VARE_EVAL for every single piece of code in here
3076 1.873 rillig * would make the code in this function too hard to read.
3077 1.873 rillig */
3078 1.873 rillig
3079 1.703 rillig /* ":ts<any><endc>" or ":ts<any>:" */
3080 1.891 rillig if (sep[0] != ch->endc && IsDelimiter(sep[1], ch)) {
3081 1.864 rillig *pp = sep + 1;
3082 1.891 rillig ch->sep = sep[0];
3083 1.703 rillig goto ok;
3084 1.703 rillig }
3085 1.468 rillig
3086 1.703 rillig /* ":ts<endc>" or ":ts:" */
3087 1.891 rillig if (IsDelimiter(sep[0], ch)) {
3088 1.864 rillig *pp = sep;
3089 1.891 rillig ch->sep = '\0'; /* no separator */
3090 1.703 rillig goto ok;
3091 1.703 rillig }
3092 1.468 rillig
3093 1.1154 rillig if (sep[0] != '\\')
3094 1.1154 rillig return AMR_UNKNOWN;
3095 1.468 rillig
3096 1.703 rillig /* ":ts\n" */
3097 1.703 rillig if (sep[1] == 'n') {
3098 1.864 rillig *pp = sep + 2;
3099 1.891 rillig ch->sep = '\n';
3100 1.703 rillig goto ok;
3101 1.703 rillig }
3102 1.468 rillig
3103 1.703 rillig /* ":ts\t" */
3104 1.703 rillig if (sep[1] == 't') {
3105 1.864 rillig *pp = sep + 2;
3106 1.891 rillig ch->sep = '\t';
3107 1.703 rillig goto ok;
3108 1.703 rillig }
3109 1.468 rillig
3110 1.703 rillig /* ":ts\x40" or ":ts\100" */
3111 1.703 rillig {
3112 1.703 rillig const char *p = sep + 1;
3113 1.703 rillig int base = 8; /* assume octal */
3114 1.468 rillig
3115 1.703 rillig if (sep[1] == 'x') {
3116 1.703 rillig base = 16;
3117 1.703 rillig p++;
3118 1.1154 rillig } else if (!ch_isdigit(sep[1]))
3119 1.1154 rillig return AMR_UNKNOWN; /* ":ts\..." */
3120 1.289 rillig
3121 1.891 rillig if (!TryParseChar(&p, base, &ch->sep)) {
3122 1.703 rillig Parse_Error(PARSE_FATAL,
3123 1.970 rillig "Invalid character number at \"%s\"", p);
3124 1.703 rillig return AMR_CLEANUP;
3125 1.703 rillig }
3126 1.1154 rillig if (!IsDelimiter(*p, ch))
3127 1.1154 rillig return AMR_UNKNOWN;
3128 1.468 rillig
3129 1.703 rillig *pp = p;
3130 1.556 rillig }
3131 1.635 rillig
3132 1.468 rillig ok:
3133 1.891 rillig ModifyWords(ch, ModifyWord_Copy, NULL, ch->oneBigWord);
3134 1.703 rillig return AMR_OK;
3135 1.289 rillig }
3136 1.289 rillig
3137 1.738 rillig static char *
3138 1.1126 sjg str_totitle(const char *str)
3139 1.1126 sjg {
3140 1.1126 sjg size_t i, n = strlen(str) + 1;
3141 1.1126 sjg char *res = bmake_malloc(n);
3142 1.1126 sjg for (i = 0; i < n; i++) {
3143 1.1126 sjg if (i == 0 || ch_isspace(res[i - 1]))
3144 1.1126 sjg res[i] = ch_toupper(str[i]);
3145 1.1126 sjg else
3146 1.1126 sjg res[i] = ch_tolower(str[i]);
3147 1.1126 sjg }
3148 1.1126 sjg return res;
3149 1.1126 sjg }
3150 1.1126 sjg
3151 1.1126 sjg
3152 1.1126 sjg static char *
3153 1.738 rillig str_toupper(const char *str)
3154 1.738 rillig {
3155 1.1106 rillig size_t i, n = strlen(str) + 1;
3156 1.1106 rillig char *res = bmake_malloc(n);
3157 1.1106 rillig for (i = 0; i < n; i++)
3158 1.738 rillig res[i] = ch_toupper(str[i]);
3159 1.738 rillig return res;
3160 1.738 rillig }
3161 1.738 rillig
3162 1.738 rillig static char *
3163 1.738 rillig str_tolower(const char *str)
3164 1.738 rillig {
3165 1.1106 rillig size_t i, n = strlen(str) + 1;
3166 1.1106 rillig char *res = bmake_malloc(n);
3167 1.1106 rillig for (i = 0; i < n; i++)
3168 1.738 rillig res[i] = ch_tolower(str[i]);
3169 1.738 rillig return res;
3170 1.738 rillig }
3171 1.738 rillig
3172 1.289 rillig /* :tA, :tu, :tl, :ts<separator>, etc. */
3173 1.356 rillig static ApplyModifierResult
3174 1.891 rillig ApplyModifier_To(const char **pp, ModChain *ch)
3175 1.236 rillig {
3176 1.891 rillig Expr *expr = ch->expr;
3177 1.703 rillig const char *mod = *pp;
3178 1.703 rillig assert(mod[0] == 't');
3179 1.363 rillig
3180 1.1154 rillig if (IsDelimiter(mod[1], ch))
3181 1.1154 rillig return AMR_UNKNOWN; /* ":t<endc>" or ":t:" */
3182 1.289 rillig
3183 1.703 rillig if (mod[1] == 's')
3184 1.891 rillig return ApplyModifier_ToSep(pp, ch);
3185 1.289 rillig
3186 1.1154 rillig if (!IsDelimiter(mod[2], ch))
3187 1.1154 rillig return AMR_UNKNOWN;
3188 1.236 rillig
3189 1.810 rillig if (mod[1] == 'A') { /* :tA */
3190 1.864 rillig *pp = mod + 2;
3191 1.891 rillig ModifyWords(ch, ModifyWord_Realpath, NULL, ch->oneBigWord);
3192 1.703 rillig return AMR_OK;
3193 1.703 rillig }
3194 1.475 rillig
3195 1.1126 sjg if (mod[1] == 't') { /* :tt */
3196 1.1126 sjg *pp = mod + 2;
3197 1.1126 sjg if (Expr_ShouldEval(expr))
3198 1.1126 sjg Expr_SetValueOwn(expr, str_totitle(Expr_Str(expr)));
3199 1.1126 sjg return AMR_OK;
3200 1.1126 sjg }
3201 1.1127 rillig
3202 1.810 rillig if (mod[1] == 'u') { /* :tu */
3203 1.864 rillig *pp = mod + 2;
3204 1.950 rillig if (Expr_ShouldEval(expr))
3205 1.965 rillig Expr_SetValueOwn(expr, str_toupper(Expr_Str(expr)));
3206 1.703 rillig return AMR_OK;
3207 1.703 rillig }
3208 1.475 rillig
3209 1.810 rillig if (mod[1] == 'l') { /* :tl */
3210 1.864 rillig *pp = mod + 2;
3211 1.950 rillig if (Expr_ShouldEval(expr))
3212 1.965 rillig Expr_SetValueOwn(expr, str_tolower(Expr_Str(expr)));
3213 1.703 rillig return AMR_OK;
3214 1.703 rillig }
3215 1.475 rillig
3216 1.810 rillig if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
3217 1.864 rillig *pp = mod + 2;
3218 1.891 rillig ch->oneBigWord = mod[1] == 'W';
3219 1.703 rillig return AMR_OK;
3220 1.703 rillig }
3221 1.475 rillig
3222 1.1154 rillig return AMR_UNKNOWN; /* ":t<any>:" or ":t<any><endc>" */
3223 1.236 rillig }
3224 1.236 rillig
3225 1.634 rillig /* :[#], :[1], :[-1..1], etc. */
3226 1.356 rillig static ApplyModifierResult
3227 1.891 rillig ApplyModifier_Words(const char **pp, ModChain *ch)
3228 1.236 rillig {
3229 1.891 rillig Expr *expr = ch->expr;
3230 1.703 rillig int first, last;
3231 1.1157 rillig const char *p;
3232 1.1079 rillig LazyBuf argBuf;
3233 1.1079 rillig FStr arg;
3234 1.412 rillig
3235 1.703 rillig (*pp)++; /* skip the '[' */
3236 1.1115 rillig if (!ParseModifierPart(pp, ']', ']', expr->emode,
3237 1.1115 rillig ch, &argBuf, NULL, NULL))
3238 1.703 rillig return AMR_CLEANUP;
3239 1.1079 rillig arg = LazyBuf_DoneGet(&argBuf);
3240 1.1079 rillig p = arg.str;
3241 1.703 rillig
3242 1.1157 rillig if (!IsDelimiter(**pp, ch)) {
3243 1.1157 rillig Parse_Error(PARSE_FATAL,
3244 1.1157 rillig "Extra text after \"[%s]\"", arg.str);
3245 1.1157 rillig FStr_Done(&arg);
3246 1.1157 rillig return AMR_CLEANUP;
3247 1.1157 rillig }
3248 1.703 rillig
3249 1.905 rillig if (!ModChain_ShouldEval(ch))
3250 1.877 rillig goto ok;
3251 1.877 rillig
3252 1.1069 rillig if (p[0] == '\0')
3253 1.1069 rillig goto bad_modifier; /* Found ":[]". */
3254 1.703 rillig
3255 1.1069 rillig if (strcmp(p, "#") == 0) { /* Found ":[#]" */
3256 1.1069 rillig if (ch->oneBigWord)
3257 1.823 rillig Expr_SetValueRefer(expr, "1");
3258 1.1069 rillig else {
3259 1.703 rillig Buffer buf;
3260 1.412 rillig
3261 1.967 rillig SubstringWords words = Expr_Words(expr);
3262 1.703 rillig size_t ac = words.len;
3263 1.961 rillig SubstringWords_Free(words);
3264 1.703 rillig
3265 1.1087 rillig Buf_Init(&buf);
3266 1.703 rillig Buf_AddInt(&buf, (int)ac);
3267 1.823 rillig Expr_SetValueOwn(expr, Buf_DoneData(&buf));
3268 1.703 rillig }
3269 1.703 rillig goto ok;
3270 1.703 rillig }
3271 1.494 rillig
3272 1.1069 rillig if (strcmp(p, "*") == 0) { /* ":[*]" */
3273 1.895 rillig ch->oneBigWord = true;
3274 1.703 rillig goto ok;
3275 1.236 rillig }
3276 1.288 rillig
3277 1.1069 rillig if (strcmp(p, "@") == 0) { /* ":[@]" */
3278 1.895 rillig ch->oneBigWord = false;
3279 1.703 rillig goto ok;
3280 1.703 rillig }
3281 1.288 rillig
3282 1.1069 rillig /* Expect ":[N]" or ":[start..end]" */
3283 1.703 rillig if (!TryParseIntBase0(&p, &first))
3284 1.1069 rillig goto bad_modifier;
3285 1.703 rillig
3286 1.1069 rillig if (p[0] == '\0') /* ":[N]" */
3287 1.703 rillig last = first;
3288 1.1069 rillig else if (strncmp(p, "..", 2) == 0) {
3289 1.703 rillig p += 2;
3290 1.703 rillig if (!TryParseIntBase0(&p, &last) || *p != '\0')
3291 1.1069 rillig goto bad_modifier;
3292 1.703 rillig } else
3293 1.1069 rillig goto bad_modifier;
3294 1.288 rillig
3295 1.1069 rillig if (first == 0 && last == 0) { /* ":[0]" or ":[0..0]" */
3296 1.895 rillig ch->oneBigWord = true;
3297 1.703 rillig goto ok;
3298 1.703 rillig }
3299 1.288 rillig
3300 1.1069 rillig if (first == 0 || last == 0) /* ":[0..N]" or ":[N..0]" */
3301 1.703 rillig goto bad_modifier;
3302 1.703 rillig
3303 1.823 rillig Expr_SetValueOwn(expr,
3304 1.965 rillig VarSelectWords(Expr_Str(expr), first, last,
3305 1.1019 rillig ch->sep, ch->oneBigWord));
3306 1.288 rillig
3307 1.288 rillig ok:
3308 1.1079 rillig FStr_Done(&arg);
3309 1.703 rillig return AMR_OK;
3310 1.288 rillig
3311 1.288 rillig bad_modifier:
3312 1.1157 rillig Parse_Error(PARSE_FATAL, "Invalid modifier \":[%s]\"", arg.str);
3313 1.1079 rillig FStr_Done(&arg);
3314 1.1155 rillig return AMR_CLEANUP;
3315 1.236 rillig }
3316 1.236 rillig
3317 1.1016 rillig #if __STDC_VERSION__ >= 199901L
3318 1.939 sjg # define NUM_TYPE long long
3319 1.1009 rillig # define PARSE_NUM_TYPE strtoll
3320 1.1009 rillig #else
3321 1.1009 rillig # define NUM_TYPE long
3322 1.1009 rillig # define PARSE_NUM_TYPE strtol
3323 1.939 sjg #endif
3324 1.939 sjg
3325 1.939 sjg static NUM_TYPE
3326 1.964 rillig num_val(Substring s)
3327 1.939 sjg {
3328 1.939 sjg NUM_TYPE val;
3329 1.939 sjg char *ep;
3330 1.939 sjg
3331 1.1009 rillig val = PARSE_NUM_TYPE(s.start, &ep, 0);
3332 1.964 rillig if (ep != s.start) {
3333 1.939 sjg switch (*ep) {
3334 1.939 sjg case 'K':
3335 1.939 sjg case 'k':
3336 1.939 sjg val <<= 10;
3337 1.939 sjg break;
3338 1.939 sjg case 'M':
3339 1.939 sjg case 'm':
3340 1.939 sjg val <<= 20;
3341 1.939 sjg break;
3342 1.939 sjg case 'G':
3343 1.939 sjg case 'g':
3344 1.939 sjg val <<= 30;
3345 1.939 sjg break;
3346 1.939 sjg }
3347 1.939 sjg }
3348 1.939 sjg return val;
3349 1.939 sjg }
3350 1.939 sjg
3351 1.939 sjg static int
3352 1.964 rillig SubNumAsc(const void *sa, const void *sb)
3353 1.939 sjg {
3354 1.939 sjg NUM_TYPE a, b;
3355 1.939 sjg
3356 1.964 rillig a = num_val(*((const Substring *)sa));
3357 1.964 rillig b = num_val(*((const Substring *)sb));
3358 1.1067 rillig return a > b ? 1 : b > a ? -1 : 0;
3359 1.939 sjg }
3360 1.940 rillig
3361 1.939 sjg static int
3362 1.964 rillig SubNumDesc(const void *sa, const void *sb)
3363 1.939 sjg {
3364 1.964 rillig return SubNumAsc(sb, sa);
3365 1.939 sjg }
3366 1.940 rillig
3367 1.404 rillig static int
3368 1.1068 rillig Substring_Cmp(Substring a, Substring b)
3369 1.1068 rillig {
3370 1.1068 rillig for (; a.start < a.end && b.start < b.end; a.start++, b.start++)
3371 1.1068 rillig if (a.start[0] != b.start[0])
3372 1.1068 rillig return (unsigned char)a.start[0]
3373 1.1068 rillig - (unsigned char)b.start[0];
3374 1.1068 rillig return (int)((a.end - a.start) - (b.end - b.start));
3375 1.1068 rillig }
3376 1.1068 rillig
3377 1.1068 rillig static int
3378 1.964 rillig SubStrAsc(const void *sa, const void *sb)
3379 1.404 rillig {
3380 1.1068 rillig return Substring_Cmp(*(const Substring *)sa, *(const Substring *)sb);
3381 1.404 rillig }
3382 1.404 rillig
3383 1.404 rillig static int
3384 1.964 rillig SubStrDesc(const void *sa, const void *sb)
3385 1.404 rillig {
3386 1.964 rillig return SubStrAsc(sb, sa);
3387 1.404 rillig }
3388 1.404 rillig
3389 1.705 rillig static void
3390 1.962 rillig ShuffleSubstrings(Substring *strs, size_t n)
3391 1.705 rillig {
3392 1.705 rillig size_t i;
3393 1.705 rillig
3394 1.705 rillig for (i = n - 1; i > 0; i--) {
3395 1.705 rillig size_t rndidx = (size_t)random() % (i + 1);
3396 1.962 rillig Substring t = strs[i];
3397 1.705 rillig strs[i] = strs[rndidx];
3398 1.705 rillig strs[rndidx] = t;
3399 1.705 rillig }
3400 1.705 rillig }
3401 1.705 rillig
3402 1.943 rillig /*
3403 1.943 rillig * :O order ascending
3404 1.943 rillig * :Or order descending
3405 1.943 rillig * :Ox shuffle
3406 1.943 rillig * :On numeric ascending
3407 1.943 rillig * :Onr, :Orn numeric descending
3408 1.939 sjg */
3409 1.356 rillig static ApplyModifierResult
3410 1.891 rillig ApplyModifier_Order(const char **pp, ModChain *ch)
3411 1.236 rillig {
3412 1.942 rillig const char *mod = *pp;
3413 1.962 rillig SubstringWords words;
3414 1.946 rillig int (*cmp)(const void *, const void *);
3415 1.401 rillig
3416 1.1032 rillig if (IsDelimiter(mod[1], ch)) {
3417 1.964 rillig cmp = SubStrAsc;
3418 1.939 sjg (*pp)++;
3419 1.1032 rillig } else if (IsDelimiter(mod[2], ch)) {
3420 1.942 rillig if (mod[1] == 'n')
3421 1.964 rillig cmp = SubNumAsc;
3422 1.942 rillig else if (mod[1] == 'r')
3423 1.964 rillig cmp = SubStrDesc;
3424 1.942 rillig else if (mod[1] == 'x')
3425 1.944 rillig cmp = NULL;
3426 1.942 rillig else
3427 1.1153 rillig return AMR_UNKNOWN;
3428 1.942 rillig *pp += 2;
3429 1.1032 rillig } else if (IsDelimiter(mod[3], ch)) {
3430 1.942 rillig if ((mod[1] == 'n' && mod[2] == 'r') ||
3431 1.944 rillig (mod[1] == 'r' && mod[2] == 'n'))
3432 1.964 rillig cmp = SubNumDesc;
3433 1.944 rillig else
3434 1.1153 rillig return AMR_UNKNOWN;
3435 1.942 rillig *pp += 3;
3436 1.996 rillig } else
3437 1.1153 rillig return AMR_UNKNOWN;
3438 1.402 rillig
3439 1.905 rillig if (!ModChain_ShouldEval(ch))
3440 1.879 rillig return AMR_OK;
3441 1.879 rillig
3442 1.967 rillig words = Expr_Words(ch->expr);
3443 1.944 rillig if (cmp == NULL)
3444 1.962 rillig ShuffleSubstrings(words.words, words.len);
3445 1.964 rillig else {
3446 1.964 rillig assert(words.words[0].end[0] == '\0');
3447 1.944 rillig qsort(words.words, words.len, sizeof(words.words[0]), cmp);
3448 1.964 rillig }
3449 1.962 rillig Expr_SetValueOwn(ch->expr, SubstringWords_JoinFree(words));
3450 1.878 rillig
3451 1.705 rillig return AMR_OK;
3452 1.236 rillig }
3453 1.236 rillig
3454 1.236 rillig /* :? then : else */
3455 1.356 rillig static ApplyModifierResult
3456 1.891 rillig ApplyModifier_IfElse(const char **pp, ModChain *ch)
3457 1.236 rillig {
3458 1.891 rillig Expr *expr = ch->expr;
3459 1.985 rillig LazyBuf thenBuf;
3460 1.985 rillig LazyBuf elseBuf;
3461 1.412 rillig
3462 1.1119 rillig VarEvalMode then_emode = VARE_PARSE;
3463 1.1119 rillig VarEvalMode else_emode = VARE_PARSE;
3464 1.1161 rillig int parseErrorsBefore = parseErrors;
3465 1.236 rillig
3466 1.1143 rillig CondResult cond_rc = CR_TRUE; /* anything other than CR_ERROR */
3467 1.905 rillig if (Expr_ShouldEval(expr)) {
3468 1.1124 rillig evalStack.elems[evalStack.len - 1].kind = VSK_COND;
3469 1.990 rillig cond_rc = Cond_EvalCondition(expr->name);
3470 1.990 rillig if (cond_rc == CR_TRUE)
3471 1.906 rillig then_emode = expr->emode;
3472 1.1161 rillig else if (cond_rc == CR_FALSE)
3473 1.906 rillig else_emode = expr->emode;
3474 1.1161 rillig else if (parseErrors == parseErrorsBefore)
3475 1.1161 rillig Parse_Error(PARSE_FATAL, "Bad condition");
3476 1.703 rillig }
3477 1.703 rillig
3478 1.1124 rillig evalStack.elems[evalStack.len - 1].kind = VSK_COND_THEN;
3479 1.988 rillig (*pp)++; /* skip past the '?' */
3480 1.1115 rillig if (!ParseModifierPart(pp, ':', ':', then_emode,
3481 1.1115 rillig ch, &thenBuf, NULL, NULL))
3482 1.703 rillig return AMR_CLEANUP;
3483 1.703 rillig
3484 1.1124 rillig evalStack.elems[evalStack.len - 1].kind = VSK_COND_ELSE;
3485 1.1115 rillig if (!ParseModifierPart(pp, ch->endc, ch->endc, else_emode,
3486 1.1115 rillig ch, &elseBuf, NULL, NULL)) {
3487 1.985 rillig LazyBuf_Done(&thenBuf);
3488 1.703 rillig return AMR_CLEANUP;
3489 1.921 rillig }
3490 1.703 rillig
3491 1.891 rillig (*pp)--; /* Go back to the ch->endc. */
3492 1.809 rillig
3493 1.990 rillig if (cond_rc == CR_ERROR) {
3494 1.985 rillig LazyBuf_Done(&thenBuf);
3495 1.985 rillig LazyBuf_Done(&elseBuf);
3496 1.703 rillig return AMR_CLEANUP;
3497 1.703 rillig }
3498 1.703 rillig
3499 1.950 rillig if (!Expr_ShouldEval(expr)) {
3500 1.985 rillig LazyBuf_Done(&thenBuf);
3501 1.985 rillig LazyBuf_Done(&elseBuf);
3502 1.990 rillig } else if (cond_rc == CR_TRUE) {
3503 1.985 rillig Expr_SetValue(expr, LazyBuf_DoneGet(&thenBuf));
3504 1.985 rillig LazyBuf_Done(&elseBuf);
3505 1.703 rillig } else {
3506 1.985 rillig LazyBuf_Done(&thenBuf);
3507 1.985 rillig Expr_SetValue(expr, LazyBuf_DoneGet(&elseBuf));
3508 1.703 rillig }
3509 1.823 rillig Expr_Define(expr);
3510 1.703 rillig return AMR_OK;
3511 1.236 rillig }
3512 1.236 rillig
3513 1.283 rillig /*
3514 1.808 rillig * The ::= modifiers are special in that they do not read the variable value
3515 1.808 rillig * but instead assign to that variable. They always expand to an empty
3516 1.808 rillig * string.
3517 1.808 rillig *
3518 1.808 rillig * Their main purpose is in supporting .for loops that generate shell commands
3519 1.808 rillig * since an ordinary variable assignment at that point would terminate the
3520 1.808 rillig * dependency group for these targets. For example:
3521 1.283 rillig *
3522 1.808 rillig * list-targets: .USE
3523 1.283 rillig * .for i in ${.TARGET} ${.TARGET:R}.gz
3524 1.808 rillig * @${t::=$i}
3525 1.808 rillig * @echo 'The target is ${t:T}.'
3526 1.283 rillig * .endfor
3527 1.283 rillig *
3528 1.283 rillig * ::=<str> Assigns <str> as the new value of variable.
3529 1.283 rillig * ::?=<str> Assigns <str> as value of variable if
3530 1.283 rillig * it was not already set.
3531 1.283 rillig * ::+=<str> Appends <str> to variable.
3532 1.283 rillig * ::!=<cmd> Assigns output of <cmd> as the new value of
3533 1.283 rillig * variable.
3534 1.283 rillig */
3535 1.356 rillig static ApplyModifierResult
3536 1.891 rillig ApplyModifier_Assign(const char **pp, ModChain *ch)
3537 1.236 rillig {
3538 1.891 rillig Expr *expr = ch->expr;
3539 1.802 rillig GNode *scope;
3540 1.921 rillig FStr val;
3541 1.921 rillig LazyBuf buf;
3542 1.272 rillig
3543 1.703 rillig const char *mod = *pp;
3544 1.703 rillig const char *op = mod + 1;
3545 1.272 rillig
3546 1.703 rillig if (op[0] == '=')
3547 1.992 rillig goto found_op;
3548 1.992 rillig if ((op[0] == '+' || op[0] == '?' || op[0] == '!') && op[1] == '=')
3549 1.992 rillig goto found_op;
3550 1.1066 rillig return AMR_UNKNOWN; /* "::<unrecognized>" */
3551 1.862 rillig
3552 1.992 rillig found_op:
3553 1.898 rillig if (expr->name[0] == '\0') {
3554 1.1156 rillig const char *value = op[0] == '=' ? op + 1 : op + 2;
3555 1.703 rillig *pp = mod + 1;
3556 1.1155 rillig /* Take a guess at where the modifier ends. */
3557 1.1156 rillig Parse_Error(PARSE_FATAL,
3558 1.1156 rillig "Invalid attempt to assign \"%.*s\" to variable \"\" "
3559 1.1156 rillig "via modifier \"::%.*s\"",
3560 1.1156 rillig (int)strcspn(value, ":)}"), value,
3561 1.1156 rillig (int)(value - op), op);
3562 1.1155 rillig return AMR_CLEANUP;
3563 1.703 rillig }
3564 1.272 rillig
3565 1.1089 rillig *pp = mod + (op[0] != '=' ? 3 : 2);
3566 1.703 rillig
3567 1.1115 rillig if (!ParseModifierPart(pp, ch->endc, ch->endc, expr->emode,
3568 1.1115 rillig ch, &buf, NULL, NULL))
3569 1.703 rillig return AMR_CLEANUP;
3570 1.921 rillig val = LazyBuf_DoneGet(&buf);
3571 1.703 rillig
3572 1.891 rillig (*pp)--; /* Go back to the ch->endc. */
3573 1.703 rillig
3574 1.905 rillig if (!Expr_ShouldEval(expr))
3575 1.882 rillig goto done;
3576 1.882 rillig
3577 1.881 rillig scope = expr->scope; /* scope where v belongs */
3578 1.1089 rillig if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL
3579 1.1089 rillig && VarFind(expr->name, expr->scope, false) == NULL)
3580 1.1089 rillig scope = SCOPE_GLOBAL;
3581 1.881 rillig
3582 1.999 rillig if (op[0] == '+')
3583 1.921 rillig Var_Append(scope, expr->name, val.str);
3584 1.999 rillig else if (op[0] == '!') {
3585 1.1000 rillig char *output, *error;
3586 1.1000 rillig output = Cmd_Exec(val.str, &error);
3587 1.1000 rillig if (error != NULL) {
3588 1.1123 rillig Parse_Error(PARSE_WARNING, "%s", error);
3589 1.1000 rillig free(error);
3590 1.1000 rillig } else
3591 1.1000 rillig Var_Set(scope, expr->name, output);
3592 1.1000 rillig free(output);
3593 1.999 rillig } else if (op[0] == '?' && expr->defined == DEF_REGULAR) {
3594 1.999 rillig /* Do nothing. */
3595 1.999 rillig } else
3596 1.921 rillig Var_Set(scope, expr->name, val.str);
3597 1.999 rillig
3598 1.882 rillig Expr_SetValueRefer(expr, "");
3599 1.882 rillig
3600 1.882 rillig done:
3601 1.921 rillig FStr_Done(&val);
3602 1.703 rillig return AMR_OK;
3603 1.236 rillig }
3604 1.236 rillig
3605 1.778 rillig /*
3606 1.778 rillig * :_=...
3607 1.778 rillig * remember current value
3608 1.778 rillig */
3609 1.356 rillig static ApplyModifierResult
3610 1.891 rillig ApplyModifier_Remember(const char **pp, ModChain *ch)
3611 1.236 rillig {
3612 1.891 rillig Expr *expr = ch->expr;
3613 1.703 rillig const char *mod = *pp;
3614 1.868 rillig FStr name;
3615 1.866 rillig
3616 1.891 rillig if (!ModMatchEq(mod, "_", ch))
3617 1.703 rillig return AMR_UNKNOWN;
3618 1.703 rillig
3619 1.868 rillig name = FStr_InitRefer("_");
3620 1.703 rillig if (mod[1] == '=') {
3621 1.847 rillig /*
3622 1.847 rillig * XXX: This ad-hoc call to strcspn deviates from the usual
3623 1.847 rillig * behavior defined in ParseModifierPart. This creates an
3624 1.1066 rillig * unnecessary and undocumented inconsistency in make.
3625 1.847 rillig */
3626 1.869 rillig const char *arg = mod + 2;
3627 1.869 rillig size_t argLen = strcspn(arg, ":)}");
3628 1.869 rillig *pp = arg + argLen;
3629 1.869 rillig name = FStr_InitOwn(bmake_strldup(arg, argLen));
3630 1.868 rillig } else
3631 1.868 rillig *pp = mod + 1;
3632 1.864 rillig
3633 1.905 rillig if (Expr_ShouldEval(expr))
3634 1.1040 sjg Var_Set(SCOPE_GLOBAL, name.str, Expr_Str(expr));
3635 1.868 rillig FStr_Done(&name);
3636 1.864 rillig
3637 1.703 rillig return AMR_OK;
3638 1.236 rillig }
3639 1.236 rillig
3640 1.778 rillig /*
3641 1.778 rillig * Apply the given function to each word of the variable value,
3642 1.778 rillig * for a single-letter modifier such as :H, :T.
3643 1.778 rillig */
3644 1.434 rillig static ApplyModifierResult
3645 1.891 rillig ApplyModifier_WordFunc(const char **pp, ModChain *ch,
3646 1.822 rillig ModifyWordProc modifyWord)
3647 1.434 rillig {
3648 1.891 rillig if (!IsDelimiter((*pp)[1], ch))
3649 1.703 rillig return AMR_UNKNOWN;
3650 1.864 rillig (*pp)++;
3651 1.703 rillig
3652 1.1097 rillig ModifyWords(ch, modifyWord, NULL, ch->oneBigWord);
3653 1.864 rillig
3654 1.703 rillig return AMR_OK;
3655 1.434 rillig }
3656 1.434 rillig
3657 1.931 rillig /* Remove adjacent duplicate words. */
3658 1.567 rillig static ApplyModifierResult
3659 1.891 rillig ApplyModifier_Unique(const char **pp, ModChain *ch)
3660 1.567 rillig {
3661 1.962 rillig SubstringWords words;
3662 1.931 rillig
3663 1.891 rillig if (!IsDelimiter((*pp)[1], ch))
3664 1.703 rillig return AMR_UNKNOWN;
3665 1.862 rillig (*pp)++;
3666 1.862 rillig
3667 1.931 rillig if (!ModChain_ShouldEval(ch))
3668 1.931 rillig return AMR_OK;
3669 1.931 rillig
3670 1.967 rillig words = Expr_Words(ch->expr);
3671 1.931 rillig
3672 1.931 rillig if (words.len > 1) {
3673 1.1067 rillig size_t di, si;
3674 1.932 rillig
3675 1.932 rillig di = 0;
3676 1.932 rillig for (si = 1; si < words.len; si++) {
3677 1.962 rillig if (!Substring_Eq(words.words[si], words.words[di])) {
3678 1.932 rillig di++;
3679 1.932 rillig if (di != si)
3680 1.932 rillig words.words[di] = words.words[si];
3681 1.932 rillig }
3682 1.932 rillig }
3683 1.932 rillig words.len = di + 1;
3684 1.931 rillig }
3685 1.931 rillig
3686 1.962 rillig Expr_SetValueOwn(ch->expr, SubstringWords_JoinFree(words));
3687 1.862 rillig
3688 1.862 rillig return AMR_OK;
3689 1.567 rillig }
3690 1.567 rillig
3691 1.1071 rillig /* Test whether the modifier has the form '<lhs>=<rhs>'. */
3692 1.1071 rillig static bool
3693 1.1071 rillig IsSysVModifier(const char *p, char startc, char endc)
3694 1.1071 rillig {
3695 1.1071 rillig bool eqFound = false;
3696 1.1071 rillig
3697 1.1071 rillig int depth = 1;
3698 1.1149 rillig while (*p != '\0') {
3699 1.1071 rillig if (*p == '=') /* XXX: should also test depth == 1 */
3700 1.1071 rillig eqFound = true;
3701 1.1149 rillig else if (*p == endc) {
3702 1.1149 rillig if (--depth == 0)
3703 1.1149 rillig break;
3704 1.1149 rillig } else if (*p == startc)
3705 1.1071 rillig depth++;
3706 1.1149 rillig p++;
3707 1.1071 rillig }
3708 1.1149 rillig return eqFound;
3709 1.1071 rillig }
3710 1.1071 rillig
3711 1.236 rillig /* :from=to */
3712 1.356 rillig static ApplyModifierResult
3713 1.891 rillig ApplyModifier_SysV(const char **pp, ModChain *ch)
3714 1.236 rillig {
3715 1.891 rillig Expr *expr = ch->expr;
3716 1.925 rillig LazyBuf lhsBuf, rhsBuf;
3717 1.925 rillig FStr rhs;
3718 1.926 rillig struct ModifyWord_SysVSubstArgs args;
3719 1.925 rillig Substring lhs;
3720 1.925 rillig const char *lhsSuffix;
3721 1.412 rillig
3722 1.703 rillig const char *mod = *pp;
3723 1.245 rillig
3724 1.1071 rillig if (!IsSysVModifier(mod, ch->startc, ch->endc))
3725 1.703 rillig return AMR_UNKNOWN;
3726 1.236 rillig
3727 1.1115 rillig if (!ParseModifierPart(pp, '=', '=', expr->emode,
3728 1.1115 rillig ch, &lhsBuf, NULL, NULL))
3729 1.703 rillig return AMR_CLEANUP;
3730 1.703 rillig
3731 1.1115 rillig if (!ParseModifierPart(pp, ch->endc, ch->endc, expr->emode,
3732 1.1115 rillig ch, &rhsBuf, NULL, NULL)) {
3733 1.925 rillig LazyBuf_Done(&lhsBuf);
3734 1.703 rillig return AMR_CLEANUP;
3735 1.921 rillig }
3736 1.925 rillig rhs = LazyBuf_DoneGet(&rhsBuf);
3737 1.703 rillig
3738 1.891 rillig (*pp)--; /* Go back to the ch->endc. */
3739 1.809 rillig
3740 1.925 rillig /* Do not turn an empty expression into non-empty. */
3741 1.965 rillig if (lhsBuf.len == 0 && Expr_Str(expr)[0] == '\0')
3742 1.925 rillig goto done;
3743 1.925 rillig
3744 1.925 rillig lhs = LazyBuf_Get(&lhsBuf);
3745 1.925 rillig lhsSuffix = Substring_SkipFirst(lhs, '%');
3746 1.925 rillig
3747 1.925 rillig args.scope = expr->scope;
3748 1.925 rillig args.lhsPrefix = Substring_Init(lhs.start,
3749 1.925 rillig lhsSuffix != lhs.start ? lhsSuffix - 1 : lhs.start);
3750 1.925 rillig args.lhsPercent = lhsSuffix != lhs.start;
3751 1.925 rillig args.lhsSuffix = Substring_Init(lhsSuffix, lhs.end);
3752 1.925 rillig args.rhs = rhs.str;
3753 1.925 rillig
3754 1.926 rillig ModifyWords(ch, ModifyWord_SysVSubst, &args, ch->oneBigWord);
3755 1.897 rillig
3756 1.925 rillig done:
3757 1.925 rillig LazyBuf_Done(&lhsBuf);
3758 1.1048 rillig FStr_Done(&rhs);
3759 1.703 rillig return AMR_OK;
3760 1.236 rillig }
3761 1.236 rillig
3762 1.548 rillig /* :sh */
3763 1.548 rillig static ApplyModifierResult
3764 1.891 rillig ApplyModifier_SunShell(const char **pp, ModChain *ch)
3765 1.548 rillig {
3766 1.891 rillig Expr *expr = ch->expr;
3767 1.703 rillig const char *p = *pp;
3768 1.891 rillig if (!(p[1] == 'h' && IsDelimiter(p[2], ch)))
3769 1.703 rillig return AMR_UNKNOWN;
3770 1.864 rillig *pp = p + 2;
3771 1.863 rillig
3772 1.905 rillig if (Expr_ShouldEval(expr)) {
3773 1.1000 rillig char *output, *error;
3774 1.1000 rillig output = Cmd_Exec(Expr_Str(expr), &error);
3775 1.1000 rillig if (error != NULL) {
3776 1.1122 rillig Parse_Error(PARSE_WARNING, "%s", error);
3777 1.1000 rillig free(error);
3778 1.1000 rillig }
3779 1.863 rillig Expr_SetValueOwn(expr, output);
3780 1.863 rillig }
3781 1.864 rillig
3782 1.863 rillig return AMR_OK;
3783 1.548 rillig }
3784 1.548 rillig
3785 1.1041 rillig /*
3786 1.1041 rillig * In cases where the evaluation mode and the definedness are the "standard"
3787 1.1041 rillig * ones, don't log them, to keep the logs readable.
3788 1.1041 rillig */
3789 1.1041 rillig static bool
3790 1.1041 rillig ShouldLogInSimpleFormat(const Expr *expr)
3791 1.1041 rillig {
3792 1.1144 rillig return (expr->emode == VARE_EVAL
3793 1.1144 rillig || expr->emode == VARE_EVAL_DEFINED
3794 1.1144 rillig || expr->emode == VARE_EVAL_DEFINED_LOUD)
3795 1.1119 rillig && expr->defined == DEF_REGULAR;
3796 1.1041 rillig }
3797 1.1041 rillig
3798 1.549 rillig static void
3799 1.891 rillig LogBeforeApply(const ModChain *ch, const char *mod)
3800 1.549 rillig {
3801 1.891 rillig const Expr *expr = ch->expr;
3802 1.895 rillig bool is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], ch);
3803 1.703 rillig
3804 1.909 rillig /*
3805 1.909 rillig * At this point, only the first character of the modifier can
3806 1.909 rillig * be used since the end of the modifier is not yet known.
3807 1.909 rillig */
3808 1.909 rillig
3809 1.909 rillig if (!Expr_ShouldEval(expr)) {
3810 1.909 rillig debug_printf("Parsing modifier ${%s:%c%s}\n",
3811 1.909 rillig expr->name, mod[0], is_single_char ? "" : "...");
3812 1.909 rillig return;
3813 1.909 rillig }
3814 1.909 rillig
3815 1.1041 rillig if (ShouldLogInSimpleFormat(expr)) {
3816 1.910 rillig debug_printf(
3817 1.910 rillig "Evaluating modifier ${%s:%c%s} on value \"%s\"\n",
3818 1.910 rillig expr->name, mod[0], is_single_char ? "" : "...",
3819 1.965 rillig Expr_Str(expr));
3820 1.910 rillig return;
3821 1.910 rillig }
3822 1.910 rillig
3823 1.909 rillig debug_printf(
3824 1.909 rillig "Evaluating modifier ${%s:%c%s} on value \"%s\" (%s, %s)\n",
3825 1.965 rillig expr->name, mod[0], is_single_char ? "" : "...", Expr_Str(expr),
3826 1.910 rillig VarEvalMode_Name[expr->emode], ExprDefined_Name[expr->defined]);
3827 1.549 rillig }
3828 1.549 rillig
3829 1.549 rillig static void
3830 1.891 rillig LogAfterApply(const ModChain *ch, const char *p, const char *mod)
3831 1.549 rillig {
3832 1.891 rillig const Expr *expr = ch->expr;
3833 1.965 rillig const char *value = Expr_Str(expr);
3834 1.703 rillig
3835 1.1041 rillig if (ShouldLogInSimpleFormat(expr)) {
3836 1.1150 rillig debug_printf("Result of ${%s:%.*s} is \"%s\"\n",
3837 1.1150 rillig expr->name, (int)(p - mod), mod, value);
3838 1.912 rillig return;
3839 1.912 rillig }
3840 1.912 rillig
3841 1.1150 rillig debug_printf("Result of ${%s:%.*s} is \"%s\" (%s, %s)\n",
3842 1.1150 rillig expr->name, (int)(p - mod), mod, value,
3843 1.906 rillig VarEvalMode_Name[expr->emode],
3844 1.825 rillig ExprDefined_Name[expr->defined]);
3845 1.549 rillig }
3846 1.549 rillig
3847 1.551 rillig static ApplyModifierResult
3848 1.891 rillig ApplyModifier(const char **pp, ModChain *ch)
3849 1.551 rillig {
3850 1.703 rillig switch (**pp) {
3851 1.857 rillig case '!':
3852 1.891 rillig return ApplyModifier_ShellCommand(pp, ch);
3853 1.703 rillig case ':':
3854 1.891 rillig return ApplyModifier_Assign(pp, ch);
3855 1.857 rillig case '?':
3856 1.891 rillig return ApplyModifier_IfElse(pp, ch);
3857 1.703 rillig case '@':
3858 1.891 rillig return ApplyModifier_Loop(pp, ch);
3859 1.857 rillig case '[':
3860 1.891 rillig return ApplyModifier_Words(pp, ch);
3861 1.703 rillig case '_':
3862 1.891 rillig return ApplyModifier_Remember(pp, ch);
3863 1.857 rillig case 'C':
3864 1.891 rillig return ApplyModifier_Regex(pp, ch);
3865 1.703 rillig case 'D':
3866 1.968 rillig case 'U':
3867 1.891 rillig return ApplyModifier_Defined(pp, ch);
3868 1.857 rillig case 'E':
3869 1.891 rillig return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix);
3870 1.703 rillig case 'g':
3871 1.995 rillig case 'l':
3872 1.995 rillig return ApplyModifier_Time(pp, ch);
3873 1.857 rillig case 'H':
3874 1.891 rillig return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head);
3875 1.703 rillig case 'h':
3876 1.891 rillig return ApplyModifier_Hash(pp, ch);
3877 1.857 rillig case 'L':
3878 1.891 rillig return ApplyModifier_Literal(pp, ch);
3879 1.857 rillig case 'M':
3880 1.703 rillig case 'N':
3881 1.891 rillig return ApplyModifier_Match(pp, ch);
3882 1.1051 sjg case 'm':
3883 1.1051 sjg return ApplyModifier_Mtime(pp, ch);
3884 1.857 rillig case 'O':
3885 1.891 rillig return ApplyModifier_Order(pp, ch);
3886 1.857 rillig case 'P':
3887 1.891 rillig return ApplyModifier_Path(pp, ch);
3888 1.857 rillig case 'Q':
3889 1.703 rillig case 'q':
3890 1.891 rillig return ApplyModifier_Quote(pp, ch);
3891 1.703 rillig case 'R':
3892 1.891 rillig return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root);
3893 1.703 rillig case 'r':
3894 1.891 rillig return ApplyModifier_Range(pp, ch);
3895 1.857 rillig case 'S':
3896 1.891 rillig return ApplyModifier_Subst(pp, ch);
3897 1.703 rillig case 's':
3898 1.891 rillig return ApplyModifier_SunShell(pp, ch);
3899 1.857 rillig case 'T':
3900 1.891 rillig return ApplyModifier_WordFunc(pp, ch, ModifyWord_Tail);
3901 1.857 rillig case 't':
3902 1.891 rillig return ApplyModifier_To(pp, ch);
3903 1.857 rillig case 'u':
3904 1.891 rillig return ApplyModifier_Unique(pp, ch);
3905 1.703 rillig default:
3906 1.703 rillig return AMR_UNKNOWN;
3907 1.703 rillig }
3908 1.551 rillig }
3909 1.551 rillig
3910 1.823 rillig static void ApplyModifiers(Expr *, const char **, char, char);
3911 1.641 rillig
3912 1.641 rillig typedef enum ApplyModifiersIndirectResult {
3913 1.752 rillig /* The indirect modifiers have been applied successfully. */
3914 1.703 rillig AMIR_CONTINUE,
3915 1.752 rillig /* Fall back to the SysV modifier. */
3916 1.849 rillig AMIR_SYSV,
3917 1.752 rillig /* Error out. */
3918 1.703 rillig AMIR_OUT
3919 1.641 rillig } ApplyModifiersIndirectResult;
3920 1.641 rillig
3921 1.752 rillig /*
3922 1.1075 rillig * While expanding an expression, expand and apply indirect modifiers,
3923 1.752 rillig * such as in ${VAR:${M_indirect}}.
3924 1.752 rillig *
3925 1.1075 rillig * All indirect modifiers of a group must come from a single
3926 1.752 rillig * expression. ${VAR:${M1}} is valid but ${VAR:${M1}${M2}} is not.
3927 1.752 rillig *
3928 1.752 rillig * Multiple groups of indirect modifiers can be chained by separating them
3929 1.752 rillig * with colons. ${VAR:${M1}:${M2}} contains 2 indirect modifiers.
3930 1.752 rillig *
3931 1.1075 rillig * If the expression is not followed by ch->endc or ':', fall
3932 1.752 rillig * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}.
3933 1.752 rillig */
3934 1.641 rillig static ApplyModifiersIndirectResult
3935 1.891 rillig ApplyModifiersIndirect(ModChain *ch, const char **pp)
3936 1.703 rillig {
3937 1.891 rillig Expr *expr = ch->expr;
3938 1.721 rillig const char *p = *pp;
3939 1.1042 rillig FStr mods = Var_Parse(&p, expr->scope, expr->emode);
3940 1.703 rillig /* TODO: handle errors */
3941 1.641 rillig
3942 1.1032 rillig if (mods.str[0] != '\0' && !IsDelimiter(*p, ch)) {
3943 1.743 rillig FStr_Done(&mods);
3944 1.849 rillig return AMIR_SYSV;
3945 1.703 rillig }
3946 1.703 rillig
3947 1.708 rillig DEBUG3(VAR, "Indirect modifier \"%s\" from \"%.*s\"\n",
3948 1.743 rillig mods.str, (int)(p - *pp), *pp);
3949 1.703 rillig
3950 1.1098 rillig if (ModChain_ShouldEval(ch) && mods.str[0] != '\0') {
3951 1.743 rillig const char *modsp = mods.str;
3952 1.1147 rillig EvalStack_Push(VSK_INDIRECT_MODIFIERS, mods.str, NULL);
3953 1.823 rillig ApplyModifiers(expr, &modsp, '\0', '\0');
3954 1.1147 rillig EvalStack_Pop();
3955 1.965 rillig if (Expr_Str(expr) == var_Error || *modsp != '\0') {
3956 1.743 rillig FStr_Done(&mods);
3957 1.721 rillig *pp = p;
3958 1.703 rillig return AMIR_OUT; /* error already reported */
3959 1.703 rillig }
3960 1.703 rillig }
3961 1.743 rillig FStr_Done(&mods);
3962 1.641 rillig
3963 1.703 rillig if (*p == ':')
3964 1.703 rillig p++;
3965 1.891 rillig else if (*p == '\0' && ch->endc != '\0') {
3966 1.1131 rillig Parse_Error(PARSE_FATAL,
3967 1.1131 rillig "Unclosed expression after indirect modifier, "
3968 1.1131 rillig "expecting '%c'",
3969 1.1131 rillig ch->endc);
3970 1.721 rillig *pp = p;
3971 1.703 rillig return AMIR_OUT;
3972 1.641 rillig }
3973 1.641 rillig
3974 1.721 rillig *pp = p;
3975 1.703 rillig return AMIR_CONTINUE;
3976 1.641 rillig }
3977 1.641 rillig
3978 1.750 rillig static ApplyModifierResult
3979 1.891 rillig ApplySingleModifier(const char **pp, ModChain *ch)
3980 1.750 rillig {
3981 1.750 rillig ApplyModifierResult res;
3982 1.850 rillig const char *mod = *pp;
3983 1.750 rillig const char *p = *pp;
3984 1.750 rillig
3985 1.750 rillig if (DEBUG(VAR))
3986 1.891 rillig LogBeforeApply(ch, mod);
3987 1.750 rillig
3988 1.1158 sjg if (posix_state == PS_SET)
3989 1.1158 sjg res = ApplyModifier_SysV(&p, ch);
3990 1.1158 sjg else
3991 1.1158 sjg res = AMR_UNKNOWN;
3992 1.1158 sjg if (res == AMR_UNKNOWN)
3993 1.1158 sjg res = ApplyModifier(&p, ch);
3994 1.750 rillig
3995 1.1158 sjg if (res == AMR_UNKNOWN && posix_state != PS_SET) {
3996 1.750 rillig assert(p == mod);
3997 1.891 rillig res = ApplyModifier_SysV(&p, ch);
3998 1.750 rillig }
3999 1.750 rillig
4000 1.750 rillig if (res == AMR_UNKNOWN) {
4001 1.750 rillig /*
4002 1.750 rillig * Guess the end of the current modifier.
4003 1.750 rillig * XXX: Skipping the rest of the modifier hides
4004 1.750 rillig * errors and leads to wrong results.
4005 1.750 rillig * Parsing should rather stop here.
4006 1.750 rillig */
4007 1.1032 rillig for (p++; !IsDelimiter(*p, ch); p++)
4008 1.750 rillig continue;
4009 1.1151 rillig Parse_Error(PARSE_FATAL, "Unknown modifier \":%.*s\"",
4010 1.851 rillig (int)(p - mod), mod);
4011 1.891 rillig Expr_SetValueRefer(ch->expr, var_Error);
4012 1.1150 rillig res = AMR_CLEANUP;
4013 1.750 rillig }
4014 1.1150 rillig if (res != AMR_OK) {
4015 1.750 rillig *pp = p;
4016 1.750 rillig return res;
4017 1.750 rillig }
4018 1.750 rillig
4019 1.750 rillig if (DEBUG(VAR))
4020 1.891 rillig LogAfterApply(ch, p, mod);
4021 1.750 rillig
4022 1.891 rillig if (*p == '\0' && ch->endc != '\0') {
4023 1.1131 rillig Parse_Error(PARSE_FATAL,
4024 1.1074 rillig "Unclosed expression, expecting '%c' for "
4025 1.1131 rillig "modifier \"%.*s\"",
4026 1.1131 rillig ch->endc, (int)(p - mod), mod);
4027 1.750 rillig } else if (*p == ':') {
4028 1.750 rillig p++;
4029 1.891 rillig } else if (opts.strict && *p != '\0' && *p != ch->endc) {
4030 1.750 rillig Parse_Error(PARSE_FATAL,
4031 1.750 rillig "Missing delimiter ':' after modifier \"%.*s\"",
4032 1.750 rillig (int)(p - mod), mod);
4033 1.750 rillig /*
4034 1.750 rillig * TODO: propagate parse error to the enclosing
4035 1.750 rillig * expression
4036 1.750 rillig */
4037 1.750 rillig }
4038 1.750 rillig *pp = p;
4039 1.750 rillig return AMR_OK;
4040 1.750 rillig }
4041 1.750 rillig
4042 1.897 rillig #if __STDC_VERSION__ >= 199901L
4043 1.1079 rillig #define ModChain_Init(expr, startc, endc, sep, oneBigWord) \
4044 1.897 rillig (ModChain) { expr, startc, endc, sep, oneBigWord }
4045 1.897 rillig #else
4046 1.897 rillig MAKE_INLINE ModChain
4047 1.1079 rillig ModChain_Init(Expr *expr, char startc, char endc, char sep, bool oneBigWord)
4048 1.897 rillig {
4049 1.897 rillig ModChain ch;
4050 1.897 rillig ch.expr = expr;
4051 1.897 rillig ch.startc = startc;
4052 1.897 rillig ch.endc = endc;
4053 1.897 rillig ch.sep = sep;
4054 1.897 rillig ch.oneBigWord = oneBigWord;
4055 1.897 rillig return ch;
4056 1.897 rillig }
4057 1.897 rillig #endif
4058 1.897 rillig
4059 1.419 rillig /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
4060 1.823 rillig static void
4061 1.357 rillig ApplyModifiers(
4062 1.823 rillig Expr *expr,
4063 1.821 rillig const char **pp, /* the parsing position, updated upon return */
4064 1.821 rillig char startc, /* '(' or '{'; or '\0' for indirect modifiers */
4065 1.823 rillig char endc /* ')' or '}'; or '\0' for indirect modifiers */
4066 1.703 rillig )
4067 1.703 rillig {
4068 1.1079 rillig ModChain ch = ModChain_Init(expr, startc, endc, ' ', false);
4069 1.703 rillig const char *p;
4070 1.703 rillig
4071 1.703 rillig assert(startc == '(' || startc == '{' || startc == '\0');
4072 1.703 rillig assert(endc == ')' || endc == '}' || endc == '\0');
4073 1.965 rillig assert(Expr_Str(expr) != NULL);
4074 1.703 rillig
4075 1.703 rillig p = *pp;
4076 1.703 rillig
4077 1.703 rillig if (*p == '\0' && endc != '\0') {
4078 1.1131 rillig Parse_Error(PARSE_FATAL,
4079 1.1131 rillig "Unclosed expression, expecting '%c'", ch.endc);
4080 1.703 rillig goto cleanup;
4081 1.703 rillig }
4082 1.703 rillig
4083 1.703 rillig while (*p != '\0' && *p != endc) {
4084 1.750 rillig ApplyModifierResult res;
4085 1.703 rillig
4086 1.703 rillig if (*p == '$') {
4087 1.1079 rillig /*
4088 1.1079 rillig * TODO: Only evaluate the expression once, no matter
4089 1.1079 rillig * whether it's an indirect modifier or the initial
4090 1.1079 rillig * part of a SysV modifier.
4091 1.1079 rillig */
4092 1.849 rillig ApplyModifiersIndirectResult amir =
4093 1.891 rillig ApplyModifiersIndirect(&ch, &p);
4094 1.703 rillig if (amir == AMIR_CONTINUE)
4095 1.703 rillig continue;
4096 1.703 rillig if (amir == AMIR_OUT)
4097 1.752 rillig break;
4098 1.703 rillig }
4099 1.752 rillig
4100 1.891 rillig res = ApplySingleModifier(&p, &ch);
4101 1.703 rillig if (res == AMR_CLEANUP)
4102 1.703 rillig goto cleanup;
4103 1.356 rillig }
4104 1.752 rillig
4105 1.703 rillig *pp = p;
4106 1.988 rillig assert(Expr_Str(expr) != NULL); /* Use var_Error or varUndefined. */
4107 1.823 rillig return;
4108 1.25 christos
4109 1.240 rillig cleanup:
4110 1.858 rillig /*
4111 1.858 rillig * TODO: Use p + strlen(p) instead, to stop parsing immediately.
4112 1.858 rillig *
4113 1.1015 rillig * In the unit tests, this generates a few shell commands with
4114 1.1015 rillig * unbalanced quotes. Instead of producing these incomplete strings,
4115 1.1015 rillig * commands with evaluation errors should not be run at all.
4116 1.858 rillig *
4117 1.858 rillig * To make that happen, Var_Subst must report the actual errors
4118 1.1044 rillig * instead of returning the resulting string unconditionally.
4119 1.858 rillig */
4120 1.703 rillig *pp = p;
4121 1.823 rillig Expr_SetValueRefer(expr, var_Error);
4122 1.108 sjg }
4123 1.25 christos
4124 1.778 rillig /*
4125 1.1015 rillig * Only 4 of the 7 built-in local variables are treated specially as they are
4126 1.1015 rillig * the only ones that will be set when dynamic sources are expanded.
4127 1.778 rillig */
4128 1.895 rillig static bool
4129 1.916 rillig VarnameIsDynamic(Substring varname)
4130 1.335 rillig {
4131 1.916 rillig const char *name;
4132 1.916 rillig size_t len;
4133 1.916 rillig
4134 1.916 rillig name = varname.start;
4135 1.916 rillig len = Substring_Length(varname);
4136 1.703 rillig if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
4137 1.703 rillig switch (name[0]) {
4138 1.703 rillig case '@':
4139 1.703 rillig case '%':
4140 1.703 rillig case '*':
4141 1.703 rillig case '!':
4142 1.895 rillig return true;
4143 1.703 rillig }
4144 1.895 rillig return false;
4145 1.335 rillig }
4146 1.335 rillig
4147 1.703 rillig if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
4148 1.916 rillig return Substring_Equals(varname, ".TARGET") ||
4149 1.916 rillig Substring_Equals(varname, ".ARCHIVE") ||
4150 1.916 rillig Substring_Equals(varname, ".PREFIX") ||
4151 1.916 rillig Substring_Equals(varname, ".MEMBER");
4152 1.703 rillig }
4153 1.335 rillig
4154 1.895 rillig return false;
4155 1.335 rillig }
4156 1.335 rillig
4157 1.502 rillig static const char *
4158 1.802 rillig UndefinedShortVarValue(char varname, const GNode *scope)
4159 1.502 rillig {
4160 1.802 rillig if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) {
4161 1.703 rillig /*
4162 1.802 rillig * If substituting a local variable in a non-local scope,
4163 1.703 rillig * assume it's for dynamic source stuff. We have to handle
4164 1.703 rillig * this specially and return the longhand for the variable
4165 1.703 rillig * with the dollar sign escaped so it makes it back to the
4166 1.703 rillig * caller. Only four of the local variables are treated
4167 1.703 rillig * specially as they are the only four that will be set
4168 1.703 rillig * when dynamic sources are expanded.
4169 1.703 rillig */
4170 1.703 rillig switch (varname) {
4171 1.703 rillig case '@':
4172 1.703 rillig return "$(.TARGET)";
4173 1.703 rillig case '%':
4174 1.703 rillig return "$(.MEMBER)";
4175 1.703 rillig case '*':
4176 1.703 rillig return "$(.PREFIX)";
4177 1.703 rillig case '!':
4178 1.703 rillig return "$(.ARCHIVE)";
4179 1.703 rillig }
4180 1.502 rillig }
4181 1.769 rillig return NULL;
4182 1.502 rillig }
4183 1.502 rillig
4184 1.778 rillig /*
4185 1.778 rillig * Parse a variable name, until the end character or a colon, whichever
4186 1.778 rillig * comes first.
4187 1.778 rillig */
4188 1.916 rillig static void
4189 1.501 rillig ParseVarname(const char **pp, char startc, char endc,
4190 1.906 rillig GNode *scope, VarEvalMode emode,
4191 1.916 rillig LazyBuf *buf)
4192 1.501 rillig {
4193 1.703 rillig const char *p = *pp;
4194 1.1066 rillig int depth = 0;
4195 1.703 rillig
4196 1.923 rillig LazyBuf_Init(buf, p);
4197 1.703 rillig
4198 1.703 rillig while (*p != '\0') {
4199 1.854 rillig if ((*p == endc || *p == ':') && depth == 0)
4200 1.854 rillig break;
4201 1.703 rillig if (*p == startc)
4202 1.703 rillig depth++;
4203 1.854 rillig if (*p == endc)
4204 1.854 rillig depth--;
4205 1.501 rillig
4206 1.703 rillig if (*p == '$') {
4207 1.1042 rillig FStr nested_val = Var_Parse(&p, scope, emode);
4208 1.703 rillig /* TODO: handle errors */
4209 1.916 rillig LazyBuf_AddStr(buf, nested_val.str);
4210 1.743 rillig FStr_Done(&nested_val);
4211 1.703 rillig } else {
4212 1.916 rillig LazyBuf_Add(buf, *p);
4213 1.703 rillig p++;
4214 1.703 rillig }
4215 1.501 rillig }
4216 1.703 rillig *pp = p;
4217 1.501 rillig }
4218 1.501 rillig
4219 1.1023 rillig static bool
4220 1.1023 rillig IsShortVarnameValid(char varname, const char *start)
4221 1.507 rillig {
4222 1.818 rillig if (varname != '$' && varname != ':' && varname != '}' &&
4223 1.818 rillig varname != ')' && varname != '\0')
4224 1.1023 rillig return true;
4225 1.507 rillig
4226 1.771 rillig if (!opts.strict)
4227 1.1023 rillig return false; /* XXX: Missing error message */
4228 1.507 rillig
4229 1.1096 sjg if (varname == '$' && save_dollars)
4230 1.703 rillig Parse_Error(PARSE_FATAL,
4231 1.507 rillig "To escape a dollar, use \\$, not $$, at \"%s\"", start);
4232 1.703 rillig else if (varname == '\0')
4233 1.703 rillig Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
4234 1.1096 sjg else if (save_dollars)
4235 1.703 rillig Parse_Error(PARSE_FATAL,
4236 1.507 rillig "Invalid variable name '%c', at \"%s\"", varname, start);
4237 1.507 rillig
4238 1.1023 rillig return false;
4239 1.507 rillig }
4240 1.507 rillig
4241 1.778 rillig /*
4242 1.817 rillig * Parse a single-character variable name such as in $V or $@.
4243 1.778 rillig * Return whether to continue parsing.
4244 1.778 rillig */
4245 1.895 rillig static bool
4246 1.817 rillig ParseVarnameShort(char varname, const char **pp, GNode *scope,
4247 1.906 rillig VarEvalMode emode,
4248 1.1042 rillig const char **out_false_val,
4249 1.896 rillig Var **out_true_var)
4250 1.667 rillig {
4251 1.703 rillig char name[2];
4252 1.703 rillig Var *v;
4253 1.1024 rillig const char *val;
4254 1.622 rillig
4255 1.1023 rillig if (!IsShortVarnameValid(varname, *pp)) {
4256 1.1025 rillig (*pp)++; /* only skip the '$' */
4257 1.896 rillig *out_false_val = var_Error;
4258 1.895 rillig return false;
4259 1.703 rillig }
4260 1.622 rillig
4261 1.817 rillig name[0] = varname;
4262 1.703 rillig name[1] = '\0';
4263 1.895 rillig v = VarFind(name, scope, true);
4264 1.1024 rillig if (v != NULL) {
4265 1.1025 rillig /* No need to advance *pp, the calling code handles this. */
4266 1.1024 rillig *out_true_var = v;
4267 1.1024 rillig return true;
4268 1.1024 rillig }
4269 1.622 rillig
4270 1.1024 rillig *pp += 2;
4271 1.769 rillig
4272 1.1024 rillig val = UndefinedShortVarValue(varname, scope);
4273 1.1024 rillig if (val == NULL)
4274 1.1144 rillig val = emode == VARE_EVAL_DEFINED
4275 1.1144 rillig || emode == VARE_EVAL_DEFINED_LOUD
4276 1.1144 rillig ? var_Error : varUndefined;
4277 1.767 rillig
4278 1.1144 rillig if ((opts.strict || emode == VARE_EVAL_DEFINED_LOUD)
4279 1.1144 rillig && val == var_Error) {
4280 1.1024 rillig Parse_Error(PARSE_FATAL,
4281 1.1024 rillig "Variable \"%s\" is undefined", name);
4282 1.622 rillig }
4283 1.622 rillig
4284 1.1024 rillig *out_false_val = val;
4285 1.1024 rillig return false;
4286 1.622 rillig }
4287 1.622 rillig
4288 1.662 rillig /* Find variables like @F or <D. */
4289 1.662 rillig static Var *
4290 1.916 rillig FindLocalLegacyVar(Substring varname, GNode *scope,
4291 1.662 rillig const char **out_extraModifiers)
4292 1.662 rillig {
4293 1.916 rillig Var *v;
4294 1.916 rillig
4295 1.802 rillig /* Only resolve these variables if scope is a "real" target. */
4296 1.802 rillig if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL)
4297 1.703 rillig return NULL;
4298 1.703 rillig
4299 1.916 rillig if (Substring_Length(varname) != 2)
4300 1.703 rillig return NULL;
4301 1.916 rillig if (varname.start[1] != 'F' && varname.start[1] != 'D')
4302 1.703 rillig return NULL;
4303 1.916 rillig if (strchr("@%?*!<>", varname.start[0]) == NULL)
4304 1.703 rillig return NULL;
4305 1.703 rillig
4306 1.1091 rillig v = VarFindSubstring(Substring_Init(varname.start, varname.start + 1),
4307 1.1091 rillig scope, false);
4308 1.916 rillig if (v == NULL)
4309 1.916 rillig return NULL;
4310 1.897 rillig
4311 1.916 rillig *out_extraModifiers = varname.start[1] == 'D' ? "H:" : "T:";
4312 1.916 rillig return v;
4313 1.662 rillig }
4314 1.662 rillig
4315 1.1044 rillig static FStr
4316 1.916 rillig EvalUndefined(bool dynamic, const char *start, const char *p,
4317 1.1159 rillig Substring varname, VarEvalMode emode, int parseErrorsBefore)
4318 1.667 rillig {
4319 1.1044 rillig if (dynamic)
4320 1.1044 rillig return FStr_InitOwn(bmake_strsedup(start, p));
4321 1.703 rillig
4322 1.1144 rillig if (emode == VARE_EVAL_DEFINED_LOUD
4323 1.1144 rillig || (emode == VARE_EVAL_DEFINED && opts.strict)) {
4324 1.1159 rillig if (parseErrors == parseErrorsBefore) {
4325 1.1159 rillig Parse_Error(PARSE_FATAL,
4326 1.1159 rillig "Variable \"%.*s\" is undefined",
4327 1.1159 rillig (int) Substring_Length(varname), varname.start);
4328 1.1159 rillig }
4329 1.1044 rillig return FStr_InitRefer(var_Error);
4330 1.703 rillig }
4331 1.703 rillig
4332 1.1044 rillig return FStr_InitRefer(
4333 1.1144 rillig emode == VARE_EVAL_DEFINED_LOUD || emode == VARE_EVAL_DEFINED
4334 1.1144 rillig ? var_Error : varUndefined);
4335 1.663 rillig }
4336 1.663 rillig
4337 1.778 rillig /*
4338 1.778 rillig * Parse a long variable name enclosed in braces or parentheses such as $(VAR)
4339 1.623 rillig * or ${VAR}, up to the closing brace or parenthesis, or in the case of
4340 1.623 rillig * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
4341 1.778 rillig * Return whether to continue parsing.
4342 1.778 rillig */
4343 1.895 rillig static bool
4344 1.623 rillig ParseVarnameLong(
4345 1.922 rillig const char **pp,
4346 1.624 rillig char startc,
4347 1.802 rillig GNode *scope,
4348 1.906 rillig VarEvalMode emode,
4349 1.1144 rillig VarEvalMode nested_emode,
4350 1.1159 rillig int parseErrorsBefore,
4351 1.624 rillig
4352 1.896 rillig const char **out_false_pp,
4353 1.896 rillig FStr *out_false_val,
4354 1.896 rillig
4355 1.896 rillig char *out_true_endc,
4356 1.896 rillig Var **out_true_v,
4357 1.896 rillig bool *out_true_haveModifier,
4358 1.896 rillig const char **out_true_extraModifiers,
4359 1.896 rillig bool *out_true_dynamic,
4360 1.896 rillig ExprDefined *out_true_exprDefined
4361 1.703 rillig )
4362 1.703 rillig {
4363 1.916 rillig LazyBuf varname;
4364 1.972 sjg Substring name;
4365 1.703 rillig Var *v;
4366 1.895 rillig bool haveModifier;
4367 1.895 rillig bool dynamic = false;
4368 1.703 rillig
4369 1.922 rillig const char *p = *pp;
4370 1.1095 rillig const char *start = p;
4371 1.703 rillig char endc = startc == '(' ? ')' : '}';
4372 1.703 rillig
4373 1.703 rillig p += 2; /* skip "${" or "$(" or "y(" */
4374 1.1144 rillig ParseVarname(&p, startc, endc, scope, nested_emode, &varname);
4375 1.972 sjg name = LazyBuf_Get(&varname);
4376 1.703 rillig
4377 1.1093 rillig if (*p == ':')
4378 1.895 rillig haveModifier = true;
4379 1.1093 rillig else if (*p == endc)
4380 1.895 rillig haveModifier = false;
4381 1.1093 rillig else {
4382 1.916 rillig Parse_Error(PARSE_FATAL, "Unclosed variable \"%.*s\"",
4383 1.916 rillig (int)Substring_Length(name), name.start);
4384 1.916 rillig LazyBuf_Done(&varname);
4385 1.896 rillig *out_false_pp = p;
4386 1.896 rillig *out_false_val = FStr_InitRefer(var_Error);
4387 1.895 rillig return false;
4388 1.703 rillig }
4389 1.623 rillig
4390 1.972 sjg v = VarFindSubstring(name, scope, true);
4391 1.623 rillig
4392 1.988 rillig /*
4393 1.988 rillig * At this point, p points just after the variable name, either at
4394 1.988 rillig * ':' or at endc.
4395 1.988 rillig */
4396 1.623 rillig
4397 1.974 rillig if (v == NULL && Substring_Equals(name, ".SUFFIXES")) {
4398 1.974 rillig char *suffixes = Suff_NamesStr();
4399 1.975 rillig v = VarNew(FStr_InitRefer(".SUFFIXES"), suffixes,
4400 1.979 rillig true, false, true);
4401 1.974 rillig free(suffixes);
4402 1.974 rillig } else if (v == NULL)
4403 1.974 rillig v = FindLocalLegacyVar(name, scope, out_true_extraModifiers);
4404 1.623 rillig
4405 1.703 rillig if (v == NULL) {
4406 1.703 rillig /*
4407 1.703 rillig * Defer expansion of dynamic variables if they appear in
4408 1.802 rillig * non-local scope since they are not defined there.
4409 1.703 rillig */
4410 1.972 sjg dynamic = VarnameIsDynamic(name) &&
4411 1.802 rillig (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL);
4412 1.703 rillig
4413 1.703 rillig if (!haveModifier) {
4414 1.703 rillig p++; /* skip endc */
4415 1.896 rillig *out_false_pp = p;
4416 1.1044 rillig *out_false_val = EvalUndefined(dynamic, start, p,
4417 1.1159 rillig name, emode, parseErrorsBefore);
4418 1.986 rillig LazyBuf_Done(&varname);
4419 1.895 rillig return false;
4420 1.703 rillig }
4421 1.623 rillig
4422 1.703 rillig /*
4423 1.1075 rillig * The expression is based on an undefined variable.
4424 1.703 rillig * Nevertheless it needs a Var, for modifiers that access the
4425 1.703 rillig * variable name, such as :L or :?.
4426 1.703 rillig *
4427 1.703 rillig * Most modifiers leave this expression in the "undefined"
4428 1.1079 rillig * state (DEF_UNDEF), only a few modifiers like :D, :U, :L,
4429 1.703 rillig * :P turn this undefined expression into a defined
4430 1.1079 rillig * expression (DEF_DEFINED).
4431 1.703 rillig *
4432 1.830 rillig * In the end, after applying all modifiers, if the expression
4433 1.703 rillig * is still undefined, Var_Parse will return an empty string
4434 1.703 rillig * instead of the actually computed value.
4435 1.703 rillig */
4436 1.978 rillig v = VarNew(LazyBuf_DoneGet(&varname), "",
4437 1.980 rillig true, false, false);
4438 1.896 rillig *out_true_exprDefined = DEF_UNDEF;
4439 1.703 rillig } else
4440 1.916 rillig LazyBuf_Done(&varname);
4441 1.623 rillig
4442 1.922 rillig *pp = p;
4443 1.896 rillig *out_true_endc = endc;
4444 1.896 rillig *out_true_v = v;
4445 1.896 rillig *out_true_haveModifier = haveModifier;
4446 1.896 rillig *out_true_dynamic = dynamic;
4447 1.895 rillig return true;
4448 1.623 rillig }
4449 1.623 rillig
4450 1.897 rillig #if __STDC_VERSION__ >= 199901L
4451 1.1079 rillig #define Expr_Init(name, value, emode, scope, defined) \
4452 1.1079 rillig (Expr) { name, value, emode, scope, defined }
4453 1.897 rillig #else
4454 1.897 rillig MAKE_INLINE Expr
4455 1.1079 rillig Expr_Init(const char *name, FStr value,
4456 1.1079 rillig VarEvalMode emode, GNode *scope, ExprDefined defined)
4457 1.897 rillig {
4458 1.897 rillig Expr expr;
4459 1.897 rillig
4460 1.898 rillig expr.name = name;
4461 1.897 rillig expr.value = value;
4462 1.917 rillig expr.emode = emode;
4463 1.897 rillig expr.scope = scope;
4464 1.897 rillig expr.defined = defined;
4465 1.897 rillig return expr;
4466 1.897 rillig }
4467 1.897 rillig #endif
4468 1.897 rillig
4469 1.666 rillig /*
4470 1.913 rillig * Expressions of the form ${:U...} with a trivial value are often generated
4471 1.1079 rillig * by .for loops and are boring, so evaluate them without debug logging.
4472 1.913 rillig */
4473 1.913 rillig static bool
4474 1.1106 rillig Var_Parse_U(const char **pp, VarEvalMode emode, FStr *out_value)
4475 1.913 rillig {
4476 1.913 rillig const char *p;
4477 1.913 rillig
4478 1.913 rillig p = *pp;
4479 1.913 rillig if (!(p[0] == '$' && p[1] == '{' && p[2] == ':' && p[3] == 'U'))
4480 1.913 rillig return false;
4481 1.913 rillig
4482 1.913 rillig p += 4;
4483 1.915 rillig while (*p != '$' && *p != '{' && *p != ':' && *p != '\\' &&
4484 1.915 rillig *p != '}' && *p != '\0')
4485 1.913 rillig p++;
4486 1.913 rillig if (*p != '}')
4487 1.913 rillig return false;
4488 1.913 rillig
4489 1.1119 rillig *out_value = emode == VARE_PARSE
4490 1.1093 rillig ? FStr_InitRefer("")
4491 1.1093 rillig : FStr_InitOwn(bmake_strsedup(*pp + 4, p));
4492 1.913 rillig *pp = p + 1;
4493 1.913 rillig return true;
4494 1.913 rillig }
4495 1.913 rillig
4496 1.913 rillig /*
4497 1.1079 rillig * Given the start of an expression (such as $v, $(VAR), ${VAR:Mpattern}),
4498 1.1079 rillig * extract the variable name and the modifiers, if any. While parsing, apply
4499 1.1079 rillig * the modifiers to the value of the expression.
4500 1.579 rillig *
4501 1.108 sjg * Input:
4502 1.666 rillig * *pp The string to parse.
4503 1.1021 rillig * When called from CondParser_FuncCallEmpty, it can
4504 1.1021 rillig * also point to the "y" of "empty(VARNAME:Modifiers)".
4505 1.1079 rillig * scope The scope for finding variables.
4506 1.1079 rillig * emode Controls the exact details of parsing and evaluation.
4507 1.666 rillig *
4508 1.666 rillig * Output:
4509 1.666 rillig * *pp The position where to continue parsing.
4510 1.666 rillig * TODO: After a parse error, the value of *pp is
4511 1.666 rillig * unspecified. It may not have been updated at all,
4512 1.666 rillig * point to some random character in the string, to the
4513 1.666 rillig * location of the parse error, or at the end of the
4514 1.666 rillig * string.
4515 1.1075 rillig * return The value of the expression, never NULL.
4516 1.1042 rillig * return var_Error if there was a parse error.
4517 1.1042 rillig * return var_Error if the base variable of the expression was
4518 1.1119 rillig * undefined, emode is VARE_EVAL_DEFINED, and none of
4519 1.666 rillig * the modifiers turned the undefined expression into a
4520 1.666 rillig * defined expression.
4521 1.666 rillig * XXX: It is not guaranteed that an error message has
4522 1.666 rillig * been printed.
4523 1.1042 rillig * return varUndefined if the base variable of the expression
4524 1.1119 rillig * was undefined, emode was not VARE_EVAL_DEFINED,
4525 1.666 rillig * and none of the modifiers turned the undefined
4526 1.666 rillig * expression into a defined expression.
4527 1.108 sjg */
4528 1.1042 rillig FStr
4529 1.1042 rillig Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
4530 1.108 sjg {
4531 1.1106 rillig const char *start, *p;
4532 1.1021 rillig bool haveModifier; /* true for ${VAR:...}, false for ${VAR} */
4533 1.1021 rillig char startc; /* the actual '{' or '(' or '\0' */
4534 1.1021 rillig char endc; /* the expected '}' or ')' or '\0' */
4535 1.703 rillig /*
4536 1.1021 rillig * true if the expression is based on one of the 7 predefined
4537 1.1021 rillig * variables that are local to a target, and the expression is
4538 1.1021 rillig * expanded in a non-local scope. The result is the text of the
4539 1.1021 rillig * expression, unaltered. This is needed to support dynamic sources.
4540 1.703 rillig */
4541 1.895 rillig bool dynamic;
4542 1.703 rillig const char *extramodifiers;
4543 1.703 rillig Var *v;
4544 1.1144 rillig Expr expr = Expr_Init(NULL, FStr_InitRefer(NULL),
4545 1.1144 rillig emode == VARE_EVAL_DEFINED || emode == VARE_EVAL_DEFINED_LOUD
4546 1.1144 rillig ? VARE_EVAL : emode,
4547 1.898 rillig scope, DEF_REGULAR);
4548 1.1042 rillig FStr val;
4549 1.1159 rillig int parseErrorsBefore = parseErrors;
4550 1.703 rillig
4551 1.1106 rillig if (Var_Parse_U(pp, emode, &val))
4552 1.1042 rillig return val;
4553 1.913 rillig
4554 1.1106 rillig p = *pp;
4555 1.1106 rillig start = p;
4556 1.906 rillig DEBUG2(VAR, "Var_Parse: %s (%s)\n", start, VarEvalMode_Name[emode]);
4557 1.703 rillig
4558 1.1042 rillig val = FStr_InitRefer(NULL);
4559 1.703 rillig extramodifiers = NULL; /* extra modifiers to apply first */
4560 1.895 rillig dynamic = false;
4561 1.473 rillig
4562 1.1021 rillig endc = '\0'; /* Appease GCC. */
4563 1.108 sjg
4564 1.703 rillig startc = p[1];
4565 1.703 rillig if (startc != '(' && startc != '{') {
4566 1.1042 rillig if (!ParseVarnameShort(startc, pp, scope, emode, &val.str, &v))
4567 1.1042 rillig return val;
4568 1.895 rillig haveModifier = false;
4569 1.703 rillig p++;
4570 1.703 rillig } else {
4571 1.1144 rillig if (!ParseVarnameLong(&p, startc, scope, emode, expr.emode,
4572 1.1159 rillig parseErrorsBefore,
4573 1.1044 rillig pp, &val,
4574 1.922 rillig &endc, &v, &haveModifier, &extramodifiers,
4575 1.825 rillig &dynamic, &expr.defined))
4576 1.1042 rillig return val;
4577 1.703 rillig }
4578 1.401 rillig
4579 1.898 rillig expr.name = v->name.str;
4580 1.1028 rillig if (v->inUse && VarEvalMode_ShouldEval(emode)) {
4581 1.1137 rillig Parse_Error(PARSE_FATAL, "Variable %s is recursive.",
4582 1.1137 rillig v->name.str);
4583 1.1138 rillig FStr_Done(&val);
4584 1.1138 rillig if (*p != '\0')
4585 1.1138 rillig p++;
4586 1.1138 rillig *pp = p;
4587 1.1138 rillig return FStr_InitRefer(var_Error);
4588 1.1008 rillig }
4589 1.187 christos
4590 1.703 rillig /*
4591 1.1078 rillig * FIXME: This assignment creates an alias to the current value of the
4592 1.703 rillig * variable. This means that as long as the value of the expression
4593 1.1078 rillig * stays the same, the value of the variable must not change, and the
4594 1.1078 rillig * variable must not be deleted. Using the ':@' modifier, it is
4595 1.1084 rillig * possible (since var.c 1.212 from 2017-02-01) to delete the variable
4596 1.1078 rillig * while its value is still being used:
4597 1.1078 rillig *
4598 1.1078 rillig * VAR= value
4599 1.1107 rillig * _:= ${VAR:${:U:@VAR@@}:S,^,prefix,}
4600 1.1078 rillig *
4601 1.1078 rillig * The same effect might be achievable using the '::=' or the ':_'
4602 1.1078 rillig * modifiers.
4603 1.1021 rillig *
4604 1.703 rillig * At the bottom of this function, the resulting value is compared to
4605 1.703 rillig * the then-current value of the variable. This might also invoke
4606 1.703 rillig * undefined behavior.
4607 1.703 rillig */
4608 1.823 rillig expr.value = FStr_InitRefer(v->val.data);
4609 1.108 sjg
4610 1.1133 rillig if (!VarEvalMode_ShouldEval(emode))
4611 1.1133 rillig EvalStack_Push(VSK_EXPR_PARSE, start, NULL);
4612 1.1133 rillig else if (expr.name[0] != '\0')
4613 1.1128 rillig EvalStack_Push(VSK_VARNAME, expr.name, &expr.value);
4614 1.1102 rillig else
4615 1.1132 rillig EvalStack_Push(VSK_EXPR, start, &expr.value);
4616 1.1102 rillig
4617 1.703 rillig /*
4618 1.703 rillig * Before applying any modifiers, expand any nested expressions from
4619 1.703 rillig * the variable value.
4620 1.703 rillig */
4621 1.1003 rillig if (VarEvalMode_ShouldEval(emode) &&
4622 1.1003 rillig strchr(Expr_Str(&expr), '$') != NULL) {
4623 1.743 rillig char *expanded;
4624 1.902 rillig v->inUse = true;
4625 1.1144 rillig expanded = Var_Subst(Expr_Str(&expr), scope, expr.emode);
4626 1.902 rillig v->inUse = false;
4627 1.703 rillig /* TODO: handle errors */
4628 1.823 rillig Expr_SetValueOwn(&expr, expanded);
4629 1.191 dholland }
4630 1.191 dholland
4631 1.855 rillig if (extramodifiers != NULL) {
4632 1.855 rillig const char *em = extramodifiers;
4633 1.855 rillig ApplyModifiers(&expr, &em, '\0', '\0');
4634 1.855 rillig }
4635 1.191 dholland
4636 1.855 rillig if (haveModifier) {
4637 1.988 rillig p++; /* Skip initial colon. */
4638 1.855 rillig ApplyModifiers(&expr, &p, startc, endc);
4639 1.191 dholland }
4640 1.438 rillig
4641 1.703 rillig if (*p != '\0') /* Skip past endc if possible. */
4642 1.703 rillig p++;
4643 1.519 rillig
4644 1.703 rillig *pp = p;
4645 1.15 christos
4646 1.980 rillig if (expr.defined == DEF_UNDEF) {
4647 1.1159 rillig Substring varname = Substring_InitStr(expr.name);
4648 1.1159 rillig FStr value = EvalUndefined(dynamic, start, p, varname, emode,
4649 1.1159 rillig parseErrorsBefore);
4650 1.1159 rillig Expr_SetValue(&expr, value);
4651 1.980 rillig }
4652 1.980 rillig
4653 1.1161 rillig EvalStack_Pop();
4654 1.1161 rillig
4655 1.978 rillig if (v->shortLived) {
4656 1.980 rillig if (expr.value.str == v->val.data) {
4657 1.980 rillig /* move ownership */
4658 1.980 rillig expr.value.freeIt = v->val.data;
4659 1.980 rillig v->val.data = NULL;
4660 1.703 rillig }
4661 1.980 rillig VarFreeShortLived(v);
4662 1.34 christos }
4663 1.980 rillig
4664 1.1042 rillig return expr.value;
4665 1.1 cgd }
4666 1.1 cgd
4667 1.678 rillig static void
4668 1.906 rillig VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalMode emode)
4669 1.768 rillig {
4670 1.830 rillig /* A dollar sign may be escaped with another dollar sign. */
4671 1.906 rillig if (save_dollars && VarEvalMode_ShouldKeepDollar(emode))
4672 1.768 rillig Buf_AddByte(res, '$');
4673 1.768 rillig Buf_AddByte(res, '$');
4674 1.768 rillig *pp += 2;
4675 1.768 rillig }
4676 1.768 rillig
4677 1.768 rillig static void
4678 1.1136 rillig VarSubstExpr(const char **pp, Buffer *buf, GNode *scope, VarEvalMode emode)
4679 1.678 rillig {
4680 1.703 rillig const char *p = *pp;
4681 1.703 rillig const char *nested_p = p;
4682 1.1042 rillig FStr val = Var_Parse(&nested_p, scope, emode);
4683 1.703 rillig /* TODO: handle errors */
4684 1.678 rillig
4685 1.743 rillig if (val.str == var_Error || val.str == varUndefined) {
4686 1.1136 rillig if (!VarEvalMode_ShouldKeepUndef(emode)
4687 1.1136 rillig || val.str == var_Error) {
4688 1.703 rillig p = nested_p;
4689 1.703 rillig } else {
4690 1.988 rillig /*
4691 1.988 rillig * Copy the initial '$' of the undefined expression,
4692 1.703 rillig * thereby deferring expansion of the expression, but
4693 1.988 rillig * expand nested expressions if already possible. See
4694 1.988 rillig * unit-tests/varparse-undef-partial.mk.
4695 1.988 rillig */
4696 1.703 rillig Buf_AddByte(buf, *p);
4697 1.703 rillig p++;
4698 1.703 rillig }
4699 1.678 rillig } else {
4700 1.703 rillig p = nested_p;
4701 1.743 rillig Buf_AddStr(buf, val.str);
4702 1.678 rillig }
4703 1.678 rillig
4704 1.743 rillig FStr_Done(&val);
4705 1.678 rillig
4706 1.703 rillig *pp = p;
4707 1.678 rillig }
4708 1.678 rillig
4709 1.768 rillig /*
4710 1.1075 rillig * Skip as many characters as possible -- either to the end of the string,
4711 1.1075 rillig * or to the next dollar sign, which may start an expression.
4712 1.768 rillig */
4713 1.768 rillig static void
4714 1.768 rillig VarSubstPlain(const char **pp, Buffer *res)
4715 1.768 rillig {
4716 1.768 rillig const char *p = *pp;
4717 1.768 rillig const char *start = p;
4718 1.768 rillig
4719 1.768 rillig for (p++; *p != '$' && *p != '\0'; p++)
4720 1.768 rillig continue;
4721 1.1055 rillig Buf_AddRange(res, start, p);
4722 1.768 rillig *pp = p;
4723 1.768 rillig }
4724 1.768 rillig
4725 1.778 rillig /*
4726 1.1075 rillig * Expand all expressions like $V, ${VAR}, $(VAR:Modifiers) in the
4727 1.660 rillig * given string.
4728 1.1 cgd *
4729 1.70 wiz * Input:
4730 1.1105 rillig * str The string in which the expressions are expanded.
4731 1.1105 rillig * scope The scope in which to start searching for variables.
4732 1.1105 rillig * The other scopes are searched as well.
4733 1.917 rillig * emode The mode for parsing or evaluating subexpressions.
4734 1.1 cgd */
4735 1.1043 rillig char *
4736 1.1043 rillig Var_Subst(const char *str, GNode *scope, VarEvalMode emode)
4737 1.1 cgd {
4738 1.703 rillig const char *p = str;
4739 1.703 rillig Buffer res;
4740 1.1 cgd
4741 1.703 rillig Buf_Init(&res);
4742 1.703 rillig
4743 1.703 rillig while (*p != '\0') {
4744 1.768 rillig if (p[0] == '$' && p[1] == '$')
4745 1.906 rillig VarSubstDollarDollar(&p, &res, emode);
4746 1.768 rillig else if (p[0] == '$')
4747 1.1136 rillig VarSubstExpr(&p, &res, scope, emode);
4748 1.768 rillig else
4749 1.768 rillig VarSubstPlain(&p, &res);
4750 1.1 cgd }
4751 1.15 christos
4752 1.1108 rillig return Buf_DoneData(&res);
4753 1.1 cgd }
4754 1.1 cgd
4755 1.1120 rillig char *
4756 1.1120 rillig Var_SubstInTarget(const char *str, GNode *scope)
4757 1.1120 rillig {
4758 1.1120 rillig char *res;
4759 1.1128 rillig EvalStack_Push(VSK_TARGET, scope->name, NULL);
4760 1.1146 rillig EvalStack_Push(VSK_COMMAND, str, NULL);
4761 1.1120 rillig res = Var_Subst(str, scope, VARE_EVAL);
4762 1.1120 rillig EvalStack_Pop();
4763 1.1146 rillig EvalStack_Pop();
4764 1.1120 rillig return res;
4765 1.1120 rillig }
4766 1.1120 rillig
4767 1.1001 rillig void
4768 1.1001 rillig Var_Expand(FStr *str, GNode *scope, VarEvalMode emode)
4769 1.1001 rillig {
4770 1.1001 rillig char *expanded;
4771 1.1001 rillig
4772 1.1001 rillig if (strchr(str->str, '$') == NULL)
4773 1.1001 rillig return;
4774 1.1043 rillig expanded = Var_Subst(str->str, scope, emode);
4775 1.1001 rillig /* TODO: handle errors */
4776 1.1001 rillig FStr_Done(str);
4777 1.1001 rillig *str = FStr_InitOwn(expanded);
4778 1.1001 rillig }
4779 1.1001 rillig
4780 1.286 sjg void
4781 1.286 sjg Var_Stats(void)
4782 1.286 sjg {
4783 1.802 rillig HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables");
4784 1.1 cgd }
4785 1.15 christos
4786 1.964 rillig static int
4787 1.964 rillig StrAsc(const void *sa, const void *sb)
4788 1.964 rillig {
4789 1.964 rillig return strcmp(
4790 1.964 rillig *((const char *const *)sa), *((const char *const *)sb));
4791 1.964 rillig }
4792 1.964 rillig
4793 1.964 rillig
4794 1.802 rillig /* Print all variables in a scope, sorted by name. */
4795 1.5 cgd void
4796 1.802 rillig Var_Dump(GNode *scope)
4797 1.1 cgd {
4798 1.703 rillig Vector /* of const char * */ vec;
4799 1.703 rillig HashIter hi;
4800 1.703 rillig size_t i;
4801 1.703 rillig const char **varnames;
4802 1.703 rillig
4803 1.703 rillig Vector_Init(&vec, sizeof(const char *));
4804 1.703 rillig
4805 1.802 rillig HashIter_Init(&hi, &scope->vars);
4806 1.1114 rillig while (HashIter_Next(&hi))
4807 1.703 rillig *(const char **)Vector_Push(&vec) = hi.entry->key;
4808 1.703 rillig varnames = vec.items;
4809 1.703 rillig
4810 1.964 rillig qsort(varnames, vec.len, sizeof varnames[0], StrAsc);
4811 1.703 rillig
4812 1.703 rillig for (i = 0; i < vec.len; i++) {
4813 1.703 rillig const char *varname = varnames[i];
4814 1.1035 rillig const Var *var = HashTable_FindValue(&scope->vars, varname);
4815 1.1018 rillig debug_printf("%-16s = %s%s\n", varname,
4816 1.1018 rillig var->val.data, ValueDescription(var->val.data));
4817 1.703 rillig }
4818 1.573 rillig
4819 1.703 rillig Vector_Done(&vec);
4820 1.1 cgd }
4821