glcpp: Flag invalid pastes for integer followed by non-digits
[mesa.git] / src / glsl / glcpp / glcpp-parse.y
index ee0018016d76a095c52d5df92170d99651d7833c..8f17d0d8ab3196c471238dae79ad026c001e9520 100644 (file)
@@ -133,8 +133,6 @@ _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
 static void
 _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
 
-#define yylex glcpp_parser_lex
-
 static int
 glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
 
@@ -162,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_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING 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
@@ -192,6 +190,14 @@ line:
        control_line {
                ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
        }
+|      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);
+               }
+       }
 |      text_line {
                _glcpp_parser_print_expanded_token_list (parser, $1);
                ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
@@ -208,16 +214,34 @@ 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 "\n",
+                                             $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 "\n",
+                                             $2, $3);
+       }
 ;
 
 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 {
@@ -303,12 +327,12 @@ control_line:
                        glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
                }
        }
-|      HASH_ELSE NEWLINE {
+|      HASH_ELSE {
                _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
-       }
-|      HASH_ENDIF NEWLINE {
+       } NEWLINE
+|      HASH_ENDIF {
                _glcpp_parser_skip_stack_pop (parser, & @1);
-       }
+       } NEWLINE
 |      HASH_VERSION integer_constant NEWLINE {
                macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
                if (macro) {
@@ -1033,16 +1057,23 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
        /* Two string-valued tokens can usually just be mashed
         * together.
         *
-        * XXX: This isn't actually legitimate. Several things here
-        * should result in a diagnostic since the result cannot be a
-        * valid, single pre-processing token. For example, pasting
-        * "123" and "abc" is not legal, but we don't catch that
-        * here. */
+        * There are some exceptions here. Notably, if the first token
+        * is a string representing an integer, then the second token
+        * must also be a an integer and must begin with a digit.
+        */
        if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
            (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
        {
                char *str;
 
+               if (token->type == INTEGER_STRING) {
+                       if (other->type != INTEGER_STRING)
+                               goto FAIL;
+                       if (other->value.str[0] < '0' ||
+                           other->value.str[0] > '9')
+                               goto FAIL;
+               }
+
                str = ralloc_asprintf (token, "%s%s", token->value.str,
                                       other->value.str);
                combined = _token_create_str (token, token->type, str);
@@ -1050,6 +1081,7 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
                return combined;
        }
 
+    FAIL:
        glcpp_error (&token->location, parser, "");
        ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \"");
        _token_print (&parser->info_log, &parser->info_log_length, token);
@@ -1120,41 +1152,55 @@ 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);
+       if (extensions != NULL) {
+          if (extensions->OES_EGL_image_external)
+             add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
+       }
 
        if (api == API_OPENGLES2)
                add_builtin_define(parser, "GL_ES", 1);
+       else {
+          add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+          add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
 
-       if (extensions != NULL) {
-          if (extensions->EXT_texture_array) {
-             add_builtin_define(parser, "GL_EXT_texture_array", 1);
-          }
+          if (extensions != NULL) {
+             if (extensions->EXT_texture_array) {
+                add_builtin_define(parser, "GL_EXT_texture_array", 1);
+             }
 
-          if (extensions->ARB_fragment_coord_conventions)
-             add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
-                                1);
+             if (extensions->ARB_fragment_coord_conventions)
+                add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+                                   1);
 
-          if (extensions->ARB_explicit_attrib_location)
-             add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+             if (extensions->ARB_explicit_attrib_location)
+                add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
 
-          if (extensions->ARB_shader_texture_lod)
-             add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
+             if (extensions->ARB_shader_texture_lod)
+                add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
 
-          if (extensions->ARB_draw_instanced)
-             add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
+             if (extensions->ARB_draw_instanced)
+                add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
 
-          if (extensions->ARB_conservative_depth) {
-             add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
-             add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
-          }
+             if (extensions->ARB_conservative_depth) {
+                add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
+                add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
+             }
 
-          if (extensions->OES_EGL_image_external)
-             add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
+             if (extensions->ARB_shader_bit_encoding)
+                add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
 
-          if (extensions->ARB_shader_bit_encoding)
-             add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
+             if (extensions->ARB_uniform_buffer_object)
+                add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1);
+
+             if (extensions->ARB_texture_cube_map_array)
+                add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1);
+          }
        }
 
        language_version = 110;
@@ -1163,12 +1209,6 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
        return parser;
 }
 
-int
-glcpp_parser_parse (glcpp_parser_t *parser)
-{
-       return yyparse (parser);
-}
-
 void
 glcpp_parser_destroy (glcpp_parser_t *parser)
 {
@@ -1268,18 +1308,30 @@ _arguments_parse (argument_list_t *arguments,
 }
 
 static token_list_t *
-_token_list_create_with_one_space (void *ctx)
+_token_list_create_with_one_ival (void *ctx, int type, int ival)
 {
        token_list_t *list;
-       token_t *space;
+       token_t *node;
 
        list = _token_list_create (ctx);
-       space = _token_create_ival (list, SPACE, SPACE);
-       _token_list_append (list, space);
+       node = _token_create_ival (list, type, ival);
+       _token_list_append (list, node);
 
        return list;
 }
 
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+       return _token_list_create_with_one_ival (ctx, SPACE, SPACE);
+}
+
+static token_list_t *
+_token_list_create_with_one_integer (void *ctx, int ival)
+{
+       return _token_list_create_with_one_ival (ctx, INTEGER, ival);
+}
+
 /* Perform macro expansion on 'list', placing the resulting tokens
  * into a new list which is initialized with a first token of type
  * 'head_token_type'. Then begin lexing from the resulting list,
@@ -1496,8 +1548,18 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
                return NULL;
        }
 
-       /* Look up this identifier in the hash table. */
+       *last = node;
        identifier = token->value.str;
+
+       /* Special handling for __LINE__ and __FILE__, (not through
+        * the hash table). */
+       if (strcmp(identifier, "__LINE__") == 0)
+               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);
+
+       /* Look up this identifier in the hash table. */
        macro = hash_table_find (parser->defines, identifier);
 
        /* Not a macro, so no expansion needed. */
@@ -1518,14 +1580,12 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
                final = _token_create_str (parser, OTHER, str);
                expansion = _token_list_create (parser);
                _token_list_append (expansion, final);
-               *last = node;
                return expansion;
        }
 
        if (! macro->is_function)
        {
                token_list_t *replacement;
-               *last = node;
 
                /* Replace a macro defined as empty with a SPACE token. */
                if (macro->replacements == NULL)
@@ -1817,7 +1877,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 ||