Make the DEBUGF() macro portable by (ugh) adding a Debug() function, which
[dragonfly.git] / usr.bin / make / var.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * 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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)var.c 8.3 (Berkeley) 3/19/94
39 * $FreeBSD: src/usr.bin/make/var.c,v 1.16.2.3 2002/02/27 14:18:57 cjc Exp $
40 * $DragonFly: src/usr.bin/make/var.c,v 1.8 2004/11/12 22:42:36 dillon Exp $
41 */
42
43/*-
44 * var.c --
45 * Variable-handling functions
46 *
47 * Interface:
48 * Var_Set Set the value of a variable in the given
49 * context. The variable is created if it doesn't
50 * yet exist. The value and variable name need not
51 * be preserved.
52 *
53 * Var_Append Append more characters to an existing variable
54 * in the given context. The variable needn't
55 * exist already -- it will be created if it doesn't.
56 * A space is placed between the old value and the
57 * new one.
58 *
59 * Var_Exists See if a variable exists.
60 *
61 * Var_Value Return the value of a variable in a context or
62 * NULL if the variable is undefined.
63 *
64 * Var_Subst Substitute named variable, or all variables if
65 * NULL in a string using
66 * the given context as the top-most one. If the
67 * third argument is non-zero, Parse_Error is
68 * called if any variables are undefined.
69 *
70 * Var_Parse Parse a variable expansion from a string and
71 * return the result and the number of characters
72 * consumed.
73 *
74 * Var_Delete Delete a variable in a context.
75 *
76 * Var_Init Initialize this module.
77 *
78 * Debugging:
79 * Var_Dump Print out all variables defined in the given
80 * context.
81 *
82 * XXX: There's a lot of duplication in these functions.
83 */
84
85#include <ctype.h>
86#include <sys/types.h>
87#include <regex.h>
88#include <stdlib.h>
89#include "make.h"
90#include "buf.h"
91
92/*
93 * This is a harmless return value for Var_Parse that can be used by Var_Subst
94 * to determine if there was an error in parsing -- easier than returning
95 * a flag, as things outside this module don't give a hoot.
96 */
97char var_Error[] = "";
98
99/*
100 * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
101 * set false. Why not just use a constant? Well, gcc likes to condense
102 * identical string instances...
103 */
104static char varNoError[] = "";
105
106/*
107 * Internally, variables are contained in four different contexts.
108 * 1) the environment. They may not be changed. If an environment
109 * variable is appended-to, the result is placed in the global
110 * context.
111 * 2) the global context. Variables set in the Makefile are located in
112 * the global context. It is the penultimate context searched when
113 * substituting.
114 * 3) the command-line context. All variables set on the command line
115 * are placed in this context. They are UNALTERABLE once placed here.
116 * 4) the local context. Each target has associated with it a context
117 * list. On this list are located the structures describing such
118 * local variables as $(@) and $(*)
119 * The four contexts are searched in the reverse order from which they are
120 * listed.
121 */
122GNode *VAR_GLOBAL; /* variables from the makefile */
123GNode *VAR_CMD; /* variables defined on the command-line */
124
125static Lst allVars; /* List of all variables */
126
127#define FIND_CMD 0x1 /* look in VAR_CMD when searching */
128#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
129#define FIND_ENV 0x4 /* look in the environment also */
130
131typedef struct Var {
132 char *name; /* the variable's name */
133 Buffer val; /* its value */
134 int flags; /* miscellaneous status flags */
135#define VAR_IN_USE 1 /* Variable's value currently being used.
136 * Used to avoid recursion */
137#define VAR_FROM_ENV 2 /* Variable comes from the environment */
138#define VAR_JUNK 4 /* Variable is a junk variable that
139 * should be destroyed when done with
140 * it. Used by Var_Parse for undefined,
141 * modified variables */
142#define VAR_TO_ENV 8 /* Place variable in environment */
143} Var;
144
145/* Var*Pattern flags */
146#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
147#define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
148#define VAR_SUB_MATCHED 0x04 /* There was a match */
149#define VAR_MATCH_START 0x08 /* Match at start of word */
150#define VAR_MATCH_END 0x10 /* Match at end of word */
151#define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
152
153typedef struct {
154 char *lhs; /* String to match */
155 int leftLen; /* Length of string */
156 char *rhs; /* Replacement string (w/ &'s removed) */
157 int rightLen; /* Length of replacement */
158 int flags;
159} VarPattern;
160
161typedef struct {
162 regex_t re;
163 int nsub;
164 regmatch_t *matches;
165 char *replace;
166 int flags;
167} VarREPattern;
168
169static int VarCmp(void *, void *);
170static Var *VarFind(char *, GNode *, int);
171static void VarAdd(char *, char *, GNode *);
172static void VarDelete(void *);
173static Boolean VarHead(char *, Boolean, Buffer, void *);
174static Boolean VarTail(char *, Boolean, Buffer, void *);
175static Boolean VarSuffix(char *, Boolean, Buffer, void *);
176static Boolean VarRoot(char *, Boolean, Buffer, void *);
177static Boolean VarMatch(char *, Boolean, Buffer, void *);
178#ifdef SYSVVARSUB
179static Boolean VarSYSVMatch(char *, Boolean, Buffer, void *);
180#endif
181static Boolean VarNoMatch(char *, Boolean, Buffer, void *);
182static void VarREError(int, regex_t *, const char *);
183static Boolean VarRESubstitute(char *, Boolean, Buffer, void *);
184static Boolean VarSubstitute(char *, Boolean, Buffer, void *);
185static char *VarGetPattern(GNode *, int, char **, int, int *, int *,
186 VarPattern *);
187static char *VarQuote(char *);
188static char *VarModify(char *, Boolean (*)(char *, Boolean, Buffer, void *),
189 void *);
190static int VarPrintVar(void *, void *);
191
192/*-
193 *-----------------------------------------------------------------------
194 * VarCmp --
195 * See if the given variable matches the named one. Called from
196 * Lst_Find when searching for a variable of a given name.
197 *
198 * Results:
199 * 0 if they match. non-zero otherwise.
200 *
201 * Side Effects:
202 * none
203 *-----------------------------------------------------------------------
204 */
205static int
206VarCmp (v, name)
207 void * v; /* VAR structure to compare */
208 void * name; /* name to look for */
209{
210 return (strcmp ((char *) name, ((Var *) v)->name));
211}
212
213/*-
214 *-----------------------------------------------------------------------
215 * VarFind --
216 * Find the given variable in the given context and any other contexts
217 * indicated.
218 *
219 * Results:
220 * A pointer to the structure describing the desired variable or
221 * NULL if the variable does not exist.
222 *
223 * Side Effects:
224 * None
225 *-----------------------------------------------------------------------
226 */
227static Var *
228VarFind (name, ctxt, flags)
229 char *name; /* name to find */
230 GNode *ctxt; /* context in which to find it */
231 int flags; /* FIND_GLOBAL set means to look in the
232 * VAR_GLOBAL context as well.
233 * FIND_CMD set means to look in the VAR_CMD
234 * context also.
235 * FIND_ENV set means to look in the
236 * environment */
237{
238 Boolean localCheckEnvFirst;
239 LstNode var;
240 Var *v;
241
242 /*
243 * If the variable name begins with a '.', it could very well be one of
244 * the local ones. We check the name against all the local variables
245 * and substitute the short version in for 'name' if it matches one of
246 * them.
247 */
248 if (*name == '.' && isupper((unsigned char) name[1]))
249 switch (name[1]) {
250 case 'A':
251 if (!strcmp(name, ".ALLSRC"))
252 name = ALLSRC;
253 if (!strcmp(name, ".ARCHIVE"))
254 name = ARCHIVE;
255 break;
256 case 'I':
257 if (!strcmp(name, ".IMPSRC"))
258 name = IMPSRC;
259 break;
260 case 'M':
261 if (!strcmp(name, ".MEMBER"))
262 name = MEMBER;
263 break;
264 case 'O':
265 if (!strcmp(name, ".OODATE"))
266 name = OODATE;
267 break;
268 case 'P':
269 if (!strcmp(name, ".PREFIX"))
270 name = PREFIX;
271 break;
272 case 'T':
273 if (!strcmp(name, ".TARGET"))
274 name = TARGET;
275 break;
276 }
277
278 /*
279 * Note whether this is one of the specific variables we were told through
280 * the -E flag to use environment-variable-override for.
281 */
282 if (Lst_Find (envFirstVars, (void *)name,
283 (int (*)(void *, void *)) strcmp) != NULL)
284 {
285 localCheckEnvFirst = TRUE;
286 } else {
287 localCheckEnvFirst = FALSE;
288 }
289
290 /*
291 * First look for the variable in the given context. If it's not there,
292 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
293 * depending on the FIND_* flags in 'flags'
294 */
295 var = Lst_Find (ctxt->context, (void *)name, VarCmp);
296
297 if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
298 var = Lst_Find (VAR_CMD->context, (void *)name, VarCmp);
299 }
300 if ((var == NULL) && (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL) &&
301 !checkEnvFirst && !localCheckEnvFirst)
302 {
303 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp);
304 }
305 if ((var == NULL) && (flags & FIND_ENV)) {
306 char *env;
307
308 if ((env = getenv (name)) != NULL) {
309 int len;
310
311 v = (Var *) emalloc(sizeof(Var));
312 v->name = estrdup(name);
313
314 len = strlen(env);
315
316 v->val = Buf_Init(len);
317 Buf_AddBytes(v->val, len, (Byte *)env);
318
319 v->flags = VAR_FROM_ENV;
320 return (v);
321 } else if ((checkEnvFirst || localCheckEnvFirst) &&
322 (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL))
323 {
324 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp);
325 if (var == NULL) {
326 return ((Var *) NULL);
327 } else {
328 return ((Var *)Lst_Datum(var));
329 }
330 } else {
331 return((Var *)NULL);
332 }
333 } else if (var == NULL) {
334 return ((Var *) NULL);
335 } else {
336 return ((Var *) Lst_Datum (var));
337 }
338}
339
340/*-
341 *-----------------------------------------------------------------------
342 * VarAdd --
343 * Add a new variable of name name and value val to the given context
344 *
345 * Results:
346 * None
347 *
348 * Side Effects:
349 * The new variable is placed at the front of the given context
350 * The name and val arguments are duplicated so they may
351 * safely be freed.
352 *-----------------------------------------------------------------------
353 */
354static void
355VarAdd (name, val, ctxt)
356 char *name; /* name of variable to add */
357 char *val; /* value to set it to */
358 GNode *ctxt; /* context in which to set it */
359{
360 Var *v;
361 int len;
362
363 v = (Var *) emalloc (sizeof (Var));
364
365 v->name = estrdup (name);
366
367 len = val ? strlen(val) : 0;
368 v->val = Buf_Init(len+1);
369 Buf_AddBytes(v->val, len, (Byte *)val);
370
371 v->flags = 0;
372
373 (void) Lst_AtFront (ctxt->context, (void *)v);
374 (void) Lst_AtEnd (allVars, (void *) v);
375 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val));
376}
377
378
379/*-
380 *-----------------------------------------------------------------------
381 * VarDelete --
382 * Delete a variable and all the space associated with it.
383 *
384 * Results:
385 * None
386 *
387 * Side Effects:
388 * None
389 *-----------------------------------------------------------------------
390 */
391static void
392VarDelete(vp)
393 void * vp;
394{
395 Var *v = (Var *) vp;
396 free(v->name);
397 Buf_Destroy(v->val, TRUE);
398 free(v);
399}
400
401
402
403/*-
404 *-----------------------------------------------------------------------
405 * Var_Delete --
406 * Remove a variable from a context.
407 *
408 * Results:
409 * None.
410 *
411 * Side Effects:
412 * The Var structure is removed and freed.
413 *
414 *-----------------------------------------------------------------------
415 */
416void
417Var_Delete(name, ctxt)
418 char *name;
419 GNode *ctxt;
420{
421 LstNode ln;
422
423 DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name));
424 ln = Lst_Find(ctxt->context, (void *)name, VarCmp);
425 if (ln != NULL) {
426 Var *v;
427
428 v = (Var *)Lst_Datum(ln);
429 Lst_Remove(ctxt->context, ln);
430 ln = Lst_Member(allVars, v);
431 Lst_Remove(allVars, ln);
432 VarDelete((void *) v);
433 }
434}
435
436/*-
437 *-----------------------------------------------------------------------
438 * Var_Set --
439 * Set the variable name to the value val in the given context.
440 *
441 * Results:
442 * None.
443 *
444 * Side Effects:
445 * If the variable doesn't yet exist, a new record is created for it.
446 * Else the old value is freed and the new one stuck in its place
447 *
448 * Notes:
449 * The variable is searched for only in its context before being
450 * created in that context. I.e. if the context is VAR_GLOBAL,
451 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
452 * VAR_CMD->context is searched. This is done to avoid the literally
453 * thousands of unnecessary strcmp's that used to be done to
454 * set, say, $(@) or $(<).
455 *-----------------------------------------------------------------------
456 */
457void
458Var_Set (name, val, ctxt)
459 char *name; /* name of variable to set */
460 char *val; /* value to give to the variable */
461 GNode *ctxt; /* context in which to set it */
462{
463 Var *v;
464
465 /*
466 * We only look for a variable in the given context since anything set
467 * here will override anything in a lower context, so there's not much
468 * point in searching them all just to save a bit of memory...
469 */
470 v = VarFind (name, ctxt, 0);
471 if (v == (Var *) NULL) {
472 VarAdd (name, val, ctxt);
473 } else {
474 Buf_Discard(v->val, Buf_Size(v->val));
475 Buf_AddBytes(v->val, strlen(val), (Byte *)val);
476
477 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val));
478 }
479 /*
480 * Any variables given on the command line are automatically exported
481 * to the environment (as per POSIX standard)
482 */
483 if (ctxt == VAR_CMD || (v != (Var *)NULL && (v->flags & VAR_TO_ENV))) {
484 setenv(name, val, 1);
485 }
486}
487
488/*
489 * Var_SetEnv --
490 * Set the VAR_TO_ENV flag on a variable
491 */
492void
493Var_SetEnv (char *name, GNode *ctxt)
494{
495 register Var *v;
496
497 v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
498 if (v) {
499 if ((v->flags & VAR_TO_ENV) == 0) {
500 v->flags |= VAR_TO_ENV;
501 setenv(v->name, Buf_GetAll(v->val, NULL), 1);
502 }
503 } else {
504 Error("Cannot set environment flag on non-existant variable %s", name);
505 }
506}
507
508/*-
509 *-----------------------------------------------------------------------
510 * Var_Append --
511 * The variable of the given name has the given value appended to it in
512 * the given context.
513 *
514 * Results:
515 * None
516 *
517 * Side Effects:
518 * If the variable doesn't exist, it is created. Else the strings
519 * are concatenated (with a space in between).
520 *
521 * Notes:
522 * Only if the variable is being sought in the global context is the
523 * environment searched.
524 * XXX: Knows its calling circumstances in that if called with ctxt
525 * an actual target, it will only search that context since only
526 * a local variable could be being appended to. This is actually
527 * a big win and must be tolerated.
528 *-----------------------------------------------------------------------
529 */
530void
531Var_Append (name, val, ctxt)
532 char *name; /* Name of variable to modify */
533 char *val; /* String to append to it */
534 GNode *ctxt; /* Context in which this should occur */
535{
536 Var *v;
537
538 v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
539
540 if (v == (Var *) NULL) {
541 VarAdd (name, val, ctxt);
542 } else {
543 Buf_AddByte(v->val, (Byte)' ');
544 Buf_AddBytes(v->val, strlen(val), (Byte *)val);
545
546 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name,
547 (char *) Buf_GetAll(v->val, (int *)NULL)));
548
549 if (v->flags & VAR_FROM_ENV) {
550 /*
551 * If the original variable came from the environment, we
552 * have to install it in the global context (we could place
553 * it in the environment, but then we should provide a way to
554 * export other variables...)
555 */
556 v->flags &= ~VAR_FROM_ENV;
557 Lst_AtFront(ctxt->context, (void *)v);
558 }
559 }
560}
561
562/*-
563 *-----------------------------------------------------------------------
564 * Var_Exists --
565 * See if the given variable exists.
566 *
567 * Results:
568 * TRUE if it does, FALSE if it doesn't
569 *
570 * Side Effects:
571 * None.
572 *
573 *-----------------------------------------------------------------------
574 */
575Boolean
576Var_Exists(name, ctxt)
577 char *name; /* Variable to find */
578 GNode *ctxt; /* Context in which to start search */
579{
580 Var *v;
581
582 v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
583
584 if (v == (Var *)NULL) {
585 return(FALSE);
586 } else if (v->flags & VAR_FROM_ENV) {
587 free(v->name);
588 Buf_Destroy(v->val, TRUE);
589 free((char *)v);
590 }
591 return(TRUE);
592}
593
594/*-
595 *-----------------------------------------------------------------------
596 * Var_Value --
597 * Return the value of the named variable in the given context
598 *
599 * Results:
600 * The value if the variable exists, NULL if it doesn't
601 *
602 * Side Effects:
603 * None
604 *-----------------------------------------------------------------------
605 */
606char *
607Var_Value (name, ctxt, frp)
608 char *name; /* name to find */
609 GNode *ctxt; /* context in which to search for it */
610 char **frp;
611{
612 Var *v;
613
614 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
615 *frp = NULL;
616 if (v != (Var *) NULL) {
617 char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
618 if (v->flags & VAR_FROM_ENV) {
619 Buf_Destroy(v->val, FALSE);
620 free(v);
621 *frp = p;
622 }
623 return p;
624 } else {
625 return ((char *) NULL);
626 }
627}
628
629/*-
630 *-----------------------------------------------------------------------
631 * VarHead --
632 * Remove the tail of the given word and place the result in the given
633 * buffer.
634 *
635 * Results:
636 * TRUE if characters were added to the buffer (a space needs to be
637 * added to the buffer before the next word).
638 *
639 * Side Effects:
640 * The trimmed word is added to the buffer.
641 *
642 *-----------------------------------------------------------------------
643 */
644static Boolean
645VarHead (word, addSpace, buf, dummy)
646 char *word; /* Word to trim */
647 Boolean addSpace; /* True if need to add a space to the buffer
648 * before sticking in the head */
649 Buffer buf; /* Buffer in which to store it */
650 void * dummy;
651{
652 char *slash;
653
654 slash = strrchr (word, '/');
655 if (slash != (char *)NULL) {
656 if (addSpace) {
657 Buf_AddByte (buf, (Byte)' ');
658 }
659 *slash = '\0';
660 Buf_AddBytes (buf, strlen (word), (Byte *)word);
661 *slash = '/';
662 return (TRUE);
663 } else {
664 /*
665 * If no directory part, give . (q.v. the POSIX standard)
666 */
667 if (addSpace) {
668 Buf_AddBytes(buf, 2, (Byte *)" .");
669 } else {
670 Buf_AddByte(buf, (Byte)'.');
671 }
672 }
673 return(dummy ? TRUE : TRUE);
674}
675
676/*-
677 *-----------------------------------------------------------------------
678 * VarTail --
679 * Remove the head of the given word and place the result in the given
680 * buffer.
681 *
682 * Results:
683 * TRUE if characters were added to the buffer (a space needs to be
684 * added to the buffer before the next word).
685 *
686 * Side Effects:
687 * The trimmed word is added to the buffer.
688 *
689 *-----------------------------------------------------------------------
690 */
691static Boolean
692VarTail (word, addSpace, buf, dummy)
693 char *word; /* Word to trim */
694 Boolean addSpace; /* TRUE if need to stick a space in the
695 * buffer before adding the tail */
696 Buffer buf; /* Buffer in which to store it */
697 void * dummy;
698{
699 char *slash;
700
701 if (addSpace) {
702 Buf_AddByte (buf, (Byte)' ');
703 }
704
705 slash = strrchr (word, '/');
706 if (slash != (char *)NULL) {
707 *slash++ = '\0';
708 Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
709 slash[-1] = '/';
710 } else {
711 Buf_AddBytes (buf, strlen(word), (Byte *)word);
712 }
713 return (dummy ? TRUE : TRUE);
714}
715
716/*-
717 *-----------------------------------------------------------------------
718 * VarSuffix --
719 * Place the suffix of the given word in the given buffer.
720 *
721 * Results:
722 * TRUE if characters were added to the buffer (a space needs to be
723 * added to the buffer before the next word).
724 *
725 * Side Effects:
726 * The suffix from the word is placed in the buffer.
727 *
728 *-----------------------------------------------------------------------
729 */
730static Boolean
731VarSuffix (word, addSpace, buf, dummy)
732 char *word; /* Word to trim */
733 Boolean addSpace; /* TRUE if need to add a space before placing
734 * the suffix in the buffer */
735 Buffer buf; /* Buffer in which to store it */
736 void * dummy;
737{
738 char *dot;
739
740 dot = strrchr (word, '.');
741 if (dot != (char *)NULL) {
742 if (addSpace) {
743 Buf_AddByte (buf, (Byte)' ');
744 }
745 *dot++ = '\0';
746 Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
747 dot[-1] = '.';
748 addSpace = TRUE;
749 }
750 return (dummy ? addSpace : addSpace);
751}
752
753/*-
754 *-----------------------------------------------------------------------
755 * VarRoot --
756 * Remove the suffix of the given word and place the result in the
757 * buffer.
758 *
759 * Results:
760 * TRUE if characters were added to the buffer (a space needs to be
761 * added to the buffer before the next word).
762 *
763 * Side Effects:
764 * The trimmed word is added to the buffer.
765 *
766 *-----------------------------------------------------------------------
767 */
768static Boolean
769VarRoot (word, addSpace, buf, dummy)
770 char *word; /* Word to trim */
771 Boolean addSpace; /* TRUE if need to add a space to the buffer
772 * before placing the root in it */
773 Buffer buf; /* Buffer in which to store it */
774 void * dummy;
775{
776 char *dot;
777
778 if (addSpace) {
779 Buf_AddByte (buf, (Byte)' ');
780 }
781
782 dot = strrchr (word, '.');
783 if (dot != (char *)NULL) {
784 *dot = '\0';
785 Buf_AddBytes (buf, strlen (word), (Byte *)word);
786 *dot = '.';
787 } else {
788 Buf_AddBytes (buf, strlen(word), (Byte *)word);
789 }
790 return (dummy ? TRUE : TRUE);
791}
792
793/*-
794 *-----------------------------------------------------------------------
795 * VarMatch --
796 * Place the word in the buffer if it matches the given pattern.
797 * Callback function for VarModify to implement the :M modifier.
798 *
799 * Results:
800 * TRUE if a space should be placed in the buffer before the next
801 * word.
802 *
803 * Side Effects:
804 * The word may be copied to the buffer.
805 *
806 *-----------------------------------------------------------------------
807 */
808static Boolean
809VarMatch (word, addSpace, buf, pattern)
810 char *word; /* Word to examine */
811 Boolean addSpace; /* TRUE if need to add a space to the
812 * buffer before adding the word, if it
813 * matches */
814 Buffer buf; /* Buffer in which to store it */
815 void * pattern; /* Pattern the word must match */
816{
817 if (Str_Match(word, (char *) pattern)) {
818 if (addSpace) {
819 Buf_AddByte(buf, (Byte)' ');
820 }
821 addSpace = TRUE;
822 Buf_AddBytes(buf, strlen(word), (Byte *)word);
823 }
824 return(addSpace);
825}
826
827#ifdef SYSVVARSUB
828/*-
829 *-----------------------------------------------------------------------
830 * VarSYSVMatch --
831 * Place the word in the buffer if it matches the given pattern.
832 * Callback function for VarModify to implement the System V %
833 * modifiers.
834 *
835 * Results:
836 * TRUE if a space should be placed in the buffer before the next
837 * word.
838 *
839 * Side Effects:
840 * The word may be copied to the buffer.
841 *
842 *-----------------------------------------------------------------------
843 */
844static Boolean
845VarSYSVMatch (word, addSpace, buf, patp)
846 char *word; /* Word to examine */
847 Boolean addSpace; /* TRUE if need to add a space to the
848 * buffer before adding the word, if it
849 * matches */
850 Buffer buf; /* Buffer in which to store it */
851 void * patp; /* Pattern the word must match */
852{
853 int len;
854 char *ptr;
855 VarPattern *pat = (VarPattern *) patp;
856
857 if (addSpace)
858 Buf_AddByte(buf, (Byte)' ');
859
860 addSpace = TRUE;
861
862 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL)
863 Str_SYSVSubst(buf, pat->rhs, ptr, len);
864 else
865 Buf_AddBytes(buf, strlen(word), (Byte *) word);
866
867 return(addSpace);
868}
869#endif
870
871
872/*-
873 *-----------------------------------------------------------------------
874 * VarNoMatch --
875 * Place the word in the buffer if it doesn't match the given pattern.
876 * Callback function for VarModify to implement the :N modifier.
877 *
878 * Results:
879 * TRUE if a space should be placed in the buffer before the next
880 * word.
881 *
882 * Side Effects:
883 * The word may be copied to the buffer.
884 *
885 *-----------------------------------------------------------------------
886 */
887static Boolean
888VarNoMatch (word, addSpace, buf, pattern)
889 char *word; /* Word to examine */
890 Boolean addSpace; /* TRUE if need to add a space to the
891 * buffer before adding the word, if it
892 * matches */
893 Buffer buf; /* Buffer in which to store it */
894 void * pattern; /* Pattern the word must match */
895{
896 if (!Str_Match(word, (char *) pattern)) {
897 if (addSpace) {
898 Buf_AddByte(buf, (Byte)' ');
899 }
900 addSpace = TRUE;
901 Buf_AddBytes(buf, strlen(word), (Byte *)word);
902 }
903 return(addSpace);
904}
905
906
907/*-
908 *-----------------------------------------------------------------------
909 * VarSubstitute --
910 * Perform a string-substitution on the given word, placing the
911 * result in the passed buffer.
912 *
913 * Results:
914 * TRUE if a space is needed before more characters are added.
915 *
916 * Side Effects:
917 * None.
918 *
919 *-----------------------------------------------------------------------
920 */
921static Boolean
922VarSubstitute (word, addSpace, buf, patternp)
923 char *word; /* Word to modify */
924 Boolean addSpace; /* True if space should be added before
925 * other characters */
926 Buffer buf; /* Buffer for result */
927 void * patternp; /* Pattern for substitution */
928{
929 int wordLen; /* Length of word */
930 char *cp; /* General pointer */
931 VarPattern *pattern = (VarPattern *) patternp;
932
933 wordLen = strlen(word);
934 if (1) { /* substitute in each word of the variable */
935 /*
936 * Break substitution down into simple anchored cases
937 * and if none of them fits, perform the general substitution case.
938 */
939 if ((pattern->flags & VAR_MATCH_START) &&
940 (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
941 /*
942 * Anchored at start and beginning of word matches pattern
943 */
944 if ((pattern->flags & VAR_MATCH_END) &&
945 (wordLen == pattern->leftLen)) {
946 /*
947 * Also anchored at end and matches to the end (word
948 * is same length as pattern) add space and rhs only
949 * if rhs is non-null.
950 */
951 if (pattern->rightLen != 0) {
952 if (addSpace) {
953 Buf_AddByte(buf, (Byte)' ');
954 }
955 addSpace = TRUE;
956 Buf_AddBytes(buf, pattern->rightLen,
957 (Byte *)pattern->rhs);
958 }
959 } else if (pattern->flags & VAR_MATCH_END) {
960 /*
961 * Doesn't match to end -- copy word wholesale
962 */
963 goto nosub;
964 } else {
965 /*
966 * Matches at start but need to copy in trailing characters
967 */
968 if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
969 if (addSpace) {
970 Buf_AddByte(buf, (Byte)' ');
971 }
972 addSpace = TRUE;
973 }
974 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
975 Buf_AddBytes(buf, wordLen - pattern->leftLen,
976 (Byte *)(word + pattern->leftLen));
977 }
978 } else if (pattern->flags & VAR_MATCH_START) {
979 /*
980 * Had to match at start of word and didn't -- copy whole word.
981 */
982 goto nosub;
983 } else if (pattern->flags & VAR_MATCH_END) {
984 /*
985 * Anchored at end, Find only place match could occur (leftLen
986 * characters from the end of the word) and see if it does. Note
987 * that because the $ will be left at the end of the lhs, we have
988 * to use strncmp.
989 */
990 cp = word + (wordLen - pattern->leftLen);
991 if ((cp >= word) &&
992 (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
993 /*
994 * Match found. If we will place characters in the buffer,
995 * add a space before hand as indicated by addSpace, then
996 * stuff in the initial, unmatched part of the word followed
997 * by the right-hand-side.
998 */
999 if (((cp - word) + pattern->rightLen) != 0) {
1000 if (addSpace) {
1001 Buf_AddByte(buf, (Byte)' ');
1002 }
1003 addSpace = TRUE;
1004 }
1005 Buf_AddBytes(buf, cp - word, (Byte *)word);
1006 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
1007 } else {
1008 /*
1009 * Had to match at end and didn't. Copy entire word.
1010 */
1011 goto nosub;
1012 }
1013 } else {
1014 /*
1015 * Pattern is unanchored: search for the pattern in the word using
1016 * String_FindSubstring, copying unmatched portions and the
1017 * right-hand-side for each match found, handling non-global
1018 * substitutions correctly, etc. When the loop is done, any
1019 * remaining part of the word (word and wordLen are adjusted
1020 * accordingly through the loop) is copied straight into the
1021 * buffer.
1022 * addSpace is set FALSE as soon as a space is added to the
1023 * buffer.
1024 */
1025 Boolean done;
1026 int origSize;
1027
1028 done = FALSE;
1029 origSize = Buf_Size(buf);
1030 while (!done) {
1031 cp = Str_FindSubstring(word, pattern->lhs);
1032 if (cp != (char *)NULL) {
1033 if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
1034 Buf_AddByte(buf, (Byte)' ');
1035 addSpace = FALSE;
1036 }
1037 Buf_AddBytes(buf, cp-word, (Byte *)word);
1038 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
1039 wordLen -= (cp - word) + pattern->leftLen;
1040 word = cp + pattern->leftLen;
1041 if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){
1042 done = TRUE;
1043 }
1044 } else {
1045 done = TRUE;
1046 }
1047 }
1048 if (wordLen != 0) {
1049 if (addSpace) {
1050 Buf_AddByte(buf, (Byte)' ');
1051 }
1052 Buf_AddBytes(buf, wordLen, (Byte *)word);
1053 }
1054 /*
1055 * If added characters to the buffer, need to add a space
1056 * before we add any more. If we didn't add any, just return
1057 * the previous value of addSpace.
1058 */
1059 return ((Buf_Size(buf) != origSize) || addSpace);
1060 }
1061 /*
1062 * Common code for anchored substitutions:
1063 * addSpace was set TRUE if characters were added to the buffer.
1064 */
1065 return (addSpace);
1066 }
1067 nosub:
1068 if (addSpace) {
1069 Buf_AddByte(buf, (Byte)' ');
1070 }
1071 Buf_AddBytes(buf, wordLen, (Byte *)word);
1072 return(TRUE);
1073}
1074
1075/*-
1076 *-----------------------------------------------------------------------
1077 * VarREError --
1078 * Print the error caused by a regcomp or regexec call.
1079 *
1080 * Results:
1081 * None.
1082 *
1083 * Side Effects:
1084 * An error gets printed.
1085 *
1086 *-----------------------------------------------------------------------
1087 */
1088static void
1089VarREError(err, pat, str)
1090 int err;
1091 regex_t *pat;
1092 const char *str;
1093{
1094 char *errbuf;
1095 int errlen;
1096
1097 errlen = regerror(err, pat, 0, 0);
1098 errbuf = emalloc(errlen);
1099 regerror(err, pat, errbuf, errlen);
1100 Error("%s: %s", str, errbuf);
1101 free(errbuf);
1102}
1103
1104
1105/*-
1106 *-----------------------------------------------------------------------
1107 * VarRESubstitute --
1108 * Perform a regex substitution on the given word, placing the
1109 * result in the passed buffer.
1110 *
1111 * Results:
1112 * TRUE if a space is needed before more characters are added.
1113 *
1114 * Side Effects:
1115 * None.
1116 *
1117 *-----------------------------------------------------------------------
1118 */
1119static Boolean
1120VarRESubstitute(word, addSpace, buf, patternp)
1121 char *word;
1122 Boolean addSpace;
1123 Buffer buf;
1124 void * patternp;
1125{
1126 VarREPattern *pat;
1127 int xrv;
1128 char *wp;
1129 char *rp;
1130 int added;
1131 int flags = 0;
1132
1133#define MAYBE_ADD_SPACE() \
1134 if (addSpace && !added) \
1135 Buf_AddByte(buf, ' '); \
1136 added = 1
1137
1138 added = 0;
1139 wp = word;
1140 pat = patternp;
1141
1142 if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
1143 (VAR_SUB_ONE|VAR_SUB_MATCHED))
1144 xrv = REG_NOMATCH;
1145 else {
1146 tryagain:
1147 xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
1148 }
1149
1150 switch (xrv) {
1151 case 0:
1152 pat->flags |= VAR_SUB_MATCHED;
1153 if (pat->matches[0].rm_so > 0) {
1154 MAYBE_ADD_SPACE();
1155 Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
1156 }
1157
1158 for (rp = pat->replace; *rp; rp++) {
1159 if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
1160 MAYBE_ADD_SPACE();
1161 Buf_AddByte(buf,rp[1]);
1162 rp++;
1163 }
1164 else if ((*rp == '&') ||
1165 ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
1166 int n;
1167 char *subbuf;
1168 int sublen;
1169 char errstr[3];
1170
1171 if (*rp == '&') {
1172 n = 0;
1173 errstr[0] = '&';
1174 errstr[1] = '\0';
1175 } else {
1176 n = rp[1] - '0';
1177 errstr[0] = '\\';
1178 errstr[1] = rp[1];
1179 errstr[2] = '\0';
1180 rp++;
1181 }
1182
1183 if (n > pat->nsub) {
1184 Error("No subexpression %s", &errstr[0]);
1185 subbuf = "";
1186 sublen = 0;
1187 } else if ((pat->matches[n].rm_so == -1) &&
1188 (pat->matches[n].rm_eo == -1)) {
1189 Error("No match for subexpression %s", &errstr[0]);
1190 subbuf = "";
1191 sublen = 0;
1192 } else {
1193 subbuf = wp + pat->matches[n].rm_so;
1194 sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
1195 }
1196
1197 if (sublen > 0) {
1198 MAYBE_ADD_SPACE();
1199 Buf_AddBytes(buf, sublen, subbuf);
1200 }
1201 } else {
1202 MAYBE_ADD_SPACE();
1203 Buf_AddByte(buf, *rp);
1204 }
1205 }
1206 wp += pat->matches[0].rm_eo;
1207 if (pat->flags & VAR_SUB_GLOBAL) {
1208 flags |= REG_NOTBOL;
1209 if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
1210 MAYBE_ADD_SPACE();
1211 Buf_AddByte(buf, *wp);
1212 wp++;
1213
1214 }
1215 if (*wp)
1216 goto tryagain;
1217 }
1218 if (*wp) {
1219 MAYBE_ADD_SPACE();
1220 Buf_AddBytes(buf, strlen(wp), wp);
1221 }
1222 break;
1223 default:
1224 VarREError(xrv, &pat->re, "Unexpected regex error");
1225 /* fall through */
1226 case REG_NOMATCH:
1227 if (*wp) {
1228 MAYBE_ADD_SPACE();
1229 Buf_AddBytes(buf,strlen(wp),wp);
1230 }
1231 break;
1232 }
1233 return(addSpace||added);
1234}
1235
1236
1237/*-
1238 *-----------------------------------------------------------------------
1239 * VarModify --
1240 * Modify each of the words of the passed string using the given
1241 * function. Used to implement all modifiers.
1242 *
1243 * Results:
1244 * A string of all the words modified appropriately.
1245 *
1246 * Side Effects:
1247 * None.
1248 *
1249 *-----------------------------------------------------------------------
1250 */
1251static char *
1252VarModify (str, modProc, datum)
1253 char *str; /* String whose words should be trimmed */
1254 /* Function to use to modify them */
1255 Boolean (*modProc)(char *, Boolean, Buffer, void *);
1256 void * datum; /* Datum to pass it */
1257{
1258 Buffer buf; /* Buffer for the new string */
1259 Boolean addSpace; /* TRUE if need to add a space to the
1260 * buffer before adding the trimmed
1261 * word */
1262 char **av; /* word list [first word does not count] */
1263 int ac, i;
1264
1265 buf = Buf_Init (0);
1266 addSpace = FALSE;
1267
1268 av = brk_string(str, &ac, FALSE);
1269
1270 for (i = 1; i < ac; i++)
1271 addSpace = (*modProc)(av[i], addSpace, buf, datum);
1272
1273 Buf_AddByte (buf, '\0');
1274 str = (char *)Buf_GetAll (buf, (int *)NULL);
1275 Buf_Destroy (buf, FALSE);
1276 return (str);
1277}
1278
1279/*-
1280 *-----------------------------------------------------------------------
1281 * VarGetPattern --
1282 * Pass through the tstr looking for 1) escaped delimiters,
1283 * '$'s and backslashes (place the escaped character in
1284 * uninterpreted) and 2) unescaped $'s that aren't before
1285 * the delimiter (expand the variable substitution unless flags
1286 * has VAR_NOSUBST set).
1287 * Return the expanded string or NULL if the delimiter was missing
1288 * If pattern is specified, handle escaped ampersands, and replace
1289 * unescaped ampersands with the lhs of the pattern.
1290 *
1291 * Results:
1292 * A string of all the words modified appropriately.
1293 * If length is specified, return the string length of the buffer
1294 * If flags is specified and the last character of the pattern is a
1295 * $ set the VAR_MATCH_END bit of flags.
1296 *
1297 * Side Effects:
1298 * None.
1299 *-----------------------------------------------------------------------
1300 */
1301static char *
1302VarGetPattern(ctxt, err, tstr, delim, flags, length, pattern)
1303 GNode *ctxt;
1304 int err;
1305 char **tstr;
1306 int delim;
1307 int *flags;
1308 int *length;
1309 VarPattern *pattern;
1310{
1311 char *cp;
1312 Buffer buf = Buf_Init(0);
1313 int junk;
1314 if (length == NULL)
1315 length = &junk;
1316
1317#define IS_A_MATCH(cp, delim) \
1318 ((cp[0] == '\\') && ((cp[1] == delim) || \
1319 (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&'))))
1320
1321 /*
1322 * Skim through until the matching delimiter is found;
1323 * pick up variable substitutions on the way. Also allow
1324 * backslashes to quote the delimiter, $, and \, but don't
1325 * touch other backslashes.
1326 */
1327 for (cp = *tstr; *cp && (*cp != delim); cp++) {
1328 if (IS_A_MATCH(cp, delim)) {
1329 Buf_AddByte(buf, (Byte) cp[1]);
1330 cp++;
1331 } else if (*cp == '$') {
1332 if (cp[1] == delim) {
1333 if (flags == NULL)
1334 Buf_AddByte(buf, (Byte) *cp);
1335 else
1336 /*
1337 * Unescaped $ at end of pattern => anchor
1338 * pattern at end.
1339 */
1340 *flags |= VAR_MATCH_END;
1341 } else {
1342 if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
1343 char *cp2;
1344 int len;
1345 Boolean freeIt;
1346
1347 /*
1348 * If unescaped dollar sign not before the
1349 * delimiter, assume it's a variable
1350 * substitution and recurse.
1351 */
1352 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1353 Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
1354 if (freeIt)
1355 free(cp2);
1356 cp += len - 1;
1357 } else {
1358 char *cp2 = &cp[1];
1359
1360 if (*cp2 == '(' || *cp2 == '{') {
1361 /*
1362 * Find the end of this variable reference
1363 * and suck it in without further ado.
1364 * It will be interperated later.
1365 */
1366 int have = *cp2;
1367 int want = (*cp2 == '(') ? ')' : '}';
1368 int depth = 1;
1369
1370 for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
1371 if (cp2[-1] != '\\') {
1372 if (*cp2 == have)
1373 ++depth;
1374 if (*cp2 == want)
1375 --depth;
1376 }
1377 }
1378 Buf_AddBytes(buf, cp2 - cp, (Byte *)cp);
1379 cp = --cp2;
1380 } else
1381 Buf_AddByte(buf, (Byte) *cp);
1382 }
1383 }
1384 }
1385 else if (pattern && *cp == '&')
1386 Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs);
1387 else
1388 Buf_AddByte(buf, (Byte) *cp);
1389 }
1390
1391 Buf_AddByte(buf, (Byte) '\0');
1392
1393 if (*cp != delim) {
1394 *tstr = cp;
1395 *length = 0;
1396 return NULL;
1397 }
1398 else {
1399 *tstr = ++cp;
1400 cp = (char *) Buf_GetAll(buf, length);
1401 *length -= 1; /* Don't count the NULL */
1402 Buf_Destroy(buf, FALSE);
1403 return cp;
1404 }
1405}
1406
1407
1408/*-
1409 *-----------------------------------------------------------------------
1410 * VarQuote --
1411 * Quote shell meta-characters in the string
1412 *
1413 * Results:
1414 * The quoted string
1415 *
1416 * Side Effects:
1417 * None.
1418 *
1419 *-----------------------------------------------------------------------
1420 */
1421static char *
1422VarQuote(str)
1423 char *str;
1424{
1425
1426 Buffer buf;
1427 /* This should cover most shells :-( */
1428 static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
1429
1430 buf = Buf_Init (MAKE_BSIZE);
1431 for (; *str; str++) {
1432 if (strchr(meta, *str) != NULL)
1433 Buf_AddByte(buf, (Byte)'\\');
1434 Buf_AddByte(buf, (Byte)*str);
1435 }
1436 Buf_AddByte(buf, (Byte) '\0');
1437 str = (char *)Buf_GetAll (buf, (int *)NULL);
1438 Buf_Destroy (buf, FALSE);
1439 return str;
1440}
1441
1442/*-
1443 *-----------------------------------------------------------------------
1444 * Var_Parse --
1445 * Given the start of a variable invocation, extract the variable
1446 * name and find its value, then modify it according to the
1447 * specification.
1448 *
1449 * Results:
1450 * The (possibly-modified) value of the variable or var_Error if the
1451 * specification is invalid. The length of the specification is
1452 * placed in *lengthPtr (for invalid specifications, this is just
1453 * 2...?).
1454 * A Boolean in *freePtr telling whether the returned string should
1455 * be freed by the caller.
1456 *
1457 * Side Effects:
1458 * None.
1459 *
1460 *-----------------------------------------------------------------------
1461 */
1462char *
1463Var_Parse (str, ctxt, err, lengthPtr, freePtr)
1464 char *str; /* The string to parse */
1465 GNode *ctxt; /* The context for the variable */
1466 Boolean err; /* TRUE if undefined variables are an error */
1467 int *lengthPtr; /* OUT: The length of the specification */
1468 Boolean *freePtr; /* OUT: TRUE if caller should free result */
1469{
1470 char *tstr; /* Pointer into str */
1471 Var *v; /* Variable in invocation */
1472 char *cp; /* Secondary pointer into str (place marker
1473 * for tstr) */
1474 Boolean haveModifier;/* TRUE if have modifiers for the variable */
1475 char endc; /* Ending character when variable in parens
1476 * or braces */
1477 char startc=0; /* Starting character when variable in parens
1478 * or braces */
1479 int cnt; /* Used to count brace pairs when variable in
1480 * in parens or braces */
1481 char *start;
1482 char delim;
1483 Boolean dynamic; /* TRUE if the variable is local and we're
1484 * expanding it in a non-local context. This
1485 * is done to support dynamic sources. The
1486 * result is just the invocation, unaltered */
1487 int vlen; /* length of variable name, after embedded variable
1488 * expansion */
1489
1490 *freePtr = FALSE;
1491 dynamic = FALSE;
1492 start = str;
1493
1494 if (str[1] != '(' && str[1] != '{') {
1495 /*
1496 * If it's not bounded by braces of some sort, life is much simpler.
1497 * We just need to check for the first character and return the
1498 * value if it exists.
1499 */
1500 char name[2];
1501
1502 name[0] = str[1];
1503 name[1] = '\0';
1504
1505 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1506 if (v == (Var *)NULL) {
1507 *lengthPtr = 2;
1508
1509 if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
1510 /*
1511 * If substituting a local variable in a non-local context,
1512 * assume it's for dynamic source stuff. We have to handle
1513 * this specially and return the longhand for the variable
1514 * with the dollar sign escaped so it makes it back to the
1515 * caller. Only four of the local variables are treated
1516 * specially as they are the only four that will be set
1517 * when dynamic sources are expanded.
1518 */
1519 /* XXX: It looks like $% and $! are reversed here */
1520 switch (str[1]) {
1521 case '@':
1522 return("$(.TARGET)");
1523 case '%':
1524 return("$(.ARCHIVE)");
1525 case '*':
1526 return("$(.PREFIX)");
1527 case '!':
1528 return("$(.MEMBER)");
1529 }
1530 }
1531 /*
1532 * Error
1533 */
1534 return (err ? var_Error : varNoError);
1535 } else {
1536 haveModifier = FALSE;
1537 tstr = &str[1];
1538 endc = str[1];
1539 }
1540 } else {
1541 /* build up expanded variable name in this buffer */
1542 Buffer buf = Buf_Init(MAKE_BSIZE);
1543
1544 startc = str[1];
1545 endc = startc == '(' ? ')' : '}';
1546
1547 /*
1548 * Skip to the end character or a colon, whichever comes first,
1549 * replacing embedded variables as we go.
1550 */
1551 for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++)
1552 if (*tstr == '$') {
1553 int rlen;
1554 Boolean rfree;
1555 char* rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
1556
1557 if (rval == var_Error) {
1558 Fatal("Error expanding embedded variable.");
1559 } else if (rval != NULL) {
1560 Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
1561 if (rfree)
1562 free(rval);
1563 }
1564 tstr += rlen - 1;
1565 } else
1566 Buf_AddByte(buf, (Byte) *tstr);
1567
1568 if (*tstr == '\0') {
1569 /*
1570 * If we never did find the end character, return NULL
1571 * right now, setting the length to be the distance to
1572 * the end of the string, since that's what make does.
1573 */
1574 *lengthPtr = tstr - str;
1575 return (var_Error);
1576 }
1577
1578 haveModifier = (*tstr == ':');
1579 *tstr = '\0';
1580
1581 Buf_AddByte(buf, (Byte) '\0');
1582 str = Buf_GetAll(buf, NULL);
1583 vlen = strlen(str);
1584
1585 v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1586 if ((v == (Var *)NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
1587 (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
1588 {
1589 /*
1590 * Check for bogus D and F forms of local variables since we're
1591 * in a local context and the name is the right length.
1592 */
1593 switch(str[0]) {
1594 case '@':
1595 case '%':
1596 case '*':
1597 case '!':
1598 case '>':
1599 case '<':
1600 {
1601 char vname[2];
1602 char *val;
1603
1604 /*
1605 * Well, it's local -- go look for it.
1606 */
1607 vname[0] = str[0];
1608 vname[1] = '\0';
1609 v = VarFind(vname, ctxt, 0);
1610
1611 if (v != (Var *)NULL && !haveModifier) {
1612 /*
1613 * No need for nested expansion or anything, as we're
1614 * the only one who sets these things and we sure don't
1615 * put nested invocations in them...
1616 */
1617 val = (char *)Buf_GetAll(v->val, (int *)NULL);
1618
1619 if (str[1] == 'D') {
1620 val = VarModify(val, VarHead, (void *)0);
1621 } else {
1622 val = VarModify(val, VarTail, (void *)0);
1623 }
1624 /*
1625 * Resulting string is dynamically allocated, so
1626 * tell caller to free it.
1627 */
1628 *freePtr = TRUE;
1629 *lengthPtr = tstr-start+1;
1630 *tstr = endc;
1631 Buf_Destroy(buf, TRUE);
1632 return(val);
1633 }
1634 break;
1635 }
1636 }
1637 }
1638
1639 if (v == (Var *)NULL) {
1640 if (((vlen == 1) ||
1641 (((vlen == 2) && (str[1] == 'F' ||
1642 str[1] == 'D')))) &&
1643 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
1644 {
1645 /*
1646 * If substituting a local variable in a non-local context,
1647 * assume it's for dynamic source stuff. We have to handle
1648 * this specially and return the longhand for the variable
1649 * with the dollar sign escaped so it makes it back to the
1650 * caller. Only four of the local variables are treated
1651 * specially as they are the only four that will be set
1652 * when dynamic sources are expanded.
1653 */
1654 switch (str[0]) {
1655 case '@':
1656 case '%':
1657 case '*':
1658 case '!':
1659 dynamic = TRUE;
1660 break;
1661 }
1662 } else if ((vlen > 2) && (str[0] == '.') &&
1663 isupper((unsigned char) str[1]) &&
1664 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
1665 {
1666 int len;
1667
1668 len = vlen - 1;
1669 if ((strncmp(str, ".TARGET", len) == 0) ||
1670 (strncmp(str, ".ARCHIVE", len) == 0) ||
1671 (strncmp(str, ".PREFIX", len) == 0) ||
1672 (strncmp(str, ".MEMBER", len) == 0))
1673 {
1674 dynamic = TRUE;
1675 }
1676 }
1677
1678 if (!haveModifier) {
1679 /*
1680 * No modifiers -- have specification length so we can return
1681 * now.
1682 */
1683 *lengthPtr = tstr - start + 1;
1684 *tstr = endc;
1685 if (dynamic) {
1686 str = emalloc(*lengthPtr + 1);
1687 strncpy(str, start, *lengthPtr);
1688 str[*lengthPtr] = '\0';
1689 *freePtr = TRUE;
1690 Buf_Destroy(buf, TRUE);
1691 return(str);
1692 } else {
1693 Buf_Destroy(buf, TRUE);
1694 return (err ? var_Error : varNoError);
1695 }
1696 } else {
1697 /*
1698 * Still need to get to the end of the variable specification,
1699 * so kludge up a Var structure for the modifications
1700 */
1701 v = (Var *) emalloc(sizeof(Var));
1702 v->name = &str[1];
1703 v->val = Buf_Init(1);
1704 v->flags = VAR_JUNK;
1705 }
1706 }
1707 Buf_Destroy(buf, TRUE);
1708 }
1709
1710 if (v->flags & VAR_IN_USE) {
1711 Fatal("Variable %s is recursive.", v->name);
1712 /*NOTREACHED*/
1713 } else {
1714 v->flags |= VAR_IN_USE;
1715 }
1716 /*
1717 * Before doing any modification, we have to make sure the value
1718 * has been fully expanded. If it looks like recursion might be
1719 * necessary (there's a dollar sign somewhere in the variable's value)
1720 * we just call Var_Subst to do any other substitutions that are
1721 * necessary. Note that the value returned by Var_Subst will have
1722 * been dynamically-allocated, so it will need freeing when we
1723 * return.
1724 */
1725 str = (char *)Buf_GetAll(v->val, (int *)NULL);
1726 if (strchr (str, '$') != (char *)NULL) {
1727 str = Var_Subst(NULL, str, ctxt, err);
1728 *freePtr = TRUE;
1729 }
1730
1731 v->flags &= ~VAR_IN_USE;
1732
1733 /*
1734 * Now we need to apply any modifiers the user wants applied.
1735 * These are:
1736 * :M<pattern> words which match the given <pattern>.
1737 * <pattern> is of the standard file
1738 * wildcarding form.
1739 * :S<d><pat1><d><pat2><d>[g]
1740 * Substitute <pat2> for <pat1> in the value
1741 * :C<d><pat1><d><pat2><d>[g]
1742 * Substitute <pat2> for regex <pat1> in the value
1743 * :H Substitute the head of each word
1744 * :T Substitute the tail of each word
1745 * :E Substitute the extension (minus '.') of
1746 * each word
1747 * :R Substitute the root of each word
1748 * (pathname minus the suffix).
1749 * :lhs=rhs Like :S, but the rhs goes to the end of
1750 * the invocation.
1751 * :U Converts variable to upper-case.
1752 * :L Converts variable to lower-case.
1753 */
1754 if ((str != (char *)NULL) && haveModifier) {
1755 /*
1756 * Skip initial colon while putting it back.
1757 */
1758 *tstr++ = ':';
1759 while (*tstr != endc) {
1760 char *newStr; /* New value to return */
1761 char termc; /* Character which terminated scan */
1762
1763 DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *tstr, str));
1764 switch (*tstr) {
1765 case 'U':
1766 if (tstr[1] == endc || tstr[1] == ':') {
1767 Buffer buf;
1768 buf = Buf_Init(MAKE_BSIZE);
1769 for (cp = str; *cp ; cp++)
1770 Buf_AddByte(buf, (Byte) toupper(*cp));
1771
1772 Buf_AddByte(buf, (Byte) '\0');
1773 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
1774 Buf_Destroy(buf, FALSE);
1775
1776 cp = tstr + 1;
1777 termc = *cp;
1778 break;
1779 }
1780 /* FALLTHROUGH */
1781 case 'L':
1782 if (tstr[1] == endc || tstr[1] == ':') {
1783 Buffer buf;
1784 buf = Buf_Init(MAKE_BSIZE);
1785 for (cp = str; *cp ; cp++)
1786 Buf_AddByte(buf, (Byte) tolower(*cp));
1787
1788 Buf_AddByte(buf, (Byte) '\0');
1789 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
1790 Buf_Destroy(buf, FALSE);
1791
1792 cp = tstr + 1;
1793 termc = *cp;
1794 break;
1795 }
1796 /* FALLTHROUGH */
1797 case 'N':
1798 case 'M':
1799 {
1800 char *pattern;
1801 char *cp2;
1802 Boolean copy;
1803
1804 copy = FALSE;
1805 for (cp = tstr + 1;
1806 *cp != '\0' && *cp != ':' && *cp != endc;
1807 cp++)
1808 {
1809 if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){
1810 copy = TRUE;
1811 cp++;
1812 }
1813 }
1814 termc = *cp;
1815 *cp = '\0';
1816 if (copy) {
1817 /*
1818 * Need to compress the \:'s out of the pattern, so
1819 * allocate enough room to hold the uncompressed
1820 * pattern (note that cp started at tstr+1, so
1821 * cp - tstr takes the null byte into account) and
1822 * compress the pattern into the space.
1823 */
1824 pattern = emalloc(cp - tstr);
1825 for (cp2 = pattern, cp = tstr + 1;
1826 *cp != '\0';
1827 cp++, cp2++)
1828 {
1829 if ((*cp == '\\') &&
1830 (cp[1] == ':' || cp[1] == endc)) {
1831 cp++;
1832 }
1833 *cp2 = *cp;
1834 }
1835 *cp2 = '\0';
1836 } else {
1837 pattern = &tstr[1];
1838 }
1839 if (*tstr == 'M' || *tstr == 'm') {
1840 newStr = VarModify(str, VarMatch, (void *)pattern);
1841 } else {
1842 newStr = VarModify(str, VarNoMatch,
1843 (void *)pattern);
1844 }
1845 if (copy) {
1846 free(pattern);
1847 }
1848 break;
1849 }
1850 case 'S':
1851 {
1852 VarPattern pattern;
1853 char delim;
1854 Buffer buf; /* Buffer for patterns */
1855
1856 pattern.flags = 0;
1857 delim = tstr[1];
1858 tstr += 2;
1859
1860 /*
1861 * If pattern begins with '^', it is anchored to the
1862 * start of the word -- skip over it and flag pattern.
1863 */
1864 if (*tstr == '^') {
1865 pattern.flags |= VAR_MATCH_START;
1866 tstr += 1;
1867 }
1868
1869 buf = Buf_Init(0);
1870
1871 /*
1872 * Pass through the lhs looking for 1) escaped delimiters,
1873 * '$'s and backslashes (place the escaped character in
1874 * uninterpreted) and 2) unescaped $'s that aren't before
1875 * the delimiter (expand the variable substitution).
1876 * The result is left in the Buffer buf.
1877 */
1878 for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
1879 if ((*cp == '\\') &&
1880 ((cp[1] == delim) ||
1881 (cp[1] == '$') ||
1882 (cp[1] == '\\')))
1883 {
1884 Buf_AddByte(buf, (Byte)cp[1]);
1885 cp++;
1886 } else if (*cp == '$') {
1887 if (cp[1] != delim) {
1888 /*
1889 * If unescaped dollar sign not before the
1890 * delimiter, assume it's a variable
1891 * substitution and recurse.
1892 */
1893 char *cp2;
1894 int len;
1895 Boolean freeIt;
1896
1897 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1898 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
1899 if (freeIt) {
1900 free(cp2);
1901 }
1902 cp += len - 1;
1903 } else {
1904 /*
1905 * Unescaped $ at end of pattern => anchor
1906 * pattern at end.
1907 */
1908 pattern.flags |= VAR_MATCH_END;
1909 }
1910 } else {
1911 Buf_AddByte(buf, (Byte)*cp);
1912 }
1913 }
1914
1915 Buf_AddByte(buf, (Byte)'\0');
1916
1917 /*
1918 * If lhs didn't end with the delimiter, complain and
1919 * return NULL
1920 */
1921 if (*cp != delim) {
1922 *lengthPtr = cp - start + 1;
1923 if (*freePtr) {
1924 free(str);
1925 }
1926 Buf_Destroy(buf, TRUE);
1927 Error("Unclosed substitution for %s (%c missing)",
1928 v->name, delim);
1929 return (var_Error);
1930 }
1931
1932 /*
1933 * Fetch pattern and destroy buffer, but preserve the data
1934 * in it, since that's our lhs. Note that Buf_GetAll
1935 * will return the actual number of bytes, which includes
1936 * the null byte, so we have to decrement the length by
1937 * one.
1938 */
1939 pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen);
1940 pattern.leftLen--;
1941 Buf_Destroy(buf, FALSE);
1942
1943 /*
1944 * Now comes the replacement string. Three things need to
1945 * be done here: 1) need to compress escaped delimiters and
1946 * ampersands and 2) need to replace unescaped ampersands
1947 * with the l.h.s. (since this isn't regexp, we can do
1948 * it right here) and 3) expand any variable substitutions.
1949 */
1950 buf = Buf_Init(0);
1951
1952 tstr = cp + 1;
1953 for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
1954 if ((*cp == '\\') &&
1955 ((cp[1] == delim) ||
1956 (cp[1] == '&') ||
1957 (cp[1] == '\\') ||
1958 (cp[1] == '$')))
1959 {
1960 Buf_AddByte(buf, (Byte)cp[1]);
1961 cp++;
1962 } else if ((*cp == '$') && (cp[1] != delim)) {
1963 char *cp2;
1964 int len;
1965 Boolean freeIt;
1966
1967 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
1968 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
1969 cp += len - 1;
1970 if (freeIt) {
1971 free(cp2);
1972 }
1973 } else if (*cp == '&') {
1974 Buf_AddBytes(buf, pattern.leftLen,
1975 (Byte *)pattern.lhs);
1976 } else {
1977 Buf_AddByte(buf, (Byte)*cp);
1978 }
1979 }
1980
1981 Buf_AddByte(buf, (Byte)'\0');
1982
1983 /*
1984 * If didn't end in delimiter character, complain
1985 */
1986 if (*cp != delim) {
1987 *lengthPtr = cp - start + 1;
1988 if (*freePtr) {
1989 free(str);
1990 }
1991 Buf_Destroy(buf, TRUE);
1992 Error("Unclosed substitution for %s (%c missing)",
1993 v->name, delim);
1994 return (var_Error);
1995 }
1996
1997 pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen);
1998 pattern.rightLen--;
1999 Buf_Destroy(buf, FALSE);
2000
2001 /*
2002 * Check for global substitution. If 'g' after the final
2003 * delimiter, substitution is global and is marked that
2004 * way.
2005 */
2006 cp++;
2007 if (*cp == 'g') {
2008 pattern.flags |= VAR_SUB_GLOBAL;
2009 cp++;
2010 }
2011
2012 termc = *cp;
2013 newStr = VarModify(str, VarSubstitute,
2014 (void *)&pattern);
2015 /*
2016 * Free the two strings.
2017 */
2018 free(pattern.lhs);
2019 free(pattern.rhs);
2020 break;
2021 }
2022 case 'C':
2023 {
2024 VarREPattern pattern;
2025 char *re;
2026 int error;
2027
2028 pattern.flags = 0;
2029 delim = tstr[1];
2030 tstr += 2;
2031
2032 cp = tstr;
2033
2034 if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
2035 NULL, NULL)) == NULL) {
2036 /* was: goto cleanup */
2037 *lengthPtr = cp - start + 1;
2038 if (*freePtr)
2039 free(str);
2040 if (delim != '\0')
2041 Error("Unclosed substitution for %s (%c missing)",
2042 v->name, delim);
2043 return (var_Error);
2044 }
2045
2046 if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
2047 delim, NULL, NULL, NULL)) == NULL){
2048 free(re);
2049
2050 /* was: goto cleanup */
2051 *lengthPtr = cp - start + 1;
2052 if (*freePtr)
2053 free(str);
2054 if (delim != '\0')
2055 Error("Unclosed substitution for %s (%c missing)",
2056 v->name, delim);
2057 return (var_Error);
2058 }
2059
2060 for (;; cp++) {
2061 switch (*cp) {
2062 case 'g':
2063 pattern.flags |= VAR_SUB_GLOBAL;
2064 continue;
2065 case '1':
2066 pattern.flags |= VAR_SUB_ONE;
2067 continue;
2068 }
2069 break;
2070 }
2071
2072 termc = *cp;
2073
2074 error = regcomp(&pattern.re, re, REG_EXTENDED);
2075 free(re);
2076 if (error) {
2077 *lengthPtr = cp - start + 1;
2078 VarREError(error, &pattern.re, "RE substitution error");
2079 free(pattern.replace);
2080 return (var_Error);
2081 }
2082
2083 pattern.nsub = pattern.re.re_nsub + 1;
2084 if (pattern.nsub < 1)
2085 pattern.nsub = 1;
2086 if (pattern.nsub > 10)
2087 pattern.nsub = 10;
2088 pattern.matches = emalloc(pattern.nsub *
2089 sizeof(regmatch_t));
2090 newStr = VarModify(str, VarRESubstitute,
2091 (void *) &pattern);
2092 regfree(&pattern.re);
2093 free(pattern.replace);
2094 free(pattern.matches);
2095 break;
2096 }
2097 case 'Q':
2098 if (tstr[1] == endc || tstr[1] == ':') {
2099 newStr = VarQuote (str);
2100 cp = tstr + 1;
2101 termc = *cp;
2102 break;
2103 }
2104 /*FALLTHRU*/
2105 case 'T':
2106 if (tstr[1] == endc || tstr[1] == ':') {
2107 newStr = VarModify (str, VarTail, (void *)0);
2108 cp = tstr + 1;
2109 termc = *cp;
2110 break;
2111 }
2112 /*FALLTHRU*/
2113 case 'H':
2114 if (tstr[1] == endc || tstr[1] == ':') {
2115 newStr = VarModify (str, VarHead, (void *)0);
2116 cp = tstr + 1;
2117 termc = *cp;
2118 break;
2119 }
2120 /*FALLTHRU*/
2121 case 'E':
2122 if (tstr[1] == endc || tstr[1] == ':') {
2123 newStr = VarModify (str, VarSuffix, (void *)0);
2124 cp = tstr + 1;
2125 termc = *cp;
2126 break;
2127 }
2128 /*FALLTHRU*/
2129 case 'R':
2130 if (tstr[1] == endc || tstr[1] == ':') {
2131 newStr = VarModify (str, VarRoot, (void *)0);
2132 cp = tstr + 1;
2133 termc = *cp;
2134 break;
2135 }
2136 /*FALLTHRU*/
2137#ifdef SUNSHCMD
2138 case 's':
2139 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
2140 char *err;
2141 newStr = Cmd_Exec (str, &err);
2142 if (err)
2143 Error (err, str);
2144 cp = tstr + 2;
2145 termc = *cp;
2146 break;
2147 }
2148 /*FALLTHRU*/
2149#endif
2150 default:
2151 {
2152#ifdef SYSVVARSUB
2153 /*
2154 * This can either be a bogus modifier or a System-V
2155 * substitution command.
2156 */
2157 VarPattern pattern;
2158 Boolean eqFound;
2159
2160 pattern.flags = 0;
2161 eqFound = FALSE;
2162 /*
2163 * First we make a pass through the string trying
2164 * to verify it is a SYSV-make-style translation:
2165 * it must be: <string1>=<string2>)
2166 */
2167 cp = tstr;
2168 cnt = 1;
2169 while (*cp != '\0' && cnt) {
2170 if (*cp == '=') {
2171 eqFound = TRUE;
2172 /* continue looking for endc */
2173 }
2174 else if (*cp == endc)
2175 cnt--;
2176 else if (*cp == startc)
2177 cnt++;
2178 if (cnt)
2179 cp++;
2180 }
2181 if (*cp == endc && eqFound) {
2182
2183 /*
2184 * Now we break this sucker into the lhs and
2185 * rhs. We must null terminate them of course.
2186 */
2187 for (cp = tstr; *cp != '='; cp++)
2188 continue;
2189 pattern.lhs = tstr;
2190 pattern.leftLen = cp - tstr;
2191 *cp++ = '\0';
2192
2193 pattern.rhs = cp;
2194 cnt = 1;
2195 while (cnt) {
2196 if (*cp == endc)
2197 cnt--;
2198 else if (*cp == startc)
2199 cnt++;
2200 if (cnt)
2201 cp++;
2202 }
2203 pattern.rightLen = cp - pattern.rhs;
2204 *cp = '\0';
2205
2206 /*
2207 * SYSV modifications happen through the whole
2208 * string. Note the pattern is anchored at the end.
2209 */
2210 newStr = VarModify(str, VarSYSVMatch,
2211 (void *)&pattern);
2212
2213 /*
2214 * Restore the nulled characters
2215 */
2216 pattern.lhs[pattern.leftLen] = '=';
2217 pattern.rhs[pattern.rightLen] = endc;
2218 termc = endc;
2219 } else
2220#endif
2221 {
2222 Error ("Unknown modifier '%c'\n", *tstr);
2223 for (cp = tstr+1;
2224 *cp != ':' && *cp != endc && *cp != '\0';
2225 cp++)
2226 continue;
2227 termc = *cp;
2228 newStr = var_Error;
2229 }
2230 }
2231 }
2232 DEBUGF(VAR, ("Result is \"%s\"\n", newStr));
2233
2234 if (*freePtr) {
2235 free (str);
2236 }
2237 str = newStr;
2238 if (str != var_Error) {
2239 *freePtr = TRUE;
2240 } else {
2241 *freePtr = FALSE;
2242 }
2243 if (termc == '\0') {
2244 Error("Unclosed variable specification for %s", v->name);
2245 } else if (termc == ':') {
2246 *cp++ = termc;
2247 } else {
2248 *cp = termc;
2249 }
2250 tstr = cp;
2251 }
2252 *lengthPtr = tstr - start + 1;
2253 } else {
2254 *lengthPtr = tstr - start + 1;
2255 *tstr = endc;
2256 }
2257
2258 if (v->flags & VAR_FROM_ENV) {
2259 Boolean destroy = FALSE;
2260
2261 if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) {
2262 destroy = TRUE;
2263 } else {
2264 /*
2265 * Returning the value unmodified, so tell the caller to free
2266 * the thing.
2267 */
2268 *freePtr = TRUE;
2269 }
2270 Buf_Destroy(v->val, destroy);
2271 free(v);
2272 } else if (v->flags & VAR_JUNK) {
2273 /*
2274 * Perform any free'ing needed and set *freePtr to FALSE so the caller
2275 * doesn't try to free a static pointer.
2276 */
2277 if (*freePtr) {
2278 free(str);
2279 }
2280 *freePtr = FALSE;
2281 Buf_Destroy(v->val, TRUE);
2282 free(v);
2283 if (dynamic) {
2284 str = emalloc(*lengthPtr + 1);
2285 strncpy(str, start, *lengthPtr);
2286 str[*lengthPtr] = '\0';
2287 *freePtr = TRUE;
2288 } else {
2289 str = err ? var_Error : varNoError;
2290 }
2291 }
2292 return (str);
2293}
2294
2295/*-
2296 *-----------------------------------------------------------------------
2297 * Var_Subst --
2298 * Substitute for all variables in the given string in the given context
2299 * If undefErr is TRUE, Parse_Error will be called when an undefined
2300 * variable is encountered.
2301 *
2302 * Results:
2303 * The resulting string.
2304 *
2305 * Side Effects:
2306 * None. The old string must be freed by the caller
2307 *-----------------------------------------------------------------------
2308 */
2309char *
2310Var_Subst (var, str, ctxt, undefErr)
2311 char *var; /* Named variable || NULL for all */
2312 char *str; /* the string in which to substitute */
2313 GNode *ctxt; /* the context wherein to find variables */
2314 Boolean undefErr; /* TRUE if undefineds are an error */
2315{
2316 Buffer buf; /* Buffer for forming things */
2317 char *val; /* Value to substitute for a variable */
2318 int length; /* Length of the variable invocation */
2319 Boolean doFree; /* Set true if val should be freed */
2320 static Boolean errorReported; /* Set true if an error has already
2321 * been reported to prevent a plethora
2322 * of messages when recursing */
2323
2324 buf = Buf_Init (MAKE_BSIZE);
2325 errorReported = FALSE;
2326
2327 while (*str) {
2328 if (var == NULL && (*str == '$') && (str[1] == '$')) {
2329 /*
2330 * A dollar sign may be escaped either with another dollar sign.
2331 * In such a case, we skip over the escape character and store the
2332 * dollar sign into the buffer directly.
2333 */
2334 str++;
2335 Buf_AddByte(buf, (Byte)*str);
2336 str++;
2337 } else if (*str != '$') {
2338 /*
2339 * Skip as many characters as possible -- either to the end of
2340 * the string or to the next dollar sign (variable invocation).
2341 */
2342 char *cp;
2343
2344 for (cp = str++; *str != '$' && *str != '\0'; str++)
2345 continue;
2346 Buf_AddBytes(buf, str - cp, (Byte *)cp);
2347 } else {
2348 if (var != NULL) {
2349 int expand;
2350 for (;;) {
2351 if (str[1] != '(' && str[1] != '{') {
2352 if (str[1] != *var) {
2353 Buf_AddBytes(buf, 2, (Byte *) str);
2354 str += 2;
2355 expand = FALSE;
2356 }
2357 else
2358 expand = TRUE;
2359 break;
2360 }
2361 else {
2362 char *p;
2363
2364 /*
2365 * Scan up to the end of the variable name.
2366 */
2367 for (p = &str[2]; *p &&
2368 *p != ':' && *p != ')' && *p != '}'; p++)
2369 if (*p == '$')
2370 break;
2371 /*
2372 * A variable inside the variable. We cannot expand
2373 * the external variable yet, so we try again with
2374 * the nested one
2375 */
2376 if (*p == '$') {
2377 Buf_AddBytes(buf, p - str, (Byte *) str);
2378 str = p;
2379 continue;
2380 }
2381
2382 if (strncmp(var, str + 2, p - str - 2) != 0 ||
2383 var[p - str - 2] != '\0') {
2384 /*
2385 * Not the variable we want to expand, scan
2386 * until the next variable
2387 */
2388 for (;*p != '$' && *p != '\0'; p++)
2389 continue;
2390 Buf_AddBytes(buf, p - str, (Byte *) str);
2391 str = p;
2392 expand = FALSE;
2393 }
2394 else
2395 expand = TRUE;
2396 break;
2397 }
2398 }
2399 if (!expand)
2400 continue;
2401 }
2402
2403 val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
2404
2405 /*
2406 * When we come down here, val should either point to the
2407 * value of this variable, suitably modified, or be NULL.
2408 * Length should be the total length of the potential
2409 * variable invocation (from $ to end character...)
2410 */
2411 if (val == var_Error || val == varNoError) {
2412 /*
2413 * If performing old-time variable substitution, skip over
2414 * the variable and continue with the substitution. Otherwise,
2415 * store the dollar sign and advance str so we continue with
2416 * the string...
2417 */
2418 if (oldVars) {
2419 str += length;
2420 } else if (undefErr) {
2421 /*
2422 * If variable is undefined, complain and skip the
2423 * variable. The complaint will stop us from doing anything
2424 * when the file is parsed.
2425 */
2426 if (!errorReported) {
2427 Parse_Error (PARSE_FATAL,
2428 "Undefined variable \"%.*s\"",length,str);
2429 }
2430 str += length;
2431 errorReported = TRUE;
2432 } else {
2433 Buf_AddByte (buf, (Byte)*str);
2434 str += 1;
2435 }
2436 } else {
2437 /*
2438 * We've now got a variable structure to store in. But first,
2439 * advance the string pointer.
2440 */
2441 str += length;
2442
2443 /*
2444 * Copy all the characters from the variable value straight
2445 * into the new string.
2446 */
2447 Buf_AddBytes (buf, strlen (val), (Byte *)val);
2448 if (doFree) {
2449 free (val);
2450 }
2451 }
2452 }
2453 }
2454
2455 Buf_AddByte (buf, '\0');
2456 str = (char *)Buf_GetAll (buf, (int *)NULL);
2457 Buf_Destroy (buf, FALSE);
2458 return (str);
2459}
2460
2461/*-
2462 *-----------------------------------------------------------------------
2463 * Var_GetTail --
2464 * Return the tail from each of a list of words. Used to set the
2465 * System V local variables.
2466 *
2467 * Results:
2468 * The resulting string.
2469 *
2470 * Side Effects:
2471 * None.
2472 *
2473 *-----------------------------------------------------------------------
2474 */
2475char *
2476Var_GetTail(file)
2477 char *file; /* Filename to modify */
2478{
2479 return(VarModify(file, VarTail, (void *)0));
2480}
2481
2482/*-
2483 *-----------------------------------------------------------------------
2484 * Var_GetHead --
2485 * Find the leading components of a (list of) filename(s).
2486 * XXX: VarHead does not replace foo by ., as (sun) System V make
2487 * does.
2488 *
2489 * Results:
2490 * The leading components.
2491 *
2492 * Side Effects:
2493 * None.
2494 *
2495 *-----------------------------------------------------------------------
2496 */
2497char *
2498Var_GetHead(file)
2499 char *file; /* Filename to manipulate */
2500{
2501 return(VarModify(file, VarHead, (void *)0));
2502}
2503
2504/*-
2505 *-----------------------------------------------------------------------
2506 * Var_Init --
2507 * Initialize the module
2508 *
2509 * Results:
2510 * None
2511 *
2512 * Side Effects:
2513 * The VAR_CMD and VAR_GLOBAL contexts are created
2514 *-----------------------------------------------------------------------
2515 */
2516void
2517Var_Init ()
2518{
2519 VAR_GLOBAL = Targ_NewGN ("Global");
2520 VAR_CMD = Targ_NewGN ("Command");
2521 allVars = Lst_Init(FALSE);
2522
2523}
2524
2525
2526void
2527Var_End ()
2528{
2529 Lst_Destroy(allVars, VarDelete);
2530}
2531
2532
2533/****************** PRINT DEBUGGING INFO *****************/
2534static int
2535VarPrintVar (vp, dummy)
2536 void * vp;
2537 void * dummy;
2538{
2539 Var *v = (Var *) vp;
2540 printf ("%-16s = %s\n", v->name, (char *) Buf_GetAll(v->val, (int *)NULL));
2541 return (dummy ? 0 : 0);
2542}
2543
2544/*-
2545 *-----------------------------------------------------------------------
2546 * Var_Dump --
2547 * print all variables in a context
2548 *-----------------------------------------------------------------------
2549 */
2550void
2551Var_Dump (ctxt)
2552 GNode *ctxt;
2553{
2554 Lst_ForEach (ctxt->context, VarPrintVar, (void *) 0);
2555}