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