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