X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fparser_proc_grammar.y;h=cd828e63861748e0a3710336c4e8e562d5f2b438;hp=4a1cc1957ec2336d6e60dcee3d8747b21f24e569;hb=fb8f7887c289ae74d6e8dd85d55ae09e6796e890;hpb=cffcbdd1df9f6d5dcf78f49a3d1b44cefe21b2f5 diff --git a/src/parser_proc_grammar.y b/src/parser_proc_grammar.y index 4a1cc19..cd828e6 100644 --- a/src/parser_proc_grammar.y +++ b/src/parser_proc_grammar.y @@ -57,8 +57,8 @@ static inline void psi_parser_proc_add_const(struct psi_parser *P, struct psi_co } static inline void psi_parser_proc_add_decl(struct psi_parser *P, struct psi_decl *decl) { assert(decl); - - if (psi_decl_is_blacklisted(decl->func->var->name)) { + + if (psi_decl_is_blacklisted(decl->func->var->name->val)) { psi_decl_free(&decl); return; } @@ -68,6 +68,14 @@ static inline void psi_parser_proc_add_decl(struct psi_parser *P, struct psi_dec } P->decls = psi_plist_add(P->decls, &decl); } +static inline void psi_parser_proc_add_decl_extvars(struct psi_parser *P, struct psi_plist *list) { + assert(list); + if (!P->vars) { + P->vars = psi_plist_init((psi_plist_dtor) psi_decl_extvar_free); + } + P->vars = psi_plist_add_r(P->vars, psi_plist_count(list), psi_plist_eles(list)); + free(list); +} static inline void psi_parser_proc_add_impl(struct psi_parser *P, struct psi_impl *impl) { assert(impl); if (!P->impls) { @@ -275,8 +283,8 @@ struct psi_parser; %type lib optional_name enum_name struct_name union_name %destructor {psi_token_free(&$$);} lib optional_name enum_name struct_name union_name -%type cpp_message_token cpp_include_token cpp_header_token cpp_no_arg_token cpp_name_arg_token cpp_exp_arg_token cpp_special_name_token -%destructor {} cpp_message_token cpp_include_token cpp_header_token cpp_no_arg_token cpp_name_arg_token cpp_exp_arg_token cpp_special_name_token +%type cpp_message_token cpp_include_token cpp_header_token cpp_no_arg_token cpp_name_arg_token cpp_exp_arg_token +%destructor {} cpp_message_token cpp_include_token cpp_header_token cpp_no_arg_token cpp_name_arg_token cpp_exp_arg_token %type name_token any_noeol_token binary_op_token unary_op_token %destructor {} name_token any_noeol_token binary_op_token unary_op_token @@ -296,25 +304,26 @@ struct psi_parser; %type cpp_macro_exp %destructor {psi_num_exp_free(&$$);} cpp_macro_exp -%type constant_type_token impl_def_val_token -%destructor {} constant_type_token impl_def_val_token +%type impl_def_val_token +%destructor {} impl_def_val_token %type constant %destructor {psi_const_free(&$$);} constant -%type constant_type -%destructor {psi_const_type_free(&$$);} constant_type %type impl_def_val %destructor {psi_impl_def_val_free(&$$);} impl_def_val %type decl_real_type decl_int_type decl_type_simple %destructor {psi_token_free(&$$);} decl_real_type decl_int_type decl_type_simple +%type decl_asm quoted_strings +%destructor {psi_token_free(&$$);} decl_asm quoted_strings + %type decl_type qualified_decl_type decl_type_complex %destructor {psi_decl_type_free(&$$);} decl_type qualified_decl_type decl_type_complex -%type decl_stmt decl decl_body decl_func_body decl_functor_body -%destructor {psi_decl_free(&$$);} decl_stmt decl decl_body decl_func_body decl_functor_body -%type decl_typedef decl_func decl_functor decl_arg decl_anon_arg typedef typedef_decl typedef_anon typedef_anon_decl -%destructor {psi_decl_arg_free(&$$);} decl_typedef decl_func decl_functor decl_arg decl_anon_arg typedef typedef_decl typedef_anon typedef_anon_decl +%type decl_stmt decl decl_body decl_func_body decl_functor_body decl_anon_functor_body ignored_decl +%destructor {psi_decl_free(&$$);} decl_stmt decl decl_body decl_func_body decl_functor_body decl_anon_functor_body ignored_decl +%type decl_typedef decl_func decl_functor decl_anon_functor decl_arg decl_anon_arg typedef typedef_decl typedef_anon typedef_anon_decl +%destructor {psi_decl_arg_free(&$$);} decl_typedef decl_func decl_functor decl_anon_functor decl_arg decl_anon_arg typedef typedef_decl typedef_anon typedef_anon_decl %type decl_var %destructor {psi_decl_var_free(&$$);} decl_var %type decl_struct @@ -325,8 +334,8 @@ struct psi_parser; %destructor {psi_decl_enum_free(&$$);} decl_enum %type decl_enum_item %destructor {psi_decl_enum_item_free(&$$);} decl_enum_item -%type decl_args decl_struct_args struct_args_block struct_args struct_arg_var_list decl_enum_items decl_vars decl_vars_with_layout call_decl_vars -%destructor {psi_plist_free($$);} decl_args decl_struct_args struct_args_block struct_args struct_arg_var_list decl_enum_items decl_vars decl_vars_with_layout call_decl_vars +%type decl_args decl_arg_list decl_struct_args struct_args_block struct_args struct_arg_var_list decl_enum_items decl_vars decl_vars_with_layout call_decl_vars decl_extvar_stmt decl_extvar_list +%destructor {psi_plist_free($$);} decl_args decl_arg_list decl_struct_args struct_args_block struct_args struct_arg_var_list decl_enum_items decl_vars decl_vars_with_layout call_decl_vars decl_extvar_stmt decl_extvar_list %type align_and_size %destructor {} align_and_size @@ -342,8 +351,8 @@ struct psi_parser; %destructor {psi_impl_func_free(&$$);} impl_func %type impl_arg %destructor {psi_impl_arg_free(&$$);} impl_arg -%type impl_type -%destructor {psi_impl_type_free(&$$);} impl_type +%type impl_type impl_type_restricted +%destructor {psi_impl_type_free(&$$);} impl_type impl_type_restricted %type impl_var %destructor {psi_impl_var_free(&$$);} impl_var @@ -373,11 +382,11 @@ struct psi_parser; %destructor {psi_free_stmt_free(&$$);} free_stmt %type free_exp %destructor {psi_free_exp_free(&$$);} free_exp - + %type impl_stmt %destructor {psi_impl_stmt_free(&$$);} impl_stmt -%type impl_type_token callback_rval let_func_token set_func_token assert_stmt_token -%destructor {psi_token_free(&$$);} impl_type_token callback_rval let_func_token set_func_token assert_stmt_token +%type impl_type_token impl_type_restricted_token impl_type_extended_token callback_rval let_func_token set_func_token assert_stmt_token +%destructor {psi_token_free(&$$);} impl_type_token impl_type_restricted_token impl_type_extended_token callback_rval let_func_token set_func_token assert_stmt_token %type impl_args impl_stmts let_exps let_func_exps callback_arg_list callback_args set_exps set_func_exps free_exps %destructor {psi_plist_free($$);} impl_args impl_stmts let_exps let_func_exps callback_arg_list callback_args set_exps set_func_exps free_exps @@ -396,9 +405,9 @@ struct psi_parser; /* rules */ -binary_op_token: PIPE | CARET | AMPERSAND | LSHIFT | RSHIFT | PLUS | MINUS | ASTERISK | SLASH | MODULO | RCHEVR | LCHEVR | CMP_GE | CMP_LE | OR | AND | CMP_EQ | CMP_NE ; +binary_op_token: PIPE | CARET | AMPERSAND | LSHIFT | RSHIFT | PLUS | MINUS | ASTERISK | SLASH | MODULO | RCHEVR | LCHEVR | CMP_GE | CMP_LE | OR | AND | CMP_EQ | CMP_NE ; unary_op_token: TILDE | NOT | PLUS | MINUS ; -name_token: NAME | FUNCTION | TEMP | FREE | SET | LET | CALLOC | CALLBACK | LIB | BOOL | STRING | ERROR | WARNING | LINE | PRAGMA_ONCE | PRAGMA | AS | let_func_token | set_func_token; +name_token: NAME | FUNCTION | TEMP | FREE | SET | LET | CALLOC | CALLBACK | LIB | BOOL | STRING | MIXED | ARRAY | OBJECT | ERROR | WARNING | LINE | PRAGMA_ONCE | PRAGMA | AS | let_func_token | set_func_token; any_noeol_token: BOOL | CHAR | SHORT | INT | SIGNED | UNSIGNED | LONG | FLOAT | DOUBLE | STRING | MIXED | ARRAY | OBJECT | CALLABLE | VOID | ZVAL | NULL | TRUE | FALSE | NAME | NSNAME | DOLLAR_NAME | NUMBER | QUOTED_STRING | QUOTED_CHAR | EOF | EOS | LPAREN | RPAREN | COMMA | COLON | LBRACE | RBRACE | LBRACKET | RBRACKET | EQUALS | HASH | PIPE | CARET | AMPERSAND | LSHIFT | RSHIFT | PLUS | MINUS | ASTERISK | SLASH | MODULO | LCHEVR | RCHEVR | CMP_GE | CMP_LE | OR | AND | CMP_EQ | CMP_NE | TILDE | NOT | PERIOD | BACKSLASH | ELLIPSIS | ERROR | WARNING | LINE | PRAGMA | PRAGMA_ONCE | IIF | IF | IFDEF | IFNDEF | ELSE | ELIF | ENDIF | DEFINE | DEFINED | UNDEF | INCLUDE | TYPEDEF | STRUCT | UNION | ENUM | CONST | LIB | STATIC | CALLBACK | FUNCTION | LET | SET | TEMP | FREE | RETURN | PRE_ASSERT | POST_ASSERT | BOOLVAL | INTVAL | STRVAL | PATHVAL | STRLEN | FLOATVAL | ARRVAL | OBJVAL | COUNT | CALLOC | TO_BOOL | TO_INT | TO_STRING | TO_FLOAT | TO_ARRAY | TO_OBJECT | COMMENT | CPP_HEADER | CPP_PASTE | CPP_INLINE | CPP_RESTRICT | CPP_EXTENSION | CPP_ASM | SIZEOF | VOLATILE | AS; any_nobrace_token: BOOL | CHAR | SHORT | INT | SIGNED | UNSIGNED | LONG | FLOAT | DOUBLE | STRING | MIXED | ARRAY | OBJECT | CALLABLE | VOID | ZVAL | NULL | TRUE | FALSE | NAME | NSNAME | DOLLAR_NAME | NUMBER | QUOTED_STRING | QUOTED_CHAR | EOF | EOS | LPAREN | RPAREN | COMMA | COLON | LBRACKET | RBRACKET | EQUALS | HASH | PIPE | CARET | AMPERSAND | LSHIFT | RSHIFT | PLUS | MINUS | ASTERISK | SLASH | MODULO | LCHEVR | RCHEVR | CMP_GE | CMP_LE | OR | AND | CMP_EQ | CMP_NE | TILDE | NOT | PERIOD | BACKSLASH | ELLIPSIS | ERROR | WARNING | LINE | PRAGMA | PRAGMA_ONCE | IIF | IF | IFDEF | IFNDEF | ELSE | ELIF | ENDIF | DEFINE | DEFINED | UNDEF | INCLUDE | TYPEDEF | STRUCT | UNION | ENUM | CONST | LIB | STATIC | CALLBACK | FUNCTION | LET | SET | TEMP | FREE | RETURN | PRE_ASSERT | POST_ASSERT | BOOLVAL | INTVAL | STRVAL | PATHVAL | STRLEN | FLOATVAL | ARRVAL | OBJVAL | COUNT | CALLOC | TO_BOOL | TO_INT | TO_STRING | TO_FLOAT | TO_ARRAY | TO_OBJECT | COMMENT | CPP_HEADER | CPP_PASTE | CPP_INLINE | CPP_RESTRICT | CPP_EXTENSION | CPP_ASM | SIZEOF | VOLATILE | AS; @@ -422,12 +431,8 @@ block: } } | lib { - if (P->file.ln) { - P->error(PSI_DATA(P), $lib, PSI_WARNING, - "Extra 'lib \"%s\"' statement has no effect", $lib->text); - } else { - P->file.ln = strndup($lib->text, $lib->size); - } + char *libname = strdup($lib->text->val); + P->file.libnames = psi_plist_add(P->file.libnames, &libname); } | constant { psi_parser_proc_add_const(P, $constant); @@ -435,8 +440,15 @@ block: | decl_stmt { psi_parser_proc_add_decl(P, $decl_stmt); } -| ignored_decl -| decl_ext_var_stmt +| decl_extvar_stmt[list] { + psi_parser_proc_add_decl_extvars(P, $list); +} +| ignored_decl { + if (P->flags & PSI_DEBUG) { + P->error(PSI_DATA(P), $ignored_decl->func->token, PSI_NOTICE, "Ignored decl: %s", $ignored_decl->func->var->name->val); + } + psi_decl_free(&$ignored_decl); +} | decl_typedef[def] { psi_parser_proc_add_typedef(P, $def); } @@ -473,20 +485,20 @@ cpp_exp[exp]: cpp_message_token cpp_macro_decl_tokens[tokens] { if ($tokens) { struct psi_token *msg = NULL; - + if (psi_plist_get($tokens, 0, &msg)) { size_t index = 1; struct psi_token *next; - msg = psi_token_copy(msg); + msg = psi_token_copy(msg); while (psi_plist_get($tokens, index++, &next)) { struct psi_token *old = msg; msg = psi_token_cat(" ", 2, msg, next); - free(old); + psi_token_free(&old); } } psi_plist_free($tokens); - + $exp = psi_cpp_exp_init($cpp_message_token->type, msg); } else { $exp = psi_cpp_exp_init($cpp_message_token->type, NULL); @@ -501,7 +513,7 @@ cpp_exp[exp]: $exp = psi_cpp_exp_init($cpp_no_arg_token->type, NULL); $exp->token = psi_token_copy($cpp_no_arg_token); } -| cpp_name_arg_token cpp_special_name_token[name_token] { +| cpp_name_arg_token any_noeol_token[name_token] { $name_token->type = PSI_T_NAME; $exp = psi_cpp_exp_init($cpp_name_arg_token->type, psi_token_copy($name_token)); $exp->token = psi_token_copy($cpp_name_arg_token); @@ -529,7 +541,7 @@ cpp_ignored_token: | PRAGMA ; -cpp_message_token: +cpp_message_token: ERROR | WARNING ; @@ -556,30 +568,31 @@ cpp_name_arg_token: | UNDEF ; -cpp_exp_arg_token: +cpp_exp_arg_token: IF | ELIF ; -cpp_special_name_token: - name_token -| NULL -| TRUE -| FALSE -| CPP_RESTRICT -| CPP_EXTENSION -| CPP_INLINE -; - cpp_macro_decl[macro]: - name_token NO_WHITESPACE LPAREN cpp_macro_sig RPAREN cpp_macro_decl_tokens { + any_noeol_token[name_token] cpp_macro_decl_tokens %dprec 1 { + $name_token->type = PSI_T_NAME; + $macro = psi_cpp_macro_decl_init(NULL, $cpp_macro_decl_tokens, NULL); + $macro->token = psi_token_copy($name_token); +} +| name_token NO_WHITESPACE LPAREN cpp_macro_sig RPAREN cpp_macro_decl_tokens %dprec 2 { $name_token->type = PSI_T_NAME; $macro = psi_cpp_macro_decl_init($cpp_macro_sig, $cpp_macro_decl_tokens, NULL); $macro->token = psi_token_copy($name_token); } -| cpp_special_name_token[name_token] cpp_macro_decl_tokens { +| name_token cpp_macro_exp[num_exp] %dprec 2 { $name_token->type = PSI_T_NAME; - $macro = psi_cpp_macro_decl_init(NULL, $cpp_macro_decl_tokens, NULL); + $macro = psi_cpp_macro_decl_init(NULL, psi_num_exp_tokens($num_exp, NULL), $num_exp); + $macro->token = psi_token_copy($name_token); +} +| name_token quoted_strings[strings] %dprec 2 { + struct psi_plist *list = psi_plist_init((psi_plist_dtor) psi_token_free); + $name_token->type = PSI_T_NAME; + $macro = psi_cpp_macro_decl_init(NULL, psi_plist_add(list, &$strings), NULL); $macro->token = psi_token_copy($name_token); } ; @@ -652,8 +665,9 @@ cpp_macro_exp[exp]: $name_token->type = PSI_T_NAME; exists = psi_cpp_defined(P->preproc, $name_token); - $exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists, 0)); - $exp->token = psi_token_copy($name_token); + $exp = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINED, &exists, 0)); + $exp->token = psi_token_copy($DEFINED); + $exp->data.n->token = psi_token_copy($name_token); } } | DEFINED LPAREN name_token RPAREN { @@ -662,8 +676,9 @@ cpp_macro_exp[exp]: $name_token->type = PSI_T_NAME; exists = psi_cpp_defined(P->preproc, $name_token); - $exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists, 0)); - $exp->token = psi_token_copy($name_token); + $exp = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINED, &exists, 0)); + $exp->token = psi_token_copy($DEFINED); + $exp->data.n->token = psi_token_copy($name_token); } } | NUMBER { @@ -691,6 +706,8 @@ cpp_macro_exp[exp]: $exp = psi_num_exp_init_num(psi_number_init(PSI_T_FUNCTION, psi_cpp_macro_call_init($name_token->text, $cpp_macro_call_args), 0)); $exp->token = psi_token_copy($name_token); + $exp->data.n->token = psi_token_copy($name_token); + $exp->data.n->data.call->token = psi_token_copy($name_token); } ; @@ -702,8 +719,16 @@ cpp_macro_call_args[args]: ; cpp_macro_call_arg_list[args]: - cpp_macro_exp { - $args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_num_exp_free), + CPP_HEADER { + /* TODO: clang include test macros */ + uint8_t no = 1; + struct psi_num_exp *exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &no, 0)); + exp->token = psi_token_copy($CPP_HEADER); + exp->data.n->token = psi_token_copy($CPP_HEADER); + $args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_num_exp_free), &exp); +} +| cpp_macro_exp { + $args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_num_exp_free), &$cpp_macro_exp); } | cpp_macro_call_arg_list[args_] COMMA cpp_macro_exp { @@ -712,63 +737,28 @@ cpp_macro_call_arg_list[args]: ; constant[const]: - CONST constant_type NSNAME EQUALS impl_def_val EOS { - $const = psi_const_init($constant_type, $NSNAME->text, $impl_def_val); + CONST impl_type_restricted[type] NSNAME EQUALS impl_def_val EOS { + $const = psi_const_init($type, $NSNAME->text, $impl_def_val); $const->token = psi_token_copy($NSNAME); } -; - -constant_type[type]: - constant_type_token[token] { - $type = psi_const_type_init($token->type, $token->text); +| CONST NSNAME EQUALS impl_def_val EOS { + $const = psi_const_init(NULL, $NSNAME->text, $impl_def_val); + $const->token = psi_token_copy($NSNAME); } ; -constant_type_token: - BOOL -| INT -| FLOAT -| STRING -; - impl_def_val[val]: - %empty { - $val = NULL; + impl_def_val_token[token] %dprec 2 { + $val = psi_impl_def_val_init($token->type, $token->text); + $val->token = psi_token_copy($token); } | num_exp[num] %dprec 1 { - if (psi_num_exp_validate(PSI_DATA(P), $num, NULL, NULL, NULL, NULL, NULL)) { - impl_val res = {0}; - token_t type = psi_num_exp_exec($num, &res, NULL, &P->preproc->defs); - - if (type == PSI_T_FLOAT || type == PSI_T_DOUBLE) { - $val = psi_impl_def_val_init(type, NULL); - } else { - $val = psi_impl_def_val_init(PSI_T_INT, NULL); - } - - switch (type) { - case PSI_T_UINT8: $val->ival.zend.lval = res.u8; break; - case PSI_T_UINT16: $val->ival.zend.lval = res.u16; break; - case PSI_T_UINT32: $val->ival.zend.lval = res.u32; break; - case PSI_T_UINT64: $val->ival.zend.lval = res.u64; break; /* FIXME */ - case PSI_T_INT8: $val->ival.zend.lval = res.i8; break; - case PSI_T_INT16: $val->ival.zend.lval = res.i16; break; - case PSI_T_INT32: $val->ival.zend.lval = res.i32; break; - case PSI_T_INT64: $val->ival.zend.lval = res.i64; break; - case PSI_T_FLOAT: $val->ival.dval = res.fval; break; - case PSI_T_DOUBLE: $val->ival.dval = res.dval; break; - default: - assert(0); - - } - } else { - $val = NULL; - } - psi_num_exp_free(&$num); + $val = psi_impl_def_val_init(PSI_T_NUMBER, $num); + $val->token = psi_token_copy($num->token); } -| impl_def_val_token[token] %dprec 2 { +| quoted_strings[token] { $val = psi_impl_def_val_init($token->type, $token->text); - $val->token = psi_token_copy($token); + $val->token = $token; } ; @@ -776,13 +766,13 @@ impl_def_val_token: NULL | TRUE | FALSE -| QUOTED_STRING ; decl_typedef[def]: TYPEDEF typedef[def_] EOS { $def = $def_; } +/* | TYPEDEF VOID name_token EOS { $def = psi_decl_arg_init( psi_decl_type_init(PSI_T_VOID, $VOID->text), @@ -792,6 +782,7 @@ decl_typedef[def]: $def->type->token = psi_token_copy($VOID); $def->var->token = psi_token_copy($name_token); } +*/ | CPP_EXTENSION TYPEDEF typedef[def_] EOS { $def = $def_; } @@ -893,13 +884,18 @@ typedef_anon_decl[def]: ; qualified_decl_type[type]: - CONST decl_type[type_] { + decl_type +| decl_type_qualifier_token decl_type[type_] { $type = $type_; } -| VOLATILE decl_type[type_] { +| qualified_decl_type[type_] decl_type_qualifier_token { $type = $type_; } -| decl_type +; + +decl_type_qualifier_token: + CONST +| VOLATILE ; decl_type[type]: @@ -934,9 +930,12 @@ decl_type_simple[type]: | NAME[type_] { $type = psi_token_copy($type_); } +| VOID[type_] { + $type = psi_token_copy($type_); +} ; -decl_real_type[type]: +decl_real_type[type]: /* allocated, so free, if set */ FLOAT[type_] { $type = psi_token_copy($type_); } @@ -953,7 +952,7 @@ int_signed[i]: | UNSIGNED ; -int_width[i]: +int_width[i]: /* allocated, so free, if set */ SHORT { $i = psi_token_copy($SHORT); } @@ -965,7 +964,7 @@ int_width[i]: } ; -decl_int_type[type]: +decl_int_type[type]: /* allocated, so free, if set */ CHAR { $type = psi_token_copy($CHAR); } @@ -975,7 +974,7 @@ decl_int_type[type]: | int_signed int_signed_types { if ($2) { $type = psi_token_cat(" ", 2, $1, $2); - free($2); + psi_token_free(&$2); } else { $type = psi_token_copy($1); } @@ -983,15 +982,15 @@ decl_int_type[type]: | int_width int_width_types { if ($2) { $type = psi_token_cat(" ", 2, $1, $2); - free($1); - free($2); + psi_token_free(&$1); + psi_token_free(&$2); } else { $type = $1; } } ; -int_signed_types[type]: +int_signed_types[type]: /* allocated, so free, if set */ %empty { $type = NULL; } @@ -1035,7 +1034,7 @@ signed_long_types[type]: | LONG INT ; -int_width_types[type]: +int_width_types[type]: /* allocated, so free, if set */ %empty { $type = NULL; } @@ -1045,7 +1044,7 @@ int_width_types[type]: | int_signed int_signed_types { if ($2) { $type = psi_token_cat(" ", 2, $1, $2); - free($2); + psi_token_free(&$2); } else { $type = psi_token_copy($1); } @@ -1055,36 +1054,81 @@ int_width_types[type]: decl_stmt: decl decl_asm EOS { $decl_stmt = $decl; + if ($decl_asm) { + $decl->redir = zend_string_copy($decl_asm->text); + psi_token_free(&$decl_asm); + } } | CPP_EXTENSION decl decl_asm EOS { $decl_stmt = $decl; + if ($decl_asm) { + $decl->redir = zend_string_copy($decl_asm->text); + psi_token_free(&$decl_asm); + } } ; decl_asm: - %empty -| CPP_ASM LPAREN ignored_quoted_strings RPAREN + %empty { + $decl_asm = NULL; +} +| CPP_ASM LPAREN quoted_strings RPAREN { + $decl_asm = $quoted_strings; +} ; -ignored_quoted_strings: - QUOTED_STRING -| ignored_quoted_strings QUOTED_STRING +quoted_strings[strings]: + QUOTED_STRING { + $strings = psi_token_copy($QUOTED_STRING); +} +| quoted_strings[strings_] QUOTED_STRING { + $strings = psi_token_cat("", 2, $strings_, $QUOTED_STRING); + psi_token_free(&$strings_); +} ; -decl_ext_var_stmt: - decl_ext_var EOS -; +decl_extvar_stmt[list]: + NAME decl_arg decl_extvar_list[vars] decl_asm EOS { + struct psi_plist *list = psi_plist_init((psi_plist_dtor) psi_decl_extvar_free); -decl_ext_var: - NAME decl_arg decl_ext_var_list { - psi_decl_arg_free(&$decl_arg); + if ($vars) { + size_t i = 0; + struct psi_decl_var *var; + + while (psi_plist_get($vars, i++, &var)) { + if (psi_decl_extvar_is_blacklisted(var->name->val)) { + psi_decl_var_free(&var); + } else { + struct psi_decl_extvar *evar = psi_decl_extvar_init( + psi_decl_arg_init(psi_decl_type_copy($decl_arg->type), var)); + list = psi_plist_add(list, &evar); + } + } + free($vars); + } + + if (psi_decl_extvar_is_blacklisted($decl_arg->var->name->val)) { + psi_decl_arg_free(&$decl_arg); + } else { + struct psi_decl_extvar *evar = psi_decl_extvar_init($decl_arg); + + if ($decl_asm) { + evar->redir = zend_string_copy($decl_asm->text); + psi_token_free(&$decl_asm); + } + list = psi_plist_add(list, &evar); + } + + $list = list; } ; -decl_ext_var_list: - %empty +decl_extvar_list[list]: + %empty { + $list = NULL; +} | COMMA decl_vars { - psi_plist_free($decl_vars); + $list = $decl_vars; } ; @@ -1098,17 +1142,20 @@ decl_vars[vars]: ; ignored_decl: - STATIC decl_body ignored_decl_body { - psi_decl_free(&$decl_body); -} -| CPP_INLINE decl_body ignored_decl_body { - psi_decl_free(&$decl_body); -} -| STATIC CPP_INLINE decl_body ignored_decl_body { - psi_decl_free(&$decl_body); + ignored_decl_qualifiers decl_body ignored_decl_body { + $ignored_decl = $decl_body; } ; +ignored_decl_qualifiers: + STATIC +| STATIC CPP_INLINE +| CPP_EXTENSION CPP_INLINE +| CPP_EXTENSION STATIC CPP_INLINE +| CPP_INLINE +| NAME CPP_INLINE +; + ignored_decl_body: LBRACE ignored_decl_body_stmts RBRACE ; @@ -1170,6 +1217,74 @@ decl_functor_body[decl]: $decl->func->var->array_size = $as; } } +| qualified_decl_type[rval_type] indirection[i] LPAREN indirection[unused1] name_token[NAME] LPAREN decl_args[args] RPAREN RPAREN LPAREN decl_args[rval_args] RPAREN array_size[as] { + (void) $unused1; + $NAME->type = PSI_T_NAME; + + struct psi_token *type_token = psi_token_append("@", psi_token_copy($NAME), 1, "rval"); + struct psi_decl_arg *rval_func = psi_decl_arg_init($rval_type, psi_decl_var_init(type_token->text, $i, 0)); + struct psi_decl *rval_decl = psi_decl_init(rval_func, $rval_args); + + rval_func->var->token = psi_token_copy(type_token); + rval_func->token = psi_token_copy(type_token); + if ($as) { + rval_func->var->pointer_level += 1; + rval_func->var->array_size = $as; + } + + struct psi_decl_type *type = psi_decl_type_init(PSI_T_FUNCTION, type_token->text); + struct psi_decl_arg *func = psi_decl_arg_init(type, psi_decl_var_init($NAME->text, 1, 0)); + + type->real.func = rval_decl; + func->var->token = psi_token_copy($NAME); + func->token = psi_token_copy($NAME); + + $decl = psi_decl_init(func, $args); +} +| qualified_decl_type[rval_type] indirection[i] LPAREN indirection[unused1] LPAREN indirection[unused2] name_token[NAME] RPAREN LPAREN decl_args[args] RPAREN RPAREN LPAREN decl_args[rval_args] RPAREN array_size[as] { + (void) $unused1; + (void) $unused2; + $NAME->type = PSI_T_NAME; + + struct psi_token *type_token = psi_token_append("@", psi_token_copy($NAME), 1, "rval"); + struct psi_decl_arg *rval_func = psi_decl_arg_init($rval_type, psi_decl_var_init(type_token->text, $i, 0)); + struct psi_decl *rval_decl = psi_decl_init(rval_func, $rval_args); + + rval_func->var->token = psi_token_copy(type_token); + rval_func->token = psi_token_copy(type_token); + if ($as) { + rval_func->var->pointer_level += 1; + rval_func->var->array_size = $as; + } + + struct psi_decl_type *type = psi_decl_type_init(PSI_T_FUNCTION, type_token->text); + struct psi_decl_arg *func = psi_decl_arg_init(type, psi_decl_var_init($NAME->text, 1, 0)); + + type->real.func = rval_decl; + func->var->token = psi_token_copy($NAME); + func->token = psi_token_copy($NAME); + type->token = type_token; + + $decl = psi_decl_init(func, $args); +} +; + +decl_anon_functor_body[decl]: + decl_anon_functor[func] LPAREN decl_args[args] RPAREN array_size[as] { + $decl = psi_decl_init($func, $args); + if ($as) { + $decl->func->var->pointer_level += 1; + $decl->func->var->array_size = $as; + } +} +| decl_anon_functor[func] LPAREN decl_args[args] COMMA ELLIPSIS RPAREN array_size[as] { + $decl = psi_decl_init($func, $args); + $decl->varargs = 1; + if ($as) { + $decl->func->var->pointer_level += 1; + $decl->func->var->array_size = $as; + } +} ; decl_functor[arg]: @@ -1180,6 +1295,8 @@ decl_functor[arg]: $arg->var->token = psi_token_copy($NAME); $arg->token = psi_token_copy($NAME); } + +/* | CONST VOID pointers LPAREN indirection[unused1] name_token[NAME] RPAREN { (void) $unused1; $NAME->type = PSI_T_NAME; @@ -1213,10 +1330,53 @@ decl_functor[arg]: $arg->var->token = psi_token_copy($NAME); $arg->token = psi_token_copy($NAME); } +*/ +; + +decl_anon_functor[arg]: + qualified_decl_type[type] indirection[i] LPAREN indirection[unused1] RPAREN { + (void) $unused1; + $arg = psi_decl_arg_init($type, psi_decl_var_init(NULL, $i, 0)); + $arg->var->token = psi_token_copy($LPAREN); + $arg->token = psi_token_copy($LPAREN); +} +/* +| CONST VOID pointers LPAREN indirection[unused1] RPAREN { + (void) $unused1; + $arg = psi_decl_arg_init( + psi_decl_type_init($VOID->type, $VOID->text), + psi_decl_var_init(NULL, $pointers, 0) + ); + $arg->type->token = psi_token_copy($VOID); + $arg->var->token = psi_token_copy($VOID); + $arg->token = psi_token_copy($VOID); +} +| VOID pointers LPAREN indirection[unused1] RPAREN { + (void) $unused1; + $arg = psi_decl_arg_init( + psi_decl_type_init($VOID->type, $VOID->text), + psi_decl_var_init(NULL, $pointers, 0) + ); + $arg->type->token = psi_token_copy($VOID); + $arg->var->token = psi_token_copy($VOID); + $arg->token = psi_token_copy($VOID); +} +| VOID LPAREN indirection[unused1] RPAREN { + (void) $unused1; + $arg = psi_decl_arg_init( + psi_decl_type_init($VOID->type, $VOID->text), + psi_decl_var_init(NULL, 0, 0) + ); + $arg->type->token = psi_token_copy($VOID); + $arg->var->token = psi_token_copy($VOID); + $arg->token = psi_token_copy($VOID); +} +*/ ; decl_func[func]: decl_arg + /* | VOID name_token[NAME] { $func = psi_decl_arg_init( psi_decl_type_init($VOID->type, $VOID->text), @@ -1226,34 +1386,56 @@ decl_func[func]: $func->var->token = psi_token_copy($NAME); $func->token = psi_token_copy($NAME); } +*/ ; decl_args[args]: %empty { $args = NULL; } -| VOID { +| VOID %dprec 2 { $args = NULL; } -| decl_anon_arg[arg] { +| decl_arg_list[args_] %dprec 1 { + $args = $args_; +} +; + +decl_arg_list[args]: + decl_anon_arg[arg] { $args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free), &$arg); } -| decl_args[args_] COMMA decl_anon_arg[arg] { +| decl_arg_list[args_] COMMA decl_anon_arg[arg] { $args = psi_plist_add($args_, &$arg); } ; decl_anon_arg[arg]: -/* FIXME decl_functor_body_anon */ - decl_arg %dprec 2 { + decl_anon_functor_body[decl] { + char digest[17]; + struct psi_token *name; + + psi_token_hash($decl->func->token, digest); + name = psi_token_append("@", psi_token_copy($decl->func->token), 2, "funct", digest); + + $arg = psi_decl_arg_init( + psi_decl_type_init(PSI_T_FUNCTION, name->text), + psi_decl_var_copy($decl->func->var) + ); + $arg->token = name; + $arg->type->token = psi_token_copy($decl->func->token); + $arg->type->real.func = $decl; +} +| decl_arg %dprec 2 { $arg = $decl_arg; } -| qualified_decl_type[type] indirection %dprec 1 { +| qualified_decl_type[type] indirection array_size[as] %dprec 1 { $arg = psi_decl_arg_init( - $type, - psi_decl_var_init(NULL, $indirection, 0) + $type, + psi_decl_var_init(NULL, $indirection, $as) ); } +/* | CONST VOID pointers { $arg = psi_decl_arg_init( psi_decl_type_init($VOID->type, $VOID->text), @@ -1272,6 +1454,7 @@ decl_anon_arg[arg]: $arg->var->token = psi_token_copy($VOID); $arg->token = psi_token_copy($VOID); } +*/ ; decl_arg[arg]: @@ -1286,6 +1469,7 @@ decl_arg[arg]: | qualified_decl_type[type] decl_var[var] { $arg = psi_decl_arg_init($type, $var); } +/* | CONST VOID pointers name_token[NAME] { $NAME->type = PSI_T_NAME; $arg = psi_decl_arg_init( @@ -1306,6 +1490,7 @@ decl_arg[arg]: $arg->var->token = psi_token_copy($NAME); $arg->token = psi_token_copy($NAME); } +*/ ; decl_var[var]: @@ -1361,7 +1546,7 @@ struct_args[args]: if ($vars) { size_t i = 0; struct psi_decl_arg *arg; - + while (psi_plist_get($vars, i++, &arg)) { arg->type = psi_decl_type_copy($arg->type); $args = psi_plist_add($args, &arg); @@ -1375,7 +1560,7 @@ struct_args[args]: if ($vars) { size_t i = 0; struct psi_decl_arg *arg; - + while (psi_plist_get($vars, i++, &arg)) { arg->type = psi_decl_type_copy($arg->type); $args = psi_plist_add($args, &arg); @@ -1409,10 +1594,26 @@ decl_vars_with_layout[vars]: $vars = psi_plist_add($vars_, &arg); } } +| decl_layout[layout] { + { + struct psi_decl_var *var = psi_decl_var_init(NULL, 0, 0); + struct psi_decl_arg *arg = psi_decl_arg_init(NULL, var); + arg->layout = $layout; + $vars = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free), &arg); + } +} +| decl_vars_with_layout[vars_] COMMA decl_layout[layout] { + { + struct psi_decl_var *var = psi_decl_var_init(NULL, 0, 0); + struct psi_decl_arg *arg = psi_decl_arg_init(NULL, var); + arg->layout = $layout; + $vars = psi_plist_add($vars_, &arg); + } +} ; decl_enum[enum]: - enum_name LBRACE decl_enum_items[list] RBRACE { + enum_name LBRACE decl_enum_items[list] optional_comma RBRACE { $enum = psi_decl_enum_init($enum_name->text, $list); $enum->token = $enum_name; } @@ -1512,6 +1713,7 @@ sizeof_body[sizeof]: if ($indirection) { int8_t sizeof_void_p = sizeof(void *); $sizeof = psi_number_init(PSI_T_INT8, &sizeof_void_p, 0); + psi_decl_type_free(&$decl_type); } else { $sizeof = psi_number_init(PSI_T_SIZEOF, $decl_type, 0); } @@ -1528,7 +1730,8 @@ sizeof_body_notypes[sizeof]: $sizeof = psi_number_init(PSI_T_INT8, &sizeof_a, 0); } | QUOTED_STRING { - $sizeof = psi_number_init(PSI_T_INT64, &$QUOTED_STRING->size, 0); + uint64_t len = $QUOTED_STRING->text->len + 1; + $sizeof = psi_number_init(PSI_T_UINT64, &len, 0); } ; @@ -1581,18 +1784,23 @@ optional_name[name]: } ; +optional_comma: + %empty +| COMMA +; + decl_layout[l]: %empty { $l = NULL; } | COLON NUMBER[width] { - $l = psi_layout_init(0, 0, psi_layout_init(0, atol($width->text), NULL)); + $l = psi_layout_init(0, 0, psi_layout_init(0, atol($width->text->val), NULL)); } | COLON COLON LPAREN NUMBER[align] COMMA NUMBER[size] RPAREN { - $l = psi_layout_init(atol($align->text), atol($size->text), NULL); + $l = psi_layout_init(atol($align->text->val), atol($size->text->val), NULL); } | COLON NUMBER[width] COLON COLON LPAREN NUMBER[align] COMMA NUMBER[size] RPAREN { - $l = psi_layout_init(atol($align->text), atol($size->text), psi_layout_init(0, atol($width->text), NULL)); + $l = psi_layout_init(atol($align->text->val), atol($size->text->val), psi_layout_init(0, atol($width->text->val), NULL)); } ; @@ -1602,8 +1810,8 @@ align_and_size[as]: $as.len = 0; } | COLON COLON LPAREN NUMBER[align] COMMA NUMBER[size] RPAREN { - $as.pos = atol($align->text); - $as.len = atol($size->text); + $as.pos = atol($align->text->val); + $as.len = atol($size->text->val); } ; @@ -1611,18 +1819,30 @@ array_size[as]: %empty { $as = 0; } -| LBRACKET RBRACKET { +| LBRACKET array_qualifier_token RBRACKET { $as = 0; } | LBRACKET num_exp RBRACKET { - if (psi_num_exp_validate(PSI_DATA(P), $num_exp, NULL, NULL, NULL, NULL, NULL)) { - $as = psi_long_num_exp($num_exp, NULL, &P->preproc->defs); + struct psi_validate_scope scope = {0}; + psi_validate_scope_ctor(&scope); + scope.cpp = P->preproc; + if (psi_num_exp_validate(PSI_DATA(P), $num_exp, &scope)) { + $as = psi_num_exp_get_long($num_exp, NULL, P->preproc); } else { $as = 0; } + psi_num_exp_free(&$num_exp); + psi_validate_scope_dtor(&scope); } ; +array_qualifier_token: + %empty +| CPP_RESTRICT +| VOLATILE +| CONST +; + indirection[i]: %empty { $i = 0; @@ -1650,7 +1870,12 @@ asterisks[a]: asterisk: ASTERISK -| ASTERISK CONST +| ASTERISK pointer_qualifier_token +; + +pointer_qualifier_token: + CONST +| VOLATILE ; /* @@ -1721,13 +1946,28 @@ impl_type[type]: } ; +impl_type_restricted[type]: + impl_type_restricted_token[token] { + $type = psi_impl_type_init($token->type, $token->text); + $type->token = psi_token_copy($token); +} +; + impl_type_token: - VOID -| MIXED -| BOOL + impl_type_restricted_token +| impl_type_extended_token +; + +impl_type_restricted_token: + BOOL | INT | FLOAT | STRING +| MIXED +; + +impl_type_extended_token: + VOID | ARRAY | OBJECT | CALLABLE @@ -1806,7 +2046,7 @@ let_exp_byref[exp]: } ; -let_exp_assign[exp]: +let_exp_assign[exp]: decl_var[var] EQUALS let_exp_byref[exp_] { $exp = $exp_; $exp->var = $var; @@ -1827,7 +2067,12 @@ let_calloc[calloc]: let_callback[callback]: CALLBACK callback_rval[func] LPAREN impl_var[var] LPAREN callback_arg_list[args] RPAREN RPAREN { - $callback = psi_let_callback_init(psi_let_func_init($func->type, $func->text, $var), $args); + $callback = psi_let_callback_init(psi_let_func_init($func->type, $func->text, $var), $args, NULL); + $callback->func->token = psi_token_copy($func); + $callback->token = psi_token_copy($CALLBACK); +} +| CALLBACK LPAREN call_decl_vars[cb_args] RPAREN AS callback_rval[func] LPAREN impl_var[var] LPAREN callback_arg_list[args] RPAREN RPAREN { + $callback = psi_let_callback_init(psi_let_func_init($func->type, $func->text, $var), $args, $cb_args); $callback->func->token = psi_token_copy($func); $callback->token = psi_token_copy($CALLBACK); } @@ -1842,16 +2087,16 @@ let_func[func]: ; let_func_token: - ZVAL -| OBJVAL -| ARRVAL -| PATHVAL -| STRLEN -| STRVAL -| FLOATVAL -| INTVAL -| BOOLVAL -| COUNT + ZVAL +| OBJVAL +| ARRVAL +| PATHVAL +| STRLEN +| STRVAL +| FLOATVAL +| INTVAL +| BOOLVAL +| COUNT ; let_func_exps[exps]: @@ -2040,20 +2285,24 @@ byref: /* epilogue */ +#define PSI_DEBUG_LEX 0 static int psi_parser_proc_lex(YYSTYPE *lvalp, struct psi_parser *P, struct psi_plist *tokens, size_t *index) { struct psi_token *token; - +#if PSI_DEBUG_LEX + PSI_DEBUG_PRINT(P, "PSI: LEX index %4zu ", *index); +#endif if (psi_plist_get(tokens, (*index)++, &token)) { - if (P->flags & PSI_DEBUG) { - psi_token_dump(2, token); - } - +#if PSI_DEBUG_LEX + PSI_DEBUG_DUMP(P, psi_token_dump, token); +#endif *((struct psi_token **)lvalp) = token; return token->type; } else { +#if PSI_DEBUG_LEX + PSI_DEBUG_PRINT(P, "EOF\n"); +#endif (*index)--; - PSI_DEBUG_PRINT(P, "EOF(%d)\n", PSI_T_EOF); } return PSI_T_EOF; @@ -2063,16 +2312,25 @@ static void psi_parser_proc_error(struct psi_parser *P, struct psi_plist *tokens { struct psi_token *T = NULL; size_t last; - + if (*index == 0) { last = 0; - } else { + } else { last = --(*index); } - + psi_plist_get(tokens, last, &T); if (T) { + size_t i = (last >= 5) ? last - 5 : 0; + P->error(PSI_DATA(P), T, PSI_WARNING, "PSI %s at col %u", msg, T->col); + while (i <= last || T->type != PSI_T_EOS) { + if (!psi_plist_get(tokens, i++, &T)) { + break; + } + P->error(PSI_DATA(P), T, PSI_WARNING, "PSI %s token '%s' at col %u", + ilast+1?"following":"offending", T->text->val, T->col); + } } else { P->error(PSI_DATA(P), NULL, PSI_WARNING, "PSI %s", msg); }