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