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