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