Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.l | 1 + tools/widl/parser.y | 3 +++ tools/widl/widltypes.h | 1 + 3 files changed, 5 insertions(+)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 8acc9c9590c..d726e76744e 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -320,6 +320,7 @@ static const struct keyword keywords[] = { */ static const struct keyword attr_keywords[] = { + {"activatable", tACTIVATABLE, 1}, {"aggregatable", tAGGREGATABLE, 0}, {"agile", tAGILE, 1}, {"all_nodes", tALLNODES, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index b43a1cdd5f2..eaeba90609d 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -166,6 +166,7 @@ static typelib_t *current_typelib; %token GREATEREQUAL LESSEQUAL %token LOGICALOR LOGICALAND %token ELLIPSIS +%token tACTIVATABLE %token tAGGREGATABLE %token tAGILE %token tALLNODES tALLOCATE tANNOTATION @@ -539,6 +540,7 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO }
attribute: { $$ = NULL; } + | tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); } | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } | tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); } @@ -2162,6 +2164,7 @@ struct allowed_attr struct allowed_attr allowed_attr[] = { /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */ + /* ATTR_ACTIVATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "activatable" }, /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, /* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "allocate" }, /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 0fba33d6a09..5d4532d6434 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -69,6 +69,7 @@ typedef struct list warning_list_t;
enum attr_type { + ATTR_ACTIVATABLE, ATTR_AGGREGATABLE, ATTR_ALLOCATE, ATTR_ANNOTATION,
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.l | 1 + tools/widl/parser.y | 8 ++++++++ tools/widl/widltypes.h | 1 + 3 files changed, 10 insertions(+)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index d726e76744e..9b93a53b839 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -427,6 +427,7 @@ static const struct keyword attr_keywords[] = {"size_is", tSIZEIS, 0}, {"source", tSOURCE, 0}, {"standard", tSTANDARD, 1}, + {"static", tSTATIC, 1}, {"strict_context_handle", tSTRICTCONTEXTHANDLE, 0}, {"string", tSTRING, 0}, {"switch_is", tSWITCHIS, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index eaeba90609d..b8c916f8336 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -277,6 +277,7 @@ static typelib_t *current_typelib; %type <expr> m_expr expr expr_const expr_int_const array m_bitfield %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const %type <expr> contract_req +%type <expr> static_attr %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list %type <function_specifier> function_specifier @@ -539,6 +540,11 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); }
+static_attr: decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) + error_loc("type %s is not an interface\n", $1->type->name); + $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); + } + attribute: { $$ = NULL; } | tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); } | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } @@ -637,6 +643,7 @@ attribute: { $$ = NULL; } | tRETVAL { $$ = make_attr(ATTR_RETVAL); } | tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); } | tSOURCE { $$ = make_attr(ATTR_SOURCE); } + | tSTATIC '(' static_attr ')' { $$ = make_attrp(ATTR_STATIC, $3); } | tSTRICTCONTEXTHANDLE { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); } | tSTRING { $$ = make_attr(ATTR_STRING); } | tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); } @@ -2258,6 +2265,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, /* ATTR_SIZEIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, + /* ATTR_STATIC */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "static" }, /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, /* ATTR_STRING */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 5d4532d6434..facfff21453 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -163,6 +163,7 @@ enum attr_type ATTR_RETVAL, ATTR_SIZEIS, ATTR_SOURCE, + ATTR_STATIC, ATTR_STRICTCONTEXTHANDLE, ATTR_STRING, ATTR_SWITCHIS,
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
For now we ignore not-yet-defined interfaces in the runtimeclass (and coclass) interface list, but it's probably worth emitting a warning at least, after Wine uses have been cleaned - which will take a while.
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
Signed-off-by: Jacek Caban jacek@codeweavers.com
As an illustration for the newly supported attributes.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.media.speechsynthesis.idl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 502261f79c6..87497678f30 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -24,10 +24,16 @@ import "inspectable.idl"; import "windows.foundation.idl";
namespace Windows { + namespace Foundation { + interface IClosable; + } namespace Media { namespace SpeechSynthesis { typedef enum VoiceGender VoiceGender; interface IInstalledVoicesStatic; + interface IInstalledVoicesStatic2; + interface ISpeechSynthesizer; + interface ISpeechSynthesizer2; interface IVoiceInformation; runtimeclass VoiceInformation; } @@ -66,6 +72,20 @@ namespace Windows { { [default] interface Windows.Media.SpeechSynthesis.IVoiceInformation; } + + [ + activatable(Windows.Foundation.UniversalApiContract, 1.0), + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + static(Windows.Media.SpeechSynthesis.IInstalledVoicesStatic, Windows.Foundation.UniversalApiContract, 1.0), + static(Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2, Windows.Foundation.UniversalApiContract, 5.0) + ] + runtimeclass SpeechSynthesizer + { + [default] interface Windows.Media.SpeechSynthesis.ISpeechSynthesizer; + interface Windows.Foundation.IClosable; + [contract(Windows.Foundation.UniversalApiContract, 4.0)] interface Windows.Media.SpeechSynthesis.ISpeechSynthesizer2; + } } } }
Signed-off-by: Jacek Caban jacek@codeweavers.com