mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Rebase against 4f7e621dc58fd82924e64c695dc61a78c55fd44e.
This commit is contained in:
parent
41cb9f5179
commit
81e3e6dafa
@ -51,7 +51,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "b922b5aeef18fd30b13a4e86c115d68e505c9393"
|
||||
echo "4f7e621dc58fd82924e64c695dc61a78c55fd44e"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
|
@ -1,398 +0,0 @@
|
||||
From ed06a9e2f0f490cd146c3fc0854f88ce59a134ae Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Tue, 13 Oct 2020 16:31:16 +0200
|
||||
Subject: [PATCH] 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.
|
||||
---
|
||||
include/windows.foundation.idl | 29 +++++++++++++++
|
||||
tools/widl/expr.c | 2 ++
|
||||
tools/widl/header.c | 8 +++--
|
||||
tools/widl/parser.y | 64 ++++++++++++++++++++++++++++++----
|
||||
tools/widl/typegen.c | 6 ++++
|
||||
tools/widl/typelib.c | 2 ++
|
||||
tools/widl/typetree.c | 39 +++++++++++++++++++++
|
||||
tools/widl/typetree.h | 4 +++
|
||||
tools/widl/widltypes.h | 9 +++++
|
||||
9 files changed, 154 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
|
||||
index 5e17062f399..ab7c4753c3b 100644
|
||||
--- a/include/windows.foundation.idl
|
||||
+++ b/include/windows.foundation.idl
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
|
||||
index 13bd5a889aa..c83e9aa5ec0 100644
|
||||
--- a/tools/widl/expr.c
|
||||
+++ b/tools/widl/expr.c
|
||||
@@ -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:
|
||||
diff --git a/tools/widl/header.c b/tools/widl/header.c
|
||||
index e6394991317..8423756e060 100644
|
||||
--- a/tools/widl/header.c
|
||||
+++ b/tools/widl/header.c
|
||||
@@ -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
|
||||
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
|
||||
index 169a5ba6386..c417a3ec963 100644
|
||||
--- a/tools/widl/parser.y
|
||||
+++ b/tools/widl/parser.y
|
||||
@@ -78,6 +78,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);
|
||||
@@ -115,6 +117,7 @@ static struct namespace global_namespace = {
|
||||
};
|
||||
|
||||
static struct namespace *current_namespace = &global_namespace;
|
||||
+static struct namespace *parameters_namespace = NULL;
|
||||
|
||||
static typelib_t *current_typelib;
|
||||
|
||||
@@ -289,6 +292,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 <typelist> type_parameters
|
||||
%type <typelist> requires required_types
|
||||
%type <ifref> class_interface
|
||||
%type <ifref_list> class_interfaces
|
||||
@@ -963,7 +968,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:
|
||||
@@ -974,9 +990,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; }
|
||||
;
|
||||
@@ -1959,6 +1984,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;
|
||||
@@ -2071,7 +2119,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;
|
||||
@@ -2093,7 +2142,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)
|
||||
@@ -2585,6 +2635,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;
|
||||
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
|
||||
index 2e9be0748c1..1b5fe16b6ec 100644
|
||||
--- a/tools/widl/typegen.c
|
||||
+++ b/tools/widl/typegen.c
|
||||
@@ -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
|
||||
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
|
||||
index ace6424e3a0..6f6c5f3ccc8 100644
|
||||
--- a/tools/widl/typelib.c
|
||||
+++ b/tools/widl/typelib.c
|
||||
@@ -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;
|
||||
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
|
||||
index c67daa6ae8c..3a0934af7c5 100644
|
||||
--- a/tools/widl/typetree.c
|
||||
+++ b/tools/widl/typetree.c
|
||||
@@ -594,6 +594,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, type_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 (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
|
||||
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
|
||||
index b238c11f615..fab32ff9e64 100644
|
||||
--- a/tools/widl/typetree.h
|
||||
+++ b/tools/widl/typetree.h
|
||||
@@ -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, type_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;
|
||||
}
|
||||
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
|
||||
index a3000a7417b..2c0ac4003ce 100644
|
||||
--- a/tools/widl/widltypes.h
|
||||
+++ b/tools/widl/widltypes.h
|
||||
@@ -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;
|
||||
--
|
||||
2.20.1
|
||||
|
@ -1,309 +0,0 @@
|
||||
From ef2cb861ce5a9d47ecc10e337a192a3de32dbda3 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Tue, 1 Dec 2020 14:41:01 +0100
|
||||
Subject: [PATCH] widl: Introduce new strappend helper.
|
||||
|
||||
And use it for format_namespace to grow buffer as needed.
|
||||
---
|
||||
include/windows.foundation.idl | 9 +++++
|
||||
tools/widl/parser.y | 35 ++++++++++++++++
|
||||
tools/widl/typetree.c | 73 +++++++++++++++++++++-------------
|
||||
tools/widl/typetree.h | 3 ++
|
||||
tools/widl/utils.c | 37 +++++++++++++++++
|
||||
tools/widl/utils.h | 1 +
|
||||
tools/widl/widltypes.h | 1 +
|
||||
7 files changed, 132 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
|
||||
index ab7c4753c3b..5f7a49c38e4 100644
|
||||
--- a/include/windows.foundation.idl
|
||||
+++ b/include/windows.foundation.idl
|
||||
@@ -127,6 +127,15 @@ namespace Windows {
|
||||
HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value);
|
||||
}
|
||||
|
||||
+ [
|
||||
+ contract(Windows.Foundation.FoundationContract, 1.0),
|
||||
+ uuid(faa585ea-6214-4217-afda-7f46de5869b3)
|
||||
+ ]
|
||||
+ interface IIterable<T> : IInspectable
|
||||
+ {
|
||||
+ HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value);
|
||||
+ }
|
||||
+
|
||||
[
|
||||
contract(Windows.Foundation.FoundationContract, 1.0),
|
||||
uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56)
|
||||
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
|
||||
index c417a3ec963..92f6345e2dc 100644
|
||||
--- a/tools/widl/parser.y
|
||||
+++ b/tools/widl/parser.y
|
||||
@@ -294,6 +294,8 @@ static typelib_t *current_typelib;
|
||||
%type <type> type unqualified_type qualified_type
|
||||
%type <type> type_parameter
|
||||
%type <typelist> type_parameters
|
||||
+%type <type> parameterized_type
|
||||
+%type <typelist> parameterized_types
|
||||
%type <typelist> requires required_types
|
||||
%type <ifref> class_interface
|
||||
%type <ifref_list> class_interfaces
|
||||
@@ -910,6 +912,20 @@ qualified_type:
|
||||
| namespace_pfx typename { $$ = find_type_or_error($1, $2); }
|
||||
;
|
||||
|
||||
+parameterized_type: qualified_type '<' parameterized_types '>'
|
||||
+ { $$ = find_parameterized_type($1, $3); }
|
||||
+ ;
|
||||
+
|
||||
+parameterized_types:
|
||||
+ base_type { $$ = append_type(NULL, $1); }
|
||||
+ | qualified_type { $$ = append_type(NULL, $1); }
|
||||
+ | qualified_type '*' { $$ = append_type(NULL, type_new_pointer($1)); }
|
||||
+ | parameterized_type { $$ = append_type(NULL, $1); }
|
||||
+ | parameterized_type '*' { $$ = append_type(NULL, type_new_pointer($1)); }
|
||||
+ | parameterized_types ',' parameterized_types
|
||||
+ { $$ = append_types($1, $3); }
|
||||
+ ;
|
||||
+
|
||||
coclass: tCOCLASS typename { $$ = type_coclass_declare($2); }
|
||||
;
|
||||
|
||||
@@ -966,6 +982,7 @@ dispinterfacedef:
|
||||
|
||||
inherit: { $$ = NULL; }
|
||||
| ':' qualified_type { $$ = $2; }
|
||||
+ | ':' parameterized_type { $$ = $2; }
|
||||
;
|
||||
|
||||
type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); }
|
||||
@@ -984,6 +1001,7 @@ interface:
|
||||
|
||||
required_types:
|
||||
qualified_type { $$ = append_type(NULL, $1); }
|
||||
+ | parameterized_type { $$ = append_type(NULL, $1); }
|
||||
| required_types ',' required_types { $$ = append_types($1, $3); }
|
||||
|
||||
requires: { $$ = NULL; }
|
||||
@@ -1208,6 +1226,7 @@ unqualified_type:
|
||||
type:
|
||||
unqualified_type
|
||||
| namespace_pfx typename { $$ = find_type_or_error($1, $2); }
|
||||
+ | parameterized_type { $$ = $1; }
|
||||
;
|
||||
|
||||
typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list
|
||||
@@ -3279,3 +3298,19 @@ void init_loc_info(loc_info_t *i)
|
||||
i->line_number = line_number;
|
||||
i->near_text = parser_text;
|
||||
}
|
||||
+
|
||||
+type_t *find_parameterized_type(type_t *type, type_list_t *params)
|
||||
+{
|
||||
+ char *name = format_parameterized_type_name(type, params);
|
||||
+
|
||||
+ if (parameters_namespace)
|
||||
+ {
|
||||
+ assert(type->type_type == TYPE_PARAMETERIZED_TYPE);
|
||||
+ type = type_parameterized_type_specialize_partial(type, params);
|
||||
+ }
|
||||
+ /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */
|
||||
+ else error_loc("parameterized type '%s' not declared\n", name);
|
||||
+
|
||||
+ free(name);
|
||||
+ return type;
|
||||
+}
|
||||
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
|
||||
index 3a0934af7c5..1a5b13add96 100644
|
||||
--- a/tools/widl/typetree.c
|
||||
+++ b/tools/widl/typetree.c
|
||||
@@ -89,41 +89,52 @@ const char *type_get_name(const type_t *type, enum name_type name_type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator, const char *abi_prefix)
|
||||
+static size_t append_namespace(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *separator, const char *abi_prefix)
|
||||
{
|
||||
- if(is_global_namespace(namespace)) {
|
||||
- if(!abi_prefix) return ptr;
|
||||
- strcpy(ptr, abi_prefix);
|
||||
- strcat(ptr, separator);
|
||||
- return ptr + strlen(ptr);
|
||||
- }
|
||||
-
|
||||
- ptr = append_namespace(ptr, namespace->parent, separator, abi_prefix);
|
||||
- strcpy(ptr, namespace->name);
|
||||
- strcat(ptr, separator);
|
||||
- return ptr + strlen(ptr);
|
||||
+ int nested = namespace && !is_global_namespace(namespace);
|
||||
+ const char *name = nested ? namespace->name : abi_prefix;
|
||||
+ size_t n = 0;
|
||||
+ if (!name) return 0;
|
||||
+ if (nested) n += append_namespace(buf, len, pos + n, namespace->parent, separator, abi_prefix);
|
||||
+ n += strappend(buf, len, pos + n, "%s%s", name, separator);
|
||||
+ return n;
|
||||
}
|
||||
|
||||
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix,
|
||||
- const char *abi_prefix)
|
||||
+static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *prefix,
|
||||
+ const char *separator, const char *suffix, const char *abi_prefix)
|
||||
{
|
||||
- unsigned len = strlen(prefix) + strlen(suffix);
|
||||
- unsigned sep_len = strlen(separator);
|
||||
- struct namespace *iter;
|
||||
- char *ret, *ptr;
|
||||
+ size_t n = 0;
|
||||
+ n += strappend(buf, len, pos + n, "%s", prefix);
|
||||
+ n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix);
|
||||
+ n += strappend(buf, len, pos + n, "%s", suffix);
|
||||
+ return n;
|
||||
+}
|
||||
|
||||
- if(abi_prefix)
|
||||
- len += strlen(abi_prefix) + sep_len;
|
||||
+char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
|
||||
+{
|
||||
+ size_t len = 0;
|
||||
+ char *buf = NULL;
|
||||
+ append_namespaces(&buf, &len, 0, namespace, prefix, separator, suffix, abi_prefix);
|
||||
+ return buf;
|
||||
+}
|
||||
|
||||
- for(iter = namespace; !is_global_namespace(iter); iter = iter->parent)
|
||||
- len += strlen(iter->name) + sep_len;
|
||||
+char *format_parameterized_type_name(type_t *type, type_list_t *params)
|
||||
+{
|
||||
+ size_t len = 0, pos = 0;
|
||||
+ char *buf = NULL;
|
||||
+ type_list_t *entry;
|
||||
|
||||
- ret = xmalloc(len+1);
|
||||
- strcpy(ret, prefix);
|
||||
- ptr = append_namespace(ret + strlen(ret), namespace, separator, abi_prefix);
|
||||
- strcpy(ptr, suffix);
|
||||
+ pos += strappend(&buf, &len, pos, "%s<", type->name);
|
||||
+ for (entry = params; entry; entry = entry->next)
|
||||
+ {
|
||||
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
|
||||
+ pos += append_namespaces(&buf, &len, pos, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL);
|
||||
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) pos += strappend(&buf, &len, pos, "*");
|
||||
+ if (entry->next) pos += strappend(&buf, &len, pos, ",");
|
||||
+ }
|
||||
+ pos += strappend(&buf, &len, pos, ">");
|
||||
|
||||
- return ret;
|
||||
+ return buf;
|
||||
}
|
||||
|
||||
type_t *type_new_function(var_list_t *args)
|
||||
@@ -633,6 +644,14 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty
|
||||
return type;
|
||||
}
|
||||
|
||||
+type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params)
|
||||
+{
|
||||
+ type_t *new_type = duptype(type, 0);
|
||||
+ new_type->details.parameterized.type = type;
|
||||
+ new_type->details.parameterized.params = params;
|
||||
+ return new_type;
|
||||
+}
|
||||
+
|
||||
int type_is_equal(const type_t *type1, const type_t *type2)
|
||||
{
|
||||
if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
|
||||
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
|
||||
index fab32ff9e64..538134871a2 100644
|
||||
--- a/tools/widl/typetree.h
|
||||
+++ b/tools/widl/typetree.h
|
||||
@@ -36,6 +36,8 @@ attr_list_t *check_interface_attrs(const char *name, attr_list_t *attrs);
|
||||
attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs);
|
||||
attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs);
|
||||
|
||||
+type_t *find_parameterized_type(type_t *type, type_list_t *params);
|
||||
+
|
||||
type_t *type_new_function(var_list_t *args);
|
||||
type_t *type_new_pointer(type_t *ref);
|
||||
type_t *type_new_alias(const decl_spec_t *t, const char *name);
|
||||
@@ -64,6 +66,7 @@ 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, type_list_t *requires);
|
||||
+type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params);
|
||||
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);
|
||||
diff --git a/tools/widl/utils.c b/tools/widl/utils.c
|
||||
index ea92372c8c7..634bd12a0ba 100644
|
||||
--- a/tools/widl/utils.c
|
||||
+++ b/tools/widl/utils.c
|
||||
@@ -245,6 +245,43 @@ char *strmake( const char* fmt, ... )
|
||||
}
|
||||
}
|
||||
|
||||
+size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...)
|
||||
+{
|
||||
+ size_t size;
|
||||
+ va_list ap;
|
||||
+ char *ptr;
|
||||
+ int n;
|
||||
+
|
||||
+ assert( buf && len );
|
||||
+ assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) );
|
||||
+
|
||||
+ if (*buf)
|
||||
+ {
|
||||
+ size = *len;
|
||||
+ ptr = *buf;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ size = 100;
|
||||
+ ptr = xmalloc( size );
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ va_start( ap, fmt );
|
||||
+ n = vsnprintf( ptr + pos, size - pos, fmt, ap );
|
||||
+ va_end( ap );
|
||||
+ if (n == -1) size *= 2;
|
||||
+ else if (pos + (size_t)n >= size) size = pos + n + 1;
|
||||
+ else break;
|
||||
+ ptr = xrealloc( ptr, size );
|
||||
+ }
|
||||
+
|
||||
+ *len = size;
|
||||
+ *buf = ptr;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
char *xstrdup(const char *str)
|
||||
{
|
||||
char *s;
|
||||
diff --git a/tools/widl/utils.h b/tools/widl/utils.h
|
||||
index 37406656504..82e0a6ae489 100644
|
||||
--- a/tools/widl/utils.h
|
||||
+++ b/tools/widl/utils.h
|
||||
@@ -45,6 +45,7 @@ void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
void warning_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3)));
|
||||
void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
char *strmake(const char* fmt, ...) __attribute__((__format__ (__printf__, 1, 2 )));
|
||||
+size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) __attribute__((__format__ (__printf__, 4, 5 )));
|
||||
|
||||
char *dup_basename(const char *name, const char *ext);
|
||||
size_t widl_getline(char **linep, size_t *lenp, FILE *fp);
|
||||
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
|
||||
index 2c0ac4003ce..be82342e31a 100644
|
||||
--- a/tools/widl/widltypes.h
|
||||
+++ b/tools/widl/widltypes.h
|
||||
@@ -650,6 +650,7 @@ void init_loc_info(loc_info_t *);
|
||||
|
||||
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix,
|
||||
const char *abi_prefix);
|
||||
+char *format_parameterized_type_name(type_t *type, type_list_t *params);
|
||||
|
||||
static inline enum type_type type_get_type_detect_alias(const type_t *type)
|
||||
{
|
||||
--
|
||||
2.20.1
|
||||
|
@ -1 +1 @@
|
||||
b922b5aeef18fd30b13a4e86c115d68e505c9393
|
||||
4f7e621dc58fd82924e64c695dc61a78c55fd44e
|
||||
|
Loading…
x
Reference in New Issue
Block a user