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