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