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