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 --- src/glsl/glcpp/glcpp-lex.l | 28 ++++++++++++++---- src/glsl/glcpp/glcpp-parse.y | 64 ++++++++++++++++++++++++++++++++++-------- src/glsl/glcpp/glcpp.h | 8 +++--- src/glsl/glcpp/pp.c | 4 +-- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l index fd28711..a6171cc 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,24 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? return SPACE; } +\"(\\.|[^\\"\n])*\" { + /* Drop the quotation marks when returning a string's literal value. + * + * Note: A truly *correct* solution would also interpret any + * escape sequences within the string. We intentionally don't + * do this. The rationale is for code savings and the + * justification is that strings aren't actually part of the + * GLSL language. We're only parsing them as a convenience for + * use in '#line XX "foo.c"' and even that isn't part of the + * specification. So, for this limited use case of filenames, + * escape sequences shouldn't be common, and when they are, + * users can deal with the un-interpreted escape sequence + * appearing in the filename in error messages. + */ + yylval->str = ralloc_strndup (yyextra, yytext + 1, strlen(yytext) - 2); + return STRING_LITERAL; +} + {HASH}version{HSPACE}+ { 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 380a1d9..eaf01cd 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,27 @@ 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 0 + if (parser->is_gles) + glcpp_error(& @1, parser, "#line with non-numeric source number (illegal in GLES)"); +#endif + 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: @@ -540,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: @@ -911,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)) { @@ -938,6 +957,9 @@ _token_print (char **out, size_t *len, token_t *token) case INTEGER: ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival); break; + case STRING_LITERAL: + ralloc_asprintf_rewrite_tail (out, len, "\"%s\"", token->value.str); + break; case IDENTIFIER: case INTEGER_STRING: case OTHER: @@ -1052,8 +1074,8 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) * the second token must also be an integer or must be a * string representing an integer that begins with a digit. */ - if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) && - (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER)) + if ((token->type == IDENTIFIER || token->type == OTHER || token->type == STRING_LITERAL || token->type == INTEGER_STRING || token->type == INTEGER) && + (other->type == IDENTIFIER || other->type == OTHER || other->type == STRING_LITERAL || INTEGER_STRING || other->type == INTEGER)) { char *str; int combined_type; @@ -1064,6 +1086,8 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) if (token->type == INTEGER_STRING || token->type == INTEGER) { switch (other->type) { + case OTHER: + case STRING_LITERAL: case INTEGER_STRING: if (other->value.str[0] < '0' || other->value.str[0] > '9') @@ -1176,8 +1200,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"; /* Add pre-defined macros. */ if (extensions != NULL) { @@ -1330,19 +1354,35 @@ _arguments_parse (argument_list_t *arguments, } static token_list_t * -_token_list_create_with_one_ival (void *ctx, int type, int ival) +_token_list_create_with_one_node (void *ctx, token_t *node) { token_list_t *list; - token_t *node; list = _token_list_create (ctx); - node = _token_create_ival (list, type, ival); _token_list_append (list, node); return list; } static token_list_t * +_token_list_create_with_one_ival (void *ctx, int type, int ival) +{ + token_t *node; + + node = _token_create_ival (ctx, type, ival); + return _token_list_create_with_one_node (ctx, node); +} + +static token_list_t * +_token_list_create_with_one_string (void *ctx, int type, const char *str) +{ + token_t *node; + + node = _token_create_str (ctx, type, ralloc_strdup (ctx, str)); + return _token_list_create_with_one_node (ctx, node); +} + +static token_list_t * _token_list_create_with_one_space (void *ctx) { return _token_list_create_with_one_ival (ctx, SPACE, SPACE); @@ -1579,7 +1619,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, return _token_list_create_with_one_integer (parser, node->token->location.first_line); if (strcmp(identifier, "__FILE__") == 0) - return _token_list_create_with_one_integer (parser, node->token->location.source); + return _token_list_create_with_one_string (parser, OTHER, node->token->location.source); /* Look up this identifier in the hash table. */ macro = hash_table_find (parser->defines, identifier); diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h index cdcbdfe..09f711c 100644 --- a/src/glsl/glcpp/glcpp.h +++ b/src/glsl/glcpp/glcpp.h @@ -67,7 +67,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 @@ -88,7 +88,7 @@ do { \ (Current).first_column = (Current).last_column = \ YYRHSLOC(Rhs, 0).last_column; \ } \ - (Current).source = 0; \ + (Current).source = "0"; \ } while (0) struct token { @@ -182,8 +182,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; }; struct gl_extensions; diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c index 789f7f9..4a43a9c 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