glcpp: Rework handling of "defined" operator.
It's now done in the grammar, and as a result, can easily handle parenthesis. defined ( identifier ) is now supported. Fixes glcpp/tests/065-if-defined-parens.c.
This commit is contained in:
@@ -110,10 +110,6 @@ _active_list_pop (active_list_t *list);
|
|||||||
int
|
int
|
||||||
_active_list_contains (active_list_t *list, const char *identifier);
|
_active_list_contains (active_list_t *list, const char *identifier);
|
||||||
|
|
||||||
static void
|
|
||||||
_glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
|
|
||||||
token_list_t *list);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
|
_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
|
||||||
token_list_t *list);
|
token_list_t *list);
|
||||||
@@ -155,8 +151,8 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
|
|||||||
%type <ival> expression INTEGER operator SPACE
|
%type <ival> expression INTEGER operator SPACE
|
||||||
%type <str> IDENTIFIER INTEGER_STRING OTHER
|
%type <str> IDENTIFIER INTEGER_STRING OTHER
|
||||||
%type <string_list> identifier_list
|
%type <string_list> identifier_list
|
||||||
%type <token> preprocessing_token
|
%type <token> preprocessing_token conditional_token
|
||||||
%type <token_list> pp_tokens replacement_list text_line
|
%type <token_list> pp_tokens replacement_list text_line conditional_tokens
|
||||||
%left OR
|
%left OR
|
||||||
%left AND
|
%left AND
|
||||||
%left '|'
|
%left '|'
|
||||||
@@ -219,7 +215,7 @@ control_line:
|
|||||||
}
|
}
|
||||||
talloc_free ($2);
|
talloc_free ($2);
|
||||||
}
|
}
|
||||||
| HASH_IF pp_tokens NEWLINE {
|
| HASH_IF conditional_tokens NEWLINE {
|
||||||
token_list_t *expanded;
|
token_list_t *expanded;
|
||||||
token_t *token;
|
token_t *token;
|
||||||
|
|
||||||
@@ -227,7 +223,6 @@ control_line:
|
|||||||
token = _token_create_ival (parser, IF_EXPANDED, IF_EXPANDED);
|
token = _token_create_ival (parser, IF_EXPANDED, IF_EXPANDED);
|
||||||
_token_list_append (expanded, token);
|
_token_list_append (expanded, token);
|
||||||
talloc_unlink (parser, token);
|
talloc_unlink (parser, token);
|
||||||
_glcpp_parser_evaluate_defined (parser, $2);
|
|
||||||
_glcpp_parser_expand_token_list (parser, $2);
|
_glcpp_parser_expand_token_list (parser, $2);
|
||||||
_token_list_append_list (expanded, $2);
|
_token_list_append_list (expanded, $2);
|
||||||
glcpp_parser_lex_from (parser, expanded);
|
glcpp_parser_lex_from (parser, expanded);
|
||||||
@@ -242,7 +237,7 @@ control_line:
|
|||||||
talloc_free ($2);
|
talloc_free ($2);
|
||||||
_glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
|
_glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
|
||||||
}
|
}
|
||||||
| HASH_ELIF pp_tokens NEWLINE {
|
| HASH_ELIF conditional_tokens NEWLINE {
|
||||||
token_list_t *expanded;
|
token_list_t *expanded;
|
||||||
token_t *token;
|
token_t *token;
|
||||||
|
|
||||||
@@ -250,7 +245,6 @@ control_line:
|
|||||||
token = _token_create_ival (parser, ELIF_EXPANDED, ELIF_EXPANDED);
|
token = _token_create_ival (parser, ELIF_EXPANDED, ELIF_EXPANDED);
|
||||||
_token_list_append (expanded, token);
|
_token_list_append (expanded, token);
|
||||||
talloc_unlink (parser, token);
|
talloc_unlink (parser, token);
|
||||||
_glcpp_parser_evaluate_defined (parser, $2);
|
|
||||||
_glcpp_parser_expand_token_list (parser, $2);
|
_glcpp_parser_expand_token_list (parser, $2);
|
||||||
_token_list_append_list (expanded, $2);
|
_token_list_append_list (expanded, $2);
|
||||||
glcpp_parser_lex_from (parser, expanded);
|
glcpp_parser_lex_from (parser, expanded);
|
||||||
@@ -382,6 +376,35 @@ junk:
|
|||||||
| pp_tokens {
|
| pp_tokens {
|
||||||
glcpp_warning(&@1, parser, "extra tokens at end of directive");
|
glcpp_warning(&@1, parser, "extra tokens at end of directive");
|
||||||
}
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
conditional_token:
|
||||||
|
/* Handle "defined" operator */
|
||||||
|
DEFINED IDENTIFIER {
|
||||||
|
int v = hash_table_find (parser->defines, $2) ? 1 : 0;
|
||||||
|
$$ = _token_create_ival (parser, INTEGER, v);
|
||||||
|
}
|
||||||
|
| DEFINED '(' IDENTIFIER ')' {
|
||||||
|
int v = hash_table_find (parser->defines, $3) ? 1 : 0;
|
||||||
|
$$ = _token_create_ival (parser, INTEGER, v);
|
||||||
|
}
|
||||||
|
| preprocessing_token
|
||||||
|
;
|
||||||
|
|
||||||
|
conditional_tokens:
|
||||||
|
/* Exactly the same as pp_tokens, but using conditional_token */
|
||||||
|
conditional_token {
|
||||||
|
parser->space_tokens = 1;
|
||||||
|
$$ = _token_list_create (parser);
|
||||||
|
_token_list_append ($$, $1);
|
||||||
|
talloc_unlink (parser, $1);
|
||||||
|
}
|
||||||
|
| conditional_tokens conditional_token {
|
||||||
|
$$ = $1;
|
||||||
|
_token_list_append ($$, $2);
|
||||||
|
talloc_unlink (parser, $2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
pp_tokens:
|
pp_tokens:
|
||||||
preprocessing_token {
|
preprocessing_token {
|
||||||
@@ -936,41 +959,6 @@ glcpp_parser_destroy (glcpp_parser_t *parser)
|
|||||||
talloc_free (parser);
|
talloc_free (parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace any occurences of DEFINED tokens in 'list' with either a
|
|
||||||
* '0' or '1' INTEGER token depending on whether the next token in the
|
|
||||||
* list is defined or not. */
|
|
||||||
static void
|
|
||||||
_glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
|
|
||||||
token_list_t *list)
|
|
||||||
{
|
|
||||||
token_node_t *node, *next;
|
|
||||||
macro_t *macro;
|
|
||||||
|
|
||||||
if (list == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (node = list->head; node; node = node->next) {
|
|
||||||
if (node->token->type != DEFINED)
|
|
||||||
continue;
|
|
||||||
next = node->next;
|
|
||||||
while (next && next->token->type == SPACE)
|
|
||||||
next = next->next;
|
|
||||||
if (next == NULL || next->token->type != IDENTIFIER) {
|
|
||||||
yyerror (&node->token->location, parser, "operator \"defined\" requires an identifier\n");
|
|
||||||
/* Already flagged an error; fake it. */
|
|
||||||
node->token->type = INTEGER;
|
|
||||||
node->token->value.ival = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
macro = hash_table_find (parser->defines,
|
|
||||||
next->token->value.str);
|
|
||||||
|
|
||||||
node->token->type = INTEGER;
|
|
||||||
node->token->value.ival = (macro != NULL);
|
|
||||||
node->next = next->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum function_status
|
typedef enum function_status
|
||||||
{
|
{
|
||||||
FUNCTION_STATUS_SUCCESS,
|
FUNCTION_STATUS_SUCCESS,
|
||||||
|
Reference in New Issue
Block a user