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