From aac78ce8234d96932c38b3f48b1d828077bc0027 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Sat, 9 Jun 2012 16:31:06 -0700 Subject: [PATCH] glsl: glcpp: Move handling of #line directives from lexer to parser. The GLSL specification requires that #line directives be interpreted after macro expansion. Our existing implementation of #line macros in the lexer prevents conformance on this point. Moving the handling of #line from the lexer to the parser gives us the macro expansion we need. An additional benefit is that the preprocessor also now supports comments on the same line as #line directives. Finally, the preprocessor now emits the (fully-macro-expanded) #line directives into the output. This allows the full GLSL compiler to also see and interpret these directives so it can also generate correct line numbers in error messages. Signed-off-by: Carl Worth Reviewed-by: Kenneth Graunke --- src/glsl/glcpp/glcpp-lex.l | 49 ++++++------------- src/glsl/glcpp/glcpp-parse.y | 33 ++++++++++++- src/glsl/glcpp/glcpp.h | 5 ++ src/glsl/glcpp/tests/091-hash-line.c.expected | 8 +-- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l index b34f2c0e9ad..7ab58cb288d 100644 --- a/src/glsl/glcpp/glcpp-lex.l +++ b/src/glsl/glcpp/glcpp-lex.l @@ -40,12 +40,18 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); #define YY_NO_INPUT -#define YY_USER_ACTION \ - do { \ - yylloc->first_column = yycolumn + 1; \ - yylloc->first_line = yylineno; \ - yycolumn += yyleng; \ - } while(0); +#define YY_USER_ACTION \ + do { \ + if (parser->has_new_line_number) \ + yylineno = parser->new_line_number; \ + if (parser->has_new_source_number) \ + yylloc->source = parser->new_source_number; \ + yylloc->first_column = yycolumn + 1; \ + yylloc->first_line = yylineno; \ + yycolumn += yyleng; \ + parser->has_new_line_number = 0; \ + parser->has_new_source_number = 0; \ + } while(0); #define YY_USER_INIT \ do { \ @@ -129,35 +135,8 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? return OTHER; } -{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ { - /* Eat characters until the first digit is - * encountered - */ - char *ptr = yytext; - while (!isdigit(*ptr)) - ptr++; - - /* Subtract one from the line number because - * yylineno is zero-based instead of - * one-based. - */ - yylineno = strtol(ptr, &ptr, 0) - 1; - yylloc->source = strtol(ptr, NULL, 0); -} - -{HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ { - /* Eat characters until the first digit is - * encountered - */ - char *ptr = yytext; - while (!isdigit(*ptr)) - ptr++; - - /* Subtract one from the line number because - * yylineno is zero-based instead of - * one-based. - */ - yylineno = strtol(ptr, &ptr, 0) - 1; +{HASH}line { + return HASH_LINE; } { diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index ee0018016d7..cc4af168976 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -162,7 +162,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); %lex-param {glcpp_parser_t *parser} %expect 0 -%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE +%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE %token PASTE %type expression INTEGER operator SPACE integer_constant %type IDENTIFIER INTEGER_STRING OTHER @@ -208,6 +208,24 @@ expanded_line: | ELIF_EXPANDED expression NEWLINE { _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2); } +| LINE_EXPANDED integer_constant NEWLINE { + parser->has_new_line_number = 1; + parser->new_line_number = $2; + ralloc_asprintf_rewrite_tail (&parser->output, + &parser->output_length, + "#line %" PRIiMAX, + $2); + } +| LINE_EXPANDED integer_constant integer_constant NEWLINE { + parser->has_new_line_number = 1; + parser->new_line_number = $2; + parser->has_new_source_number = 1; + parser->new_source_number = $3; + ralloc_asprintf_rewrite_tail (&parser->output, + &parser->output_length, + "#line %" PRIiMAX " %" PRIiMAX, + $2, $3); + } ; control_line: @@ -228,6 +246,14 @@ control_line: } ralloc_free ($2); } +| HASH_LINE pp_tokens NEWLINE { + if (parser->skip_stack == NULL || + parser->skip_stack->type == SKIP_NO_SKIP) + { + _glcpp_parser_expand_and_lex_from (parser, + LINE_EXPANDED, $2); + } + } | HASH_IF conditional_tokens NEWLINE { /* Be careful to only evaluate the 'if' expression if * we are not skipping. When we are skipping, we @@ -1120,6 +1146,11 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) parser->info_log_length = 0; parser->error = 0; + parser->has_new_line_number = 0; + parser->new_line_number = 1; + parser->has_new_source_number = 0; + parser->new_source_number = 0; + /* Add pre-defined macros. */ add_builtin_define(parser, "GL_ARB_draw_buffers", 1); add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h index 2d7cad2e601..a13ade69ee4 100644 --- a/src/glsl/glcpp/glcpp.h +++ b/src/glsl/glcpp/glcpp.h @@ -25,6 +25,7 @@ #define GLCPP_H #include +#include #include "../ralloc.h" @@ -177,6 +178,10 @@ struct glcpp_parser { size_t output_length; size_t info_log_length; int error; + bool has_new_line_number; + int new_line_number; + bool has_new_source_number; + int new_source_number; }; struct gl_extensions; diff --git a/src/glsl/glcpp/tests/091-hash-line.c.expected b/src/glsl/glcpp/tests/091-hash-line.c.expected index e663398c160..ea29149bc62 100644 --- a/src/glsl/glcpp/tests/091-hash-line.c.expected +++ b/src/glsl/glcpp/tests/091-hash-line.c.expected @@ -3,11 +3,11 @@ 1:0(1): preprocessor error: #error source 1, line 0 error 2:30(1): preprocessor error: #error source 2, line 30 error +#line 0 +#line 25 +#line 0 1 - - - - +#line 30 2 -- 2.30.2