1b8e80941Smrg%{ 2b8e80941Smrg/* 3b8e80941Smrg * Copyright © 2010 Intel Corporation 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg * to deal in the Software without restriction, including without limitation 8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 10b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg * 12b8e80941Smrg * The above copyright notice and this permission notice (including the next 13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg * Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22b8e80941Smrg * DEALINGS IN THE SOFTWARE. 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg#include <stdio.h> 26b8e80941Smrg#include <stdlib.h> 27b8e80941Smrg#include <string.h> 28b8e80941Smrg#include <assert.h> 29b8e80941Smrg#include <inttypes.h> 30b8e80941Smrg 31b8e80941Smrg#include "glcpp.h" 32b8e80941Smrg#include "main/mtypes.h" 33b8e80941Smrg 34b8e80941Smrgstatic void 35b8e80941Smrgyyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error); 36b8e80941Smrg 37b8e80941Smrgstatic void 38b8e80941Smrg_define_object_macro(glcpp_parser_t *parser, 39b8e80941Smrg YYLTYPE *loc, 40b8e80941Smrg const char *macro, 41b8e80941Smrg token_list_t *replacements); 42b8e80941Smrg 43b8e80941Smrgstatic void 44b8e80941Smrg_define_function_macro(glcpp_parser_t *parser, 45b8e80941Smrg YYLTYPE *loc, 46b8e80941Smrg const char *macro, 47b8e80941Smrg string_list_t *parameters, 48b8e80941Smrg token_list_t *replacements); 49b8e80941Smrg 50b8e80941Smrgstatic string_list_t * 51b8e80941Smrg_string_list_create(glcpp_parser_t *parser); 52b8e80941Smrg 53b8e80941Smrgstatic void 54b8e80941Smrg_string_list_append_item(glcpp_parser_t *parser, string_list_t *list, 55b8e80941Smrg const char *str); 56b8e80941Smrg 57b8e80941Smrgstatic int 58b8e80941Smrg_string_list_contains(string_list_t *list, const char *member, int *index); 59b8e80941Smrg 60b8e80941Smrgstatic const char * 61b8e80941Smrg_string_list_has_duplicate(string_list_t *list); 62b8e80941Smrg 63b8e80941Smrgstatic int 64b8e80941Smrg_string_list_length(string_list_t *list); 65b8e80941Smrg 66b8e80941Smrgstatic int 67b8e80941Smrg_string_list_equal(string_list_t *a, string_list_t *b); 68b8e80941Smrg 69b8e80941Smrgstatic argument_list_t * 70b8e80941Smrg_argument_list_create(glcpp_parser_t *parser); 71b8e80941Smrg 72b8e80941Smrgstatic void 73b8e80941Smrg_argument_list_append(glcpp_parser_t *parser, argument_list_t *list, 74b8e80941Smrg token_list_t *argument); 75b8e80941Smrg 76b8e80941Smrgstatic int 77b8e80941Smrg_argument_list_length(argument_list_t *list); 78b8e80941Smrg 79b8e80941Smrgstatic token_list_t * 80b8e80941Smrg_argument_list_member_at(argument_list_t *list, int index); 81b8e80941Smrg 82b8e80941Smrgstatic token_t * 83b8e80941Smrg_token_create_str(glcpp_parser_t *parser, int type, char *str); 84b8e80941Smrg 85b8e80941Smrgstatic token_t * 86b8e80941Smrg_token_create_ival(glcpp_parser_t *parser, int type, int ival); 87b8e80941Smrg 88b8e80941Smrgstatic token_list_t * 89b8e80941Smrg_token_list_create(glcpp_parser_t *parser); 90b8e80941Smrg 91b8e80941Smrgstatic void 92b8e80941Smrg_token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token); 93b8e80941Smrg 94b8e80941Smrgstatic void 95b8e80941Smrg_token_list_append_list(token_list_t *list, token_list_t *tail); 96b8e80941Smrg 97b8e80941Smrgstatic int 98b8e80941Smrg_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b); 99b8e80941Smrg 100b8e80941Smrgstatic void 101b8e80941Smrg_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, 102b8e80941Smrg token_node_t *marker); 103b8e80941Smrg 104b8e80941Smrgstatic void 105b8e80941Smrg_parser_active_list_pop(glcpp_parser_t *parser); 106b8e80941Smrg 107b8e80941Smrgstatic int 108b8e80941Smrg_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier); 109b8e80941Smrg 110b8e80941Smrgtypedef enum { 111b8e80941Smrg EXPANSION_MODE_IGNORE_DEFINED, 112b8e80941Smrg EXPANSION_MODE_EVALUATE_DEFINED 113b8e80941Smrg} expansion_mode_t; 114b8e80941Smrg 115b8e80941Smrg/* Expand list, and begin lexing from the result (after first 116b8e80941Smrg * prefixing a token of type 'head_token_type'). 117b8e80941Smrg */ 118b8e80941Smrgstatic void 119b8e80941Smrg_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, 120b8e80941Smrg token_list_t *list, expansion_mode_t mode); 121b8e80941Smrg 122b8e80941Smrg/* Perform macro expansion in-place on the given list. */ 123b8e80941Smrgstatic void 124b8e80941Smrg_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, 125b8e80941Smrg expansion_mode_t mode); 126b8e80941Smrg 127b8e80941Smrgstatic void 128b8e80941Smrg_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, 129b8e80941Smrg token_list_t *list); 130b8e80941Smrg 131b8e80941Smrgstatic void 132b8e80941Smrg_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, 133b8e80941Smrg int condition); 134b8e80941Smrg 135b8e80941Smrgstatic void 136b8e80941Smrg_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, 137b8e80941Smrg const char *type, int condition); 138b8e80941Smrg 139b8e80941Smrgstatic void 140b8e80941Smrg_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc); 141b8e80941Smrg 142b8e80941Smrgstatic void 143b8e80941Smrg_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, 144b8e80941Smrg const char *ident, bool explicitly_set); 145b8e80941Smrg 146b8e80941Smrgstatic int 147b8e80941Smrgglcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); 148b8e80941Smrg 149b8e80941Smrgstatic void 150b8e80941Smrgglcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list); 151b8e80941Smrg 152b8e80941Smrgstatic void 153b8e80941Smrgadd_builtin_define(glcpp_parser_t *parser, const char *name, int value); 154b8e80941Smrg 155b8e80941Smrg%} 156b8e80941Smrg 157b8e80941Smrg%pure-parser 158b8e80941Smrg%error-verbose 159b8e80941Smrg 160b8e80941Smrg%locations 161b8e80941Smrg%initial-action { 162b8e80941Smrg @$.first_line = 1; 163b8e80941Smrg @$.first_column = 1; 164b8e80941Smrg @$.last_line = 1; 165b8e80941Smrg @$.last_column = 1; 166b8e80941Smrg @$.source = 0; 167b8e80941Smrg} 168b8e80941Smrg 169b8e80941Smrg%parse-param {glcpp_parser_t *parser} 170b8e80941Smrg%lex-param {glcpp_parser_t *parser} 171b8e80941Smrg 172b8e80941Smrg%expect 0 173b8e80941Smrg 174b8e80941Smrg /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to 175b8e80941Smrg * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols, 176b8e80941Smrg * (such as the <HASH> and <DEFINE> start conditions in the lexer). */ 177b8e80941Smrg%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS 178b8e80941Smrg%token PASTE 179b8e80941Smrg%type <ival> INTEGER operator SPACE integer_constant version_constant 180b8e80941Smrg%type <expression_value> expression 181b8e80941Smrg%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA 182b8e80941Smrg%type <string_list> identifier_list 183b8e80941Smrg%type <token> preprocessing_token 184b8e80941Smrg%type <token_list> pp_tokens replacement_list text_line 185b8e80941Smrg%left OR 186b8e80941Smrg%left AND 187b8e80941Smrg%left '|' 188b8e80941Smrg%left '^' 189b8e80941Smrg%left '&' 190b8e80941Smrg%left EQUAL NOT_EQUAL 191b8e80941Smrg%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL 192b8e80941Smrg%left LEFT_SHIFT RIGHT_SHIFT 193b8e80941Smrg%left '+' '-' 194b8e80941Smrg%left '*' '/' '%' 195b8e80941Smrg%right UNARY 196b8e80941Smrg 197b8e80941Smrg%debug 198b8e80941Smrg 199b8e80941Smrg%% 200b8e80941Smrg 201b8e80941Smrginput: 202b8e80941Smrg /* empty */ 203b8e80941Smrg| input line 204b8e80941Smrg; 205b8e80941Smrg 206b8e80941Smrgline: 207b8e80941Smrg control_line 208b8e80941Smrg| SPACE control_line 209b8e80941Smrg| text_line { 210b8e80941Smrg _glcpp_parser_print_expanded_token_list (parser, $1); 211b8e80941Smrg _mesa_string_buffer_append_char(parser->output, '\n'); 212b8e80941Smrg } 213b8e80941Smrg| expanded_line 214b8e80941Smrg; 215b8e80941Smrg 216b8e80941Smrgexpanded_line: 217b8e80941Smrg IF_EXPANDED expression NEWLINE { 218b8e80941Smrg if (parser->is_gles && $2.undefined_macro) 219b8e80941Smrg glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro); 220b8e80941Smrg _glcpp_parser_skip_stack_push_if (parser, & @1, $2.value); 221b8e80941Smrg } 222b8e80941Smrg| ELIF_EXPANDED expression NEWLINE { 223b8e80941Smrg if (parser->is_gles && $2.undefined_macro) 224b8e80941Smrg glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro); 225b8e80941Smrg _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2.value); 226b8e80941Smrg } 227b8e80941Smrg| LINE_EXPANDED integer_constant NEWLINE { 228b8e80941Smrg parser->has_new_line_number = 1; 229b8e80941Smrg parser->new_line_number = $2; 230b8e80941Smrg _mesa_string_buffer_printf(parser->output, "#line %" PRIiMAX "\n", $2); 231b8e80941Smrg } 232b8e80941Smrg| LINE_EXPANDED integer_constant integer_constant NEWLINE { 233b8e80941Smrg parser->has_new_line_number = 1; 234b8e80941Smrg parser->new_line_number = $2; 235b8e80941Smrg parser->has_new_source_number = 1; 236b8e80941Smrg parser->new_source_number = $3; 237b8e80941Smrg _mesa_string_buffer_printf(parser->output, 238b8e80941Smrg "#line %" PRIiMAX " %" PRIiMAX "\n", 239b8e80941Smrg $2, $3); 240b8e80941Smrg } 241b8e80941Smrg; 242b8e80941Smrg 243b8e80941Smrgdefine: 244b8e80941Smrg OBJ_IDENTIFIER replacement_list NEWLINE { 245b8e80941Smrg _define_object_macro (parser, & @1, $1, $2); 246b8e80941Smrg } 247b8e80941Smrg| FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE { 248b8e80941Smrg _define_function_macro (parser, & @1, $1, NULL, $4); 249b8e80941Smrg } 250b8e80941Smrg| FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE { 251b8e80941Smrg _define_function_macro (parser, & @1, $1, $3, $5); 252b8e80941Smrg } 253b8e80941Smrg; 254b8e80941Smrg 255b8e80941Smrgcontrol_line: 256b8e80941Smrg control_line_success { 257b8e80941Smrg _mesa_string_buffer_append_char(parser->output, '\n'); 258b8e80941Smrg } 259b8e80941Smrg| control_line_error 260b8e80941Smrg| HASH_TOKEN LINE pp_tokens NEWLINE { 261b8e80941Smrg 262b8e80941Smrg if (parser->skip_stack == NULL || 263b8e80941Smrg parser->skip_stack->type == SKIP_NO_SKIP) 264b8e80941Smrg { 265b8e80941Smrg _glcpp_parser_expand_and_lex_from (parser, 266b8e80941Smrg LINE_EXPANDED, $3, 267b8e80941Smrg EXPANSION_MODE_IGNORE_DEFINED); 268b8e80941Smrg } 269b8e80941Smrg } 270b8e80941Smrg; 271b8e80941Smrg 272b8e80941Smrgcontrol_line_success: 273b8e80941Smrg HASH_TOKEN DEFINE_TOKEN define 274b8e80941Smrg| HASH_TOKEN UNDEF IDENTIFIER NEWLINE { 275b8e80941Smrg struct hash_entry *entry; 276b8e80941Smrg 277b8e80941Smrg /* Section 3.4 (Preprocessor) of the GLSL ES 3.00 spec says: 278b8e80941Smrg * 279b8e80941Smrg * It is an error to undefine or to redefine a built-in 280b8e80941Smrg * (pre-defined) macro name. 281b8e80941Smrg * 282b8e80941Smrg * The GLSL ES 1.00 spec does not contain this text, but 283b8e80941Smrg * dEQP's preprocess test in GLES2 checks for it. 284b8e80941Smrg * 285b8e80941Smrg * Section 3.3 (Preprocessor) revision 7, of the GLSL 4.50 286b8e80941Smrg * spec says: 287b8e80941Smrg * 288b8e80941Smrg * By convention, all macro names containing two consecutive 289b8e80941Smrg * underscores ( __ ) are reserved for use by underlying 290b8e80941Smrg * software layers. Defining or undefining such a name 291b8e80941Smrg * in a shader does not itself result in an error, but may 292b8e80941Smrg * result in unintended behaviors that stem from having 293b8e80941Smrg * multiple definitions of the same name. All macro names 294b8e80941Smrg * prefixed with "GL_" (...) are also reseved, and defining 295b8e80941Smrg * such a name results in a compile-time error. 296b8e80941Smrg * 297b8e80941Smrg * The code below implements the same checks as GLSLang. 298b8e80941Smrg */ 299b8e80941Smrg if (strncmp("GL_", $3, 3) == 0) 300b8e80941Smrg glcpp_error(& @1, parser, "Built-in (pre-defined)" 301b8e80941Smrg " names beginning with GL_ cannot be undefined."); 302b8e80941Smrg else if (strstr($3, "__") != NULL) { 303b8e80941Smrg if (parser->is_gles 304b8e80941Smrg && parser->version >= 300 305b8e80941Smrg && (strcmp("__LINE__", $3) == 0 306b8e80941Smrg || strcmp("__FILE__", $3) == 0 307b8e80941Smrg || strcmp("__VERSION__", $3) == 0)) { 308b8e80941Smrg glcpp_error(& @1, parser, "Built-in (pre-defined)" 309b8e80941Smrg " names cannot be undefined."); 310b8e80941Smrg } else if (parser->is_gles && parser->version <= 300) { 311b8e80941Smrg glcpp_error(& @1, parser, 312b8e80941Smrg " names containing consecutive underscores" 313b8e80941Smrg " are reserved."); 314b8e80941Smrg } else { 315b8e80941Smrg glcpp_warning(& @1, parser, 316b8e80941Smrg " names containing consecutive underscores" 317b8e80941Smrg " are reserved."); 318b8e80941Smrg } 319b8e80941Smrg } 320b8e80941Smrg 321b8e80941Smrg entry = _mesa_hash_table_search (parser->defines, $3); 322b8e80941Smrg if (entry) { 323b8e80941Smrg _mesa_hash_table_remove (parser->defines, entry); 324b8e80941Smrg } 325b8e80941Smrg } 326b8e80941Smrg| HASH_TOKEN IF pp_tokens NEWLINE { 327b8e80941Smrg /* Be careful to only evaluate the 'if' expression if 328b8e80941Smrg * we are not skipping. When we are skipping, we 329b8e80941Smrg * simply push a new 0-valued 'if' onto the skip 330b8e80941Smrg * stack. 331b8e80941Smrg * 332b8e80941Smrg * This avoids generating diagnostics for invalid 333b8e80941Smrg * expressions that are being skipped. */ 334b8e80941Smrg if (parser->skip_stack == NULL || 335b8e80941Smrg parser->skip_stack->type == SKIP_NO_SKIP) 336b8e80941Smrg { 337b8e80941Smrg _glcpp_parser_expand_and_lex_from (parser, 338b8e80941Smrg IF_EXPANDED, $3, 339b8e80941Smrg EXPANSION_MODE_EVALUATE_DEFINED); 340b8e80941Smrg } 341b8e80941Smrg else 342b8e80941Smrg { 343b8e80941Smrg _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 344b8e80941Smrg parser->skip_stack->type = SKIP_TO_ENDIF; 345b8e80941Smrg } 346b8e80941Smrg } 347b8e80941Smrg| HASH_TOKEN IF NEWLINE { 348b8e80941Smrg /* #if without an expression is only an error if we 349b8e80941Smrg * are not skipping */ 350b8e80941Smrg if (parser->skip_stack == NULL || 351b8e80941Smrg parser->skip_stack->type == SKIP_NO_SKIP) 352b8e80941Smrg { 353b8e80941Smrg glcpp_error(& @1, parser, "#if with no expression"); 354b8e80941Smrg } 355b8e80941Smrg _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 356b8e80941Smrg } 357b8e80941Smrg| HASH_TOKEN IFDEF IDENTIFIER junk NEWLINE { 358b8e80941Smrg struct hash_entry *entry = 359b8e80941Smrg _mesa_hash_table_search(parser->defines, $3); 360b8e80941Smrg macro_t *macro = entry ? entry->data : NULL; 361b8e80941Smrg _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); 362b8e80941Smrg } 363b8e80941Smrg| HASH_TOKEN IFNDEF IDENTIFIER junk NEWLINE { 364b8e80941Smrg struct hash_entry *entry = 365b8e80941Smrg _mesa_hash_table_search(parser->defines, $3); 366b8e80941Smrg macro_t *macro = entry ? entry->data : NULL; 367b8e80941Smrg _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL); 368b8e80941Smrg } 369b8e80941Smrg| HASH_TOKEN ELIF pp_tokens NEWLINE { 370b8e80941Smrg /* Be careful to only evaluate the 'elif' expression 371b8e80941Smrg * if we are not skipping. When we are skipping, we 372b8e80941Smrg * simply change to a 0-valued 'elif' on the skip 373b8e80941Smrg * stack. 374b8e80941Smrg * 375b8e80941Smrg * This avoids generating diagnostics for invalid 376b8e80941Smrg * expressions that are being skipped. */ 377b8e80941Smrg if (parser->skip_stack && 378b8e80941Smrg parser->skip_stack->type == SKIP_TO_ELSE) 379b8e80941Smrg { 380b8e80941Smrg _glcpp_parser_expand_and_lex_from (parser, 381b8e80941Smrg ELIF_EXPANDED, $3, 382b8e80941Smrg EXPANSION_MODE_EVALUATE_DEFINED); 383b8e80941Smrg } 384b8e80941Smrg else if (parser->skip_stack && 385b8e80941Smrg parser->skip_stack->has_else) 386b8e80941Smrg { 387b8e80941Smrg glcpp_error(& @1, parser, "#elif after #else"); 388b8e80941Smrg } 389b8e80941Smrg else 390b8e80941Smrg { 391b8e80941Smrg _glcpp_parser_skip_stack_change_if (parser, & @1, 392b8e80941Smrg "elif", 0); 393b8e80941Smrg } 394b8e80941Smrg } 395b8e80941Smrg| HASH_TOKEN ELIF NEWLINE { 396b8e80941Smrg /* #elif without an expression is an error unless we 397b8e80941Smrg * are skipping. */ 398b8e80941Smrg if (parser->skip_stack && 399b8e80941Smrg parser->skip_stack->type == SKIP_TO_ELSE) 400b8e80941Smrg { 401b8e80941Smrg glcpp_error(& @1, parser, "#elif with no expression"); 402b8e80941Smrg } 403b8e80941Smrg else if (parser->skip_stack && 404b8e80941Smrg parser->skip_stack->has_else) 405b8e80941Smrg { 406b8e80941Smrg glcpp_error(& @1, parser, "#elif after #else"); 407b8e80941Smrg } 408b8e80941Smrg else 409b8e80941Smrg { 410b8e80941Smrg _glcpp_parser_skip_stack_change_if (parser, & @1, 411b8e80941Smrg "elif", 0); 412b8e80941Smrg glcpp_warning(& @1, parser, "ignoring illegal #elif without expression"); 413b8e80941Smrg } 414b8e80941Smrg } 415b8e80941Smrg| HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE { 416b8e80941Smrg if (parser->skip_stack && 417b8e80941Smrg parser->skip_stack->has_else) 418b8e80941Smrg { 419b8e80941Smrg glcpp_error(& @1, parser, "multiple #else"); 420b8e80941Smrg } 421b8e80941Smrg else 422b8e80941Smrg { 423b8e80941Smrg _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1); 424b8e80941Smrg if (parser->skip_stack) 425b8e80941Smrg parser->skip_stack->has_else = true; 426b8e80941Smrg } 427b8e80941Smrg } 428b8e80941Smrg| HASH_TOKEN ENDIF { 429b8e80941Smrg _glcpp_parser_skip_stack_pop (parser, & @1); 430b8e80941Smrg } NEWLINE 431b8e80941Smrg| HASH_TOKEN VERSION_TOKEN version_constant NEWLINE { 432b8e80941Smrg if (parser->version_set) { 433b8e80941Smrg glcpp_error(& @1, parser, "#version must appear on the first line"); 434b8e80941Smrg } 435b8e80941Smrg _glcpp_parser_handle_version_declaration(parser, $3, NULL, true); 436b8e80941Smrg } 437b8e80941Smrg| HASH_TOKEN VERSION_TOKEN version_constant IDENTIFIER NEWLINE { 438b8e80941Smrg if (parser->version_set) { 439b8e80941Smrg glcpp_error(& @1, parser, "#version must appear on the first line"); 440b8e80941Smrg } 441b8e80941Smrg _glcpp_parser_handle_version_declaration(parser, $3, $4, true); 442b8e80941Smrg } 443b8e80941Smrg| HASH_TOKEN NEWLINE { 444b8e80941Smrg glcpp_parser_resolve_implicit_version(parser); 445b8e80941Smrg } 446b8e80941Smrg| HASH_TOKEN PRAGMA NEWLINE { 447b8e80941Smrg _mesa_string_buffer_printf(parser->output, "#%s", $2); 448b8e80941Smrg } 449b8e80941Smrg; 450b8e80941Smrg 451b8e80941Smrgcontrol_line_error: 452b8e80941Smrg HASH_TOKEN ERROR_TOKEN NEWLINE { 453b8e80941Smrg glcpp_error(& @1, parser, "#%s", $2); 454b8e80941Smrg } 455b8e80941Smrg| HASH_TOKEN DEFINE_TOKEN NEWLINE { 456b8e80941Smrg glcpp_error (& @1, parser, "#define without macro name"); 457b8e80941Smrg } 458b8e80941Smrg| HASH_TOKEN GARBAGE pp_tokens NEWLINE { 459b8e80941Smrg glcpp_error (& @1, parser, "Illegal non-directive after #"); 460b8e80941Smrg } 461b8e80941Smrg; 462b8e80941Smrg 463b8e80941Smrginteger_constant: 464b8e80941Smrg INTEGER_STRING { 465b8e80941Smrg /* let strtoll detect the base */ 466b8e80941Smrg $$ = strtoll ($1, NULL, 0); 467b8e80941Smrg } 468b8e80941Smrg| INTEGER { 469b8e80941Smrg $$ = $1; 470b8e80941Smrg } 471b8e80941Smrg 472b8e80941Smrgversion_constant: 473b8e80941Smrg INTEGER_STRING { 474b8e80941Smrg /* Both octal and hexadecimal constants begin with 0. */ 475b8e80941Smrg if ($1[0] == '0' && $1[1] != '\0') { 476b8e80941Smrg glcpp_error(&@1, parser, "invalid #version \"%s\" (not a decimal constant)", $1); 477b8e80941Smrg $$ = 0; 478b8e80941Smrg } else { 479b8e80941Smrg $$ = strtoll($1, NULL, 10); 480b8e80941Smrg } 481b8e80941Smrg } 482b8e80941Smrg 483b8e80941Smrgexpression: 484b8e80941Smrg integer_constant { 485b8e80941Smrg $$.value = $1; 486b8e80941Smrg $$.undefined_macro = NULL; 487b8e80941Smrg } 488b8e80941Smrg| IDENTIFIER { 489b8e80941Smrg $$.value = 0; 490b8e80941Smrg if (parser->is_gles) 491b8e80941Smrg $$.undefined_macro = linear_strdup(parser->linalloc, $1); 492b8e80941Smrg else 493b8e80941Smrg $$.undefined_macro = NULL; 494b8e80941Smrg } 495b8e80941Smrg| expression OR expression { 496b8e80941Smrg $$.value = $1.value || $3.value; 497b8e80941Smrg 498b8e80941Smrg /* Short-circuit: Only flag undefined from right side 499b8e80941Smrg * if left side evaluates to false. 500b8e80941Smrg */ 501b8e80941Smrg if ($1.undefined_macro) 502b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 503b8e80941Smrg else if (! $1.value) 504b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 505b8e80941Smrg } 506b8e80941Smrg| expression AND expression { 507b8e80941Smrg $$.value = $1.value && $3.value; 508b8e80941Smrg 509b8e80941Smrg /* Short-circuit: Only flag undefined from right-side 510b8e80941Smrg * if left side evaluates to true. 511b8e80941Smrg */ 512b8e80941Smrg if ($1.undefined_macro) 513b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 514b8e80941Smrg else if ($1.value) 515b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 516b8e80941Smrg } 517b8e80941Smrg| expression '|' expression { 518b8e80941Smrg $$.value = $1.value | $3.value; 519b8e80941Smrg if ($1.undefined_macro) 520b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 521b8e80941Smrg else 522b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 523b8e80941Smrg } 524b8e80941Smrg| expression '^' expression { 525b8e80941Smrg $$.value = $1.value ^ $3.value; 526b8e80941Smrg if ($1.undefined_macro) 527b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 528b8e80941Smrg else 529b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 530b8e80941Smrg } 531b8e80941Smrg| expression '&' expression { 532b8e80941Smrg $$.value = $1.value & $3.value; 533b8e80941Smrg if ($1.undefined_macro) 534b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 535b8e80941Smrg else 536b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 537b8e80941Smrg } 538b8e80941Smrg| expression NOT_EQUAL expression { 539b8e80941Smrg $$.value = $1.value != $3.value; 540b8e80941Smrg if ($1.undefined_macro) 541b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 542b8e80941Smrg else 543b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 544b8e80941Smrg } 545b8e80941Smrg| expression EQUAL expression { 546b8e80941Smrg $$.value = $1.value == $3.value; 547b8e80941Smrg if ($1.undefined_macro) 548b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 549b8e80941Smrg else 550b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 551b8e80941Smrg } 552b8e80941Smrg| expression GREATER_OR_EQUAL expression { 553b8e80941Smrg $$.value = $1.value >= $3.value; 554b8e80941Smrg if ($1.undefined_macro) 555b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 556b8e80941Smrg else 557b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 558b8e80941Smrg } 559b8e80941Smrg| expression LESS_OR_EQUAL expression { 560b8e80941Smrg $$.value = $1.value <= $3.value; 561b8e80941Smrg if ($1.undefined_macro) 562b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 563b8e80941Smrg else 564b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 565b8e80941Smrg } 566b8e80941Smrg| expression '>' expression { 567b8e80941Smrg $$.value = $1.value > $3.value; 568b8e80941Smrg if ($1.undefined_macro) 569b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 570b8e80941Smrg else 571b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 572b8e80941Smrg } 573b8e80941Smrg| expression '<' expression { 574b8e80941Smrg $$.value = $1.value < $3.value; 575b8e80941Smrg if ($1.undefined_macro) 576b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 577b8e80941Smrg else 578b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 579b8e80941Smrg } 580b8e80941Smrg| expression RIGHT_SHIFT expression { 581b8e80941Smrg $$.value = $1.value >> $3.value; 582b8e80941Smrg if ($1.undefined_macro) 583b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 584b8e80941Smrg else 585b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 586b8e80941Smrg } 587b8e80941Smrg| expression LEFT_SHIFT expression { 588b8e80941Smrg $$.value = $1.value << $3.value; 589b8e80941Smrg if ($1.undefined_macro) 590b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 591b8e80941Smrg else 592b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 593b8e80941Smrg } 594b8e80941Smrg| expression '-' expression { 595b8e80941Smrg $$.value = $1.value - $3.value; 596b8e80941Smrg if ($1.undefined_macro) 597b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 598b8e80941Smrg else 599b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 600b8e80941Smrg } 601b8e80941Smrg| expression '+' expression { 602b8e80941Smrg $$.value = $1.value + $3.value; 603b8e80941Smrg if ($1.undefined_macro) 604b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 605b8e80941Smrg else 606b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 607b8e80941Smrg } 608b8e80941Smrg| expression '%' expression { 609b8e80941Smrg if ($3.value == 0) { 610b8e80941Smrg yyerror (& @1, parser, 611b8e80941Smrg "zero modulus in preprocessor directive"); 612b8e80941Smrg } else { 613b8e80941Smrg $$.value = $1.value % $3.value; 614b8e80941Smrg } 615b8e80941Smrg if ($1.undefined_macro) 616b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 617b8e80941Smrg else 618b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 619b8e80941Smrg } 620b8e80941Smrg| expression '/' expression { 621b8e80941Smrg if ($3.value == 0) { 622b8e80941Smrg yyerror (& @1, parser, 623b8e80941Smrg "division by 0 in preprocessor directive"); 624b8e80941Smrg } else { 625b8e80941Smrg $$.value = $1.value / $3.value; 626b8e80941Smrg } 627b8e80941Smrg if ($1.undefined_macro) 628b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 629b8e80941Smrg else 630b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 631b8e80941Smrg } 632b8e80941Smrg| expression '*' expression { 633b8e80941Smrg $$.value = $1.value * $3.value; 634b8e80941Smrg if ($1.undefined_macro) 635b8e80941Smrg $$.undefined_macro = $1.undefined_macro; 636b8e80941Smrg else 637b8e80941Smrg $$.undefined_macro = $3.undefined_macro; 638b8e80941Smrg } 639b8e80941Smrg| '!' expression %prec UNARY { 640b8e80941Smrg $$.value = ! $2.value; 641b8e80941Smrg $$.undefined_macro = $2.undefined_macro; 642b8e80941Smrg } 643b8e80941Smrg| '~' expression %prec UNARY { 644b8e80941Smrg $$.value = ~ $2.value; 645b8e80941Smrg $$.undefined_macro = $2.undefined_macro; 646b8e80941Smrg } 647b8e80941Smrg| '-' expression %prec UNARY { 648b8e80941Smrg $$.value = - $2.value; 649b8e80941Smrg $$.undefined_macro = $2.undefined_macro; 650b8e80941Smrg } 651b8e80941Smrg| '+' expression %prec UNARY { 652b8e80941Smrg $$.value = + $2.value; 653b8e80941Smrg $$.undefined_macro = $2.undefined_macro; 654b8e80941Smrg } 655b8e80941Smrg| '(' expression ')' { 656b8e80941Smrg $$ = $2; 657b8e80941Smrg } 658b8e80941Smrg; 659b8e80941Smrg 660b8e80941Smrgidentifier_list: 661b8e80941Smrg IDENTIFIER { 662b8e80941Smrg $$ = _string_list_create (parser); 663b8e80941Smrg _string_list_append_item (parser, $$, $1); 664b8e80941Smrg } 665b8e80941Smrg| identifier_list ',' IDENTIFIER { 666b8e80941Smrg $$ = $1; 667b8e80941Smrg _string_list_append_item (parser, $$, $3); 668b8e80941Smrg } 669b8e80941Smrg; 670b8e80941Smrg 671b8e80941Smrgtext_line: 672b8e80941Smrg NEWLINE { $$ = NULL; } 673b8e80941Smrg| pp_tokens NEWLINE 674b8e80941Smrg; 675b8e80941Smrg 676b8e80941Smrgreplacement_list: 677b8e80941Smrg /* empty */ { $$ = NULL; } 678b8e80941Smrg| pp_tokens 679b8e80941Smrg; 680b8e80941Smrg 681b8e80941Smrgjunk: 682b8e80941Smrg /* empty */ 683b8e80941Smrg| pp_tokens { 684b8e80941Smrg glcpp_error(&@1, parser, "extra tokens at end of directive"); 685b8e80941Smrg } 686b8e80941Smrg; 687b8e80941Smrg 688b8e80941Smrgpp_tokens: 689b8e80941Smrg preprocessing_token { 690b8e80941Smrg parser->space_tokens = 1; 691b8e80941Smrg $$ = _token_list_create (parser); 692b8e80941Smrg _token_list_append (parser, $$, $1); 693b8e80941Smrg } 694b8e80941Smrg| pp_tokens preprocessing_token { 695b8e80941Smrg $$ = $1; 696b8e80941Smrg _token_list_append (parser, $$, $2); 697b8e80941Smrg } 698b8e80941Smrg; 699b8e80941Smrg 700b8e80941Smrgpreprocessing_token: 701b8e80941Smrg IDENTIFIER { 702b8e80941Smrg $$ = _token_create_str (parser, IDENTIFIER, $1); 703b8e80941Smrg $$->location = yylloc; 704b8e80941Smrg } 705b8e80941Smrg| INTEGER_STRING { 706b8e80941Smrg $$ = _token_create_str (parser, INTEGER_STRING, $1); 707b8e80941Smrg $$->location = yylloc; 708b8e80941Smrg } 709b8e80941Smrg| operator { 710b8e80941Smrg $$ = _token_create_ival (parser, $1, $1); 711b8e80941Smrg $$->location = yylloc; 712b8e80941Smrg } 713b8e80941Smrg| DEFINED { 714b8e80941Smrg $$ = _token_create_ival (parser, DEFINED, DEFINED); 715b8e80941Smrg $$->location = yylloc; 716b8e80941Smrg } 717b8e80941Smrg| OTHER { 718b8e80941Smrg $$ = _token_create_str (parser, OTHER, $1); 719b8e80941Smrg $$->location = yylloc; 720b8e80941Smrg } 721b8e80941Smrg| SPACE { 722b8e80941Smrg $$ = _token_create_ival (parser, SPACE, SPACE); 723b8e80941Smrg $$->location = yylloc; 724b8e80941Smrg } 725b8e80941Smrg; 726b8e80941Smrg 727b8e80941Smrgoperator: 728b8e80941Smrg '[' { $$ = '['; } 729b8e80941Smrg| ']' { $$ = ']'; } 730b8e80941Smrg| '(' { $$ = '('; } 731b8e80941Smrg| ')' { $$ = ')'; } 732b8e80941Smrg| '{' { $$ = '{'; } 733b8e80941Smrg| '}' { $$ = '}'; } 734b8e80941Smrg| '.' { $$ = '.'; } 735b8e80941Smrg| '&' { $$ = '&'; } 736b8e80941Smrg| '*' { $$ = '*'; } 737b8e80941Smrg| '+' { $$ = '+'; } 738b8e80941Smrg| '-' { $$ = '-'; } 739b8e80941Smrg| '~' { $$ = '~'; } 740b8e80941Smrg| '!' { $$ = '!'; } 741b8e80941Smrg| '/' { $$ = '/'; } 742b8e80941Smrg| '%' { $$ = '%'; } 743b8e80941Smrg| LEFT_SHIFT { $$ = LEFT_SHIFT; } 744b8e80941Smrg| RIGHT_SHIFT { $$ = RIGHT_SHIFT; } 745b8e80941Smrg| '<' { $$ = '<'; } 746b8e80941Smrg| '>' { $$ = '>'; } 747b8e80941Smrg| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; } 748b8e80941Smrg| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; } 749b8e80941Smrg| EQUAL { $$ = EQUAL; } 750b8e80941Smrg| NOT_EQUAL { $$ = NOT_EQUAL; } 751b8e80941Smrg| '^' { $$ = '^'; } 752b8e80941Smrg| '|' { $$ = '|'; } 753b8e80941Smrg| AND { $$ = AND; } 754b8e80941Smrg| OR { $$ = OR; } 755b8e80941Smrg| ';' { $$ = ';'; } 756b8e80941Smrg| ',' { $$ = ','; } 757b8e80941Smrg| '=' { $$ = '='; } 758b8e80941Smrg| PASTE { $$ = PASTE; } 759b8e80941Smrg| PLUS_PLUS { $$ = PLUS_PLUS; } 760b8e80941Smrg| MINUS_MINUS { $$ = MINUS_MINUS; } 761b8e80941Smrg; 762b8e80941Smrg 763b8e80941Smrg%% 764b8e80941Smrg 765b8e80941Smrgstring_list_t * 766b8e80941Smrg_string_list_create(glcpp_parser_t *parser) 767b8e80941Smrg{ 768b8e80941Smrg string_list_t *list; 769b8e80941Smrg 770b8e80941Smrg list = linear_alloc_child(parser->linalloc, sizeof(string_list_t)); 771b8e80941Smrg list->head = NULL; 772b8e80941Smrg list->tail = NULL; 773b8e80941Smrg 774b8e80941Smrg return list; 775b8e80941Smrg} 776b8e80941Smrg 777b8e80941Smrgvoid 778b8e80941Smrg_string_list_append_item(glcpp_parser_t *parser, string_list_t *list, 779b8e80941Smrg const char *str) 780b8e80941Smrg{ 781b8e80941Smrg string_node_t *node; 782b8e80941Smrg 783b8e80941Smrg node = linear_alloc_child(parser->linalloc, sizeof(string_node_t)); 784b8e80941Smrg node->str = linear_strdup(parser->linalloc, str); 785b8e80941Smrg 786b8e80941Smrg node->next = NULL; 787b8e80941Smrg 788b8e80941Smrg if (list->head == NULL) { 789b8e80941Smrg list->head = node; 790b8e80941Smrg } else { 791b8e80941Smrg list->tail->next = node; 792b8e80941Smrg } 793b8e80941Smrg 794b8e80941Smrg list->tail = node; 795b8e80941Smrg} 796b8e80941Smrg 797b8e80941Smrgint 798b8e80941Smrg_string_list_contains(string_list_t *list, const char *member, int *index) 799b8e80941Smrg{ 800b8e80941Smrg string_node_t *node; 801b8e80941Smrg int i; 802b8e80941Smrg 803b8e80941Smrg if (list == NULL) 804b8e80941Smrg return 0; 805b8e80941Smrg 806b8e80941Smrg for (i = 0, node = list->head; node; i++, node = node->next) { 807b8e80941Smrg if (strcmp (node->str, member) == 0) { 808b8e80941Smrg if (index) 809b8e80941Smrg *index = i; 810b8e80941Smrg return 1; 811b8e80941Smrg } 812b8e80941Smrg } 813b8e80941Smrg 814b8e80941Smrg return 0; 815b8e80941Smrg} 816b8e80941Smrg 817b8e80941Smrg/* Return duplicate string in list (if any), NULL otherwise. */ 818b8e80941Smrgconst char * 819b8e80941Smrg_string_list_has_duplicate(string_list_t *list) 820b8e80941Smrg{ 821b8e80941Smrg string_node_t *node, *dup; 822b8e80941Smrg 823b8e80941Smrg if (list == NULL) 824b8e80941Smrg return NULL; 825b8e80941Smrg 826b8e80941Smrg for (node = list->head; node; node = node->next) { 827b8e80941Smrg for (dup = node->next; dup; dup = dup->next) { 828b8e80941Smrg if (strcmp (node->str, dup->str) == 0) 829b8e80941Smrg return node->str; 830b8e80941Smrg } 831b8e80941Smrg } 832b8e80941Smrg 833b8e80941Smrg return NULL; 834b8e80941Smrg} 835b8e80941Smrg 836b8e80941Smrgint 837b8e80941Smrg_string_list_length(string_list_t *list) 838b8e80941Smrg{ 839b8e80941Smrg int length = 0; 840b8e80941Smrg string_node_t *node; 841b8e80941Smrg 842b8e80941Smrg if (list == NULL) 843b8e80941Smrg return 0; 844b8e80941Smrg 845b8e80941Smrg for (node = list->head; node; node = node->next) 846b8e80941Smrg length++; 847b8e80941Smrg 848b8e80941Smrg return length; 849b8e80941Smrg} 850b8e80941Smrg 851b8e80941Smrgint 852b8e80941Smrg_string_list_equal(string_list_t *a, string_list_t *b) 853b8e80941Smrg{ 854b8e80941Smrg string_node_t *node_a, *node_b; 855b8e80941Smrg 856b8e80941Smrg if (a == NULL && b == NULL) 857b8e80941Smrg return 1; 858b8e80941Smrg 859b8e80941Smrg if (a == NULL || b == NULL) 860b8e80941Smrg return 0; 861b8e80941Smrg 862b8e80941Smrg for (node_a = a->head, node_b = b->head; 863b8e80941Smrg node_a && node_b; 864b8e80941Smrg node_a = node_a->next, node_b = node_b->next) 865b8e80941Smrg { 866b8e80941Smrg if (strcmp (node_a->str, node_b->str)) 867b8e80941Smrg return 0; 868b8e80941Smrg } 869b8e80941Smrg 870b8e80941Smrg /* Catch the case of lists being different lengths, (which 871b8e80941Smrg * would cause the loop above to terminate after the shorter 872b8e80941Smrg * list). */ 873b8e80941Smrg return node_a == node_b; 874b8e80941Smrg} 875b8e80941Smrg 876b8e80941Smrgargument_list_t * 877b8e80941Smrg_argument_list_create(glcpp_parser_t *parser) 878b8e80941Smrg{ 879b8e80941Smrg argument_list_t *list; 880b8e80941Smrg 881b8e80941Smrg list = linear_alloc_child(parser->linalloc, sizeof(argument_list_t)); 882b8e80941Smrg list->head = NULL; 883b8e80941Smrg list->tail = NULL; 884b8e80941Smrg 885b8e80941Smrg return list; 886b8e80941Smrg} 887b8e80941Smrg 888b8e80941Smrgvoid 889b8e80941Smrg_argument_list_append(glcpp_parser_t *parser, 890b8e80941Smrg argument_list_t *list, token_list_t *argument) 891b8e80941Smrg{ 892b8e80941Smrg argument_node_t *node; 893b8e80941Smrg 894b8e80941Smrg node = linear_alloc_child(parser->linalloc, sizeof(argument_node_t)); 895b8e80941Smrg node->argument = argument; 896b8e80941Smrg 897b8e80941Smrg node->next = NULL; 898b8e80941Smrg 899b8e80941Smrg if (list->head == NULL) { 900b8e80941Smrg list->head = node; 901b8e80941Smrg } else { 902b8e80941Smrg list->tail->next = node; 903b8e80941Smrg } 904b8e80941Smrg 905b8e80941Smrg list->tail = node; 906b8e80941Smrg} 907b8e80941Smrg 908b8e80941Smrgint 909b8e80941Smrg_argument_list_length(argument_list_t *list) 910b8e80941Smrg{ 911b8e80941Smrg int length = 0; 912b8e80941Smrg argument_node_t *node; 913b8e80941Smrg 914b8e80941Smrg if (list == NULL) 915b8e80941Smrg return 0; 916b8e80941Smrg 917b8e80941Smrg for (node = list->head; node; node = node->next) 918b8e80941Smrg length++; 919b8e80941Smrg 920b8e80941Smrg return length; 921b8e80941Smrg} 922b8e80941Smrg 923b8e80941Smrgtoken_list_t * 924b8e80941Smrg_argument_list_member_at(argument_list_t *list, int index) 925b8e80941Smrg{ 926b8e80941Smrg argument_node_t *node; 927b8e80941Smrg int i; 928b8e80941Smrg 929b8e80941Smrg if (list == NULL) 930b8e80941Smrg return NULL; 931b8e80941Smrg 932b8e80941Smrg node = list->head; 933b8e80941Smrg for (i = 0; i < index; i++) { 934b8e80941Smrg node = node->next; 935b8e80941Smrg if (node == NULL) 936b8e80941Smrg break; 937b8e80941Smrg } 938b8e80941Smrg 939b8e80941Smrg if (node) 940b8e80941Smrg return node->argument; 941b8e80941Smrg 942b8e80941Smrg return NULL; 943b8e80941Smrg} 944b8e80941Smrg 945b8e80941Smrgtoken_t * 946b8e80941Smrg_token_create_str(glcpp_parser_t *parser, int type, char *str) 947b8e80941Smrg{ 948b8e80941Smrg token_t *token; 949b8e80941Smrg 950b8e80941Smrg token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 951b8e80941Smrg token->type = type; 952b8e80941Smrg token->value.str = str; 953b8e80941Smrg 954b8e80941Smrg return token; 955b8e80941Smrg} 956b8e80941Smrg 957b8e80941Smrgtoken_t * 958b8e80941Smrg_token_create_ival(glcpp_parser_t *parser, int type, int ival) 959b8e80941Smrg{ 960b8e80941Smrg token_t *token; 961b8e80941Smrg 962b8e80941Smrg token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 963b8e80941Smrg token->type = type; 964b8e80941Smrg token->value.ival = ival; 965b8e80941Smrg 966b8e80941Smrg return token; 967b8e80941Smrg} 968b8e80941Smrg 969b8e80941Smrgtoken_list_t * 970b8e80941Smrg_token_list_create(glcpp_parser_t *parser) 971b8e80941Smrg{ 972b8e80941Smrg token_list_t *list; 973b8e80941Smrg 974b8e80941Smrg list = linear_alloc_child(parser->linalloc, sizeof(token_list_t)); 975b8e80941Smrg list->head = NULL; 976b8e80941Smrg list->tail = NULL; 977b8e80941Smrg list->non_space_tail = NULL; 978b8e80941Smrg 979b8e80941Smrg return list; 980b8e80941Smrg} 981b8e80941Smrg 982b8e80941Smrgvoid 983b8e80941Smrg_token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token) 984b8e80941Smrg{ 985b8e80941Smrg token_node_t *node; 986b8e80941Smrg 987b8e80941Smrg node = linear_alloc_child(parser->linalloc, sizeof(token_node_t)); 988b8e80941Smrg node->token = token; 989b8e80941Smrg node->next = NULL; 990b8e80941Smrg 991b8e80941Smrg if (list->head == NULL) { 992b8e80941Smrg list->head = node; 993b8e80941Smrg } else { 994b8e80941Smrg list->tail->next = node; 995b8e80941Smrg } 996b8e80941Smrg 997b8e80941Smrg list->tail = node; 998b8e80941Smrg if (token->type != SPACE) 999b8e80941Smrg list->non_space_tail = node; 1000b8e80941Smrg} 1001b8e80941Smrg 1002b8e80941Smrgvoid 1003b8e80941Smrg_token_list_append_list(token_list_t *list, token_list_t *tail) 1004b8e80941Smrg{ 1005b8e80941Smrg if (tail == NULL || tail->head == NULL) 1006b8e80941Smrg return; 1007b8e80941Smrg 1008b8e80941Smrg if (list->head == NULL) { 1009b8e80941Smrg list->head = tail->head; 1010b8e80941Smrg } else { 1011b8e80941Smrg list->tail->next = tail->head; 1012b8e80941Smrg } 1013b8e80941Smrg 1014b8e80941Smrg list->tail = tail->tail; 1015b8e80941Smrg list->non_space_tail = tail->non_space_tail; 1016b8e80941Smrg} 1017b8e80941Smrg 1018b8e80941Smrgstatic token_list_t * 1019b8e80941Smrg_token_list_copy(glcpp_parser_t *parser, token_list_t *other) 1020b8e80941Smrg{ 1021b8e80941Smrg token_list_t *copy; 1022b8e80941Smrg token_node_t *node; 1023b8e80941Smrg 1024b8e80941Smrg if (other == NULL) 1025b8e80941Smrg return NULL; 1026b8e80941Smrg 1027b8e80941Smrg copy = _token_list_create (parser); 1028b8e80941Smrg for (node = other->head; node; node = node->next) { 1029b8e80941Smrg token_t *new_token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 1030b8e80941Smrg *new_token = *node->token; 1031b8e80941Smrg _token_list_append (parser, copy, new_token); 1032b8e80941Smrg } 1033b8e80941Smrg 1034b8e80941Smrg return copy; 1035b8e80941Smrg} 1036b8e80941Smrg 1037b8e80941Smrgstatic void 1038b8e80941Smrg_token_list_trim_trailing_space(token_list_t *list) 1039b8e80941Smrg{ 1040b8e80941Smrg if (list->non_space_tail) { 1041b8e80941Smrg list->non_space_tail->next = NULL; 1042b8e80941Smrg list->tail = list->non_space_tail; 1043b8e80941Smrg } 1044b8e80941Smrg} 1045b8e80941Smrg 1046b8e80941Smrgstatic int 1047b8e80941Smrg_token_list_is_empty_ignoring_space(token_list_t *l) 1048b8e80941Smrg{ 1049b8e80941Smrg token_node_t *n; 1050b8e80941Smrg 1051b8e80941Smrg if (l == NULL) 1052b8e80941Smrg return 1; 1053b8e80941Smrg 1054b8e80941Smrg n = l->head; 1055b8e80941Smrg while (n != NULL && n->token->type == SPACE) 1056b8e80941Smrg n = n->next; 1057b8e80941Smrg 1058b8e80941Smrg return n == NULL; 1059b8e80941Smrg} 1060b8e80941Smrg 1061b8e80941Smrgint 1062b8e80941Smrg_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b) 1063b8e80941Smrg{ 1064b8e80941Smrg token_node_t *node_a, *node_b; 1065b8e80941Smrg 1066b8e80941Smrg if (a == NULL || b == NULL) { 1067b8e80941Smrg int a_empty = _token_list_is_empty_ignoring_space(a); 1068b8e80941Smrg int b_empty = _token_list_is_empty_ignoring_space(b); 1069b8e80941Smrg return a_empty == b_empty; 1070b8e80941Smrg } 1071b8e80941Smrg 1072b8e80941Smrg node_a = a->head; 1073b8e80941Smrg node_b = b->head; 1074b8e80941Smrg 1075b8e80941Smrg while (1) 1076b8e80941Smrg { 1077b8e80941Smrg if (node_a == NULL && node_b == NULL) 1078b8e80941Smrg break; 1079b8e80941Smrg 1080b8e80941Smrg /* Ignore trailing whitespace */ 1081b8e80941Smrg if (node_a == NULL && node_b->token->type == SPACE) { 1082b8e80941Smrg while (node_b && node_b->token->type == SPACE) 1083b8e80941Smrg node_b = node_b->next; 1084b8e80941Smrg } 1085b8e80941Smrg 1086b8e80941Smrg if (node_b == NULL && node_a->token->type == SPACE) { 1087b8e80941Smrg while (node_a && node_a->token->type == SPACE) 1088b8e80941Smrg node_a = node_a->next; 1089b8e80941Smrg } 1090b8e80941Smrg 1091b8e80941Smrg if (node_a == NULL && node_b == NULL) 1092b8e80941Smrg break; 1093b8e80941Smrg 1094b8e80941Smrg if (node_a == NULL || node_b == NULL) 1095b8e80941Smrg return 0; 1096b8e80941Smrg /* Make sure whitespace appears in the same places in both. 1097b8e80941Smrg * It need not be exactly the same amount of whitespace, 1098b8e80941Smrg * though. 1099b8e80941Smrg */ 1100b8e80941Smrg if (node_a->token->type == SPACE && node_b->token->type == SPACE) { 1101b8e80941Smrg while (node_a && node_a->token->type == SPACE) 1102b8e80941Smrg node_a = node_a->next; 1103b8e80941Smrg while (node_b && node_b->token->type == SPACE) 1104b8e80941Smrg node_b = node_b->next; 1105b8e80941Smrg continue; 1106b8e80941Smrg } 1107b8e80941Smrg 1108b8e80941Smrg if (node_a->token->type != node_b->token->type) 1109b8e80941Smrg return 0; 1110b8e80941Smrg 1111b8e80941Smrg switch (node_a->token->type) { 1112b8e80941Smrg case INTEGER: 1113b8e80941Smrg if (node_a->token->value.ival != node_b->token->value.ival) { 1114b8e80941Smrg return 0; 1115b8e80941Smrg } 1116b8e80941Smrg break; 1117b8e80941Smrg case IDENTIFIER: 1118b8e80941Smrg case INTEGER_STRING: 1119b8e80941Smrg case OTHER: 1120b8e80941Smrg if (strcmp(node_a->token->value.str, node_b->token->value.str)) { 1121b8e80941Smrg return 0; 1122b8e80941Smrg } 1123b8e80941Smrg break; 1124b8e80941Smrg } 1125b8e80941Smrg 1126b8e80941Smrg node_a = node_a->next; 1127b8e80941Smrg node_b = node_b->next; 1128b8e80941Smrg } 1129b8e80941Smrg 1130b8e80941Smrg return 1; 1131b8e80941Smrg} 1132b8e80941Smrg 1133b8e80941Smrgstatic void 1134b8e80941Smrg_token_print(struct _mesa_string_buffer *out, token_t *token) 1135b8e80941Smrg{ 1136b8e80941Smrg if (token->type < 256) { 1137b8e80941Smrg _mesa_string_buffer_append_char(out, token->type); 1138b8e80941Smrg return; 1139b8e80941Smrg } 1140b8e80941Smrg 1141b8e80941Smrg switch (token->type) { 1142b8e80941Smrg case INTEGER: 1143b8e80941Smrg _mesa_string_buffer_printf(out, "%" PRIiMAX, token->value.ival); 1144b8e80941Smrg break; 1145b8e80941Smrg case IDENTIFIER: 1146b8e80941Smrg case INTEGER_STRING: 1147b8e80941Smrg case OTHER: 1148b8e80941Smrg _mesa_string_buffer_append(out, token->value.str); 1149b8e80941Smrg break; 1150b8e80941Smrg case SPACE: 1151b8e80941Smrg _mesa_string_buffer_append_char(out, ' '); 1152b8e80941Smrg break; 1153b8e80941Smrg case LEFT_SHIFT: 1154b8e80941Smrg _mesa_string_buffer_append(out, "<<"); 1155b8e80941Smrg break; 1156b8e80941Smrg case RIGHT_SHIFT: 1157b8e80941Smrg _mesa_string_buffer_append(out, ">>"); 1158b8e80941Smrg break; 1159b8e80941Smrg case LESS_OR_EQUAL: 1160b8e80941Smrg _mesa_string_buffer_append(out, "<="); 1161b8e80941Smrg break; 1162b8e80941Smrg case GREATER_OR_EQUAL: 1163b8e80941Smrg _mesa_string_buffer_append(out, ">="); 1164b8e80941Smrg break; 1165b8e80941Smrg case EQUAL: 1166b8e80941Smrg _mesa_string_buffer_append(out, "=="); 1167b8e80941Smrg break; 1168b8e80941Smrg case NOT_EQUAL: 1169b8e80941Smrg _mesa_string_buffer_append(out, "!="); 1170b8e80941Smrg break; 1171b8e80941Smrg case AND: 1172b8e80941Smrg _mesa_string_buffer_append(out, "&&"); 1173b8e80941Smrg break; 1174b8e80941Smrg case OR: 1175b8e80941Smrg _mesa_string_buffer_append(out, "||"); 1176b8e80941Smrg break; 1177b8e80941Smrg case PASTE: 1178b8e80941Smrg _mesa_string_buffer_append(out, "##"); 1179b8e80941Smrg break; 1180b8e80941Smrg case PLUS_PLUS: 1181b8e80941Smrg _mesa_string_buffer_append(out, "++"); 1182b8e80941Smrg break; 1183b8e80941Smrg case MINUS_MINUS: 1184b8e80941Smrg _mesa_string_buffer_append(out, "--"); 1185b8e80941Smrg break; 1186b8e80941Smrg case DEFINED: 1187b8e80941Smrg _mesa_string_buffer_append(out, "defined"); 1188b8e80941Smrg break; 1189b8e80941Smrg case PLACEHOLDER: 1190b8e80941Smrg /* Nothing to print. */ 1191b8e80941Smrg break; 1192b8e80941Smrg default: 1193b8e80941Smrg assert(!"Error: Don't know how to print token."); 1194b8e80941Smrg 1195b8e80941Smrg break; 1196b8e80941Smrg } 1197b8e80941Smrg} 1198b8e80941Smrg 1199b8e80941Smrg/* Return a new token formed by pasting 'token' and 'other'. Note that this 1200b8e80941Smrg * function may return 'token' or 'other' directly rather than allocating 1201b8e80941Smrg * anything new. 1202b8e80941Smrg * 1203b8e80941Smrg * Caution: Only very cursory error-checking is performed to see if 1204b8e80941Smrg * the final result is a valid single token. */ 1205b8e80941Smrgstatic token_t * 1206b8e80941Smrg_token_paste(glcpp_parser_t *parser, token_t *token, token_t *other) 1207b8e80941Smrg{ 1208b8e80941Smrg token_t *combined = NULL; 1209b8e80941Smrg 1210b8e80941Smrg /* Pasting a placeholder onto anything makes no change. */ 1211b8e80941Smrg if (other->type == PLACEHOLDER) 1212b8e80941Smrg return token; 1213b8e80941Smrg 1214b8e80941Smrg /* When 'token' is a placeholder, just return 'other'. */ 1215b8e80941Smrg if (token->type == PLACEHOLDER) 1216b8e80941Smrg return other; 1217b8e80941Smrg 1218b8e80941Smrg /* A very few single-character punctuators can be combined 1219b8e80941Smrg * with another to form a multi-character punctuator. */ 1220b8e80941Smrg switch (token->type) { 1221b8e80941Smrg case '<': 1222b8e80941Smrg if (other->type == '<') 1223b8e80941Smrg combined = _token_create_ival (parser, LEFT_SHIFT, LEFT_SHIFT); 1224b8e80941Smrg else if (other->type == '=') 1225b8e80941Smrg combined = _token_create_ival (parser, LESS_OR_EQUAL, LESS_OR_EQUAL); 1226b8e80941Smrg break; 1227b8e80941Smrg case '>': 1228b8e80941Smrg if (other->type == '>') 1229b8e80941Smrg combined = _token_create_ival (parser, RIGHT_SHIFT, RIGHT_SHIFT); 1230b8e80941Smrg else if (other->type == '=') 1231b8e80941Smrg combined = _token_create_ival (parser, GREATER_OR_EQUAL, GREATER_OR_EQUAL); 1232b8e80941Smrg break; 1233b8e80941Smrg case '=': 1234b8e80941Smrg if (other->type == '=') 1235b8e80941Smrg combined = _token_create_ival (parser, EQUAL, EQUAL); 1236b8e80941Smrg break; 1237b8e80941Smrg case '!': 1238b8e80941Smrg if (other->type == '=') 1239b8e80941Smrg combined = _token_create_ival (parser, NOT_EQUAL, NOT_EQUAL); 1240b8e80941Smrg break; 1241b8e80941Smrg case '&': 1242b8e80941Smrg if (other->type == '&') 1243b8e80941Smrg combined = _token_create_ival (parser, AND, AND); 1244b8e80941Smrg break; 1245b8e80941Smrg case '|': 1246b8e80941Smrg if (other->type == '|') 1247b8e80941Smrg combined = _token_create_ival (parser, OR, OR); 1248b8e80941Smrg break; 1249b8e80941Smrg } 1250b8e80941Smrg 1251b8e80941Smrg if (combined != NULL) { 1252b8e80941Smrg /* Inherit the location from the first token */ 1253b8e80941Smrg combined->location = token->location; 1254b8e80941Smrg return combined; 1255b8e80941Smrg } 1256b8e80941Smrg 1257b8e80941Smrg /* Two string-valued (or integer) tokens can usually just be 1258b8e80941Smrg * mashed together. (We also handle a string followed by an 1259b8e80941Smrg * integer here as well.) 1260b8e80941Smrg * 1261b8e80941Smrg * There are some exceptions here. Notably, if the first token 1262b8e80941Smrg * is an integer (or a string representing an integer), then 1263b8e80941Smrg * the second token must also be an integer or must be a 1264b8e80941Smrg * string representing an integer that begins with a digit. 1265b8e80941Smrg */ 1266b8e80941Smrg if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) && 1267b8e80941Smrg (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER)) 1268b8e80941Smrg { 1269b8e80941Smrg char *str; 1270b8e80941Smrg int combined_type; 1271b8e80941Smrg 1272b8e80941Smrg /* Check that pasting onto an integer doesn't create a 1273b8e80941Smrg * non-integer, (that is, only digits can be 1274b8e80941Smrg * pasted. */ 1275b8e80941Smrg if (token->type == INTEGER_STRING || token->type == INTEGER) { 1276b8e80941Smrg switch (other->type) { 1277b8e80941Smrg case INTEGER_STRING: 1278b8e80941Smrg if (other->value.str[0] < '0' || other->value.str[0] > '9') 1279b8e80941Smrg goto FAIL; 1280b8e80941Smrg break; 1281b8e80941Smrg case INTEGER: 1282b8e80941Smrg if (other->value.ival < 0) 1283b8e80941Smrg goto FAIL; 1284b8e80941Smrg break; 1285b8e80941Smrg default: 1286b8e80941Smrg goto FAIL; 1287b8e80941Smrg } 1288b8e80941Smrg } 1289b8e80941Smrg 1290b8e80941Smrg if (token->type == INTEGER) 1291b8e80941Smrg str = linear_asprintf(parser->linalloc, "%" PRIiMAX, token->value.ival); 1292b8e80941Smrg else 1293b8e80941Smrg str = linear_strdup(parser->linalloc, token->value.str); 1294b8e80941Smrg 1295b8e80941Smrg if (other->type == INTEGER) 1296b8e80941Smrg linear_asprintf_append(parser->linalloc, &str, "%" PRIiMAX, other->value.ival); 1297b8e80941Smrg else 1298b8e80941Smrg linear_strcat(parser->linalloc, &str, other->value.str); 1299b8e80941Smrg 1300b8e80941Smrg /* New token is same type as original token, unless we 1301b8e80941Smrg * started with an integer, in which case we will be 1302b8e80941Smrg * creating an integer-string. */ 1303b8e80941Smrg combined_type = token->type; 1304b8e80941Smrg if (combined_type == INTEGER) 1305b8e80941Smrg combined_type = INTEGER_STRING; 1306b8e80941Smrg 1307b8e80941Smrg combined = _token_create_str (parser, combined_type, str); 1308b8e80941Smrg combined->location = token->location; 1309b8e80941Smrg return combined; 1310b8e80941Smrg } 1311b8e80941Smrg 1312b8e80941Smrg FAIL: 1313b8e80941Smrg glcpp_error (&token->location, parser, ""); 1314b8e80941Smrg _mesa_string_buffer_append(parser->info_log, "Pasting \""); 1315b8e80941Smrg _token_print(parser->info_log, token); 1316b8e80941Smrg _mesa_string_buffer_append(parser->info_log, "\" and \""); 1317b8e80941Smrg _token_print(parser->info_log, other); 1318b8e80941Smrg _mesa_string_buffer_append(parser->info_log, "\" does not give a valid preprocessing token.\n"); 1319b8e80941Smrg 1320b8e80941Smrg return token; 1321b8e80941Smrg} 1322b8e80941Smrg 1323b8e80941Smrgstatic void 1324b8e80941Smrg_token_list_print(glcpp_parser_t *parser, token_list_t *list) 1325b8e80941Smrg{ 1326b8e80941Smrg token_node_t *node; 1327b8e80941Smrg 1328b8e80941Smrg if (list == NULL) 1329b8e80941Smrg return; 1330b8e80941Smrg 1331b8e80941Smrg for (node = list->head; node; node = node->next) 1332b8e80941Smrg _token_print(parser->output, node->token); 1333b8e80941Smrg} 1334b8e80941Smrg 1335b8e80941Smrgvoid 1336b8e80941Smrgyyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error) 1337b8e80941Smrg{ 1338b8e80941Smrg glcpp_error(locp, parser, "%s", error); 1339b8e80941Smrg} 1340b8e80941Smrg 1341b8e80941Smrgstatic void 1342b8e80941Smrgadd_builtin_define(glcpp_parser_t *parser, const char *name, int value) 1343b8e80941Smrg{ 1344b8e80941Smrg token_t *tok; 1345b8e80941Smrg token_list_t *list; 1346b8e80941Smrg 1347b8e80941Smrg tok = _token_create_ival (parser, INTEGER, value); 1348b8e80941Smrg 1349b8e80941Smrg list = _token_list_create(parser); 1350b8e80941Smrg _token_list_append(parser, list, tok); 1351b8e80941Smrg _define_object_macro(parser, NULL, name, list); 1352b8e80941Smrg} 1353b8e80941Smrg 1354b8e80941Smrg/* Initial output buffer size, 4096 minus ralloc() overhead. It was selected 1355b8e80941Smrg * to minimize total amount of allocated memory during shader-db run. 1356b8e80941Smrg */ 1357b8e80941Smrg#define INITIAL_PP_OUTPUT_BUF_SIZE 4048 1358b8e80941Smrg 1359b8e80941Smrgglcpp_parser_t * 1360b8e80941Smrgglcpp_parser_create(const struct gl_extensions *extension_list, 1361b8e80941Smrg glcpp_extension_iterator extensions, void *state, gl_api api) 1362b8e80941Smrg{ 1363b8e80941Smrg glcpp_parser_t *parser; 1364b8e80941Smrg 1365b8e80941Smrg parser = ralloc (NULL, glcpp_parser_t); 1366b8e80941Smrg 1367b8e80941Smrg glcpp_lex_init_extra (parser, &parser->scanner); 1368b8e80941Smrg parser->defines = _mesa_hash_table_create(NULL, _mesa_key_hash_string, 1369b8e80941Smrg _mesa_key_string_equal); 1370b8e80941Smrg parser->linalloc = linear_alloc_parent(parser, 0); 1371b8e80941Smrg parser->active = NULL; 1372b8e80941Smrg parser->lexing_directive = 0; 1373b8e80941Smrg parser->lexing_version_directive = 0; 1374b8e80941Smrg parser->space_tokens = 1; 1375b8e80941Smrg parser->last_token_was_newline = 0; 1376b8e80941Smrg parser->last_token_was_space = 0; 1377b8e80941Smrg parser->first_non_space_token_this_line = 1; 1378b8e80941Smrg parser->newline_as_space = 0; 1379b8e80941Smrg parser->in_control_line = 0; 1380b8e80941Smrg parser->paren_count = 0; 1381b8e80941Smrg parser->commented_newlines = 0; 1382b8e80941Smrg 1383b8e80941Smrg parser->skip_stack = NULL; 1384b8e80941Smrg parser->skipping = 0; 1385b8e80941Smrg 1386b8e80941Smrg parser->lex_from_list = NULL; 1387b8e80941Smrg parser->lex_from_node = NULL; 1388b8e80941Smrg 1389b8e80941Smrg parser->output = _mesa_string_buffer_create(parser, 1390b8e80941Smrg INITIAL_PP_OUTPUT_BUF_SIZE); 1391b8e80941Smrg parser->info_log = _mesa_string_buffer_create(parser, 1392b8e80941Smrg INITIAL_PP_OUTPUT_BUF_SIZE); 1393b8e80941Smrg parser->error = 0; 1394b8e80941Smrg 1395b8e80941Smrg parser->extensions = extensions; 1396b8e80941Smrg parser->extension_list = extension_list; 1397b8e80941Smrg parser->state = state; 1398b8e80941Smrg parser->api = api; 1399b8e80941Smrg parser->version = 0; 1400b8e80941Smrg parser->version_set = false; 1401b8e80941Smrg 1402b8e80941Smrg parser->has_new_line_number = 0; 1403b8e80941Smrg parser->new_line_number = 1; 1404b8e80941Smrg parser->has_new_source_number = 0; 1405b8e80941Smrg parser->new_source_number = 0; 1406b8e80941Smrg 1407b8e80941Smrg parser->is_gles = false; 1408b8e80941Smrg 1409b8e80941Smrg return parser; 1410b8e80941Smrg} 1411b8e80941Smrg 1412b8e80941Smrgvoid 1413b8e80941Smrgglcpp_parser_destroy(glcpp_parser_t *parser) 1414b8e80941Smrg{ 1415b8e80941Smrg glcpp_lex_destroy (parser->scanner); 1416b8e80941Smrg _mesa_hash_table_destroy(parser->defines, NULL); 1417b8e80941Smrg ralloc_free (parser); 1418b8e80941Smrg} 1419b8e80941Smrg 1420b8e80941Smrgtypedef enum function_status 1421b8e80941Smrg{ 1422b8e80941Smrg FUNCTION_STATUS_SUCCESS, 1423b8e80941Smrg FUNCTION_NOT_A_FUNCTION, 1424b8e80941Smrg FUNCTION_UNBALANCED_PARENTHESES 1425b8e80941Smrg} function_status_t; 1426b8e80941Smrg 1427b8e80941Smrg/* Find a set of function-like macro arguments by looking for a 1428b8e80941Smrg * balanced set of parentheses. 1429b8e80941Smrg * 1430b8e80941Smrg * When called, 'node' should be the opening-parenthesis token, (or 1431b8e80941Smrg * perhaps preceeding SPACE tokens). Upon successful return *last will 1432b8e80941Smrg * be the last consumed node, (corresponding to the closing right 1433b8e80941Smrg * parenthesis). 1434b8e80941Smrg * 1435b8e80941Smrg * Return values: 1436b8e80941Smrg * 1437b8e80941Smrg * FUNCTION_STATUS_SUCCESS: 1438b8e80941Smrg * 1439b8e80941Smrg * Successfully parsed a set of function arguments. 1440b8e80941Smrg * 1441b8e80941Smrg * FUNCTION_NOT_A_FUNCTION: 1442b8e80941Smrg * 1443b8e80941Smrg * Macro name not followed by a '('. This is not an error, but 1444b8e80941Smrg * simply that the macro name should be treated as a non-macro. 1445b8e80941Smrg * 1446b8e80941Smrg * FUNCTION_UNBALANCED_PARENTHESES 1447b8e80941Smrg * 1448b8e80941Smrg * Macro name is not followed by a balanced set of parentheses. 1449b8e80941Smrg */ 1450b8e80941Smrgstatic function_status_t 1451b8e80941Smrg_arguments_parse(glcpp_parser_t *parser, 1452b8e80941Smrg argument_list_t *arguments, token_node_t *node, 1453b8e80941Smrg token_node_t **last) 1454b8e80941Smrg{ 1455b8e80941Smrg token_list_t *argument; 1456b8e80941Smrg int paren_count; 1457b8e80941Smrg 1458b8e80941Smrg node = node->next; 1459b8e80941Smrg 1460b8e80941Smrg /* Ignore whitespace before first parenthesis. */ 1461b8e80941Smrg while (node && node->token->type == SPACE) 1462b8e80941Smrg node = node->next; 1463b8e80941Smrg 1464b8e80941Smrg if (node == NULL || node->token->type != '(') 1465b8e80941Smrg return FUNCTION_NOT_A_FUNCTION; 1466b8e80941Smrg 1467b8e80941Smrg node = node->next; 1468b8e80941Smrg 1469b8e80941Smrg argument = _token_list_create (parser); 1470b8e80941Smrg _argument_list_append (parser, arguments, argument); 1471b8e80941Smrg 1472b8e80941Smrg for (paren_count = 1; node; node = node->next) { 1473b8e80941Smrg if (node->token->type == '(') { 1474b8e80941Smrg paren_count++; 1475b8e80941Smrg } else if (node->token->type == ')') { 1476b8e80941Smrg paren_count--; 1477b8e80941Smrg if (paren_count == 0) 1478b8e80941Smrg break; 1479b8e80941Smrg } 1480b8e80941Smrg 1481b8e80941Smrg if (node->token->type == ',' && paren_count == 1) { 1482b8e80941Smrg _token_list_trim_trailing_space (argument); 1483b8e80941Smrg argument = _token_list_create (parser); 1484b8e80941Smrg _argument_list_append (parser, arguments, argument); 1485b8e80941Smrg } else { 1486b8e80941Smrg if (argument->head == NULL) { 1487b8e80941Smrg /* Don't treat initial whitespace as part of the argument. */ 1488b8e80941Smrg if (node->token->type == SPACE) 1489b8e80941Smrg continue; 1490b8e80941Smrg } 1491b8e80941Smrg _token_list_append(parser, argument, node->token); 1492b8e80941Smrg } 1493b8e80941Smrg } 1494b8e80941Smrg 1495b8e80941Smrg if (paren_count) 1496b8e80941Smrg return FUNCTION_UNBALANCED_PARENTHESES; 1497b8e80941Smrg 1498b8e80941Smrg *last = node; 1499b8e80941Smrg 1500b8e80941Smrg return FUNCTION_STATUS_SUCCESS; 1501b8e80941Smrg} 1502b8e80941Smrg 1503b8e80941Smrgstatic token_list_t * 1504b8e80941Smrg_token_list_create_with_one_ival(glcpp_parser_t *parser, int type, int ival) 1505b8e80941Smrg{ 1506b8e80941Smrg token_list_t *list; 1507b8e80941Smrg token_t *node; 1508b8e80941Smrg 1509b8e80941Smrg list = _token_list_create(parser); 1510b8e80941Smrg node = _token_create_ival(parser, type, ival); 1511b8e80941Smrg _token_list_append(parser, list, node); 1512b8e80941Smrg 1513b8e80941Smrg return list; 1514b8e80941Smrg} 1515b8e80941Smrg 1516b8e80941Smrgstatic token_list_t * 1517b8e80941Smrg_token_list_create_with_one_space(glcpp_parser_t *parser) 1518b8e80941Smrg{ 1519b8e80941Smrg return _token_list_create_with_one_ival(parser, SPACE, SPACE); 1520b8e80941Smrg} 1521b8e80941Smrg 1522b8e80941Smrgstatic token_list_t * 1523b8e80941Smrg_token_list_create_with_one_integer(glcpp_parser_t *parser, int ival) 1524b8e80941Smrg{ 1525b8e80941Smrg return _token_list_create_with_one_ival(parser, INTEGER, ival); 1526b8e80941Smrg} 1527b8e80941Smrg 1528b8e80941Smrg/* Evaluate a DEFINED token node (based on subsequent tokens in the list). 1529b8e80941Smrg * 1530b8e80941Smrg * Note: This function must only be called when "node" is a DEFINED token, 1531b8e80941Smrg * (and will abort with an assertion failure otherwise). 1532b8e80941Smrg * 1533b8e80941Smrg * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token 1534b8e80941Smrg * (optionally preceded and followed by '(' and ')' tokens) then the following 1535b8e80941Smrg * occurs: 1536b8e80941Smrg * 1537b8e80941Smrg * If the identifier is a defined macro, this function returns 1. 1538b8e80941Smrg * 1539b8e80941Smrg * If the identifier is not a defined macro, this function returns 0. 1540b8e80941Smrg * 1541b8e80941Smrg * In either case, *last will be updated to the last node in the list 1542b8e80941Smrg * consumed by the evaluation, (either the token of the identifier or the 1543b8e80941Smrg * token of the closing parenthesis). 1544b8e80941Smrg * 1545b8e80941Smrg * In all other cases, (such as "node is the final node of the list", or 1546b8e80941Smrg * "missing closing parenthesis", etc.), this function generates a 1547b8e80941Smrg * preprocessor error, returns -1 and *last will not be set. 1548b8e80941Smrg */ 1549b8e80941Smrgstatic int 1550b8e80941Smrg_glcpp_parser_evaluate_defined(glcpp_parser_t *parser, token_node_t *node, 1551b8e80941Smrg token_node_t **last) 1552b8e80941Smrg{ 1553b8e80941Smrg token_node_t *argument, *defined = node; 1554b8e80941Smrg 1555b8e80941Smrg assert(node->token->type == DEFINED); 1556b8e80941Smrg 1557b8e80941Smrg node = node->next; 1558b8e80941Smrg 1559b8e80941Smrg /* Ignore whitespace after DEFINED token. */ 1560b8e80941Smrg while (node && node->token->type == SPACE) 1561b8e80941Smrg node = node->next; 1562b8e80941Smrg 1563b8e80941Smrg if (node == NULL) 1564b8e80941Smrg goto FAIL; 1565b8e80941Smrg 1566b8e80941Smrg if (node->token->type == IDENTIFIER || node->token->type == OTHER) { 1567b8e80941Smrg argument = node; 1568b8e80941Smrg } else if (node->token->type == '(') { 1569b8e80941Smrg node = node->next; 1570b8e80941Smrg 1571b8e80941Smrg /* Ignore whitespace after '(' token. */ 1572b8e80941Smrg while (node && node->token->type == SPACE) 1573b8e80941Smrg node = node->next; 1574b8e80941Smrg 1575b8e80941Smrg if (node == NULL || (node->token->type != IDENTIFIER && 1576b8e80941Smrg node->token->type != OTHER)) { 1577b8e80941Smrg goto FAIL; 1578b8e80941Smrg } 1579b8e80941Smrg 1580b8e80941Smrg argument = node; 1581b8e80941Smrg 1582b8e80941Smrg node = node->next; 1583b8e80941Smrg 1584b8e80941Smrg /* Ignore whitespace after identifier, before ')' token. */ 1585b8e80941Smrg while (node && node->token->type == SPACE) 1586b8e80941Smrg node = node->next; 1587b8e80941Smrg 1588b8e80941Smrg if (node == NULL || node->token->type != ')') 1589b8e80941Smrg goto FAIL; 1590b8e80941Smrg } else { 1591b8e80941Smrg goto FAIL; 1592b8e80941Smrg } 1593b8e80941Smrg 1594b8e80941Smrg *last = node; 1595b8e80941Smrg 1596b8e80941Smrg return _mesa_hash_table_search(parser->defines, 1597b8e80941Smrg argument->token->value.str) ? 1 : 0; 1598b8e80941Smrg 1599b8e80941SmrgFAIL: 1600b8e80941Smrg glcpp_error (&defined->token->location, parser, 1601b8e80941Smrg "\"defined\" not followed by an identifier"); 1602b8e80941Smrg return -1; 1603b8e80941Smrg} 1604b8e80941Smrg 1605b8e80941Smrg/* Evaluate all DEFINED nodes in a given list, modifying the list in place. 1606b8e80941Smrg */ 1607b8e80941Smrgstatic void 1608b8e80941Smrg_glcpp_parser_evaluate_defined_in_list(glcpp_parser_t *parser, 1609b8e80941Smrg token_list_t *list) 1610b8e80941Smrg{ 1611b8e80941Smrg token_node_t *node, *node_prev, *replacement, *last = NULL; 1612b8e80941Smrg int value; 1613b8e80941Smrg 1614b8e80941Smrg if (list == NULL) 1615b8e80941Smrg return; 1616b8e80941Smrg 1617b8e80941Smrg node_prev = NULL; 1618b8e80941Smrg node = list->head; 1619b8e80941Smrg 1620b8e80941Smrg while (node) { 1621b8e80941Smrg 1622b8e80941Smrg if (node->token->type != DEFINED) 1623b8e80941Smrg goto NEXT; 1624b8e80941Smrg 1625b8e80941Smrg value = _glcpp_parser_evaluate_defined (parser, node, &last); 1626b8e80941Smrg if (value == -1) 1627b8e80941Smrg goto NEXT; 1628b8e80941Smrg 1629b8e80941Smrg replacement = linear_alloc_child(parser->linalloc, sizeof(token_node_t)); 1630b8e80941Smrg replacement->token = _token_create_ival (parser, INTEGER, value); 1631b8e80941Smrg 1632b8e80941Smrg /* Splice replacement node into list, replacing from "node" 1633b8e80941Smrg * through "last". */ 1634b8e80941Smrg if (node_prev) 1635b8e80941Smrg node_prev->next = replacement; 1636b8e80941Smrg else 1637b8e80941Smrg list->head = replacement; 1638b8e80941Smrg replacement->next = last->next; 1639b8e80941Smrg if (last == list->tail) 1640b8e80941Smrg list->tail = replacement; 1641b8e80941Smrg 1642b8e80941Smrg node = replacement; 1643b8e80941Smrg 1644b8e80941Smrg NEXT: 1645b8e80941Smrg node_prev = node; 1646b8e80941Smrg node = node->next; 1647b8e80941Smrg } 1648b8e80941Smrg} 1649b8e80941Smrg 1650b8e80941Smrg/* Perform macro expansion on 'list', placing the resulting tokens 1651b8e80941Smrg * into a new list which is initialized with a first token of type 1652b8e80941Smrg * 'head_token_type'. Then begin lexing from the resulting list, 1653b8e80941Smrg * (return to the current lexing source when this list is exhausted). 1654b8e80941Smrg * 1655b8e80941Smrg * See the documentation of _glcpp_parser_expand_token_list for a description 1656b8e80941Smrg * of the "mode" parameter. 1657b8e80941Smrg */ 1658b8e80941Smrgstatic void 1659b8e80941Smrg_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, 1660b8e80941Smrg token_list_t *list, expansion_mode_t mode) 1661b8e80941Smrg{ 1662b8e80941Smrg token_list_t *expanded; 1663b8e80941Smrg token_t *token; 1664b8e80941Smrg 1665b8e80941Smrg expanded = _token_list_create (parser); 1666b8e80941Smrg token = _token_create_ival (parser, head_token_type, head_token_type); 1667b8e80941Smrg _token_list_append (parser, expanded, token); 1668b8e80941Smrg _glcpp_parser_expand_token_list (parser, list, mode); 1669b8e80941Smrg _token_list_append_list (expanded, list); 1670b8e80941Smrg glcpp_parser_lex_from (parser, expanded); 1671b8e80941Smrg} 1672b8e80941Smrg 1673b8e80941Smrgstatic void 1674b8e80941Smrg_glcpp_parser_apply_pastes(glcpp_parser_t *parser, token_list_t *list) 1675b8e80941Smrg{ 1676b8e80941Smrg token_node_t *node; 1677b8e80941Smrg 1678b8e80941Smrg node = list->head; 1679b8e80941Smrg while (node) { 1680b8e80941Smrg token_node_t *next_non_space; 1681b8e80941Smrg 1682b8e80941Smrg /* Look ahead for a PASTE token, skipping space. */ 1683b8e80941Smrg next_non_space = node->next; 1684b8e80941Smrg while (next_non_space && next_non_space->token->type == SPACE) 1685b8e80941Smrg next_non_space = next_non_space->next; 1686b8e80941Smrg 1687b8e80941Smrg if (next_non_space == NULL) 1688b8e80941Smrg break; 1689b8e80941Smrg 1690b8e80941Smrg if (next_non_space->token->type != PASTE) { 1691b8e80941Smrg node = next_non_space; 1692b8e80941Smrg continue; 1693b8e80941Smrg } 1694b8e80941Smrg 1695b8e80941Smrg /* Now find the next non-space token after the PASTE. */ 1696b8e80941Smrg next_non_space = next_non_space->next; 1697b8e80941Smrg while (next_non_space && next_non_space->token->type == SPACE) 1698b8e80941Smrg next_non_space = next_non_space->next; 1699b8e80941Smrg 1700b8e80941Smrg if (next_non_space == NULL) { 1701b8e80941Smrg yyerror(&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); 1702b8e80941Smrg return; 1703b8e80941Smrg } 1704b8e80941Smrg 1705b8e80941Smrg node->token = _token_paste(parser, node->token, next_non_space->token); 1706b8e80941Smrg node->next = next_non_space->next; 1707b8e80941Smrg if (next_non_space == list->tail) 1708b8e80941Smrg list->tail = node; 1709b8e80941Smrg } 1710b8e80941Smrg 1711b8e80941Smrg list->non_space_tail = list->tail; 1712b8e80941Smrg} 1713b8e80941Smrg 1714b8e80941Smrg/* This is a helper function that's essentially part of the 1715b8e80941Smrg * implementation of _glcpp_parser_expand_node. It shouldn't be called 1716b8e80941Smrg * except for by that function. 1717b8e80941Smrg * 1718b8e80941Smrg * Returns NULL if node is a simple token with no expansion, (that is, 1719b8e80941Smrg * although 'node' corresponds to an identifier defined as a 1720b8e80941Smrg * function-like macro, it is not followed with a parenthesized 1721b8e80941Smrg * argument list). 1722b8e80941Smrg * 1723b8e80941Smrg * Compute the complete expansion of node (which is a function-like 1724b8e80941Smrg * macro) and subsequent nodes which are arguments. 1725b8e80941Smrg * 1726b8e80941Smrg * Returns the token list that results from the expansion and sets 1727b8e80941Smrg * *last to the last node in the list that was consumed by the 1728b8e80941Smrg * expansion. Specifically, *last will be set as follows: as the 1729b8e80941Smrg * token of the closing right parenthesis. 1730b8e80941Smrg * 1731b8e80941Smrg * See the documentation of _glcpp_parser_expand_token_list for a description 1732b8e80941Smrg * of the "mode" parameter. 1733b8e80941Smrg */ 1734b8e80941Smrgstatic token_list_t * 1735b8e80941Smrg_glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node, 1736b8e80941Smrg token_node_t **last, expansion_mode_t mode) 1737b8e80941Smrg{ 1738b8e80941Smrg struct hash_entry *entry; 1739b8e80941Smrg macro_t *macro; 1740b8e80941Smrg const char *identifier; 1741b8e80941Smrg argument_list_t *arguments; 1742b8e80941Smrg function_status_t status; 1743b8e80941Smrg token_list_t *substituted; 1744b8e80941Smrg int parameter_index; 1745b8e80941Smrg 1746b8e80941Smrg identifier = node->token->value.str; 1747b8e80941Smrg 1748b8e80941Smrg entry = _mesa_hash_table_search(parser->defines, identifier); 1749b8e80941Smrg macro = entry ? entry->data : NULL; 1750b8e80941Smrg 1751b8e80941Smrg assert(macro->is_function); 1752b8e80941Smrg 1753b8e80941Smrg arguments = _argument_list_create(parser); 1754b8e80941Smrg status = _arguments_parse(parser, arguments, node, last); 1755b8e80941Smrg 1756b8e80941Smrg switch (status) { 1757b8e80941Smrg case FUNCTION_STATUS_SUCCESS: 1758b8e80941Smrg break; 1759b8e80941Smrg case FUNCTION_NOT_A_FUNCTION: 1760b8e80941Smrg return NULL; 1761b8e80941Smrg case FUNCTION_UNBALANCED_PARENTHESES: 1762b8e80941Smrg glcpp_error(&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); 1763b8e80941Smrg return NULL; 1764b8e80941Smrg } 1765b8e80941Smrg 1766b8e80941Smrg /* Replace a macro defined as empty with a SPACE token. */ 1767b8e80941Smrg if (macro->replacements == NULL) { 1768b8e80941Smrg return _token_list_create_with_one_space(parser); 1769b8e80941Smrg } 1770b8e80941Smrg 1771b8e80941Smrg if (!((_argument_list_length (arguments) == 1772b8e80941Smrg _string_list_length (macro->parameters)) || 1773b8e80941Smrg (_string_list_length (macro->parameters) == 0 && 1774b8e80941Smrg _argument_list_length (arguments) == 1 && 1775b8e80941Smrg arguments->head->argument->head == NULL))) { 1776b8e80941Smrg glcpp_error(&node->token->location, parser, 1777b8e80941Smrg "Error: macro %s invoked with %d arguments (expected %d)\n", 1778b8e80941Smrg identifier, _argument_list_length (arguments), 1779b8e80941Smrg _string_list_length(macro->parameters)); 1780b8e80941Smrg return NULL; 1781b8e80941Smrg } 1782b8e80941Smrg 1783b8e80941Smrg /* Perform argument substitution on the replacement list. */ 1784b8e80941Smrg substituted = _token_list_create(parser); 1785b8e80941Smrg 1786b8e80941Smrg for (node = macro->replacements->head; node; node = node->next) { 1787b8e80941Smrg if (node->token->type == IDENTIFIER && 1788b8e80941Smrg _string_list_contains(macro->parameters, node->token->value.str, 1789b8e80941Smrg ¶meter_index)) { 1790b8e80941Smrg token_list_t *argument; 1791b8e80941Smrg argument = _argument_list_member_at(arguments, parameter_index); 1792b8e80941Smrg /* Before substituting, we expand the argument tokens, or append a 1793b8e80941Smrg * placeholder token for an empty argument. */ 1794b8e80941Smrg if (argument->head) { 1795b8e80941Smrg token_list_t *expanded_argument; 1796b8e80941Smrg expanded_argument = _token_list_copy(parser, argument); 1797b8e80941Smrg _glcpp_parser_expand_token_list(parser, expanded_argument, mode); 1798b8e80941Smrg _token_list_append_list(substituted, expanded_argument); 1799b8e80941Smrg } else { 1800b8e80941Smrg token_t *new_token; 1801b8e80941Smrg 1802b8e80941Smrg new_token = _token_create_ival(parser, PLACEHOLDER, 1803b8e80941Smrg PLACEHOLDER); 1804b8e80941Smrg _token_list_append(parser, substituted, new_token); 1805b8e80941Smrg } 1806b8e80941Smrg } else { 1807b8e80941Smrg _token_list_append(parser, substituted, node->token); 1808b8e80941Smrg } 1809b8e80941Smrg } 1810b8e80941Smrg 1811b8e80941Smrg /* After argument substitution, and before further expansion 1812b8e80941Smrg * below, implement token pasting. */ 1813b8e80941Smrg 1814b8e80941Smrg _token_list_trim_trailing_space(substituted); 1815b8e80941Smrg 1816b8e80941Smrg _glcpp_parser_apply_pastes(parser, substituted); 1817b8e80941Smrg 1818b8e80941Smrg return substituted; 1819b8e80941Smrg} 1820b8e80941Smrg 1821b8e80941Smrg/* Compute the complete expansion of node, (and subsequent nodes after 1822b8e80941Smrg * 'node' in the case that 'node' is a function-like macro and 1823b8e80941Smrg * subsequent nodes are arguments). 1824b8e80941Smrg * 1825b8e80941Smrg * Returns NULL if node is a simple token with no expansion. 1826b8e80941Smrg * 1827b8e80941Smrg * Otherwise, returns the token list that results from the expansion 1828b8e80941Smrg * and sets *last to the last node in the list that was consumed by 1829b8e80941Smrg * the expansion. Specifically, *last will be set as follows: 1830b8e80941Smrg * 1831b8e80941Smrg * As 'node' in the case of object-like macro expansion. 1832b8e80941Smrg * 1833b8e80941Smrg * As the token of the closing right parenthesis in the case of 1834b8e80941Smrg * function-like macro expansion. 1835b8e80941Smrg * 1836b8e80941Smrg * See the documentation of _glcpp_parser_expand_token_list for a description 1837b8e80941Smrg * of the "mode" parameter. 1838b8e80941Smrg */ 1839b8e80941Smrgstatic token_list_t * 1840b8e80941Smrg_glcpp_parser_expand_node(glcpp_parser_t *parser, token_node_t *node, 1841b8e80941Smrg token_node_t **last, expansion_mode_t mode) 1842b8e80941Smrg{ 1843b8e80941Smrg token_t *token = node->token; 1844b8e80941Smrg const char *identifier; 1845b8e80941Smrg struct hash_entry *entry; 1846b8e80941Smrg macro_t *macro; 1847b8e80941Smrg 1848b8e80941Smrg /* We only expand identifiers */ 1849b8e80941Smrg if (token->type != IDENTIFIER) { 1850b8e80941Smrg return NULL; 1851b8e80941Smrg } 1852b8e80941Smrg 1853b8e80941Smrg *last = node; 1854b8e80941Smrg identifier = token->value.str; 1855b8e80941Smrg 1856b8e80941Smrg /* Special handling for __LINE__ and __FILE__, (not through 1857b8e80941Smrg * the hash table). */ 1858b8e80941Smrg if (*identifier == '_') { 1859b8e80941Smrg if (strcmp(identifier, "__LINE__") == 0) 1860b8e80941Smrg return _token_list_create_with_one_integer(parser, 1861b8e80941Smrg node->token->location.first_line); 1862b8e80941Smrg 1863b8e80941Smrg if (strcmp(identifier, "__FILE__") == 0) 1864b8e80941Smrg return _token_list_create_with_one_integer(parser, 1865b8e80941Smrg node->token->location.source); 1866b8e80941Smrg } 1867b8e80941Smrg 1868b8e80941Smrg /* Look up this identifier in the hash table. */ 1869b8e80941Smrg entry = _mesa_hash_table_search(parser->defines, identifier); 1870b8e80941Smrg macro = entry ? entry->data : NULL; 1871b8e80941Smrg 1872b8e80941Smrg /* Not a macro, so no expansion needed. */ 1873b8e80941Smrg if (macro == NULL) 1874b8e80941Smrg return NULL; 1875b8e80941Smrg 1876b8e80941Smrg /* Finally, don't expand this macro if we're already actively 1877b8e80941Smrg * expanding it, (to avoid infinite recursion). */ 1878b8e80941Smrg if (_parser_active_list_contains (parser, identifier)) { 1879b8e80941Smrg /* We change the token type here from IDENTIFIER to OTHER to prevent any 1880b8e80941Smrg * future expansion of this unexpanded token. */ 1881b8e80941Smrg char *str; 1882b8e80941Smrg token_list_t *expansion; 1883b8e80941Smrg token_t *final; 1884b8e80941Smrg 1885b8e80941Smrg str = linear_strdup(parser->linalloc, token->value.str); 1886b8e80941Smrg final = _token_create_str(parser, OTHER, str); 1887b8e80941Smrg expansion = _token_list_create(parser); 1888b8e80941Smrg _token_list_append(parser, expansion, final); 1889b8e80941Smrg return expansion; 1890b8e80941Smrg } 1891b8e80941Smrg 1892b8e80941Smrg if (! macro->is_function) { 1893b8e80941Smrg token_list_t *replacement; 1894b8e80941Smrg 1895b8e80941Smrg /* Replace a macro defined as empty with a SPACE token. */ 1896b8e80941Smrg if (macro->replacements == NULL) 1897b8e80941Smrg return _token_list_create_with_one_space(parser); 1898b8e80941Smrg 1899b8e80941Smrg replacement = _token_list_copy(parser, macro->replacements); 1900b8e80941Smrg _glcpp_parser_apply_pastes(parser, replacement); 1901b8e80941Smrg return replacement; 1902b8e80941Smrg } 1903b8e80941Smrg 1904b8e80941Smrg return _glcpp_parser_expand_function(parser, node, last, mode); 1905b8e80941Smrg} 1906b8e80941Smrg 1907b8e80941Smrg/* Push a new identifier onto the parser's active list. 1908b8e80941Smrg * 1909b8e80941Smrg * Here, 'marker' is the token node that appears in the list after the 1910b8e80941Smrg * expansion of 'identifier'. That is, when the list iterator begins 1911b8e80941Smrg * examining 'marker', then it is time to pop this node from the 1912b8e80941Smrg * active stack. 1913b8e80941Smrg */ 1914b8e80941Smrgstatic void 1915b8e80941Smrg_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, 1916b8e80941Smrg token_node_t *marker) 1917b8e80941Smrg{ 1918b8e80941Smrg active_list_t *node; 1919b8e80941Smrg 1920b8e80941Smrg node = linear_alloc_child(parser->linalloc, sizeof(active_list_t)); 1921b8e80941Smrg node->identifier = linear_strdup(parser->linalloc, identifier); 1922b8e80941Smrg node->marker = marker; 1923b8e80941Smrg node->next = parser->active; 1924b8e80941Smrg 1925b8e80941Smrg parser->active = node; 1926b8e80941Smrg} 1927b8e80941Smrg 1928b8e80941Smrgstatic void 1929b8e80941Smrg_parser_active_list_pop(glcpp_parser_t *parser) 1930b8e80941Smrg{ 1931b8e80941Smrg active_list_t *node = parser->active; 1932b8e80941Smrg 1933b8e80941Smrg if (node == NULL) { 1934b8e80941Smrg parser->active = NULL; 1935b8e80941Smrg return; 1936b8e80941Smrg } 1937b8e80941Smrg 1938b8e80941Smrg node = parser->active->next; 1939b8e80941Smrg parser->active = node; 1940b8e80941Smrg} 1941b8e80941Smrg 1942b8e80941Smrgstatic int 1943b8e80941Smrg_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier) 1944b8e80941Smrg{ 1945b8e80941Smrg active_list_t *node; 1946b8e80941Smrg 1947b8e80941Smrg if (parser->active == NULL) 1948b8e80941Smrg return 0; 1949b8e80941Smrg 1950b8e80941Smrg for (node = parser->active; node; node = node->next) 1951b8e80941Smrg if (strcmp(node->identifier, identifier) == 0) 1952b8e80941Smrg return 1; 1953b8e80941Smrg 1954b8e80941Smrg return 0; 1955b8e80941Smrg} 1956b8e80941Smrg 1957b8e80941Smrg/* Walk over the token list replacing nodes with their expansion. 1958b8e80941Smrg * Whenever nodes are expanded the walking will walk over the new 1959b8e80941Smrg * nodes, continuing to expand as necessary. The results are placed in 1960b8e80941Smrg * 'list' itself. 1961b8e80941Smrg * 1962b8e80941Smrg * The "mode" argument controls the handling of any DEFINED tokens that 1963b8e80941Smrg * result from expansion as follows: 1964b8e80941Smrg * 1965b8e80941Smrg * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be 1966b8e80941Smrg * left in the final list, unevaluated. This is the correct mode 1967b8e80941Smrg * for expanding any list in any context other than a 1968b8e80941Smrg * preprocessor conditional, (#if or #elif). 1969b8e80941Smrg * 1970b8e80941Smrg * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be 1971b8e80941Smrg * evaluated to 0 or 1 tokens depending on whether the following 1972b8e80941Smrg * token is the name of a defined macro. If the DEFINED token is 1973b8e80941Smrg * not followed by an (optionally parenthesized) identifier, then 1974b8e80941Smrg * an error will be generated. This the correct mode for 1975b8e80941Smrg * expanding any list in the context of a preprocessor 1976b8e80941Smrg * conditional, (#if or #elif). 1977b8e80941Smrg */ 1978b8e80941Smrgstatic void 1979b8e80941Smrg_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, 1980b8e80941Smrg expansion_mode_t mode) 1981b8e80941Smrg{ 1982b8e80941Smrg token_node_t *node_prev; 1983b8e80941Smrg token_node_t *node, *last = NULL; 1984b8e80941Smrg token_list_t *expansion; 1985b8e80941Smrg active_list_t *active_initial = parser->active; 1986b8e80941Smrg 1987b8e80941Smrg if (list == NULL) 1988b8e80941Smrg return; 1989b8e80941Smrg 1990b8e80941Smrg _token_list_trim_trailing_space (list); 1991b8e80941Smrg 1992b8e80941Smrg node_prev = NULL; 1993b8e80941Smrg node = list->head; 1994b8e80941Smrg 1995b8e80941Smrg if (mode == EXPANSION_MODE_EVALUATE_DEFINED) 1996b8e80941Smrg _glcpp_parser_evaluate_defined_in_list (parser, list); 1997b8e80941Smrg 1998b8e80941Smrg while (node) { 1999b8e80941Smrg 2000b8e80941Smrg while (parser->active && parser->active->marker == node) 2001b8e80941Smrg _parser_active_list_pop (parser); 2002b8e80941Smrg 2003b8e80941Smrg expansion = _glcpp_parser_expand_node (parser, node, &last, mode); 2004b8e80941Smrg if (expansion) { 2005b8e80941Smrg token_node_t *n; 2006b8e80941Smrg 2007b8e80941Smrg if (mode == EXPANSION_MODE_EVALUATE_DEFINED) { 2008b8e80941Smrg _glcpp_parser_evaluate_defined_in_list (parser, expansion); 2009b8e80941Smrg } 2010b8e80941Smrg 2011b8e80941Smrg for (n = node; n != last->next; n = n->next) 2012b8e80941Smrg while (parser->active && parser->active->marker == n) { 2013b8e80941Smrg _parser_active_list_pop (parser); 2014b8e80941Smrg } 2015b8e80941Smrg 2016b8e80941Smrg _parser_active_list_push(parser, node->token->value.str, last->next); 2017b8e80941Smrg 2018b8e80941Smrg /* Splice expansion into list, supporting a simple deletion if the 2019b8e80941Smrg * expansion is empty. 2020b8e80941Smrg */ 2021b8e80941Smrg if (expansion->head) { 2022b8e80941Smrg if (node_prev) 2023b8e80941Smrg node_prev->next = expansion->head; 2024b8e80941Smrg else 2025b8e80941Smrg list->head = expansion->head; 2026b8e80941Smrg expansion->tail->next = last->next; 2027b8e80941Smrg if (last == list->tail) 2028b8e80941Smrg list->tail = expansion->tail; 2029b8e80941Smrg } else { 2030b8e80941Smrg if (node_prev) 2031b8e80941Smrg node_prev->next = last->next; 2032b8e80941Smrg else 2033b8e80941Smrg list->head = last->next; 2034b8e80941Smrg if (last == list->tail) 2035b8e80941Smrg list->tail = NULL; 2036b8e80941Smrg } 2037b8e80941Smrg } else { 2038b8e80941Smrg node_prev = node; 2039b8e80941Smrg } 2040b8e80941Smrg node = node_prev ? node_prev->next : list->head; 2041b8e80941Smrg } 2042b8e80941Smrg 2043b8e80941Smrg /* Remove any lingering effects of this invocation on the 2044b8e80941Smrg * active list. That is, pop until the list looks like it did 2045b8e80941Smrg * at the beginning of this function. */ 2046b8e80941Smrg while (parser->active && parser->active != active_initial) 2047b8e80941Smrg _parser_active_list_pop (parser); 2048b8e80941Smrg 2049b8e80941Smrg list->non_space_tail = list->tail; 2050b8e80941Smrg} 2051b8e80941Smrg 2052b8e80941Smrgvoid 2053b8e80941Smrg_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, 2054b8e80941Smrg token_list_t *list) 2055b8e80941Smrg{ 2056b8e80941Smrg if (list == NULL) 2057b8e80941Smrg return; 2058b8e80941Smrg 2059b8e80941Smrg _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED); 2060b8e80941Smrg 2061b8e80941Smrg _token_list_trim_trailing_space (list); 2062b8e80941Smrg 2063b8e80941Smrg _token_list_print (parser, list); 2064b8e80941Smrg} 2065b8e80941Smrg 2066b8e80941Smrgstatic void 2067b8e80941Smrg_check_for_reserved_macro_name(glcpp_parser_t *parser, YYLTYPE *loc, 2068b8e80941Smrg const char *identifier) 2069b8e80941Smrg{ 2070b8e80941Smrg /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and 2071b8e80941Smrg * the GLSL ES spec (all versions) say: 2072b8e80941Smrg * 2073b8e80941Smrg * "All macro names containing two consecutive underscores ( __ ) 2074b8e80941Smrg * are reserved for future use as predefined macro names. All 2075b8e80941Smrg * macro names prefixed with "GL_" ("GL" followed by a single 2076b8e80941Smrg * underscore) are also reserved." 2077b8e80941Smrg * 2078b8e80941Smrg * The intention is that names containing __ are reserved for internal 2079b8e80941Smrg * use by the implementation, and names prefixed with GL_ are reserved 2080b8e80941Smrg * for use by Khronos. Since every extension adds a name prefixed 2081b8e80941Smrg * with GL_ (i.e., the name of the extension), that should be an 2082b8e80941Smrg * error. Names simply containing __ are dangerous to use, but should 2083b8e80941Smrg * be allowed. 2084b8e80941Smrg * 2085b8e80941Smrg * A future version of the GLSL specification will clarify this. 2086b8e80941Smrg */ 2087b8e80941Smrg if (strstr(identifier, "__")) { 2088b8e80941Smrg glcpp_warning(loc, parser, "Macro names containing \"__\" are reserved " 2089b8e80941Smrg "for use by the implementation.\n"); 2090b8e80941Smrg } 2091b8e80941Smrg if (strncmp(identifier, "GL_", 3) == 0) { 2092b8e80941Smrg glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); 2093b8e80941Smrg } 2094b8e80941Smrg if (strcmp(identifier, "defined") == 0) { 2095b8e80941Smrg glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name"); 2096b8e80941Smrg } 2097b8e80941Smrg} 2098b8e80941Smrg 2099b8e80941Smrgstatic int 2100b8e80941Smrg_macro_equal(macro_t *a, macro_t *b) 2101b8e80941Smrg{ 2102b8e80941Smrg if (a->is_function != b->is_function) 2103b8e80941Smrg return 0; 2104b8e80941Smrg 2105b8e80941Smrg if (a->is_function) { 2106b8e80941Smrg if (! _string_list_equal (a->parameters, b->parameters)) 2107b8e80941Smrg return 0; 2108b8e80941Smrg } 2109b8e80941Smrg 2110b8e80941Smrg return _token_list_equal_ignoring_space(a->replacements, b->replacements); 2111b8e80941Smrg} 2112b8e80941Smrg 2113b8e80941Smrgvoid 2114b8e80941Smrg_define_object_macro(glcpp_parser_t *parser, YYLTYPE *loc, 2115b8e80941Smrg const char *identifier, token_list_t *replacements) 2116b8e80941Smrg{ 2117b8e80941Smrg macro_t *macro, *previous; 2118b8e80941Smrg struct hash_entry *entry; 2119b8e80941Smrg 2120b8e80941Smrg /* We define pre-defined macros before we've started parsing the actual 2121b8e80941Smrg * file. So if there's no location defined yet, that's what were doing and 2122b8e80941Smrg * we don't want to generate an error for using the reserved names. */ 2123b8e80941Smrg if (loc != NULL) 2124b8e80941Smrg _check_for_reserved_macro_name(parser, loc, identifier); 2125b8e80941Smrg 2126b8e80941Smrg macro = linear_alloc_child(parser->linalloc, sizeof(macro_t)); 2127b8e80941Smrg 2128b8e80941Smrg macro->is_function = 0; 2129b8e80941Smrg macro->parameters = NULL; 2130b8e80941Smrg macro->identifier = linear_strdup(parser->linalloc, identifier); 2131b8e80941Smrg macro->replacements = replacements; 2132b8e80941Smrg 2133b8e80941Smrg entry = _mesa_hash_table_search(parser->defines, identifier); 2134b8e80941Smrg previous = entry ? entry->data : NULL; 2135b8e80941Smrg if (previous) { 2136b8e80941Smrg if (_macro_equal (macro, previous)) { 2137b8e80941Smrg return; 2138b8e80941Smrg } 2139b8e80941Smrg glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); 2140b8e80941Smrg } 2141b8e80941Smrg 2142b8e80941Smrg _mesa_hash_table_insert (parser->defines, identifier, macro); 2143b8e80941Smrg} 2144b8e80941Smrg 2145b8e80941Smrgvoid 2146b8e80941Smrg_define_function_macro(glcpp_parser_t *parser, YYLTYPE *loc, 2147b8e80941Smrg const char *identifier, string_list_t *parameters, 2148b8e80941Smrg token_list_t *replacements) 2149b8e80941Smrg{ 2150b8e80941Smrg macro_t *macro, *previous; 2151b8e80941Smrg struct hash_entry *entry; 2152b8e80941Smrg const char *dup; 2153b8e80941Smrg 2154b8e80941Smrg _check_for_reserved_macro_name(parser, loc, identifier); 2155b8e80941Smrg 2156b8e80941Smrg /* Check for any duplicate parameter names. */ 2157b8e80941Smrg if ((dup = _string_list_has_duplicate (parameters)) != NULL) { 2158b8e80941Smrg glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", dup); 2159b8e80941Smrg } 2160b8e80941Smrg 2161b8e80941Smrg macro = linear_alloc_child(parser->linalloc, sizeof(macro_t)); 2162b8e80941Smrg 2163b8e80941Smrg macro->is_function = 1; 2164b8e80941Smrg macro->parameters = parameters; 2165b8e80941Smrg macro->identifier = linear_strdup(parser->linalloc, identifier); 2166b8e80941Smrg macro->replacements = replacements; 2167b8e80941Smrg 2168b8e80941Smrg entry = _mesa_hash_table_search(parser->defines, identifier); 2169b8e80941Smrg previous = entry ? entry->data : NULL; 2170b8e80941Smrg if (previous) { 2171b8e80941Smrg if (_macro_equal (macro, previous)) { 2172b8e80941Smrg return; 2173b8e80941Smrg } 2174b8e80941Smrg glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); 2175b8e80941Smrg } 2176b8e80941Smrg 2177b8e80941Smrg _mesa_hash_table_insert(parser->defines, identifier, macro); 2178b8e80941Smrg} 2179b8e80941Smrg 2180b8e80941Smrgstatic int 2181b8e80941Smrgglcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) 2182b8e80941Smrg{ 2183b8e80941Smrg token_node_t *node; 2184b8e80941Smrg int ret; 2185b8e80941Smrg 2186b8e80941Smrg if (parser->lex_from_list == NULL) { 2187b8e80941Smrg ret = glcpp_lex(yylval, yylloc, parser->scanner); 2188b8e80941Smrg 2189b8e80941Smrg /* XXX: This ugly block of code exists for the sole 2190b8e80941Smrg * purpose of converting a NEWLINE token into a SPACE 2191b8e80941Smrg * token, but only in the case where we have seen a 2192b8e80941Smrg * function-like macro name, but have not yet seen its 2193b8e80941Smrg * closing parenthesis. 2194b8e80941Smrg * 2195b8e80941Smrg * There's perhaps a more compact way to do this with 2196b8e80941Smrg * mid-rule actions in the grammar. 2197b8e80941Smrg * 2198b8e80941Smrg * I'm definitely not pleased with the complexity of 2199b8e80941Smrg * this code here. 2200b8e80941Smrg */ 2201b8e80941Smrg if (parser->newline_as_space) { 2202b8e80941Smrg if (ret == '(') { 2203b8e80941Smrg parser->paren_count++; 2204b8e80941Smrg } else if (ret == ')') { 2205b8e80941Smrg parser->paren_count--; 2206b8e80941Smrg if (parser->paren_count == 0) 2207b8e80941Smrg parser->newline_as_space = 0; 2208b8e80941Smrg } else if (ret == NEWLINE) { 2209b8e80941Smrg ret = SPACE; 2210b8e80941Smrg } else if (ret != SPACE) { 2211b8e80941Smrg if (parser->paren_count == 0) 2212b8e80941Smrg parser->newline_as_space = 0; 2213b8e80941Smrg } 2214b8e80941Smrg } else if (parser->in_control_line) { 2215b8e80941Smrg if (ret == NEWLINE) 2216b8e80941Smrg parser->in_control_line = 0; 2217b8e80941Smrg } 2218b8e80941Smrg else if (ret == DEFINE_TOKEN || ret == UNDEF || ret == IF || 2219b8e80941Smrg ret == IFDEF || ret == IFNDEF || ret == ELIF || ret == ELSE || 2220b8e80941Smrg ret == ENDIF || ret == HASH_TOKEN) { 2221b8e80941Smrg parser->in_control_line = 1; 2222b8e80941Smrg } else if (ret == IDENTIFIER) { 2223b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(parser->defines, 2224b8e80941Smrg yylval->str); 2225b8e80941Smrg macro_t *macro = entry ? entry->data : NULL; 2226b8e80941Smrg if (macro && macro->is_function) { 2227b8e80941Smrg parser->newline_as_space = 1; 2228b8e80941Smrg parser->paren_count = 0; 2229b8e80941Smrg } 2230b8e80941Smrg } 2231b8e80941Smrg 2232b8e80941Smrg return ret; 2233b8e80941Smrg } 2234b8e80941Smrg 2235b8e80941Smrg node = parser->lex_from_node; 2236b8e80941Smrg 2237b8e80941Smrg if (node == NULL) { 2238b8e80941Smrg parser->lex_from_list = NULL; 2239b8e80941Smrg return NEWLINE; 2240b8e80941Smrg } 2241b8e80941Smrg 2242b8e80941Smrg *yylval = node->token->value; 2243b8e80941Smrg ret = node->token->type; 2244b8e80941Smrg 2245b8e80941Smrg parser->lex_from_node = node->next; 2246b8e80941Smrg 2247b8e80941Smrg return ret; 2248b8e80941Smrg} 2249b8e80941Smrg 2250b8e80941Smrgstatic void 2251b8e80941Smrgglcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list) 2252b8e80941Smrg{ 2253b8e80941Smrg token_node_t *node; 2254b8e80941Smrg 2255b8e80941Smrg assert (parser->lex_from_list == NULL); 2256b8e80941Smrg 2257b8e80941Smrg /* Copy list, eliminating any space tokens. */ 2258b8e80941Smrg parser->lex_from_list = _token_list_create (parser); 2259b8e80941Smrg 2260b8e80941Smrg for (node = list->head; node; node = node->next) { 2261b8e80941Smrg if (node->token->type == SPACE) 2262b8e80941Smrg continue; 2263b8e80941Smrg _token_list_append (parser, parser->lex_from_list, node->token); 2264b8e80941Smrg } 2265b8e80941Smrg 2266b8e80941Smrg parser->lex_from_node = parser->lex_from_list->head; 2267b8e80941Smrg 2268b8e80941Smrg /* It's possible the list consisted of nothing but whitespace. */ 2269b8e80941Smrg if (parser->lex_from_node == NULL) { 2270b8e80941Smrg parser->lex_from_list = NULL; 2271b8e80941Smrg } 2272b8e80941Smrg} 2273b8e80941Smrg 2274b8e80941Smrgstatic void 2275b8e80941Smrg_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, 2276b8e80941Smrg int condition) 2277b8e80941Smrg{ 2278b8e80941Smrg skip_type_t current = SKIP_NO_SKIP; 2279b8e80941Smrg skip_node_t *node; 2280b8e80941Smrg 2281b8e80941Smrg if (parser->skip_stack) 2282b8e80941Smrg current = parser->skip_stack->type; 2283b8e80941Smrg 2284b8e80941Smrg node = linear_alloc_child(parser->linalloc, sizeof(skip_node_t)); 2285b8e80941Smrg node->loc = *loc; 2286b8e80941Smrg 2287b8e80941Smrg if (current == SKIP_NO_SKIP) { 2288b8e80941Smrg if (condition) 2289b8e80941Smrg node->type = SKIP_NO_SKIP; 2290b8e80941Smrg else 2291b8e80941Smrg node->type = SKIP_TO_ELSE; 2292b8e80941Smrg } else { 2293b8e80941Smrg node->type = SKIP_TO_ENDIF; 2294b8e80941Smrg } 2295b8e80941Smrg 2296b8e80941Smrg node->has_else = false; 2297b8e80941Smrg node->next = parser->skip_stack; 2298b8e80941Smrg parser->skip_stack = node; 2299b8e80941Smrg} 2300b8e80941Smrg 2301b8e80941Smrgstatic void 2302b8e80941Smrg_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, 2303b8e80941Smrg const char *type, int condition) 2304b8e80941Smrg{ 2305b8e80941Smrg if (parser->skip_stack == NULL) { 2306b8e80941Smrg glcpp_error (loc, parser, "#%s without #if\n", type); 2307b8e80941Smrg return; 2308b8e80941Smrg } 2309b8e80941Smrg 2310b8e80941Smrg if (parser->skip_stack->type == SKIP_TO_ELSE) { 2311b8e80941Smrg if (condition) 2312b8e80941Smrg parser->skip_stack->type = SKIP_NO_SKIP; 2313b8e80941Smrg } else { 2314b8e80941Smrg parser->skip_stack->type = SKIP_TO_ENDIF; 2315b8e80941Smrg } 2316b8e80941Smrg} 2317b8e80941Smrg 2318b8e80941Smrgstatic void 2319b8e80941Smrg_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc) 2320b8e80941Smrg{ 2321b8e80941Smrg skip_node_t *node; 2322b8e80941Smrg 2323b8e80941Smrg if (parser->skip_stack == NULL) { 2324b8e80941Smrg glcpp_error (loc, parser, "#endif without #if\n"); 2325b8e80941Smrg return; 2326b8e80941Smrg } 2327b8e80941Smrg 2328b8e80941Smrg node = parser->skip_stack; 2329b8e80941Smrg parser->skip_stack = node->next; 2330b8e80941Smrg} 2331b8e80941Smrg 2332b8e80941Smrgstatic void 2333b8e80941Smrg_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, 2334b8e80941Smrg const char *identifier, 2335b8e80941Smrg bool explicitly_set) 2336b8e80941Smrg{ 2337b8e80941Smrg if (parser->version_set) 2338b8e80941Smrg return; 2339b8e80941Smrg 2340b8e80941Smrg parser->version = version; 2341b8e80941Smrg parser->version_set = true; 2342b8e80941Smrg 2343b8e80941Smrg add_builtin_define (parser, "__VERSION__", version); 2344b8e80941Smrg 2345b8e80941Smrg parser->is_gles = (version == 100) || 2346b8e80941Smrg (identifier && (strcmp(identifier, "es") == 0)); 2347b8e80941Smrg bool is_compat = version >= 150 && identifier && 2348b8e80941Smrg strcmp(identifier, "compatibility") == 0; 2349b8e80941Smrg 2350b8e80941Smrg /* Add pre-defined macros. */ 2351b8e80941Smrg if (parser->is_gles) 2352b8e80941Smrg add_builtin_define(parser, "GL_ES", 1); 2353b8e80941Smrg else if (is_compat) 2354b8e80941Smrg add_builtin_define(parser, "GL_compatibility_profile", 1); 2355b8e80941Smrg else if (version >= 150) 2356b8e80941Smrg add_builtin_define(parser, "GL_core_profile", 1); 2357b8e80941Smrg 2358b8e80941Smrg /* Currently, all ES2/ES3 implementations support highp in the 2359b8e80941Smrg * fragment shader, so we always define this macro in ES2/ES3. 2360b8e80941Smrg * If we ever get a driver that doesn't support highp, we'll 2361b8e80941Smrg * need to add a flag to the gl_context and check that here. 2362b8e80941Smrg */ 2363b8e80941Smrg if (version >= 130 || parser->is_gles) 2364b8e80941Smrg add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); 2365b8e80941Smrg 2366b8e80941Smrg /* Add all the extension macros available in this context */ 2367b8e80941Smrg if (parser->extensions) 2368b8e80941Smrg parser->extensions(parser->state, add_builtin_define, parser, 2369b8e80941Smrg version, parser->is_gles); 2370b8e80941Smrg 2371b8e80941Smrg if (parser->extension_list) { 2372b8e80941Smrg /* If MESA_shader_integer_functions is supported, then the building 2373b8e80941Smrg * blocks required for the 64x64 => 64 multiply exist. Add defines for 2374b8e80941Smrg * those functions so that they can be tested. 2375b8e80941Smrg */ 2376b8e80941Smrg if (parser->extension_list->MESA_shader_integer_functions) { 2377b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_sign64", 1); 2378b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_umul64", 1); 2379b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_udiv64", 1); 2380b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_umod64", 1); 2381b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1); 2382b8e80941Smrg add_builtin_define(parser, "__have_builtin_builtin_imod64", 1); 2383b8e80941Smrg } 2384b8e80941Smrg } 2385b8e80941Smrg 2386b8e80941Smrg if (explicitly_set) { 2387b8e80941Smrg _mesa_string_buffer_printf(parser->output, 2388b8e80941Smrg "#version %" PRIiMAX "%s%s", version, 2389b8e80941Smrg identifier ? " " : "", 2390b8e80941Smrg identifier ? identifier : ""); 2391b8e80941Smrg } 2392b8e80941Smrg} 2393b8e80941Smrg 2394b8e80941Smrg/* GLSL version if no version is explicitly specified. */ 2395b8e80941Smrg#define IMPLICIT_GLSL_VERSION 110 2396b8e80941Smrg 2397b8e80941Smrg/* GLSL ES version if no version is explicitly specified. */ 2398b8e80941Smrg#define IMPLICIT_GLSL_ES_VERSION 100 2399b8e80941Smrg 2400b8e80941Smrgvoid 2401b8e80941Smrgglcpp_parser_resolve_implicit_version(glcpp_parser_t *parser) 2402b8e80941Smrg{ 2403b8e80941Smrg int language_version = parser->api == API_OPENGLES2 ? 2404b8e80941Smrg IMPLICIT_GLSL_ES_VERSION : IMPLICIT_GLSL_VERSION; 2405b8e80941Smrg 2406b8e80941Smrg _glcpp_parser_handle_version_declaration(parser, language_version, 2407b8e80941Smrg NULL, false); 2408b8e80941Smrg} 2409