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