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