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