widl: Support WinRT parameterized type parsing.
And add IVectorView<T> and IIterator<T> parameterized interfaces to windows.foundation.idl for illustration and future use. They won't generate any additional code until they are fully specialized. This is a WIDL-specific feature, but MIDL has some magic knowledge of these Windows.Foundation.Collections interface templates, and we need a way to instruct WIDL about them too. Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef is easier and more flexible than re-creating the types by hand in WIDL source. 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
b79b158d6b
commit
ed21c29481
|
@ -111,5 +111,34 @@ namespace Windows {
|
|||
{
|
||||
HRESULT ToString([out, retval] HSTRING *value);
|
||||
}
|
||||
|
||||
#ifdef __WIDL__
|
||||
namespace Collections
|
||||
{
|
||||
[
|
||||
contract(Windows.Foundation.FoundationContract, 1.0),
|
||||
uuid(6a79e863-4300-459a-9966-cbb660963ee1)
|
||||
]
|
||||
interface IIterator<T> : IInspectable
|
||||
{
|
||||
[propget] HRESULT Current([out, retval] T *value);
|
||||
[propget] HRESULT HasCurrent([out, retval] BOOL *value);
|
||||
HRESULT MoveNext([out, retval] BOOL *value);
|
||||
HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value);
|
||||
}
|
||||
|
||||
[
|
||||
contract(Windows.Foundation.FoundationContract, 1.0),
|
||||
uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56)
|
||||
]
|
||||
interface IVectorView<T> : IInspectable
|
||||
{
|
||||
HRESULT GetAt([in] ULONG index, [out, retval] T *value);
|
||||
[propget] HRESULT Size([out, retval] ULONG *value);
|
||||
HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value);
|
||||
HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,6 +464,8 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
|
|||
case TYPE_BITFIELD:
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_RUNTIMECLASS:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* nothing to do */
|
||||
break;
|
||||
case TYPE_ALIAS:
|
||||
|
|
|
@ -488,6 +488,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
|
|||
break;
|
||||
}
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* shouldn't be here */
|
||||
assert(0);
|
||||
break;
|
||||
|
@ -555,6 +557,8 @@ void write_type_right(FILE *h, type_t *t, int is_field)
|
|||
case TYPE_RUNTIMECLASS:
|
||||
break;
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* not supposed to be here */
|
||||
assert(0);
|
||||
break;
|
||||
|
@ -1864,10 +1868,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
|
|||
write_apicontract(header, stmt->u.type);
|
||||
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
|
||||
write_runtimeclass(header, stmt->u.type);
|
||||
else
|
||||
{
|
||||
else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE)
|
||||
write_type_definition(header, stmt->u.type, stmt->declonly);
|
||||
}
|
||||
break;
|
||||
case STMT_TYPEREF:
|
||||
/* FIXME: shouldn't write out forward declarations for undefined
|
||||
|
|
|
@ -38,12 +38,6 @@
|
|||
#include "expr.h"
|
||||
#include "typetree.h"
|
||||
|
||||
typedef struct list typelist_t;
|
||||
struct typenode {
|
||||
type_t *type;
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
struct _import_t
|
||||
{
|
||||
char *name;
|
||||
|
@ -51,6 +45,7 @@ struct _import_t
|
|||
};
|
||||
|
||||
static str_list_t *append_str(str_list_t *list, char *str);
|
||||
static type_list_t *append_type(type_list_t *list, type_t *type);
|
||||
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
|
||||
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
|
||||
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right,
|
||||
|
@ -82,6 +77,8 @@ static var_t *reg_const(var_t *var);
|
|||
|
||||
static void push_namespace(const char *name);
|
||||
static void pop_namespace(const char *name);
|
||||
static void push_parameters_namespace(const char *name);
|
||||
static void pop_parameters_namespace(const char *name);
|
||||
|
||||
static void check_arg_attrs(const var_t *arg);
|
||||
static void check_statements(const statement_list_t *stmts, int is_inside_library);
|
||||
|
@ -119,6 +116,7 @@ static struct namespace global_namespace = {
|
|||
};
|
||||
|
||||
static struct namespace *current_namespace = &global_namespace;
|
||||
static struct namespace *parameters_namespace = NULL;
|
||||
|
||||
static typelib_t *current_typelib;
|
||||
|
||||
|
@ -130,6 +128,7 @@ static typelib_t *current_typelib;
|
|||
expr_t *expr;
|
||||
expr_list_t *expr_list;
|
||||
type_t *type;
|
||||
type_list_t *type_list;
|
||||
var_t *var;
|
||||
var_list_t *var_list;
|
||||
declarator_t *declarator;
|
||||
|
@ -292,6 +291,8 @@ static typelib_t *current_typelib;
|
|||
%type <type> base_type int_std
|
||||
%type <type> enumdef structdef uniondef typedecl
|
||||
%type <type> type unqualified_type qualified_type
|
||||
%type <type> type_parameter
|
||||
%type <type_list> type_parameters
|
||||
%type <ifref> class_interface
|
||||
%type <ifref_list> class_interfaces
|
||||
%type <ifref_list> requires required_types
|
||||
|
@ -966,7 +967,18 @@ inherit: { $$ = NULL; }
|
|||
| ':' qualified_type { $$ = $2; }
|
||||
;
|
||||
|
||||
interface: tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); }
|
||||
type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); }
|
||||
;
|
||||
|
||||
type_parameters:
|
||||
type_parameter { $$ = append_type(NULL, $1); }
|
||||
| type_parameters ',' type_parameter { $$ = append_type($1, $3); }
|
||||
;
|
||||
|
||||
interface:
|
||||
tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); }
|
||||
| tINTERFACE typename '<' { push_parameters_namespace($2); } type_parameters { pop_parameters_namespace($2); } '>'
|
||||
{ $$ = type_parameterized_interface_declare($2, current_namespace, $5); }
|
||||
;
|
||||
|
||||
required_types:
|
||||
|
@ -977,9 +989,18 @@ 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($$);
|
||||
interfacedef: attributes interface { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) push_parameters_namespace($2->name); }
|
||||
inherit requires '{' int_statements '}' semicolon_opt
|
||||
{ if ($2->type_type == TYPE_PARAMETERIZED_TYPE)
|
||||
{
|
||||
$$ = type_parameterized_interface_define($2, $1, $4, $7, $5);
|
||||
pop_parameters_namespace($2->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = type_interface_define($2, $1, $4, $7, $5);
|
||||
check_async_uuid($$);
|
||||
}
|
||||
}
|
||||
| dispinterfacedef semicolon_opt { $$ = $1; }
|
||||
;
|
||||
|
@ -1808,6 +1829,16 @@ static ifref_t *make_ifref(type_t *iface)
|
|||
return l;
|
||||
}
|
||||
|
||||
static type_list_t *append_type(type_list_t *list, type_t *type)
|
||||
{
|
||||
type_list_t *entry;
|
||||
if (!type) return list;
|
||||
entry = xmalloc( sizeof(*entry) );
|
||||
entry->type = type;
|
||||
entry->next = list;
|
||||
return entry;
|
||||
}
|
||||
|
||||
var_list_t *append_var(var_list_t *list, var_t *var)
|
||||
{
|
||||
if (!var) return list;
|
||||
|
@ -1942,6 +1973,29 @@ static void pop_namespace(const char *name)
|
|||
current_namespace = current_namespace->parent;
|
||||
}
|
||||
|
||||
static void push_parameters_namespace(const char *name)
|
||||
{
|
||||
struct namespace *namespace;
|
||||
|
||||
if (!(namespace = find_sub_namespace(current_namespace, name)))
|
||||
{
|
||||
namespace = xmalloc(sizeof(*namespace));
|
||||
namespace->name = xstrdup(name);
|
||||
namespace->parent = current_namespace;
|
||||
list_add_tail(¤t_namespace->children, &namespace->entry);
|
||||
list_init(&namespace->children);
|
||||
memset(namespace->type_hash, 0, sizeof(namespace->type_hash));
|
||||
}
|
||||
|
||||
parameters_namespace = namespace;
|
||||
}
|
||||
|
||||
static void pop_parameters_namespace(const char *name)
|
||||
{
|
||||
assert(!strcmp(parameters_namespace->name, name) && parameters_namespace->parent);
|
||||
parameters_namespace = NULL;
|
||||
}
|
||||
|
||||
struct rtype {
|
||||
const char *name;
|
||||
type_t *type;
|
||||
|
@ -2054,7 +2108,8 @@ type_t *find_type(const char *name, struct namespace *namespace, int t)
|
|||
static type_t *find_type_or_error(struct namespace *namespace, const char *name)
|
||||
{
|
||||
type_t *type;
|
||||
if (!(type = find_type(name, namespace, 0)))
|
||||
if (!(type = find_type(name, namespace, 0)) &&
|
||||
!(type = find_type(name, parameters_namespace, 0)))
|
||||
{
|
||||
error_loc("type '%s' not found in %s namespace\n", name, namespace && namespace->name ? namespace->name : "global");
|
||||
return NULL;
|
||||
|
@ -2076,7 +2131,8 @@ static struct namespace *find_namespace_or_error(struct namespace *parent, const
|
|||
|
||||
int is_type(const char *name)
|
||||
{
|
||||
return find_type(name, current_namespace, 0) != NULL;
|
||||
return find_type(name, current_namespace, 0) != NULL ||
|
||||
find_type(name, parameters_namespace, 0);
|
||||
}
|
||||
|
||||
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t)
|
||||
|
@ -2568,6 +2624,8 @@ static int is_allowed_conf_type(const type_t *type)
|
|||
case TYPE_RUNTIMECLASS:
|
||||
return FALSE;
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* not supposed to be here */
|
||||
assert(0);
|
||||
break;
|
||||
|
|
|
@ -377,6 +377,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
|
|||
case TYPE_RUNTIMECLASS:
|
||||
break;
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* not supposed to be here */
|
||||
assert(0);
|
||||
break;
|
||||
|
@ -1974,6 +1976,8 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
|
|||
case TYPE_BITFIELD:
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_RUNTIMECLASS:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* 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
|
||||
|
@ -2077,6 +2081,8 @@ static unsigned int type_buffer_alignment(const type_t *t)
|
|||
case TYPE_BITFIELD:
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_RUNTIMECLASS:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* 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
|
||||
|
|
|
@ -226,6 +226,8 @@ unsigned short get_type_vt(type_t *t)
|
|||
|
||||
case TYPE_ALIAS:
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
/* not supposed to be here */
|
||||
assert(0);
|
||||
break;
|
||||
|
|
|
@ -619,6 +619,45 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs)
|
|||
return apicontract;
|
||||
}
|
||||
|
||||
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);
|
||||
if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE)
|
||||
error_loc("pinterface %s previously not declared a pinterface at %s:%d\n",
|
||||
type->name, type->loc_info.input_name, type->loc_info.line_number);
|
||||
type->details.parameterized.type = make_type(TYPE_INTERFACE);
|
||||
type->details.parameterized.params = params;
|
||||
return type;
|
||||
}
|
||||
|
||||
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 *iface;
|
||||
if (type->defined)
|
||||
error_loc("pinterface %s already defined at %s:%d\n",
|
||||
type->name, type->loc_info.input_name, type->loc_info.line_number);
|
||||
|
||||
/* The parameterized type UUID is actually a PIID that is then used as a seed to generate
|
||||
* a new type GUID with the rules described in:
|
||||
* https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#parameterized-types
|
||||
* TODO: store type signatures for generated interfaces, and generate their GUIDs
|
||||
*/
|
||||
type->attrs = check_interface_attrs(type->name, attrs);
|
||||
|
||||
iface = type->details.parameterized.type;
|
||||
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 = inherit;
|
||||
iface->details.iface->disp_inherit = NULL;
|
||||
iface->details.iface->async_iface = NULL;
|
||||
iface->details.iface->requires = requires;
|
||||
|
||||
type->defined = TRUE;
|
||||
return type;
|
||||
}
|
||||
|
||||
int type_is_equal(const type_t *type1, const type_t *type2)
|
||||
{
|
||||
if (type1 == type2)
|
||||
|
|
|
@ -62,6 +62,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_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);
|
||||
int type_is_equal(const type_t *type1, const type_t *type2);
|
||||
const char *type_get_name(const type_t *type, enum name_type name_type);
|
||||
char *gen_name(void);
|
||||
|
@ -246,6 +248,8 @@ static inline int type_is_complete(const type_t *type)
|
|||
case TYPE_RUNTIMECLASS:
|
||||
return TRUE;
|
||||
case TYPE_APICONTRACT:
|
||||
case TYPE_PARAMETERIZED_TYPE:
|
||||
case TYPE_PARAMETER:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -436,6 +436,12 @@ struct runtimeclass_details
|
|||
ifref_list_t *ifaces;
|
||||
};
|
||||
|
||||
struct parameterized_details
|
||||
{
|
||||
type_t *type;
|
||||
type_list_t *params;
|
||||
};
|
||||
|
||||
#define HASHMAX 64
|
||||
|
||||
struct namespace {
|
||||
|
@ -464,6 +470,8 @@ enum type_type
|
|||
TYPE_BITFIELD,
|
||||
TYPE_APICONTRACT,
|
||||
TYPE_RUNTIMECLASS,
|
||||
TYPE_PARAMETERIZED_TYPE,
|
||||
TYPE_PARAMETER,
|
||||
};
|
||||
|
||||
struct _type_t {
|
||||
|
@ -485,6 +493,7 @@ struct _type_t {
|
|||
struct bitfield_details bitfield;
|
||||
struct alias_details alias;
|
||||
struct runtimeclass_details runtimeclass;
|
||||
struct parameterized_details parameterized;
|
||||
} details;
|
||||
const char *c_name;
|
||||
unsigned int typestring_offset;
|
||||
|
|
Loading…
Reference in New Issue