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