mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 17:10:11 +01:00
Treat newlines as space when invoking a function-like macro invocation.
This adds three new pieces of state to the parser, (is_control_line, newline_as_space, and paren_count), and a large amount of messy code. I'd definitely like to see a cleaner solution for this. With this fix, the "define-func-extra-newlines" now passes so we put it back to test #26 where it was originally (lately it has been known as test #55). Also, we tweak test 25 slightly. Previously this test was ending a file function-like macro name that was not actually a macro (not followed by a left parenthesis). As is, this fix was making that test fail because the text_line production expects to see a terminating NEWLINE, but that NEWLINE is now getting turned into a SPACE here. This seems unlikely to be a problem in the wild, (function macros being used in a non-macro sense seems rare enough---but more than likely they won't happen at the end of a file). Still, we document this shortcoming in the README.
This commit is contained in:
parent
0324cad796
commit
95951ea7bb
5 changed files with 67 additions and 3 deletions
4
README
4
README
|
|
@ -24,3 +24,7 @@ parentheses.
|
|||
|
||||
The #error, #pragma, #extension, #version, and #line macros are not
|
||||
yet supported.
|
||||
|
||||
A file that ends with a function-like macro name as the last
|
||||
non-whitespace token will result in a parse error, (where it should be
|
||||
passed through as is).
|
||||
|
|
@ -856,6 +856,9 @@ glcpp_parser_create (void)
|
|||
hash_table_string_compare);
|
||||
parser->active = _string_list_create (parser);
|
||||
parser->space_tokens = 1;
|
||||
parser->newline_as_space = 0;
|
||||
parser->in_control_line = 0;
|
||||
parser->paren_count = 0;
|
||||
|
||||
parser->skip_stack = NULL;
|
||||
|
||||
|
|
@ -1274,8 +1277,62 @@ glcpp_parser_lex (glcpp_parser_t *parser)
|
|||
token_node_t *node;
|
||||
int ret;
|
||||
|
||||
if (parser->lex_from_list == NULL)
|
||||
return glcpp_lex (parser->scanner);
|
||||
if (parser->lex_from_list == NULL) {
|
||||
ret = glcpp_lex (parser->scanner);
|
||||
|
||||
/* XXX: This ugly block of code exists for the sole
|
||||
* purpose of converting a NEWLINE token into a SPACE
|
||||
* token, but only in the case where we have seen a
|
||||
* function-like macro name, but have not yet seen its
|
||||
* closing parenthesis.
|
||||
*
|
||||
* There's perhaps a more compact way to do this with
|
||||
* mid-rule actions in the grammar.
|
||||
*
|
||||
* I'm definitely not pleased with the complexity of
|
||||
* this code here.
|
||||
*/
|
||||
if (parser->newline_as_space)
|
||||
{
|
||||
if (ret == '(') {
|
||||
parser->paren_count++;
|
||||
} else if (ret == ')') {
|
||||
parser->paren_count--;
|
||||
if (parser->paren_count == 0)
|
||||
parser->newline_as_space = 0;
|
||||
} else if (ret == NEWLINE) {
|
||||
ret = SPACE;
|
||||
} else if (ret != SPACE) {
|
||||
if (parser->paren_count == 0)
|
||||
parser->newline_as_space = 0;
|
||||
}
|
||||
}
|
||||
else if (parser->in_control_line)
|
||||
{
|
||||
if (ret == NEWLINE)
|
||||
parser->in_control_line = 0;
|
||||
}
|
||||
else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
|
||||
ret == HASH_UNDEF || ret == HASH_IF ||
|
||||
ret == HASH_IFDEF || ret == HASH_IFNDEF ||
|
||||
ret == HASH_ELIF || ret == HASH_ELSE ||
|
||||
ret == HASH_ENDIF || ret == HASH)
|
||||
{
|
||||
parser->in_control_line = 1;
|
||||
}
|
||||
else if (ret == IDENTIFIER)
|
||||
{
|
||||
macro_t *macro;
|
||||
macro = hash_table_find (parser->defines,
|
||||
yylval.str);
|
||||
if (macro && macro->is_function) {
|
||||
parser->newline_as_space = 1;
|
||||
parser->paren_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = parser->lex_from_node;
|
||||
|
||||
|
|
|
|||
3
glcpp.h
3
glcpp.h
|
|
@ -128,6 +128,9 @@ struct glcpp_parser {
|
|||
struct hash_table *defines;
|
||||
string_list_t *active;
|
||||
int space_tokens;
|
||||
int newline_as_space;
|
||||
int in_control_line;
|
||||
int paren_count;
|
||||
skip_node_t *skip_stack;
|
||||
token_list_t *lex_from_list;
|
||||
token_node_t *lex_from_node;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#define foo(bar) bar
|
||||
foo
|
||||
foo bar
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue