Annotation of src/usr.bin/make/var.c, Revision 1.300
1.300 ! rillig 1: /* $NetBSD: var.c,v 1.299 2020/07/24 07:24:21 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.300 ! rillig 72: static char rcsid[] = "$NetBSD: var.c,v 1.299 2020/07/24 07:24:21 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.300 ! rillig 79: __RCSID("$NetBSD: var.c,v 1.299 2020/07/24 07:24:21 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:
1.296 rillig 1569: for (i = start; (step < 0) == (i >= end); i += step) {
1.278 rillig 1570: if (av[i][0] != '\0') {
1571: SepBuf_AddBytes(&buf, av[i], strlen(av[i]));
1572: SepBuf_Sep(&buf);
1.81 sjg 1573: }
1574: }
1575:
1576: free(as);
1577: free(av);
1578:
1.278 rillig 1579: return SepBuf_Destroy(&buf, FALSE);
1.81 sjg 1580: }
1581:
1.156 sjg 1582:
1.291 rillig 1583: /* Callback for ModifyWords to implement the :tA modifier.
1.244 rillig 1584: * Replace each word with the result of realpath() if successful. */
1.278 rillig 1585: static void
1.295 rillig 1586: ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.156 sjg 1587: {
1.242 rillig 1588: struct stat st;
1589: char rbuf[MAXPATHLEN];
1.231 rillig 1590:
1.278 rillig 1591: char *rp = cached_realpath(word, rbuf);
1.257 rillig 1592: if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1.242 rillig 1593: word = rp;
1.231 rillig 1594:
1.278 rillig 1595: SepBuf_AddBytes(buf, word, strlen(word));
1.156 sjg 1596: }
1597:
1.1 cgd 1598: /*-
1599: *-----------------------------------------------------------------------
1.244 rillig 1600: * Modify each of the words of the passed string using the given function.
1.1 cgd 1601: *
1.70 wiz 1602: * Input:
1.278 rillig 1603: * str String whose words should be modified
1.291 rillig 1604: * modifyWord Function that modifies a single word
1605: * data Custom data for modifyWord
1.70 wiz 1606: *
1.1 cgd 1607: * Results:
1608: * A string of all the words modified appropriately.
1609: *-----------------------------------------------------------------------
1610: */
1611: static char *
1.291 rillig 1612: ModifyWords(GNode *ctx, Var_Parse_State *vpstate,
1613: const char *str, ModifyWordsCallback modifyWord, void *data)
1.1 cgd 1614: {
1.278 rillig 1615: SepBuf result;
1.240 rillig 1616: char **av; /* word list */
1617: char *as; /* word list memory */
1.127 christos 1618: int ac, i;
1.7 jtc 1619:
1.278 rillig 1620: SepBuf_Init(&result, vpstate->varSpace);
1.1 cgd 1621:
1.81 sjg 1622: if (vpstate->oneBigWord) {
1623: /* fake what brk_string() would do if there were only one word */
1624: ac = 1;
1.242 rillig 1625: av = bmake_malloc((ac + 1) * sizeof(char *));
1.134 joerg 1626: as = bmake_strdup(str);
1.81 sjg 1627: av[0] = as;
1628: av[1] = NULL;
1629: } else {
1630: av = brk_string(str, &ac, FALSE, &as);
1631: }
1.1 cgd 1632:
1.255 rillig 1633: if (DEBUG(VAR)) {
1.292 rillig 1634: fprintf(debug_file, "ModifyWords: split \"%s\" into %d words\n",
1.255 rillig 1635: str, ac);
1636: }
1637:
1.278 rillig 1638: for (i = 0; i < ac; i++) {
1639: size_t orig_count = result.buf.count;
1.295 rillig 1640: modifyWord(av[i], &result, data);
1.278 rillig 1641: size_t count = result.buf.count;
1642: if (count != orig_count)
1643: SepBuf_Sep(&result);
1644: }
1.24 christos 1645:
1646: free(as);
1647: free(av);
1.15 christos 1648:
1.278 rillig 1649: vpstate->varSpace = result.sep;
1650: return SepBuf_Destroy(&result, FALSE);
1.1 cgd 1651: }
1652:
1.35 christos 1653:
1654: static int
1.70 wiz 1655: VarWordCompare(const void *a, const void *b)
1.35 christos 1656: {
1.242 rillig 1657: int r = strcmp(*(const char * const *)a, *(const char * const *)b);
1658: return r;
1.35 christos 1659: }
1660:
1.224 sjg 1661: static int
1662: VarWordCompareReverse(const void *a, const void *b)
1663: {
1.242 rillig 1664: int r = strcmp(*(const char * const *)b, *(const char * const *)a);
1665: return r;
1.224 sjg 1666: }
1667:
1.35 christos 1668: /*-
1669: *-----------------------------------------------------------------------
1.93 sjg 1670: * VarOrder --
1671: * Order the words in the string.
1.35 christos 1672: *
1.70 wiz 1673: * Input:
1.93 sjg 1674: * str String whose words should be sorted.
1675: * otype How to order: s - sort, x - random.
1.70 wiz 1676: *
1.35 christos 1677: * Results:
1.93 sjg 1678: * A string containing the words ordered.
1.35 christos 1679: *
1680: * Side Effects:
1681: * None.
1682: *
1683: *-----------------------------------------------------------------------
1684: */
1685: static char *
1.93 sjg 1686: VarOrder(const char *str, const char otype)
1.35 christos 1687: {
1.240 rillig 1688: Buffer buf; /* Buffer for the new string */
1689: char **av; /* word list [first word does not count] */
1690: char *as; /* word list memory */
1.127 christos 1691: int ac, i;
1.35 christos 1692:
1.146 dsl 1693: Buf_Init(&buf, 0);
1.35 christos 1694:
1695: av = brk_string(str, &ac, FALSE, &as);
1696:
1.240 rillig 1697: if (ac > 0) {
1.93 sjg 1698: switch (otype) {
1.240 rillig 1699: case 'r': /* reverse sort alphabetically */
1.224 sjg 1700: qsort(av, ac, sizeof(char *), VarWordCompareReverse);
1701: break;
1.240 rillig 1702: case 's': /* sort alphabetically */
1.93 sjg 1703: qsort(av, ac, sizeof(char *), VarWordCompare);
1704: break;
1.240 rillig 1705: case 'x': /* randomize */
1706: {
1707: /*
1708: * We will use [ac..2] range for mod factors. This will produce
1709: * random numbers in [(ac-1)..0] interval, and minimal
1710: * reasonable value for mod factor is 2 (the mod 1 will produce
1711: * 0 with probability 1).
1712: */
1713: for (i = ac - 1; i > 0; i--) {
1714: int rndidx = random() % (i + 1);
1715: char *t = av[i];
1.93 sjg 1716: av[i] = av[rndidx];
1717: av[rndidx] = t;
1718: }
1719: }
1720: }
1.240 rillig 1721: }
1.35 christos 1722:
1723: for (i = 0; i < ac; i++) {
1.146 dsl 1724: Buf_AddBytes(&buf, strlen(av[i]), av[i]);
1.35 christos 1725: if (i != ac - 1)
1.146 dsl 1726: Buf_AddByte(&buf, ' ');
1.35 christos 1727: }
1728:
1729: free(as);
1730: free(av);
1731:
1.146 dsl 1732: return Buf_Destroy(&buf, FALSE);
1.35 christos 1733: }
1734:
1735:
1.1 cgd 1736: /*-
1737: *-----------------------------------------------------------------------
1.55 christos 1738: * VarUniq --
1739: * Remove adjacent duplicate words.
1740: *
1.70 wiz 1741: * Input:
1742: * str String whose words should be sorted
1743: *
1.55 christos 1744: * Results:
1745: * A string containing the resulting words.
1746: *
1747: * Side Effects:
1748: * None.
1749: *
1750: *-----------------------------------------------------------------------
1751: */
1752: static char *
1.73 christos 1753: VarUniq(const char *str)
1.55 christos 1754: {
1.240 rillig 1755: Buffer buf; /* Buffer for new string */
1756: char **av; /* List of words to affect */
1757: char *as; /* Word list memory */
1.127 christos 1758: int ac, i, j;
1.55 christos 1759:
1.146 dsl 1760: Buf_Init(&buf, 0);
1.55 christos 1761: av = brk_string(str, &ac, FALSE, &as);
1762:
1763: if (ac > 1) {
1764: for (j = 0, i = 1; i < ac; i++)
1765: if (strcmp(av[i], av[j]) != 0 && (++j != i))
1766: av[j] = av[i];
1767: ac = j + 1;
1768: }
1769:
1770: for (i = 0; i < ac; i++) {
1.146 dsl 1771: Buf_AddBytes(&buf, strlen(av[i]), av[i]);
1.55 christos 1772: if (i != ac - 1)
1.146 dsl 1773: Buf_AddByte(&buf, ' ');
1.55 christos 1774: }
1775:
1776: free(as);
1777: free(av);
1778:
1.146 dsl 1779: return Buf_Destroy(&buf, FALSE);
1.55 christos 1780: }
1781:
1.210 sjg 1782: /*-
1783: *-----------------------------------------------------------------------
1784: * VarRange --
1785: * Return an integer sequence
1786: *
1787: * Input:
1788: * str String whose words provide default range
1789: * ac range length, if 0 use str words
1790: *
1791: * Side Effects:
1792: * None.
1793: *
1794: *-----------------------------------------------------------------------
1795: */
1796: static char *
1797: VarRange(const char *str, int ac)
1798: {
1.240 rillig 1799: Buffer buf; /* Buffer for new string */
1800: char tmp[32]; /* each element */
1801: char **av; /* List of words to affect */
1802: char *as; /* Word list memory */
1.210 sjg 1803: int i, n;
1804:
1805: Buf_Init(&buf, 0);
1806: if (ac > 0) {
1807: as = NULL;
1808: av = NULL;
1809: } else {
1810: av = brk_string(str, &ac, FALSE, &as);
1811: }
1812: for (i = 0; i < ac; i++) {
1813: n = snprintf(tmp, sizeof(tmp), "%d", 1 + i);
1814: if (n >= (int)sizeof(tmp))
1815: break;
1816: Buf_AddBytes(&buf, n, tmp);
1817: if (i != ac - 1)
1818: Buf_AddByte(&buf, ' ');
1819: }
1820:
1821: free(as);
1822: free(av);
1823:
1824: return Buf_Destroy(&buf, FALSE);
1825: }
1826:
1.55 christos 1827:
1828: /*-
1.265 rillig 1829: * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/
1830: * or the :@ modifier. Nested variables in the text are expanded unless
1.287 rillig 1831: * VARE_NOSUBST is set.
1.265 rillig 1832: *
1833: * The text part is parsed until the next delimiter. To escape the delimiter,
1834: * a backslash or a dollar, put a backslash before it.
1835: *
1836: * Return the expanded string or NULL if the delimiter was missing.
1837: * If pattern is specified, handle escaped ampersands and replace unescaped
1838: * ampersands with the lhs of the pattern (for the :S and :C modifiers).
1839: *
1840: * If length is specified, return the string length of the buffer.
1841: * If mpflags is specified and the last character of the pattern is a $,
1.288 rillig 1842: * set the VARP_ANCHOR_END bit of mpflags.
1.16 christos 1843: */
1844: static char *
1.266 rillig 1845: ParseModifierPart(GNode *ctxt, const char **tstr, int delim,
1846: VarEvalFlags eflags, VarPatternFlags *mpflags,
1.291 rillig 1847: size_t *length, ModifyWord_SubstArgs *subst)
1.16 christos 1848: {
1.73 christos 1849: const char *cp;
1.146 dsl 1850: char *rstr;
1851: Buffer buf;
1.281 rillig 1852: size_t junk;
1.261 rillig 1853: VarEvalFlags errnum = eflags & VARE_UNDEFERR;
1.146 dsl 1854:
1855: Buf_Init(&buf, 0);
1.16 christos 1856: if (length == NULL)
1857: length = &junk;
1858:
1859: /*
1860: * Skim through until the matching delimiter is found;
1861: * pick up variable substitutions on the way. Also allow
1862: * backslashes to quote the delimiter, $, and \, but don't
1863: * touch other backslashes.
1864: */
1.278 rillig 1865: for (cp = *tstr; *cp != '\0' && *cp != delim; cp++) {
1.263 rillig 1866: Boolean is_escaped = cp[0] == '\\' && (cp[1] == delim ||
1.281 rillig 1867: cp[1] == '\\' || cp[1] == '$' || (subst != NULL && cp[1] == '&'));
1.263 rillig 1868: if (is_escaped) {
1.146 dsl 1869: Buf_AddByte(&buf, cp[1]);
1.16 christos 1870: cp++;
1871: } else if (*cp == '$') {
1.288 rillig 1872: if (cp[1] == delim) { /* Unescaped $ at end of pattern */
1.261 rillig 1873: if (mpflags == NULL)
1.146 dsl 1874: Buf_AddByte(&buf, *cp);
1.16 christos 1875: else
1.288 rillig 1876: *mpflags |= VARP_ANCHOR_END;
1.40 sjg 1877: } else {
1.287 rillig 1878: if (!(eflags & VARE_NOSUBST)) {
1.40 sjg 1879: char *cp2;
1.127 christos 1880: int len;
1.104 christos 1881: void *freeIt;
1.40 sjg 1882:
1883: /*
1884: * If unescaped dollar sign not before the
1885: * delimiter, assume it's a variable
1886: * substitution and recurse.
1887: */
1.261 rillig 1888: cp2 = Var_Parse(cp, ctxt, errnum | (eflags & VARE_WANTRES),
1.249 rillig 1889: &len, &freeIt);
1.146 dsl 1890: Buf_AddBytes(&buf, strlen(cp2), cp2);
1.196 christos 1891: free(freeIt);
1.40 sjg 1892: cp += len - 1;
1893: } else {
1.73 christos 1894: const char *cp2 = &cp[1];
1.16 christos 1895:
1.100 christos 1896: if (*cp2 == PROPEN || *cp2 == BROPEN) {
1.40 sjg 1897: /*
1898: * Find the end of this variable reference
1899: * and suck it in without further ado.
1.232 rillig 1900: * It will be interpreted later.
1.40 sjg 1901: */
1902: int have = *cp2;
1.100 christos 1903: int want = (*cp2 == PROPEN) ? PRCLOSE : BRCLOSE;
1.40 sjg 1904: int depth = 1;
1905:
1906: for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
1907: if (cp2[-1] != '\\') {
1908: if (*cp2 == have)
1909: ++depth;
1910: if (*cp2 == want)
1911: --depth;
1912: }
1913: }
1.146 dsl 1914: Buf_AddBytes(&buf, cp2 - cp, cp);
1.40 sjg 1915: cp = --cp2;
1916: } else
1.146 dsl 1917: Buf_AddByte(&buf, *cp);
1.40 sjg 1918: }
1.16 christos 1919: }
1.281 rillig 1920: } else if (subst != NULL && *cp == '&')
1921: Buf_AddBytes(&buf, subst->lhsLen, subst->lhs);
1.16 christos 1922: else
1.146 dsl 1923: Buf_AddByte(&buf, *cp);
1.16 christos 1924: }
1925:
1926: if (*cp != delim) {
1927: *tstr = cp;
1928: *length = 0;
1929: return NULL;
1930: }
1.146 dsl 1931:
1932: *tstr = ++cp;
1933: *length = Buf_Size(&buf);
1934: rstr = Buf_Destroy(&buf, FALSE);
1935: if (DEBUG(VAR))
1.278 rillig 1936: fprintf(debug_file, "Modifier part: \"%s\"\n", rstr);
1.146 dsl 1937: return rstr;
1.16 christos 1938: }
1939:
1940: /*-
1941: *-----------------------------------------------------------------------
1942: * VarQuote --
1.194 mlelstv 1943: * Quote shell meta-characters and space characters in the string
1.220 christos 1944: * if quoteDollar is set, also quote and double any '$' characters.
1.16 christos 1945: *
1946: * Results:
1947: * The quoted string
1948: *
1949: * Side Effects:
1950: * None.
1951: *
1952: *-----------------------------------------------------------------------
1953: */
1954: static char *
1.220 christos 1955: VarQuote(char *str, Boolean quoteDollar)
1.16 christos 1956: {
1.293 rillig 1957: Buffer buf;
1.146 dsl 1958: Buf_Init(&buf, 0);
1.193 christos 1959:
1960: for (; *str != '\0'; str++) {
1961: if (*str == '\n') {
1.293 rillig 1962: const char *newline = Shell_GetNewline();
1963: if (newline == NULL)
1964: newline = "\\\n";
1965: Buf_AddBytes(&buf, strlen(newline), newline);
1.193 christos 1966: continue;
1967: }
1.195 christos 1968: if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
1.146 dsl 1969: Buf_AddByte(&buf, '\\');
1.193 christos 1970: Buf_AddByte(&buf, *str);
1.220 christos 1971: if (quoteDollar && *str == '$')
1.219 christos 1972: Buf_AddBytes(&buf, 2, "\\$");
1.16 christos 1973: }
1.193 christos 1974:
1.146 dsl 1975: str = Buf_Destroy(&buf, FALSE);
1.137 christos 1976: if (DEBUG(VAR))
1977: fprintf(debug_file, "QuoteMeta: [%s]\n", str);
1.16 christos 1978: return str;
1979: }
1980:
1.68 pk 1981: /*-
1982: *-----------------------------------------------------------------------
1.163 joerg 1983: * VarHash --
1984: * Hash the string using the MurmurHash3 algorithm.
1985: * Output is computed using 32bit Little Endian arithmetic.
1986: *
1987: * Input:
1988: * str String to modify
1989: *
1990: * Results:
1991: * Hash value of str, encoded as 8 hex digits.
1992: *
1993: * Side Effects:
1994: * None.
1995: *
1996: *-----------------------------------------------------------------------
1997: */
1998: static char *
1.252 rillig 1999: VarHash(const char *str)
1.163 joerg 2000: {
2001: static const char hexdigits[16] = "0123456789abcdef";
2002: Buffer buf;
2003: size_t len, len2;
1.252 rillig 2004: const unsigned char *ustr = (const unsigned char *)str;
1.163 joerg 2005: uint32_t h, k, c1, c2;
2006:
2007: h = 0x971e137bU;
2008: c1 = 0x95543787U;
2009: c2 = 0x2ad7eb25U;
2010: len2 = strlen(str);
2011:
2012: for (len = len2; len; ) {
2013: k = 0;
2014: switch (len) {
2015: default:
1.252 rillig 2016: k = ((uint32_t)ustr[3] << 24) |
2017: ((uint32_t)ustr[2] << 16) |
2018: ((uint32_t)ustr[1] << 8) |
2019: (uint32_t)ustr[0];
1.163 joerg 2020: len -= 4;
2021: ustr += 4;
2022: break;
2023: case 3:
1.252 rillig 2024: k |= (uint32_t)ustr[2] << 16;
1.222 mrg 2025: /* FALLTHROUGH */
1.163 joerg 2026: case 2:
1.252 rillig 2027: k |= (uint32_t)ustr[1] << 8;
1.222 mrg 2028: /* FALLTHROUGH */
1.163 joerg 2029: case 1:
1.252 rillig 2030: k |= (uint32_t)ustr[0];
1.163 joerg 2031: len = 0;
2032: }
2033: c1 = c1 * 5 + 0x7b7d159cU;
2034: c2 = c2 * 5 + 0x6bce6396U;
2035: k *= c1;
2036: k = (k << 11) ^ (k >> 21);
2037: k *= c2;
2038: h = (h << 13) ^ (h >> 19);
2039: h = h * 5 + 0x52dce729U;
2040: h ^= k;
1.242 rillig 2041: }
2042: h ^= len2;
2043: h *= 0x85ebca6b;
2044: h ^= h >> 13;
2045: h *= 0xc2b2ae35;
2046: h ^= h >> 16;
2047:
2048: Buf_Init(&buf, 0);
2049: for (len = 0; len < 8; ++len) {
2050: Buf_AddByte(&buf, hexdigits[h & 15]);
2051: h >>= 4;
1.249 rillig 2052: }
1.163 joerg 2053:
1.249 rillig 2054: return Buf_Destroy(&buf, FALSE);
1.163 joerg 2055: }
2056:
1.164 sjg 2057: static char *
1.209 sjg 2058: VarStrftime(const char *fmt, int zulu, time_t utc)
1.164 sjg 2059: {
2060: char buf[BUFSIZ];
2061:
1.209 sjg 2062: if (!utc)
2063: time(&utc);
1.164 sjg 2064: if (!*fmt)
2065: fmt = "%c";
2066: strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&utc) : localtime(&utc));
1.235 rillig 2067:
1.164 sjg 2068: buf[sizeof(buf) - 1] = '\0';
2069: return bmake_strdup(buf);
2070: }
2071:
1.236 rillig 2072: typedef struct {
2073: /* const parameters */
1.267 rillig 2074: int startc; /* '\0' or '{' or '(' */
1.236 rillig 2075: int endc;
1.242 rillig 2076: Var *v;
1.236 rillig 2077: GNode *ctxt;
1.268 rillig 2078: VarEvalFlags eflags;
1.242 rillig 2079: int *lengthPtr;
2080: void **freePtr;
1.236 rillig 2081:
2082: /* read-write */
2083: char *nstr;
2084: const char *start;
1.300 ! rillig 2085: const char *cp; /* The position where parsing continues
! 2086: * after the current modifier. */
1.236 rillig 2087: char termc; /* Character which terminated scan */
1.298 rillig 2088: char missing_delim; /* For error reporting */
1.236 rillig 2089: int modifier; /* that we are processing */
1.242 rillig 2090: Var_Parse_State parsestate; /* Flags passed to helper functions */
1.236 rillig 2091:
2092: /* result */
2093: char *newStr; /* New value to return */
2094: } ApplyModifiersState;
2095:
2096: /* we now have some modifiers with long names */
2097: #define STRMOD_MATCH(s, want, n) \
2098: (strncmp(s, want, n) == 0 && (s[n] == st->endc || s[n] == ':'))
2099: #define STRMOD_MATCHX(s, want, n) \
1.246 rillig 2100: (strncmp(s, want, n) == 0 && \
2101: (s[n] == st->endc || s[n] == ':' || s[n] == '='))
1.236 rillig 2102: #define CHARMOD_MATCH(c) (c == st->endc || c == ':')
2103:
2104: /* :@var@...${var}...@ */
2105: static Boolean
1.299 rillig 2106: ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) {
1.291 rillig 2107: ModifyWord_LoopArgs args;
1.236 rillig 2108:
1.295 rillig 2109: args.ctx = st->ctxt;
1.299 rillig 2110: st->cp = mod + 1;
1.298 rillig 2111: char delim = '@';
2112: args.tvar = ParseModifierPart(st->ctxt, &st->cp, delim,
1.288 rillig 2113: st->eflags | VARE_NOSUBST,
2114: NULL, NULL, NULL);
1.298 rillig 2115: if (args.tvar == NULL) {
2116: st->missing_delim = delim;
1.236 rillig 2117: return FALSE;
1.298 rillig 2118: }
1.236 rillig 2119:
1.298 rillig 2120: args.str = ParseModifierPart(st->ctxt, &st->cp, delim,
1.288 rillig 2121: st->eflags | VARE_NOSUBST,
2122: NULL, NULL, NULL);
1.298 rillig 2123: if (args.str == NULL) {
2124: st->missing_delim = delim;
1.236 rillig 2125: return FALSE;
1.298 rillig 2126: }
1.236 rillig 2127:
2128: st->termc = *st->cp;
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
1.299 rillig 2144: ApplyModifier_Defined(const char *mod, ApplyModifiersState *st)
1.236 rillig 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.299 rillig 2151: if (*mod == 'U')
1.236 rillig 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);
1.299 rillig 2169: for (st->cp = mod + 1;
1.236 rillig 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
1.299 rillig 2209: ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st)
1.236 rillig 2210: {
2211: time_t utc;
2212: char *ep;
2213:
1.299 rillig 2214: st->cp = mod + 1; /* make sure it is set */
2215: if (!STRMOD_MATCHX(mod, "gmtime", 6))
1.236 rillig 2216: return FALSE;
1.299 rillig 2217: if (mod[6] == '=') {
2218: utc = strtoul(mod + 7, &ep, 10);
1.236 rillig 2219: st->cp = ep;
2220: } else {
2221: utc = 0;
1.299 rillig 2222: st->cp = mod + 6;
1.236 rillig 2223: }
2224: st->newStr = VarStrftime(st->nstr, 1, utc);
2225: st->termc = *st->cp;
2226: return TRUE;
2227: }
2228:
2229: /* :localtime */
2230: static Boolean
1.299 rillig 2231: ApplyModifier_Localtime(const char *mod, ApplyModifiersState *st)
1.236 rillig 2232: {
2233: time_t utc;
2234: char *ep;
2235:
1.299 rillig 2236: st->cp = mod + 1; /* make sure it is set */
2237: if (!STRMOD_MATCHX(mod, "localtime", 9))
1.236 rillig 2238: return FALSE;
2239:
1.299 rillig 2240: if (mod[9] == '=') {
2241: utc = strtoul(mod + 10, &ep, 10);
1.236 rillig 2242: st->cp = ep;
2243: } else {
2244: utc = 0;
1.299 rillig 2245: st->cp = mod + 9;
1.236 rillig 2246: }
2247: st->newStr = VarStrftime(st->nstr, 0, utc);
2248: st->termc = *st->cp;
2249: return TRUE;
2250: }
2251:
2252: /* :hash */
2253: static Boolean
1.299 rillig 2254: ApplyModifier_Hash(const char *mod, ApplyModifiersState *st)
1.236 rillig 2255: {
1.299 rillig 2256: st->cp = mod + 1; /* make sure it is set */
2257: if (!STRMOD_MATCH(mod, "hash", 4))
1.236 rillig 2258: return FALSE;
2259: st->newStr = VarHash(st->nstr);
1.299 rillig 2260: st->cp = mod + 4;
1.236 rillig 2261: st->termc = *st->cp;
2262: return TRUE;
2263: }
2264:
2265: /* :P */
2266: static void
1.299 rillig 2267: ApplyModifier_Path(const char *mod, ApplyModifiersState *st)
1.236 rillig 2268: {
2269: if ((st->v->flags & VAR_JUNK) != 0)
2270: st->v->flags |= VAR_KEEP;
1.299 rillig 2271: GNode *gn = Targ_FindNode(st->v->name, TARG_NOCREATE);
1.236 rillig 2272: if (gn == NULL || gn->type & OP_NOPATH) {
2273: st->newStr = NULL;
2274: } else if (gn->path) {
2275: st->newStr = bmake_strdup(gn->path);
2276: } else {
2277: st->newStr = Dir_FindFile(st->v->name, Suff_FindPath(gn));
2278: }
2279: if (!st->newStr)
2280: st->newStr = bmake_strdup(st->v->name);
1.299 rillig 2281: st->cp = mod + 1;
2282: st->termc = *st->cp;
1.236 rillig 2283: }
2284:
2285: /* :!cmd! */
2286: static Boolean
1.299 rillig 2287: ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st)
1.236 rillig 2288: {
1.299 rillig 2289: st->cp = mod + 1;
1.298 rillig 2290: char delim = '!';
2291: char *cmd = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.274 rillig 2292: NULL, NULL, NULL);
1.298 rillig 2293: if (cmd == NULL) {
2294: st->missing_delim = delim;
1.236 rillig 2295: return FALSE;
1.298 rillig 2296: }
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: if (st->v->flags & VAR_JUNK)
2310: st->v->flags |= VAR_KEEP;
2311: return TRUE;
2312: }
2313:
2314: /* :range */
2315: static Boolean
1.299 rillig 2316: ApplyModifier_Range(const char *mod, ApplyModifiersState *st)
1.236 rillig 2317: {
2318: int n;
2319: char *ep;
2320:
1.299 rillig 2321: st->cp = mod + 1; /* make sure it is set */
2322: if (!STRMOD_MATCHX(mod, "range", 5))
1.236 rillig 2323: return FALSE;
2324:
1.299 rillig 2325: if (mod[5] == '=') {
2326: n = strtoul(mod + 6, &ep, 10);
1.236 rillig 2327: st->cp = ep;
2328: } else {
2329: n = 0;
1.299 rillig 2330: st->cp = mod + 5;
1.236 rillig 2331: }
2332: st->newStr = VarRange(st->nstr, n);
2333: st->termc = *st->cp;
2334: return TRUE;
2335: }
2336:
2337: /* :Mpattern or :Npattern */
2338: static void
1.299 rillig 2339: ApplyModifier_Match(const char *mod, ApplyModifiersState *st)
1.236 rillig 2340: {
1.288 rillig 2341: Boolean copy = FALSE; /* pattern should be, or has been, copied */
2342: Boolean needSubst = FALSE;
1.236 rillig 2343: /*
1.288 rillig 2344: * In the loop below, ignore ':' unless we are at (or back to) the
2345: * original brace level.
2346: * XXX This will likely not work right if $() and ${} are intermixed.
1.236 rillig 2347: */
1.288 rillig 2348: int nest = 1;
1.299 rillig 2349: for (st->cp = mod + 1;
1.236 rillig 2350: *st->cp != '\0' && !(*st->cp == ':' && nest == 1);
2351: st->cp++) {
2352: if (*st->cp == '\\' &&
2353: (st->cp[1] == ':' || st->cp[1] == st->endc ||
2354: st->cp[1] == st->startc)) {
2355: if (!needSubst)
2356: copy = TRUE;
2357: st->cp++;
2358: continue;
2359: }
2360: if (*st->cp == '$')
2361: needSubst = TRUE;
2362: if (*st->cp == '(' || *st->cp == '{')
2363: ++nest;
2364: if (*st->cp == ')' || *st->cp == '}') {
2365: --nest;
2366: if (nest == 0)
2367: break;
2368: }
2369: }
2370: st->termc = *st->cp;
1.288 rillig 2371: const char *endpat = st->cp;
2372:
2373: char *pattern = NULL;
1.236 rillig 2374: if (copy) {
2375: /*
2376: * Need to compress the \:'s out of the pattern, so
2377: * allocate enough room to hold the uncompressed
1.299 rillig 2378: * pattern (note that st->cp started at mod+1, so
2379: * st->cp - mod takes the null byte into account) and
1.236 rillig 2380: * compress the pattern into the space.
2381: */
1.299 rillig 2382: pattern = bmake_malloc(st->cp - mod);
1.288 rillig 2383: char *cp2;
1.299 rillig 2384: for (cp2 = pattern, st->cp = mod + 1;
1.236 rillig 2385: st->cp < endpat;
2386: st->cp++, cp2++) {
2387: if ((*st->cp == '\\') && (st->cp+1 < endpat) &&
2388: (st->cp[1] == ':' || st->cp[1] == st->endc))
2389: st->cp++;
2390: *cp2 = *st->cp;
2391: }
2392: *cp2 = '\0';
2393: endpat = cp2;
2394: } else {
2395: /*
1.292 rillig 2396: * Either Var_Subst or ModifyWords will need a
1.236 rillig 2397: * nul-terminated string soon, so construct one now.
2398: */
1.299 rillig 2399: pattern = bmake_strndup(mod + 1, endpat - (mod + 1));
1.236 rillig 2400: }
2401: if (needSubst) {
2402: /* pattern contains embedded '$', so use Var_Subst to expand it. */
1.288 rillig 2403: char *old_pattern = pattern;
2404: pattern = Var_Subst(NULL, pattern, st->ctxt, st->eflags);
2405: free(old_pattern);
1.236 rillig 2406: }
2407: if (DEBUG(VAR))
2408: fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
2409: st->v->name, st->nstr, pattern);
1.299 rillig 2410: ModifyWordsCallback callback = mod[0] == 'M'
1.291 rillig 2411: ? ModifyWord_Match : ModifyWord_NoMatch;
2412: st->newStr = ModifyWords(st->ctxt, &st->parsestate, st->nstr,
2413: callback, pattern);
1.236 rillig 2414: free(pattern);
2415: }
2416:
2417: /* :S,from,to, */
2418: static Boolean
1.299 rillig 2419: ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st)
1.236 rillig 2420: {
1.291 rillig 2421: ModifyWord_SubstArgs args;
1.281 rillig 2422: Var_Parse_State tmpparsestate = st->parsestate;
1.299 rillig 2423: char delim = mod[1];
2424:
2425: st->cp = mod + 2;
1.236 rillig 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.299 rillig 2432: if (*st->cp == '^') {
1.288 rillig 2433: args.pflags |= VARP_ANCHOR_START;
1.299 rillig 2434: st->cp++;
1.236 rillig 2435: }
2436:
1.298 rillig 2437: char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.281 rillig 2438: &args.pflags, &args.lhsLen, NULL);
1.298 rillig 2439: if (lhs == NULL) {
2440: st->missing_delim = delim;
1.236 rillig 2441: return FALSE;
1.298 rillig 2442: }
1.281 rillig 2443: args.lhs = lhs;
1.236 rillig 2444:
1.298 rillig 2445: char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.281 rillig 2446: NULL, &args.rhsLen, &args);
1.298 rillig 2447: if (rhs == NULL) {
2448: st->missing_delim = delim;
1.236 rillig 2449: return FALSE;
1.298 rillig 2450: }
1.281 rillig 2451: args.rhs = rhs;
1.236 rillig 2452:
2453: /*
2454: * Check for global substitution. If 'g' after the final
2455: * delimiter, substitution is global and is marked that
2456: * way.
2457: */
2458: for (;; st->cp++) {
2459: switch (*st->cp) {
2460: case 'g':
1.281 rillig 2461: args.pflags |= VARP_SUB_GLOBAL;
1.236 rillig 2462: continue;
2463: case '1':
1.281 rillig 2464: args.pflags |= VARP_SUB_ONE;
1.236 rillig 2465: continue;
2466: case 'W':
2467: tmpparsestate.oneBigWord = TRUE;
2468: continue;
2469: }
2470: break;
2471: }
2472:
2473: st->termc = *st->cp;
1.291 rillig 2474: st->newStr = ModifyWords(st->ctxt, &tmpparsestate, st->nstr,
2475: ModifyWord_Subst, &args);
1.236 rillig 2476:
1.281 rillig 2477: free(lhs);
2478: free(rhs);
1.236 rillig 2479: return TRUE;
2480: }
2481:
2482: #ifndef NO_REGEX
1.291 rillig 2483:
1.236 rillig 2484: /* :C,from,to, */
2485: static Boolean
1.299 rillig 2486: ApplyModifier_Regex(const char *mod, ApplyModifiersState *st)
1.236 rillig 2487: {
1.291 rillig 2488: ModifyWord_SubstRegexArgs args;
1.236 rillig 2489:
1.291 rillig 2490: args.pflags = 0;
1.288 rillig 2491: Var_Parse_State tmpparsestate = st->parsestate;
1.299 rillig 2492: char delim = mod[1];
1.236 rillig 2493:
1.299 rillig 2494: st->cp = mod + 2;
1.236 rillig 2495:
1.297 rillig 2496: char *re = ParseModifierPart(st->ctxt, &st->cp, delim,
1.291 rillig 2497: st->eflags, NULL, NULL, NULL);
1.297 rillig 2498: if (re == NULL) {
1.298 rillig 2499: st->missing_delim = delim;
1.236 rillig 2500: return FALSE;
1.297 rillig 2501: }
1.236 rillig 2502:
1.297 rillig 2503: args.replace = ParseModifierPart(st->ctxt, &st->cp, delim,
1.291 rillig 2504: st->eflags, NULL, NULL, NULL);
2505: if (args.replace == NULL) {
1.236 rillig 2506: free(re);
1.298 rillig 2507: st->missing_delim = delim;
1.236 rillig 2508: return FALSE;
2509: }
2510:
2511: for (;; st->cp++) {
2512: switch (*st->cp) {
2513: case 'g':
1.291 rillig 2514: args.pflags |= VARP_SUB_GLOBAL;
1.236 rillig 2515: continue;
2516: case '1':
1.291 rillig 2517: args.pflags |= VARP_SUB_ONE;
1.236 rillig 2518: continue;
2519: case 'W':
2520: tmpparsestate.oneBigWord = TRUE;
2521: continue;
2522: }
2523: break;
2524: }
2525:
2526: st->termc = *st->cp;
2527:
1.291 rillig 2528: int error = regcomp(&args.re, re, REG_EXTENDED);
1.236 rillig 2529: free(re);
1.242 rillig 2530: if (error) {
1.236 rillig 2531: *st->lengthPtr = st->cp - st->start + 1;
1.291 rillig 2532: VarREError(error, &args.re, "RE substitution error");
2533: free(args.replace);
1.236 rillig 2534: return FALSE;
2535: }
2536:
1.291 rillig 2537: args.nsub = args.re.re_nsub + 1;
2538: if (args.nsub < 1)
2539: args.nsub = 1;
2540: if (args.nsub > 10)
2541: args.nsub = 10;
2542: args.matches = bmake_malloc(args.nsub * sizeof(regmatch_t));
2543: st->newStr = ModifyWords(st->ctxt, &tmpparsestate, st->nstr,
2544: ModifyWord_SubstRegex, &args);
2545: regfree(&args.re);
2546: free(args.replace);
2547: free(args.matches);
1.236 rillig 2548: return TRUE;
2549: }
2550: #endif
2551:
1.278 rillig 2552: static void
1.295 rillig 2553: ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.278 rillig 2554: {
2555: SepBuf_AddBytes(buf, word, strlen(word));
1.275 rillig 2556: }
2557:
1.289 rillig 2558: /* :ts<separator> */
2559: static Boolean
1.299 rillig 2560: ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
1.289 rillig 2561: {
2562: if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
2563: /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */
2564: st->parsestate.varSpace = sep[0];
2565: st->cp = sep + 1;
2566: } else if (sep[0] == st->endc || sep[0] == ':') {
2567: /* ":ts<endc>" or ":ts:" */
2568: st->parsestate.varSpace = 0; /* no separator */
2569: st->cp = sep;
2570: } else if (sep[0] == '\\') {
2571: const char *xp = sep + 1;
2572: int base = 8; /* assume octal */
2573:
2574: switch (sep[1]) {
2575: case 'n':
2576: st->parsestate.varSpace = '\n';
2577: st->cp = sep + 2;
2578: break;
2579: case 't':
2580: st->parsestate.varSpace = '\t';
2581: st->cp = sep + 2;
2582: break;
2583: case 'x':
2584: base = 16;
2585: xp++;
2586: goto get_numeric;
2587: case '0':
2588: base = 0;
2589: goto get_numeric;
2590: default:
2591: if (!isdigit((unsigned char)sep[1]))
2592: return FALSE; /* ":ts<backslash><unrecognised>". */
2593:
2594: char *end;
2595: get_numeric:
1.295 rillig 2596: st->parsestate.varSpace = strtoul(sep + 1 + (sep[1] == 'x'),
2597: &end, base);
1.289 rillig 2598: if (*end != ':' && *end != st->endc)
2599: return FALSE;
2600: st->cp = end;
2601: break;
2602: }
2603: } else {
2604: return FALSE; /* Found ":ts<unrecognised><unrecognised>". */
2605: }
2606:
2607: st->termc = *st->cp;
1.291 rillig 2608: st->newStr = ModifyWords(st->ctxt, &st->parsestate, st->nstr,
1.292 rillig 2609: ModifyWord_Copy, NULL);
1.289 rillig 2610: return TRUE;
2611: }
2612:
2613: /* :tA, :tu, :tl, :ts<separator>, etc. */
1.236 rillig 2614: static Boolean
1.299 rillig 2615: ApplyModifier_To(const char *mod, ApplyModifiersState *st)
1.236 rillig 2616: {
1.299 rillig 2617: st->cp = mod + 1; /* make sure it is set */
2618: if (mod[1] == st->endc || mod[1] == ':')
1.289 rillig 2619: return FALSE; /* Found ":t<endc>" or ":t:". */
2620:
1.299 rillig 2621: if (mod[1] == 's')
2622: return ApplyModifier_ToSep(mod + 2, st);
1.289 rillig 2623:
1.299 rillig 2624: if (mod[2] != st->endc && mod[2] != ':')
1.289 rillig 2625: return FALSE; /* Found ":t<unrecognised><unrecognised>". */
1.236 rillig 2626:
1.289 rillig 2627: /* Check for two-character options: ":tu", ":tl" */
1.299 rillig 2628: if (mod[1] == 'A') { /* absolute path */
1.291 rillig 2629: st->newStr = ModifyWords(st->ctxt, &st->parsestate, st->nstr,
2630: ModifyWord_Realpath, NULL);
1.299 rillig 2631: st->cp = mod + 2;
1.289 rillig 2632: st->termc = *st->cp;
1.299 rillig 2633: } else if (mod[1] == 'u') {
1.289 rillig 2634: char *dp = bmake_strdup(st->nstr);
2635: for (st->newStr = dp; *dp; dp++)
2636: *dp = toupper((unsigned char)*dp);
1.299 rillig 2637: st->cp = mod + 2;
1.289 rillig 2638: st->termc = *st->cp;
1.299 rillig 2639: } else if (mod[1] == 'l') {
1.289 rillig 2640: char *dp = bmake_strdup(st->nstr);
2641: for (st->newStr = dp; *dp; dp++)
2642: *dp = tolower((unsigned char)*dp);
1.299 rillig 2643: st->cp = mod + 2;
1.289 rillig 2644: st->termc = *st->cp;
1.299 rillig 2645: } else if (mod[1] == 'W' || mod[1] == 'w') {
2646: st->parsestate.oneBigWord = (mod[1] == 'W');
1.289 rillig 2647: st->newStr = st->nstr;
1.299 rillig 2648: st->cp = mod + 2;
1.289 rillig 2649: st->termc = *st->cp;
1.236 rillig 2650: } else {
1.289 rillig 2651: /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
1.236 rillig 2652: return FALSE;
2653: }
2654: return TRUE;
2655: }
2656:
2657: /* :[#], :[1], etc. */
2658: static int
1.299 rillig 2659: ApplyModifier_Words(const char *mod, ApplyModifiersState *st)
1.236 rillig 2660: {
1.299 rillig 2661: st->cp = mod + 1; /* point to char after '[' */
1.298 rillig 2662: char delim = ']'; /* look for closing ']' */
2663: char *estr = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.266 rillig 2664: NULL, NULL, NULL);
1.298 rillig 2665: if (estr == NULL) {
2666: st->missing_delim = delim;
2667: return 'c';
2668: }
1.288 rillig 2669:
1.236 rillig 2670: /* now st->cp points just after the closing ']' */
1.288 rillig 2671: if (st->cp[0] != ':' && st->cp[0] != st->endc)
2672: goto bad_modifier; /* Found junk after ']' */
2673:
2674: if (estr[0] == '\0')
2675: goto bad_modifier; /* empty square brackets in ":[]". */
1.236 rillig 2676:
1.288 rillig 2677: if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
1.236 rillig 2678: /*
1.288 rillig 2679: * We will need enough space for the decimal representation of an int.
2680: * We calculate the space needed for the octal representation, and add
2681: * enough slop to cope with a '-' sign (which should never be needed)
2682: * and a '\0' string terminator.
1.236 rillig 2683: */
2684: int newStrSize = (sizeof(int) * CHAR_BIT + 2) / 3 + 2;
2685:
2686: st->newStr = bmake_malloc(newStrSize);
2687: if (st->parsestate.oneBigWord) {
2688: strncpy(st->newStr, "1", newStrSize);
2689: } else {
2690: /* XXX: brk_string() is a rather expensive
2691: * way of counting words. */
2692: char **av;
2693: char *as;
2694: int ac;
2695:
2696: av = brk_string(st->nstr, &ac, FALSE, &as);
1.242 rillig 2697: snprintf(st->newStr, newStrSize, "%d", ac);
1.236 rillig 2698: free(as);
2699: free(av);
2700: }
1.288 rillig 2701: goto ok;
2702: }
2703:
2704: if (estr[0] == '*' && estr[1] == '\0') {
1.236 rillig 2705: /* Found ":[*]" */
2706: st->parsestate.oneBigWord = TRUE;
2707: st->newStr = st->nstr;
1.288 rillig 2708: goto ok;
2709: }
2710:
2711: if (estr[0] == '@' && estr[1] == '\0') {
1.236 rillig 2712: /* Found ":[@]" */
2713: st->parsestate.oneBigWord = FALSE;
2714: st->newStr = st->nstr;
1.288 rillig 2715: goto ok;
2716: }
2717:
2718: /*
2719: * We expect estr to contain a single integer for :[N], or two integers
2720: * separated by ".." for :[start..end].
2721: */
2722: char *ep;
1.290 rillig 2723: int first = strtol(estr, &ep, 0);
2724: int last;
1.288 rillig 2725: if (ep == estr) /* Found junk instead of a number */
2726: goto bad_modifier;
2727:
2728: if (ep[0] == '\0') { /* Found only one integer in :[N] */
1.290 rillig 2729: last = first;
1.288 rillig 2730: } else if (ep[0] == '.' && ep[1] == '.' && ep[2] != '\0') {
2731: /* Expecting another integer after ".." */
2732: ep += 2;
1.290 rillig 2733: last = strtol(ep, &ep, 0);
1.288 rillig 2734: if (ep[0] != '\0') /* Found junk after ".." */
2735: goto bad_modifier;
2736: } else
2737: goto bad_modifier; /* Found junk instead of ".." */
1.236 rillig 2738:
1.288 rillig 2739: /*
2740: * Now seldata is properly filled in, but we still have to check for 0 as
2741: * a special case.
2742: */
1.290 rillig 2743: if (first == 0 && last == 0) {
1.288 rillig 2744: /* ":[0]" or perhaps ":[0..0]" */
2745: st->parsestate.oneBigWord = TRUE;
2746: st->newStr = st->nstr;
2747: goto ok;
1.236 rillig 2748: }
1.288 rillig 2749:
2750: /* ":[0..N]" or ":[N..0]" */
1.290 rillig 2751: if (first == 0 || last == 0)
1.288 rillig 2752: goto bad_modifier;
2753:
2754: /* Normal case: select the words described by seldata. */
1.295 rillig 2755: st->newStr = VarSelectWords(&st->parsestate, st->nstr, first, last);
1.288 rillig 2756:
2757: ok:
2758: st->termc = *st->cp;
2759: free(estr);
2760: return 0;
2761:
2762: bad_modifier:
2763: free(estr);
2764: return 'b';
1.236 rillig 2765: }
2766:
2767: /* :O or :Ox */
2768: static Boolean
1.299 rillig 2769: ApplyModifier_Order(const char *mod, ApplyModifiersState *st)
1.236 rillig 2770: {
2771: char otype;
2772:
1.299 rillig 2773: st->cp = mod + 1; /* skip to the rest in any case */
2774: if (mod[1] == st->endc || mod[1] == ':') {
1.236 rillig 2775: otype = 's';
2776: st->termc = *st->cp;
1.299 rillig 2777: } else if ((mod[1] == 'r' || mod[1] == 'x') &&
2778: (mod[2] == st->endc || mod[2] == ':')) {
2779: otype = mod[1];
2780: st->cp = mod + 2;
1.236 rillig 2781: st->termc = *st->cp;
2782: } else {
2783: return FALSE;
2784: }
2785: st->newStr = VarOrder(st->nstr, otype);
2786: return TRUE;
2787: }
2788:
2789: /* :? then : else */
2790: static Boolean
1.299 rillig 2791: ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st)
1.236 rillig 2792: {
1.285 rillig 2793: Boolean value = FALSE;
2794: int cond_rc = 0;
2795: VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES;
2796: VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES;
1.236 rillig 2797:
1.268 rillig 2798: if (st->eflags & VARE_WANTRES) {
1.236 rillig 2799: cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE);
1.285 rillig 2800: if (cond_rc != COND_INVALID && value)
2801: then_eflags |= VARE_WANTRES;
2802: if (cond_rc != COND_INVALID && !value)
2803: else_eflags |= VARE_WANTRES;
1.236 rillig 2804: }
2805:
1.299 rillig 2806: st->cp = mod + 1;
1.298 rillig 2807: char delim = ':';
1.265 rillig 2808: char *then_expr = ParseModifierPart(
1.298 rillig 2809: st->ctxt, &st->cp, delim, then_eflags, NULL, NULL, NULL);
2810: if (then_expr == NULL) {
2811: st->missing_delim = delim;
1.236 rillig 2812: return FALSE;
1.298 rillig 2813: }
1.236 rillig 2814:
1.298 rillig 2815: delim = st->endc; /* BRCLOSE or PRCLOSE */
1.265 rillig 2816: char *else_expr = ParseModifierPart(
1.298 rillig 2817: st->ctxt, &st->cp, delim, else_eflags, NULL, NULL, NULL);
2818: if (else_expr == NULL) {
2819: st->missing_delim = delim;
1.236 rillig 2820: return FALSE;
1.298 rillig 2821: }
1.236 rillig 2822:
2823: st->termc = *--st->cp;
2824: if (cond_rc == COND_INVALID) {
2825: Error("Bad conditional expression `%s' in %s?%s:%s",
1.258 rillig 2826: st->v->name, st->v->name, then_expr, else_expr);
1.236 rillig 2827: return FALSE;
2828: }
2829:
2830: if (value) {
1.258 rillig 2831: st->newStr = then_expr;
2832: free(else_expr);
1.236 rillig 2833: } else {
1.258 rillig 2834: st->newStr = else_expr;
1.270 rillig 2835: free(then_expr);
1.236 rillig 2836: }
2837: if (st->v->flags & VAR_JUNK)
2838: st->v->flags |= VAR_KEEP;
2839: return TRUE;
2840: }
2841:
1.283 rillig 2842: /*
2843: * The ::= modifiers actually assign a value to the variable.
2844: * Their main purpose is in supporting modifiers of .for loop
2845: * iterators and other obscure uses. They always expand to
2846: * nothing. In a target rule that would otherwise expand to an
2847: * empty line they can be preceded with @: to keep make happy.
2848: * Eg.
2849: *
2850: * foo: .USE
2851: * .for i in ${.TARGET} ${.TARGET:R}.gz
2852: * @: ${t::=$i}
2853: * @echo blah ${t:T}
2854: * .endfor
2855: *
2856: * ::=<str> Assigns <str> as the new value of variable.
2857: * ::?=<str> Assigns <str> as value of variable if
2858: * it was not already set.
2859: * ::+=<str> Appends <str> to variable.
2860: * ::!=<cmd> Assigns output of <cmd> as the new value of
2861: * variable.
2862: */
1.236 rillig 2863: static int
1.299 rillig 2864: ApplyModifier_Assign(const char *mod, ApplyModifiersState *st)
1.236 rillig 2865: {
1.299 rillig 2866: const char *op = mod + 1;
1.272 rillig 2867: if (!(op[0] == '=' ||
2868: (op[1] == '=' &&
2869: (op[0] == '!' || op[0] == '+' || op[0] == '?'))))
2870: return 'd'; /* "::<unrecognised>" */
1.236 rillig 2871:
1.272 rillig 2872: GNode *v_ctxt; /* context where v belongs */
2873:
2874: if (st->v->name[0] == 0)
2875: return 'b';
2876:
2877: v_ctxt = st->ctxt;
1.273 rillig 2878: char *sv_name = NULL;
1.272 rillig 2879: if (st->v->flags & VAR_JUNK) {
2880: /*
2881: * We need to bmake_strdup() it incase ParseModifierPart() recurses.
2882: */
2883: sv_name = st->v->name;
2884: st->v->name = bmake_strdup(st->v->name);
2885: } else if (st->ctxt != VAR_GLOBAL) {
2886: Var *gv = VarFind(st->v->name, st->ctxt, 0);
2887: if (gv == NULL)
2888: v_ctxt = VAR_GLOBAL;
2889: else
2890: VarFreeEnv(gv, TRUE);
2891: }
2892:
1.273 rillig 2893: switch (op[0]) {
1.272 rillig 2894: case '+':
2895: case '?':
2896: case '!':
1.299 rillig 2897: st->cp = mod + 3;
1.272 rillig 2898: break;
2899: default:
1.299 rillig 2900: st->cp = mod + 2;
1.272 rillig 2901: break;
2902: }
2903:
1.298 rillig 2904: char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE;
1.287 rillig 2905: VarEvalFlags eflags = (st->eflags & VARE_WANTRES) ? 0 : VARE_NOSUBST;
1.298 rillig 2906: char *val = ParseModifierPart(st->ctxt, &st->cp, delim,
1.287 rillig 2907: st->eflags | eflags, NULL, NULL, NULL);
1.272 rillig 2908: if (st->v->flags & VAR_JUNK) {
2909: /* restore original name */
2910: free(st->v->name);
2911: st->v->name = sv_name;
2912: }
1.298 rillig 2913: if (val == NULL) {
2914: st->missing_delim = delim;
1.272 rillig 2915: return 'c';
1.298 rillig 2916: }
1.236 rillig 2917:
1.272 rillig 2918: st->termc = *--st->cp;
1.236 rillig 2919:
1.272 rillig 2920: if (st->eflags & VARE_WANTRES) {
1.273 rillig 2921: switch (op[0]) {
1.236 rillig 2922: case '+':
1.273 rillig 2923: Var_Append(st->v->name, val, v_ctxt);
1.272 rillig 2924: break;
1.273 rillig 2925: case '!': {
2926: const char *emsg;
2927: st->newStr = Cmd_Exec(val, &emsg);
1.272 rillig 2928: if (emsg)
2929: Error(emsg, st->nstr);
2930: else
2931: Var_Set(st->v->name, st->newStr, v_ctxt);
2932: free(st->newStr);
1.236 rillig 2933: break;
1.273 rillig 2934: }
1.272 rillig 2935: case '?':
2936: if ((st->v->flags & VAR_JUNK) == 0)
2937: break;
2938: /* FALLTHROUGH */
1.236 rillig 2939: default:
1.273 rillig 2940: Var_Set(st->v->name, val, v_ctxt);
1.236 rillig 2941: break;
2942: }
2943: }
1.273 rillig 2944: free(val);
1.272 rillig 2945: st->newStr = varNoError;
2946: return 0;
1.236 rillig 2947: }
2948:
2949: /* remember current value */
2950: static Boolean
1.299 rillig 2951: ApplyModifier_Remember(const char *mod, ApplyModifiersState *st)
1.236 rillig 2952: {
1.299 rillig 2953: st->cp = mod + 1; /* make sure it is set */
2954: if (!STRMOD_MATCHX(mod, "_", 1))
1.236 rillig 2955: return FALSE;
2956:
1.299 rillig 2957: if (mod[1] == '=') {
1.236 rillig 2958: char *np;
2959: int n;
2960:
2961: st->cp++;
2962: n = strcspn(st->cp, ":)}");
1.249 rillig 2963: np = bmake_strndup(st->cp, n + 1);
1.236 rillig 2964: np[n] = '\0';
1.299 rillig 2965: st->cp = mod + 2 + n;
1.236 rillig 2966: Var_Set(np, st->nstr, st->ctxt);
2967: free(np);
2968: } else {
2969: Var_Set("_", st->nstr, st->ctxt);
2970: }
2971: st->newStr = st->nstr;
2972: st->termc = *st->cp;
2973: return TRUE;
2974: }
2975:
2976: #ifdef SYSVVARSUB
2977: /* :from=to */
2978: static int
1.299 rillig 2979: ApplyModifier_SysV(const char *mod, ApplyModifiersState *st)
1.236 rillig 2980: {
1.276 rillig 2981: Boolean eqFound = FALSE;
1.245 rillig 2982:
1.236 rillig 2983: /*
2984: * First we make a pass through the string trying
2985: * to verify it is a SYSV-make-style translation:
2986: * it must be: <string1>=<string2>)
2987: */
1.299 rillig 2988: st->cp = mod;
1.262 rillig 2989: int nest = 1;
2990: while (*st->cp != '\0' && nest > 0) {
1.236 rillig 2991: if (*st->cp == '=') {
2992: eqFound = TRUE;
2993: /* continue looking for st->endc */
1.242 rillig 2994: } else if (*st->cp == st->endc)
1.262 rillig 2995: nest--;
1.236 rillig 2996: else if (*st->cp == st->startc)
1.262 rillig 2997: nest++;
2998: if (nest > 0)
1.236 rillig 2999: st->cp++;
3000: }
1.245 rillig 3001: if (*st->cp != st->endc || !eqFound)
3002: return 0;
1.236 rillig 3003:
1.298 rillig 3004: char delim = '=';
1.299 rillig 3005: st->cp = mod;
1.298 rillig 3006: char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.284 rillig 3007: NULL, NULL, NULL);
1.298 rillig 3008: if (lhs == NULL) {
3009: st->missing_delim = delim;
1.245 rillig 3010: return 'c';
1.298 rillig 3011: }
1.245 rillig 3012:
1.298 rillig 3013: delim = st->endc;
3014: char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.276 rillig 3015: NULL, NULL, NULL);
1.298 rillig 3016: if (rhs == NULL) {
3017: st->missing_delim = delim;
1.245 rillig 3018: return 'c';
1.298 rillig 3019: }
1.236 rillig 3020:
1.245 rillig 3021: /*
3022: * SYSV modifications happen through the whole
3023: * string. Note the pattern is anchored at the end.
3024: */
3025: st->termc = *--st->cp;
1.276 rillig 3026: if (lhs[0] == '\0' && *st->nstr == '\0') {
1.245 rillig 3027: st->newStr = st->nstr; /* special case */
3028: } else {
1.295 rillig 3029: ModifyWord_SYSVSubstArgs args = { st->ctxt, lhs, rhs };
1.291 rillig 3030: st->newStr = ModifyWords(st->ctxt, &st->parsestate, st->nstr,
3031: ModifyWord_SYSVSubst, &args);
1.245 rillig 3032: }
1.276 rillig 3033: free(lhs);
3034: free(rhs);
1.245 rillig 3035: return '=';
1.236 rillig 3036: }
3037: #endif
3038:
1.108 sjg 3039: /*
3040: * Now we need to apply any modifiers the user wants applied.
3041: * These are:
3042: * :M<pattern> words which match the given <pattern>.
1.138 dsl 3043: * <pattern> is of the standard file
3044: * wildcarding form.
1.108 sjg 3045: * :N<pattern> words which do not match the given <pattern>.
3046: * :S<d><pat1><d><pat2><d>[1gW]
1.138 dsl 3047: * Substitute <pat2> for <pat1> in the value
1.108 sjg 3048: * :C<d><pat1><d><pat2><d>[1gW]
1.138 dsl 3049: * Substitute <pat2> for regex <pat1> in the value
3050: * :H Substitute the head of each word
3051: * :T Substitute the tail of each word
3052: * :E Substitute the extension (minus '.') of
3053: * each word
3054: * :R Substitute the root of each word
3055: * (pathname minus the suffix).
3056: * :O ("Order") Alphabeticaly sort words in variable.
3057: * :Ox ("intermiX") Randomize words in variable.
3058: * :u ("uniq") Remove adjacent duplicate words.
3059: * :tu Converts the variable contents to uppercase.
3060: * :tl Converts the variable contents to lowercase.
3061: * :ts[c] Sets varSpace - the char used to
3062: * separate words to 'c'. If 'c' is
3063: * omitted then no separation is used.
3064: * :tW Treat the variable contents as a single
3065: * word, even if it contains spaces.
3066: * (Mnemonic: one big 'W'ord.)
3067: * :tw Treat the variable contents as multiple
3068: * space-separated words.
3069: * (Mnemonic: many small 'w'ords.)
3070: * :[index] Select a single word from the value.
3071: * :[start..end] Select multiple words from the value.
3072: * :[*] or :[0] Select the entire value, as a single
3073: * word. Equivalent to :tW.
3074: * :[@] Select the entire value, as multiple
3075: * words. Undoes the effect of :[*].
3076: * Equivalent to :tw.
3077: * :[#] Returns the number of words in the value.
3078: *
3079: * :?<true-value>:<false-value>
3080: * If the variable evaluates to true, return
3081: * true value, else return the second value.
3082: * :lhs=rhs Like :S, but the rhs goes to the end of
3083: * the invocation.
3084: * :sh Treat the current value as a command
3085: * to be run, new value is its output.
1.108 sjg 3086: * The following added so we can handle ODE makefiles.
1.138 dsl 3087: * :@<tmpvar>@<newval>@
3088: * Assign a temporary local variable <tmpvar>
3089: * to the current value of each word in turn
3090: * and replace each word with the result of
3091: * evaluating <newval>
3092: * :D<newval> Use <newval> as value if variable defined
3093: * :U<newval> Use <newval> as value if variable undefined
3094: * :L Use the name of the variable as the value.
3095: * :P Use the path of the node that has the same
3096: * name as the variable as the value. This
3097: * basically includes an implied :L so that
3098: * the common method of refering to the path
3099: * of your dependent 'x' in a rule is to use
3100: * the form '${x:P}'.
3101: * :!<cmd>! Run cmd much the same as :sh run's the
3102: * current value of the variable.
1.283 rillig 3103: * Assignment operators (see ApplyModifier_Assign).
1.1 cgd 3104: */
1.108 sjg 3105: static char *
3106: ApplyModifiers(char *nstr, const char *tstr,
1.236 rillig 3107: int const startc, int const endc,
1.268 rillig 3108: Var * const v, GNode * const ctxt, VarEvalFlags const eflags,
1.236 rillig 3109: int * const lengthPtr, void ** const freePtr)
3110: {
3111: ApplyModifiersState st = {
1.268 rillig 3112: startc, endc, v, ctxt, eflags, lengthPtr, freePtr,
1.299 rillig 3113: nstr, tstr, tstr,
1.262 rillig 3114: '\0', '\0', 0, {' ', FALSE}, NULL
1.236 rillig 3115: };
1.15 christos 3116:
1.299 rillig 3117: const char *p = tstr;
3118: while (*p != '\0' && *p != endc) {
1.142 dsl 3119:
1.299 rillig 3120: if (*p == '$') {
1.142 dsl 3121: /*
1.167 sjg 3122: * We may have some complex modifiers in a variable.
1.1 cgd 3123: */
1.108 sjg 3124: void *freeIt;
3125: char *rval;
1.127 christos 3126: int rlen;
1.167 sjg 3127: int c;
1.22 christos 3128:
1.299 rillig 3129: rval = Var_Parse(p, st.ctxt, st.eflags, &rlen, &freeIt);
1.1 cgd 3130:
1.167 sjg 3131: /*
1.236 rillig 3132: * If we have not parsed up to st.endc or ':',
1.167 sjg 3133: * we are not interested.
3134: */
3135: if (rval != NULL && *rval &&
1.299 rillig 3136: (c = p[rlen]) != '\0' &&
1.167 sjg 3137: c != ':' &&
1.236 rillig 3138: c != st.endc) {
1.196 christos 3139: free(freeIt);
1.167 sjg 3140: goto apply_mods;
3141: }
3142:
1.108 sjg 3143: if (DEBUG(VAR)) {
1.114 dsl 3144: fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
1.299 rillig 3145: rval, rlen, p, rlen, p + rlen);
1.22 christos 3146: }
1.1 cgd 3147:
1.299 rillig 3148: p += rlen;
1.15 christos 3149:
1.108 sjg 3150: if (rval != NULL && *rval) {
1.127 christos 3151: int used;
1.15 christos 3152:
1.236 rillig 3153: st.nstr = ApplyModifiers(st.nstr, rval, 0, 0, st.v,
1.268 rillig 3154: st.ctxt, st.eflags, &used, st.freePtr);
1.236 rillig 3155: if (st.nstr == var_Error
1.268 rillig 3156: || (st.nstr == varNoError && (st.eflags & VARE_UNDEFERR) == 0)
1.111 rillig 3157: || strlen(rval) != (size_t) used) {
1.196 christos 3158: free(freeIt);
1.240 rillig 3159: goto out; /* error already reported */
1.1 cgd 3160: }
3161: }
1.196 christos 3162: free(freeIt);
1.299 rillig 3163: if (*p == ':')
3164: p++;
3165: else if (*p == '\0' && endc != '\0') {
1.246 rillig 3166: Error("Unclosed variable specification after complex "
3167: "modifier (expecting '%c') for %s", st.endc, st.v->name);
1.119 sjg 3168: goto out;
3169: }
1.108 sjg 3170: continue;
3171: }
1.167 sjg 3172: apply_mods:
1.108 sjg 3173: if (DEBUG(VAR)) {
1.236 rillig 3174: fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", st.v->name,
1.299 rillig 3175: *p, st.nstr);
1.1 cgd 3176: }
1.236 rillig 3177: st.newStr = var_Error;
1.299 rillig 3178: switch ((st.modifier = *p)) {
1.108 sjg 3179: case ':':
1.1 cgd 3180: {
1.299 rillig 3181: int res = ApplyModifier_Assign(p, &st);
1.236 rillig 3182: if (res == 'b')
3183: goto bad_modifier;
3184: if (res == 'c')
1.108 sjg 3185: goto cleanup;
1.236 rillig 3186: if (res == 'd')
3187: goto default_case;
1.108 sjg 3188: break;
3189: }
1.236 rillig 3190: case '@':
1.299 rillig 3191: ApplyModifier_Loop(p, &st);
1.236 rillig 3192: break;
3193: case '_':
1.299 rillig 3194: if (!ApplyModifier_Remember(p, &st))
1.236 rillig 3195: goto default_case;
3196: break;
1.108 sjg 3197: case 'D':
3198: case 'U':
1.299 rillig 3199: ApplyModifier_Defined(p, &st);
1.236 rillig 3200: break;
1.108 sjg 3201: case 'L':
3202: {
1.236 rillig 3203: if ((st.v->flags & VAR_JUNK) != 0)
3204: st.v->flags |= VAR_KEEP;
3205: st.newStr = bmake_strdup(st.v->name);
1.299 rillig 3206: st.cp = p + 1;
3207: st.termc = *st.cp;
1.108 sjg 3208: break;
3209: }
3210: case 'P':
1.299 rillig 3211: ApplyModifier_Path(p, &st);
1.236 rillig 3212: break;
1.108 sjg 3213: case '!':
1.299 rillig 3214: if (!ApplyModifier_Exclam(p, &st))
1.236 rillig 3215: goto cleanup;
3216: break;
3217: case '[':
1.108 sjg 3218: {
1.299 rillig 3219: int res = ApplyModifier_Words(p, &st);
1.236 rillig 3220: if (res == 'b')
3221: goto bad_modifier;
3222: if (res == 'c')
1.108 sjg 3223: goto cleanup;
3224: break;
3225: }
1.164 sjg 3226: case 'g':
1.299 rillig 3227: if (!ApplyModifier_Gmtime(p, &st))
1.165 sjg 3228: goto default_case;
1.164 sjg 3229: break;
1.163 joerg 3230: case 'h':
1.299 rillig 3231: if (!ApplyModifier_Hash(p, &st))
1.165 sjg 3232: goto default_case;
1.163 joerg 3233: break;
1.164 sjg 3234: case 'l':
1.299 rillig 3235: if (!ApplyModifier_Localtime(p, &st))
1.165 sjg 3236: goto default_case;
1.164 sjg 3237: break;
1.108 sjg 3238: case 't':
1.299 rillig 3239: if (!ApplyModifier_To(p, &st))
1.236 rillig 3240: goto bad_modifier;
3241: break;
1.108 sjg 3242: case 'N':
3243: case 'M':
1.299 rillig 3244: ApplyModifier_Match(p, &st);
1.236 rillig 3245: break;
1.108 sjg 3246: case 'S':
1.299 rillig 3247: if (!ApplyModifier_Subst(p, &st))
1.236 rillig 3248: goto cleanup;
3249: break;
1.108 sjg 3250: case '?':
1.299 rillig 3251: if (!ApplyModifier_IfElse(p, &st))
1.236 rillig 3252: goto cleanup;
3253: break;
1.108 sjg 3254: #ifndef NO_REGEX
3255: case 'C':
1.299 rillig 3256: if (!ApplyModifier_Regex(p, &st))
1.236 rillig 3257: goto cleanup;
3258: break;
1.108 sjg 3259: #endif
1.220 christos 3260: case 'q':
1.108 sjg 3261: case 'Q':
1.299 rillig 3262: if (p[1] == st.endc || p[1] == ':') {
1.236 rillig 3263: st.newStr = VarQuote(st.nstr, st.modifier == 'q');
1.299 rillig 3264: st.cp = p + 1;
1.236 rillig 3265: st.termc = *st.cp;
1.108 sjg 3266: break;
3267: }
3268: goto default_case;
3269: case 'T':
1.299 rillig 3270: if (p[1] == st.endc || p[1] == ':') {
1.291 rillig 3271: st.newStr = ModifyWords(st.ctxt, &st.parsestate, st.nstr,
3272: ModifyWord_Tail, NULL);
1.299 rillig 3273: st.cp = p + 1;
1.236 rillig 3274: st.termc = *st.cp;
1.108 sjg 3275: break;
3276: }
3277: goto default_case;
3278: case 'H':
1.299 rillig 3279: if (p[1] == st.endc || p[1] == ':') {
1.291 rillig 3280: st.newStr = ModifyWords(st.ctxt, &st.parsestate, st.nstr,
3281: ModifyWord_Head, NULL);
1.299 rillig 3282: st.cp = p + 1;
1.236 rillig 3283: st.termc = *st.cp;
1.108 sjg 3284: break;
3285: }
3286: goto default_case;
3287: case 'E':
1.299 rillig 3288: if (p[1] == st.endc || p[1] == ':') {
1.291 rillig 3289: st.newStr = ModifyWords(st.ctxt, &st.parsestate, st.nstr,
3290: ModifyWord_Suffix, NULL);
1.299 rillig 3291: st.cp = p + 1;
1.236 rillig 3292: st.termc = *st.cp;
1.108 sjg 3293: break;
3294: }
3295: goto default_case;
3296: case 'R':
1.299 rillig 3297: if (p[1] == st.endc || p[1] == ':') {
1.291 rillig 3298: st.newStr = ModifyWords(st.ctxt, &st.parsestate, st.nstr,
3299: ModifyWord_Root, NULL);
1.299 rillig 3300: st.cp = p + 1;
1.236 rillig 3301: st.termc = *st.cp;
1.108 sjg 3302: break;
3303: }
3304: goto default_case;
1.210 sjg 3305: case 'r':
1.299 rillig 3306: if (!ApplyModifier_Range(p, &st))
1.236 rillig 3307: goto default_case;
3308: break;
1.108 sjg 3309: case 'O':
1.299 rillig 3310: if (!ApplyModifier_Order(p, &st))
1.236 rillig 3311: goto bad_modifier;
3312: break;
1.108 sjg 3313: case 'u':
1.299 rillig 3314: if (p[1] == st.endc || p[1] == ':') {
1.236 rillig 3315: st.newStr = VarUniq(st.nstr);
1.299 rillig 3316: st.cp = p + 1;
1.236 rillig 3317: st.termc = *st.cp;
1.108 sjg 3318: break;
3319: }
3320: goto default_case;
3321: #ifdef SUNSHCMD
3322: case 's':
1.299 rillig 3323: if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) {
1.108 sjg 3324: const char *emsg;
1.268 rillig 3325: if (st.eflags & VARE_WANTRES) {
1.236 rillig 3326: st.newStr = Cmd_Exec(st.nstr, &emsg);
1.197 sjg 3327: if (emsg)
1.236 rillig 3328: Error(emsg, st.nstr);
1.197 sjg 3329: } else
1.236 rillig 3330: st.newStr = varNoError;
1.299 rillig 3331: st.cp = p + 2;
1.236 rillig 3332: st.termc = *st.cp;
1.108 sjg 3333: break;
3334: }
3335: goto default_case;
3336: #endif
3337: default:
1.142 dsl 3338: default_case:
1.236 rillig 3339: {
1.108 sjg 3340: #ifdef SYSVVARSUB
1.299 rillig 3341: int res = ApplyModifier_SysV(p, &st);
1.236 rillig 3342: if (res == 'c')
1.108 sjg 3343: goto cleanup;
1.236 rillig 3344: if (res != '=')
1.108 sjg 3345: #endif
3346: {
1.299 rillig 3347: Error("Unknown modifier '%c'", *p);
3348: for (st.cp = p + 1;
1.236 rillig 3349: *st.cp != ':' && *st.cp != st.endc && *st.cp != '\0';
3350: st.cp++)
1.108 sjg 3351: continue;
1.236 rillig 3352: st.termc = *st.cp;
3353: st.newStr = var_Error;
1.108 sjg 3354: }
3355: }
3356: }
3357: if (DEBUG(VAR)) {
1.172 christos 3358: fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
1.236 rillig 3359: st.v->name, st.modifier, st.newStr);
1.108 sjg 3360: }
1.25 christos 3361:
1.236 rillig 3362: if (st.newStr != st.nstr) {
3363: if (*st.freePtr) {
3364: free(st.nstr);
3365: *st.freePtr = NULL;
1.108 sjg 3366: }
1.236 rillig 3367: st.nstr = st.newStr;
3368: if (st.nstr != var_Error && st.nstr != varNoError) {
3369: *st.freePtr = st.nstr;
1.108 sjg 3370: }
3371: }
1.236 rillig 3372: if (st.termc == '\0' && st.endc != '\0') {
1.246 rillig 3373: Error("Unclosed variable specification (expecting '%c') "
3374: "for \"%s\" (value \"%s\") modifier %c",
3375: st.endc, st.v->name, st.nstr, st.modifier);
1.236 rillig 3376: } else if (st.termc == ':') {
3377: st.cp++;
1.108 sjg 3378: }
1.299 rillig 3379: p = st.cp;
1.108 sjg 3380: }
1.240 rillig 3381: out:
1.299 rillig 3382: *st.lengthPtr = p - st.start;
1.236 rillig 3383: return st.nstr;
1.25 christos 3384:
1.240 rillig 3385: bad_modifier:
1.299 rillig 3386: Error("Bad modifier `:%.*s' for %s",
3387: (int)strcspn(p, ":)}"), p, st.v->name);
1.25 christos 3388:
1.240 rillig 3389: cleanup:
1.236 rillig 3390: *st.lengthPtr = st.cp - st.start;
1.298 rillig 3391: if (st.missing_delim != '\0')
1.108 sjg 3392: Error("Unclosed substitution for %s (%c missing)",
1.298 rillig 3393: st.v->name, st.missing_delim);
1.236 rillig 3394: free(*st.freePtr);
3395: *st.freePtr = NULL;
1.231 rillig 3396: return var_Error;
1.108 sjg 3397: }
1.25 christos 3398:
1.108 sjg 3399: /*-
3400: *-----------------------------------------------------------------------
3401: * Var_Parse --
3402: * Given the start of a variable invocation, extract the variable
3403: * name and find its value, then modify it according to the
3404: * specification.
3405: *
3406: * Input:
3407: * str The string to parse
3408: * ctxt The context for the variable
1.259 rillig 3409: * flags VARE_UNDEFERR if undefineds are an error
3410: * VARE_WANTRES if we actually want the result
3411: * VARE_ASSIGN if we are in a := assignment
1.108 sjg 3412: * lengthPtr OUT: The length of the specification
1.121 apb 3413: * freePtr OUT: Non-NULL if caller should free *freePtr
1.108 sjg 3414: *
3415: * Results:
3416: * The (possibly-modified) value of the variable or var_Error if the
3417: * specification is invalid. The length of the specification is
3418: * placed in *lengthPtr (for invalid specifications, this is just
3419: * 2...?).
1.121 apb 3420: * If *freePtr is non-NULL then it's a pointer that the caller
3421: * should pass to free() to free memory used by the result.
1.108 sjg 3422: *
3423: * Side Effects:
3424: * None.
3425: *
3426: *-----------------------------------------------------------------------
3427: */
3428: /* coverity[+alloc : arg-*4] */
3429: char *
1.259 rillig 3430: Var_Parse(const char *str, GNode *ctxt, VarEvalFlags flags,
1.202 christos 3431: int *lengthPtr, void **freePtr)
1.108 sjg 3432: {
1.240 rillig 3433: const char *tstr; /* Pointer into str */
3434: Var *v; /* Variable in invocation */
3435: Boolean haveModifier; /* TRUE if have modifiers for the variable */
3436: char endc; /* Ending character when variable in parens
1.108 sjg 3437: * or braces */
1.240 rillig 3438: char startc; /* Starting character when variable in parens
1.108 sjg 3439: * or braces */
1.240 rillig 3440: int vlen; /* Length of variable name */
3441: const char *start; /* Points to original start of str */
3442: char *nstr; /* New string, used during expansion */
3443: Boolean dynamic; /* TRUE if the variable is local and we're
1.108 sjg 3444: * expanding it in a non-local context. This
3445: * is done to support dynamic sources. The
3446: * result is just the invocation, unaltered */
1.240 rillig 3447: const char *extramodifiers; /* extra modifiers to apply first */
3448: char name[2];
1.1 cgd 3449:
1.108 sjg 3450: *freePtr = NULL;
1.191 dholland 3451: extramodifiers = NULL;
1.108 sjg 3452: dynamic = FALSE;
3453: start = str;
1.1 cgd 3454:
1.141 dsl 3455: startc = str[1];
3456: if (startc != PROPEN && startc != BROPEN) {
1.108 sjg 3457: /*
3458: * If it's not bounded by braces of some sort, life is much simpler.
3459: * We just need to check for the first character and return the
3460: * value if it exists.
3461: */
1.15 christos 3462:
1.141 dsl 3463: /* Error out some really stupid names */
3464: if (startc == '\0' || strchr(")}:$", startc)) {
3465: *lengthPtr = 1;
3466: return var_Error;
3467: }
3468: name[0] = startc;
1.108 sjg 3469: name[1] = '\0';
1.16 christos 3470:
1.108 sjg 3471: v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1.136 dsl 3472: if (v == NULL) {
1.108 sjg 3473: *lengthPtr = 2;
1.1 cgd 3474:
1.108 sjg 3475: if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
3476: /*
3477: * If substituting a local variable in a non-local context,
3478: * assume it's for dynamic source stuff. We have to handle
3479: * this specially and return the longhand for the variable
3480: * with the dollar sign escaped so it makes it back to the
3481: * caller. Only four of the local variables are treated
3482: * specially as they are the only four that will be set
3483: * when dynamic sources are expanded.
3484: */
3485: switch (str[1]) {
1.242 rillig 3486: case '@':
3487: return UNCONST("$(.TARGET)");
3488: case '%':
3489: return UNCONST("$(.MEMBER)");
3490: case '*':
3491: return UNCONST("$(.PREFIX)");
3492: case '!':
3493: return UNCONST("$(.ARCHIVE)");
1.108 sjg 3494: }
3495: }
1.259 rillig 3496: return (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.108 sjg 3497: } else {
3498: haveModifier = FALSE;
3499: tstr = &str[1];
3500: endc = str[1];
3501: }
1.123 apb 3502: } else {
1.240 rillig 3503: Buffer buf; /* Holds the variable name */
1.185 sjg 3504: int depth = 1;
1.1 cgd 3505:
1.108 sjg 3506: endc = startc == PROPEN ? PRCLOSE : BRCLOSE;
1.146 dsl 3507: Buf_Init(&buf, 0);
1.1 cgd 3508:
1.108 sjg 3509: /*
3510: * Skip to the end character or a colon, whichever comes first.
3511: */
1.249 rillig 3512: for (tstr = str + 2; *tstr != '\0'; tstr++) {
1.240 rillig 3513: /* Track depth so we can spot parse errors. */
3514: if (*tstr == startc)
1.185 sjg 3515: depth++;
3516: if (*tstr == endc) {
3517: if (--depth == 0)
3518: break;
3519: }
1.240 rillig 3520: if (depth == 1 && *tstr == ':')
1.185 sjg 3521: break;
1.240 rillig 3522: /* A variable inside a variable, expand. */
1.108 sjg 3523: if (*tstr == '$') {
1.127 christos 3524: int rlen;
1.108 sjg 3525: void *freeIt;
1.226 rillig 3526: char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
1.240 rillig 3527: if (rval != NULL)
1.146 dsl 3528: Buf_AddBytes(&buf, strlen(rval), rval);
1.196 christos 3529: free(freeIt);
1.108 sjg 3530: tstr += rlen - 1;
1.242 rillig 3531: } else
1.146 dsl 3532: Buf_AddByte(&buf, *tstr);
1.108 sjg 3533: }
3534: if (*tstr == ':') {
3535: haveModifier = TRUE;
1.185 sjg 3536: } else if (*tstr == endc) {
1.108 sjg 3537: haveModifier = FALSE;
3538: } else {
3539: /*
3540: * If we never did find the end character, return NULL
3541: * right now, setting the length to be the distance to
3542: * the end of the string, since that's what make does.
3543: */
3544: *lengthPtr = tstr - str;
1.146 dsl 3545: Buf_Destroy(&buf, TRUE);
1.231 rillig 3546: return var_Error;
1.108 sjg 3547: }
1.146 dsl 3548: str = Buf_GetAll(&buf, &vlen);
1.93 sjg 3549:
1.123 apb 3550: /*
3551: * At this point, str points into newly allocated memory from
3552: * buf, containing only the name of the variable.
3553: *
3554: * start and tstr point into the const string that was pointed
3555: * to by the original value of the str parameter. start points
3556: * to the '$' at the beginning of the string, while tstr points
3557: * to the char just after the end of the variable name -- this
3558: * will be '\0', ':', PRCLOSE, or BRCLOSE.
3559: */
3560:
1.108 sjg 3561: v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1.141 dsl 3562: /*
3563: * Check also for bogus D and F forms of local variables since we're
3564: * in a local context and the name is the right length.
3565: */
1.136 dsl 3566: if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
1.141 dsl 3567: (vlen == 2) && (str[1] == 'F' || str[1] == 'D') &&
1.190 dholland 3568: strchr("@%?*!<>", str[0]) != NULL) {
1.108 sjg 3569: /*
1.141 dsl 3570: * Well, it's local -- go look for it.
1.108 sjg 3571: */
1.141 dsl 3572: name[0] = *str;
3573: name[1] = '\0';
3574: v = VarFind(name, ctxt, 0);
1.15 christos 3575:
1.141 dsl 3576: if (v != NULL) {
3577: if (str[1] == 'D') {
1.240 rillig 3578: extramodifiers = "H:";
1.242 rillig 3579: } else { /* F */
1.240 rillig 3580: extramodifiers = "T:";
1.1 cgd 3581: }
3582: }
1.108 sjg 3583: }
3584:
1.136 dsl 3585: if (v == NULL) {
1.108 sjg 3586: if (((vlen == 1) ||
1.141 dsl 3587: (((vlen == 2) && (str[1] == 'F' || str[1] == 'D')))) &&
1.108 sjg 3588: ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
3589: {
3590: /*
3591: * If substituting a local variable in a non-local context,
3592: * assume it's for dynamic source stuff. We have to handle
3593: * this specially and return the longhand for the variable
3594: * with the dollar sign escaped so it makes it back to the
3595: * caller. Only four of the local variables are treated
3596: * specially as they are the only four that will be set
3597: * when dynamic sources are expanded.
3598: */
3599: switch (*str) {
1.242 rillig 3600: case '@':
3601: case '%':
3602: case '*':
3603: case '!':
3604: dynamic = TRUE;
3605: break;
1.108 sjg 3606: }
1.240 rillig 3607: } else if (vlen > 2 && *str == '.' &&
1.108 sjg 3608: isupper((unsigned char) str[1]) &&
1.240 rillig 3609: (ctxt == VAR_CMD || ctxt == VAR_GLOBAL))
1.108 sjg 3610: {
1.240 rillig 3611: int len = vlen - 1;
1.108 sjg 3612: if ((strncmp(str, ".TARGET", len) == 0) ||
3613: (strncmp(str, ".ARCHIVE", len) == 0) ||
3614: (strncmp(str, ".PREFIX", len) == 0) ||
3615: (strncmp(str, ".MEMBER", len) == 0))
3616: {
3617: dynamic = TRUE;
3618: }
1.1 cgd 3619: }
1.15 christos 3620:
1.108 sjg 3621: if (!haveModifier) {
3622: /*
3623: * No modifiers -- have specification length so we can return
3624: * now.
3625: */
3626: *lengthPtr = tstr - start + 1;
3627: if (dynamic) {
1.134 joerg 3628: char *pstr = bmake_strndup(start, *lengthPtr);
1.108 sjg 3629: *freePtr = pstr;
1.146 dsl 3630: Buf_Destroy(&buf, TRUE);
1.231 rillig 3631: return pstr;
1.40 sjg 3632: } else {
1.146 dsl 3633: Buf_Destroy(&buf, TRUE);
1.259 rillig 3634: return (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.40 sjg 3635: }
1.1 cgd 3636: } else {
1.108 sjg 3637: /*
3638: * Still need to get to the end of the variable specification,
3639: * so kludge up a Var structure for the modifications
3640: */
1.134 joerg 3641: v = bmake_malloc(sizeof(Var));
1.108 sjg 3642: v->name = UNCONST(str);
1.146 dsl 3643: Buf_Init(&v->val, 1);
1.108 sjg 3644: v->flags = VAR_JUNK;
1.146 dsl 3645: Buf_Destroy(&buf, FALSE);
1.1 cgd 3646: }
1.108 sjg 3647: } else
1.146 dsl 3648: Buf_Destroy(&buf, TRUE);
1.108 sjg 3649: }
3650:
1.188 joerg 3651: if (v->flags & VAR_IN_USE) {
3652: Fatal("Variable %s is recursive.", v->name);
3653: /*NOTREACHED*/
3654: } else {
3655: v->flags |= VAR_IN_USE;
3656: }
3657: /*
3658: * Before doing any modification, we have to make sure the value
3659: * has been fully expanded. If it looks like recursion might be
3660: * necessary (there's a dollar sign somewhere in the variable's value)
3661: * we just call Var_Subst to do any other substitutions that are
3662: * necessary. Note that the value returned by Var_Subst will have
3663: * been dynamically-allocated, so it will need freeing when we
3664: * return.
3665: */
3666: nstr = Buf_GetAll(&v->val, NULL);
1.259 rillig 3667: if (strchr(nstr, '$') != NULL && (flags & VARE_WANTRES) != 0) {
1.202 christos 3668: nstr = Var_Subst(NULL, nstr, ctxt, flags);
1.188 joerg 3669: *freePtr = nstr;
3670: }
1.187 christos 3671:
1.188 joerg 3672: v->flags &= ~VAR_IN_USE;
1.108 sjg 3673:
1.240 rillig 3674: if (nstr != NULL && (haveModifier || extramodifiers != NULL)) {
1.191 dholland 3675: void *extraFree;
1.127 christos 3676: int used;
1.108 sjg 3677:
1.191 dholland 3678: extraFree = NULL;
3679: if (extramodifiers != NULL) {
1.240 rillig 3680: nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
3681: v, ctxt, flags, &used, &extraFree);
1.191 dholland 3682: }
3683:
3684: if (haveModifier) {
1.240 rillig 3685: /* Skip initial colon. */
3686: tstr++;
1.191 dholland 3687:
1.240 rillig 3688: nstr = ApplyModifiers(nstr, tstr, startc, endc,
3689: v, ctxt, flags, &used, freePtr);
3690: tstr += used;
3691: free(extraFree);
1.191 dholland 3692: } else {
1.240 rillig 3693: *freePtr = extraFree;
1.191 dholland 3694: }
1.119 sjg 3695: }
1.240 rillig 3696: *lengthPtr = tstr - start + (*tstr ? 1 : 0);
1.15 christos 3697:
1.1 cgd 3698: if (v->flags & VAR_FROM_ENV) {
1.249 rillig 3699: Boolean destroy = FALSE;
1.15 christos 3700:
1.146 dsl 3701: if (nstr != Buf_GetAll(&v->val, NULL)) {
1.1 cgd 3702: destroy = TRUE;
3703: } else {
3704: /*
3705: * Returning the value unmodified, so tell the caller to free
3706: * the thing.
3707: */
1.104 christos 3708: *freePtr = nstr;
1.1 cgd 3709: }
1.105 christos 3710: VarFreeEnv(v, destroy);
1.1 cgd 3711: } else if (v->flags & VAR_JUNK) {
3712: /*
1.121 apb 3713: * Perform any free'ing needed and set *freePtr to NULL so the caller
1.1 cgd 3714: * doesn't try to free a static pointer.
1.40 sjg 3715: * If VAR_KEEP is also set then we want to keep str as is.
1.1 cgd 3716: */
1.58 itojun 3717: if (!(v->flags & VAR_KEEP)) {
1.40 sjg 3718: if (*freePtr) {
1.73 christos 3719: free(nstr);
1.108 sjg 3720: *freePtr = NULL;
1.40 sjg 3721: }
3722: if (dynamic) {
1.134 joerg 3723: nstr = bmake_strndup(start, *lengthPtr);
1.104 christos 3724: *freePtr = nstr;
1.40 sjg 3725: } else {
1.259 rillig 3726: nstr = (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.40 sjg 3727: }
1.34 christos 3728: }
1.146 dsl 3729: if (nstr != Buf_GetAll(&v->val, NULL))
3730: Buf_Destroy(&v->val, TRUE);
1.98 christos 3731: free(v->name);
3732: free(v);
1.1 cgd 3733: }
1.231 rillig 3734: return nstr;
1.1 cgd 3735: }
3736:
3737: /*-
3738: *-----------------------------------------------------------------------
3739: * Var_Subst --
1.250 rillig 3740: * Substitute for all variables in the given string in the given context.
1.259 rillig 3741: * If flags & VARE_UNDEFERR, Parse_Error will be called when an undefined
1.1 cgd 3742: * variable is encountered.
3743: *
1.70 wiz 3744: * Input:
3745: * var Named variable || NULL for all
3746: * str the string which to substitute
3747: * ctxt the context wherein to find variables
1.259 rillig 3748: * flags VARE_UNDEFERR if undefineds are an error
3749: * VARE_WANTRES if we actually want the result
3750: * VARE_ASSIGN if we are in a := assignment
1.70 wiz 3751: *
1.1 cgd 3752: * Results:
3753: * The resulting string.
3754: *
3755: * Side Effects:
1.250 rillig 3756: * None.
1.1 cgd 3757: *-----------------------------------------------------------------------
3758: */
3759: char *
1.259 rillig 3760: Var_Subst(const char *var, const char *str, GNode *ctxt, VarEvalFlags flags)
1.1 cgd 3761: {
1.240 rillig 3762: Buffer buf; /* Buffer for forming things */
3763: char *val; /* Value to substitute for a variable */
3764: int length; /* Length of the variable invocation */
3765: Boolean trailingBslash; /* variable ends in \ */
3766: void *freeIt = NULL; /* Set if it should be freed */
3767: static Boolean errorReported; /* Set true if an error has already
3768: * been reported to prevent a plethora
3769: * of messages when recursing */
1.1 cgd 3770:
1.146 dsl 3771: Buf_Init(&buf, 0);
1.1 cgd 3772: errorReported = FALSE;
1.96 christos 3773: trailingBslash = FALSE;
1.1 cgd 3774:
3775: while (*str) {
1.96 christos 3776: if (*str == '\n' && trailingBslash)
1.146 dsl 3777: Buf_AddByte(&buf, ' ');
1.48 mycroft 3778: if (var == NULL && (*str == '$') && (str[1] == '$')) {
1.1 cgd 3779: /*
3780: * A dollar sign may be escaped either with another dollar sign.
3781: * In such a case, we skip over the escape character and store the
3782: * dollar sign into the buffer directly.
3783: */
1.259 rillig 3784: if (save_dollars && (flags & VARE_ASSIGN))
1.201 christos 3785: Buf_AddByte(&buf, *str);
1.1 cgd 3786: str++;
1.146 dsl 3787: Buf_AddByte(&buf, *str);
1.1 cgd 3788: str++;
3789: } else if (*str != '$') {
3790: /*
3791: * Skip as many characters as possible -- either to the end of
3792: * the string or to the next dollar sign (variable invocation).
3793: */
1.249 rillig 3794: const char *cp;
1.1 cgd 3795:
1.5 cgd 3796: for (cp = str++; *str != '$' && *str != '\0'; str++)
3797: continue;
1.146 dsl 3798: Buf_AddBytes(&buf, str - cp, cp);
1.1 cgd 3799: } else {
1.48 mycroft 3800: if (var != NULL) {
3801: int expand;
3802: for (;;) {
1.100 christos 3803: if (str[1] == '\0') {
3804: /* A trailing $ is kind of a special case */
1.146 dsl 3805: Buf_AddByte(&buf, str[0]);
1.100 christos 3806: str++;
3807: expand = FALSE;
3808: } else if (str[1] != PROPEN && str[1] != BROPEN) {
1.48 mycroft 3809: if (str[1] != *var || strlen(var) > 1) {
1.146 dsl 3810: Buf_AddBytes(&buf, 2, str);
1.48 mycroft 3811: str += 2;
3812: expand = FALSE;
1.242 rillig 3813: } else
1.48 mycroft 3814: expand = TRUE;
3815: break;
1.240 rillig 3816: } else {
1.73 christos 3817: const char *p;
1.48 mycroft 3818:
1.242 rillig 3819: /* Scan up to the end of the variable name. */
1.48 mycroft 3820: for (p = &str[2]; *p &&
1.100 christos 3821: *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++)
1.48 mycroft 3822: if (*p == '$')
3823: break;
3824: /*
3825: * A variable inside the variable. We cannot expand
3826: * the external variable yet, so we try again with
3827: * the nested one
3828: */
3829: if (*p == '$') {
1.146 dsl 3830: Buf_AddBytes(&buf, p - str, str);
1.48 mycroft 3831: str = p;
3832: continue;
3833: }
3834:
1.127 christos 3835: if (strncmp(var, str + 2, p - str - 2) != 0 ||
1.48 mycroft 3836: var[p - str - 2] != '\0') {
3837: /*
3838: * Not the variable we want to expand, scan
3839: * until the next variable
3840: */
1.249 rillig 3841: for (; *p != '$' && *p != '\0'; p++)
1.48 mycroft 3842: continue;
1.146 dsl 3843: Buf_AddBytes(&buf, p - str, str);
1.48 mycroft 3844: str = p;
3845: expand = FALSE;
1.240 rillig 3846: } else
1.48 mycroft 3847: expand = TRUE;
3848: break;
3849: }
3850: }
3851: if (!expand)
3852: continue;
3853: }
3854:
1.202 christos 3855: val = Var_Parse(str, ctxt, flags, &length, &freeIt);
1.1 cgd 3856:
3857: /*
3858: * When we come down here, val should either point to the
3859: * value of this variable, suitably modified, or be NULL.
3860: * Length should be the total length of the potential
3861: * variable invocation (from $ to end character...)
3862: */
3863: if (val == var_Error || val == varNoError) {
3864: /*
3865: * If performing old-time variable substitution, skip over
3866: * the variable and continue with the substitution. Otherwise,
3867: * store the dollar sign and advance str so we continue with
3868: * the string...
3869: */
3870: if (oldVars) {
3871: str += length;
1.259 rillig 3872: } else if ((flags & VARE_UNDEFERR) || val == var_Error) {
1.1 cgd 3873: /*
3874: * If variable is undefined, complain and skip the
3875: * variable. The complaint will stop us from doing anything
3876: * when the file is parsed.
3877: */
3878: if (!errorReported) {
1.231 rillig 3879: Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",
3880: length, str);
1.1 cgd 3881: }
3882: str += length;
3883: errorReported = TRUE;
3884: } else {
1.146 dsl 3885: Buf_AddByte(&buf, *str);
1.1 cgd 3886: str += 1;
3887: }
3888: } else {
3889: /*
3890: * We've now got a variable structure to store in. But first,
3891: * advance the string pointer.
3892: */
3893: str += length;
1.15 christos 3894:
1.1 cgd 3895: /*
3896: * Copy all the characters from the variable value straight
3897: * into the new string.
3898: */
1.96 christos 3899: length = strlen(val);
1.146 dsl 3900: Buf_AddBytes(&buf, length, val);
1.96 christos 3901: trailingBslash = length > 0 && val[length - 1] == '\\';
1.104 christos 3902: }
1.196 christos 3903: free(freeIt);
3904: freeIt = NULL;
1.1 cgd 3905: }
3906: }
1.15 christos 3907:
1.168 sjg 3908: return Buf_DestroyCompact(&buf);
1.1 cgd 3909: }
3910:
1.250 rillig 3911: /* Initialize the module. */
1.1 cgd 3912: void
1.70 wiz 3913: Var_Init(void)
1.1 cgd 3914: {
1.184 sjg 3915: VAR_INTERNAL = Targ_NewGN("Internal");
1.92 christos 3916: VAR_GLOBAL = Targ_NewGN("Global");
3917: VAR_CMD = Targ_NewGN("Command");
1.6 jtc 3918: }
3919:
1.1 cgd 3920:
1.6 jtc 3921: void
1.70 wiz 3922: Var_End(void)
1.6 jtc 3923: {
1.286 sjg 3924: Var_Stats();
3925: }
3926:
3927: void
3928: Var_Stats(void)
3929: {
3930: Hash_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL");
1.1 cgd 3931: }
1.15 christos 3932:
1.1 cgd 3933:
3934: /****************** PRINT DEBUGGING INFO *****************/
1.36 mycroft 3935: static void
1.241 rillig 3936: VarPrintVar(void *vp, void *data MAKE_ATTR_UNUSED)
1.1 cgd 3937: {
1.242 rillig 3938: Var *v = (Var *)vp;
1.146 dsl 3939: fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL));
1.1 cgd 3940: }
3941:
3942: /*-
3943: *-----------------------------------------------------------------------
3944: * Var_Dump --
3945: * print all variables in a context
3946: *-----------------------------------------------------------------------
3947: */
1.5 cgd 3948: void
1.70 wiz 3949: Var_Dump(GNode *ctxt)
1.1 cgd 3950: {
1.241 rillig 3951: Hash_ForEach(&ctxt->context, VarPrintVar, NULL);
1.1 cgd 3952: }
CVSweb <webmaster@jp.NetBSD.org>