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