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