Rémi Bernon : widl: Support WinRT parameterized delegate type.
Alexandre Julliard
julliard at winehq.org
Thu Feb 18 16:06:07 CST 2021
Module: wine
Branch: master
Commit: fecfd245a15b60d44a17c1b7411a282b5e954858
URL: https://source.winehq.org/git/wine.git/?a=commit;h=fecfd245a15b60d44a17c1b7411a282b5e954858
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Thu Feb 18 10:39:00 2021 +0100
widl: Support WinRT parameterized delegate type.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Jacek Caban<jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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);
More information about the wine-cvs
mailing list