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