diff --git a/tools/widl/expr.c b/tools/widl/expr.c index c83e9aa5ec0..88d59290d6b 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -466,6 +466,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* nothing to do */ break; case TYPE_ALIAS: diff --git a/tools/widl/header.c b/tools/widl/header.c index f0f2b39073b..3c8ad09bd63 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -470,6 +470,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_RUNTIMECLASS: fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type)); break; + case TYPE_DELEGATE: + fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type)); + break; case TYPE_VOID: fprintf(h, "void"); break; @@ -555,6 +558,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_COCLASS: case TYPE_INTERFACE: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: break; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -974,7 +978,7 @@ int has_out_arg_or_return(const var_t *func) int is_object(const type_t *iface) { const attr_t *attr; - if (type_is_defined(iface) && type_iface_get_inherit(iface)) + if (type_is_defined(iface) && (type_get_type(iface) == TYPE_DELEGATE || type_iface_get_inherit(iface))) return 1; if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; @@ -1799,9 +1803,10 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { type_t *iface = stmt->u.type; + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) { write_forward(header, iface); @@ -1841,10 +1846,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { - type_t *iface = stmt->u.type; - type_t *async_iface = type_iface_get_async_iface(iface); + type_t *iface = stmt->u.type, *async_iface; + if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + async_iface = type_iface_get_async_iface(iface); if (is_object(iface)) is_object_interface++; if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) { diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 741e9cbcfca..4d3b9d683e8 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -278,6 +278,7 @@ static const struct keyword keywords[] = { {"cpp_quote", tCPPQUOTE, 0}, {"declare", tDECLARE, 1}, {"default", tDEFAULT, 0}, + {"delegate", tDELEGATE, 1}, {"dispinterface", tDISPINTERFACE, 0}, {"double", tDOUBLE, 0}, {"enum", tENUM, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index cc849619ce8..16d2e0023b7 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -106,6 +106,7 @@ static statement_t *make_statement_module(type_t *type); static statement_t *make_statement_typedef(var_list_t *names, int declonly); static statement_t *make_statement_import(const char *str); static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params); +static statement_t *make_statement_delegate(type_t *ret, var_list_t *args); static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); static statement_list_t *append_statements(statement_list_t *, statement_list_t *); static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); @@ -180,6 +181,7 @@ static typelib_t *current_typelib; %token tCUSTOM %token tDECLARE %token tDECODE tDEFAULT tDEFAULTBIND +%token tDELEGATE %token tDEFAULTCOLLELEM %token tDEFAULTVALUE %token tDEFAULTVTABLE @@ -278,6 +280,7 @@ static typelib_t *current_typelib; %type m_exprs /* exprs expr_list */ expr_list_int_const %type contract_req %type static_attr +%type delegatedef %type storage_cls_spec %type type_qualifier m_type_qual_list %type function_specifier @@ -384,6 +387,7 @@ gbl_statements: { $$ = NULL; } | gbl_statements interface ';' { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements dispinterface ';' { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | gbl_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | gbl_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } @@ -408,6 +412,7 @@ imp_statements: { $$ = NULL; } | imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}' { pop_namespace($2); $$ = append_statements($1, $5); } | imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | imp_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); @@ -1029,6 +1034,12 @@ interface: { $$ = type_parameterized_interface_declare($2, current_namespace, $5); } ; +delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt + { $$ = type_delegate_declare($4->name, current_namespace); + $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6))); + } + ; + required_types: qualified_type { $$ = append_typeref(NULL, make_typeref($1)); } | parameterized_type { $$ = append_typeref(NULL, make_typeref($1)); } @@ -2663,6 +2674,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_INTERFACE: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return FALSE; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -3299,6 +3311,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, typeref_list return stmt; } +static statement_t *make_statement_delegate(type_t *ret, var_list_t *args) +{ + declarator_t *decl = make_declarator(make_var(xstrdup("Invoke"))); + decl_spec_t *spec = make_decl_spec(ret, NULL, NULL, STG_NONE, 0, 0); + append_chain_type(decl, type_new_function(args), 0); + return make_statement_declaration(declare_var(NULL, spec, decl, FALSE)); +} + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) { if (!l2) return l1; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 6ae55ac1934..2c1017b9f2b 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -354,6 +354,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_POINTER: if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || type_get_type(type_pointer_get_ref_type(type)) == TYPE_RUNTIMECLASS || + type_get_type(type_pointer_get_ref_type(type)) == TYPE_DELEGATE || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) return TGT_IFACE_POINTER; else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) @@ -375,6 +376,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_ALIAS: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: break; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -1978,6 +1980,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or @@ -2083,6 +2086,7 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index 6f6c5f3ccc8..8b2a2401367 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -219,6 +219,7 @@ unsigned short get_type_vt(type_t *t) case TYPE_UNION: case TYPE_ENCAPSULATED_UNION: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return VT_USERDEFINED; case TYPE_VOID: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 3f90fcbe014..468b81d450d 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -664,6 +664,54 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; } +static void compute_delegate_iface_names(type_t *delegate) +{ + type_t *iface = delegate->details.delegate.iface; + iface->namespace = delegate->namespace; + iface->name = strmake("I%s", delegate->name); + iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL); +} + +type_t *type_delegate_declare(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_DELEGATE, name, NULL, 0); + if (type_get_type_detect_alias(type) != TYPE_DELEGATE) + error_loc("delegate %s previously not declared a delegate at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + return type; +} + +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts) +{ + type_t *iface; + + if (delegate->defined) + error_loc("delegate %s already defined at %s:%d\n", + delegate->name, delegate->loc_info.input_name, delegate->loc_info.line_number); + + delegate->attrs = check_interface_attrs(delegate->name, attrs); + + iface = make_type(TYPE_INTERFACE); + iface->attrs = delegate->attrs; + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; + iface->details.iface->stmts = stmts; + iface->details.iface->inherit = find_type("IUnknown", NULL, 0); + if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; + iface->defined = TRUE; + compute_method_indexes(iface); + + delegate->details.delegate.iface = iface; + delegate->defined = TRUE; + compute_delegate_iface_names(delegate); + + return delegate; +} + type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params) { type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0); @@ -821,6 +869,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *ori case TYPE_BITFIELD: case TYPE_INTERFACE: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return type; case TYPE_PARAMETER: if (!orig || !repl) return NULL; diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 4f2d39a0434..c2b3b6c90c6 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -64,6 +64,8 @@ type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces); type_t *type_apicontract_declare(char *name, struct namespace *namespace); type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs); +type_t *type_delegate_declare(char *name, struct namespace *namespace); +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts); type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params); type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires); type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params); @@ -254,6 +256,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_ARRAY: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return TRUE; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -376,6 +379,13 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) return NULL; } +static inline type_t *type_delegate_get_iface(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_DELEGATE); + return type->details.delegate.iface; +} + static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 777aabc78ff..e07aeddf511 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -441,6 +441,11 @@ struct parameterized_details typeref_list_t *params; }; +struct delegate_details +{ + type_t *iface; +}; + #define HASHMAX 64 struct namespace { @@ -471,6 +476,7 @@ enum type_type TYPE_RUNTIMECLASS, TYPE_PARAMETERIZED_TYPE, TYPE_PARAMETER, + TYPE_DELEGATE, }; struct _type_t { @@ -493,6 +499,7 @@ struct _type_t { struct alias_details alias; struct runtimeclass_details runtimeclass; struct parameterized_details parameterized; + struct delegate_details delegate; } details; const char *c_name; unsigned int typestring_offset;