On 06/09/2012 04:41 PM, Carl Worth wrote:
> 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.
> ---
>  src/glsl/glcpp/glcpp-lex.l                    |   49 
> +++++++------------------
>  src/glsl/glcpp/glcpp-parse.y                  |   33 ++++++++++++++++-
>  src/glsl/glcpp/glcpp.h                        |    4 ++
>  src/glsl/glcpp/tests/091-hash-line.c.expected |    8 ++--
>  4 files changed, 54 insertions(+), 40 deletions(-)

Hi Carl,

Sorry for the extremely late review.  (Lost this one in the inbox.)
Comments below...

> diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
> index b34f2c0..7ab58cb 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;     \

Could yylineno and yylloc->source be set directly from the rules, rather
than using flags and setting them here?  It seems like they could, but I
imagine you tried that and it doesn't work.

> +             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;
>  }
>  
>  <SKIP,INITIAL>{
> diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
> index ee00180..cc4af16 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 <ival> expression INTEGER operator SPACE integer_constant
>  %type <str> 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);
> +             }
> +     }

Hm.  I originally thought #line took effect regardless of any #if trees,
but it looks like that's not the case.  Feeding GCC's cpp the following
yields 20, and no mention of 10:

#ifdef FOO
#line 10
#else
#line 20
#endif

So I think this is right.

>  |    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 2d7cad2..9d4005c 100644
> --- a/src/glsl/glcpp/glcpp.h
> +++ b/src/glsl/glcpp/glcpp.h
> @@ -177,6 +177,10 @@ struct glcpp_parser {
>       size_t output_length;
>       size_t info_log_length;
>       int error;
> +     int has_new_line_number;
> +     int new_line_number;
> +     int has_new_source_number;
> +     int new_source_number;
>  };

Could you please #include <stdbool.h> and use 'bool' instead of 'int'
for the has_* variables?  This is not only a bit nicer to read, it
causes the compiler to generate proper warnings if you do something
silly like assign GL_FLAT to a boolean.

>  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 e663398..ea29149 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

Other than those minor comments, this looks good.  Thanks for doing
this!  Way better than my hack.

For the series:
Reviewed-by: Kenneth Graunke <kenn...@whitecape.org>
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to