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