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 <cworth@cworth.org>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Carl Worth
2012-06-09 16:31:06 -07:00
parent 39f8c46eaa
commit aac78ce823
4 changed files with 55 additions and 40 deletions

View File

@@ -40,12 +40,18 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
#define YY_NO_INPUT #define YY_NO_INPUT
#define YY_USER_ACTION \ #define YY_USER_ACTION \
do { \ do { \
yylloc->first_column = yycolumn + 1; \ if (parser->has_new_line_number) \
yylloc->first_line = yylineno; \ yylineno = parser->new_line_number; \
yycolumn += yyleng; \ if (parser->has_new_source_number) \
} while(0); 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 \ #define YY_USER_INIT \
do { \ do { \
@@ -129,35 +135,8 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
return OTHER; return OTHER;
} }
{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ { {HASH}line {
/* Eat characters until the first digit is return HASH_LINE;
* 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;
} }
<SKIP,INITIAL>{ <SKIP,INITIAL>{

View File

@@ -162,7 +162,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
%lex-param {glcpp_parser_t *parser} %lex-param {glcpp_parser_t *parser}
%expect 0 %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 %token PASTE
%type <ival> expression INTEGER operator SPACE integer_constant %type <ival> expression INTEGER operator SPACE integer_constant
%type <str> IDENTIFIER INTEGER_STRING OTHER %type <str> IDENTIFIER INTEGER_STRING OTHER
@@ -208,6 +208,24 @@ expanded_line:
| ELIF_EXPANDED expression NEWLINE { | ELIF_EXPANDED expression NEWLINE {
_glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2); _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: control_line:
@@ -228,6 +246,14 @@ control_line:
} }
ralloc_free ($2); 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 { | HASH_IF conditional_tokens NEWLINE {
/* Be careful to only evaluate the 'if' expression if /* Be careful to only evaluate the 'if' expression if
* we are not skipping. When we are skipping, we * 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->info_log_length = 0;
parser->error = 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 pre-defined macros. */
add_builtin_define(parser, "GL_ARB_draw_buffers", 1); add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);

View File

@@ -25,6 +25,7 @@
#define GLCPP_H #define GLCPP_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "../ralloc.h" #include "../ralloc.h"
@@ -177,6 +178,10 @@ struct glcpp_parser {
size_t output_length; size_t output_length;
size_t info_log_length; size_t info_log_length;
int error; int error;
bool has_new_line_number;
int new_line_number;
bool has_new_source_number;
int new_source_number;
}; };
struct gl_extensions; struct gl_extensions;

View File

@@ -3,11 +3,11 @@
1:0(1): preprocessor error: #error source 1, line 0 error 1:0(1): preprocessor error: #error source 1, line 0 error
2:30(1): preprocessor error: #error source 2, line 30 error 2:30(1): preprocessor error: #error source 2, line 30 error
#line 0
#line 25
#line 0 1
#line 30 2