glcpp: Don't use infinite lookhead for #define differentiation.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 22 Oct 2012 17:56:46 +0000 (10:56 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 25 Oct 2012 21:52:53 +0000 (14:52 -0700)
Previously, we used lookahead patterns to differentiate:

   #define FOO(x)  function macro
   #define FOO (x) object macro

Unfortunately, our rule for function macros:

   {HASH}define{HSPACE}+/{IDENTIFIER}"("

relies on infinite lookahead, and apparently triggers a Flex bug where
the generated code overflows a state buffer (see YY_STATE_BUF_SIZE).

There's no need to use infinite lookahead.  We can simply change state,
match the identifier, and use a single character lookahead for the '('.
This apparently makes Flex not generate the giant state array, which
avoids the buffer overflow, and should be more efficient anyway.

Fixes piglit test 17000-consecutive-chars-identifier.frag.

NOTE: This is a candidate for every release branch ever.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Carl Worth <cworth@cworth.org>
src/glsl/glcpp/glcpp-lex.l
src/glsl/glcpp/glcpp-parse.y

index 7ab58cb288da6dec633a6bc5a2c209672bb2aea1..783c545495e3848ed13175600a968c2bde89bc91 100644 (file)
@@ -67,7 +67,7 @@ void glcpp_set_column (int  column_no , yyscan_t yyscanner);
 %option stack
 %option never-interactive
 
-%x DONE COMMENT UNREACHABLE SKIP
+%x DONE COMMENT UNREACHABLE SKIP DEFINE
 
 SPACE          [[:space:]]
 NONSPACE       [^[:space:]]
@@ -184,14 +184,22 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
        glcpp_error(yylloc, yyextra, "#error%s", p);
 }
 
-{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
+{HASH}define{HSPACE}+ {
        yyextra->space_tokens = 0;
-       return HASH_DEFINE_FUNC;
+       yy_push_state(DEFINE, yyscanner);
+       return HASH_DEFINE;
 }
 
-{HASH}define {
-       yyextra->space_tokens = 0;
-       return HASH_DEFINE_OBJ;
+<DEFINE>{IDENTIFIER}/"(" {
+       yy_pop_state(yyscanner);
+       yylval->str = ralloc_strdup (yyextra, yytext);
+       return FUNC_IDENTIFIER;
+}
+
+<DEFINE>{IDENTIFIER} {
+       yy_pop_state(yyscanner);
+       yylval->str = ralloc_strdup (yyextra, yytext);
+       return OBJ_IDENTIFIER;
 }
 
 {HASH}undef {
index fb9bc588ef80f4beae5b83f084e1af957290a48e..ffb48e330b0235d62ffd716dbd2a9209344b803e 100644 (file)
@@ -160,10 +160,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 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 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 PASTE
 %type <ival> expression INTEGER operator SPACE integer_constant
-%type <str> IDENTIFIER INTEGER_STRING OTHER
+%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER
 %type <string_list> identifier_list
 %type <token> preprocessing_token conditional_token
 %type <token_list> pp_tokens replacement_list text_line conditional_tokens
@@ -227,13 +227,13 @@ expanded_line:
 ;
 
 control_line:
-       HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+       HASH_DEFINE OBJ_IDENTIFIER replacement_list NEWLINE {
                _define_object_macro (parser, & @2, $2, $3);
        }
-|      HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
+|      HASH_DEFINE FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
                _define_function_macro (parser, & @2, $2, NULL, $5);
        }
-|      HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+|      HASH_DEFINE FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
                _define_function_macro (parser, & @2, $2, $4, $6);
        }
 |      HASH_UNDEF IDENTIFIER NEWLINE {
@@ -1843,7 +1843,7 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
                        if (ret == NEWLINE)
                                parser->in_control_line = 0;
                }
-               else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+               else if (ret == HASH_DEFINE ||
                           ret == HASH_UNDEF || ret == HASH_IF ||
                           ret == HASH_IFDEF || ret == HASH_IFNDEF ||
                           ret == HASH_ELIF || ret == HASH_ELSE ||