Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.idl | 6 +++ tools/widl/parser.y | 6 +++ tools/widl/typetree.c | 73 ++++++++++++++++++++++++++++++---- tools/widl/typetree.h | 2 + 4 files changed, 80 insertions(+), 7 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 292090170e5..76ed1855f86 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1033,6 +1033,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 1ab41a488ca..cd4bc6843fc 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -142,16 +142,16 @@ static char const *parameterized_type_shorthands[][2] = { {"Windows_CFoundation_C", "__F"}, };
-static char *format_parameterized_type_c_name(type_t *type, type_list_t *params) +static char *format_parameterized_type_c_name(type_t *type, type_list_t *params, const char *prefix) { size_t len = 0, pos = 0; char *buf = NULL, *tmp; type_list_t *entry; int i, count = 0;
- pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); + pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL); for (entry = params; entry; entry = entry->next) count++; - pos += strappend(&buf, &len, pos, "_%d", count); + pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count); for (entry = params; entry; entry = entry->next) { for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} @@ -665,12 +665,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, type_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) @@ -708,7 +709,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; } @@ -752,6 +753,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, type_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, type_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, type_list_t *orig, type_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, type_list_t *params) { type_t *tmpl = type->details.parameterized.type; @@ -940,7 +986,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa 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; } @@ -953,6 +1005,8 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
if (tmpl->type_type == TYPE_INTERFACE) type_parameterized_interface_specialize(tmpl, iface, orig, params); + else if (tmpl->type_type == TYPE_DELEGATE) + type_parameterized_delegate_specialize(tmpl, iface, orig, params); else { error_loc("Unsupported parameterized type template %d\n", tmpl->type_type); @@ -960,6 +1014,11 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par }
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 13d6a4d51fb..af0764b68b0 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, type_list_t *params); type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires); +type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, type_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, type_list_t *params); type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params); type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params);