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