glcpp: Add support for "redefined macro" error.

Carefully avoiding printing any error when the new definition matches
the existing definition.

This fixes the recently-added 088-redefine-macro-legitimate.c and
089-redefine-macro-error.c tests as well as glsparsertest/preprocess1
in piglit.
This commit is contained in:
Carl Worth 2010-08-17 23:20:58 -07:00
parent 105e2137d6
commit 3882cf2169
1 changed files with 123 additions and 2 deletions

View File

@ -63,6 +63,9 @@ _string_list_contains (string_list_t *list, const char *member, int *index);
static int
_string_list_length (string_list_t *list);
static int
_string_list_equal (string_list_t *a, string_list_t *b);
static argument_list_t *
_argument_list_create (void *ctx);
@ -95,6 +98,9 @@ _token_list_append (token_list_t *list, token_t *token);
static void
_token_list_append_list (token_list_t *list, token_list_t *tail);
static int
_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
static active_list_t *
_active_list_push (active_list_t *list,
const char *identifier,
@ -604,6 +610,31 @@ _string_list_length (string_list_t *list)
return length;
}
int
_string_list_equal (string_list_t *a, string_list_t *b)
{
string_node_t *node_a, *node_b;
if (a == NULL && b == NULL)
return 1;
if (a == NULL || b == NULL)
return 0;
for (node_a = a->head, node_b = b->head;
node_a && node_b;
node_a = node_a->next, node_b = node_b->next)
{
if (strcmp (node_a->str, node_b->str))
return 0;
}
/* Catch the case of lists being different lengths, (which
* would cause the loop above to terminate after the shorter
* list). */
return node_a == node_b;
}
argument_list_t *
_argument_list_create (void *ctx)
{
@ -781,6 +812,61 @@ _token_list_trim_trailing_space (token_list_t *list)
}
}
int
_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
{
token_node_t *node_a, *node_b;
node_a = a->head;
node_b = b->head;
while (1)
{
if (node_a == NULL && node_b == NULL)
break;
if (node_a == NULL || node_b == NULL)
return 0;
if (node_a->token->type == SPACE) {
node_a = node_a->next;
continue;
}
if (node_b->token->type == SPACE) {
node_b = node_b->next;
continue;
}
if (node_a->token->type != node_b->token->type)
return 0;
switch (node_a->token->type) {
case INTEGER:
if (node_a->token->value.ival !=
node_b->token->value.ival)
{
return 0;
}
break;
case IDENTIFIER:
case INTEGER_STRING:
case OTHER:
if (strcmp (node_a->token->value.str,
node_b->token->value.str))
{
return 0;
}
break;
}
node_a = node_a->next;
node_b = node_b->next;
}
return 1;
}
static void
_token_print (char **out, token_t *token)
{
@ -1522,13 +1608,28 @@ _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
}
}
static int
_macro_equal (macro_t *a, macro_t *b)
{
if (a->is_function != b->is_function)
return 0;
if (a->is_function) {
if (! _string_list_equal (a->parameters, b->parameters))
return 0;
}
return _token_list_equal_ignoring_space (a->replacements,
b->replacements);
}
void
_define_object_macro (glcpp_parser_t *parser,
YYLTYPE *loc,
const char *identifier,
token_list_t *replacements)
{
macro_t *macro;
macro_t *macro, *previous;
if (loc != NULL)
_check_for_reserved_macro_name(parser, loc, identifier);
@ -1540,6 +1641,16 @@ _define_object_macro (glcpp_parser_t *parser,
macro->identifier = talloc_strdup (macro, identifier);
macro->replacements = talloc_steal (macro, replacements);
previous = hash_table_find (parser->defines, identifier);
if (previous) {
if (_macro_equal (macro, previous)) {
talloc_free (macro);
return;
}
glcpp_error (loc, parser, "Redefinition of macro %s\n",
identifier);
}
hash_table_insert (parser->defines, macro, identifier);
}
@ -1550,7 +1661,7 @@ _define_function_macro (glcpp_parser_t *parser,
string_list_t *parameters,
token_list_t *replacements)
{
macro_t *macro;
macro_t *macro, *previous;
_check_for_reserved_macro_name(parser, loc, identifier);
@ -1561,6 +1672,16 @@ _define_function_macro (glcpp_parser_t *parser,
macro->identifier = talloc_strdup (macro, identifier);
macro->replacements = talloc_steal (macro, replacements);
previous = hash_table_find (parser->defines, identifier);
if (previous) {
if (_macro_equal (macro, previous)) {
talloc_free (macro);
return;
}
glcpp_error (loc, parser, "Redefinition of macro %s\n",
identifier);
}
hash_table_insert (parser->defines, macro, identifier);
}