1/* 2 +----------------------------------------------------------------------+ 3 | Copyright (c) The PHP Group | 4 +----------------------------------------------------------------------+ 5 | This source file is subject to version 3.01 of the PHP license, | 6 | that is bundled with this package in the file LICENSE, and is | 7 | available through the world-wide-web at the following url: | 8 | https://www.php.net/license/3_01.txt | 9 | If you did not receive a copy of the PHP license and are unable to | 10 | obtain it through the world-wide-web, please send a note to | 11 | license@php.net so we can mail you a copy immediately. | 12 +----------------------------------------------------------------------+ 13 | Author: Dmitry Stogov <dmitry@zend.com> | 14 +----------------------------------------------------------------------+ 15*/ 16 17/* 18To generate ffi_parser.c use llk <https://github.com/dstogov/llk>: 19php llk.php ffi.g 20*/ 21 22%start declarations 23%sub-start type_name 24%case-sensetive true 25%global-vars false 26%output "ffi_parser.c" 27%language "c" 28%indent "\t" 29 30%{ 31/* 32 +----------------------------------------------------------------------+ 33 | Copyright (c) The PHP Group | 34 +----------------------------------------------------------------------+ 35 | This source file is subject to version 3.01 of the PHP license, | 36 | that is bundled with this package in the file LICENSE, and is | 37 | available through the world-wide-web at the following url: | 38 | https://www.php.net/license/3_01.txt | 39 | If you did not receive a copy of the PHP license and are unable to | 40 | obtain it through the world-wide-web, please send a note to | 41 | license@php.net so we can mail you a copy immediately. | 42 +----------------------------------------------------------------------+ 43 | Author: Dmitry Stogov <dmitry@zend.com> | 44 +----------------------------------------------------------------------+ 45*/ 46 47#ifdef HAVE_CONFIG_H 48# include "config.h" 49#endif 50 51#include "php.h" 52#include "php_ffi.h" 53 54#include <stdio.h> 55#include <stdlib.h> 56#include <string.h> 57 58#define yy_buf FFI_G(buf) 59#define yy_end FFI_G(end) 60#define yy_pos FFI_G(pos) 61#define yy_text FFI_G(text) 62#define yy_line FFI_G(line) 63 64/* forward declarations */ 65static void yy_error(const char *msg); 66static void yy_error_sym(const char *msg, int sym); 67 68%} 69 70declarations: 71 ( 72 {zend_ffi_dcl common_dcl = ZEND_FFI_ATTR_INIT;} 73 "__extension__"? 74 declaration_specifiers(&common_dcl) 75 ( 76 {const char *name;} 77 {size_t name_len;} 78 {zend_ffi_dcl dcl;} 79 {dcl = common_dcl;} 80 declarator(&dcl, &name, &name_len) 81 ( 82 {zend_ffi_val asm_str;} 83 "__asm__" 84 "(" 85 STRING(&asm_str)+ 86 /*TODO*/ 87 ")" 88 )? 89 attributes(&dcl)? 90 initializer? 91 {zend_ffi_declare(name, name_len, &dcl);} 92 ( "," 93 {dcl = common_dcl;} 94 declarator(&dcl, &name, &name_len) 95 attributes(&dcl)? 96 initializer? 97 {zend_ffi_declare(name, name_len, &dcl);} 98 )* 99 )? 100 ";" 101 )* 102; 103 104declaration_specifiers(zend_ffi_dcl *dcl): 105 ( ?{sym != YY_ID || !(dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS)} 106 ( {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);} 107 "typedef" 108 {dcl->flags |= ZEND_FFI_DCL_TYPEDEF;} 109 | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);} 110 "extern" 111 {dcl->flags |= ZEND_FFI_DCL_EXTERN;} 112 | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);} 113 "static" 114 {dcl->flags |= ZEND_FFI_DCL_STATIC;} 115 | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);} 116 "auto" 117 {dcl->flags |= ZEND_FFI_DCL_AUTO;} 118 | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);} 119 "register" 120 {dcl->flags |= ZEND_FFI_DCL_REGISTER;} 121// | "_Thread_local" // TODO: not-implemented ??? 122 | ("inline"|"__inline"|"__inline__") 123 {dcl->flags |= ZEND_FFI_DCL_INLINE;} 124 | "_Noreturn" 125 {dcl->flags |= ZEND_FFI_DCL_NO_RETURN;} 126 | "_Alignas" 127 "(" 128 ( &type_name_start 129 {zend_ffi_dcl align_dcl = ZEND_FFI_ATTR_INIT;} 130 type_name(&align_dcl) 131 {zend_ffi_align_as_type(dcl, &align_dcl);} 132 | {zend_ffi_val align_val;} 133 constant_expression(&align_val) 134 {zend_ffi_align_as_val(dcl, &align_val);} 135 ) 136 ")" 137 | attributes(dcl) 138 | type_qualifier(dcl) 139 | type_specifier(dcl) 140 ) 141 )+ 142; 143 144specifier_qualifier_list(zend_ffi_dcl *dcl): 145 "__extension__"? 146 ( ?{sym != YY_ID || zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text) || (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) == 0} 147 ( type_specifier(dcl) 148 | type_qualifier(dcl) 149 | attributes(dcl) 150 ) 151 )+ 152; 153 154type_qualifier_list(zend_ffi_dcl *dcl): 155 ( type_qualifier(dcl) 156 | attributes(dcl) 157 )+ 158; 159 160type_qualifier(zend_ffi_dcl *dcl): 161 ("const"|"__const"|"__const__") 162 {dcl->flags |= ZEND_FFI_DCL_CONST;} 163 {dcl->attr |= ZEND_FFI_ATTR_CONST;} 164 | ("restrict"|"__restrict"|"__restrict__") 165 {dcl->flags |= ZEND_FFI_DCL_RESTRICT;} 166 | ("volatile"|"__volatile"|"__volatile__") 167 {dcl->flags |= ZEND_FFI_DCL_VOLATILE;} 168 | "_Atomic" 169 {dcl->flags |= ZEND_FFI_DCL_ATOMIC;} 170; 171 172type_specifier(zend_ffi_dcl *dcl): 173 {const char *name;} 174 {size_t name_len;} 175 ( {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);} 176 "void" 177 {dcl->flags |= ZEND_FFI_DCL_VOID;} 178 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED))) yy_error_sym("unexpected", sym);} 179 "char" 180 {dcl->flags |= ZEND_FFI_DCL_CHAR;} 181 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);} 182 "short" 183 {dcl->flags |= ZEND_FFI_DCL_SHORT;} 184 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG))) yy_error_sym("unexpected", sym);} 185 "int" 186 {dcl->flags |= ZEND_FFI_DCL_INT;} 187 | { 188 if (dcl->flags & ZEND_FFI_DCL_LONG) { 189 if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym); 190 dcl->flags |= ZEND_FFI_DCL_LONG_LONG; 191 } else { 192 if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_DOUBLE|ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym); 193 dcl->flags |= ZEND_FFI_DCL_LONG; 194 } 195 } 196 "long" 197 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym);} 198 "float" 199 {dcl->flags |= ZEND_FFI_DCL_FLOAT;} 200 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym);} 201 "double" 202 {dcl->flags |= ZEND_FFI_DCL_DOUBLE;} 203 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);} 204 "signed" 205 {dcl->flags |= ZEND_FFI_DCL_SIGNED;} 206 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);} 207 "unsigned" 208 {dcl->flags |= ZEND_FFI_DCL_UNSIGNED;} 209 | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);} 210 "_Bool" 211 {dcl->flags |= ZEND_FFI_DCL_BOOL;} 212 | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE|ZEND_FFI_DCL_LONG))) yy_error_sym("unexpected", sym);} 213 ("_Complex"|"complex"|"__complex"|"__complex__") 214 {dcl->flags |= ZEND_FFI_DCL_COMPLEX;} 215// | "_Atomic" "(" type_name ")" // TODO: not-implemented ??? 216 | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);} 217 struct_or_union_specifier(dcl) 218 | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);} 219 enum_specifier(dcl) 220 | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);} 221 {/*redeclaration of '%.*s' ??? */} 222 ID(&name, &name_len) 223 {dcl->flags |= ZEND_FFI_DCL_TYPEDEF_NAME;} 224 {zend_ffi_resolve_typedef(name, name_len, dcl);} 225 ) 226; 227 228struct_or_union_specifier(zend_ffi_dcl *dcl): 229 ( "struct" 230 {dcl->flags |= ZEND_FFI_DCL_STRUCT;} 231 | "union" 232 {dcl->flags |= ZEND_FFI_DCL_UNION;} 233 ) 234 attributes(dcl)? 235 ( {const char *name;} 236 {size_t name_len;} 237 ID(&name, &name_len) 238 {zend_ffi_declare_tag(name, name_len, dcl, 1);} 239 ( struct_contents(dcl) 240 {zend_ffi_declare_tag(name, name_len, dcl, 0);} 241 )? 242 | {zend_ffi_make_struct_type(dcl);} 243 struct_contents(dcl) 244 ) 245; 246 247struct_contents(zend_ffi_dcl *dcl): 248 "{" 249 ( struct_declaration(dcl) 250 ( ";" 251 struct_declaration(dcl) 252 )* 253 (";")? 254 )? 255 "}" 256 attributes(dcl)?+ 257 {zend_ffi_adjust_struct_size(dcl);} 258; 259 260 261struct_declaration(zend_ffi_dcl *struct_dcl): 262 {zend_ffi_dcl common_field_dcl = ZEND_FFI_ATTR_INIT;} 263 specifier_qualifier_list(&common_field_dcl) 264 ( /* empty */ 265 {zend_ffi_add_anonymous_field(struct_dcl, &common_field_dcl);} 266 | struct_declarator(struct_dcl, &common_field_dcl) 267 ( "," 268 {zend_ffi_dcl field_dcl = common_field_dcl;} 269 attributes(&field_dcl)? 270 struct_declarator(struct_dcl, &field_dcl) 271 )* 272 ) 273; 274 275struct_declarator(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl): 276 {const char *name = NULL;} 277 {size_t name_len = 0;} 278 {zend_ffi_val bits;} 279 ( declarator(field_dcl, &name, &name_len) 280 ( ":" 281 constant_expression(&bits) 282 attributes(field_dcl)? 283 {zend_ffi_add_bit_field(struct_dcl, name, name_len, field_dcl, &bits);} 284 | /*empty */ 285 attributes(field_dcl)? 286 {zend_ffi_add_field(struct_dcl, name, name_len, field_dcl);} 287 ) 288 | ":" 289 constant_expression(&bits) 290 {zend_ffi_add_bit_field(struct_dcl, NULL, 0, field_dcl, &bits);} 291 ) 292; 293 294enum_specifier(zend_ffi_dcl *dcl): 295 "enum" 296 {dcl->flags |= ZEND_FFI_DCL_ENUM;} 297 attributes(dcl)? 298 ( {const char *name;} 299 {size_t name_len;} 300 ID(&name, &name_len) 301 ( {zend_ffi_declare_tag(name, name_len, dcl, 0);} 302 "{" 303 enumerator_list(dcl) 304 "}" 305 attributes(dcl)?+ 306 | {zend_ffi_declare_tag(name, name_len, dcl, 1);} 307 ) 308 | "{" 309 {zend_ffi_make_enum_type(dcl);} 310 enumerator_list(dcl) 311 "}" 312 attributes(dcl)?+ 313 ) 314; 315 316enumerator_list(zend_ffi_dcl *enum_dcl): 317 {int64_t min = 0, max = 0, last = -1;} 318 enumerator(enum_dcl, &min, &max, &last) 319 ( "," 320 enumerator(enum_dcl, &min, &max, &last) 321 )* 322 ","? 323; 324 325enumerator(zend_ffi_dcl *enum_dcl, int64_t *min, int64_t *max, int64_t *last): 326 {const char *name;} 327 {size_t name_len;} 328 {zend_ffi_val val = {.kind = ZEND_FFI_VAL_EMPTY};} 329 ID(&name, &name_len) 330 ( "=" 331 constant_expression(&val) 332 )? 333 {zend_ffi_add_enum_val(enum_dcl, name, name_len, &val, min, max, last);} 334; 335 336declarator(zend_ffi_dcl *dcl, const char **name, size_t *name_len): 337 {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};} 338 {bool nested = 0;} 339 pointer(dcl)? 340 ( ID(name, name_len) 341 | "(" 342 attributes(&nested_dcl)? 343 declarator(&nested_dcl, name, name_len) 344 ")" 345 {nested = 1;} 346 ) 347 array_or_function_declarators(dcl, &nested_dcl)? 348 {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);} 349; 350 351abstract_declarator(zend_ffi_dcl *dcl): 352 {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};} 353 {bool nested = 0;} 354 pointer(dcl)? 355 ( &nested_declarator_start 356 "(" 357 attributes(&nested_dcl)? 358 abstract_declarator(&nested_dcl) 359 ")" 360 {nested = 1;} 361 )? 362 array_or_function_declarators(dcl, &nested_dcl)? 363 {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);} 364; 365 366parameter_declarator(zend_ffi_dcl *dcl, const char **name, size_t *name_len): 367 {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};} 368 {bool nested = 0;} 369 pointer(dcl)? 370 ( &nested_declarator_start 371 "(" 372 attributes(&nested_dcl)? 373 parameter_declarator(&nested_dcl, name, name_len) 374 ")" 375 {nested = 1;} 376 | ID(name, name_len) 377 | /* empty */ 378 ) 379 array_or_function_declarators(dcl, &nested_dcl)? 380 {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);} 381; 382 383pointer(zend_ffi_dcl *dcl): 384 ( "*" 385 {zend_ffi_make_pointer_type(dcl);} 386 type_qualifier_list(dcl)? 387 )+ 388; 389 390array_or_function_declarators(zend_ffi_dcl *dcl, zend_ffi_dcl *nested_dcl): 391 {zend_ffi_dcl dummy = ZEND_FFI_ATTR_INIT;} 392 {zend_ffi_val len = {.kind = ZEND_FFI_VAL_EMPTY};} 393 {HashTable *args = NULL;} 394 {uint32_t attr = 0;} 395 ( "[" 396 ( "static" 397 type_qualifier_list(&dummy)? 398 assignment_expression(&len) 399 | type_qualifier_list(&dummy) 400 ( "static" assignment_expression(&len) 401 | /* empty */ 402 {attr |= ZEND_FFI_ATTR_INCOMPLETE_ARRAY;} 403 | "*" 404 {attr |= ZEND_FFI_ATTR_VLA;} 405 | assignment_expression(&len) 406 ) 407 | ( /* empty */ 408 {attr |= ZEND_FFI_ATTR_INCOMPLETE_ARRAY;} 409 | "*" 410 {attr |= ZEND_FFI_ATTR_VLA;} 411 | assignment_expression(&len) 412 ) 413 ) 414 "]" 415 array_or_function_declarators(dcl, nested_dcl)? 416 {dcl->attr |= attr;} 417 {zend_ffi_make_array_type(dcl, &len);} 418 | "(" 419 ( 420 parameter_declaration(&args) 421 ( "," 422 parameter_declaration(&args) 423 )* 424 ( 425 "," 426 "..." 427 {attr |= ZEND_FFI_ATTR_VARIADIC;} 428 )? 429 | "..." 430 {attr |= ZEND_FFI_ATTR_VARIADIC;} 431 )? 432 ")" 433 array_or_function_declarators(dcl, nested_dcl)? 434 {dcl->attr |= attr;} 435 {zend_ffi_make_func_type(dcl, args, nested_dcl);} 436// | "(" (ID ("," ID)*)? ")" // TODO: ANSI function not-implemented ??? 437 ) 438; 439 440parameter_declaration(HashTable **args): 441 {const char *name = NULL;} 442 {size_t name_len = 0;} 443 {bool old_allow_vla = FFI_G(allow_vla);} 444 {FFI_G(allow_vla) = 1;} 445 {zend_ffi_dcl param_dcl = ZEND_FFI_ATTR_INIT;} 446 specifier_qualifier_list(¶m_dcl) 447 parameter_declarator(¶m_dcl, &name, &name_len) 448 /*attributes(¶m_dcl)? conflict ???*/ 449 {zend_ffi_add_arg(args, name, name_len, ¶m_dcl);} 450 {FFI_G(allow_vla) = old_allow_vla;} 451; 452 453type_name(zend_ffi_dcl *dcl): 454 specifier_qualifier_list(dcl) 455 abstract_declarator(dcl) 456; 457 458attributes(zend_ffi_dcl *dcl): 459 {const char *name;} 460 {size_t name_len;} 461 {zend_ffi_val val;} 462 ( 463 ("__attribute"|"__attribute__") 464 "(" 465 "(" 466 attrib(dcl) 467 ( "," 468 attrib(dcl) 469 )* 470 ")" 471 ")" 472 | "__declspec" 473 "(" 474 ( ID(&name, &name_len) 475 ( 476 "(" 477 assignment_expression(&val) 478 {zend_ffi_add_msvc_attribute_value(dcl, name, name_len, &val);} 479 ")" 480 )? 481 )+ 482 ")" 483 | "__cdecl" 484 {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_CDECL);} 485 | "__stdcall" 486 {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_STDCALL);} 487 | "__fastcall" 488 {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_FASTCALL);} 489 | "__thiscall" 490 {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_THISCALL);} 491 | "__vectorcall" 492 {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_VECTORCALL);} 493 )++ 494; 495 496attrib(zend_ffi_dcl *dcl): 497 {const char *name;} 498 {size_t name_len;} 499 {int n;} 500 {zend_ffi_val val;} 501 {bool orig_attribute_parsing;} 502 ( ID(&name, &name_len) 503 ( /* empty */ 504 {zend_ffi_add_attribute(dcl, name, name_len);} 505 | "(" 506 {orig_attribute_parsing = FFI_G(attribute_parsing);} 507 {FFI_G(attribute_parsing) = 1;} 508 assignment_expression(&val) 509 {zend_ffi_add_attribute_value(dcl, name, name_len, 0, &val);} 510 {n = 0;} 511 ( "," 512 assignment_expression(&val) 513 {zend_ffi_add_attribute_value(dcl, name, name_len, ++n, &val);} 514 )* 515 {FFI_G(attribute_parsing) = orig_attribute_parsing;} 516 ")" 517 ) 518 | "const" 519 | "__const" 520 | "__const__" 521 )? 522; 523 524initializer: 525 {zend_ffi_val dummy;} 526 "=" 527 ( assignment_expression(&dummy) 528 | "{" designation? initializer ( "," designation? initializer)* ","? "}" 529 ) 530; 531 532designation: 533 {const char *name;} 534 {size_t name_len;} 535 {zend_ffi_val dummy;} 536 ( "[" constant_expression(&dummy) "]" 537 | "." ID(&name, &name_len) 538 )+ 539 "=" 540; 541 542expr_list: 543 {zend_ffi_val dummy;} 544 assignment_expression(&dummy) 545 ( "," 546 assignment_expression(&dummy) 547 )* 548; 549 550expression(zend_ffi_val *val): 551 assignment_expression(val) 552 ( "," 553 assignment_expression(val) 554 )* 555; 556 557assignment_expression(zend_ffi_val *val): 558// ( unary_expression 559// ("="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=") 560// )* // TODO: not-implemented ??? 561 conditional_expression(val) 562; 563 564constant_expression(zend_ffi_val *val): 565 conditional_expression(val) 566; 567 568conditional_expression(zend_ffi_val *val): 569 {zend_ffi_val op2, op3;} 570 logical_or_expression(val) 571 ( "?" 572 expression(&op2) 573 ":" 574 conditional_expression(&op3) 575 {zend_ffi_expr_conditional(val, &op2, &op3);} 576 )? 577; 578 579logical_or_expression(zend_ffi_val *val): 580 {zend_ffi_val op2;} 581 logical_and_expression(val) 582 ( "||" 583 logical_and_expression(&op2) 584 {zend_ffi_expr_bool_or(val, &op2);} 585 )* 586; 587 588logical_and_expression(zend_ffi_val *val): 589 {zend_ffi_val op2;} 590 inclusive_or_expression(val) 591 ( "&&" 592 inclusive_or_expression(&op2) 593 {zend_ffi_expr_bool_and(val, &op2);} 594 )* 595; 596 597inclusive_or_expression(zend_ffi_val *val): 598 {zend_ffi_val op2;} 599 exclusive_or_expression(val) 600 ( "|" 601 exclusive_or_expression(&op2) 602 {zend_ffi_expr_bw_or(val, &op2);} 603 )* 604; 605 606exclusive_or_expression(zend_ffi_val *val): 607 {zend_ffi_val op2;} 608 and_expression(val) 609 ( "^" 610 and_expression(&op2) 611 {zend_ffi_expr_bw_xor(val, &op2);} 612 )* 613; 614 615and_expression(zend_ffi_val *val): 616 {zend_ffi_val op2;} 617 equality_expression(val) 618 ( "&" 619 equality_expression(&op2) 620 {zend_ffi_expr_bw_and(val, &op2);} 621 )* 622; 623 624equality_expression(zend_ffi_val *val): 625 {zend_ffi_val op2;} 626 relational_expression(val) 627 ( "==" 628 relational_expression(&op2) 629 {zend_ffi_expr_is_equal(val, &op2);} 630 | "!=" 631 relational_expression(&op2) 632 {zend_ffi_expr_is_not_equal(val, &op2);} 633 )* 634; 635 636relational_expression(zend_ffi_val *val): 637 {zend_ffi_val op2;} 638 shift_expression(val) 639 ( "<" 640 shift_expression(&op2) 641 {zend_ffi_expr_is_less(val, &op2);} 642 | ">" 643 shift_expression(&op2) 644 {zend_ffi_expr_is_greater(val, &op2);} 645 | "<=" 646 shift_expression(&op2) 647 {zend_ffi_expr_is_less_or_equal(val, &op2);} 648 | ">=" 649 shift_expression(&op2) 650 {zend_ffi_expr_is_greater_or_equal(val, &op2);} 651 )* 652; 653 654shift_expression(zend_ffi_val *val): 655 {zend_ffi_val op2;} 656 additive_expression(val) 657 ( "<<" 658 additive_expression(&op2) 659 {zend_ffi_expr_shift_left(val, &op2);} 660 | ">>" 661 additive_expression(&op2) 662 {zend_ffi_expr_shift_right(val, &op2);} 663 )* 664; 665 666additive_expression(zend_ffi_val *val): 667 {zend_ffi_val op2;} 668 multiplicative_expression(val) 669 ( "+" 670 multiplicative_expression(&op2) 671 {zend_ffi_expr_add(val, &op2);} 672 | "-" 673 multiplicative_expression(&op2) 674 {zend_ffi_expr_sub(val, &op2);} 675 )* 676; 677 678multiplicative_expression(zend_ffi_val *val): 679 {zend_ffi_val op2;} 680 cast_expression(val) 681 ( "*" 682 cast_expression(&op2) 683 {zend_ffi_expr_mul(val, &op2);} 684 | "/" 685 cast_expression(&op2) 686 {zend_ffi_expr_div(val, &op2);} 687 | "%" 688 cast_expression(&op2) 689 {zend_ffi_expr_mod(val, &op2);} 690 )* 691; 692 693cast_expression(zend_ffi_val *val): 694 {int do_cast = 0;} 695 {zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;} 696 ( &( "(" type_name_start ) 697 "(" 698 type_name(&dcl) 699 ")" 700 {do_cast = 1;} 701 )? 702 unary_expression(val) 703 {if (do_cast) zend_ffi_expr_cast(val, &dcl);} 704; 705 706unary_expression(zend_ffi_val *val): 707 {const char *name;} 708 {size_t name_len;} 709 {zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;} 710 ( ID(&name, &name_len) 711 {zend_ffi_resolve_const(name, name_len, val);} 712 ( 713 ( "[" 714 expr_list 715 "]" 716 | "(" 717 expr_list? 718 ")" 719 | "." 720 ID(&name, &name_len) 721 | "->" 722 ID(&name, &name_len) 723 | "++" 724 | "--" 725 ) 726 {zend_ffi_val_error(val);} 727 )* 728 | OCTNUMBER(val) 729 | DECNUMBER(val) 730 | HEXNUMBER(val) 731 | FLOATNUMBER(val) 732 | STRING(val) 733 | CHARACTER(val) 734 | "(" 735 expression(val) 736 ")" 737 | "++" 738 unary_expression(val) 739 {zend_ffi_val_error(val);} 740 | "--" 741 unary_expression(val) 742 {zend_ffi_val_error(val);} 743 | "&" 744 cast_expression(val) 745 {zend_ffi_val_error(val);} 746 | "*" 747 cast_expression(val) 748 {zend_ffi_val_error(val);} 749 | "+" 750 cast_expression(val) 751 {zend_ffi_expr_plus(val);} 752 | "-" 753 cast_expression(val) 754 {zend_ffi_expr_neg(val);} 755 | "~" 756 cast_expression(val) 757 {zend_ffi_expr_bw_not(val);} 758 | "!" 759 cast_expression(val) 760 {zend_ffi_expr_bool_not(val);} 761 | "sizeof" 762 ( &( "(" type_name_start ) 763 "(" 764 type_name(&dcl) 765 ")" 766 {zend_ffi_expr_sizeof_type(val, &dcl);} 767 | unary_expression(val) 768 {zend_ffi_expr_sizeof_val(val);} 769 ) 770 | "_Alignof" 771 "(" 772 type_name(&dcl) 773 ")" 774 {zend_ffi_expr_alignof_type(val, &dcl);} 775 | ("__alignof"|"__alignof__") 776 ( &( "(" type_name_start ) 777 "(" 778 type_name(&dcl) 779 ")" 780 {zend_ffi_expr_alignof_type(val, &dcl);} 781 | unary_expression(val) 782 {zend_ffi_expr_alignof_val(val);} 783 ) 784 ) 785; 786 787/* lookahead rules */ 788nested_declarator_start: 789 "(" 790 ( ?{!zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text)} 791 ID 792 | "__attribute" 793 | "__attribute__" 794 | "__declspec" 795 | "*" 796 | "(" 797 | "[" 798 ) 799; 800 801type_name_start: 802 ( ?{zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text)} 803 ID 804 | "void" 805 | "char" 806 | "short" 807 | "int" 808 | "long" 809 | "float" 810 | "double" 811 | "signed" 812 | "unsigned" 813 | "_Bool" 814 | "_Complex" 815 | "complex" 816 | "__complex" 817 | "__complex__" 818 | "struct" 819 | "union" 820 | "enum" 821 | "const" 822 | "__const" 823 | "__const__" 824 | "restrict" 825 | "__restict" 826 | "__restrict__" 827 | "volatile" 828 | "__volatile" 829 | "__volatile__" 830 | "_Atomic" 831 | "__attribute" 832 | "__attribute__" 833 | "__declspec" 834 ) 835; 836 837/* scanner rules */ 838ID(const char **name, size_t *name_len): 839 /[A-Za-z_][A-Za-z_0-9]*/ 840 {*name = (const char*)yy_text; *name_len = yy_pos - yy_text;} 841; 842 843OCTNUMBER(zend_ffi_val *val): 844 /0[0-7]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/ 845 {zend_ffi_val_number(val, 8, (const char*)yy_text, yy_pos - yy_text);} 846; 847 848DECNUMBER(zend_ffi_val *val): 849 /[1-9][0-9]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/ 850 {zend_ffi_val_number(val, 10, (const char*)yy_text, yy_pos - yy_text);} 851; 852 853HEXNUMBER(zend_ffi_val *val): 854 /0[xX][0-9A-Fa-f][0-9A-Fa-f]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/ 855 {zend_ffi_val_number(val, 16, (const char*)yy_text + 2, yy_pos - yy_text - 2);} 856; 857 858FLOATNUMBER(zend_ffi_val *val): 859 /([0-9]*\.[0-9]+([Ee][\+\-]?[0-9]+)?|[0-9]+\.([Ee][\+\-]?[0-9]+)?|[0-9]+[Ee][\+\-]?[0-9]+)[flFL]?/ 860 {zend_ffi_val_float_number(val, (const char*)yy_text, yy_pos - yy_text);} 861; 862 863STRING(zend_ffi_val *val): 864 /(u8|u|U|L)?"([^"\\]|\\.)*"/ 865 {zend_ffi_val_string(val, (const char*)yy_text, yy_pos - yy_text);} 866; 867 868CHARACTER(zend_ffi_val *val): 869 /[LuU]?'([^'\\]|\\.)*'/ 870 {zend_ffi_val_character(val, (const char*)yy_text, yy_pos - yy_text);} 871; 872 873EOL: /\r\n|\r|\n/; 874WS: /[ \t\f\v]+/; 875ONE_LINE_COMMENT: /(\/\/|#)[^\r\n]*(\r\n|\r|\n)/; 876COMMENT: /\/\*([^\*]|\*+[^\*\/])*\*+\//; 877 878SKIP: ( EOL | WS | ONE_LINE_COMMENT | COMMENT )*; 879 880%% 881int zend_ffi_parse_decl(const char *str, size_t len) { 882 if (SETJMP(FFI_G(bailout))==0) { 883 FFI_G(allow_vla) = 0; 884 FFI_G(attribute_parsing) = 0; 885 yy_buf = (unsigned char*)str; 886 yy_end = yy_buf + len; 887 parse(); 888 return SUCCESS; 889 } else { 890 return FAILURE; 891 } 892} 893 894int zend_ffi_parse_type(const char *str, size_t len, zend_ffi_dcl *dcl) { 895 int sym; 896 897 if (SETJMP(FFI_G(bailout))==0) { 898 FFI_G(allow_vla) = 0; 899 FFI_G(attribute_parsing) = 0; 900 yy_pos = yy_text = yy_buf = (unsigned char*)str; 901 yy_end = yy_buf + len; 902 yy_line = 1; 903 sym = parse_type_name(get_sym(), dcl); 904 if (sym != YY_EOF) { 905 yy_error_sym("<EOF> expected, got", sym); 906 } 907 zend_ffi_validate_type_name(dcl); 908 return SUCCESS; 909 } else { 910 return FAILURE; 911 }; 912} 913 914static void yy_error(const char *msg) { 915 zend_ffi_parser_error("%s at line %d", msg, yy_line); 916} 917 918static void yy_error_sym(const char *msg, int sym) { 919 zend_ffi_parser_error("%s '%s' at line %d", msg, sym_name[sym], yy_line); 920} 921