Annotation of src/usr.bin/make/var.c, Revision 1.640
1.640 ! rillig 1: /* $NetBSD: var.c,v 1.639 2020/11/01 22:12:54 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: *
83: * Var_Set Set the value of the variable, creating it if
84: * necessary.
85: *
86: * Var_Append Append more characters to the variable, creating it if
87: * necessary. A space is placed between the old value and
88: * the new one.
1.1 cgd 89: *
1.546 rillig 90: * Var_Exists See if a variable exists.
1.1 cgd 91: *
1.592 rillig 92: * Var_Value Return the unexpanded value of a variable, or NULL if
93: * the variable is undefined.
94: *
95: * Var_Subst Substitute all variable expressions in a string.
96: *
97: * Var_Parse Parse a variable expression such as ${VAR:Mpattern}.
1.1 cgd 98: *
1.592 rillig 99: * Var_Delete Delete a variable.
1.1 cgd 100: *
1.592 rillig 101: * Var_ExportVars Export some or even all variables to the environment
102: * of this process and its child processes.
1.1 cgd 103: *
1.592 rillig 104: * Var_Export Export the variable to the environment of this process
105: * and its child processes.
1.1 cgd 106: *
1.592 rillig 107: * Var_UnExport Don't export the variable anymore.
1.1 cgd 108: *
109: * Debugging:
1.592 rillig 110: * Var_Stats Print out hashing statistics if in -dh mode.
111: *
112: * Var_Dump Print out all variables defined in the given context.
1.1 cgd 113: *
114: * XXX: There's a lot of duplication in these functions.
115: */
116:
1.630 rillig 117: #include <sys/stat.h>
1.31 gwr 118: #ifndef NO_REGEX
1.630 rillig 119: #include <sys/types.h>
120: #include <regex.h>
1.17 christos 121: #endif
1.631 rillig 122: #include <errno.h>
1.630 rillig 123: #include <inttypes.h>
124: #include <limits.h>
125: #include <time.h>
126:
127: #include "make.h"
128: #include "dir.h"
129: #include "job.h"
130: #include "metachar.h"
1.1 cgd 131:
1.512 rillig 132: /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
1.640 ! rillig 133: MAKE_RCSID("$NetBSD: var.c,v 1.639 2020/11/01 22:12:54 rillig Exp $");
1.512 rillig 134:
1.547 rillig 135: #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
136: #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
137: #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3)
138: #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4)
1.411 rillig 139:
1.471 rillig 140: ENUM_FLAGS_RTTI_3(VarEvalFlags,
141: VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN);
1.430 rillig 142:
1.1 cgd 143: /*
1.170 sjg 144: * This lets us tell if we have replaced the original environ
145: * (which we cannot free).
146: */
147: char **savedEnv = NULL;
148:
1.536 rillig 149: /* Special return value for Var_Parse, indicating a parse error. It may be
150: * caused by an undefined variable, a syntax error in a modifier or
151: * something entirely different. */
1.249 rillig 152: char var_Error[] = "";
1.1 cgd 153:
1.536 rillig 154: /* Special return value for Var_Parse, indicating an undefined variable in
155: * a case where VARE_UNDEFERR is not set. This undefined variable is
156: * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
157: * be deferred until it is defined in an actual target. */
158: static char varUndefined[] = "";
159:
160: /* Special return value for Var_Parse, just to avoid allocating empty strings.
161: * In contrast to var_Error and varUndefined, this is not an error marker but
162: * just an ordinary successful return value. */
163: static char emptyString[] = "";
1.1 cgd 164:
165: /*
1.593 rillig 166: * Traditionally this make consumed $$ during := like any other expansion.
167: * Other make's do not, and this make follows straight since 2016-01-09.
168: *
1.205 sjg 169: * This knob allows controlling the behavior.
1.292 rillig 170: * FALSE to consume $$ during := assignment.
171: * TRUE to preserve $$ during := assignment.
1.205 sjg 172: */
1.593 rillig 173: #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
1.205 sjg 174: static Boolean save_dollars = TRUE;
175:
176: /*
1.1 cgd 177: * Internally, variables are contained in four different contexts.
1.292 rillig 178: * 1) the environment. They cannot be changed. If an environment
1.594 rillig 179: * variable is appended to, the result is placed in the global
180: * context.
181: * 2) the global context. Variables set in the makefiles are located
182: * here.
1.1 cgd 183: * 3) the command-line context. All variables set on the command line
1.594 rillig 184: * are placed in this context.
1.1 cgd 185: * 4) the local context. Each target has associated with it a context
186: * list. On this list are located the structures describing such
187: * local variables as $(@) and $(*)
188: * The four contexts are searched in the reverse order from which they are
1.591 rillig 189: * listed (but see opts.checkEnvFirst).
1.1 cgd 190: */
1.240 rillig 191: GNode *VAR_INTERNAL; /* variables from make itself */
192: GNode *VAR_GLOBAL; /* variables from the makefile */
1.594 rillig 193: GNode *VAR_CMDLINE; /* variables defined on the command-line */
1.240 rillig 194:
1.578 rillig 195: typedef enum VarFlags {
1.601 rillig 196:
1.440 rillig 197: /* The variable's value is currently being used by Var_Parse or Var_Subst.
198: * This marker is used to avoid endless recursion. */
199: VAR_IN_USE = 0x01,
1.601 rillig 200:
1.440 rillig 201: /* The variable comes from the environment.
202: * These variables are not registered in any GNode, therefore they must
203: * be freed as soon as they are not used anymore. */
204: VAR_FROM_ENV = 0x02,
1.601 rillig 205:
1.440 rillig 206: /* The variable is exported to the environment, to be used by child
207: * processes. */
208: VAR_EXPORTED = 0x10,
1.601 rillig 209:
1.440 rillig 210: /* At the point where this variable was exported, it contained an
211: * unresolved reference to another variable. Before any child process is
212: * started, it needs to be exported again, in the hope that the referenced
213: * variable can then be resolved. */
214: VAR_REEXPORT = 0x20,
1.601 rillig 215:
216: /* The variable came from the command line. */
1.457 sjg 217: VAR_FROM_CMD = 0x40,
1.601 rillig 218:
219: /* The variable value cannot be changed anymore, and the variable cannot
220: * be deleted. Any attempts to do so are ignored. */
1.457 sjg 221: VAR_READONLY = 0x80
1.414 rillig 222: } VarFlags;
1.228 rillig 223:
1.527 rillig 224: ENUM_FLAGS_RTTI_6(VarFlags,
225: VAR_IN_USE, VAR_FROM_ENV,
1.471 rillig 226: VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY);
1.430 rillig 227:
1.570 rillig 228: /* Variables are defined using one of the VAR=value assignments. Their
229: * value can be queried by expressions such as $V, ${VAR}, or with modifiers
230: * such as ${VAR:S,from,to,g:Q}.
231: *
232: * There are 3 kinds of variables: context variables, environment variables,
233: * undefined variables.
234: *
235: * Context variables are stored in a GNode.context. The only way to undefine
236: * a context variable is using the .undef directive. In particular, it must
237: * not be possible to undefine a variable during the evaluation of an
238: * expression, or Var.name might point nowhere.
239: *
240: * Environment variables are temporary. They are returned by VarFind, and
241: * after using them, they must be freed using VarFreeEnv.
242: *
243: * Undefined variables occur during evaluation of variable expressions such
244: * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
245: */
1.1 cgd 246: typedef struct Var {
1.570 rillig 247: /* The name of the variable, once set, doesn't change anymore.
1.576 rillig 248: * For context variables, it aliases the corresponding HashEntry name.
1.570 rillig 249: * For environment and undefined variables, it is allocated. */
250: const char *name;
251: void *name_freeIt;
252:
1.138 dsl 253: Buffer val; /* its value */
1.546 rillig 254: VarFlags flags; /* miscellaneous status flags */
1.417 rillig 255: } Var;
1.1 cgd 256:
1.118 sjg 257: /*
258: * Exporting vars is expensive so skip it if we can
259: */
1.578 rillig 260: typedef enum VarExportedMode {
1.292 rillig 261: VAR_EXPORTED_NONE,
1.602 rillig 262: VAR_EXPORTED_SOME,
1.292 rillig 263: VAR_EXPORTED_ALL
264: } VarExportedMode;
1.421 rillig 265:
1.292 rillig 266: static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
267:
1.578 rillig 268: typedef enum VarExportFlags {
1.292 rillig 269: /*
270: * We pass this to Var_Export when doing the initial export
271: * or after updating an exported var.
272: */
273: VAR_EXPORT_PARENT = 0x01,
274: /*
275: * We pass this to Var_Export1 to tell it to leave the value alone.
276: */
277: VAR_EXPORT_LITERAL = 0x02
278: } VarExportFlags;
1.16 christos 279:
1.261 rillig 280: /* Flags for pattern matching in the :S and :C modifiers */
1.578 rillig 281: typedef enum VarPatternFlags {
1.604 rillig 282: VARP_SUB_GLOBAL = 0x01, /* Replace as often as possible ('g') */
283: VARP_SUB_ONE = 0x02, /* Replace only once ('1') */
284: VARP_ANCHOR_START = 0x04, /* Match at start of word ('^') */
285: VARP_ANCHOR_END = 0x08 /* Match at end of word ('$') */
1.261 rillig 286: } VarPatternFlags;
1.16 christos 287:
1.569 rillig 288: static Var *
1.570 rillig 289: VarNew(const char *name, void *name_freeIt, const char *value, VarFlags flags)
1.569 rillig 290: {
291: size_t value_len = strlen(value);
292: Var *var = bmake_malloc(sizeof *var);
293: var->name = name;
1.570 rillig 294: var->name_freeIt = name_freeIt;
1.569 rillig 295: Buf_Init(&var->val, value_len + 1);
296: Buf_AddBytes(&var->val, value, value_len);
297: var->flags = flags;
298: return var;
299: }
300:
1.580 rillig 301: static const char *
302: CanonicalVarname(const char *name)
1.1 cgd 303: {
1.493 rillig 304: if (*name == '.' && ch_isupper(name[1])) {
1.242 rillig 305: switch (name[1]) {
306: case 'A':
1.257 rillig 307: if (strcmp(name, ".ALLSRC") == 0)
1.242 rillig 308: name = ALLSRC;
1.257 rillig 309: if (strcmp(name, ".ARCHIVE") == 0)
1.242 rillig 310: name = ARCHIVE;
311: break;
312: case 'I':
1.257 rillig 313: if (strcmp(name, ".IMPSRC") == 0)
1.242 rillig 314: name = IMPSRC;
315: break;
316: case 'M':
1.257 rillig 317: if (strcmp(name, ".MEMBER") == 0)
1.242 rillig 318: name = MEMBER;
319: break;
320: case 'O':
1.257 rillig 321: if (strcmp(name, ".OODATE") == 0)
1.242 rillig 322: name = OODATE;
323: break;
324: case 'P':
1.257 rillig 325: if (strcmp(name, ".PREFIX") == 0)
1.242 rillig 326: name = PREFIX;
327: break;
1.457 sjg 328: case 'S':
1.580 rillig 329: if (strcmp(name, ".SHELL") == 0) {
1.457 sjg 330: if (!shellPath)
331: Shell_Init();
332: }
333: break;
1.242 rillig 334: case 'T':
1.257 rillig 335: if (strcmp(name, ".TARGET") == 0)
1.242 rillig 336: name = TARGET;
337: break;
338: }
339: }
340:
1.580 rillig 341: /* GNU make has an additional alias $^ == ${.ALLSRC}. */
342:
343: return name;
344: }
345:
1.587 rillig 346: static Var *
347: GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash)
348: {
1.588 rillig 349: return HashTable_FindValueHash(&ctxt->context, varname, hash);
1.587 rillig 350: }
351:
1.605 rillig 352: /* Find the variable in the context, and maybe in other contexts as well.
1.580 rillig 353: *
354: * Input:
1.607 rillig 355: * name name to find, is not expanded any further
1.605 rillig 356: * ctxt context in which to look first
357: * elsewhere TRUE to look in other contexts as well
1.580 rillig 358: *
359: * Results:
1.605 rillig 360: * The found variable, or NULL if the variable does not exist.
361: * If the variable is an environment variable, it must be freed using
362: * VarFreeEnv after use.
1.580 rillig 363: */
364: static Var *
1.596 rillig 365: VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
1.580 rillig 366: {
367: Var *var;
1.586 rillig 368: unsigned int nameHash;
1.580 rillig 369:
370: /*
371: * If the variable name begins with a '.', it could very well be one of
372: * the local ones. We check the name against all the local variables
373: * and substitute the short version in for 'name' if it matches one of
374: * them.
375: */
376: name = CanonicalVarname(name);
1.586 rillig 377: nameHash = Hash_Hash(name);
1.160 christos 378:
1.605 rillig 379: /* First look for the variable in the given context. */
1.587 rillig 380: var = GNode_FindVar(ctxt, name, nameHash);
1.597 rillig 381: if (!elsewhere)
1.599 rillig 382: return var;
1.1 cgd 383:
1.605 rillig 384: /* The variable was not found in the given context. Now look for it in
385: * the other contexts as well. */
1.597 rillig 386: if (var == NULL && ctxt != VAR_CMDLINE)
1.594 rillig 387: var = GNode_FindVar(VAR_CMDLINE, name, nameHash);
1.399 rillig 388:
1.597 rillig 389: if (!opts.checkEnvFirst && var == NULL && ctxt != VAR_GLOBAL) {
1.587 rillig 390: var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
1.231 rillig 391: if (var == NULL && ctxt != VAR_INTERNAL) {
1.184 sjg 392: /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
1.587 rillig 393: var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
1.184 sjg 394: }
1.1 cgd 395: }
1.399 rillig 396:
1.597 rillig 397: if (var == NULL) {
1.1 cgd 398: char *env;
399:
1.570 rillig 400: if ((env = getenv(name)) != NULL) {
401: char *varname = bmake_strdup(name);
402: return VarNew(varname, varname, env, VAR_FROM_ENV);
403: }
1.399 rillig 404:
1.597 rillig 405: if (opts.checkEnvFirst && ctxt != VAR_GLOBAL) {
1.587 rillig 406: var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
1.399 rillig 407: if (var == NULL && ctxt != VAR_INTERNAL)
1.587 rillig 408: var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
1.542 rillig 409: return var;
1.1 cgd 410: }
1.399 rillig 411:
412: return NULL;
413: }
414:
1.542 rillig 415: return var;
1.1 cgd 416: }
417:
1.605 rillig 418: /* If the variable is an environment variable, free it.
1.105 christos 419: *
420: * Input:
421: * v the variable
1.605 rillig 422: * freeValue true if the variable value should be freed as well
1.105 christos 423: *
424: * Results:
1.400 rillig 425: * TRUE if it is an environment variable, FALSE otherwise.
1.105 christos 426: */
427: static Boolean
1.605 rillig 428: VarFreeEnv(Var *v, Boolean freeValue)
1.105 christos 429: {
1.257 rillig 430: if (!(v->flags & VAR_FROM_ENV))
1.105 christos 431: return FALSE;
1.605 rillig 432:
1.570 rillig 433: free(v->name_freeIt);
1.605 rillig 434: Buf_Destroy(&v->val, freeValue);
1.105 christos 435: free(v);
436: return TRUE;
437: }
438:
1.400 rillig 439: /* Add a new variable of the given name and value to the given context.
440: * The name and val arguments are duplicated so they may safely be freed. */
1.5 cgd 441: static void
1.464 rillig 442: VarAdd(const char *name, const char *val, GNode *ctxt, VarSet_Flags flags)
1.1 cgd 443: {
1.588 rillig 444: HashEntry *he = HashTable_CreateEntry(&ctxt->context, name, NULL);
1.605 rillig 445: Var *v = VarNew(he->key /* aliased */, NULL, val,
1.577 rillig 446: flags & VAR_SET_READONLY ? VAR_READONLY : 0);
1.588 rillig 447: HashEntry_Set(he, v);
1.547 rillig 448: if (!(ctxt->flags & INTERNAL)) {
449: VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
450: }
1.1 cgd 451: }
452:
1.607 rillig 453: /* Remove a variable from a context, freeing all related memory as well.
454: * The variable name is expanded once. */
1.1 cgd 455: void
1.73 christos 456: Var_Delete(const char *name, GNode *ctxt)
1.1 cgd 457: {
1.397 rillig 458: char *name_freeIt = NULL;
1.576 rillig 459: HashEntry *he;
1.412 rillig 460:
1.533 rillig 461: if (strchr(name, '$') != NULL) {
462: (void)Var_Subst(name, VAR_GLOBAL, VARE_WANTRES, &name_freeIt);
463: /* TODO: handle errors */
464: name = name_freeIt;
465: }
1.588 rillig 466: he = HashTable_FindEntry(&ctxt->context, name);
1.547 rillig 467: VAR_DEBUG3("%s:delete %s%s\n",
468: ctxt->name, name, he != NULL ? "" : " (not found)");
1.397 rillig 469: free(name_freeIt);
470:
1.414 rillig 471: if (he != NULL) {
1.588 rillig 472: Var *v = HashEntry_Get(he);
1.292 rillig 473: if (v->flags & VAR_EXPORTED)
1.118 sjg 474: unsetenv(v->name);
1.420 rillig 475: if (strcmp(v->name, MAKE_EXPORTED) == 0)
1.155 sjg 476: var_exportedVars = VAR_EXPORTED_NONE;
1.570 rillig 477: assert(v->name_freeIt == NULL);
1.588 rillig 478: HashTable_DeleteEntry(&ctxt->context, he);
1.146 dsl 479: Buf_Destroy(&v->val, TRUE);
1.98 christos 480: free(v);
1.1 cgd 481: }
482: }
483:
1.421 rillig 484: static Boolean
1.598 rillig 485: MayExport(const char *name)
1.118 sjg 486: {
1.422 rillig 487: if (name[0] == '.')
1.421 rillig 488: return FALSE; /* skip internals */
1.567 rillig 489: if (name[0] == '-')
490: return FALSE; /* skip misnamed variables */
1.422 rillig 491: if (name[1] == '\0') {
1.118 sjg 492: /*
493: * A single char.
494: * If it is one of the vars that should only appear in
495: * local context, skip it, else we can get Var_Subst
496: * into a loop.
497: */
498: switch (name[0]) {
499: case '@':
500: case '%':
501: case '*':
502: case '!':
1.421 rillig 503: return FALSE;
1.118 sjg 504: }
505: }
1.598 rillig 506: return TRUE;
507: }
508:
509: /*
510: * Export a single variable.
511: * We ignore make internal variables (those which start with '.').
512: * Also we jump through some hoops to avoid calling setenv
513: * more than necessary since it can leak.
514: * We only manipulate flags of vars if 'parent' is set.
515: */
516: static Boolean
517: Var_Export1(const char *name, VarExportFlags flags)
518: {
519: VarExportFlags parent = flags & VAR_EXPORT_PARENT;
520: Var *v;
521: char *val;
522:
523: if (!MayExport(name))
524: return FALSE;
1.401 rillig 525:
1.412 rillig 526: v = VarFind(name, VAR_GLOBAL, 0);
1.257 rillig 527: if (v == NULL)
1.421 rillig 528: return FALSE;
1.401 rillig 529:
1.372 rillig 530: if (!parent && (v->flags & VAR_EXPORTED) && !(v->flags & VAR_REEXPORT))
1.421 rillig 531: return FALSE; /* nothing to do */
1.401 rillig 532:
1.433 rillig 533: val = Buf_GetAll(&v->val, NULL);
1.422 rillig 534: if (!(flags & VAR_EXPORT_LITERAL) && strchr(val, '$') != NULL) {
1.446 rillig 535: char *expr;
1.412 rillig 536:
1.152 sjg 537: if (parent) {
1.118 sjg 538: /*
1.605 rillig 539: * Flag the variable as something we need to re-export.
1.118 sjg 540: * No point actually exporting it now though,
1.605 rillig 541: * the child process can do it at the last minute.
1.118 sjg 542: */
1.365 rillig 543: v->flags |= VAR_EXPORTED | VAR_REEXPORT;
1.421 rillig 544: return TRUE;
1.118 sjg 545: }
1.158 sjg 546: if (v->flags & VAR_IN_USE) {
547: /*
548: * We recursed while exporting in a child.
549: * This isn't going to end well, just skip it.
550: */
1.421 rillig 551: return FALSE;
1.158 sjg 552: }
1.446 rillig 553:
1.607 rillig 554: /* XXX: name is injected without escaping it */
1.446 rillig 555: expr = str_concat3("${", name, "}");
1.533 rillig 556: (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &val);
557: /* TODO: handle errors */
1.446 rillig 558: setenv(name, val, 1);
559: free(val);
560: free(expr);
1.118 sjg 561: } else {
1.292 rillig 562: if (parent)
1.448 rillig 563: v->flags &= ~(unsigned)VAR_REEXPORT; /* once will do */
1.292 rillig 564: if (parent || !(v->flags & VAR_EXPORTED))
1.118 sjg 565: setenv(name, val, 1);
566: }
1.605 rillig 567:
1.118 sjg 568: /*
569: * This is so Var_Set knows to call Var_Export again...
570: */
1.152 sjg 571: if (parent) {
572: v->flags |= VAR_EXPORTED;
573: }
1.421 rillig 574: return TRUE;
1.118 sjg 575: }
576:
577: /*
1.605 rillig 578: * This gets called from our child processes.
1.118 sjg 579: */
580: void
581: Var_ExportVars(void)
582: {
1.412 rillig 583: char *val;
584:
1.182 christos 585: /*
586: * Several make's support this sort of mechanism for tracking
587: * recursion - but each uses a different name.
588: * We allow the makefiles to update MAKELEVEL and ensure
589: * children see a correctly incremented value.
590: */
1.401 rillig 591: char tmp[BUFSIZ];
1.182 christos 592: snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
593: setenv(MAKE_LEVEL_ENV, tmp, 1);
594:
1.420 rillig 595: if (var_exportedVars == VAR_EXPORTED_NONE)
1.118 sjg 596: return;
597:
1.420 rillig 598: if (var_exportedVars == VAR_EXPORTED_ALL) {
1.599 rillig 599: HashIter hi;
1.575 rillig 600:
601: /* Ouch! Exporting all variables at once is crazy... */
602: HashIter_Init(&hi, &VAR_GLOBAL->context);
1.603 rillig 603: while (HashIter_Next(&hi) != NULL) {
604: Var *var = hi.entry->value;
1.575 rillig 605: Var_Export1(var->name, 0);
606: }
1.118 sjg 607: return;
608: }
1.369 rillig 609:
1.533 rillig 610: (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES, &val);
611: /* TODO: handle errors */
1.369 rillig 612: if (*val) {
1.494 rillig 613: Words words = Str_Words(val, FALSE);
1.465 rillig 614: size_t i;
1.142 dsl 615:
1.479 rillig 616: for (i = 0; i < words.len; i++)
617: Var_Export1(words.words[i], 0);
618: Words_Free(words);
1.118 sjg 619: }
1.369 rillig 620: free(val);
1.118 sjg 621: }
622:
623: /*
1.400 rillig 624: * This is called when .export is seen or .MAKE.EXPORTED is modified.
1.441 rillig 625: *
1.400 rillig 626: * It is also called when any exported variable is modified.
1.441 rillig 627: * XXX: Is it really?
628: *
629: * str has the format "[-env|-literal] varname...".
1.118 sjg 630: */
631: void
1.441 rillig 632: Var_Export(const char *str, Boolean isExport)
1.118 sjg 633: {
1.412 rillig 634: VarExportFlags flags;
635: char *val;
636:
1.422 rillig 637: if (isExport && str[0] == '\0') {
1.118 sjg 638: var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
639: return;
640: }
641:
1.567 rillig 642: if (isExport && strncmp(str, "-env", 4) == 0) {
1.159 sjg 643: str += 4;
1.571 rillig 644: flags = 0;
1.567 rillig 645: } else if (isExport && strncmp(str, "-literal", 8) == 0) {
1.203 sjg 646: str += 8;
1.567 rillig 647: flags = VAR_EXPORT_LITERAL;
1.159 sjg 648: } else {
1.567 rillig 649: flags = VAR_EXPORT_PARENT;
1.159 sjg 650: }
1.302 rillig 651:
1.533 rillig 652: (void)Var_Subst(str, VAR_GLOBAL, VARE_WANTRES, &val);
653: /* TODO: handle errors */
1.422 rillig 654: if (val[0] != '\0') {
1.494 rillig 655: Words words = Str_Words(val, FALSE);
1.401 rillig 656:
1.465 rillig 657: size_t i;
1.479 rillig 658: for (i = 0; i < words.len; i++) {
659: const char *name = words.words[i];
1.203 sjg 660: if (Var_Export1(name, flags)) {
1.602 rillig 661: if (var_exportedVars == VAR_EXPORTED_NONE)
662: var_exportedVars = VAR_EXPORTED_SOME;
1.203 sjg 663: if (isExport && (flags & VAR_EXPORT_PARENT)) {
1.200 sjg 664: Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
665: }
1.118 sjg 666: }
667: }
1.479 rillig 668: Words_Free(words);
1.118 sjg 669: }
670: free(val);
671: }
672:
1.155 sjg 673:
1.257 rillig 674: extern char **environ;
675:
1.155 sjg 676: /*
677: * This is called when .unexport[-env] is seen.
1.338 rillig 678: *
679: * str must have the form "unexport[-env] varname...".
1.155 sjg 680: */
681: void
1.423 rillig 682: Var_UnExport(const char *str)
1.155 sjg 683: {
1.423 rillig 684: const char *varnames;
685: char *varnames_freeIt;
1.412 rillig 686: Boolean unexport_env;
1.155 sjg 687:
1.423 rillig 688: varnames = NULL;
689: varnames_freeIt = NULL;
1.155 sjg 690:
1.338 rillig 691: str += strlen("unexport");
1.412 rillig 692: unexport_env = strncmp(str, "-env", 4) == 0;
1.155 sjg 693: if (unexport_env) {
1.423 rillig 694: const char *cp;
1.155 sjg 695: char **newenv;
696:
1.179 sjg 697: cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */
1.170 sjg 698: if (environ == savedEnv) {
1.155 sjg 699: /* we have been here before! */
700: newenv = bmake_realloc(environ, 2 * sizeof(char *));
701: } else {
1.170 sjg 702: if (savedEnv) {
703: free(savedEnv);
704: savedEnv = NULL;
1.155 sjg 705: }
706: newenv = bmake_malloc(2 * sizeof(char *));
707: }
1.423 rillig 708:
1.155 sjg 709: /* Note: we cannot safely free() the original environ. */
1.170 sjg 710: environ = savedEnv = newenv;
1.155 sjg 711: newenv[0] = NULL;
712: newenv[1] = NULL;
1.221 sjg 713: if (cp && *cp)
714: setenv(MAKE_LEVEL_ENV, cp, 1);
1.155 sjg 715: } else {
1.567 rillig 716: cpp_skip_whitespace(&str);
1.423 rillig 717: if (str[0] != '\0')
718: varnames = str;
1.155 sjg 719: }
720:
1.423 rillig 721: if (varnames == NULL) {
1.155 sjg 722: /* Using .MAKE.EXPORTED */
1.533 rillig 723: (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES,
724: &varnames_freeIt);
725: /* TODO: handle errors */
726: varnames = varnames_freeIt;
1.155 sjg 727: }
1.423 rillig 728:
1.477 rillig 729: {
1.155 sjg 730: Var *v;
1.465 rillig 731: size_t i;
1.155 sjg 732:
1.479 rillig 733: Words words = Str_Words(varnames, FALSE);
734: for (i = 0; i < words.len; i++) {
735: const char *varname = words.words[i];
736: v = VarFind(varname, VAR_GLOBAL, 0);
1.423 rillig 737: if (v == NULL) {
1.547 rillig 738: VAR_DEBUG1("Not unexporting \"%s\" (not found)\n", varname);
1.155 sjg 739: continue;
1.423 rillig 740: }
741:
1.547 rillig 742: VAR_DEBUG1("Unexporting \"%s\"\n", varname);
1.423 rillig 743: if (!unexport_env && (v->flags & VAR_EXPORTED) &&
744: !(v->flags & VAR_REEXPORT))
1.155 sjg 745: unsetenv(v->name);
1.448 rillig 746: v->flags &= ~(unsigned)(VAR_EXPORTED | VAR_REEXPORT);
1.423 rillig 747:
1.155 sjg 748: /*
749: * If we are unexporting a list,
750: * remove each one from .MAKE.EXPORTED.
751: * If we are removing them all,
752: * just delete .MAKE.EXPORTED below.
753: */
1.423 rillig 754: if (varnames == str) {
1.614 rillig 755: /* XXX: v->name is injected without escaping it */
1.446 rillig 756: char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}");
1.533 rillig 757: char *cp;
758: (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp);
759: /* TODO: handle errors */
1.446 rillig 760: Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL);
761: free(cp);
762: free(expr);
1.155 sjg 763: }
764: }
1.479 rillig 765: Words_Free(words);
1.423 rillig 766: if (varnames != str) {
1.155 sjg 767: Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
1.423 rillig 768: free(varnames_freeIt);
1.155 sjg 769: }
770: }
771: }
772:
1.400 rillig 773: /* See Var_Set for documentation. */
1.457 sjg 774: void
1.242 rillig 775: Var_Set_with_flags(const char *name, const char *val, GNode *ctxt,
776: VarSet_Flags flags)
1.1 cgd 777: {
1.458 rillig 778: const char *unexpanded_name = name;
1.370 rillig 779: char *name_freeIt = NULL;
1.412 rillig 780: Var *v;
1.142 dsl 781:
1.460 rillig 782: assert(val != NULL);
783:
1.533 rillig 784: if (strchr(name, '$') != NULL) {
785: (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
786: /* TODO: handle errors */
787: name = name_freeIt;
788: }
1.458 rillig 789:
790: if (name[0] == '\0') {
1.547 rillig 791: VAR_DEBUG2("Var_Set(\"%s\", \"%s\", ...) "
792: "name expands to empty string - ignored\n",
793: unexpanded_name, val);
1.458 rillig 794: free(name_freeIt);
795: return;
1.139 dsl 796: }
1.400 rillig 797:
1.129 sjg 798: if (ctxt == VAR_GLOBAL) {
1.594 rillig 799: v = VarFind(name, VAR_CMDLINE, 0);
1.136 dsl 800: if (v != NULL) {
1.371 rillig 801: if (v->flags & VAR_FROM_CMD) {
1.547 rillig 802: VAR_DEBUG3("%s:%s = %s ignored!\n", ctxt->name, name, val);
1.131 sjg 803: goto out;
804: }
805: VarFreeEnv(v, TRUE);
1.129 sjg 806: }
807: }
1.400 rillig 808:
1.582 rillig 809: /*
810: * We only look for a variable in the given context since anything set
811: * here will override anything in a lower context, so there's not much
812: * point in searching them all just to save a bit of memory...
813: */
1.92 christos 814: v = VarFind(name, ctxt, 0);
1.136 dsl 815: if (v == NULL) {
1.594 rillig 816: if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT)) {
1.183 sjg 817: /*
818: * This var would normally prevent the same name being added
819: * to VAR_GLOBAL, so delete it from there if needed.
820: * Otherwise -V name may show the wrong value.
821: */
1.607 rillig 822: /* XXX: name is expanded for the second time */
1.183 sjg 823: Var_Delete(name, VAR_GLOBAL);
824: }
1.464 rillig 825: VarAdd(name, val, ctxt, flags);
1.1 cgd 826: } else {
1.457 sjg 827: if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) {
1.547 rillig 828: VAR_DEBUG3("%s:%s = %s ignored (read-only)\n",
829: ctxt->name, name, val);
1.457 sjg 830: goto out;
1.599 rillig 831: }
1.146 dsl 832: Buf_Empty(&v->val);
1.608 rillig 833: Buf_AddStr(&v->val, val);
1.1 cgd 834:
1.547 rillig 835: VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
1.371 rillig 836: if (v->flags & VAR_EXPORTED) {
1.152 sjg 837: Var_Export1(name, VAR_EXPORT_PARENT);
1.118 sjg 838: }
1.1 cgd 839: }
840: /*
841: * Any variables given on the command line are automatically exported
842: * to the environment (as per POSIX standard)
1.457 sjg 843: * Other than internals.
1.1 cgd 844: */
1.594 rillig 845: if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT) && name[0] != '.') {
1.608 rillig 846: if (v == NULL)
847: v = VarFind(name, ctxt, 0); /* we just added it */
848: v->flags |= VAR_FROM_CMD;
849:
1.71 thorpej 850: /*
851: * If requested, don't export these in the environment
852: * individually. We still put them in MAKEOVERRIDES so
853: * that the command-line settings continue to override
854: * Makefile settings.
855: */
1.590 rillig 856: if (!opts.varNoExportEnv)
1.613 rillig 857: setenv(name, val, 1);
1.62 sjg 858:
1.64 sjg 859: Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
1.1 cgd 860: }
1.593 rillig 861: if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
1.292 rillig 862: save_dollars = s2Boolean(val, save_dollars);
1.205 sjg 863:
1.242 rillig 864: out:
1.370 rillig 865: free(name_freeIt);
1.136 dsl 866: if (v != NULL)
1.107 christos 867: VarFreeEnv(v, TRUE);
1.1 cgd 868: }
869:
870: /*-
871: *-----------------------------------------------------------------------
1.230 rillig 872: * Var_Set --
873: * Set the variable name to the value val in the given context.
874: *
1.483 rillig 875: * If the variable doesn't yet exist, it is created.
876: * Otherwise the new value overwrites and replaces the old value.
877: *
1.230 rillig 878: * Input:
1.607 rillig 879: * name name of the variable to set, is expanded once
1.230 rillig 880: * val value to give to the variable
881: * ctxt context in which to set it
882: *
883: * Notes:
884: * The variable is searched for only in its context before being
885: * created in that context. I.e. if the context is VAR_GLOBAL,
1.594 rillig 886: * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMDLINE,
887: * only VAR_CMDLINE->context is searched. This is done to avoid the
888: * literally thousands of unnecessary strcmp's that used to be done to
1.230 rillig 889: * set, say, $(@) or $(<).
890: * If the context is VAR_GLOBAL though, we check if the variable
1.594 rillig 891: * was set in VAR_CMDLINE from the command line and skip it if so.
1.230 rillig 892: *-----------------------------------------------------------------------
893: */
894: void
895: Var_Set(const char *name, const char *val, GNode *ctxt)
896: {
1.242 rillig 897: Var_Set_with_flags(name, val, ctxt, 0);
1.230 rillig 898: }
899:
900: /*-
901: *-----------------------------------------------------------------------
1.1 cgd 902: * Var_Append --
903: * The variable of the given name has the given value appended to it in
904: * the given context.
905: *
1.483 rillig 906: * If the variable doesn't exist, it is created. Otherwise the strings
907: * are concatenated, with a space in between.
908: *
1.70 wiz 909: * Input:
1.607 rillig 910: * name name of the variable to modify, is expanded once
1.400 rillig 911: * val string to append to it
912: * ctxt context in which this should occur
1.70 wiz 913: *
1.1 cgd 914: * Notes:
915: * Only if the variable is being sought in the global context is the
916: * environment searched.
917: * XXX: Knows its calling circumstances in that if called with ctxt
918: * an actual target, it will only search that context since only
919: * a local variable could be being appended to. This is actually
920: * a big win and must be tolerated.
921: *-----------------------------------------------------------------------
922: */
923: void
1.73 christos 924: Var_Append(const char *name, const char *val, GNode *ctxt)
1.1 cgd 925: {
1.427 rillig 926: char *name_freeIt = NULL;
1.412 rillig 927: Var *v;
1.1 cgd 928:
1.460 rillig 929: assert(val != NULL);
930:
1.139 dsl 931: if (strchr(name, '$') != NULL) {
1.456 rillig 932: const char *unexpanded_name = name;
1.533 rillig 933: (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
934: /* TODO: handle errors */
935: name = name_freeIt;
1.427 rillig 936: if (name[0] == '\0') {
1.547 rillig 937: VAR_DEBUG2("Var_Append(\"%s\", \"%s\", ...) "
1.599 rillig 938: "name expands to empty string - ignored\n",
939: unexpanded_name, val);
1.427 rillig 940: free(name_freeIt);
1.139 dsl 941: return;
942: }
943: }
1.142 dsl 944:
1.596 rillig 945: v = VarFind(name, ctxt, ctxt == VAR_GLOBAL);
1.1 cgd 946:
1.136 dsl 947: if (v == NULL) {
1.607 rillig 948: /* XXX: name is expanded for the second time */
1.230 rillig 949: Var_Set(name, val, ctxt);
1.600 rillig 950: } else if (v->flags & VAR_READONLY) {
1.614 rillig 951: VAR_DEBUG1("Ignoring append to %s since it is read-only\n", name);
1.594 rillig 952: } else if (ctxt == VAR_CMDLINE || !(v->flags & VAR_FROM_CMD)) {
1.146 dsl 953: Buf_AddByte(&v->val, ' ');
1.313 rillig 954: Buf_AddStr(&v->val, val);
1.1 cgd 955:
1.547 rillig 956: VAR_DEBUG3("%s:%s = %s\n",
1.599 rillig 957: ctxt->name, name, Buf_GetAll(&v->val, NULL));
1.1 cgd 958:
959: if (v->flags & VAR_FROM_ENV) {
1.576 rillig 960: HashEntry *h;
1.412 rillig 961:
1.1 cgd 962: /*
963: * If the original variable came from the environment, we
964: * have to install it in the global context (we could place
965: * it in the environment, but then we should provide a way to
966: * export other variables...)
967: */
1.448 rillig 968: v->flags &= ~(unsigned)VAR_FROM_ENV;
1.588 rillig 969: h = HashTable_CreateEntry(&ctxt->context, name, NULL);
970: HashEntry_Set(h, v);
1.1 cgd 971: }
972: }
1.427 rillig 973: free(name_freeIt);
1.1 cgd 974: }
975:
1.483 rillig 976: /* See if the given variable exists, in the given context or in other
977: * fallback contexts.
1.1 cgd 978: *
1.70 wiz 979: * Input:
1.607 rillig 980: * name Variable to find, is expanded once
1.70 wiz 981: * ctxt Context in which to start search
1.1 cgd 982: */
983: Boolean
1.73 christos 984: Var_Exists(const char *name, GNode *ctxt)
1.1 cgd 985: {
1.373 rillig 986: char *name_freeIt = NULL;
1.412 rillig 987: Var *v;
988:
1.533 rillig 989: if (strchr(name, '$') != NULL) {
990: (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
991: /* TODO: handle errors */
992: name = name_freeIt;
993: }
1.1 cgd 994:
1.596 rillig 995: v = VarFind(name, ctxt, TRUE);
1.373 rillig 996: free(name_freeIt);
1.257 rillig 997: if (v == NULL)
1.231 rillig 998: return FALSE;
999:
1000: (void)VarFreeEnv(v, TRUE);
1001: return TRUE;
1.1 cgd 1002: }
1003:
1004: /*-
1005: *-----------------------------------------------------------------------
1006: * Var_Value --
1.337 rillig 1007: * Return the unexpanded value of the given variable in the given
1.374 rillig 1008: * context, or the usual contexts.
1.1 cgd 1009: *
1.70 wiz 1010: * Input:
1.607 rillig 1011: * name name to find, is not expanded any further
1.70 wiz 1012: * ctxt context in which to search for it
1013: *
1.1 cgd 1014: * Results:
1.337 rillig 1015: * The value if the variable exists, NULL if it doesn't.
1.632 rillig 1016: * If the returned value is not NULL, the caller must free
1017: * out_freeIt when the returned value is no longer needed.
1.1 cgd 1018: *-----------------------------------------------------------------------
1019: */
1.375 rillig 1020: const char *
1.632 rillig 1021: Var_Value(const char *name, GNode *ctxt, void **out_freeIt)
1.1 cgd 1022: {
1.596 rillig 1023: Var *v = VarFind(name, ctxt, TRUE);
1.609 rillig 1024: char *value;
1.412 rillig 1025:
1.632 rillig 1026: *out_freeIt = NULL;
1.231 rillig 1027: if (v == NULL)
1.136 dsl 1028: return NULL;
1.231 rillig 1029:
1.609 rillig 1030: value = Buf_GetAll(&v->val, NULL);
1.231 rillig 1031: if (VarFreeEnv(v, FALSE))
1.632 rillig 1032: *out_freeIt = value;
1.609 rillig 1033: return value;
1.1 cgd 1034: }
1035:
1.616 rillig 1036: /* Return the unexpanded variable value from this node, without trying to look
1037: * up the variable in any other context. */
1038: const char *
1039: Var_ValueDirect(const char *name, GNode *ctxt)
1040: {
1041: Var *v = VarFind(name, ctxt, FALSE);
1042: return v != NULL ? Buf_GetAll(&v->val, NULL) : NULL;
1043: }
1044:
1.244 rillig 1045:
1.610 rillig 1046: /* SepBuf is a string being built from words, interleaved with separators. */
1.541 rillig 1047: typedef struct SepBuf {
1.278 rillig 1048: Buffer buf;
1049: Boolean needSep;
1.453 rillig 1050: char sep; /* usually ' ', but see the :ts modifier */
1.278 rillig 1051: } SepBuf;
1052:
1053: static void
1054: SepBuf_Init(SepBuf *buf, char sep)
1055: {
1.433 rillig 1056: Buf_Init(&buf->buf, 32 /* bytes */);
1.278 rillig 1057: buf->needSep = FALSE;
1058: buf->sep = sep;
1059: }
1060:
1061: static void
1062: SepBuf_Sep(SepBuf *buf)
1063: {
1064: buf->needSep = TRUE;
1065: }
1066:
1067: static void
1.314 rillig 1068: SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1.278 rillig 1069: {
1070: if (mem_size == 0)
1071: return;
1072: if (buf->needSep && buf->sep != '\0') {
1073: Buf_AddByte(&buf->buf, buf->sep);
1074: buf->needSep = FALSE;
1075: }
1.433 rillig 1076: Buf_AddBytes(&buf->buf, mem, mem_size);
1.278 rillig 1077: }
1078:
1.314 rillig 1079: static void
1080: SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end)
1081: {
1082: SepBuf_AddBytes(buf, start, (size_t)(end - start));
1083: }
1084:
1085: static void
1086: SepBuf_AddStr(SepBuf *buf, const char *str)
1087: {
1088: SepBuf_AddBytes(buf, str, strlen(str));
1089: }
1090:
1.278 rillig 1091: static char *
1092: SepBuf_Destroy(SepBuf *buf, Boolean free_buf)
1093: {
1094: return Buf_Destroy(&buf->buf, free_buf);
1095: }
1096:
1097:
1.609 rillig 1098: /* This callback for ModifyWords gets a single word from a variable expression
1099: * and typically adds a modification of this word to the buffer. It may also
1100: * do nothing or add several words.
1101: *
1102: * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for
1103: * each word of "a b c". */
1.295 rillig 1104: typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data);
1.244 rillig 1105:
1106:
1.291 rillig 1107: /* Callback for ModifyWords to implement the :H modifier.
1.244 rillig 1108: * Add the dirname of the given word to the buffer. */
1.278 rillig 1109: static void
1.295 rillig 1110: ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1111: {
1.238 rillig 1112: const char *slash = strrchr(word, '/');
1113: if (slash != NULL)
1.314 rillig 1114: SepBuf_AddBytesBetween(buf, word, slash);
1.238 rillig 1115: else
1.314 rillig 1116: SepBuf_AddStr(buf, ".");
1.1 cgd 1117: }
1118:
1.291 rillig 1119: /* Callback for ModifyWords to implement the :T modifier.
1.244 rillig 1120: * Add the basename of the given word to the buffer. */
1.278 rillig 1121: static void
1.295 rillig 1122: ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1123: {
1.238 rillig 1124: const char *slash = strrchr(word, '/');
1125: const char *base = slash != NULL ? slash + 1 : word;
1.314 rillig 1126: SepBuf_AddStr(buf, base);
1.1 cgd 1127: }
1128:
1.291 rillig 1129: /* Callback for ModifyWords to implement the :E modifier.
1.244 rillig 1130: * Add the filename suffix of the given word to the buffer, if it exists. */
1.278 rillig 1131: static void
1.295 rillig 1132: ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1133: {
1.239 rillig 1134: const char *dot = strrchr(word, '.');
1.278 rillig 1135: if (dot != NULL)
1.314 rillig 1136: SepBuf_AddStr(buf, dot + 1);
1.1 cgd 1137: }
1138:
1.291 rillig 1139: /* Callback for ModifyWords to implement the :R modifier.
1140: * Add the basename of the given word to the buffer. */
1.278 rillig 1141: static void
1.295 rillig 1142: ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1143: {
1.314 rillig 1144: const char *dot = strrchr(word, '.');
1.247 lukem 1145: size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1.278 rillig 1146: SepBuf_AddBytes(buf, word, len);
1.1 cgd 1147: }
1148:
1.291 rillig 1149: /* Callback for ModifyWords to implement the :M modifier.
1.244 rillig 1150: * Place the word in the buffer if it matches the given pattern. */
1.278 rillig 1151: static void
1.295 rillig 1152: ModifyWord_Match(const char *word, SepBuf *buf, void *data)
1.1 cgd 1153: {
1.244 rillig 1154: const char *pattern = data;
1.547 rillig 1155: VAR_DEBUG2("VarMatch [%s] [%s]\n", word, pattern);
1.278 rillig 1156: if (Str_Match(word, pattern))
1.314 rillig 1157: SepBuf_AddStr(buf, word);
1.1 cgd 1158: }
1159:
1.291 rillig 1160: /* Callback for ModifyWords to implement the :N modifier.
1161: * Place the word in the buffer if it doesn't match the given pattern. */
1162: static void
1.295 rillig 1163: ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
1.291 rillig 1164: {
1165: const char *pattern = data;
1166: if (!Str_Match(word, pattern))
1.314 rillig 1167: SepBuf_AddStr(buf, word);
1.291 rillig 1168: }
1169:
1.13 christos 1170: #ifdef SYSVVARSUB
1.610 rillig 1171: /* Check word against pattern for a match (% is a wildcard).
1.256 rillig 1172: *
1173: * Input:
1174: * word Word to examine
1175: * pattern Pattern to examine against
1176: *
1177: * Results:
1.377 rillig 1178: * Returns the start of the match, or NULL.
1.610 rillig 1179: * out_match_len returns the length of the match, if any.
1180: * out_hasPercent returns whether the pattern contains a percent.
1.256 rillig 1181: */
1.277 rillig 1182: static const char *
1.610 rillig 1183: SysVMatch(const char *word, const char *pattern,
1184: size_t *out_match_len, Boolean *out_hasPercent)
1.256 rillig 1185: {
1186: const char *p = pattern;
1187: const char *w = word;
1.412 rillig 1188: const char *percent;
1189: size_t w_len;
1190: size_t p_len;
1191: const char *w_tail;
1.256 rillig 1192:
1.610 rillig 1193: *out_hasPercent = FALSE;
1.412 rillig 1194: percent = strchr(p, '%');
1.377 rillig 1195: if (percent != NULL) { /* ${VAR:...%...=...} */
1.610 rillig 1196: *out_hasPercent = TRUE;
1.377 rillig 1197: if (*w == '\0')
1198: return NULL; /* empty word does not match pattern */
1199:
1.256 rillig 1200: /* check that the prefix matches */
1.377 rillig 1201: for (; p != percent && *w != '\0' && *w == *p; w++, p++)
1.417 rillig 1202: continue;
1.377 rillig 1203: if (p != percent)
1.256 rillig 1204: return NULL; /* No match */
1205:
1.377 rillig 1206: p++; /* Skip the percent */
1207: if (*p == '\0') {
1.256 rillig 1208: /* No more pattern, return the rest of the string */
1.610 rillig 1209: *out_match_len = strlen(w);
1.277 rillig 1210: return w;
1.256 rillig 1211: }
1212: }
1213:
1.378 rillig 1214: /* Test whether the tail matches */
1.412 rillig 1215: w_len = strlen(w);
1216: p_len = strlen(p);
1.378 rillig 1217: if (w_len < p_len)
1218: return NULL;
1.256 rillig 1219:
1.412 rillig 1220: w_tail = w + w_len - p_len;
1.378 rillig 1221: if (memcmp(p, w_tail, p_len) != 0)
1.380 rillig 1222: return NULL;
1.256 rillig 1223:
1.610 rillig 1224: *out_match_len = (size_t)(w_tail - w);
1.378 rillig 1225: return w;
1.256 rillig 1226: }
1227:
1.541 rillig 1228: struct ModifyWord_SYSVSubstArgs {
1.295 rillig 1229: GNode *ctx;
1.276 rillig 1230: const char *lhs;
1231: const char *rhs;
1.541 rillig 1232: };
1.276 rillig 1233:
1.291 rillig 1234: /* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1.278 rillig 1235: static void
1.295 rillig 1236: ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
1.5 cgd 1237: {
1.541 rillig 1238: const struct ModifyWord_SYSVSubstArgs *args = data;
1.412 rillig 1239: char *rhs_expanded;
1240: const char *rhs;
1241: const char *percent;
1.5 cgd 1242:
1.377 rillig 1243: size_t match_len;
1244: Boolean lhsPercent;
1.610 rillig 1245: const char *match = SysVMatch(word, args->lhs, &match_len, &lhsPercent);
1.379 rillig 1246: if (match == NULL) {
1.314 rillig 1247: SepBuf_AddStr(buf, word);
1.379 rillig 1248: return;
1249: }
1250:
1251: /* Append rhs to the buffer, substituting the first '%' with the
1252: * match, but only if the lhs had a '%' as well. */
1253:
1.533 rillig 1254: (void)Var_Subst(args->rhs, args->ctx, VARE_WANTRES, &rhs_expanded);
1255: /* TODO: handle errors */
1.379 rillig 1256:
1.412 rillig 1257: rhs = rhs_expanded;
1258: percent = strchr(rhs, '%');
1.379 rillig 1259:
1260: if (percent != NULL && lhsPercent) {
1261: /* Copy the prefix of the replacement pattern */
1262: SepBuf_AddBytesBetween(buf, rhs, percent);
1263: rhs = percent + 1;
1.61 explorer 1264: }
1.379 rillig 1265: if (percent != NULL || !lhsPercent)
1266: SepBuf_AddBytes(buf, match, match_len);
1267:
1268: /* Append the suffix of the replacement pattern */
1269: SepBuf_AddStr(buf, rhs);
1270:
1271: free(rhs_expanded);
1.5 cgd 1272: }
1.13 christos 1273: #endif
1.5 cgd 1274:
1.1 cgd 1275:
1.541 rillig 1276: struct ModifyWord_SubstArgs {
1.291 rillig 1277: const char *lhs;
1278: size_t lhsLen;
1279: const char *rhs;
1280: size_t rhsLen;
1281: VarPatternFlags pflags;
1.452 rillig 1282: Boolean matched;
1.541 rillig 1283: };
1.291 rillig 1284:
1285: /* Callback for ModifyWords to implement the :S,from,to, modifier.
1.244 rillig 1286: * Perform a string substitution on the given word. */
1.278 rillig 1287: static void
1.295 rillig 1288: ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
1.1 cgd 1289: {
1.279 rillig 1290: size_t wordLen = strlen(word);
1.541 rillig 1291: struct ModifyWord_SubstArgs *args = data;
1.412 rillig 1292: const char *match;
1.1 cgd 1293:
1.452 rillig 1294: if ((args->pflags & VARP_SUB_ONE) && args->matched)
1.279 rillig 1295: goto nosub;
1296:
1.288 rillig 1297: if (args->pflags & VARP_ANCHOR_START) {
1.282 rillig 1298: if (wordLen < args->lhsLen ||
1299: memcmp(word, args->lhs, args->lhsLen) != 0)
1.1 cgd 1300: goto nosub;
1.279 rillig 1301:
1.611 rillig 1302: if ((args->pflags & VARP_ANCHOR_END) && wordLen != args->lhsLen)
1303: goto nosub;
1304:
1305: /* :S,^prefix,replacement, or :S,^whole$,replacement, */
1306: SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1307: SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen);
1308: args->matched = TRUE;
1.278 rillig 1309: return;
1.1 cgd 1310: }
1.279 rillig 1311:
1.288 rillig 1312: if (args->pflags & VARP_ANCHOR_END) {
1.417 rillig 1313: const char *start;
1.412 rillig 1314:
1.281 rillig 1315: if (wordLen < args->lhsLen)
1.280 rillig 1316: goto nosub;
1.315 rillig 1317:
1.412 rillig 1318: start = word + (wordLen - args->lhsLen);
1.281 rillig 1319: if (memcmp(start, args->lhs, args->lhsLen) != 0)
1.279 rillig 1320: goto nosub;
1321:
1.476 rillig 1322: /* :S,suffix$,replacement, */
1.314 rillig 1323: SepBuf_AddBytesBetween(buf, word, start);
1.281 rillig 1324: SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1.452 rillig 1325: args->matched = TRUE;
1.279 rillig 1326: return;
1327: }
1328:
1.567 rillig 1329: if (args->lhs[0] == '\0')
1.571 rillig 1330: goto nosub;
1.567 rillig 1331:
1.424 rillig 1332: /* unanchored case, may match more than once */
1.567 rillig 1333: while ((match = strstr(word, args->lhs)) != NULL) {
1.315 rillig 1334: SepBuf_AddBytesBetween(buf, word, match);
1.281 rillig 1335: SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1.452 rillig 1336: args->matched = TRUE;
1.448 rillig 1337: wordLen -= (size_t)(match - word) + args->lhsLen;
1338: word += (size_t)(match - word) + args->lhsLen;
1.281 rillig 1339: if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL))
1.279 rillig 1340: break;
1341: }
1.242 rillig 1342: nosub:
1.278 rillig 1343: SepBuf_AddBytes(buf, word, wordLen);
1.1 cgd 1344: }
1345:
1.31 gwr 1346: #ifndef NO_REGEX
1.400 rillig 1347: /* Print the error caused by a regcomp or regexec call. */
1.16 christos 1348: static void
1.202 christos 1349: VarREError(int reerr, regex_t *pat, const char *str)
1.16 christos 1350: {
1.448 rillig 1351: size_t errlen = regerror(reerr, pat, 0, 0);
1.401 rillig 1352: char *errbuf = bmake_malloc(errlen);
1.202 christos 1353: regerror(reerr, pat, errbuf, errlen);
1.16 christos 1354: Error("%s: %s", str, errbuf);
1355: free(errbuf);
1356: }
1357:
1.541 rillig 1358: struct ModifyWord_SubstRegexArgs {
1.546 rillig 1359: regex_t re;
1360: size_t nsub;
1361: char *replace;
1.291 rillig 1362: VarPatternFlags pflags;
1.546 rillig 1363: Boolean matched;
1.541 rillig 1364: };
1.291 rillig 1365:
1366: /* Callback for ModifyWords to implement the :C/from/to/ modifier.
1.244 rillig 1367: * Perform a regex substitution on the given word. */
1.278 rillig 1368: static void
1.295 rillig 1369: ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data)
1.16 christos 1370: {
1.541 rillig 1371: struct ModifyWord_SubstRegexArgs *args = data;
1.16 christos 1372: int xrv;
1.253 rillig 1373: const char *wp = word;
1.16 christos 1374: char *rp;
1.20 christos 1375: int flags = 0;
1.305 rillig 1376: regmatch_t m[10];
1.16 christos 1377:
1.452 rillig 1378: if ((args->pflags & VARP_SUB_ONE) && args->matched)
1.307 rillig 1379: goto nosub;
1380:
1381: tryagain:
1382: xrv = regexec(&args->re, wp, args->nsub, m, flags);
1.16 christos 1383:
1384: switch (xrv) {
1385: case 0:
1.452 rillig 1386: args->matched = TRUE;
1.448 rillig 1387: SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1.16 christos 1388:
1.304 rillig 1389: for (rp = args->replace; *rp; rp++) {
1.278 rillig 1390: if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
1391: SepBuf_AddBytes(buf, rp + 1, 1);
1.16 christos 1392: rp++;
1.445 rillig 1393: continue;
1394: }
1395:
1396: if (*rp == '&') {
1397: SepBuf_AddBytesBetween(buf, wp + m[0].rm_so, wp + m[0].rm_eo);
1398: continue;
1399: }
1400:
1.493 rillig 1401: if (*rp != '\\' || !ch_isdigit(rp[1])) {
1.445 rillig 1402: SepBuf_AddBytes(buf, rp, 1);
1403: continue;
1404: }
1405:
1406: { /* \0 to \9 backreference */
1.448 rillig 1407: size_t n = (size_t)(rp[1] - '0');
1.445 rillig 1408: rp++;
1.16 christos 1409:
1.304 rillig 1410: if (n >= args->nsub) {
1.448 rillig 1411: Error("No subexpression \\%zu", n);
1.617 rillig 1412: } else if (m[n].rm_so == -1) {
1.448 rillig 1413: Error("No match for subexpression \\%zu", n);
1.242 rillig 1414: } else {
1.314 rillig 1415: SepBuf_AddBytesBetween(buf, wp + m[n].rm_so,
1416: wp + m[n].rm_eo);
1.16 christos 1417: }
1418: }
1419: }
1.445 rillig 1420:
1.305 rillig 1421: wp += m[0].rm_eo;
1.304 rillig 1422: if (args->pflags & VARP_SUB_GLOBAL) {
1.20 christos 1423: flags |= REG_NOTBOL;
1.305 rillig 1424: if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1.278 rillig 1425: SepBuf_AddBytes(buf, wp, 1);
1.20 christos 1426: wp++;
1427: }
1428: if (*wp)
1429: goto tryagain;
1430: }
1.16 christos 1431: if (*wp) {
1.314 rillig 1432: SepBuf_AddStr(buf, wp);
1.16 christos 1433: }
1434: break;
1435: default:
1.304 rillig 1436: VarREError(xrv, &args->re, "Unexpected regex error");
1.568 rillig 1437: /* FALLTHROUGH */
1.16 christos 1438: case REG_NOMATCH:
1.307 rillig 1439: nosub:
1.314 rillig 1440: SepBuf_AddStr(buf, wp);
1.16 christos 1441: break;
1442: }
1443: }
1.17 christos 1444: #endif
1.16 christos 1445:
1446:
1.541 rillig 1447: struct ModifyWord_LoopArgs {
1.295 rillig 1448: GNode *ctx;
1.291 rillig 1449: char *tvar; /* name of temporary variable */
1450: char *str; /* string to expand */
1451: VarEvalFlags eflags;
1.541 rillig 1452: };
1.291 rillig 1453:
1454: /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1.278 rillig 1455: static void
1.295 rillig 1456: ModifyWord_Loop(const char *word, SepBuf *buf, void *data)
1.40 sjg 1457: {
1.541 rillig 1458: const struct ModifyWord_LoopArgs *args;
1.412 rillig 1459: char *s;
1460:
1.278 rillig 1461: if (word[0] == '\0')
1462: return;
1463:
1.412 rillig 1464: args = data;
1.295 rillig 1465: Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT);
1.533 rillig 1466: (void)Var_Subst(args->str, args->ctx, args->eflags, &s);
1467: /* TODO: handle errors */
1.411 rillig 1468:
1.618 rillig 1469: VAR_DEBUG4("ModifyWord_Loop: "
1470: "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n",
1.547 rillig 1471: word, args->tvar, args->str, s);
1.64 sjg 1472:
1.544 rillig 1473: if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1.477 rillig 1474: buf->needSep = FALSE;
1475: SepBuf_AddStr(buf, s);
1.278 rillig 1476: free(s);
1.40 sjg 1477: }
1478:
1.81 sjg 1479:
1.619 rillig 1480: /* The :[first..last] modifier selects words from the expression.
1481: * It can also reverse the words. */
1.81 sjg 1482: static char *
1.449 rillig 1483: VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first,
1.301 rillig 1484: int last)
1.81 sjg 1485: {
1.479 rillig 1486: Words words;
1.583 rillig 1487: int len, start, end, step;
1.412 rillig 1488: int i;
1489:
1.278 rillig 1490: SepBuf buf;
1.401 rillig 1491: SepBuf_Init(&buf, sep);
1492:
1.301 rillig 1493: if (oneBigWord) {
1.479 rillig 1494: /* fake what Str_Words() would do if there were only one word */
1495: words.len = 1;
1496: words.words = bmake_malloc((words.len + 1) * sizeof(char *));
1497: words.freeIt = bmake_strdup(str);
1498: words.words[0] = words.freeIt;
1499: words.words[1] = NULL;
1.81 sjg 1500: } else {
1.479 rillig 1501: words = Str_Words(str, FALSE);
1.81 sjg 1502: }
1503:
1504: /*
1.400 rillig 1505: * Now sanitize the given range.
1506: * If first or last are negative, convert them to the positive equivalents
1507: * (-1 gets converted to ac, -2 gets converted to (ac - 1), etc.).
1.81 sjg 1508: */
1.583 rillig 1509: len = (int)words.len;
1.290 rillig 1510: if (first < 0)
1.583 rillig 1511: first += len + 1;
1.290 rillig 1512: if (last < 0)
1.583 rillig 1513: last += len + 1;
1.81 sjg 1514:
1515: /*
1516: * We avoid scanning more of the list than we need to.
1517: */
1.290 rillig 1518: if (first > last) {
1.583 rillig 1519: start = (first > len ? len : first) - 1;
1520: end = last < 1 ? 0 : last - 1;
1.81 sjg 1521: step = -1;
1522: } else {
1.583 rillig 1523: start = first < 1 ? 0 : first - 1;
1524: end = last > len ? len : last;
1.81 sjg 1525: step = 1;
1526: }
1527:
1.296 rillig 1528: for (i = start; (step < 0) == (i >= end); i += step) {
1.479 rillig 1529: SepBuf_AddStr(&buf, words.words[i]);
1.308 rillig 1530: SepBuf_Sep(&buf);
1.81 sjg 1531: }
1532:
1.479 rillig 1533: Words_Free(words);
1.81 sjg 1534:
1.278 rillig 1535: return SepBuf_Destroy(&buf, FALSE);
1.81 sjg 1536: }
1537:
1.156 sjg 1538:
1.291 rillig 1539: /* Callback for ModifyWords to implement the :tA modifier.
1.244 rillig 1540: * Replace each word with the result of realpath() if successful. */
1.278 rillig 1541: static void
1.295 rillig 1542: ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.156 sjg 1543: {
1.242 rillig 1544: struct stat st;
1545: char rbuf[MAXPATHLEN];
1.231 rillig 1546:
1.314 rillig 1547: const char *rp = cached_realpath(word, rbuf);
1.257 rillig 1548: if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1.242 rillig 1549: word = rp;
1.231 rillig 1550:
1.314 rillig 1551: SepBuf_AddStr(buf, word);
1.156 sjg 1552: }
1553:
1.619 rillig 1554: /* Modify each of the words of the passed string using the given function.
1.1 cgd 1555: *
1.70 wiz 1556: * Input:
1.278 rillig 1557: * str String whose words should be modified
1.291 rillig 1558: * modifyWord Function that modifies a single word
1.453 rillig 1559: * modifyWord_args Custom arguments for modifyWord
1.70 wiz 1560: *
1.1 cgd 1561: * Results:
1562: * A string of all the words modified appropriately.
1563: *-----------------------------------------------------------------------
1564: */
1565: static char *
1.619 rillig 1566: ModifyWords(const char *str,
1567: ModifyWordsCallback modifyWord, void *modifyWord_args,
1568: Boolean oneBigWord, char sep)
1.1 cgd 1569: {
1.412 rillig 1570: SepBuf result;
1.479 rillig 1571: Words words;
1.465 rillig 1572: size_t i;
1.412 rillig 1573:
1.316 rillig 1574: if (oneBigWord) {
1575: SepBuf_Init(&result, sep);
1.453 rillig 1576: modifyWord(str, &result, modifyWord_args);
1.316 rillig 1577: return SepBuf_Destroy(&result, FALSE);
1578: }
1579:
1.401 rillig 1580: SepBuf_Init(&result, sep);
1581:
1.479 rillig 1582: words = Str_Words(str, FALSE);
1.1 cgd 1583:
1.547 rillig 1584: VAR_DEBUG2("ModifyWords: split \"%s\" into %zu words\n", str, words.len);
1.255 rillig 1585:
1.479 rillig 1586: for (i = 0; i < words.len; i++) {
1587: modifyWord(words.words[i], &result, modifyWord_args);
1.545 rillig 1588: if (Buf_Len(&result.buf) > 0)
1.278 rillig 1589: SepBuf_Sep(&result);
1590: }
1.24 christos 1591:
1.479 rillig 1592: Words_Free(words);
1.15 christos 1593:
1.278 rillig 1594: return SepBuf_Destroy(&result, FALSE);
1.1 cgd 1595: }
1596:
1.35 christos 1597:
1.403 rillig 1598: static char *
1.479 rillig 1599: Words_JoinFree(Words words)
1.403 rillig 1600: {
1601: Buffer buf;
1.465 rillig 1602: size_t i;
1.412 rillig 1603:
1.433 rillig 1604: Buf_Init(&buf, 0);
1.403 rillig 1605:
1.479 rillig 1606: for (i = 0; i < words.len; i++) {
1.403 rillig 1607: if (i != 0)
1.442 rillig 1608: Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */
1.479 rillig 1609: Buf_AddStr(&buf, words.words[i]);
1.403 rillig 1610: }
1611:
1.479 rillig 1612: Words_Free(words);
1.403 rillig 1613:
1614: return Buf_Destroy(&buf, FALSE);
1615: }
1616:
1.319 rillig 1617: /* Remove adjacent duplicate words. */
1.55 christos 1618: static char *
1.73 christos 1619: VarUniq(const char *str)
1.55 christos 1620: {
1.479 rillig 1621: Words words = Str_Words(str, FALSE);
1.55 christos 1622:
1.480 rillig 1623: if (words.len > 1) {
1.465 rillig 1624: size_t i, j;
1.480 rillig 1625: for (j = 0, i = 1; i < words.len; i++)
1.482 rillig 1626: if (strcmp(words.words[i], words.words[j]) != 0 && (++j != i))
1627: words.words[j] = words.words[i];
1.480 rillig 1628: words.len = j + 1;
1.55 christos 1629: }
1630:
1.479 rillig 1631: return Words_JoinFree(words);
1.55 christos 1632: }
1633:
1634:
1.483 rillig 1635: /* Quote shell meta-characters and space characters in the string.
1636: * If quoteDollar is set, also quote and double any '$' characters. */
1.16 christos 1637: static char *
1.483 rillig 1638: VarQuote(const char *str, Boolean quoteDollar)
1.16 christos 1639: {
1.293 rillig 1640: Buffer buf;
1.433 rillig 1641: Buf_Init(&buf, 0);
1.193 christos 1642:
1643: for (; *str != '\0'; str++) {
1644: if (*str == '\n') {
1.293 rillig 1645: const char *newline = Shell_GetNewline();
1646: if (newline == NULL)
1647: newline = "\\\n";
1.313 rillig 1648: Buf_AddStr(&buf, newline);
1.193 christos 1649: continue;
1650: }
1.629 rillig 1651: if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str))
1.146 dsl 1652: Buf_AddByte(&buf, '\\');
1.193 christos 1653: Buf_AddByte(&buf, *str);
1.220 christos 1654: if (quoteDollar && *str == '$')
1.313 rillig 1655: Buf_AddStr(&buf, "\\$");
1.16 christos 1656: }
1.193 christos 1657:
1.628 rillig 1658: return Buf_Destroy(&buf, FALSE);
1.16 christos 1659: }
1660:
1.400 rillig 1661: /* Compute the 32-bit hash of the given string, using the MurmurHash3
1662: * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */
1.163 joerg 1663: static char *
1.252 rillig 1664: VarHash(const char *str)
1.163 joerg 1665: {
1666: static const char hexdigits[16] = "0123456789abcdef";
1.252 rillig 1667: const unsigned char *ustr = (const unsigned char *)str;
1.163 joerg 1668:
1.401 rillig 1669: uint32_t h = 0x971e137bU;
1670: uint32_t c1 = 0x95543787U;
1671: uint32_t c2 = 0x2ad7eb25U;
1672: size_t len2 = strlen(str);
1.163 joerg 1673:
1.412 rillig 1674: char *buf;
1675: size_t i;
1676:
1.401 rillig 1677: size_t len;
1.163 joerg 1678: for (len = len2; len; ) {
1.401 rillig 1679: uint32_t k = 0;
1.163 joerg 1680: switch (len) {
1681: default:
1.252 rillig 1682: k = ((uint32_t)ustr[3] << 24) |
1683: ((uint32_t)ustr[2] << 16) |
1684: ((uint32_t)ustr[1] << 8) |
1685: (uint32_t)ustr[0];
1.163 joerg 1686: len -= 4;
1687: ustr += 4;
1688: break;
1689: case 3:
1.252 rillig 1690: k |= (uint32_t)ustr[2] << 16;
1.222 mrg 1691: /* FALLTHROUGH */
1.163 joerg 1692: case 2:
1.252 rillig 1693: k |= (uint32_t)ustr[1] << 8;
1.222 mrg 1694: /* FALLTHROUGH */
1.163 joerg 1695: case 1:
1.252 rillig 1696: k |= (uint32_t)ustr[0];
1.163 joerg 1697: len = 0;
1698: }
1699: c1 = c1 * 5 + 0x7b7d159cU;
1700: c2 = c2 * 5 + 0x6bce6396U;
1701: k *= c1;
1702: k = (k << 11) ^ (k >> 21);
1703: k *= c2;
1704: h = (h << 13) ^ (h >> 19);
1705: h = h * 5 + 0x52dce729U;
1706: h ^= k;
1.242 rillig 1707: }
1.448 rillig 1708: h ^= (uint32_t)len2;
1.242 rillig 1709: h *= 0x85ebca6b;
1710: h ^= h >> 13;
1711: h *= 0xc2b2ae35;
1712: h ^= h >> 16;
1713:
1.412 rillig 1714: buf = bmake_malloc(9);
1.405 rillig 1715: for (i = 0; i < 8; i++) {
1716: buf[i] = hexdigits[h & 0x0f];
1.242 rillig 1717: h >>= 4;
1.249 rillig 1718: }
1.405 rillig 1719: buf[8] = '\0';
1720: return buf;
1.163 joerg 1721: }
1722:
1.164 sjg 1723: static char *
1.425 rillig 1724: VarStrftime(const char *fmt, Boolean zulu, time_t tim)
1.164 sjg 1725: {
1726: char buf[BUFSIZ];
1727:
1.425 rillig 1728: if (!tim)
1729: time(&tim);
1.164 sjg 1730: if (!*fmt)
1731: fmt = "%c";
1.425 rillig 1732: strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&tim) : localtime(&tim));
1.235 rillig 1733:
1.164 sjg 1734: buf[sizeof(buf) - 1] = '\0';
1735: return bmake_strdup(buf);
1736: }
1737:
1.409 rillig 1738: /* The ApplyModifier functions all work in the same way. They get the
1739: * current parsing position (pp) and parse the modifier from there. The
1.467 rillig 1740: * modifier typically lasts until the next ':', or a closing '}' or ')'
1.409 rillig 1741: * (taken from st->endc), or the end of the string (parse error).
1742: *
1.467 rillig 1743: * The high-level behavior of these functions is:
1744: *
1745: * 1. parse the modifier
1746: * 2. evaluate the modifier
1747: * 3. housekeeping
1748: *
1749: * Parsing the modifier
1750: *
1751: * If parsing succeeds, the parsing position *pp is updated to point to the
1752: * first character following the modifier, which typically is either ':' or
1753: * st->endc.
1754: *
1755: * If parsing fails because of a missing delimiter (as in the :S, :C or :@
1.530 rillig 1756: * modifiers), return AMR_CLEANUP.
1.467 rillig 1757: *
1758: * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
1759: * try the SysV modifier ${VAR:from=to} as fallback. This should only be
1760: * done as long as there have been no side effects from evaluating nested
1761: * variables, to avoid evaluating them more than once. In this case, the
1762: * parsing position must not be updated. (XXX: Why not? The original parsing
1763: * position is well-known in ApplyModifiers.)
1764: *
1765: * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
1766: * as a fallback, either issue an error message using Error or Parse_Error
1767: * and then return AMR_CLEANUP, or return AMR_BAD for the default error
1768: * message. Both of these return values will stop processing the variable
1769: * expression. (XXX: As of 2020-08-23, evaluation of the whole string
1770: * continues nevertheless after skipping a few bytes, which essentially is
1771: * undefined behavior. Not in the sense of C, but still it's impossible to
1772: * predict what happens in the parser.)
1773: *
1774: * Evaluating the modifier
1775: *
1776: * After parsing, the modifier is evaluated. The side effects from evaluating
1777: * nested variable expressions in the modifier text often already happen
1778: * during parsing though.
1779: *
1780: * Evaluating the modifier usually takes the current value of the variable
1781: * expression from st->val, or the variable name from st->v->name and stores
1782: * the result in st->newVal.
1783: *
1784: * If evaluating fails (as of 2020-08-23), an error message is printed using
1785: * Error. This function has no side-effects, it really just prints the error
1786: * message. Processing the expression continues as if everything were ok.
1787: * XXX: This should be fixed by adding proper error handling to Var_Subst,
1788: * Var_Parse, ApplyModifiers and ModifyWords.
1789: *
1790: * Housekeeping
1791: *
1.528 rillig 1792: * Some modifiers such as :D and :U turn undefined expressions into defined
1793: * expressions (see VEF_UNDEF, VEF_DEF).
1.467 rillig 1794: *
1795: * Some modifiers need to free some memory.
1.350 rillig 1796: */
1.409 rillig 1797:
1.527 rillig 1798: typedef enum VarExprFlags {
1799: /* The variable expression is based on an undefined variable. */
1800: VEF_UNDEF = 0x01,
1801: /* The variable expression started as an undefined expression, but one
1802: * of the modifiers (such as :D or :U) has turned the expression from
1803: * undefined to defined. */
1804: VEF_DEF = 0x02
1805: } VarExprFlags;
1806:
1807: ENUM_FLAGS_RTTI_2(VarExprFlags,
1808: VEF_UNDEF, VEF_DEF);
1809:
1810:
1.541 rillig 1811: typedef struct ApplyModifiersState {
1.437 rillig 1812: const char startc; /* '\0' or '{' or '(' */
1813: const char endc; /* '\0' or '}' or ')' */
1.368 rillig 1814: Var * const v;
1815: GNode * const ctxt;
1816: const VarEvalFlags eflags;
1.236 rillig 1817:
1.454 rillig 1818: char *val; /* The old value of the expression,
1.460 rillig 1819: * before applying the modifier, never NULL */
1.454 rillig 1820: char *newVal; /* The new value of the expression,
1.460 rillig 1821: * after applying the modifier, never NULL */
1.449 rillig 1822: char sep; /* Word separator in expansions
1.444 rillig 1823: * (see the :ts modifier) */
1.454 rillig 1824: Boolean oneBigWord; /* TRUE if some modifiers that otherwise split
1825: * the variable value into words, like :S and
1826: * :C, treat the variable value as a single big
1827: * word, possibly containing spaces. */
1.527 rillig 1828: VarExprFlags exprFlags;
1.236 rillig 1829: } ApplyModifiersState;
1830:
1.525 rillig 1831: static void
1.527 rillig 1832: ApplyModifiersState_Define(ApplyModifiersState *st)
1.525 rillig 1833: {
1.527 rillig 1834: if (st->exprFlags & VEF_UNDEF)
1.571 rillig 1835: st->exprFlags |= VEF_DEF;
1.525 rillig 1836: }
1837:
1.578 rillig 1838: typedef enum ApplyModifierResult {
1.356 rillig 1839: AMR_OK, /* Continue parsing */
1.400 rillig 1840: AMR_UNKNOWN, /* Not a match, try other modifiers as well */
1841: AMR_BAD, /* Error out with "Bad modifier" message */
1.530 rillig 1842: AMR_CLEANUP /* Error out without error message */
1.356 rillig 1843: } ApplyModifierResult;
1844:
1.620 rillig 1845: /* Allow backslashes to escape the delimiter, $, and \, but don't touch other
1846: * backslashes. */
1847: static Boolean
1848: IsEscapedModifierPart(const char *p, char delim,
1849: struct ModifyWord_SubstArgs *subst)
1850: {
1851: if (p[0] != '\\')
1852: return FALSE;
1853: if (p[1] == delim || p[1] == '\\' || p[1] == '$')
1854: return TRUE;
1855: return p[1] == '&' && subst != NULL;
1856: }
1857:
1858: /*
1859: * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
1860: * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
1.529 rillig 1861: * including the next unescaped delimiter. The delimiter, as well as the
1862: * backslash or the dollar, can be escaped with a backslash.
1863: *
1864: * Return the parsed (and possibly expanded) string, or NULL if no delimiter
1865: * was found. On successful return, the parsing position pp points right
1866: * after the delimiter. The delimiter is not included in the returned
1867: * value though.
1868: */
1.531 rillig 1869: static VarParseResult
1.529 rillig 1870: ParseModifierPart(
1871: const char **pp, /* The parsing position, updated upon return */
1.621 rillig 1872: char delim, /* Parsing stops at this delimiter */
1.529 rillig 1873: VarEvalFlags eflags, /* Flags for evaluating nested variables;
1874: * if VARE_WANTRES is not set, the text is
1875: * only parsed */
1876: ApplyModifiersState *st,
1.531 rillig 1877: char **out_part,
1.529 rillig 1878: size_t *out_length, /* Optionally stores the length of the returned
1879: * string, just to save another strlen call. */
1880: VarPatternFlags *out_pflags,/* For the first part of the :S modifier,
1881: * sets the VARP_ANCHOR_END flag if the last
1882: * character of the pattern is a $. */
1.541 rillig 1883: struct ModifyWord_SubstArgs *subst
1884: /* For the second part of the :S modifier,
1.529 rillig 1885: * allow ampersands to be escaped and replace
1886: * unescaped ampersands with subst->lhs. */
1887: ) {
1888: Buffer buf;
1889: const char *p;
1890:
1891: Buf_Init(&buf, 0);
1892:
1893: /*
1.620 rillig 1894: * Skim through until the matching delimiter is found; pick up variable
1895: * expressions on the way.
1.529 rillig 1896: */
1897: p = *pp;
1898: while (*p != '\0' && *p != delim) {
1899: const char *varstart;
1900:
1.620 rillig 1901: if (IsEscapedModifierPart(p, delim, subst)) {
1.529 rillig 1902: Buf_AddByte(&buf, p[1]);
1903: p += 2;
1904: continue;
1905: }
1906:
1907: if (*p != '$') { /* Unescaped, simple text */
1908: if (subst != NULL && *p == '&')
1909: Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
1910: else
1911: Buf_AddByte(&buf, *p);
1912: p++;
1913: continue;
1914: }
1915:
1916: if (p[1] == delim) { /* Unescaped $ at end of pattern */
1917: if (out_pflags != NULL)
1918: *out_pflags |= VARP_ANCHOR_END;
1919: else
1920: Buf_AddByte(&buf, *p);
1921: p++;
1922: continue;
1923: }
1924:
1925: if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */
1926: const char *nested_p = p;
1927: const char *nested_val;
1928: void *nested_val_freeIt;
1929: VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN;
1930:
1931: (void)Var_Parse(&nested_p, st->ctxt, nested_eflags,
1932: &nested_val, &nested_val_freeIt);
1933: /* TODO: handle errors */
1934: Buf_AddStr(&buf, nested_val);
1935: free(nested_val_freeIt);
1936: p += nested_p - p;
1937: continue;
1938: }
1939:
1940: /* XXX: This whole block is very similar to Var_Parse without
1941: * VARE_WANTRES. There may be subtle edge cases though that are
1942: * not yet covered in the unit tests and that are parsed differently,
1943: * depending on whether they are evaluated or not.
1944: *
1945: * This subtle difference is not documented in the manual page,
1946: * neither is the difference between parsing :D and :M documented.
1947: * No code should ever depend on these details, but who knows. */
1948:
1949: varstart = p; /* Nested variable, only parsed */
1950: if (p[1] == '(' || p[1] == '{') {
1951: /*
1952: * Find the end of this variable reference
1953: * and suck it in without further ado.
1954: * It will be interpreted later.
1955: */
1.627 rillig 1956: char startc = p[1];
1957: int endc = startc == '(' ? ')' : '}';
1.529 rillig 1958: int depth = 1;
1959:
1960: for (p += 2; *p != '\0' && depth > 0; p++) {
1961: if (p[-1] != '\\') {
1.627 rillig 1962: if (*p == startc)
1.529 rillig 1963: depth++;
1.627 rillig 1964: if (*p == endc)
1.529 rillig 1965: depth--;
1966: }
1967: }
1968: Buf_AddBytesBetween(&buf, varstart, p);
1969: } else {
1970: Buf_AddByte(&buf, *varstart);
1971: p++;
1972: }
1973: }
1974:
1975: if (*p != delim) {
1976: *pp = p;
1.530 rillig 1977: Error("Unfinished modifier for %s ('%c' missing)", st->v->name, delim);
1.531 rillig 1978: *out_part = NULL;
1979: return VPR_PARSE_MSG;
1.529 rillig 1980: }
1981:
1982: *pp = ++p;
1983: if (out_length != NULL)
1.545 rillig 1984: *out_length = Buf_Len(&buf);
1.529 rillig 1985:
1.531 rillig 1986: *out_part = Buf_Destroy(&buf, FALSE);
1.547 rillig 1987: VAR_DEBUG1("Modifier part: \"%s\"\n", *out_part);
1.531 rillig 1988: return VPR_OK;
1.529 rillig 1989: }
1990:
1.400 rillig 1991: /* Test whether mod starts with modname, followed by a delimiter. */
1.340 rillig 1992: static Boolean
1993: ModMatch(const char *mod, const char *modname, char endc)
1994: {
1995: size_t n = strlen(modname);
1996: return strncmp(mod, modname, n) == 0 &&
1997: (mod[n] == endc || mod[n] == ':');
1998: }
1999:
1.400 rillig 2000: /* Test whether mod starts with modname, followed by a delimiter or '='. */
1.340 rillig 2001: static inline Boolean
2002: ModMatchEq(const char *mod, const char *modname, char endc)
2003: {
2004: size_t n = strlen(modname);
2005: return strncmp(mod, modname, n) == 0 &&
2006: (mod[n] == endc || mod[n] == ':' || mod[n] == '=');
2007: }
1.236 rillig 2008:
1.635 rillig 2009: static Boolean
2010: TryParseIntBase0(const char **pp, int *out_num)
2011: {
2012: char *end;
2013: long n;
2014:
2015: errno = 0;
2016: n = strtol(*pp, &end, 0);
2017: if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
2018: return FALSE;
2019: if (n < INT_MIN || n > INT_MAX)
2020: return FALSE;
2021:
2022: *pp = end;
2023: *out_num = (int)n;
2024: return TRUE;
2025: }
2026:
2027: static Boolean
2028: TryParseSize(const char **pp, size_t *out_num)
2029: {
2030: char *end;
2031: unsigned long n;
2032:
2033: if (!ch_isdigit(**pp))
2034: return FALSE;
2035:
2036: errno = 0;
2037: n = strtoul(*pp, &end, 10);
2038: if (n == ULONG_MAX && errno == ERANGE)
2039: return FALSE;
2040: if (n > SIZE_MAX)
2041: return FALSE;
2042:
2043: *pp = end;
2044: *out_num = (size_t)n;
2045: return TRUE;
2046: }
2047:
2048: static Boolean
2049: TryParseChar(const char **pp, int base, char *out_ch)
2050: {
2051: char *end;
2052: unsigned long n;
2053:
2054: if (!ch_isalnum(**pp))
2055: return FALSE;
2056:
2057: errno = 0;
2058: n = strtoul(*pp, &end, base);
2059: if (n == ULONG_MAX && errno == ERANGE)
2060: return FALSE;
2061: if (n > UCHAR_MAX)
2062: return FALSE;
2063:
2064: *pp = end;
2065: *out_ch = (char)n;
2066: return TRUE;
2067: }
2068:
1.236 rillig 2069: /* :@var@...${var}...@ */
1.356 rillig 2070: static ApplyModifierResult
1.417 rillig 2071: ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
2072: {
1.541 rillig 2073: struct ModifyWord_LoopArgs args;
1.448 rillig 2074: char prev_sep;
2075: VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.531 rillig 2076: VarParseResult res;
1.236 rillig 2077:
1.295 rillig 2078: args.ctx = st->ctxt;
1.409 rillig 2079:
2080: (*pp)++; /* Skip the first '@' */
1.535 rillig 2081: res = ParseModifierPart(pp, '@', eflags, st,
1.531 rillig 2082: &args.tvar, NULL, NULL, NULL);
2083: if (res != VPR_OK)
1.356 rillig 2084: return AMR_CLEANUP;
1.410 rillig 2085: if (DEBUG(LINT) && strchr(args.tvar, '$') != NULL) {
2086: Parse_Error(PARSE_FATAL,
2087: "In the :@ modifier of \"%s\", the variable name \"%s\" "
2088: "must not contain a dollar.",
2089: st->v->name, args.tvar);
1.417 rillig 2090: return AMR_CLEANUP;
1.410 rillig 2091: }
1.236 rillig 2092:
1.535 rillig 2093: res = ParseModifierPart(pp, '@', eflags, st,
1.531 rillig 2094: &args.str, NULL, NULL, NULL);
2095: if (res != VPR_OK)
1.356 rillig 2096: return AMR_CLEANUP;
1.236 rillig 2097:
1.291 rillig 2098: args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
1.412 rillig 2099: prev_sep = st->sep;
1.409 rillig 2100: st->sep = ' '; /* XXX: should be st->sep for consistency */
1.619 rillig 2101: st->newVal = ModifyWords(st->val, ModifyWord_Loop, &args,
2102: st->oneBigWord, st->sep);
1.301 rillig 2103: st->sep = prev_sep;
1.291 rillig 2104: Var_Delete(args.tvar, st->ctxt);
2105: free(args.tvar);
2106: free(args.str);
1.356 rillig 2107: return AMR_OK;
1.236 rillig 2108: }
2109:
2110: /* :Ddefined or :Uundefined */
1.356 rillig 2111: static ApplyModifierResult
1.409 rillig 2112: ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
1.236 rillig 2113: {
1.467 rillig 2114: Buffer buf;
1.412 rillig 2115: const char *p;
2116:
1.448 rillig 2117: VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.268 rillig 2118: if (st->eflags & VARE_WANTRES) {
1.527 rillig 2119: if ((**pp == 'D') == !(st->exprFlags & VEF_UNDEF))
1.415 rillig 2120: eflags |= VARE_WANTRES;
2121: }
1.236 rillig 2122:
1.433 rillig 2123: Buf_Init(&buf, 0);
1.412 rillig 2124: p = *pp + 1;
1.339 rillig 2125: while (*p != st->endc && *p != ':' && *p != '\0') {
1.466 rillig 2126:
1.494 rillig 2127: /* Escaped delimiter or other special character */
1.466 rillig 2128: if (*p == '\\') {
2129: char c = p[1];
2130: if (c == st->endc || c == ':' || c == '$' || c == '\\') {
2131: Buf_AddByte(&buf, c);
2132: p += 2;
2133: continue;
2134: }
2135: }
2136:
1.467 rillig 2137: /* Nested variable expression */
1.466 rillig 2138: if (*p == '$') {
1.486 rillig 2139: const char *nested_val;
2140: void *nested_val_freeIt;
1.236 rillig 2141:
1.514 rillig 2142: (void)Var_Parse(&p, st->ctxt, eflags,
2143: &nested_val, &nested_val_freeIt);
2144: /* TODO: handle errors */
1.486 rillig 2145: Buf_AddStr(&buf, nested_val);
2146: free(nested_val_freeIt);
1.466 rillig 2147: continue;
1.236 rillig 2148: }
1.466 rillig 2149:
2150: /* Ordinary text */
2151: Buf_AddByte(&buf, *p);
2152: p++;
1.236 rillig 2153: }
1.409 rillig 2154: *pp = p;
1.236 rillig 2155:
1.527 rillig 2156: ApplyModifiersState_Define(st);
1.525 rillig 2157:
1.415 rillig 2158: if (eflags & VARE_WANTRES) {
1.349 rillig 2159: st->newVal = Buf_Destroy(&buf, FALSE);
1.236 rillig 2160: } else {
1.349 rillig 2161: st->newVal = st->val;
1.236 rillig 2162: Buf_Destroy(&buf, TRUE);
2163: }
1.356 rillig 2164: return AMR_OK;
1.236 rillig 2165: }
2166:
1.567 rillig 2167: /* :L */
2168: static ApplyModifierResult
2169: ApplyModifier_Literal(const char **pp, ApplyModifiersState *st)
2170: {
2171: ApplyModifiersState_Define(st);
2172: st->newVal = bmake_strdup(st->v->name);
2173: (*pp)++;
2174: return AMR_OK;
2175: }
2176:
1.633 rillig 2177: static Boolean
2178: TryParseTime(const char **pp, time_t *out_time)
1.631 rillig 2179: {
2180: char *end;
2181: unsigned long n;
2182:
2183: if (!ch_isdigit(**pp))
2184: return FALSE;
2185:
2186: errno = 0;
2187: n = strtoul(*pp, &end, 10);
2188: if (n == ULONG_MAX && errno == ERANGE)
2189: return FALSE;
2190:
2191: *pp = end;
2192: *out_time = (time_t)n; /* ignore possible truncation for now */
2193: return TRUE;
2194: }
2195:
1.236 rillig 2196: /* :gmtime */
1.356 rillig 2197: static ApplyModifierResult
1.409 rillig 2198: ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st)
1.236 rillig 2199: {
1.412 rillig 2200: time_t utc;
2201:
1.409 rillig 2202: const char *mod = *pp;
1.358 rillig 2203: if (!ModMatchEq(mod, "gmtime", st->endc))
1.356 rillig 2204: return AMR_UNKNOWN;
1.340 rillig 2205:
1.299 rillig 2206: if (mod[6] == '=') {
1.631 rillig 2207: const char *arg = mod + 7;
2208: if (!TryParseTime(&arg, &utc)) {
2209: Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 7);
2210: return AMR_CLEANUP;
2211: }
2212: *pp = arg;
1.236 rillig 2213: } else {
2214: utc = 0;
1.409 rillig 2215: *pp = mod + 6;
1.236 rillig 2216: }
1.425 rillig 2217: st->newVal = VarStrftime(st->val, TRUE, utc);
1.356 rillig 2218: return AMR_OK;
1.236 rillig 2219: }
2220:
2221: /* :localtime */
1.505 rillig 2222: static ApplyModifierResult
1.409 rillig 2223: ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st)
1.236 rillig 2224: {
1.412 rillig 2225: time_t utc;
2226:
1.409 rillig 2227: const char *mod = *pp;
1.358 rillig 2228: if (!ModMatchEq(mod, "localtime", st->endc))
1.356 rillig 2229: return AMR_UNKNOWN;
1.236 rillig 2230:
1.299 rillig 2231: if (mod[9] == '=') {
1.631 rillig 2232: const char *arg = mod + 10;
2233: if (!TryParseTime(&arg, &utc)) {
2234: Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 10);
2235: return AMR_CLEANUP;
2236: }
2237: *pp = arg;
1.236 rillig 2238: } else {
2239: utc = 0;
1.409 rillig 2240: *pp = mod + 9;
1.236 rillig 2241: }
1.425 rillig 2242: st->newVal = VarStrftime(st->val, FALSE, utc);
1.356 rillig 2243: return AMR_OK;
1.236 rillig 2244: }
2245:
2246: /* :hash */
1.356 rillig 2247: static ApplyModifierResult
1.409 rillig 2248: ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
1.236 rillig 2249: {
1.409 rillig 2250: if (!ModMatch(*pp, "hash", st->endc))
1.356 rillig 2251: return AMR_UNKNOWN;
1.340 rillig 2252:
1.349 rillig 2253: st->newVal = VarHash(st->val);
1.409 rillig 2254: *pp += 4;
1.356 rillig 2255: return AMR_OK;
1.236 rillig 2256: }
2257:
2258: /* :P */
1.356 rillig 2259: static ApplyModifierResult
1.409 rillig 2260: ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
1.236 rillig 2261: {
1.412 rillig 2262: GNode *gn;
1.461 rillig 2263: char *path;
1.412 rillig 2264:
1.527 rillig 2265: ApplyModifiersState_Define(st);
1.409 rillig 2266:
1.543 rillig 2267: gn = Targ_FindNode(st->v->name);
1.236 rillig 2268: if (gn == NULL || gn->type & OP_NOPATH) {
1.461 rillig 2269: path = NULL;
1.589 rillig 2270: } else if (gn->path != NULL) {
1.461 rillig 2271: path = bmake_strdup(gn->path);
1.236 rillig 2272: } else {
1.524 rillig 2273: SearchPath *searchPath = Suff_FindPath(gn);
1.461 rillig 2274: path = Dir_FindFile(st->v->name, searchPath);
1.236 rillig 2275: }
1.461 rillig 2276: if (path == NULL)
2277: path = bmake_strdup(st->v->name);
2278: st->newVal = path;
1.409 rillig 2279:
2280: (*pp)++;
1.356 rillig 2281: return AMR_OK;
1.236 rillig 2282: }
2283:
2284: /* :!cmd! */
1.356 rillig 2285: static ApplyModifierResult
1.509 rillig 2286: ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st)
1.236 rillig 2287: {
1.412 rillig 2288: char *cmd;
1.416 rillig 2289: const char *errfmt;
1.531 rillig 2290: VarParseResult res;
1.412 rillig 2291:
1.409 rillig 2292: (*pp)++;
1.535 rillig 2293: res = ParseModifierPart(pp, '!', st->eflags, st,
1.531 rillig 2294: &cmd, NULL, NULL, NULL);
2295: if (res != VPR_OK)
1.356 rillig 2296: return AMR_CLEANUP;
1.274 rillig 2297:
1.416 rillig 2298: errfmt = NULL;
1.268 rillig 2299: if (st->eflags & VARE_WANTRES)
1.416 rillig 2300: st->newVal = Cmd_Exec(cmd, &errfmt);
1.236 rillig 2301: else
1.536 rillig 2302: st->newVal = emptyString;
1.274 rillig 2303: free(cmd);
2304:
1.416 rillig 2305: if (errfmt != NULL)
2306: Error(errfmt, st->val); /* XXX: why still return AMR_OK? */
1.274 rillig 2307:
1.527 rillig 2308: ApplyModifiersState_Define(st);
1.356 rillig 2309: return AMR_OK;
1.236 rillig 2310: }
2311:
1.386 rillig 2312: /* The :range modifier generates an integer sequence as long as the words.
2313: * The :range=7 modifier generates an integer sequence from 1 to 7. */
1.356 rillig 2314: static ApplyModifierResult
1.409 rillig 2315: ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
1.236 rillig 2316: {
1.465 rillig 2317: size_t n;
1.412 rillig 2318: Buffer buf;
1.465 rillig 2319: size_t i;
1.412 rillig 2320:
1.409 rillig 2321: const char *mod = *pp;
1.358 rillig 2322: if (!ModMatchEq(mod, "range", st->endc))
1.356 rillig 2323: return AMR_UNKNOWN;
1.236 rillig 2324:
1.299 rillig 2325: if (mod[5] == '=') {
1.635 rillig 2326: const char *p = mod + 6;
2327: if (!TryParseSize(&p, &n)) {
2328: Parse_Error(PARSE_FATAL, "Invalid number: %s\n", mod + 6);
2329: return AMR_CLEANUP;
2330: }
2331: *pp = p;
1.236 rillig 2332: } else {
2333: n = 0;
1.409 rillig 2334: *pp = mod + 5;
1.236 rillig 2335: }
1.386 rillig 2336:
2337: if (n == 0) {
1.494 rillig 2338: Words words = Str_Words(st->val, FALSE);
2339: n = words.len;
2340: Words_Free(words);
1.386 rillig 2341: }
2342:
1.433 rillig 2343: Buf_Init(&buf, 0);
1.386 rillig 2344:
2345: for (i = 0; i < n; i++) {
2346: if (i != 0)
1.442 rillig 2347: Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */
1.465 rillig 2348: Buf_AddInt(&buf, 1 + (int)i);
1.386 rillig 2349: }
2350:
2351: st->newVal = Buf_Destroy(&buf, FALSE);
1.356 rillig 2352: return AMR_OK;
1.236 rillig 2353: }
2354:
2355: /* :Mpattern or :Npattern */
1.356 rillig 2356: static ApplyModifierResult
1.409 rillig 2357: ApplyModifier_Match(const char **pp, ApplyModifiersState *st)
1.236 rillig 2358: {
1.409 rillig 2359: const char *mod = *pp;
1.288 rillig 2360: Boolean copy = FALSE; /* pattern should be, or has been, copied */
2361: Boolean needSubst = FALSE;
1.412 rillig 2362: const char *endpat;
2363: char *pattern;
2364: ModifyWordsCallback callback;
2365:
1.236 rillig 2366: /*
1.288 rillig 2367: * In the loop below, ignore ':' unless we are at (or back to) the
2368: * original brace level.
2369: * XXX This will likely not work right if $() and ${} are intermixed.
1.236 rillig 2370: */
1.387 rillig 2371: int nest = 0;
1.347 rillig 2372: const char *p;
1.387 rillig 2373: for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) {
1.347 rillig 2374: if (*p == '\\' &&
2375: (p[1] == ':' || p[1] == st->endc || p[1] == st->startc)) {
1.637 rillig 2376: if (!needSubst)
2377: copy = TRUE;
1.347 rillig 2378: p++;
1.236 rillig 2379: continue;
2380: }
1.347 rillig 2381: if (*p == '$')
1.236 rillig 2382: needSubst = TRUE;
1.347 rillig 2383: if (*p == '(' || *p == '{')
1.426 rillig 2384: nest++;
1.347 rillig 2385: if (*p == ')' || *p == '}') {
1.426 rillig 2386: nest--;
1.387 rillig 2387: if (nest < 0)
1.236 rillig 2388: break;
2389: }
2390: }
1.409 rillig 2391: *pp = p;
1.412 rillig 2392: endpat = p;
1.288 rillig 2393:
1.236 rillig 2394: if (copy) {
1.417 rillig 2395: char *dst;
2396: const char *src;
1.412 rillig 2397:
1.345 rillig 2398: /* Compress the \:'s out of the pattern. */
1.448 rillig 2399: pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
1.412 rillig 2400: dst = pattern;
2401: src = mod + 1;
1.346 rillig 2402: for (; src < endpat; src++, dst++) {
2403: if (src[0] == '\\' && src + 1 < endpat &&
1.345 rillig 2404: /* XXX: st->startc is missing here; see above */
1.346 rillig 2405: (src[1] == ':' || src[1] == st->endc))
2406: src++;
2407: *dst = *src;
1.236 rillig 2408: }
1.346 rillig 2409: *dst = '\0';
2410: endpat = dst;
1.236 rillig 2411: } else {
1.474 rillig 2412: pattern = bmake_strsedup(mod + 1, endpat);
1.236 rillig 2413: }
1.346 rillig 2414:
1.236 rillig 2415: if (needSubst) {
2416: /* pattern contains embedded '$', so use Var_Subst to expand it. */
1.288 rillig 2417: char *old_pattern = pattern;
1.533 rillig 2418: (void)Var_Subst(pattern, st->ctxt, st->eflags, &pattern);
2419: /* TODO: handle errors */
1.288 rillig 2420: free(old_pattern);
1.236 rillig 2421: }
1.346 rillig 2422:
1.547 rillig 2423: VAR_DEBUG3("Pattern[%s] for [%s] is [%s]\n", st->v->name, st->val, pattern);
1.346 rillig 2424:
1.412 rillig 2425: callback = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
1.619 rillig 2426: st->newVal = ModifyWords(st->val, callback, pattern,
2427: st->oneBigWord, st->sep);
1.236 rillig 2428: free(pattern);
1.356 rillig 2429: return AMR_OK;
1.236 rillig 2430: }
2431:
2432: /* :S,from,to, */
1.356 rillig 2433: static ApplyModifierResult
1.409 rillig 2434: ApplyModifier_Subst(const char **pp, ApplyModifiersState *st)
1.236 rillig 2435: {
1.541 rillig 2436: struct ModifyWord_SubstArgs args;
1.412 rillig 2437: char *lhs, *rhs;
2438: Boolean oneBigWord;
1.531 rillig 2439: VarParseResult res;
1.412 rillig 2440:
1.409 rillig 2441: char delim = (*pp)[1];
1.359 rillig 2442: if (delim == '\0') {
2443: Error("Missing delimiter for :S modifier");
1.409 rillig 2444: (*pp)++;
1.359 rillig 2445: return AMR_CLEANUP;
2446: }
1.299 rillig 2447:
1.409 rillig 2448: *pp += 2;
1.236 rillig 2449:
1.362 rillig 2450: args.pflags = 0;
1.452 rillig 2451: args.matched = FALSE;
1.362 rillig 2452:
1.236 rillig 2453: /*
2454: * If pattern begins with '^', it is anchored to the
2455: * start of the word -- skip over it and flag pattern.
2456: */
1.409 rillig 2457: if (**pp == '^') {
1.288 rillig 2458: args.pflags |= VARP_ANCHOR_START;
1.409 rillig 2459: (*pp)++;
1.236 rillig 2460: }
2461:
1.531 rillig 2462: res = ParseModifierPart(pp, delim, st->eflags, st,
2463: &lhs, &args.lhsLen, &args.pflags, NULL);
2464: if (res != VPR_OK)
1.356 rillig 2465: return AMR_CLEANUP;
1.281 rillig 2466: args.lhs = lhs;
1.236 rillig 2467:
1.531 rillig 2468: res = ParseModifierPart(pp, delim, st->eflags, st,
2469: &rhs, &args.rhsLen, NULL, &args);
2470: if (res != VPR_OK)
1.356 rillig 2471: return AMR_CLEANUP;
1.281 rillig 2472: args.rhs = rhs;
1.236 rillig 2473:
1.412 rillig 2474: oneBigWord = st->oneBigWord;
1.409 rillig 2475: for (;; (*pp)++) {
2476: switch (**pp) {
1.236 rillig 2477: case 'g':
1.281 rillig 2478: args.pflags |= VARP_SUB_GLOBAL;
1.236 rillig 2479: continue;
2480: case '1':
1.281 rillig 2481: args.pflags |= VARP_SUB_ONE;
1.236 rillig 2482: continue;
2483: case 'W':
1.301 rillig 2484: oneBigWord = TRUE;
1.236 rillig 2485: continue;
2486: }
2487: break;
2488: }
2489:
1.619 rillig 2490: st->newVal = ModifyWords(st->val, ModifyWord_Subst, &args,
2491: oneBigWord, st->sep);
1.236 rillig 2492:
1.281 rillig 2493: free(lhs);
2494: free(rhs);
1.356 rillig 2495: return AMR_OK;
1.236 rillig 2496: }
2497:
2498: #ifndef NO_REGEX
1.291 rillig 2499:
1.236 rillig 2500: /* :C,from,to, */
1.356 rillig 2501: static ApplyModifierResult
1.409 rillig 2502: ApplyModifier_Regex(const char **pp, ApplyModifiersState *st)
1.236 rillig 2503: {
1.412 rillig 2504: char *re;
1.541 rillig 2505: struct ModifyWord_SubstRegexArgs args;
1.412 rillig 2506: Boolean oneBigWord;
2507: int error;
1.531 rillig 2508: VarParseResult res;
1.412 rillig 2509:
1.409 rillig 2510: char delim = (*pp)[1];
1.360 rillig 2511: if (delim == '\0') {
2512: Error("Missing delimiter for :C modifier");
1.409 rillig 2513: (*pp)++;
1.360 rillig 2514: return AMR_CLEANUP;
2515: }
1.236 rillig 2516:
1.409 rillig 2517: *pp += 2;
1.236 rillig 2518:
1.531 rillig 2519: res = ParseModifierPart(pp, delim, st->eflags, st,
1.599 rillig 2520: &re, NULL, NULL, NULL);
1.531 rillig 2521: if (res != VPR_OK)
1.356 rillig 2522: return AMR_CLEANUP;
1.236 rillig 2523:
1.531 rillig 2524: res = ParseModifierPart(pp, delim, st->eflags, st,
2525: &args.replace, NULL, NULL, NULL);
1.291 rillig 2526: if (args.replace == NULL) {
1.236 rillig 2527: free(re);
1.356 rillig 2528: return AMR_CLEANUP;
1.236 rillig 2529: }
2530:
1.361 rillig 2531: args.pflags = 0;
1.452 rillig 2532: args.matched = FALSE;
1.412 rillig 2533: oneBigWord = st->oneBigWord;
1.409 rillig 2534: for (;; (*pp)++) {
2535: switch (**pp) {
1.236 rillig 2536: case 'g':
1.291 rillig 2537: args.pflags |= VARP_SUB_GLOBAL;
1.236 rillig 2538: continue;
2539: case '1':
1.291 rillig 2540: args.pflags |= VARP_SUB_ONE;
1.236 rillig 2541: continue;
2542: case 'W':
1.301 rillig 2543: oneBigWord = TRUE;
1.236 rillig 2544: continue;
2545: }
2546: break;
2547: }
2548:
1.412 rillig 2549: error = regcomp(&args.re, re, REG_EXTENDED);
1.236 rillig 2550: free(re);
1.242 rillig 2551: if (error) {
1.385 rillig 2552: VarREError(error, &args.re, "Regex compilation error");
1.291 rillig 2553: free(args.replace);
1.356 rillig 2554: return AMR_CLEANUP;
1.236 rillig 2555: }
2556:
1.291 rillig 2557: args.nsub = args.re.re_nsub + 1;
2558: if (args.nsub > 10)
2559: args.nsub = 10;
1.619 rillig 2560: st->newVal = ModifyWords(st->val, ModifyWord_SubstRegex, &args,
2561: oneBigWord, st->sep);
1.291 rillig 2562: regfree(&args.re);
2563: free(args.replace);
1.356 rillig 2564: return AMR_OK;
1.236 rillig 2565: }
2566: #endif
2567:
1.555 rillig 2568: /* :Q, :q */
2569: static ApplyModifierResult
2570: ApplyModifier_Quote(const char **pp, ApplyModifiersState *st)
2571: {
2572: if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
2573: st->newVal = VarQuote(st->val, **pp == 'q');
2574: (*pp)++;
2575: return AMR_OK;
2576: } else
2577: return AMR_UNKNOWN;
2578: }
2579:
1.278 rillig 2580: static void
1.295 rillig 2581: ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.278 rillig 2582: {
1.314 rillig 2583: SepBuf_AddStr(buf, word);
1.275 rillig 2584: }
2585:
1.289 rillig 2586: /* :ts<separator> */
1.356 rillig 2587: static ApplyModifierResult
1.409 rillig 2588: ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
1.289 rillig 2589: {
1.556 rillig 2590: const char *sep = *pp + 2;
1.468 rillig 2591:
2592: /* ":ts<any><endc>" or ":ts<any>:" */
1.289 rillig 2593: if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
1.301 rillig 2594: st->sep = sep[0];
1.409 rillig 2595: *pp = sep + 1;
1.468 rillig 2596: goto ok;
2597: }
2598:
2599: /* ":ts<endc>" or ":ts:" */
2600: if (sep[0] == st->endc || sep[0] == ':') {
1.301 rillig 2601: st->sep = '\0'; /* no separator */
1.409 rillig 2602: *pp = sep;
1.468 rillig 2603: goto ok;
2604: }
2605:
2606: /* ":ts<unrecognised><unrecognised>". */
1.556 rillig 2607: if (sep[0] != '\\') {
2608: (*pp)++; /* just for backwards compatibility */
1.468 rillig 2609: return AMR_BAD;
1.556 rillig 2610: }
1.468 rillig 2611:
2612: /* ":ts\n" */
2613: if (sep[1] == 'n') {
2614: st->sep = '\n';
2615: *pp = sep + 2;
2616: goto ok;
2617: }
2618:
2619: /* ":ts\t" */
2620: if (sep[1] == 't') {
2621: st->sep = '\t';
2622: *pp = sep + 2;
2623: goto ok;
2624: }
2625:
2626: /* ":ts\x40" or ":ts\100" */
2627: {
1.635 rillig 2628: const char *p = sep + 1;
1.289 rillig 2629: int base = 8; /* assume octal */
2630:
1.468 rillig 2631: if (sep[1] == 'x') {
1.289 rillig 2632: base = 16;
1.635 rillig 2633: p++;
1.556 rillig 2634: } else if (!ch_isdigit(sep[1])) {
2635: (*pp)++; /* just for backwards compatibility */
1.468 rillig 2636: return AMR_BAD; /* ":ts<backslash><unrecognised>". */
1.556 rillig 2637: }
1.468 rillig 2638:
1.635 rillig 2639: if (!TryParseChar(&p, base, &st->sep)) {
2640: Parse_Error(PARSE_FATAL, "Invalid character number: %s\n", p);
2641: return AMR_CLEANUP;
2642: }
2643: if (*p != ':' && *p != st->endc) {
1.556 rillig 2644: (*pp)++; /* just for backwards compatibility */
1.468 rillig 2645: return AMR_BAD;
1.556 rillig 2646: }
1.635 rillig 2647:
2648: *pp = p;
1.289 rillig 2649: }
2650:
1.468 rillig 2651: ok:
1.619 rillig 2652: st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL,
2653: st->oneBigWord, st->sep);
1.356 rillig 2654: return AMR_OK;
1.289 rillig 2655: }
2656:
2657: /* :tA, :tu, :tl, :ts<separator>, etc. */
1.356 rillig 2658: static ApplyModifierResult
1.409 rillig 2659: ApplyModifier_To(const char **pp, ApplyModifiersState *st)
1.236 rillig 2660: {
1.409 rillig 2661: const char *mod = *pp;
1.363 rillig 2662: assert(mod[0] == 't');
2663:
1.556 rillig 2664: if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') {
2665: *pp = mod + 1;
1.356 rillig 2666: return AMR_BAD; /* Found ":t<endc>" or ":t:". */
1.556 rillig 2667: }
1.289 rillig 2668:
1.299 rillig 2669: if (mod[1] == 's')
1.409 rillig 2670: return ApplyModifier_ToSep(pp, st);
1.289 rillig 2671:
1.556 rillig 2672: if (mod[2] != st->endc && mod[2] != ':') {
2673: *pp = mod + 1;
1.356 rillig 2674: return AMR_BAD; /* Found ":t<unrecognised><unrecognised>". */
1.556 rillig 2675: }
1.236 rillig 2676:
1.289 rillig 2677: /* Check for two-character options: ":tu", ":tl" */
1.299 rillig 2678: if (mod[1] == 'A') { /* absolute path */
1.619 rillig 2679: st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL,
2680: st->oneBigWord, st->sep);
1.409 rillig 2681: *pp = mod + 2;
1.475 rillig 2682: return AMR_OK;
2683: }
2684:
1.556 rillig 2685: if (mod[1] == 'u') { /* :tu */
1.412 rillig 2686: size_t i;
1.364 rillig 2687: size_t len = strlen(st->val);
2688: st->newVal = bmake_malloc(len + 1);
2689: for (i = 0; i < len + 1; i++)
1.493 rillig 2690: st->newVal[i] = ch_toupper(st->val[i]);
1.409 rillig 2691: *pp = mod + 2;
1.475 rillig 2692: return AMR_OK;
2693: }
2694:
1.556 rillig 2695: if (mod[1] == 'l') { /* :tl */
1.412 rillig 2696: size_t i;
1.364 rillig 2697: size_t len = strlen(st->val);
2698: st->newVal = bmake_malloc(len + 1);
2699: for (i = 0; i < len + 1; i++)
1.493 rillig 2700: st->newVal[i] = ch_tolower(st->val[i]);
1.409 rillig 2701: *pp = mod + 2;
1.475 rillig 2702: return AMR_OK;
2703: }
2704:
1.556 rillig 2705: if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
1.301 rillig 2706: st->oneBigWord = mod[1] == 'W';
1.349 rillig 2707: st->newVal = st->val;
1.409 rillig 2708: *pp = mod + 2;
1.475 rillig 2709: return AMR_OK;
1.236 rillig 2710: }
1.475 rillig 2711:
2712: /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
1.556 rillig 2713: *pp = mod + 1;
1.475 rillig 2714: return AMR_BAD;
1.236 rillig 2715: }
2716:
1.634 rillig 2717: /* :[#], :[1], :[-1..1], etc. */
1.356 rillig 2718: static ApplyModifierResult
1.409 rillig 2719: ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
1.236 rillig 2720: {
1.412 rillig 2721: char *estr;
2722: int first, last;
1.531 rillig 2723: VarParseResult res;
1.635 rillig 2724: const char *p;
1.412 rillig 2725:
1.409 rillig 2726: (*pp)++; /* skip the '[' */
1.535 rillig 2727: res = ParseModifierPart(pp, ']', st->eflags, st,
1.531 rillig 2728: &estr, NULL, NULL, NULL);
2729: if (res != VPR_OK)
1.356 rillig 2730: return AMR_CLEANUP;
1.288 rillig 2731:
1.409 rillig 2732: /* now *pp points just after the closing ']' */
2733: if (**pp != ':' && **pp != st->endc)
1.288 rillig 2734: goto bad_modifier; /* Found junk after ']' */
2735:
2736: if (estr[0] == '\0')
2737: goto bad_modifier; /* empty square brackets in ":[]". */
1.236 rillig 2738:
1.288 rillig 2739: if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
1.301 rillig 2740: if (st->oneBigWord) {
1.349 rillig 2741: st->newVal = bmake_strdup("1");
1.236 rillig 2742: } else {
1.412 rillig 2743: Buffer buf;
2744:
1.479 rillig 2745: Words words = Str_Words(st->val, FALSE);
2746: size_t ac = words.len;
2747: Words_Free(words);
1.494 rillig 2748:
1.479 rillig 2749: Buf_Init(&buf, 4); /* 3 digits + '\0' is usually enough */
1.465 rillig 2750: Buf_AddInt(&buf, (int)ac);
1.349 rillig 2751: st->newVal = Buf_Destroy(&buf, FALSE);
1.236 rillig 2752: }
1.288 rillig 2753: goto ok;
2754: }
2755:
2756: if (estr[0] == '*' && estr[1] == '\0') {
1.236 rillig 2757: /* Found ":[*]" */
1.301 rillig 2758: st->oneBigWord = TRUE;
1.349 rillig 2759: st->newVal = st->val;
1.288 rillig 2760: goto ok;
2761: }
2762:
2763: if (estr[0] == '@' && estr[1] == '\0') {
1.236 rillig 2764: /* Found ":[@]" */
1.301 rillig 2765: st->oneBigWord = FALSE;
1.349 rillig 2766: st->newVal = st->val;
1.288 rillig 2767: goto ok;
2768: }
2769:
2770: /*
2771: * We expect estr to contain a single integer for :[N], or two integers
2772: * separated by ".." for :[start..end].
2773: */
1.635 rillig 2774: p = estr;
2775: if (!TryParseIntBase0(&p, &first))
2776: goto bad_modifier; /* Found junk instead of a number */
1.288 rillig 2777:
1.635 rillig 2778: if (p[0] == '\0') { /* Found only one integer in :[N] */
1.290 rillig 2779: last = first;
1.635 rillig 2780: } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') {
1.288 rillig 2781: /* Expecting another integer after ".." */
1.635 rillig 2782: p += 2;
2783: if (!TryParseIntBase0(&p, &last) || *p != '\0')
2784: goto bad_modifier; /* Found junk after ".." */
1.288 rillig 2785: } else
2786: goto bad_modifier; /* Found junk instead of ".." */
1.236 rillig 2787:
1.288 rillig 2788: /*
1.633 rillig 2789: * Now first and last are properly filled in, but we still have to check
2790: * for 0 as a special case.
1.288 rillig 2791: */
1.290 rillig 2792: if (first == 0 && last == 0) {
1.288 rillig 2793: /* ":[0]" or perhaps ":[0..0]" */
1.301 rillig 2794: st->oneBigWord = TRUE;
1.349 rillig 2795: st->newVal = st->val;
1.288 rillig 2796: goto ok;
1.236 rillig 2797: }
1.288 rillig 2798:
2799: /* ":[0..N]" or ":[N..0]" */
1.290 rillig 2800: if (first == 0 || last == 0)
1.288 rillig 2801: goto bad_modifier;
2802:
1.633 rillig 2803: /* Normal case: select the words described by first and last. */
1.349 rillig 2804: st->newVal = VarSelectWords(st->sep, st->oneBigWord, st->val, first, last);
1.288 rillig 2805:
2806: ok:
2807: free(estr);
1.356 rillig 2808: return AMR_OK;
1.288 rillig 2809:
2810: bad_modifier:
2811: free(estr);
1.356 rillig 2812: return AMR_BAD;
1.236 rillig 2813: }
2814:
1.404 rillig 2815: static int
2816: str_cmp_asc(const void *a, const void *b)
2817: {
2818: return strcmp(*(const char * const *)a, *(const char * const *)b);
2819: }
2820:
2821: static int
2822: str_cmp_desc(const void *a, const void *b)
2823: {
2824: return strcmp(*(const char * const *)b, *(const char * const *)a);
2825: }
2826:
1.402 rillig 2827: /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
1.356 rillig 2828: static ApplyModifierResult
1.409 rillig 2829: ApplyModifier_Order(const char **pp, ApplyModifiersState *st)
1.236 rillig 2830: {
1.409 rillig 2831: const char *mod = (*pp)++; /* skip past the 'O' in any case */
1.402 rillig 2832:
1.479 rillig 2833: Words words = Str_Words(st->val, FALSE);
1.401 rillig 2834:
1.299 rillig 2835: if (mod[1] == st->endc || mod[1] == ':') {
1.417 rillig 2836: /* :O sorts ascending */
1.479 rillig 2837: qsort(words.words, words.len, sizeof(char *), str_cmp_asc);
1.402 rillig 2838:
1.299 rillig 2839: } else if ((mod[1] == 'r' || mod[1] == 'x') &&
2840: (mod[2] == st->endc || mod[2] == ':')) {
1.409 rillig 2841: (*pp)++;
1.402 rillig 2842:
2843: if (mod[1] == 'r') {
2844: /* :Or sorts descending */
1.479 rillig 2845: qsort(words.words, words.len, sizeof(char *), str_cmp_desc);
1.402 rillig 2846:
2847: } else {
2848: /* :Ox shuffles
2849: *
2850: * We will use [ac..2] range for mod factors. This will produce
2851: * random numbers in [(ac-1)..0] interval, and minimal
2852: * reasonable value for mod factor is 2 (the mod 1 will produce
2853: * 0 with probability 1).
2854: */
1.465 rillig 2855: size_t i;
1.479 rillig 2856: for (i = words.len - 1; i > 0; i--) {
1.465 rillig 2857: size_t rndidx = (size_t)random() % (i + 1);
1.479 rillig 2858: char *t = words.words[i];
2859: words.words[i] = words.words[rndidx];
2860: words.words[rndidx] = t;
1.402 rillig 2861: }
2862: }
1.236 rillig 2863: } else {
1.479 rillig 2864: Words_Free(words);
1.356 rillig 2865: return AMR_BAD;
1.236 rillig 2866: }
1.402 rillig 2867:
1.479 rillig 2868: st->newVal = Words_JoinFree(words);
1.356 rillig 2869: return AMR_OK;
1.236 rillig 2870: }
2871:
2872: /* :? then : else */
1.356 rillig 2873: static ApplyModifierResult
1.409 rillig 2874: ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
1.236 rillig 2875: {
1.412 rillig 2876: char *then_expr, *else_expr;
1.531 rillig 2877: VarParseResult res;
1.412 rillig 2878:
1.285 rillig 2879: Boolean value = FALSE;
1.448 rillig 2880: VarEvalFlags then_eflags = st->eflags & ~(unsigned)VARE_WANTRES;
2881: VarEvalFlags else_eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.236 rillig 2882:
1.384 rillig 2883: int cond_rc = COND_PARSE; /* anything other than COND_INVALID */
1.268 rillig 2884: if (st->eflags & VARE_WANTRES) {
1.511 rillig 2885: cond_rc = Cond_EvalCondition(st->v->name, &value);
1.285 rillig 2886: if (cond_rc != COND_INVALID && value)
2887: then_eflags |= VARE_WANTRES;
2888: if (cond_rc != COND_INVALID && !value)
2889: else_eflags |= VARE_WANTRES;
1.236 rillig 2890: }
2891:
1.409 rillig 2892: (*pp)++; /* skip past the '?' */
1.535 rillig 2893: res = ParseModifierPart(pp, ':', then_eflags, st,
1.531 rillig 2894: &then_expr, NULL, NULL, NULL);
2895: if (res != VPR_OK)
1.356 rillig 2896: return AMR_CLEANUP;
1.236 rillig 2897:
1.535 rillig 2898: res = ParseModifierPart(pp, st->endc, else_eflags, st,
1.531 rillig 2899: &else_expr, NULL, NULL, NULL);
2900: if (res != VPR_OK)
1.356 rillig 2901: return AMR_CLEANUP;
1.236 rillig 2902:
1.409 rillig 2903: (*pp)--;
1.236 rillig 2904: if (cond_rc == COND_INVALID) {
2905: Error("Bad conditional expression `%s' in %s?%s:%s",
1.417 rillig 2906: st->v->name, st->v->name, then_expr, else_expr);
1.356 rillig 2907: return AMR_CLEANUP;
1.236 rillig 2908: }
2909:
2910: if (value) {
1.349 rillig 2911: st->newVal = then_expr;
1.258 rillig 2912: free(else_expr);
1.236 rillig 2913: } else {
1.349 rillig 2914: st->newVal = else_expr;
1.270 rillig 2915: free(then_expr);
1.236 rillig 2916: }
1.527 rillig 2917: ApplyModifiersState_Define(st);
1.356 rillig 2918: return AMR_OK;
1.236 rillig 2919: }
2920:
1.283 rillig 2921: /*
2922: * The ::= modifiers actually assign a value to the variable.
2923: * Their main purpose is in supporting modifiers of .for loop
2924: * iterators and other obscure uses. They always expand to
2925: * nothing. In a target rule that would otherwise expand to an
2926: * empty line they can be preceded with @: to keep make happy.
2927: * Eg.
2928: *
2929: * foo: .USE
2930: * .for i in ${.TARGET} ${.TARGET:R}.gz
1.546 rillig 2931: * @: ${t::=$i}
1.283 rillig 2932: * @echo blah ${t:T}
2933: * .endfor
2934: *
2935: * ::=<str> Assigns <str> as the new value of variable.
2936: * ::?=<str> Assigns <str> as value of variable if
2937: * it was not already set.
2938: * ::+=<str> Appends <str> to variable.
2939: * ::!=<cmd> Assigns output of <cmd> as the new value of
2940: * variable.
2941: */
1.356 rillig 2942: static ApplyModifierResult
1.409 rillig 2943: ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
1.236 rillig 2944: {
1.412 rillig 2945: GNode *v_ctxt;
2946: char delim;
2947: char *val;
1.531 rillig 2948: VarParseResult res;
1.412 rillig 2949:
1.409 rillig 2950: const char *mod = *pp;
1.299 rillig 2951: const char *op = mod + 1;
1.236 rillig 2952:
1.638 rillig 2953: if (op[0] == '=')
1.640 ! rillig 2954: goto ok;
1.638 rillig 2955: if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=')
2956: goto ok;
2957: return AMR_UNKNOWN; /* "::<unrecognised>" */
2958: ok:
1.272 rillig 2959:
1.570 rillig 2960: if (st->v->name[0] == '\0') {
1.409 rillig 2961: *pp = mod + 1;
1.356 rillig 2962: return AMR_BAD;
1.355 rillig 2963: }
1.272 rillig 2964:
1.412 rillig 2965: v_ctxt = st->ctxt; /* context where v belongs */
1.570 rillig 2966: if (!(st->exprFlags & VEF_UNDEF) && st->ctxt != VAR_GLOBAL) {
1.272 rillig 2967: Var *gv = VarFind(st->v->name, st->ctxt, 0);
2968: if (gv == NULL)
2969: v_ctxt = VAR_GLOBAL;
2970: else
2971: VarFreeEnv(gv, TRUE);
2972: }
2973:
1.273 rillig 2974: switch (op[0]) {
1.272 rillig 2975: case '+':
2976: case '?':
2977: case '!':
1.409 rillig 2978: *pp = mod + 3;
1.272 rillig 2979: break;
2980: default:
1.409 rillig 2981: *pp = mod + 2;
1.272 rillig 2982: break;
2983: }
2984:
1.521 rillig 2985: delim = st->startc == '(' ? ')' : '}';
1.531 rillig 2986: res = ParseModifierPart(pp, delim, st->eflags, st, &val, NULL, NULL, NULL);
2987: if (res != VPR_OK)
1.356 rillig 2988: return AMR_CLEANUP;
1.236 rillig 2989:
1.409 rillig 2990: (*pp)--;
1.236 rillig 2991:
1.272 rillig 2992: if (st->eflags & VARE_WANTRES) {
1.273 rillig 2993: switch (op[0]) {
1.236 rillig 2994: case '+':
1.273 rillig 2995: Var_Append(st->v->name, val, v_ctxt);
1.272 rillig 2996: break;
1.273 rillig 2997: case '!': {
1.416 rillig 2998: const char *errfmt;
2999: char *cmd_output = Cmd_Exec(val, &errfmt);
3000: if (errfmt)
1.472 rillig 3001: Error(errfmt, val);
1.272 rillig 3002: else
1.406 rillig 3003: Var_Set(st->v->name, cmd_output, v_ctxt);
3004: free(cmd_output);
1.236 rillig 3005: break;
1.273 rillig 3006: }
1.272 rillig 3007: case '?':
1.527 rillig 3008: if (!(st->exprFlags & VEF_UNDEF))
1.272 rillig 3009: break;
3010: /* FALLTHROUGH */
1.236 rillig 3011: default:
1.273 rillig 3012: Var_Set(st->v->name, val, v_ctxt);
1.236 rillig 3013: break;
3014: }
3015: }
1.273 rillig 3016: free(val);
1.536 rillig 3017: st->newVal = emptyString;
1.356 rillig 3018: return AMR_OK;
1.236 rillig 3019: }
3020:
1.639 rillig 3021: /* :_=...
3022: * remember current value */
1.356 rillig 3023: static ApplyModifierResult
1.409 rillig 3024: ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
1.236 rillig 3025: {
1.409 rillig 3026: const char *mod = *pp;
1.358 rillig 3027: if (!ModMatchEq(mod, "_", st->endc))
1.356 rillig 3028: return AMR_UNKNOWN;
1.236 rillig 3029:
1.299 rillig 3030: if (mod[1] == '=') {
1.340 rillig 3031: size_t n = strcspn(mod + 2, ":)}");
1.450 rillig 3032: char *name = bmake_strldup(mod + 2, n);
1.349 rillig 3033: Var_Set(name, st->val, st->ctxt);
1.340 rillig 3034: free(name);
1.409 rillig 3035: *pp = mod + 2 + n;
1.236 rillig 3036: } else {
1.349 rillig 3037: Var_Set("_", st->val, st->ctxt);
1.409 rillig 3038: *pp = mod + 1;
1.236 rillig 3039: }
1.349 rillig 3040: st->newVal = st->val;
1.356 rillig 3041: return AMR_OK;
1.236 rillig 3042: }
3043:
1.639 rillig 3044: /* Apply the given function to each word of the variable value,
3045: * for a single-letter modifier such as :H, :T. */
1.434 rillig 3046: static ApplyModifierResult
3047: ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
3048: ModifyWordsCallback modifyWord)
3049: {
3050: char delim = (*pp)[1];
3051: if (delim != st->endc && delim != ':')
3052: return AMR_UNKNOWN;
3053:
1.619 rillig 3054: st->newVal = ModifyWords(st->val, modifyWord, NULL,
3055: st->oneBigWord, st->sep);
1.434 rillig 3056: (*pp)++;
3057: return AMR_OK;
3058: }
3059:
1.567 rillig 3060: static ApplyModifierResult
3061: ApplyModifier_Unique(const char **pp, ApplyModifiersState *st)
3062: {
3063: if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
3064: st->newVal = VarUniq(st->val);
3065: (*pp)++;
3066: return AMR_OK;
3067: } else
3068: return AMR_UNKNOWN;
3069: }
3070:
1.236 rillig 3071: #ifdef SYSVVARSUB
3072: /* :from=to */
1.356 rillig 3073: static ApplyModifierResult
1.409 rillig 3074: ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
1.236 rillig 3075: {
1.412 rillig 3076: char *lhs, *rhs;
1.531 rillig 3077: VarParseResult res;
1.412 rillig 3078:
1.409 rillig 3079: const char *mod = *pp;
1.276 rillig 3080: Boolean eqFound = FALSE;
1.245 rillig 3081:
1.236 rillig 3082: /*
1.639 rillig 3083: * First we make a pass through the string trying to verify it is a
3084: * SysV-make-style translation. It must be: <lhs>=<rhs>
1.236 rillig 3085: */
1.639 rillig 3086: int depth = 1;
3087: const char *p = mod;
3088: while (*p != '\0' && depth > 0) {
3089: if (*p == '=') { /* XXX: should also test depth == 1 */
1.236 rillig 3090: eqFound = TRUE;
3091: /* continue looking for st->endc */
1.639 rillig 3092: } else if (*p == st->endc)
3093: depth--;
3094: else if (*p == st->startc)
3095: depth++;
3096: if (depth > 0)
3097: p++;
1.236 rillig 3098: }
1.639 rillig 3099: if (*p != st->endc || !eqFound)
1.356 rillig 3100: return AMR_UNKNOWN;
1.236 rillig 3101:
1.409 rillig 3102: *pp = mod;
1.535 rillig 3103: res = ParseModifierPart(pp, '=', st->eflags, st,
3104: &lhs, NULL, NULL, NULL);
1.531 rillig 3105: if (res != VPR_OK)
1.356 rillig 3106: return AMR_CLEANUP;
1.245 rillig 3107:
1.640 ! rillig 3108: /* The SysV modifier lasts until the end of the variable expression. */
1.535 rillig 3109: res = ParseModifierPart(pp, st->endc, st->eflags, st,
3110: &rhs, NULL, NULL, NULL);
1.531 rillig 3111: if (res != VPR_OK)
1.356 rillig 3112: return AMR_CLEANUP;
1.236 rillig 3113:
1.409 rillig 3114: (*pp)--;
1.492 rillig 3115: if (lhs[0] == '\0' && st->val[0] == '\0') {
1.349 rillig 3116: st->newVal = st->val; /* special case */
1.245 rillig 3117: } else {
1.541 rillig 3118: struct ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs};
1.619 rillig 3119: st->newVal = ModifyWords(st->val, ModifyWord_SYSVSubst, &args,
3120: st->oneBigWord, st->sep);
1.245 rillig 3121: }
1.276 rillig 3122: free(lhs);
3123: free(rhs);
1.356 rillig 3124: return AMR_OK;
1.236 rillig 3125: }
3126: #endif
3127:
1.548 rillig 3128: #ifdef SUNSHCMD
3129: /* :sh */
3130: static ApplyModifierResult
3131: ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st)
3132: {
3133: const char *p = *pp;
3134: if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) {
3135: if (st->eflags & VARE_WANTRES) {
3136: const char *errfmt;
3137: st->newVal = Cmd_Exec(st->val, &errfmt);
3138: if (errfmt)
3139: Error(errfmt, st->val);
3140: } else
3141: st->newVal = emptyString;
3142: *pp = p + 2;
3143: return AMR_OK;
3144: } else
3145: return AMR_UNKNOWN;
3146: }
3147: #endif
3148:
1.549 rillig 3149: static void
3150: LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc)
3151: {
3152: char eflags_str[VarEvalFlags_ToStringSize];
3153: char vflags_str[VarFlags_ToStringSize];
3154: char exprflags_str[VarExprFlags_ToStringSize];
3155: Boolean is_single_char = mod[0] != '\0' &&
3156: (mod[1] == endc || mod[1] == ':');
3157:
3158: /* At this point, only the first character of the modifier can
3159: * be used since the end of the modifier is not yet known. */
1.550 rillig 3160: debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n",
3161: st->v->name, mod[0], is_single_char ? "" : "...", st->val,
3162: Enum_FlagsToString(eflags_str, sizeof eflags_str,
3163: st->eflags, VarEvalFlags_ToStringSpecs),
3164: Enum_FlagsToString(vflags_str, sizeof vflags_str,
3165: st->v->flags, VarFlags_ToStringSpecs),
3166: Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
3167: st->exprFlags,
3168: VarExprFlags_ToStringSpecs));
1.549 rillig 3169: }
3170:
3171: static void
3172: LogAfterApply(ApplyModifiersState *st, const char *p, const char *mod)
3173: {
3174: char eflags_str[VarEvalFlags_ToStringSize];
3175: char vflags_str[VarFlags_ToStringSize];
3176: char exprflags_str[VarExprFlags_ToStringSize];
3177: const char *quot = st->newVal == var_Error ? "" : "\"";
3178: const char *newVal = st->newVal == var_Error ? "error" : st->newVal;
3179:
1.550 rillig 3180: debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n",
3181: st->v->name, (int)(p - mod), mod, quot, newVal, quot,
3182: Enum_FlagsToString(eflags_str, sizeof eflags_str,
3183: st->eflags, VarEvalFlags_ToStringSpecs),
3184: Enum_FlagsToString(vflags_str, sizeof vflags_str,
3185: st->v->flags, VarFlags_ToStringSpecs),
3186: Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
3187: st->exprFlags,
3188: VarExprFlags_ToStringSpecs));
1.549 rillig 3189: }
3190:
1.551 rillig 3191: static ApplyModifierResult
3192: ApplyModifier(const char **pp, ApplyModifiersState *st)
3193: {
3194: switch (**pp) {
3195: case ':':
3196: return ApplyModifier_Assign(pp, st);
3197: case '@':
3198: return ApplyModifier_Loop(pp, st);
3199: case '_':
3200: return ApplyModifier_Remember(pp, st);
3201: case 'D':
3202: case 'U':
3203: return ApplyModifier_Defined(pp, st);
3204: case 'L':
1.571 rillig 3205: return ApplyModifier_Literal(pp, st);
1.551 rillig 3206: case 'P':
3207: return ApplyModifier_Path(pp, st);
3208: case '!':
3209: return ApplyModifier_ShellCommand(pp, st);
3210: case '[':
3211: return ApplyModifier_Words(pp, st);
3212: case 'g':
3213: return ApplyModifier_Gmtime(pp, st);
3214: case 'h':
3215: return ApplyModifier_Hash(pp, st);
3216: case 'l':
3217: return ApplyModifier_Localtime(pp, st);
3218: case 't':
3219: return ApplyModifier_To(pp, st);
3220: case 'N':
3221: case 'M':
3222: return ApplyModifier_Match(pp, st);
3223: case 'S':
3224: return ApplyModifier_Subst(pp, st);
3225: case '?':
3226: return ApplyModifier_IfElse(pp, st);
3227: #ifndef NO_REGEX
3228: case 'C':
3229: return ApplyModifier_Regex(pp, st);
3230: #endif
3231: case 'q':
3232: case 'Q':
1.571 rillig 3233: return ApplyModifier_Quote(pp, st);
1.551 rillig 3234: case 'T':
3235: return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail);
3236: case 'H':
3237: return ApplyModifier_WordFunc(pp, st, ModifyWord_Head);
3238: case 'E':
3239: return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix);
3240: case 'R':
3241: return ApplyModifier_WordFunc(pp, st, ModifyWord_Root);
3242: case 'r':
3243: return ApplyModifier_Range(pp, st);
3244: case 'O':
3245: return ApplyModifier_Order(pp, st);
3246: case 'u':
1.571 rillig 3247: return ApplyModifier_Unique(pp, st);
1.551 rillig 3248: #ifdef SUNSHCMD
3249: case 's':
3250: return ApplyModifier_SunShell(pp, st);
3251: #endif
3252: default:
3253: return AMR_UNKNOWN;
3254: }
3255: }
3256:
1.419 rillig 3257: /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
1.108 sjg 3258: static char *
1.357 rillig 3259: ApplyModifiers(
1.367 rillig 3260: const char **pp, /* the parsing position, updated upon return */
1.640 ! rillig 3261: char *const val, /* the current value of the expression */
1.444 rillig 3262: char const startc, /* '(' or '{', or '\0' for indirect modifiers */
3263: char const endc, /* ')' or '}', or '\0' for indirect modifiers */
1.527 rillig 3264: Var * const v,
3265: VarExprFlags *exprFlags,
1.357 rillig 3266: GNode * const ctxt, /* for looking up and modifying variables */
3267: VarEvalFlags const eflags,
1.640 ! rillig 3268: void ** const out_freeIt /* free this after using the return value */
1.357 rillig 3269: ) {
1.236 rillig 3270: ApplyModifiersState st = {
1.640 ! rillig 3271: startc, endc, v, ctxt, eflags,
! 3272: val, /* .val */
1.460 rillig 3273: var_Error, /* .newVal */
1.443 rillig 3274: ' ', /* .sep */
1.527 rillig 3275: FALSE, /* .oneBigWord */
3276: *exprFlags /* .exprFlags */
1.443 rillig 3277: };
1.412 rillig 3278: const char *p;
3279: const char *mod;
3280: ApplyModifierResult res;
3281:
3282: assert(startc == '(' || startc == '{' || startc == '\0');
1.413 rillig 3283: assert(endc == ')' || endc == '}' || endc == '\0');
1.460 rillig 3284: assert(val != NULL);
1.15 christos 3285:
1.412 rillig 3286: p = *pp;
1.299 rillig 3287: while (*p != '\0' && *p != endc) {
1.142 dsl 3288:
1.299 rillig 3289: if (*p == '$') {
1.142 dsl 3290: /*
1.167 sjg 3291: * We may have some complex modifiers in a variable.
1.1 cgd 3292: */
1.489 rillig 3293: const char *nested_p = p;
1.108 sjg 3294: void *freeIt;
1.514 rillig 3295: const char *rval;
1.539 rillig 3296: char c;
1.514 rillig 3297:
3298: (void)Var_Parse(&nested_p, st.ctxt, st.eflags, &rval, &freeIt);
3299: /* TODO: handle errors */
1.1 cgd 3300:
1.167 sjg 3301: /*
1.567 rillig 3302: * If we have not parsed up to st.endc or ':', we are not
3303: * interested. This means the expression ${VAR:${M_1}${M_2}}
3304: * is not accepted, but ${VAR:${M_1}:${M_2}} is.
1.167 sjg 3305: */
1.447 rillig 3306: if (rval[0] != '\0' &&
1.489 rillig 3307: (c = *nested_p) != '\0' && c != ':' && c != st.endc) {
1.567 rillig 3308: if (DEBUG(LINT))
3309: Parse_Error(PARSE_FATAL,
3310: "Missing delimiter ':' after indirect modifier \"%.*s\"",
3311: (int)(nested_p - p), p);
3312:
1.196 christos 3313: free(freeIt);
1.491 rillig 3314: /* XXX: apply_mods doesn't sound like "not interested". */
1.567 rillig 3315: /* XXX: Why is the indirect modifier parsed again by
3316: * apply_mods? If any, p should be advanced to nested_p. */
1.167 sjg 3317: goto apply_mods;
3318: }
3319:
1.547 rillig 3320: VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n",
1.599 rillig 3321: rval, (int)(size_t)(nested_p - p), p);
1.1 cgd 3322:
1.489 rillig 3323: p = nested_p;
1.15 christos 3324:
1.447 rillig 3325: if (rval[0] != '\0') {
1.367 rillig 3326: const char *rval_pp = rval;
1.444 rillig 3327: st.val = ApplyModifiers(&rval_pp, st.val, '\0', '\0', v,
1.640 ! rillig 3328: &st.exprFlags, ctxt, eflags, out_freeIt);
1.349 rillig 3329: if (st.val == var_Error
1.536 rillig 3330: || (st.val == varUndefined && !(st.eflags & VARE_UNDEFERR))
1.367 rillig 3331: || *rval_pp != '\0') {
1.196 christos 3332: free(freeIt);
1.240 rillig 3333: goto out; /* error already reported */
1.1 cgd 3334: }
3335: }
1.196 christos 3336: free(freeIt);
1.567 rillig 3337:
1.299 rillig 3338: if (*p == ':')
3339: p++;
3340: else if (*p == '\0' && endc != '\0') {
1.246 rillig 3341: Error("Unclosed variable specification after complex "
1.417 rillig 3342: "modifier (expecting '%c') for %s", st.endc, st.v->name);
1.119 sjg 3343: goto out;
3344: }
1.108 sjg 3345: continue;
3346: }
1.167 sjg 3347: apply_mods:
1.417 rillig 3348: st.newVal = var_Error; /* default value, in case of errors */
1.409 rillig 3349: mod = p;
1.430 rillig 3350:
1.549 rillig 3351: if (DEBUG(VAR))
3352: LogBeforeApply(&st, mod, endc);
1.430 rillig 3353:
1.551 rillig 3354: res = ApplyModifier(&p, &st);
1.356 rillig 3355:
1.108 sjg 3356: #ifdef SYSVVARSUB
1.409 rillig 3357: if (res == AMR_UNKNOWN) {
3358: assert(p == mod);
3359: res = ApplyModifier_SysV(&p, &st);
3360: }
1.108 sjg 3361: #endif
1.356 rillig 3362:
3363: if (res == AMR_UNKNOWN) {
1.409 rillig 3364: Error("Unknown modifier '%c'", *mod);
3365: for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++)
3366: continue;
1.356 rillig 3367: st.newVal = var_Error;
3368: }
3369: if (res == AMR_CLEANUP)
3370: goto cleanup;
3371: if (res == AMR_BAD)
3372: goto bad_modifier;
3373:
1.549 rillig 3374: if (DEBUG(VAR))
3375: LogAfterApply(&st, p, mod);
1.25 christos 3376:
1.349 rillig 3377: if (st.newVal != st.val) {
1.640 ! rillig 3378: if (*out_freeIt) {
1.349 rillig 3379: free(st.val);
1.640 ! rillig 3380: *out_freeIt = NULL;
1.108 sjg 3381: }
1.349 rillig 3382: st.val = st.newVal;
1.536 rillig 3383: if (st.val != var_Error && st.val != varUndefined &&
3384: st.val != emptyString) {
1.640 ! rillig 3385: *out_freeIt = st.val;
1.108 sjg 3386: }
3387: }
1.409 rillig 3388: if (*p == '\0' && st.endc != '\0') {
1.246 rillig 3389: Error("Unclosed variable specification (expecting '%c') "
1.417 rillig 3390: "for \"%s\" (value \"%s\") modifier %c",
3391: st.endc, st.v->name, st.val, *mod);
1.409 rillig 3392: } else if (*p == ':') {
3393: p++;
1.567 rillig 3394: } else if (DEBUG(LINT) && *p != '\0' && *p != endc) {
3395: Parse_Error(PARSE_FATAL,
3396: "Missing delimiter ':' after modifier \"%.*s\"",
3397: (int)(p - mod), mod);
1.108 sjg 3398: }
3399: }
1.240 rillig 3400: out:
1.367 rillig 3401: *pp = p;
1.536 rillig 3402: assert(st.val != NULL); /* Use var_Error or varUndefined instead. */
1.527 rillig 3403: *exprFlags = st.exprFlags;
1.349 rillig 3404: return st.val;
1.25 christos 3405:
1.240 rillig 3406: bad_modifier:
1.299 rillig 3407: Error("Bad modifier `:%.*s' for %s",
1.409 rillig 3408: (int)strcspn(mod, ":)}"), mod, st.v->name);
1.25 christos 3409:
1.240 rillig 3410: cleanup:
1.409 rillig 3411: *pp = p;
1.640 ! rillig 3412: free(*out_freeIt);
! 3413: *out_freeIt = NULL;
1.527 rillig 3414: *exprFlags = st.exprFlags;
1.231 rillig 3415: return var_Error;
1.108 sjg 3416: }
1.25 christos 3417:
1.626 rillig 3418: /* Only four of the local variables are treated specially as they are the
3419: * only four that will be set when dynamic sources are expanded. */
1.335 rillig 3420: static Boolean
1.626 rillig 3421: VarnameIsDynamic(const char *name, size_t len)
1.335 rillig 3422: {
1.626 rillig 3423: if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
3424: switch (name[0]) {
1.335 rillig 3425: case '@':
3426: case '%':
3427: case '*':
3428: case '!':
3429: return TRUE;
3430: }
3431: return FALSE;
3432: }
3433:
1.626 rillig 3434: if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
3435: return strcmp(name, ".TARGET") == 0 ||
3436: strcmp(name, ".ARCHIVE") == 0 ||
3437: strcmp(name, ".PREFIX") == 0 ||
3438: strcmp(name, ".MEMBER") == 0;
1.335 rillig 3439: }
3440:
3441: return FALSE;
3442: }
3443:
1.502 rillig 3444: static const char *
1.553 rillig 3445: UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags)
1.502 rillig 3446: {
1.594 rillig 3447: if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) {
1.502 rillig 3448: /*
3449: * If substituting a local variable in a non-local context,
3450: * assume it's for dynamic source stuff. We have to handle
3451: * this specially and return the longhand for the variable
3452: * with the dollar sign escaped so it makes it back to the
3453: * caller. Only four of the local variables are treated
3454: * specially as they are the only four that will be set
3455: * when dynamic sources are expanded.
3456: */
3457: switch (varname) {
3458: case '@':
3459: return "$(.TARGET)";
3460: case '%':
3461: return "$(.MEMBER)";
3462: case '*':
3463: return "$(.PREFIX)";
3464: case '!':
3465: return "$(.ARCHIVE)";
3466: }
3467: }
1.536 rillig 3468: return eflags & VARE_UNDEFERR ? var_Error : varUndefined;
1.502 rillig 3469: }
3470:
1.504 rillig 3471: /* Parse a variable name, until the end character or a colon, whichever
3472: * comes first. */
3473: static char *
1.501 rillig 3474: ParseVarname(const char **pp, char startc, char endc,
1.504 rillig 3475: GNode *ctxt, VarEvalFlags eflags,
3476: size_t *out_varname_len)
1.501 rillig 3477: {
1.504 rillig 3478: Buffer buf;
1.501 rillig 3479: const char *p = *pp;
3480: int depth = 1;
3481:
1.504 rillig 3482: Buf_Init(&buf, 0);
3483:
1.501 rillig 3484: while (*p != '\0') {
3485: /* Track depth so we can spot parse errors. */
3486: if (*p == startc)
3487: depth++;
3488: if (*p == endc) {
3489: if (--depth == 0)
3490: break;
3491: }
3492: if (*p == ':' && depth == 1)
3493: break;
1.504 rillig 3494:
1.501 rillig 3495: /* A variable inside a variable, expand. */
3496: if (*p == '$') {
3497: void *freeIt;
1.514 rillig 3498: const char *rval;
3499: (void)Var_Parse(&p, ctxt, eflags, &rval, &freeIt);
3500: /* TODO: handle errors */
1.504 rillig 3501: Buf_AddStr(&buf, rval);
1.501 rillig 3502: free(freeIt);
3503: } else {
1.504 rillig 3504: Buf_AddByte(&buf, *p);
1.501 rillig 3505: p++;
3506: }
3507: }
3508: *pp = p;
1.545 rillig 3509: *out_varname_len = Buf_Len(&buf);
1.504 rillig 3510: return Buf_Destroy(&buf, FALSE);
1.501 rillig 3511: }
3512:
1.507 rillig 3513: static Boolean
3514: ValidShortVarname(char varname, const char *start)
3515: {
1.508 rillig 3516: switch (varname) {
3517: case '\0':
3518: case ')':
3519: case '}':
3520: case ':':
3521: case '$':
1.523 rillig 3522: break; /* and continue below */
1.508 rillig 3523: default:
1.571 rillig 3524: return TRUE;
1.508 rillig 3525: }
1.507 rillig 3526:
3527: if (!DEBUG(LINT))
3528: return FALSE;
3529:
3530: if (varname == '$')
3531: Parse_Error(PARSE_FATAL,
3532: "To escape a dollar, use \\$, not $$, at \"%s\"", start);
3533: else if (varname == '\0')
3534: Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
3535: else
3536: Parse_Error(PARSE_FATAL,
3537: "Invalid variable name '%c', at \"%s\"", varname, start);
3538:
3539: return FALSE;
3540: }
3541:
1.622 rillig 3542: /* Parse a single-character variable name such as $V or $@.
3543: * Return whether to continue parsing. */
3544: static Boolean
1.624 rillig 3545: ParseVarnameShort(
3546: char startc,
3547: const char **pp,
3548: GNode *ctxt,
3549: VarEvalFlags eflags,
3550: VarParseResult *out_FALSE_res,
3551: const char **out_FALSE_val,
3552: Var **out_TRUE_var
3553: ) {
1.622 rillig 3554: char name[2];
3555: Var *v;
3556:
3557: /*
3558: * If it's not bounded by braces of some sort, life is much simpler.
3559: * We just need to check for the first character and return the
3560: * value if it exists.
3561: */
3562:
3563: if (!ValidShortVarname(startc, *pp)) {
3564: (*pp)++;
3565: *out_FALSE_val = var_Error;
3566: *out_FALSE_res = VPR_PARSE_MSG;
3567: return FALSE;
3568: }
3569:
3570: name[0] = startc;
3571: name[1] = '\0';
3572: v = VarFind(name, ctxt, TRUE);
3573: if (v == NULL) {
3574: *pp += 2;
3575:
3576: *out_FALSE_val = UndefinedShortVarValue(startc, ctxt, eflags);
3577: if (DEBUG(LINT) && *out_FALSE_val == var_Error) {
3578: Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", name);
3579: *out_FALSE_res = VPR_UNDEF_MSG;
3580: return FALSE;
3581: }
3582: *out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF_SILENT : VPR_OK;
3583: return FALSE;
3584: }
3585:
3586: *out_TRUE_var = v;
3587: return TRUE;
3588: }
3589:
1.623 rillig 3590: /* Parse a long variable name enclosed in braces or parentheses such as $(VAR)
3591: * or ${VAR}, up to the closing brace or parenthesis, or in the case of
3592: * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
3593: * Return whether to continue parsing. */
3594: static Boolean
3595: ParseVarnameLong(
1.624 rillig 3596: const char **pp,
3597: char startc,
3598: GNode *ctxt,
3599: VarEvalFlags eflags,
3600:
3601: VarParseResult *out_FALSE_res,
3602: const char **out_FALSE_val,
3603: void **out_FALSE_freePtr,
3604:
3605: char *out_TRUE_endc,
3606: const char **out_TRUE_p,
3607: Var **out_TRUE_v,
3608: Boolean *out_TRUE_haveModifier,
3609: const char **out_TRUE_extraModifiers,
3610: Boolean *out_TRUE_dynamic,
3611: VarExprFlags *out_TRUE_exprFlags
1.623 rillig 3612: ) {
3613: size_t namelen;
3614: char *varname;
3615: Var *v;
3616: Boolean haveModifier;
3617: Boolean dynamic = FALSE;
3618:
3619: const char *const start = *pp;
3620: char endc = startc == '(' ? ')' : '}';
3621:
3622: const char *p = start + 2;
3623: varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen);
3624:
3625: if (*p == ':') {
3626: haveModifier = TRUE;
3627: } else if (*p == endc) {
3628: haveModifier = FALSE;
3629: } else {
3630: Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname);
3631: *pp = p;
3632: free(varname);
3633: *out_FALSE_val = var_Error;
3634: *out_FALSE_res = VPR_PARSE_MSG;
3635: return FALSE;
3636: }
3637:
3638: v = VarFind(varname, ctxt, TRUE);
3639:
3640: /* At this point, p points just after the variable name,
3641: * either at ':' or at endc. */
3642:
3643: /*
3644: * Check also for bogus D and F forms of local variables since we're
3645: * in a local context and the name is the right length.
3646: */
3647: if (v == NULL && ctxt != VAR_CMDLINE && ctxt != VAR_GLOBAL &&
3648: namelen == 2 && (varname[1] == 'F' || varname[1] == 'D') &&
3649: strchr("@%?*!<>", varname[0]) != NULL)
3650: {
3651: /*
3652: * Well, it's local -- go look for it.
3653: */
3654: char name[] = { varname[0], '\0' };
3655: v = VarFind(name, ctxt, 0);
3656:
3657: if (v != NULL) {
3658: if (varname[1] == 'D') {
3659: *out_TRUE_extraModifiers = "H:";
3660: } else { /* F */
3661: *out_TRUE_extraModifiers = "T:";
3662: }
3663: }
3664: }
3665:
3666: if (v == NULL) {
1.626 rillig 3667: /* Defer expansion of dynamic variables if they appear in non-local
3668: * context since they are not defined there. */
3669: dynamic = VarnameIsDynamic(varname, namelen) &&
3670: (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL);
1.623 rillig 3671:
3672: if (!haveModifier) {
3673: p++; /* skip endc */
3674: *pp = p;
3675: if (dynamic) {
3676: char *pstr = bmake_strsedup(start, p);
3677: free(varname);
3678: *out_FALSE_res = VPR_OK;
3679: *out_FALSE_freePtr = pstr;
3680: *out_FALSE_val = pstr;
3681: return FALSE;
3682: }
3683:
3684: if ((eflags & VARE_UNDEFERR) && (eflags & VARE_WANTRES) &&
3685: DEBUG(LINT))
3686: {
3687: Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined",
3688: varname);
3689: free(varname);
3690: *out_FALSE_res = VPR_UNDEF_MSG;
3691: *out_FALSE_val = var_Error;
3692: return FALSE;
3693: }
3694:
3695: if (eflags & VARE_UNDEFERR) {
3696: free(varname);
3697: *out_FALSE_res = VPR_UNDEF_SILENT;
3698: *out_FALSE_val = var_Error;
3699: return FALSE;
3700: }
3701:
3702: free(varname);
3703: *out_FALSE_res = VPR_OK;
3704: *out_FALSE_val = varUndefined;
3705: return FALSE;
3706: }
3707:
3708: /* The variable expression is based on an undefined variable.
3709: * Nevertheless it needs a Var, for modifiers that access the
3710: * variable name, such as :L or :?.
3711: *
3712: * Most modifiers leave this expression in the "undefined" state
3713: * (VEF_UNDEF), only a few modifiers like :D, :U, :L, :P turn this
3714: * undefined expression into a defined expression (VEF_DEF).
3715: *
3716: * At the end, after applying all modifiers, if the expression
3717: * is still undefined, Var_Parse will return an empty string
3718: * instead of the actually computed value. */
3719: v = VarNew(varname, varname, "", 0);
3720: *out_TRUE_exprFlags = VEF_UNDEF;
3721: } else
3722: free(varname);
3723:
3724: *out_TRUE_endc = endc;
3725: *out_TRUE_p = p;
3726: *out_TRUE_v = v;
3727: *out_TRUE_haveModifier = haveModifier;
3728: *out_TRUE_dynamic = dynamic;
3729: return TRUE;
3730: }
3731:
1.108 sjg 3732: /*-
3733: *-----------------------------------------------------------------------
3734: * Var_Parse --
1.503 rillig 3735: * Given the start of a variable expression (such as $v, $(VAR),
1.328 rillig 3736: * ${VAR:Mpattern}), extract the variable name, possibly some
3737: * modifiers and find its value by applying the modifiers to the
3738: * original value.
1.108 sjg 3739: *
1.579 rillig 3740: * When parsing a condition in ParseEmptyArg, pp may also point to
3741: * the "y" of "empty(VARNAME:Modifiers)", which is syntactically
3742: * identical.
3743: *
1.108 sjg 3744: * Input:
3745: * str The string to parse
3746: * ctxt The context for the variable
1.625 rillig 3747: * flags Select the exact details of parsing
3748: * out_val_freeIt Must be freed by the caller after using out_val
1.108 sjg 3749: *
3750: * Results:
1.478 rillig 3751: * Returns the value of the variable expression, never NULL.
1.536 rillig 3752: * Returns var_Error if there was a parse error and VARE_UNDEFERR was
3753: * set.
3754: * Returns varUndefined if there was an undefined variable and
3755: * VARE_UNDEFERR was not set.
3756: *
3757: * Parsing should continue at *pp.
3758: * TODO: Document the value of *pp on parse errors. It might be advanced
3759: * by 0, or +1, or the index of the parse error, or the guessed end of the
1.491 rillig 3760: * variable expression.
3761: *
3762: * If var_Error is returned, a diagnostic may or may not have been
3763: * printed. XXX: This is inconsistent.
3764: *
1.536 rillig 3765: * If varUndefined is returned, a diagnostic may or may not have been
3766: * printed. XXX: This is inconsistent.
1.455 rillig 3767: *
1.625 rillig 3768: * After using the returned value, *out_val_freeIt must be freed,
3769: * preferably using bmake_free since it is NULL in most cases.
1.108 sjg 3770: *
3771: * Side Effects:
1.429 rillig 3772: * Any effects from the modifiers, such as :!cmd! or ::=value.
1.108 sjg 3773: *-----------------------------------------------------------------------
3774: */
1.514 rillig 3775: /* coverity[+alloc : arg-*4] */
1.526 rillig 3776: VarParseResult
1.514 rillig 3777: Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags,
1.625 rillig 3778: const char **out_val, void **out_val_freeIt)
1.108 sjg 3779: {
1.498 rillig 3780: const char *const start = *pp;
3781: const char *p;
1.546 rillig 3782: Boolean haveModifier; /* TRUE if have modifiers for the variable */
3783: char startc; /* Starting character if variable in parens
1.401 rillig 3784: * or braces */
1.546 rillig 3785: char endc; /* Ending character if variable in parens
1.108 sjg 3786: * or braces */
1.546 rillig 3787: Boolean dynamic; /* TRUE if the variable is local and we're
1.108 sjg 3788: * expanding it in a non-local context. This
3789: * is done to support dynamic sources. The
1.503 rillig 3790: * result is just the expression, unaltered */
1.412 rillig 3791: const char *extramodifiers;
3792: Var *v;
3793: char *nstr;
1.436 rillig 3794: char eflags_str[VarEvalFlags_ToStringSize];
1.527 rillig 3795: VarExprFlags exprFlags = 0;
1.432 rillig 3796:
1.626 rillig 3797: VAR_DEBUG2("Var_Parse: %s with %s\n", start,
1.547 rillig 3798: Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags,
3799: VarEvalFlags_ToStringSpecs));
1.1 cgd 3800:
1.625 rillig 3801: *out_val_freeIt = NULL;
1.412 rillig 3802: extramodifiers = NULL; /* extra modifiers to apply first */
1.108 sjg 3803: dynamic = FALSE;
1.1 cgd 3804:
1.510 martin 3805: /* Appease GCC, which thinks that the variable might not be
1.473 rillig 3806: * initialized. */
3807: endc = '\0';
3808:
1.497 rillig 3809: startc = start[1];
1.521 rillig 3810: if (startc != '(' && startc != '{') {
1.623 rillig 3811: VarParseResult res;
1.624 rillig 3812: if (!ParseVarnameShort(startc, pp, ctxt, eflags, &res, out_val, &v))
1.622 rillig 3813: return res;
3814: haveModifier = FALSE;
3815: p = start + 1;
1.123 apb 3816: } else {
1.623 rillig 3817: VarParseResult res;
3818: if (!ParseVarnameLong(pp, startc, ctxt, eflags,
1.625 rillig 3819: &res, out_val, out_val_freeIt,
1.623 rillig 3820: &endc, &p, &v, &haveModifier, &extramodifiers,
3821: &dynamic, &exprFlags))
3822: return res;
1.108 sjg 3823: }
3824:
1.615 rillig 3825: if (v->flags & VAR_IN_USE)
1.188 joerg 3826: Fatal("Variable %s is recursive.", v->name);
1.401 rillig 3827:
1.188 joerg 3828: /*
3829: * Before doing any modification, we have to make sure the value
3830: * has been fully expanded. If it looks like recursion might be
3831: * necessary (there's a dollar sign somewhere in the variable's value)
3832: * we just call Var_Subst to do any other substitutions that are
3833: * necessary. Note that the value returned by Var_Subst will have
3834: * been dynamically-allocated, so it will need freeing when we
3835: * return.
3836: */
1.433 rillig 3837: nstr = Buf_GetAll(&v->val, NULL);
1.507 rillig 3838: if (strchr(nstr, '$') != NULL && (eflags & VARE_WANTRES)) {
1.571 rillig 3839: VarEvalFlags nested_eflags = eflags;
3840: if (DEBUG(LINT))
3841: nested_eflags &= ~(unsigned)VARE_UNDEFERR;
1.615 rillig 3842: v->flags |= VAR_IN_USE;
1.533 rillig 3843: (void)Var_Subst(nstr, ctxt, nested_eflags, &nstr);
1.615 rillig 3844: v->flags &= ~(unsigned)VAR_IN_USE;
1.533 rillig 3845: /* TODO: handle errors */
1.625 rillig 3846: *out_val_freeIt = nstr;
1.188 joerg 3847: }
1.187 christos 3848:
1.447 rillig 3849: if (haveModifier || extramodifiers != NULL) {
1.191 dholland 3850: void *extraFree;
1.108 sjg 3851:
1.191 dholland 3852: extraFree = NULL;
3853: if (extramodifiers != NULL) {
1.367 rillig 3854: const char *em = extramodifiers;
3855: nstr = ApplyModifiers(&em, nstr, '(', ')',
1.527 rillig 3856: v, &exprFlags, ctxt, eflags, &extraFree);
1.191 dholland 3857: }
3858:
3859: if (haveModifier) {
1.240 rillig 3860: /* Skip initial colon. */
1.497 rillig 3861: p++;
1.191 dholland 3862:
1.497 rillig 3863: nstr = ApplyModifiers(&p, nstr, startc, endc,
1.625 rillig 3864: v, &exprFlags, ctxt, eflags, out_val_freeIt);
1.240 rillig 3865: free(extraFree);
1.191 dholland 3866: } else {
1.625 rillig 3867: *out_val_freeIt = extraFree;
1.191 dholland 3868: }
1.119 sjg 3869: }
1.438 rillig 3870:
1.519 rillig 3871: if (*p != '\0') /* Skip past endc if possible. */
3872: p++;
3873:
3874: *pp = p;
1.15 christos 3875:
1.1 cgd 3876: if (v->flags & VAR_FROM_ENV) {
1.571 rillig 3877: /* Free the environment variable now since we own it,
3878: * but don't free the variable value if it will be returned. */
1.499 rillig 3879: Boolean keepValue = nstr == Buf_GetAll(&v->val, NULL);
3880: if (keepValue)
1.625 rillig 3881: *out_val_freeIt = nstr;
1.499 rillig 3882: (void)VarFreeEnv(v, !keepValue);
3883:
1.527 rillig 3884: } else if (exprFlags & VEF_UNDEF) {
3885: if (!(exprFlags & VEF_DEF)) {
1.625 rillig 3886: if (*out_val_freeIt != NULL) {
3887: free(*out_val_freeIt);
3888: *out_val_freeIt = NULL;
1.40 sjg 3889: }
3890: if (dynamic) {
1.519 rillig 3891: nstr = bmake_strsedup(start, p);
1.625 rillig 3892: *out_val_freeIt = nstr;
1.40 sjg 3893: } else {
1.528 rillig 3894: /* The expression is still undefined, therefore discard the
1.536 rillig 3895: * actual value and return an error marker instead. */
3896: nstr = (eflags & VARE_UNDEFERR) ? var_Error : varUndefined;
1.40 sjg 3897: }
1.34 christos 3898: }
1.433 rillig 3899: if (nstr != Buf_GetAll(&v->val, NULL))
1.146 dsl 3900: Buf_Destroy(&v->val, TRUE);
1.570 rillig 3901: free(v->name_freeIt);
1.98 christos 3902: free(v);
1.1 cgd 3903: }
1.514 rillig 3904: *out_val = nstr;
1.526 rillig 3905: return VPR_UNKNOWN;
1.1 cgd 3906: }
3907:
1.484 rillig 3908: /* Substitute for all variables in the given string in the given context.
3909: *
3910: * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined
3911: * variable is encountered.
3912: *
3913: * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=,
3914: * :sh or !cmd! take place.
1.1 cgd 3915: *
1.70 wiz 3916: * Input:
3917: * str the string which to substitute
3918: * ctxt the context wherein to find variables
1.333 rillig 3919: * eflags VARE_UNDEFERR if undefineds are an error
1.259 rillig 3920: * VARE_WANTRES if we actually want the result
3921: * VARE_ASSIGN if we are in a := assignment
1.70 wiz 3922: *
1.1 cgd 3923: * Results:
3924: * The resulting string.
3925: */
1.533 rillig 3926: VarParseResult
3927: Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res)
1.1 cgd 3928: {
1.537 rillig 3929: const char *p = str;
1.401 rillig 3930: Buffer buf; /* Buffer for forming things */
1.1 cgd 3931:
1.401 rillig 3932: /* Set true if an error has already been reported,
3933: * to prevent a plethora of messages when recursing */
3934: static Boolean errorReported;
1.412 rillig 3935:
1.433 rillig 3936: Buf_Init(&buf, 0);
1.1 cgd 3937: errorReported = FALSE;
3938:
1.537 rillig 3939: while (*p != '\0') {
3940: if (p[0] == '$' && p[1] == '$') {
1.567 rillig 3941: /* A dollar sign may be escaped with another dollar sign. */
1.333 rillig 3942: if (save_dollars && (eflags & VARE_ASSIGN))
1.381 rillig 3943: Buf_AddByte(&buf, '$');
3944: Buf_AddByte(&buf, '$');
1.537 rillig 3945: p += 2;
3946: } else if (*p != '$') {
1.1 cgd 3947: /*
3948: * Skip as many characters as possible -- either to the end of
1.503 rillig 3949: * the string or to the next dollar sign (variable expression).
1.1 cgd 3950: */
1.537 rillig 3951: const char *plainStart = p;
1.1 cgd 3952:
1.537 rillig 3953: for (p++; *p != '$' && *p != '\0'; p++)
1.5 cgd 3954: continue;
1.537 rillig 3955: Buf_AddBytesBetween(&buf, plainStart, p);
1.1 cgd 3956: } else {
1.537 rillig 3957: const char *nested_p = p;
1.406 rillig 3958: void *freeIt;
1.514 rillig 3959: const char *val;
1.537 rillig 3960: (void)Var_Parse(&nested_p, ctxt, eflags, &val, &freeIt);
1.514 rillig 3961: /* TODO: handle errors */
1.1 cgd 3962:
1.536 rillig 3963: if (val == var_Error || val == varUndefined) {
1.1 cgd 3964: /*
3965: * If performing old-time variable substitution, skip over
3966: * the variable and continue with the substitution. Otherwise,
3967: * store the dollar sign and advance str so we continue with
3968: * the string...
3969: */
3970: if (oldVars) {
1.537 rillig 3971: p = nested_p;
1.333 rillig 3972: } else if ((eflags & VARE_UNDEFERR) || val == var_Error) {
1.1 cgd 3973: /*
3974: * If variable is undefined, complain and skip the
3975: * variable. The complaint will stop us from doing anything
3976: * when the file is parsed.
3977: */
3978: if (!errorReported) {
1.231 rillig 3979: Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",
1.537 rillig 3980: (int)(size_t)(nested_p - p), p);
1.1 cgd 3981: }
1.537 rillig 3982: p = nested_p;
1.1 cgd 3983: errorReported = TRUE;
3984: } else {
1.538 rillig 3985: /* Copy the initial '$' of the undefined expression,
3986: * thereby deferring expansion of the expression, but
3987: * expand nested expressions if already possible.
3988: * See unit-tests/varparse-undef-partial.mk. */
1.537 rillig 3989: Buf_AddByte(&buf, *p);
3990: p++;
1.1 cgd 3991: }
3992: } else {
1.537 rillig 3993: p = nested_p;
1.534 rillig 3994: Buf_AddStr(&buf, val);
1.104 christos 3995: }
1.196 christos 3996: free(freeIt);
3997: freeIt = NULL;
1.1 cgd 3998: }
3999: }
1.15 christos 4000:
1.533 rillig 4001: *out_res = Buf_DestroyCompact(&buf);
4002: return VPR_OK;
1.1 cgd 4003: }
4004:
1.572 rillig 4005: /* Initialize the variables module. */
1.1 cgd 4006: void
1.70 wiz 4007: Var_Init(void)
1.1 cgd 4008: {
1.184 sjg 4009: VAR_INTERNAL = Targ_NewGN("Internal");
1.92 christos 4010: VAR_GLOBAL = Targ_NewGN("Global");
1.594 rillig 4011: VAR_CMDLINE = Targ_NewGN("Command");
1.6 jtc 4012: }
4013:
1.572 rillig 4014: /* Clean up the variables module. */
1.6 jtc 4015: void
1.70 wiz 4016: Var_End(void)
1.6 jtc 4017: {
1.286 sjg 4018: Var_Stats();
4019: }
4020:
4021: void
4022: Var_Stats(void)
4023: {
1.588 rillig 4024: HashTable_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL");
1.1 cgd 4025: }
1.15 christos 4026:
1.573 rillig 4027: /* Print all variables in a context, sorted by name. */
1.5 cgd 4028: void
1.70 wiz 4029: Var_Dump(GNode *ctxt)
1.1 cgd 4030: {
1.585 rillig 4031: Vector /* of const char * */ vec;
1.575 rillig 4032: HashIter hi;
1.573 rillig 4033: size_t i;
1.585 rillig 4034: const char **varnames;
1.573 rillig 4035:
1.585 rillig 4036: Vector_Init(&vec, sizeof(const char *));
1.575 rillig 4037:
4038: HashIter_Init(&hi, &ctxt->context);
1.603 rillig 4039: while (HashIter_Next(&hi) != NULL)
4040: *(const char **)Vector_Push(&vec) = hi.entry->key;
1.585 rillig 4041: varnames = vec.items;
1.573 rillig 4042:
1.585 rillig 4043: qsort(varnames, vec.len, sizeof varnames[0], str_cmp_asc);
1.573 rillig 4044:
1.585 rillig 4045: for (i = 0; i < vec.len; i++) {
1.599 rillig 4046: const char *varname = varnames[i];
4047: Var *var = HashTable_FindValue(&ctxt->context, varname);
1.573 rillig 4048: debug_printf("%-16s = %s\n", varname, Buf_GetAll(&var->val, NULL));
4049: }
4050:
1.585 rillig 4051: Vector_Done(&vec);
1.1 cgd 4052: }
CVSweb <webmaster@jp.NetBSD.org>