summaryrefslogtreecommitdiff
path: root/expand.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>1995-01-15 15:32:37 +0000
committerRoland McGrath <roland@redhat.com>1995-01-15 15:32:37 +0000
commite167e0a3c2751fa141e1cd7bbc4dde58b759cf8a (patch)
tree8f7d8d1002d33cd47f5ca09cb99f8c6176ce2de4 /expand.c
parent78794575450122bd215d07cfe47f447ffe21350d (diff)
downloadgunmake-e167e0a3c2751fa141e1cd7bbc4dde58b759cf8a.tar.gz
(variable_expand): Rewrote computed variable name and substitution
reference handling to be simpler. First expand the entire text between the parens if it contains any $s, then examine the result of that for subtitution references and do no further expansion while parsing them.
Diffstat (limited to 'expand.c')
-rw-r--r--expand.c202
1 files changed, 92 insertions, 110 deletions
diff --git a/expand.c b/expand.c
index bbbd6a7..867cf91 100644
--- a/expand.c
+++ b/expand.c
@@ -1,5 +1,5 @@
/* Variable expansion functions for GNU Make.
-Copyright (C) 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+Copyright (C) 1988, 89, 91, 92, 93, 95 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -197,9 +197,9 @@ variable_expand (line)
char openparen = *p;
char closeparen = (openparen == '(') ? ')' : '}';
register char *beg = p + 1;
+ int free_beg = 0;
char *op, *begp;
- char *end;
- char *colon = 0;
+ char *end, *colon;
op = o;
begp = p;
@@ -213,10 +213,18 @@ variable_expand (line)
/* Is there a variable reference inside the parens or braces?
If so, expand it before expanding the entire reference. */
- p1 = index (beg, closeparen);
+ end = index (beg, closeparen);
+ if (end == 0)
+ {
+ /* Unterminated variable reference. */
+ if (reading_filename != 0)
+ makefile_fatal (reading_filename, *reading_lineno_ptr,
+ "unterminated variable reference");
+ else
+ fatal ("unterminated variable reference");
+ }
+ p1 = lindex (beg, end, '$');
if (p1 != 0)
- p1 = lindex (beg, p1, '$');
- if (p1 != 0 && lindex (beg, p1, ':') == 0)
{
/* BEG now points past the opening paren or brace.
Count parens or braces until it is matched. */
@@ -227,133 +235,107 @@ variable_expand (line)
++count;
else if (*p == closeparen && --count < 0)
break;
- else if (colon == 0 && count == 0 && *p == ':')
- /* Record where we found a colon, which
- indicates a substitution reference.
- We want to expand the text before the
- reference only. */
- colon = p;
}
/* If COUNT is >= 0, there were unmatched opening parens
or braces, so we go to the simple case of a variable name
such as `$($(a)'. */
if (count < 0)
{
- char *name = expand_argument (beg, colon == 0 ? p : colon);
- unsigned int namelen = strlen (name);
- if (colon == 0)
- {
- /* This is a simple reference to the expanded name. */
- o = reference_variable (o, name, namelen);
- free (name);
- break;
- }
- else
- {
- /* This is a substitution reference to the expanded
- name. We replace the pending text with a copy
- containing the expanded name in place of the
- original name, and then fall through to
- the normal substitution reference code below. */
- unsigned int restlen = strlen (colon) + 1;
- beg = (char *) alloca (namelen + restlen);
- bcopy (name, beg, namelen);
- bcopy (colon, &beg[namelen], restlen);
- /* Point COLON into the new copy. */
- colon = &beg[namelen];
- }
+ beg = expand_argument (beg, p); /* Expand the name. */
+ free_beg = 1; /* Remember to free BEG when finished. */
+ end = index (beg, '\0');
}
}
+ else
+ /* Advance P to the end of this reference. After we are
+ finished expanding this one, P will be incremented to
+ continue the scan. */
+ p = end;
/* This is not a reference to a built-in function and
- it does not contain any variable references inside.
- There are several things it could be. */
+ any variable references inside are now expanded.
+ Is the resultant text a substitution reference? */
- if (colon == 0)
- colon = index (beg, ':');
- if (colon != 0 && lindex (beg, colon, closeparen) == 0)
+ colon = index (beg, ':');
+ if (colon != 0)
{
- /* This is a substitution reference: $(FOO:A=B). */
- int count;
+ /* This looks like a substitution reference: $(FOO:A=B). */
char *subst_beg, *subst_end, *replace_beg, *replace_end;
- v = lookup_variable (beg, colon - beg);
- if (v == 0)
- warn_undefined (beg, colon - beg);
-
subst_beg = colon + 1;
- count = 0;
- for (p = subst_beg; *p != '\0'; ++p)
+ subst_end = index (subst_beg, '=');
+ if (subst_end == 0)
+ /* There is no = in sight. Punt on the substitution
+ reference and treat this as a variable name containing
+ a colon, in the code below. */
+ colon = 0;
+ else
{
- if (*p == openparen)
- ++count;
- else if (*p == closeparen)
- --count;
- else if (*p == '=' && count <= 0)
- break;
- }
- if (count > 0)
- /* There were unmatched opening parens. */
- return initialize_variable_output ();
- subst_end = p;
-
- replace_beg = p + 1;
- count = 0;
- for (p = replace_beg; *p != '\0'; ++p)
- {
- if (*p == openparen)
- ++count;
- else if (*p == closeparen && --count < 0)
- break;
- }
- if (count > 0)
- /* There were unmatched opening parens. */
- return initialize_variable_output ();
- end = p;
- replace_end = p;
+ replace_beg = subst_end + 1;
+ replace_end = end;
- p = expand_argument (subst_beg, subst_end);
- p1 = expand_argument (replace_beg, replace_end);
+ /* Extract the variable name before the colon
+ and look up that variable. */
+ v = lookup_variable (beg, colon - beg);
+ if (v == 0)
+ warn_undefined (beg, colon - beg);
- if (v != 0 && *v->value != '\0')
- {
- char *value = (v->recursive ? recursively_expand (v)
- : v->value);
- char *percent = find_percent (p);
- if (percent != 0)
- o = patsubst_expand (o, value, p, p1,
- percent, (char *) 0);
- else
- o = subst_expand (o, value,
- p, p1, strlen (p), strlen (p1),
- 0, 1);
- if (v->recursive)
- free (value);
+ if (v != 0 && *v->value != '\0')
+ {
+ char *value = (v->recursive ? recursively_expand (v)
+ : v->value);
+ char *pattern, *percent;
+ if (free_beg)
+ {
+ *subst_end = '\0';
+ pattern = subst_beg;
+ }
+ else
+ {
+ pattern = alloca (subst_end - subst_beg + 1);
+ bcopy (subst_beg, pattern, subst_end - subst_beg);
+ pattern[subst_end - subst_beg] = '\0';
+ }
+ percent = find_percent (pattern);
+ if (percent != 0)
+ {
+ char *replace;
+ if (free_beg)
+ {
+ *replace_end = '\0';
+ replace = replace_beg;
+ }
+ else
+ {
+ replace = alloca (replace_end - replace_beg
+ + 1);
+ bcopy (replace_beg, replace,
+ replace_end - replace_beg);
+ replace[replace_end - replace_beg] = '\0';
+ }
+
+ o = patsubst_expand (o, value, pattern, replace,
+ percent, (char *) 0);
+ }
+ else
+ o = subst_expand (o, value,
+ pattern, replace_beg,
+ strlen (pattern),
+ end - replace_beg,
+ 0, 1);
+ if (v->recursive)
+ free (value);
+ }
}
-
- free (p);
- free (p1);
}
- /* No, this must be an ordinary variable reference. */
- else
- {
- /* Look up the value of the variable. */
- end = index (beg, closeparen);
- if (end == 0)
- {
- /* Unterminated variable reference. */
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "unterminated variable reference");
- else
- fatal ("unterminated variable reference");
- }
+ if (colon == 0)
+ /* This is an ordinary variable reference.
+ Look up the value of the variable. */
o = reference_variable (o, beg, end - beg);
- }
- /* Advance p past the variable reference to resume scan. */
- p = end;
+ if (free_beg)
+ free (beg);
}
break;