widl: Support WinRT requires keyword.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1442ddf942
commit
daba929a52
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue