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