Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.idl | 6 +++ tools/widl/parser.y | 6 +++ tools/widl/typetree.c | 76 ++++++++++++++++++++++++++++++---- tools/widl/typetree.h | 2 + 4 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 5f7a49c38e4..bb0fafcab77 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -113,6 +113,12 @@ namespace Windows { }
#ifdef __WIDL__ + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f) + ] + delegate HRESULT EventHandler<T>([in] IInspectable *sender, [in] T args); + namespace Collections { [ diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 16d2e0023b7..57e7809fc1a 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1038,6 +1038,12 @@ 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))); } + | m_attributes tDELEGATE type ident + '<' { push_parameters_namespace($4->name); } type_parameters '>' + '(' m_args ')' { pop_parameters_namespace($4->name); } semicolon_opt + { $$ = type_parameterized_delegate_declare($4->name, current_namespace, $7); + $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10))); + } ;
required_types: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 468b81d450d..0a63b7ebf7f 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -142,15 +142,15 @@ static char const *parameterized_type_shorthands[][2] = { {"Windows_CFoundation_C", "__F"}, };
-static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params) +static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params, const char *prefix) { size_t len = 0, pos = 0; char *buf = NULL, *tmp; int i, count = params ? list_count(params) : 0; typeref_t *ref;
- pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); - pos += strappend(&buf, &len, pos, "_%d", count); + pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL); + pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count); if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) { for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} @@ -664,12 +664,13 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; }
-static void compute_delegate_iface_names(type_t *delegate) +static void compute_delegate_iface_names(type_t *delegate, type_t *type, typeref_list_t *params) { 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); + if (type) iface->c_name = format_parameterized_type_c_name(type, params, "I"); + else 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) @@ -707,7 +708,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis
delegate->details.delegate.iface = iface; delegate->defined = TRUE; - compute_delegate_iface_names(delegate); + compute_delegate_iface_names(delegate, NULL, NULL);
return delegate; } @@ -751,6 +752,46 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty return type; }
+type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params) +{ + type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0); + if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE) + error_loc("pdelegate %s previously not declared a pdelegate at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->details.parameterized.type = make_type(TYPE_DELEGATE); + type->details.parameterized.params = params; + return type; +} + +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts) +{ + type_t *iface, *delegate; + + if (type->defined) + error_loc("pdelegate %s already defined at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + + type->attrs = check_interface_attrs(type->name, attrs); + + delegate = type->details.parameterized.type; + delegate->attrs = type->attrs; + delegate->details.delegate.iface = make_type(TYPE_INTERFACE); + + iface = delegate->details.delegate.iface; + 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; + + type->defined = TRUE; + return type; +} + type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params) { type_t *new_type = duptype(type, 0); @@ -932,6 +973,11 @@ static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, iface->details.iface->requires = NULL; }
+static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, typeref_list_t *orig, typeref_list_t *repl) +{ + type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl); +} + type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params) { type_t *tmpl = type->details.parameterized.type; @@ -940,7 +986,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t new_type->namespace = type->namespace; new_type->name = format_parameterized_type_name(type, params); reg_type(new_type, new_type->name, new_type->namespace, 0); - new_type->c_name = format_parameterized_type_c_name(type, params); + new_type->c_name = format_parameterized_type_c_name(type, params, ""); + + if (new_type->type_type == TYPE_DELEGATE) + { + new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); + compute_delegate_iface_names(new_type, type, params); + }
return new_type; } @@ -960,11 +1012,19 @@ type_t *type_parameterized_type_specialize_define(type_t *type) if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_INTERFACE && type_get_type_detect_alias(iface) == TYPE_INTERFACE) type_parameterized_interface_specialize(tmpl->details.parameterized.type, iface, orig, repl); + else if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_DELEGATE && + type_get_type_detect_alias(iface) == TYPE_DELEGATE) + type_parameterized_delegate_specialize(tmpl->details.parameterized.type, iface, orig, repl); else - error_loc("pinterface %s previously not declared a pinterface at %s:%d\n", + error_loc("pinterface/pdelegate %s previously not declared a pinterface/pdelegate at %s:%d\n", iface->name, iface->loc_info.input_name, iface->loc_info.line_number);
iface->defined = TRUE; + if (iface->type_type == TYPE_DELEGATE) + { + iface = iface->details.delegate.iface; + iface->defined = TRUE; + } compute_method_indexes(iface); return iface; } diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index c2b3b6c90c6..8130174fe2a 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -68,6 +68,8 @@ 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_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params); +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts); type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params); type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params); type_t *type_parameterized_type_specialize_define(type_t *type);