Such as: #line 23 "foo.c"
Having a filename here is quite useful and many other OpenGL implementations allow this. Note that for GLES we take the hard line and insist on a numeric source string number as per the specification and which glcpp has always supported: #line 23 3 --- This is something of a proof-of-concept for now. Ian mentioned to me yesterday that he would like to have support for '#line XX "filename.c"' has described above. And this is my quickest implementation of that. This is simple in that the string literal is not actually interpreted, (escape sequences aren't converted into their representations). The escape sequences are properly captured by a regular expression, but all just sucked up literally. This was easier to write, and is also what we want for re-emitting the #line directive, (with all of the escape sequences in place). This is slightly bogus for emitting the error messages, though. You'll get a C-formatted string literal instead of a filename. At a minimum this will look like: "foo.c":25: Syntax error So there are extra quotation marks there. And it will appear uglier if there are further escape sequences in the string. Fixing this would mean writing a fair amount of code to decode the C string literal, and then additional code to re-encode it to emit the #line directive. It's not totally clear to me whether that's all worth it. (Note that the code does exist in many implementations of C grammars, so it would be easy to find a version that we could legitimately copy into our implementation.) Meanwhile, the bigger issue that makes this just a proof-of-concept is that only the pre-processor is changed here. And unlike something like #define, the downstream compiler still sees #line directives emitted by the pre-processor. So a complete implementation of the feature of interest here requires augmenting the downstream code that is handling #line. I'll look at that next, but just wanted to mention the issue of string interpretation here first. And yes, it is silly that we are parsing #line in two different places of the code. Someday we'll have to integrate the GLSL compiler's parser with the output of the preprocessor, (drop the GLSL compiler's separate lexer, and make the preprocessor emit tokens rather than strings). When we do that, a feature like this one will be simpler. -Carl src/glsl/glcpp/glcpp-lex.l | 15 ++++++++++----- src/glsl/glcpp/glcpp-parse.y | 34 ++++++++++++++++++++++++++-------- src/glsl/glcpp/glcpp.h | 8 ++++---- src/glsl/glcpp/pp.c | 4 ++-- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l index 783c545..893ce66 100644 --- a/src/glsl/glcpp/glcpp-lex.l +++ b/src/glsl/glcpp/glcpp-lex.l @@ -44,20 +44,20 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); do { \ if (parser->has_new_line_number) \ yylineno = parser->new_line_number; \ - if (parser->has_new_source_number) \ - yylloc->source = parser->new_source_number; \ + if (parser->has_new_source) \ + yylloc->source = parser->new_source; \ yylloc->first_column = yycolumn + 1; \ yylloc->first_line = yylineno; \ yycolumn += yyleng; \ parser->has_new_line_number = 0; \ - parser->has_new_source_number = 0; \ + parser->has_new_source = 0; \ } while(0); #define YY_USER_INIT \ do { \ yylineno = 1; \ yycolumn = 1; \ - yylloc->source = 0; \ + yylloc->source = "0"; \ } while(0) %} @@ -84,7 +84,7 @@ strings, we have to be careful to avoid OTHER matching and hiding something that CPP does care about. So we simply exclude all characters that appear in any other expressions. */ -OTHER [^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,=+-] +OTHER [^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,="+-] DIGITS [0-9][0-9]* DECIMAL_INTEGER [1-9][0-9]*[uU]? @@ -120,6 +120,11 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? return SPACE; } +\"(\\.|[^\\"\n])*\" { + yylval->str = ralloc_strdup (yyextra, yytext); + return STRING_LITERAL; +} + {HASH}version { yylval->str = ralloc_strdup (yyextra, yytext); yyextra->space_tokens = 0; diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index bdf7e17..7d7499d 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -164,10 +164,10 @@ 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_IDENTIFIER OBJ_IDENTIFIER 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 COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER 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 STRING_LITERAL %token PASTE %type <ival> expression INTEGER operator SPACE integer_constant -%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER +%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER STRING_LITERAL %type <string_list> identifier_list %type <token> preprocessing_token conditional_token %type <token_list> pp_tokens replacement_list text_line conditional_tokens @@ -229,13 +229,25 @@ expanded_line: | 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; + parser->has_new_source = 1; + parser->new_source = ralloc_asprintf (parser, "%" PRIiMAX, $3); ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#line %" PRIiMAX " %" PRIiMAX "\n", $2, $3); } +| LINE_EXPANDED integer_constant STRING_LITERAL NEWLINE { + if (parser->is_gles) + glcpp_error(& @1, parser, "#line with non-numeric source number (illegal in GLES)"); + parser->has_new_line_number = 1; + parser->new_line_number = $2; + parser->has_new_source = 1; + parser->new_source = $3; + ralloc_asprintf_rewrite_tail (&parser->output, + &parser->output_length, + "#line %" PRIiMAX " %s\n", + $2, $3); + } ; control_line: @@ -542,6 +554,10 @@ preprocessing_token: $$ = _token_create_ival (parser, SPACE, SPACE); $$->location = yylloc; } +| STRING_LITERAL { + $$ = _token_create_str (parser, STRING_LITERAL, $1); + $$->location = yylloc; + } ; operator: @@ -913,6 +929,7 @@ _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b) case IDENTIFIER: case INTEGER_STRING: case OTHER: + case STRING_LITERAL: if (strcmp (node_a->token->value.str, node_b->token->value.str)) { @@ -943,6 +960,7 @@ _token_print (char **out, size_t *len, token_t *token) case IDENTIFIER: case INTEGER_STRING: case OTHER: + case STRING_LITERAL: ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str); break; case SPACE: @@ -1053,8 +1071,8 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) * valid, single pre-processing token. For example, pasting * "123" and "abc" is not legal, but we don't catch that * here. */ - if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) && - (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING)) + if ((token->type == IDENTIFIER || token->type == OTHER || token->type == STRING_LITERAL || token->type == INTEGER_STRING) && + (other->type == IDENTIFIER || other->type == OTHER || other->type == STRING_LITERAL || other->type == INTEGER_STRING)) { char *str; @@ -1137,8 +1155,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) parser->has_new_line_number = 0; parser->new_line_number = 1; - parser->has_new_source_number = 0; - parser->new_source_number = 0; + parser->has_new_source = 0; + parser->new_source = "0"; parser->is_gles = false; diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h index 03a77b7..b564177 100644 --- a/src/glsl/glcpp/glcpp.h +++ b/src/glsl/glcpp/glcpp.h @@ -65,7 +65,7 @@ typedef struct YYLTYPE { int first_column; int last_line; int last_column; - unsigned source; + const char *source; } YYLTYPE; # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 @@ -86,7 +86,7 @@ do { \ (Current).first_column = (Current).last_column = \ YYRHSLOC(Rhs, 0).last_column; \ } \ - (Current).source = 0; \ + (Current).source = "0"; \ } while (0) struct token { @@ -180,8 +180,8 @@ struct glcpp_parser { int error; bool has_new_line_number; int new_line_number; - bool has_new_source_number; - int new_source_number; + bool has_new_source; + const char *new_source; bool is_gles; }; diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c index 11b2941..6062150 100644 --- a/src/glsl/glcpp/pp.c +++ b/src/glsl/glcpp/pp.c @@ -35,7 +35,7 @@ glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) parser->error = 1; ralloc_asprintf_rewrite_tail(&parser->info_log, &parser->info_log_length, - "%u:%u(%u): " + "%s:%u(%u): " "preprocessor error: ", locp->source, locp->first_line, @@ -56,7 +56,7 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) ralloc_asprintf_rewrite_tail(&parser->info_log, &parser->info_log_length, - "%u:%u(%u): " + "%s:%u(%u): " "preprocessor warning: ", locp->source, locp->first_line, -- 1.7.10 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev