Thread View: gnu.utils.bug
1 messages
1 total messages
Started by Marc Ullman
Wed, 05 Jul 1989 18:39
Bug in GNU Make - Improper handling of nested variable references
Author: Marc Ullman
Date: Wed, 05 Jul 1989 18:39
Date: Wed, 05 Jul 1989 18:39
88 lines
3194 bytes
3194 bytes
B U G R E P O R T
Program: GNU Make
Version: 3.48
Computer: Sun 3
Operating System: SunOS 4.0.1
Reported By: Marc Ullman (marc@sun-valley.stanford.edu)
Date: July 5, 1989
gnumake has a bug with nested variable references when text strings contain
parentheses "(",")" and/or braces "{", "}" as the following example makefile
shows:
SOURCES = src1.c src2.c src3.c
LIB_NAME = testlib.a
LIB_OBJS = ${SOURCES:%.c=$(LIB_NAME)(%.o)}
all :
@echo "$(LIB_OBJS)"
running gnumake on this file produces the following result:
testlib.a(src1.o testlib.a(src2.o testlib.a(src3.o)
^ ^
| |
Missing parentheses
The bug results from an incorrect assumption in the function variable_expand()
in the file variable.c. A fragment of this function is shown below:
/* Is there a variable reference inside the parens or braces?
If so, expand it before expanding the entire reference. */
p1 = index (beg, closeparen);
if (p1 != 0)
p1 = lindex (beg, p1, '$');
if (p1 != 0)
{
/* BEG now points past the opening paren or brace.
Count parens or braces until it is matched. */
int count = 0;
for (p = beg; *p != '\0'; ++p)
{
if (*p == openparen)
++count;
else if (*p == closeparen && --count < 0)
break;
}
/* 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, p);
p1 = concat ("$(", name, ")");
free (name);
name = expand_argument (p1, p1 + strlen (p1));
o = variable_buffer_output (o, name, strlen (name));
free (name);
break;
}
}
The line
p1 = concat ("$(", name, ")");
blindly restores parentheses around the previously evaluated expression
rather than restoring the appropriate delimiters depending on the current
state of the variables "openparen" and "closeparen". A possible fix is shown below:
if (count < 0)
{
char var_start_str[3] = {'$', openparen, '\0' }; /* NEW */
char var_end_str[2] = {closeparen, '\0'}; /* NEW */
char *name = expand_argument (beg, p);
p1 = concat (var_start_str, name, var_end_str); /* REVISED */
free (name);
name = expand_argument (p1, p1 + strlen (p1));
o = variable_buffer_output (o, name, strlen (name));
free (name);
break;
}
With this revision, the sample makefile shown above yields the desirerd result:
testlib.a(src1.o) testlib.a(src2.o) testlib.a(src3.o)
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads