Not really necessary as the errors are usually more cryptic, but nice to have when it fails there.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Tweak style in a few locations.
tools/widl/parser.y | 10 ++++++++-- tools/widl/widltypes.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 3ef8d89ba1c..98bd8949f13 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -118,7 +118,7 @@ static statement_list_t *append_statements(statement_list_t *, statement_list_t static attr_list_t *append_attribs(attr_list_t *, attr_list_t *);
static struct namespace global_namespace = { - NULL, NULL, LIST_INIT(global_namespace.entry), LIST_INIT(global_namespace.children) + NULL, NULL, NULL, LIST_INIT(global_namespace.entry), LIST_INIT(global_namespace.children) };
static struct namespace *current_namespace = &global_namespace; @@ -1833,6 +1833,12 @@ static void push_namespace(const char *name) if(!namespace) { namespace = xmalloc(sizeof(*namespace)); namespace->name = xstrdup(name); + if (!current_namespace->full_name) namespace->full_name = xstrdup(name); + else + { + namespace->full_name = xmalloc(strlen(current_namespace->full_name) + strlen(name) + 1); + sprintf(namespace->full_name, "%s.%s", current_namespace->full_name, name); + } namespace->parent = current_namespace; list_add_tail(¤t_namespace->children, &namespace->entry); list_init(&namespace->children); @@ -1961,7 +1967,7 @@ static type_t *find_type_or_error(const char *name, int t) { type_t *type = find_type(name, NULL, t); if (!type) { - error_loc("type '%s' not found\n", name); + error_loc("type '%s' not found in %s\n", name, current_namespace->full_name); return NULL; } return type; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 085a0ff55f5..1634f9bd50b 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -409,6 +409,7 @@ struct alias_details
struct namespace { const char *name; + char *full_name; struct namespace *parent; struct list entry; struct list children;
This fixes WinRT interface generation where only simple names were used instead of the C interface names.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/client.c | 3 +-- tools/widl/header.c | 42 ++++++++++++++++++++---------------------- tools/widl/header.h | 2 +- tools/widl/proxy.c | 4 ++-- 4 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/tools/widl/client.c b/tools/widl/client.c index 6ef1cee2f73..185ab8dffc2 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -61,8 +61,7 @@ static void write_client_func_decl( const type_t *iface, const var_t *func ) fprintf(client, " %s ", callconv); fprintf(client, "%s%s(\n", prefix_client, get_name(func)); indent++; - if (args) - write_args(client, args, iface->name, 0, TRUE); + if (args) write_args(client, args, iface->name, 0, TRUE, NAME_DEFAULT); else print_client("void"); fprintf(client, ")\n"); diff --git a/tools/widl/header.c b/tools/widl/header.c index a319f2425e3..c8a12556cc9 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -43,7 +43,7 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list); context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
-static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name); +static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name, enum name_type name_type);
static void indent(FILE *h, int delta) { @@ -250,7 +250,7 @@ static void write_fields(FILE *h, var_list_t *fields) default: ; } - write_type_v(h, &v->declspec, TRUE, v->declonly, name); + write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_DEFAULT); fprintf(h, ";\n"); } } @@ -452,7 +452,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_INTERFACE: case TYPE_MODULE: case TYPE_COCLASS: - fprintf(h, "%s", t->name); + fprintf(h, "%s", name); break; case TYPE_VOID: fprintf(h, "void"); @@ -500,8 +500,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) { const var_list_t *args = type_function_get_args(t); fputc('(', h); - if (args) - write_args(h, args, NULL, 0, FALSE); + if (args) write_args(h, args, NULL, 0, FALSE, NAME_DEFAULT); else fprintf(h, "void"); fputc(')', h); @@ -533,14 +532,13 @@ void write_type_right(FILE *h, type_t *t, int is_field) } }
-static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name) +static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name, enum name_type name_type) { type_t *t = ds->type;
if (!h) return;
- if (t) - write_type_left(h, ds, NAME_DEFAULT, declonly, TRUE); + if (t) write_type_left(h, ds, name_type, declonly, TRUE);
if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
@@ -575,7 +573,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
void write_type_decl(FILE *f, const decl_spec_t *t, const char *name) { - write_type_v(f, t, FALSE, TRUE, name); + write_type_v(f, t, FALSE, TRUE, name, NAME_DEFAULT); }
void write_type_decl_left(FILE *f, const decl_spec_t *ds) @@ -804,7 +802,7 @@ static void write_generic_handle_routines(FILE *header) static void write_typedef(FILE *header, type_t *type, int declonly) { fprintf(header, "typedef "); - write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name); + write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_DEFAULT); fprintf(header, ";\n"); }
@@ -848,7 +846,7 @@ static void write_declaration(FILE *header, const var_t *v) fprintf(header, "extern "); break; } - write_type_v(header, &v->declspec, FALSE, v->declonly, v->name); + write_type_v(header, &v->declspec, FALSE, v->declonly, v->name, NAME_DEFAULT); fprintf(header, ";\n\n"); } } @@ -1065,7 +1063,7 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t * } }
-void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent) +void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent, enum name_type name_type) { const var_t *arg; int count = 0; @@ -1091,7 +1089,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i /* In theory we should be writing the definition using write_type_v(..., arg->declonly), * but that causes redefinition in e.g. proxy files. In fact MIDL disallows * defining UDTs inside of an argument list. */ - write_type_decl(h, &arg->declspec, arg->name); + write_type_v(h, &arg->declspec, FALSE, TRUE, arg->name, name_type); if (method == 2) { const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); if (expr) { @@ -1153,14 +1151,14 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) --indentation; if (args) { fprintf(header, ",\n"); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); } fprintf(header, ") = 0;\n");
indent(header, 0); write_type_decl_left(header, ret); fprintf(header, " %s %s(\n", callconv, get_name(func)); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); fprintf(header, ")\n"); indent(header, 0); fprintf(header, "{\n"); @@ -1185,7 +1183,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) fprintf(header, "virtual "); write_type_decl_left(header, ret); fprintf(header, " %s %s(\n", callconv, get_name(func)); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); fprintf(header, ") = 0;\n");
if (is_aggregate_return(func)) @@ -1222,7 +1220,7 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_ fprintf(header, "static FORCEINLINE "); write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " %s_%s(", name, get_name(func)); - write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE); + write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE, NAME_C); fprintf(header, ") {\n"); ++indentation; if (!is_aggregate_return(func)) { @@ -1286,7 +1284,7 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char --indentation; if (type_function_get_args(func->declspec.type)) { fprintf(header, ",\n"); - write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE); + write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE, NAME_C); } fprintf(header, ");\n"); fprintf(header, "\n"); @@ -1318,7 +1316,7 @@ static void write_method_proto(FILE *header, const type_t *iface) /* proxy prototype */ write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE); + write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(header, ");\n"); /* stub prototype */ fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); @@ -1353,7 +1351,7 @@ static void write_locals(FILE *fp, const type_t *iface, int body) /* proxy prototype - use local prototype */ write_type_decl_left(fp, type_function_get_ret(m->declspec.type)); fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); - write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE); + write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(fp, ")"); if (body) { const decl_spec_t *rt = type_function_get_ret(m->declspec.type); @@ -1375,7 +1373,7 @@ static void write_locals(FILE *fp, const type_t *iface, int body) /* stub prototype - use remotable prototype */ write_type_decl_left(fp, type_function_get_ret(func->declspec.type)); fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); - write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE); + write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(fp, ")"); if (body) /* Remotable methods must all return HRESULTs. */ @@ -1429,7 +1427,7 @@ static void write_function_proto(FILE *header, const type_t *iface, const var_t fprintf(header, " %s ", callconv); fprintf(header, "%s%s(\n", prefix, get_name(fun)); if (type_function_get_args(fun->declspec.type)) - write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE); + write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE, NAME_DEFAULT); else fprintf(header, " void"); fprintf(header, ");\n\n"); diff --git a/tools/widl/header.h b/tools/widl/header.h index cebfd83fe4c..d14e310addf 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -47,7 +47,7 @@ extern int need_proxy_file(const statement_list_t *stmts); extern int need_proxy_delegation(const statement_list_t *stmts); extern int need_inline_stubs_file(const statement_list_t *stmts); extern const var_t *is_callas(const attr_list_t *list); -extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent); +extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent, enum name_type name_type); extern const type_t* get_explicit_generic_handle_type(const var_t* var); extern const var_t *get_func_handle_var( const type_t *iface, const var_t *func, unsigned char *explicit_fc, unsigned char *implicit_fc ); diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index d7788e1d57e..457f29a2650 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -204,7 +204,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, if (get_stub_mode() == MODE_Oif && !is_callas( func->attrs )) return; write_type_decl_left(proxy, &retval->declspec); print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(proxy, args, iface->name, 1, TRUE); + write_args(proxy, args, iface->name, 1, TRUE, NAME_DEFAULT); print_proxy( ")\n"); write_client_call_routine( proxy, iface, func, "Object", proc_offset ); return; @@ -221,7 +221,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
write_type_decl_left(proxy, &retval->declspec); print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(proxy, args, iface->name, 1, TRUE); + write_args(proxy, args, iface->name, 1, TRUE, NAME_DEFAULT); print_proxy( ")\n"); print_proxy( "{\n"); indent ++;
We will scope the generics parameters into their respective interfaces, and widl would fail to find them as known types when parsing the methods otherwise.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 98bd8949f13..36711ff650c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1965,7 +1965,7 @@ type_t *find_type(const char *name, struct namespace *namespace, int t)
static type_t *find_type_or_error(const char *name, int t) { - type_t *type = find_type(name, NULL, t); + type_t *type = find_type(name, current_namespace, t); if (!type) { error_loc("type '%s' not found in %s\n", name, current_namespace->full_name); return NULL;
Interfaces are going to reference each other across namespaces, so this implements a type lookup with the full name.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.h | 1 + tools/widl/parser.l | 2 +- tools/widl/parser.y | 63 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/tools/widl/parser.h b/tools/widl/parser.h index a67b160d48a..a6dc94ae6b8 100644 --- a/tools/widl/parser.h +++ b/tools/widl/parser.h @@ -38,6 +38,7 @@ void pop_import(void); #define parse_only import_stack_ptr
int is_type(const char *name); +int is_namespace(const char *name);
int do_warning(char *toggle, warning_list_t *wnum); int is_warning_enabled(int warning); diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 3cbf4ff2d2b..925265d00db 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -451,7 +451,7 @@ static int kw_token(const char *kw) return kwp->token; } parser_lval.str = xstrdup(kw); - return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; + return is_type(kw) ? aKNOWNTYPE : is_namespace(kw) ? aNAMESPACE : aIDENTIFIER; }
static int attr_token(const char *kw) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 36711ff650c..d0883f7b8ab 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -81,6 +81,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 init_lookup_namespace(const char *name); +static void push_lookup_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); @@ -122,6 +124,7 @@ static struct namespace global_namespace = { };
static struct namespace *current_namespace = &global_namespace; +static struct namespace *lookup_namespace = &global_namespace;
static typelib_t *current_typelib;
@@ -156,7 +159,7 @@ static typelib_t *current_typelib; }
%token <str> aIDENTIFIER aPRAGMA -%token <str> aKNOWNTYPE +%token <str> aKNOWNTYPE aNAMESPACE %token <num> aNUM aHEXNUM %token <dbl> aDOUBLE %token <str> aSTRING aWSTRING aSQSTRING @@ -271,7 +274,7 @@ static typelib_t *current_typelib; %type <str> namespacedef %type <type> base_type int_std %type <type> enumdef structdef uniondef typedecl -%type <type> type +%type <type> type qualified_seq qualified_type %type <ifref> coclass_int %type <ifref_list> coclass_ints %type <var> arg ne_union_field union_field s_field case enum declaration @@ -817,6 +820,16 @@ int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); } | tINT3264 { $$ = type_new_int(TYPE_BASIC_INT3264, 0); } ;
+qualified_seq: + aKNOWNTYPE { $$ = find_type_or_error($1, 0); } + | aIDENTIFIER '.' { push_lookup_namespace($1); } qualified_seq { $$ = $4; } + ; + +qualified_type: + aKNOWNTYPE { $$ = find_type_or_error($1, 0); } + | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; } + ; + coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); if (type_get_type_detect_alias($$) != TYPE_COCLASS) @@ -837,6 +850,7 @@ coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt ;
namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } + | tNAMESPACE aNAMESPACE { $$ = $2; } ;
coclass_ints: { $$ = NULL; } @@ -881,7 +895,7 @@ dispinterfacedef: dispinterfacehdr '{' ;
inherit: { $$ = NULL; } - | ':' aKNOWNTYPE { $$ = find_type_or_error2($2, 0); } + | ':' qualified_type { $$ = $2; } ;
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } @@ -1096,7 +1110,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_nam ;
type: tVOID { $$ = type_new_void(); } - | aKNOWNTYPE { $$ = find_type_or_error($1, 0); } + | qualified_type { $$ = $1; } | base_type { $$ = $1; } | enumdef { $$ = $1; } | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } @@ -1854,6 +1868,21 @@ static void pop_namespace(const char *name) current_namespace = current_namespace->parent; }
+static void init_lookup_namespace(const char *name) +{ + if (!(lookup_namespace = find_sub_namespace(&global_namespace, name))) + error_loc("namespace '%s' not found\n", name); +} + +static void push_lookup_namespace(const char *name) +{ + struct namespace *namespace; + if (!(namespace = find_sub_namespace(lookup_namespace, name))) + error_loc("namespace '%s' not found in '%s'\n", name, + lookup_namespace->full_name ? lookup_namespace->full_name : "(global)"); + lookup_namespace = namespace; +} + struct rtype { const char *name; type_t *type; @@ -1965,12 +1994,16 @@ type_t *find_type(const char *name, struct namespace *namespace, int t)
static type_t *find_type_or_error(const char *name, int t) { - type_t *type = find_type(name, current_namespace, t); - if (!type) { - error_loc("type '%s' not found in %s\n", name, current_namespace->full_name); - return NULL; - } - return type; + type_t *type; + if (!(type = find_type(name, current_namespace, t)) && + !(type = find_type(name, lookup_namespace, t))) + { + error_loc("type '%s' not found in '%s' or '%s'\n", name, + current_namespace->full_name ? current_namespace->full_name : "(global)", + lookup_namespace->full_name ? lookup_namespace->full_name : "(global)"); + return NULL; + } + return type; }
static type_t *find_type_or_error2(char *name, int t) @@ -1982,7 +2015,15 @@ static type_t *find_type_or_error2(char *name, int t)
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, lookup_namespace, 0) != NULL; +} + +int is_namespace(const char *name) +{ + if (!winrt_mode) return 0; + return find_sub_namespace(current_namespace, name) != NULL || + find_sub_namespace(&global_namespace, name) != NULL; }
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t)
This should be enough to add the UWP dll stubs in idl files, but it's casting generics to void*. MIDL does something different apparently and even generates a new interface for every parameter type.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/expr.c | 1 + tools/widl/header.c | 4 ++++ tools/widl/parser.y | 27 +++++++++++++++++++++++---- tools/widl/typegen.c | 4 ++++ tools/widl/typelib.c | 1 + tools/widl/typetree.h | 1 + tools/widl/widltypes.h | 1 + 7 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index d1ee599a39e..950a1e46b6f 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -460,6 +460,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_COCLASS: case TYPE_INTERFACE: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_ARRAY: case TYPE_BITFIELD: /* nothing to do */ diff --git a/tools/widl/header.c b/tools/widl/header.c index c8a12556cc9..fcc73169d00 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -454,6 +454,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_COCLASS: fprintf(h, "%s", name); break; + case TYPE_GENERIC: + fprintf(h, "void*/*%s*/", name); + break; case TYPE_VOID: fprintf(h, "void"); break; @@ -518,6 +521,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_BITFIELD: fprintf(h, " : %u", type_bitfield_get_bits(t)->cval); break; + case TYPE_GENERIC: case TYPE_VOID: case TYPE_BASIC: case TYPE_ENUM: diff --git a/tools/widl/parser.y b/tools/widl/parser.y index d0883f7b8ab..1ca1ecb23c7 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -274,7 +274,7 @@ static typelib_t *current_typelib; %type <str> namespacedef %type <type> base_type int_std %type <type> enumdef structdef uniondef typedecl -%type <type> type qualified_seq qualified_type +%type <type> type qualified_seq qualified_type generics_type generics_decl %type <ifref> coclass_int %type <ifref_list> coclass_ints %type <var> arg ne_union_field union_field s_field case enum declaration @@ -830,6 +830,11 @@ qualified_type: | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; } ;
+generics_list: generics_type | generics_type '*' | generics_list ',' generics_list; +generics_args: | '<' generics_list '>'; + +generics_type: qualified_type generics_args; + coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); if (type_get_type_detect_alias($$) != TYPE_COCLASS) @@ -895,13 +900,16 @@ dispinterfacedef: dispinterfacehdr '{' ;
inherit: { $$ = NULL; } - | ':' qualified_type { $$ = $2; } + | ':' generics_type { $$ = $2; } ;
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } ;
+generics_decl: aIDENTIFIER { $$ = get_type(TYPE_GENERIC, $1, current_namespace, 0); }; +generics_decls: generics_decl | generics_decls ',' generics_decls; + interfacehdr: attributes interface { $$ = $2; check_def($2); $2->attrs = check_iface_attrs($2->name, $1); @@ -923,11 +931,21 @@ interfacedef: interfacehdr inherit semicolon_opt { $$ = $1; type_interface_define($$, find_type_or_error2($3, 0), $6); } + | interfacehdr + '<' { push_namespace($1->name); } generics_decls '>' inherit + '{' int_statements '}' semicolon_opt + { + $$ = $1; + if($$ == $6) error_loc("Interface can't inherit from itself\n"); + type_interface_define($$, $6, $8); + check_async_uuid($$); + pop_namespace($1->name); + } | dispinterfacedef semicolon_opt { $$ = $1; } ;
interfacedec: - interface ';' { $$ = $1; } + interface generics_args ';' { $$ = $1; } | dispinterface ';' { $$ = $1; } ;
@@ -1110,7 +1128,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_nam ;
type: tVOID { $$ = type_new_void(); } - | qualified_type { $$ = $1; } + | generics_type { $$ = $1; } | base_type { $$ = $1; } | enumdef { $$ = $1; } | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } @@ -2431,6 +2449,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_ENCAPSULATED_UNION: case TYPE_ARRAY: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_VOID: case TYPE_MODULE: case TYPE_COCLASS: diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 04280cbb722..f872e039010 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -351,6 +351,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) return TGT_RANGE; return TGT_ENUM; + case TYPE_GENERIC: + return TGT_IFACE_POINTER; case TYPE_POINTER: if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) @@ -1936,6 +1938,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) size = union_memsize(type_union_get_cases(t), align); break; case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_INTERFACE: assert( pointer_size ); size = pointer_size; @@ -2060,6 +2063,7 @@ static unsigned int type_buffer_alignment(const type_t *t) /* else fall through */ case TYPE_POINTER: return 4; + case TYPE_GENERIC: case TYPE_INTERFACE: case TYPE_ALIAS: case TYPE_VOID: diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index cf027558d0a..060ef45218a 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -193,6 +193,7 @@ unsigned short get_type_vt(type_t *t) break;
case TYPE_POINTER: + case TYPE_GENERIC: return VT_PTR;
case TYPE_ARRAY: diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index e288c574002..6afa5d25fe5 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -220,6 +220,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_MODULE: case TYPE_COCLASS: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_ARRAY: case TYPE_BITFIELD: return TRUE; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 1634f9bd50b..47704ce7d34 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -432,6 +432,7 @@ enum type_type TYPE_POINTER, TYPE_ARRAY, TYPE_BITFIELD, + TYPE_GENERIC, };
struct _type_t {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index fcc73169d00..6b86f0a95fe 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1460,12 +1460,65 @@ static void write_com_interface_start(FILE *header, const type_t *iface) fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); }
+static char *get_winrt_guard_macro(type_t *iface) +{ + const char *tmp = (char *)iface->c_name; + char *macro; + int i; + + if (!strncmp(tmp, "__x", 3)) tmp += 3; + if (!strncmp(tmp, "_ABI_", 5)) tmp += 5; + macro = xstrdup(tmp); + for (i = strlen(macro); i > 0; --i) macro[i - 1] = toupper(macro[i - 1]); + + return macro; +} + +static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *child) +{ + const statement_t *stmt; + + if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), child); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + + if (is_override_method(iface, child, func)) continue; + + if (!is_callas(func->attrs)) + fprintf(header, "#define %s_%s %s_%s\n", child->name, get_name(func), child->c_name, get_name(func)); + } +} + +static void write_widl_using_macros(FILE *header, type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + char *macro; + + if (!strcmp(iface->name, iface->c_name)) return; + + macro = get_winrt_guard_macro(iface); + fprintf(header, "#ifdef WIDL_USING_%s\n", macro); + + if (uuid) fprintf(header, "#define IID_%s IID_%s\n", iface->name, iface->c_name); + fprintf(header, "#define %sVtbl %sVtbl\n", iface->name, iface->c_name); + fprintf(header, "#define %s %s\n", iface->name, iface->c_name); + + write_widl_using_method_macros(header, iface, iface); + + fprintf(header, "#endif /* WIDL_USING_%s */\n\n", macro); + free(macro); +} + static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); type_t *type;
+ if (winrt_mode) write_widl_using_macros(header, iface); + if (uuid) write_guid(header, dispinterface ? "DIID" : "IID", iface->c_name, uuid);