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