From e167e0a3c2751fa141e1cd7bbc4dde58b759cf8a Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 15 Jan 1995 15:32:37 +0000 Subject: [PATCH] (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. --- expand.c | 206 +++++++++++++++++++++++++------------------------------ 1 file changed, 94 insertions(+), 112 deletions(-) diff --git a/expand.c b/expand.c index bbbd6a70..867cf914 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; + replace_beg = subst_end + 1; + replace_end = 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 *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); + } } - 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; - - p = expand_argument (subst_beg, subst_end); - p1 = expand_argument (replace_beg, replace_end); - - 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); - } - - 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;