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