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