Rémi Bernon : widl: Support WinRT requires keyword.
Alexandre Julliard
julliard at winehq.org
Tue Feb 9 15:57:08 CST 2021
Module: wine
Branch: master
Commit: daba929a521163d1cb49106425d5e6184bcf8e8f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=daba929a521163d1cb49106425d5e6184bcf8e8f
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Tue Feb 9 10:37:21 2021 +0100
widl: Support WinRT requires keyword.
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>
---
tools/widl/parser.l | 1 +
tools/widl/parser.y | 16 +++++++++++++---
tools/widl/typetree.c | 34 +++++++++++++++++++++++++++++++++-
tools/widl/typetree.h | 9 ++++++++-
tools/widl/widltypes.h | 1 +
5 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 9b93a53b839..946dba84cd6 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -298,6 +298,7 @@ static const struct keyword keywords[] = {
{"pascal", tPASCAL, 0},
{"properties", tPROPERTIES, 0},
{"register", tREGISTER, 0},
+ {"requires", tREQUIRES, 1},
{"runtimeclass", tRUNTIMECLASS, 1},
{"short", tSHORT, 0},
{"signed", tSIGNED, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index b8c916f8336..a6128074f2d 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -240,6 +240,7 @@ static typelib_t *current_typelib;
%token tREADONLY tREF
%token tREGISTER tREPRESENTAS
%token tREQUESTEDIT
+%token tREQUIRES
%token tRESTRICTED
%token tRETVAL
%token tRUNTIMECLASS
@@ -293,6 +294,7 @@ static typelib_t *current_typelib;
%type <type> type unqualified_type qualified_type
%type <ifref> class_interface
%type <ifref_list> class_interfaces
+%type <ifref_list> requires required_types
%type <var> arg ne_union_field union_field s_field case enum enum_member declaration
%type <var> funcdef
%type <var_list> m_args arg_list args dispint_meths
@@ -967,8 +969,16 @@ inherit: { $$ = NULL; }
interface: tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); }
;
-interfacedef: attributes interface inherit
- '{' int_statements '}' semicolon_opt { $$ = type_interface_define($2, $1, $3, $5);
+required_types:
+ qualified_type { $$ = append_ifref(NULL, make_ifref($1)); }
+ | required_types ',' qualified_type { $$ = append_ifref($1, make_ifref($3)); }
+
+requires: { $$ = NULL; }
+ | tREQUIRES required_types { $$ = $2; }
+ ;
+
+interfacedef: attributes interface inherit requires
+ '{' int_statements '}' semicolon_opt { $$ = type_interface_define($2, $1, $3, $6, $4);
check_async_uuid($$);
}
| dispinterfacedef semicolon_opt { $$ = $1; }
@@ -2981,7 +2991,7 @@ static void check_async_uuid(type_t *iface)
stmts = append_statement(stmts, make_statement_declaration(finish_func));
}
- type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts);
+ type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts, NULL);
iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface;
}
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index b3f0725f00e..3c2f183eb13 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -441,7 +441,7 @@ type_t *type_interface_declare(char *name, struct namespace *namespace)
return type;
}
-type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts)
+type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires)
{
if (iface->defined)
error_loc("interface %s already defined at %s:%d\n",
@@ -457,6 +457,7 @@ type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit
iface->details.iface->inherit = inherit;
iface->details.iface->disp_inherit = NULL;
iface->details.iface->async_iface = NULL;
+ iface->details.iface->requires = requires;
iface->defined = TRUE;
compute_method_indexes(iface);
return iface;
@@ -485,6 +486,7 @@ type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t
if (!iface->details.iface->inherit) error_loc("IDispatch 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);
return iface;
@@ -504,6 +506,7 @@ type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *att
if (!dispiface->details.iface->inherit) error_loc("IDispatch is undefined\n");
dispiface->details.iface->disp_inherit = iface;
dispiface->details.iface->async_iface = NULL;
+ dispiface->details.iface->requires = NULL;
dispiface->defined = TRUE;
compute_method_indexes(dispiface);
return dispiface;
@@ -561,6 +564,9 @@ type_t *type_runtimeclass_declare(char *name, struct namespace *namespace)
type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_list_t *ifaces)
{
+ ifref_t *ifref, *required, *tmp;
+ ifref_list_t *requires;
+
if (runtimeclass->defined)
error_loc("runtimeclass %s already defined at %s:%d\n",
runtimeclass->name, runtimeclass->loc_info.input_name, runtimeclass->loc_info.line_number);
@@ -569,6 +575,28 @@ type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref
runtimeclass->defined = TRUE;
if (!type_runtimeclass_get_default_iface(runtimeclass))
error_loc("missing default interface on runtimeclass %s\n", runtimeclass->name);
+
+ LIST_FOR_EACH_ENTRY(ifref, ifaces, ifref_t, entry)
+ {
+ /* FIXME: this should probably not be allowed, here or in coclass, */
+ /* but for now there's too many places in Wine IDL where it is to */
+ /* even print a warning. */
+ if (!(ifref->iface->defined)) continue;
+ if (!(requires = type_iface_get_requires(ifref->iface))) continue;
+ LIST_FOR_EACH_ENTRY(required, requires, ifref_t, entry)
+ {
+ int found = 0;
+
+ LIST_FOR_EACH_ENTRY(tmp, ifaces, ifref_t, entry)
+ if ((found = type_is_equal(tmp->iface, required->iface))) break;
+
+ if (!found)
+ error_loc("interface '%s' also requires interface '%s', "
+ "but runtimeclass '%s' does not implement it.\n",
+ ifref->iface->name, required->iface->name, runtimeclass->name);
+ }
+ }
+
return runtimeclass;
}
@@ -593,8 +621,12 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs)
int type_is_equal(const type_t *type1, const type_t *type2)
{
+ if (type1 == type2)
+ return TRUE;
if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
return FALSE;
+ if (type1->namespace != type2->namespace)
+ return FALSE;
if (type1->name && type2->name)
return !strcmp(type1->name, type2->name);
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 8e04537ab4d..9866d2a1e98 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -53,7 +53,7 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
type_t *type_new_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_runtimeclass_declare(char *name, struct namespace *namespace);
type_t *type_interface_declare(char *name, struct namespace *namespace);
-type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts);
+type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires);
type_t *type_dispinterface_declare(char *name);
type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t *props, var_list_t *methods);
type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *attrs, type_t *iface);
@@ -181,6 +181,13 @@ static inline type_t *type_iface_get_inherit(const type_t *type)
return type->details.iface->inherit;
}
+static inline ifref_list_t *type_iface_get_requires(const type_t *type)
+{
+ type = type_get_real_type(type);
+ assert(type_get_type(type) == TYPE_INTERFACE);
+ return type->details.iface->requires;
+}
+
static inline type_t *type_iface_get_async_iface(const type_t *type)
{
type = type_get_real_type(type);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index facfff21453..e22d425e85b 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -386,6 +386,7 @@ struct iface_details
struct _type_t *inherit;
struct _type_t *disp_inherit;
struct _type_t *async_iface;
+ ifref_list_t *requires;
};
struct module_details
More information about the wine-cvs
mailing list