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