var.c revision 1.122 1 /* $NetBSD: var.c,v 1.122 2007/10/13 16:16:41 apb 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.122 2007/10/13 16:16:41 apb 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.122 2007/10/13 16:16:41 apb 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 = estrdup(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 = estrdup(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 else if (!*tstr && endc) {
2233 Error("Unclosed variable specification for %s", v->name);
2234 goto out;
2235 }
2236 continue;
2237 }
2238 if (DEBUG(VAR)) {
2239 fprintf(debug_file, "Applying :%c to \"%s\"\n", *tstr, nstr);
2240 }
2241 newStr = var_Error;
2242 switch ((modifier = *tstr)) {
2243 case ':':
2244 {
2245 if (tstr[1] == '=' ||
2246 (tstr[2] == '=' &&
2247 (tstr[1] == '!' || tstr[1] == '+' || tstr[1] == '?'))) {
2248 /*
2249 * "::=", "::!=", "::+=", or "::?="
2250 */
2251 GNode *v_ctxt; /* context where v belongs */
2252 const char *emsg;
2253 char *sv_name;
2254 VarPattern pattern;
2255 int how;
2256
2257 v_ctxt = ctxt;
2258 sv_name = NULL;
2259 ++tstr;
2260 if (v->flags & VAR_JUNK) {
2261 /*
2262 * We need to estrdup() it incase
2263 * VarGetPattern() recurses.
2264 */
2265 sv_name = v->name;
2266 v->name = estrdup(v->name);
2267 } else if (ctxt != VAR_GLOBAL) {
2268 Var *gv = VarFind(v->name, ctxt, 0);
2269 if (gv == (Var *)NIL)
2270 v_ctxt = VAR_GLOBAL;
2271 else
2272 VarFreeEnv(gv, TRUE);
2273 }
2274
2275 switch ((how = *tstr)) {
2276 case '+':
2277 case '?':
2278 case '!':
2279 cp = &tstr[2];
2280 break;
2281 default:
2282 cp = ++tstr;
2283 break;
2284 }
2285 delim = BRCLOSE;
2286 pattern.flags = 0;
2287
2288 pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2289 &cp, delim, NULL,
2290 &pattern.rightLen,
2291 NULL);
2292 if (v->flags & VAR_JUNK) {
2293 /* restore original name */
2294 free(v->name);
2295 v->name = sv_name;
2296 }
2297 if (pattern.rhs == NULL)
2298 goto cleanup;
2299
2300 termc = *--cp;
2301 delim = '\0';
2302
2303 switch (how) {
2304 case '+':
2305 Var_Append(v->name, pattern.rhs, v_ctxt);
2306 break;
2307 case '!':
2308 newStr = Cmd_Exec(pattern.rhs, &emsg);
2309 if (emsg)
2310 Error(emsg, nstr);
2311 else
2312 Var_Set(v->name, newStr, v_ctxt, 0);
2313 if (newStr)
2314 free(newStr);
2315 break;
2316 case '?':
2317 if ((v->flags & VAR_JUNK) == 0)
2318 break;
2319 /* FALLTHROUGH */
2320 default:
2321 Var_Set(v->name, pattern.rhs, v_ctxt, 0);
2322 break;
2323 }
2324 free(UNCONST(pattern.rhs));
2325 newStr = var_Error;
2326 break;
2327 }
2328 goto default_case; /* "::<unrecognised>" */
2329 }
2330 case '@':
2331 {
2332 VarLoop_t loop;
2333 int flags = VAR_NOSUBST;
2334
2335 cp = ++tstr;
2336 delim = '@';
2337 if ((loop.tvar = VarGetPattern(ctxt, &parsestate, errnum,
2338 &cp, delim,
2339 &flags, &loop.tvarLen,
2340 NULL)) == NULL)
2341 goto cleanup;
2342
2343 if ((loop.str = VarGetPattern(ctxt, &parsestate, errnum,
2344 &cp, delim,
2345 &flags, &loop.strLen,
2346 NULL)) == NULL)
2347 goto cleanup;
2348
2349 termc = *cp;
2350 delim = '\0';
2351
2352 loop.errnum = errnum;
2353 loop.ctxt = ctxt;
2354 newStr = VarModify(ctxt, &parsestate, nstr, VarLoopExpand,
2355 &loop);
2356 free(loop.tvar);
2357 free(loop.str);
2358 break;
2359 }
2360 case 'D':
2361 case 'U':
2362 {
2363 Buffer buf; /* Buffer for patterns */
2364 int wantit; /* want data in buffer */
2365
2366 /*
2367 * Pass through tstr looking for 1) escaped delimiters,
2368 * '$'s and backslashes (place the escaped character in
2369 * uninterpreted) and 2) unescaped $'s that aren't before
2370 * the delimiter (expand the variable substitution).
2371 * The result is left in the Buffer buf.
2372 */
2373 buf = Buf_Init(0);
2374 for (cp = tstr + 1;
2375 *cp != endc && *cp != ':' && *cp != '\0';
2376 cp++) {
2377 if ((*cp == '\\') &&
2378 ((cp[1] == ':') ||
2379 (cp[1] == '$') ||
2380 (cp[1] == endc) ||
2381 (cp[1] == '\\')))
2382 {
2383 Buf_AddByte(buf, (Byte)cp[1]);
2384 cp++;
2385 } else if (*cp == '$') {
2386 /*
2387 * If unescaped dollar sign, assume it's a
2388 * variable substitution and recurse.
2389 */
2390 char *cp2;
2391 int len;
2392 void *freeIt;
2393
2394 cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
2395 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
2396 if (freeIt)
2397 free(freeIt);
2398 cp += len - 1;
2399 } else {
2400 Buf_AddByte(buf, (Byte)*cp);
2401 }
2402 }
2403 Buf_AddByte(buf, (Byte)'\0');
2404
2405 termc = *cp;
2406
2407 if (*tstr == 'U')
2408 wantit = ((v->flags & VAR_JUNK) != 0);
2409 else
2410 wantit = ((v->flags & VAR_JUNK) == 0);
2411 if ((v->flags & VAR_JUNK) != 0)
2412 v->flags |= VAR_KEEP;
2413 if (wantit) {
2414 newStr = (char *)Buf_GetAll(buf, NULL);
2415 Buf_Destroy(buf, FALSE);
2416 } else {
2417 newStr = nstr;
2418 Buf_Destroy(buf, TRUE);
2419 }
2420 break;
2421 }
2422 case 'L':
2423 {
2424 if ((v->flags & VAR_JUNK) != 0)
2425 v->flags |= VAR_KEEP;
2426 newStr = estrdup(v->name);
2427 cp = ++tstr;
2428 termc = *tstr;
2429 break;
2430 }
2431 case 'P':
2432 {
2433 GNode *gn;
2434
2435 if ((v->flags & VAR_JUNK) != 0)
2436 v->flags |= VAR_KEEP;
2437 gn = Targ_FindNode(v->name, TARG_NOCREATE);
2438 if (gn == NILGNODE || gn->type & OP_NOPATH) {
2439 newStr = NULL;
2440 } else if (gn->path) {
2441 newStr = estrdup(gn->path);
2442 } else {
2443 newStr = Dir_FindFile(v->name, Suff_FindPath(gn));
2444 }
2445 if (!newStr) {
2446 newStr = estrdup(v->name);
2447 }
2448 cp = ++tstr;
2449 termc = *tstr;
2450 break;
2451 }
2452 case '!':
2453 {
2454 const char *emsg;
2455 VarPattern pattern;
2456 pattern.flags = 0;
2457
2458 delim = '!';
2459
2460 cp = ++tstr;
2461 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2462 &cp, delim,
2463 NULL, &pattern.rightLen,
2464 NULL)) == NULL)
2465 goto cleanup;
2466 newStr = Cmd_Exec(pattern.rhs, &emsg);
2467 free(UNCONST(pattern.rhs));
2468 if (emsg)
2469 Error(emsg, nstr);
2470 termc = *cp;
2471 delim = '\0';
2472 if (v->flags & VAR_JUNK) {
2473 v->flags |= VAR_KEEP;
2474 }
2475 break;
2476 }
2477 case '[':
2478 {
2479 /*
2480 * Look for the closing ']', recursively
2481 * expanding any embedded variables.
2482 *
2483 * estr is a pointer to the expanded result,
2484 * which we must free().
2485 */
2486 char *estr;
2487
2488 cp = tstr+1; /* point to char after '[' */
2489 delim = ']'; /* look for closing ']' */
2490 estr = VarGetPattern(ctxt, &parsestate,
2491 errnum, &cp, delim,
2492 NULL, NULL, NULL);
2493 if (estr == NULL)
2494 goto cleanup; /* report missing ']' */
2495 /* now cp points just after the closing ']' */
2496 delim = '\0';
2497 if (cp[0] != ':' && cp[0] != endc) {
2498 /* Found junk after ']' */
2499 free(estr);
2500 goto bad_modifier;
2501 }
2502 if (estr[0] == '\0') {
2503 /* Found empty square brackets in ":[]". */
2504 free(estr);
2505 goto bad_modifier;
2506 } else if (estr[0] == '#' && estr[1] == '\0') {
2507 /* Found ":[#]" */
2508
2509 /*
2510 * We will need enough space for the decimal
2511 * representation of an int. We calculate the
2512 * space needed for the octal representation,
2513 * and add enough slop to cope with a '-' sign
2514 * (which should never be needed) and a '\0'
2515 * string terminator.
2516 */
2517 int newStrSize =
2518 (sizeof(int) * CHAR_BIT + 2) / 3 + 2;
2519
2520 newStr = emalloc(newStrSize);
2521 if (parsestate.oneBigWord) {
2522 strncpy(newStr, "1", newStrSize);
2523 } else {
2524 /* XXX: brk_string() is a rather expensive
2525 * way of counting words. */
2526 char **av;
2527 char *as;
2528 int ac;
2529
2530 av = brk_string(nstr, &ac, FALSE, &as);
2531 snprintf(newStr, newStrSize, "%d", ac);
2532 free(as);
2533 free(av);
2534 }
2535 termc = *cp;
2536 free(estr);
2537 break;
2538 } else if (estr[0] == '*' && estr[1] == '\0') {
2539 /* Found ":[*]" */
2540 parsestate.oneBigWord = TRUE;
2541 newStr = nstr;
2542 termc = *cp;
2543 free(estr);
2544 break;
2545 } else if (estr[0] == '@' && estr[1] == '\0') {
2546 /* Found ":[@]" */
2547 parsestate.oneBigWord = FALSE;
2548 newStr = nstr;
2549 termc = *cp;
2550 free(estr);
2551 break;
2552 } else {
2553 /*
2554 * We expect estr to contain a single
2555 * integer for :[N], or two integers
2556 * separated by ".." for :[start..end].
2557 */
2558 char *ep;
2559
2560 VarSelectWords_t seldata = { 0, 0 };
2561
2562 seldata.start = strtol(estr, &ep, 0);
2563 if (ep == estr) {
2564 /* Found junk instead of a number */
2565 free(estr);
2566 goto bad_modifier;
2567 } else if (ep[0] == '\0') {
2568 /* Found only one integer in :[N] */
2569 seldata.end = seldata.start;
2570 } else if (ep[0] == '.' && ep[1] == '.' &&
2571 ep[2] != '\0') {
2572 /* Expecting another integer after ".." */
2573 ep += 2;
2574 seldata.end = strtol(ep, &ep, 0);
2575 if (ep[0] != '\0') {
2576 /* Found junk after ".." */
2577 free(estr);
2578 goto bad_modifier;
2579 }
2580 } else {
2581 /* Found junk instead of ".." */
2582 free(estr);
2583 goto bad_modifier;
2584 }
2585 /*
2586 * Now seldata is properly filled in,
2587 * but we still have to check for 0 as
2588 * a special case.
2589 */
2590 if (seldata.start == 0 && seldata.end == 0) {
2591 /* ":[0]" or perhaps ":[0..0]" */
2592 parsestate.oneBigWord = TRUE;
2593 newStr = nstr;
2594 termc = *cp;
2595 free(estr);
2596 break;
2597 } else if (seldata.start == 0 ||
2598 seldata.end == 0) {
2599 /* ":[0..N]" or ":[N..0]" */
2600 free(estr);
2601 goto bad_modifier;
2602 }
2603 /*
2604 * Normal case: select the words
2605 * described by seldata.
2606 */
2607 newStr = VarSelectWords(ctxt, &parsestate,
2608 nstr, &seldata);
2609
2610 termc = *cp;
2611 free(estr);
2612 break;
2613 }
2614
2615 }
2616 case 't':
2617 {
2618 cp = tstr + 1; /* make sure it is set */
2619 if (tstr[1] != endc && tstr[1] != ':') {
2620 if (tstr[1] == 's') {
2621 /*
2622 * Use the char (if any) at tstr[2]
2623 * as the word separator.
2624 */
2625 VarPattern pattern;
2626
2627 if (tstr[2] != endc &&
2628 (tstr[3] == endc || tstr[3] == ':')) {
2629 /* ":ts<unrecognised><endc>" or
2630 * ":ts<unrecognised>:" */
2631 parsestate.varSpace = tstr[2];
2632 cp = tstr + 3;
2633 } else if (tstr[2] == endc || tstr[2] == ':') {
2634 /* ":ts<endc>" or ":ts:" */
2635 parsestate.varSpace = 0; /* no separator */
2636 cp = tstr + 2;
2637 } else if (tstr[2] == '\\') {
2638 switch (tstr[3]) {
2639 case 'n':
2640 parsestate.varSpace = '\n';
2641 cp = tstr + 4;
2642 break;
2643 case 't':
2644 parsestate.varSpace = '\t';
2645 cp = tstr + 4;
2646 break;
2647 default:
2648 if (isdigit((unsigned char)tstr[3])) {
2649 char *ep;
2650
2651 parsestate.varSpace =
2652 strtoul(&tstr[3], &ep, 0);
2653 if (*ep != ':' && *ep != endc)
2654 goto bad_modifier;
2655 cp = ep;
2656 } else {
2657 /*
2658 * ":ts<backslash><unrecognised>".
2659 */
2660 goto bad_modifier;
2661 }
2662 break;
2663 }
2664 } else {
2665 /*
2666 * Found ":ts<unrecognised><unrecognised>".
2667 */
2668 goto bad_modifier;
2669 }
2670
2671 termc = *cp;
2672
2673 /*
2674 * We cannot be certain that VarModify
2675 * will be used - even if there is a
2676 * subsequent modifier, so do a no-op
2677 * VarSubstitute now to for str to be
2678 * re-expanded without the spaces.
2679 */
2680 pattern.flags = VAR_SUB_ONE;
2681 pattern.lhs = pattern.rhs = "\032";
2682 pattern.leftLen = pattern.rightLen = 1;
2683
2684 newStr = VarModify(ctxt, &parsestate, nstr,
2685 VarSubstitute,
2686 &pattern);
2687 } else if (tstr[2] == endc || tstr[2] == ':') {
2688 /*
2689 * Check for two-character options:
2690 * ":tu", ":tl"
2691 */
2692 if (tstr[1] == 'u' || tstr[1] == 'l') {
2693 newStr = VarChangeCase(nstr, (tstr[1] == 'u'));
2694 cp = tstr + 2;
2695 termc = *cp;
2696 } else if (tstr[1] == 'W' || tstr[1] == 'w') {
2697 parsestate.oneBigWord = (tstr[1] == 'W');
2698 newStr = nstr;
2699 cp = tstr + 2;
2700 termc = *cp;
2701 } else {
2702 /* Found ":t<unrecognised>:" or
2703 * ":t<unrecognised><endc>". */
2704 goto bad_modifier;
2705 }
2706 } else {
2707 /*
2708 * Found ":t<unrecognised><unrecognised>".
2709 */
2710 goto bad_modifier;
2711 }
2712 } else {
2713 /*
2714 * Found ":t<endc>" or ":t:".
2715 */
2716 goto bad_modifier;
2717 }
2718 break;
2719 }
2720 case 'N':
2721 case 'M':
2722 {
2723 char *pattern;
2724 char *cp2;
2725 Boolean copy;
2726 int nest;
2727
2728 copy = FALSE;
2729 nest = 1;
2730 /*
2731 * In the loop below, ignore ':' unless we are at
2732 * (or back to) the original brace level.
2733 * XXX This will likely not work right if $() and ${}
2734 * are intermixed.
2735 */
2736 for (cp = tstr + 1;
2737 *cp != '\0' && !(*cp == ':' && nest == 1);
2738 cp++)
2739 {
2740 if (*cp == '\\' &&
2741 (cp[1] == ':' ||
2742 cp[1] == endc || cp[1] == startc)) {
2743 copy = TRUE;
2744 cp++;
2745 continue;
2746 }
2747 if (*cp == startc)
2748 ++nest;
2749 if (*cp == endc) {
2750 --nest;
2751 if (nest == 0)
2752 break;
2753 }
2754 }
2755 termc = *cp;
2756 *WR(cp) = '\0';
2757 if (copy) {
2758 /*
2759 * Need to compress the \:'s out of the pattern, so
2760 * allocate enough room to hold the uncompressed
2761 * pattern (note that cp started at tstr+1, so
2762 * cp - tstr takes the null byte into account) and
2763 * compress the pattern into the space.
2764 */
2765 pattern = emalloc(cp - tstr);
2766 for (cp2 = pattern, cp = tstr + 1;
2767 *cp != '\0';
2768 cp++, cp2++)
2769 {
2770 if ((*cp == '\\') &&
2771 (cp[1] == ':' || cp[1] == endc)) {
2772 cp++;
2773 }
2774 *cp2 = *cp;
2775 }
2776 *cp2 = '\0';
2777 } else {
2778 pattern = UNCONST(&tstr[1]);
2779 }
2780 if ((cp2 = strchr(pattern, '$'))) {
2781 cp2 = pattern;
2782 pattern = Var_Subst(NULL, cp2, ctxt, errnum);
2783 if (copy)
2784 free(cp2);
2785 copy = TRUE;
2786 }
2787 if (*tstr == 'M' || *tstr == 'm') {
2788 newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
2789 pattern);
2790 } else {
2791 newStr = VarModify(ctxt, &parsestate, nstr, VarNoMatch,
2792 pattern);
2793 }
2794 if (copy) {
2795 free(pattern);
2796 }
2797 break;
2798 }
2799 case 'S':
2800 {
2801 VarPattern pattern;
2802 Var_Parse_State tmpparsestate;
2803
2804 pattern.flags = 0;
2805 tmpparsestate = parsestate;
2806 delim = tstr[1];
2807 tstr += 2;
2808
2809 /*
2810 * If pattern begins with '^', it is anchored to the
2811 * start of the word -- skip over it and flag pattern.
2812 */
2813 if (*tstr == '^') {
2814 pattern.flags |= VAR_MATCH_START;
2815 tstr += 1;
2816 }
2817
2818 cp = tstr;
2819 if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
2820 &cp, delim,
2821 &pattern.flags,
2822 &pattern.leftLen,
2823 NULL)) == NULL)
2824 goto cleanup;
2825
2826 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2827 &cp, delim, NULL,
2828 &pattern.rightLen,
2829 &pattern)) == NULL)
2830 goto cleanup;
2831
2832 /*
2833 * Check for global substitution. If 'g' after the final
2834 * delimiter, substitution is global and is marked that
2835 * way.
2836 */
2837 for (;; cp++) {
2838 switch (*cp) {
2839 case 'g':
2840 pattern.flags |= VAR_SUB_GLOBAL;
2841 continue;
2842 case '1':
2843 pattern.flags |= VAR_SUB_ONE;
2844 continue;
2845 case 'W':
2846 tmpparsestate.oneBigWord = TRUE;
2847 continue;
2848 }
2849 break;
2850 }
2851
2852 termc = *cp;
2853 newStr = VarModify(ctxt, &tmpparsestate, nstr,
2854 VarSubstitute,
2855 &pattern);
2856
2857 /*
2858 * Free the two strings.
2859 */
2860 free(UNCONST(pattern.lhs));
2861 free(UNCONST(pattern.rhs));
2862 delim = '\0';
2863 break;
2864 }
2865 case '?':
2866 {
2867 VarPattern pattern;
2868 Boolean value;
2869
2870 /* find ':', and then substitute accordingly */
2871
2872 pattern.flags = 0;
2873
2874 cp = ++tstr;
2875 delim = ':';
2876 if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
2877 &cp, delim, NULL,
2878 &pattern.leftLen,
2879 NULL)) == NULL)
2880 goto cleanup;
2881
2882 /* BROPEN or PROPEN */
2883 delim = endc;
2884 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2885 &cp, delim, NULL,
2886 &pattern.rightLen,
2887 NULL)) == NULL)
2888 goto cleanup;
2889
2890 termc = *--cp;
2891 delim = '\0';
2892 if (Cond_EvalExpression(1, v->name, &value, 0)
2893 == COND_INVALID) {
2894 Error("Bad conditional expression `%s' in %s?%s:%s",
2895 v->name, v->name, pattern.lhs, pattern.rhs);
2896 goto cleanup;
2897 }
2898
2899 if (value) {
2900 newStr = UNCONST(pattern.lhs);
2901 free(UNCONST(pattern.rhs));
2902 } else {
2903 newStr = UNCONST(pattern.rhs);
2904 free(UNCONST(pattern.lhs));
2905 }
2906 if (v->flags & VAR_JUNK) {
2907 v->flags |= VAR_KEEP;
2908 }
2909 break;
2910 }
2911 #ifndef NO_REGEX
2912 case 'C':
2913 {
2914 VarREPattern pattern;
2915 char *re;
2916 int error;
2917 Var_Parse_State tmpparsestate;
2918
2919 pattern.flags = 0;
2920 tmpparsestate = parsestate;
2921 delim = tstr[1];
2922 tstr += 2;
2923
2924 cp = tstr;
2925
2926 if ((re = VarGetPattern(ctxt, &parsestate, errnum, &cp, delim,
2927 NULL, NULL, NULL)) == NULL)
2928 goto cleanup;
2929
2930 if ((pattern.replace = VarGetPattern(ctxt, &parsestate,
2931 errnum, &cp, delim, NULL,
2932 NULL, NULL)) == NULL){
2933 free(re);
2934 goto cleanup;
2935 }
2936
2937 for (;; cp++) {
2938 switch (*cp) {
2939 case 'g':
2940 pattern.flags |= VAR_SUB_GLOBAL;
2941 continue;
2942 case '1':
2943 pattern.flags |= VAR_SUB_ONE;
2944 continue;
2945 case 'W':
2946 tmpparsestate.oneBigWord = TRUE;
2947 continue;
2948 }
2949 break;
2950 }
2951
2952 termc = *cp;
2953
2954 error = regcomp(&pattern.re, re, REG_EXTENDED);
2955 free(re);
2956 if (error) {
2957 *lengthPtr = cp - start + 1;
2958 VarREError(error, &pattern.re, "RE substitution error");
2959 free(pattern.replace);
2960 goto cleanup;
2961 }
2962
2963 pattern.nsub = pattern.re.re_nsub + 1;
2964 if (pattern.nsub < 1)
2965 pattern.nsub = 1;
2966 if (pattern.nsub > 10)
2967 pattern.nsub = 10;
2968 pattern.matches = emalloc(pattern.nsub *
2969 sizeof(regmatch_t));
2970 newStr = VarModify(ctxt, &tmpparsestate, nstr,
2971 VarRESubstitute,
2972 &pattern);
2973 regfree(&pattern.re);
2974 free(pattern.replace);
2975 free(pattern.matches);
2976 delim = '\0';
2977 break;
2978 }
2979 #endif
2980 case 'Q':
2981 if (tstr[1] == endc || tstr[1] == ':') {
2982 newStr = VarQuote(nstr);
2983 cp = tstr + 1;
2984 termc = *cp;
2985 break;
2986 }
2987 goto default_case;
2988 case 'T':
2989 if (tstr[1] == endc || tstr[1] == ':') {
2990 newStr = VarModify(ctxt, &parsestate, nstr, VarTail,
2991 NULL);
2992 cp = tstr + 1;
2993 termc = *cp;
2994 break;
2995 }
2996 goto default_case;
2997 case 'H':
2998 if (tstr[1] == endc || tstr[1] == ':') {
2999 newStr = VarModify(ctxt, &parsestate, nstr, VarHead,
3000 NULL);
3001 cp = tstr + 1;
3002 termc = *cp;
3003 break;
3004 }
3005 goto default_case;
3006 case 'E':
3007 if (tstr[1] == endc || tstr[1] == ':') {
3008 newStr = VarModify(ctxt, &parsestate, nstr, VarSuffix,
3009 NULL);
3010 cp = tstr + 1;
3011 termc = *cp;
3012 break;
3013 }
3014 goto default_case;
3015 case 'R':
3016 if (tstr[1] == endc || tstr[1] == ':') {
3017 newStr = VarModify(ctxt, &parsestate, nstr, VarRoot,
3018 NULL);
3019 cp = tstr + 1;
3020 termc = *cp;
3021 break;
3022 }
3023 goto default_case;
3024 case 'O':
3025 {
3026 char otype;
3027
3028 cp = tstr + 1; /* skip to the rest in any case */
3029 if (tstr[1] == endc || tstr[1] == ':') {
3030 otype = 's';
3031 termc = *cp;
3032 } else if ( (tstr[1] == 'x') &&
3033 (tstr[2] == endc || tstr[2] == ':') ) {
3034 otype = tstr[1];
3035 cp = tstr + 2;
3036 termc = *cp;
3037 } else {
3038 goto bad_modifier;
3039 }
3040 newStr = VarOrder(nstr, otype);
3041 break;
3042 }
3043 case 'u':
3044 if (tstr[1] == endc || tstr[1] == ':') {
3045 newStr = VarUniq(nstr);
3046 cp = tstr + 1;
3047 termc = *cp;
3048 break;
3049 }
3050 goto default_case;
3051 #ifdef SUNSHCMD
3052 case 's':
3053 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
3054 const char *emsg;
3055 newStr = Cmd_Exec(nstr, &emsg);
3056 if (emsg)
3057 Error(emsg, nstr);
3058 cp = tstr + 2;
3059 termc = *cp;
3060 break;
3061 }
3062 goto default_case;
3063 #endif
3064 default:
3065 default_case:
3066 {
3067 #ifdef SYSVVARSUB
3068 /*
3069 * This can either be a bogus modifier or a System-V
3070 * substitution command.
3071 */
3072 VarPattern pattern;
3073 Boolean eqFound;
3074
3075 pattern.flags = 0;
3076 eqFound = FALSE;
3077 /*
3078 * First we make a pass through the string trying
3079 * to verify it is a SYSV-make-style translation:
3080 * it must be: <string1>=<string2>)
3081 */
3082 cp = tstr;
3083 cnt = 1;
3084 while (*cp != '\0' && cnt) {
3085 if (*cp == '=') {
3086 eqFound = TRUE;
3087 /* continue looking for endc */
3088 }
3089 else if (*cp == endc)
3090 cnt--;
3091 else if (*cp == startc)
3092 cnt++;
3093 if (cnt)
3094 cp++;
3095 }
3096 if (*cp == endc && eqFound) {
3097
3098 /*
3099 * Now we break this sucker into the lhs and
3100 * rhs. We must null terminate them of course.
3101 */
3102 delim='=';
3103 cp = tstr;
3104 if ((pattern.lhs = VarGetPattern(ctxt, &parsestate,
3105 errnum, &cp, delim, &pattern.flags,
3106 &pattern.leftLen, NULL)) == NULL)
3107 goto cleanup;
3108 delim = endc;
3109 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate,
3110 errnum, &cp, delim, NULL, &pattern.rightLen,
3111 &pattern)) == NULL)
3112 goto cleanup;
3113
3114 /*
3115 * SYSV modifications happen through the whole
3116 * string. Note the pattern is anchored at the end.
3117 */
3118 termc = *--cp;
3119 delim = '\0';
3120 newStr = VarModify(ctxt, &parsestate, nstr,
3121 VarSYSVMatch,
3122 &pattern);
3123 free(UNCONST(pattern.lhs));
3124 free(UNCONST(pattern.rhs));
3125 } else
3126 #endif
3127 {
3128 Error("Unknown modifier '%c'", *tstr);
3129 for (cp = tstr+1;
3130 *cp != ':' && *cp != endc && *cp != '\0';
3131 cp++)
3132 continue;
3133 termc = *cp;
3134 newStr = var_Error;
3135 }
3136 }
3137 }
3138 if (DEBUG(VAR)) {
3139 fprintf(debug_file, "Result of :%c is \"%s\"\n", modifier, newStr);
3140 }
3141
3142 if (newStr != nstr) {
3143 if (*freePtr) {
3144 free(nstr);
3145 *freePtr = NULL;
3146 }
3147 nstr = newStr;
3148 if (nstr != var_Error && nstr != varNoError) {
3149 *freePtr = nstr;
3150 }
3151 }
3152 if (termc == '\0' && endc != '\0') {
3153 Error("Unclosed variable specification for %s", v->name);
3154 } else if (termc == ':') {
3155 *WR(cp) = termc;
3156 cp++;
3157 } else {
3158 *WR(cp) = termc;
3159 }
3160 tstr = cp;
3161 }
3162 out:
3163 *lengthPtr = tstr - start;
3164 return (nstr);
3165
3166 bad_modifier:
3167 /* "{(" */
3168 Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr, ":)}"), tstr,
3169 v->name);
3170
3171 cleanup:
3172 *lengthPtr = cp - start;
3173 if (delim != '\0')
3174 Error("Unclosed substitution for %s (%c missing)",
3175 v->name, delim);
3176 if (*freePtr) {
3177 free(*freePtr);
3178 *freePtr = NULL;
3179 }
3180 return (var_Error);
3181 }
3182
3183 /*-
3184 *-----------------------------------------------------------------------
3185 * Var_Parse --
3186 * Given the start of a variable invocation, extract the variable
3187 * name and find its value, then modify it according to the
3188 * specification.
3189 *
3190 * Input:
3191 * str The string to parse
3192 * ctxt The context for the variable
3193 * errnum TRUE if undefined variables are an error
3194 * lengthPtr OUT: The length of the specification
3195 * freePtr OUT: Non-NULL if caller should free *freePtr
3196 *
3197 * Results:
3198 * The (possibly-modified) value of the variable or var_Error if the
3199 * specification is invalid. The length of the specification is
3200 * placed in *lengthPtr (for invalid specifications, this is just
3201 * 2...?).
3202 * If *freePtr is non-NULL then it's a pointer that the caller
3203 * should pass to free() to free memory used by the result.
3204 *
3205 * Side Effects:
3206 * None.
3207 *
3208 *-----------------------------------------------------------------------
3209 */
3210 /* coverity[+alloc : arg-*4] */
3211 char *
3212 Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
3213 void **freePtr)
3214 {
3215 const char *tstr; /* Pointer into str */
3216 Var *v; /* Variable in invocation */
3217 Boolean haveModifier;/* TRUE if have modifiers for the variable */
3218 char endc; /* Ending character when variable in parens
3219 * or braces */
3220 char startc=0; /* Starting character when variable in parens
3221 * or braces */
3222 int vlen; /* Length of variable name */
3223 const char *start;
3224 char *nstr;
3225 Boolean dynamic; /* TRUE if the variable is local and we're
3226 * expanding it in a non-local context. This
3227 * is done to support dynamic sources. The
3228 * result is just the invocation, unaltered */
3229 Var_Parse_State parsestate; /* Flags passed to helper functions */
3230
3231 *freePtr = NULL;
3232 dynamic = FALSE;
3233 start = str;
3234 parsestate.oneBigWord = FALSE;
3235 parsestate.varSpace = ' '; /* word separator */
3236
3237 if (str[1] != PROPEN && str[1] != BROPEN) {
3238 /*
3239 * If it's not bounded by braces of some sort, life is much simpler.
3240 * We just need to check for the first character and return the
3241 * value if it exists.
3242 */
3243 char name[2];
3244
3245 name[0] = str[1];
3246 name[1] = '\0';
3247
3248 v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
3249 if (v == (Var *)NIL) {
3250 *lengthPtr = 2;
3251
3252 if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
3253 /*
3254 * If substituting a local variable in a non-local context,
3255 * assume it's for dynamic source stuff. We have to handle
3256 * this specially and return the longhand for the variable
3257 * with the dollar sign escaped so it makes it back to the
3258 * caller. Only four of the local variables are treated
3259 * specially as they are the only four that will be set
3260 * when dynamic sources are expanded.
3261 */
3262 switch (str[1]) {
3263 case '@':
3264 return UNCONST("$(.TARGET)");
3265 case '%':
3266 return UNCONST("$(.ARCHIVE)");
3267 case '*':
3268 return UNCONST("$(.PREFIX)");
3269 case '!':
3270 return UNCONST("$(.MEMBER)");
3271 }
3272 }
3273 /*
3274 * Error
3275 */
3276 return (errnum ? var_Error : varNoError);
3277 } else {
3278 haveModifier = FALSE;
3279 tstr = &str[1];
3280 endc = str[1];
3281 }
3282 } else if (str[1] == '\0') {
3283 *lengthPtr = 1;
3284 return (errnum ? var_Error : varNoError);
3285 } else {
3286 Buffer buf; /* Holds the variable name */
3287
3288 startc = str[1];
3289 endc = startc == PROPEN ? PRCLOSE : BRCLOSE;
3290 buf = Buf_Init(0);
3291
3292 /*
3293 * Skip to the end character or a colon, whichever comes first.
3294 */
3295 for (tstr = str + 2;
3296 *tstr != '\0' && *tstr != endc && *tstr != ':';
3297 tstr++)
3298 {
3299 /*
3300 * A variable inside a variable, expand
3301 */
3302 if (*tstr == '$') {
3303 int rlen;
3304 void *freeIt;
3305 char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
3306 if (rval != NULL) {
3307 Buf_AddBytes(buf, strlen(rval), (Byte *)rval);
3308 }
3309 if (freeIt)
3310 free(freeIt);
3311 tstr += rlen - 1;
3312 }
3313 else
3314 Buf_AddByte(buf, (Byte)*tstr);
3315 }
3316 if (*tstr == ':') {
3317 haveModifier = TRUE;
3318 } else if (*tstr != '\0') {
3319 haveModifier = FALSE;
3320 } else {
3321 /*
3322 * If we never did find the end character, return NULL
3323 * right now, setting the length to be the distance to
3324 * the end of the string, since that's what make does.
3325 */
3326 *lengthPtr = tstr - str;
3327 Buf_Destroy(buf, TRUE);
3328 return (var_Error);
3329 }
3330 *WR(tstr) = '\0';
3331 Buf_AddByte(buf, (Byte)'\0');
3332 str = Buf_GetAll(buf, NULL);
3333 vlen = strlen(str);
3334
3335 v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
3336 if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
3337 (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
3338 {
3339 /*
3340 * Check for bogus D and F forms of local variables since we're
3341 * in a local context and the name is the right length.
3342 */
3343 switch(*str) {
3344 case '@':
3345 case '%':
3346 case '*':
3347 case '!':
3348 case '>':
3349 case '<':
3350 {
3351 char vname[2];
3352 char *val;
3353
3354 /*
3355 * Well, it's local -- go look for it.
3356 */
3357 vname[0] = *str;
3358 vname[1] = '\0';
3359 v = VarFind(vname, ctxt, 0);
3360
3361 if (v != (Var *)NIL) {
3362 /*
3363 * No need for nested expansion or anything, as we're
3364 * the only one who sets these things and we sure don't
3365 * but nested invocations in them...
3366 */
3367 val = (char *)Buf_GetAll(v->val, NULL);
3368
3369 if (str[1] == 'D') {
3370 val = VarModify(ctxt, &parsestate, val, VarHead,
3371 NULL);
3372 } else {
3373 val = VarModify(ctxt, &parsestate, val, VarTail,
3374 NULL);
3375 }
3376 /*
3377 * Resulting string is dynamically allocated, so
3378 * tell caller to free it.
3379 */
3380 *freePtr = val;
3381 *lengthPtr = tstr-start+1;
3382 *WR(tstr) = endc;
3383 Buf_Destroy(buf, TRUE);
3384 VarFreeEnv(v, TRUE);
3385 return(val);
3386 }
3387 break;
3388 }
3389 }
3390 }
3391
3392 if (v == (Var *)NIL) {
3393 if (((vlen == 1) ||
3394 (((vlen == 2) && (str[1] == 'F' ||
3395 str[1] == 'D')))) &&
3396 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
3397 {
3398 /*
3399 * If substituting a local variable in a non-local context,
3400 * assume it's for dynamic source stuff. We have to handle
3401 * this specially and return the longhand for the variable
3402 * with the dollar sign escaped so it makes it back to the
3403 * caller. Only four of the local variables are treated
3404 * specially as they are the only four that will be set
3405 * when dynamic sources are expanded.
3406 */
3407 switch (*str) {
3408 case '@':
3409 case '%':
3410 case '*':
3411 case '!':
3412 dynamic = TRUE;
3413 break;
3414 }
3415 } else if ((vlen > 2) && (*str == '.') &&
3416 isupper((unsigned char) str[1]) &&
3417 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
3418 {
3419 int len;
3420
3421 len = vlen - 1;
3422 if ((strncmp(str, ".TARGET", len) == 0) ||
3423 (strncmp(str, ".ARCHIVE", len) == 0) ||
3424 (strncmp(str, ".PREFIX", len) == 0) ||
3425 (strncmp(str, ".MEMBER", len) == 0))
3426 {
3427 dynamic = TRUE;
3428 }
3429 }
3430
3431 if (!haveModifier) {
3432 /*
3433 * No modifiers -- have specification length so we can return
3434 * now.
3435 */
3436 *lengthPtr = tstr - start + 1;
3437 *WR(tstr) = endc;
3438 if (dynamic) {
3439 char *pstr = estrndup(start, *lengthPtr);
3440 *freePtr = pstr;
3441 Buf_Destroy(buf, TRUE);
3442 return(pstr);
3443 } else {
3444 Buf_Destroy(buf, TRUE);
3445 return (errnum ? var_Error : varNoError);
3446 }
3447 } else {
3448 /*
3449 * Still need to get to the end of the variable specification,
3450 * so kludge up a Var structure for the modifications
3451 */
3452 v = emalloc(sizeof(Var));
3453 v->name = UNCONST(str);
3454 v->val = Buf_Init(1);
3455 v->flags = VAR_JUNK;
3456 Buf_Destroy(buf, FALSE);
3457 }
3458 } else
3459 Buf_Destroy(buf, TRUE);
3460 }
3461
3462
3463 if (v->flags & VAR_IN_USE) {
3464 Fatal("Variable %s is recursive.", v->name);
3465 /*NOTREACHED*/
3466 } else {
3467 v->flags |= VAR_IN_USE;
3468 }
3469 /*
3470 * Before doing any modification, we have to make sure the value
3471 * has been fully expanded. If it looks like recursion might be
3472 * necessary (there's a dollar sign somewhere in the variable's value)
3473 * we just call Var_Subst to do any other substitutions that are
3474 * necessary. Note that the value returned by Var_Subst will have
3475 * been dynamically-allocated, so it will need freeing when we
3476 * return.
3477 */
3478 nstr = (char *)Buf_GetAll(v->val, NULL);
3479 if (strchr(nstr, '$') != NULL) {
3480 nstr = Var_Subst(NULL, nstr, ctxt, errnum);
3481 *freePtr = nstr;
3482 }
3483
3484 v->flags &= ~VAR_IN_USE;
3485
3486 if ((nstr != NULL) && haveModifier) {
3487 int used;
3488 /*
3489 * Skip initial colon while putting it back.
3490 */
3491 *WR(tstr) = ':';
3492 tstr++;
3493
3494 nstr = ApplyModifiers(nstr, tstr, startc, endc,
3495 v, ctxt, errnum, &used, freePtr);
3496 tstr += used;
3497 } else {
3498 *WR(tstr) = endc;
3499 }
3500 if (*tstr) {
3501 *lengthPtr = tstr - start + 1;
3502 } else {
3503 *lengthPtr = tstr - start;
3504 }
3505
3506 if (v->flags & VAR_FROM_ENV) {
3507 Boolean destroy = FALSE;
3508
3509 if (nstr != (char *)Buf_GetAll(v->val, NULL)) {
3510 destroy = TRUE;
3511 } else {
3512 /*
3513 * Returning the value unmodified, so tell the caller to free
3514 * the thing.
3515 */
3516 *freePtr = nstr;
3517 }
3518 VarFreeEnv(v, destroy);
3519 } else if (v->flags & VAR_JUNK) {
3520 /*
3521 * Perform any free'ing needed and set *freePtr to NULL so the caller
3522 * doesn't try to free a static pointer.
3523 * If VAR_KEEP is also set then we want to keep str as is.
3524 */
3525 if (!(v->flags & VAR_KEEP)) {
3526 if (*freePtr) {
3527 free(nstr);
3528 *freePtr = NULL;
3529 }
3530 if (dynamic) {
3531 nstr = estrndup(start, *lengthPtr);
3532 *freePtr = nstr;
3533 } else {
3534 nstr = var_Error;
3535 }
3536 }
3537 if (nstr != (char *)Buf_GetAll(v->val, NULL))
3538 Buf_Destroy(v->val, TRUE);
3539 free(v->name);
3540 free(v);
3541 }
3542 return (nstr);
3543 }
3544
3545 /*-
3546 *-----------------------------------------------------------------------
3547 * Var_Subst --
3548 * Substitute for all variables in the given string in the given context
3549 * If undefErr is TRUE, Parse_Error will be called when an undefined
3550 * variable is encountered.
3551 *
3552 * Input:
3553 * var Named variable || NULL for all
3554 * str the string which to substitute
3555 * ctxt the context wherein to find variables
3556 * undefErr TRUE if undefineds are an error
3557 *
3558 * Results:
3559 * The resulting string.
3560 *
3561 * Side Effects:
3562 * None. The old string must be freed by the caller
3563 *-----------------------------------------------------------------------
3564 */
3565 char *
3566 Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
3567 {
3568 Buffer buf; /* Buffer for forming things */
3569 char *val; /* Value to substitute for a variable */
3570 int length; /* Length of the variable invocation */
3571 Boolean trailingBslash; /* variable ends in \ */
3572 void *freeIt = NULL; /* Set if it should be freed */
3573 static Boolean errorReported; /* Set true if an error has already
3574 * been reported to prevent a plethora
3575 * of messages when recursing */
3576
3577 buf = Buf_Init(0);
3578 errorReported = FALSE;
3579 trailingBslash = FALSE;
3580
3581 while (*str) {
3582 if (*str == '\n' && trailingBslash)
3583 Buf_AddByte(buf, ' ');
3584 if (var == NULL && (*str == '$') && (str[1] == '$')) {
3585 /*
3586 * A dollar sign may be escaped either with another dollar sign.
3587 * In such a case, we skip over the escape character and store the
3588 * dollar sign into the buffer directly.
3589 */
3590 str++;
3591 Buf_AddByte(buf, (Byte)*str);
3592 str++;
3593 } else if (*str != '$') {
3594 /*
3595 * Skip as many characters as possible -- either to the end of
3596 * the string or to the next dollar sign (variable invocation).
3597 */
3598 const char *cp;
3599
3600 for (cp = str++; *str != '$' && *str != '\0'; str++)
3601 continue;
3602 Buf_AddBytes(buf, str - cp, (const Byte *)cp);
3603 } else {
3604 if (var != NULL) {
3605 int expand;
3606 for (;;) {
3607 if (str[1] == '\0') {
3608 /* A trailing $ is kind of a special case */
3609 Buf_AddByte(buf, str[0]);
3610 str++;
3611 expand = FALSE;
3612 } else if (str[1] != PROPEN && str[1] != BROPEN) {
3613 if (str[1] != *var || strlen(var) > 1) {
3614 Buf_AddBytes(buf, 2, (const Byte *)str);
3615 str += 2;
3616 expand = FALSE;
3617 }
3618 else
3619 expand = TRUE;
3620 break;
3621 }
3622 else {
3623 const char *p;
3624
3625 /*
3626 * Scan up to the end of the variable name.
3627 */
3628 for (p = &str[2]; *p &&
3629 *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++)
3630 if (*p == '$')
3631 break;
3632 /*
3633 * A variable inside the variable. We cannot expand
3634 * the external variable yet, so we try again with
3635 * the nested one
3636 */
3637 if (*p == '$') {
3638 Buf_AddBytes(buf, p - str, (const Byte *)str);
3639 str = p;
3640 continue;
3641 }
3642
3643 if (strncmp(var, str + 2, p - str - 2) != 0 ||
3644 var[p - str - 2] != '\0') {
3645 /*
3646 * Not the variable we want to expand, scan
3647 * until the next variable
3648 */
3649 for (;*p != '$' && *p != '\0'; p++)
3650 continue;
3651 Buf_AddBytes(buf, p - str, (const Byte *)str);
3652 str = p;
3653 expand = FALSE;
3654 }
3655 else
3656 expand = TRUE;
3657 break;
3658 }
3659 }
3660 if (!expand)
3661 continue;
3662 }
3663
3664 val = Var_Parse(str, ctxt, undefErr, &length, &freeIt);
3665
3666 /*
3667 * When we come down here, val should either point to the
3668 * value of this variable, suitably modified, or be NULL.
3669 * Length should be the total length of the potential
3670 * variable invocation (from $ to end character...)
3671 */
3672 if (val == var_Error || val == varNoError) {
3673 /*
3674 * If performing old-time variable substitution, skip over
3675 * the variable and continue with the substitution. Otherwise,
3676 * store the dollar sign and advance str so we continue with
3677 * the string...
3678 */
3679 if (oldVars) {
3680 str += length;
3681 } else if (undefErr) {
3682 /*
3683 * If variable is undefined, complain and skip the
3684 * variable. The complaint will stop us from doing anything
3685 * when the file is parsed.
3686 */
3687 if (!errorReported) {
3688 Parse_Error(PARSE_FATAL,
3689 "Undefined variable \"%.*s\"",length,str);
3690 }
3691 str += length;
3692 errorReported = TRUE;
3693 } else {
3694 Buf_AddByte(buf, (Byte)*str);
3695 str += 1;
3696 }
3697 } else {
3698 /*
3699 * We've now got a variable structure to store in. But first,
3700 * advance the string pointer.
3701 */
3702 str += length;
3703
3704 /*
3705 * Copy all the characters from the variable value straight
3706 * into the new string.
3707 */
3708 length = strlen(val);
3709 Buf_AddBytes(buf, length, (Byte *)val);
3710 trailingBslash = length > 0 && val[length - 1] == '\\';
3711 }
3712 if (freeIt) {
3713 free(freeIt);
3714 freeIt = NULL;
3715 }
3716 }
3717 }
3718
3719 Buf_AddByte(buf, '\0');
3720 val = (char *)Buf_GetAll(buf, NULL);
3721 Buf_Destroy(buf, FALSE);
3722 return (val);
3723 }
3724
3725 /*-
3726 *-----------------------------------------------------------------------
3727 * Var_GetTail --
3728 * Return the tail from each of a list of words. Used to set the
3729 * System V local variables.
3730 *
3731 * Input:
3732 * file Filename to modify
3733 *
3734 * Results:
3735 * The resulting string.
3736 *
3737 * Side Effects:
3738 * None.
3739 *
3740 *-----------------------------------------------------------------------
3741 */
3742 #if 0
3743 char *
3744 Var_GetTail(char *file)
3745 {
3746 return(VarModify(file, VarTail, NULL));
3747 }
3748
3749 /*-
3750 *-----------------------------------------------------------------------
3751 * Var_GetHead --
3752 * Find the leading components of a (list of) filename(s).
3753 * XXX: VarHead does not replace foo by ., as (sun) System V make
3754 * does.
3755 *
3756 * Input:
3757 * file Filename to manipulate
3758 *
3759 * Results:
3760 * The leading components.
3761 *
3762 * Side Effects:
3763 * None.
3764 *
3765 *-----------------------------------------------------------------------
3766 */
3767 char *
3768 Var_GetHead(char *file)
3769 {
3770 return(VarModify(file, VarHead, NULL));
3771 }
3772 #endif
3773
3774 /*-
3775 *-----------------------------------------------------------------------
3776 * Var_Init --
3777 * Initialize the module
3778 *
3779 * Results:
3780 * None
3781 *
3782 * Side Effects:
3783 * The VAR_CMD and VAR_GLOBAL contexts are created
3784 *-----------------------------------------------------------------------
3785 */
3786 void
3787 Var_Init(void)
3788 {
3789 VAR_GLOBAL = Targ_NewGN("Global");
3790 VAR_CMD = Targ_NewGN("Command");
3791
3792 }
3793
3794
3795 void
3796 Var_End(void)
3797 {
3798 }
3799
3800
3801 /****************** PRINT DEBUGGING INFO *****************/
3802 static void
3803 VarPrintVar(ClientData vp)
3804 {
3805 Var *v = (Var *)vp;
3806 fprintf(debug_file, "%-16s = %s\n", v->name, (char *)Buf_GetAll(v->val, NULL));
3807 }
3808
3809 /*-
3810 *-----------------------------------------------------------------------
3811 * Var_Dump --
3812 * print all variables in a context
3813 *-----------------------------------------------------------------------
3814 */
3815 void
3816 Var_Dump(GNode *ctxt)
3817 {
3818 Hash_Search search;
3819 Hash_Entry *h;
3820
3821 for (h = Hash_EnumFirst(&ctxt->context, &search);
3822 h != NULL;
3823 h = Hash_EnumNext(&search)) {
3824 VarPrintVar(Hash_GetValue(h));
3825 }
3826 }
3827