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