[PATCH 3/4] widl: Support WinRT delegate type.
Rémi Bernon
rbernon at codeweavers.com
Mon Feb 15 04:09:45 CST 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
tools/widl/expr.c | 1 +
tools/widl/header.c | 16 +++++++++-----
tools/widl/parser.l | 1 +
tools/widl/parser.y | 20 +++++++++++++++++
tools/widl/typegen.c | 4 ++++
tools/widl/typelib.c | 1 +
tools/widl/typetree.c | 49 ++++++++++++++++++++++++++++++++++++++++++
tools/widl/typetree.h | 10 +++++++++
tools/widl/widltypes.h | 7 ++++++
9 files changed, 104 insertions(+), 5 deletions(-)
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 a4f1db56a01..7ab79d3b6e1 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 d319954edd3..f5e91dc741a 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 9f5c12fd922..292090170e5 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -110,6 +110,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, type_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 *);
@@ -185,6 +186,7 @@ static typelib_t *current_typelib;
%token tCUSTOM
%token tDECLARE
%token tDECODE tDEFAULT tDEFAULTBIND
+%token tDELEGATE
%token tDEFAULTCOLLELEM
%token tDEFAULTVALUE
%token tDEFAULTVTABLE
@@ -283,6 +285,7 @@ static typelib_t *current_typelib;
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <expr> contract_req
%type <expr> static_attr
+%type <type> delegatedef
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
%type <function_specifier> function_specifier
@@ -388,6 +391,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);
}
@@ -412,6 +416,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);
@@ -1024,6 +1029,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_ifref(NULL, make_ifref($1)); }
| parameterized_type { $$ = append_ifref(NULL, make_ifref($1)); }
@@ -2678,6 +2689,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:
@@ -3320,6 +3332,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, type_list_t
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 1b5fe16b6ec..ec85f149da1 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 58b019cc090..1ab41a488ca 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -665,6 +665,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, type_list_t *params)
{
type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0);
@@ -824,6 +872,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig,
case TYPE_BITFIELD:
case TYPE_INTERFACE:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
return type;
case TYPE_PARAMETER:
for (o = orig, r = repl; o && r; o = o->next, r = r->next)
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 0dc75dff62e..13d6a4d51fb 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, ifref_list_t *i
type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_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, 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_type_specialize_partial(type_t *type, type_list_t *params);
@@ -251,6 +253,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:
@@ -373,6 +376,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 ce48567d583..69f95b9cbbe 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -442,6 +442,11 @@ struct parameterized_details
type_list_t *params;
};
+struct delegate_details
+{
+ type_t *iface;
+};
+
#define HASHMAX 64
struct namespace {
@@ -472,6 +477,7 @@ enum type_type
TYPE_RUNTIMECLASS,
TYPE_PARAMETERIZED_TYPE,
TYPE_PARAMETER,
+ TYPE_DELEGATE,
};
struct _type_t {
@@ -494,6 +500,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;
--
2.30.0
More information about the wine-devel
mailing list