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