Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Updating this patch with the suggested change, and adding a few more.
tools/widl/header.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 63389440c94..e6394991317 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1702,6 +1702,7 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) { expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT); char *name, *c_name; + size_t i, len; name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL); c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL); fprintf(header, "/*\n"); @@ -1710,6 +1711,14 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) if (contract) write_apicontract_guard_start(header, contract); fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); + fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n"); + /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ + fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#else\n"); + fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n"); + fprintf(header, "#endif\n"); fprintf(header, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name); free(c_name); free(name);
And make qualified name lookup more robust:
* Either parse a non-qualified name directly from the current (or global) namespace, or start parsing a qualified name.
* Qualified name parsing uses the lookup namespace stack only to find types or sub-namespaces.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.media.speechsynthesis.idl | 2 +- tools/widl/parser.y | 58 +++++++++++++++-------- 2 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 71c51b74c0c..502261f79c6 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -64,7 +64,7 @@ namespace Windows { ] runtimeclass VoiceInformation { - [default] interface IVoiceInformation; + [default] interface Windows.Media.SpeechSynthesis.IVoiceInformation; } } } diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 480552e3723..1e3e254ec8c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -75,6 +75,8 @@ static void append_chain_callconv(type_t *chain, char *callconv); static warning_list_t *append_warning(warning_list_t *, int);
static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); +static type_t *get_qualified_type(enum type_type type, char *name, int t); +static type_t *find_qualified_type_or_error(const char *name, int t); static type_t *find_type_or_error(const char *name, int t); static type_t *find_type_or_error2(char *name, int t);
@@ -82,7 +84,6 @@ 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); @@ -295,7 +296,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_type %type <ifref> class_interface %type <ifref_list> class_interfaces %type <var> arg ne_union_field union_field s_field case enum enum_member declaration @@ -888,15 +889,15 @@ 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; } - ; +namespace_pfx: + aNAMESPACE '.' { push_lookup_namespace($1); } + | namespace_pfx aNAMESPACE '.' { push_lookup_namespace($2); } + ;
qualified_type: - aKNOWNTYPE { $$ = find_type_or_error($1, 0); } - | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; } - ; + aKNOWNTYPE { $$ = find_type_or_error($1, 0); } + | namespace_pfx aKNOWNTYPE { $$ = find_qualified_type_or_error($2, 0); } + ;
coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); @@ -994,6 +995,8 @@ inherit: { $$ = NULL; }
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } + | tINTERFACE namespace_pfx aIDENTIFIER { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); } + | tINTERFACE namespace_pfx aKNOWNTYPE { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); } ;
interfacehdr: attributes interface { $$ = $2; @@ -1970,12 +1973,6 @@ 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; @@ -2093,11 +2090,29 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) return NULL; }
+static type_t *get_qualified_type(enum type_type type_type, char *name, int t) +{ + type_t *type = get_type(type_type, name, lookup_namespace, t); + lookup_namespace = &global_namespace; + return type; +} + +static type_t *find_qualified_type_or_error(const char *name, int t) +{ + type_t *type; + if (!(type = find_type(name, lookup_namespace, t))) + { + error_loc("type '%s' not found\n", name); + return NULL; + } + lookup_namespace = &global_namespace; + return type; +} + static type_t *find_type_or_error(const char *name, int t) { type_t *type; - if (!(type = find_type(name, current_namespace, t)) && - !(type = find_type(name, lookup_namespace, t))) + if (!(type = find_type(name, current_namespace, t))) { error_loc("type '%s' not found\n", name); return NULL; @@ -2114,15 +2129,16 @@ 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 || - find_type(name, lookup_namespace, 0) != NULL; + if (lookup_namespace != &global_namespace) + return find_type(name, lookup_namespace, 0) != NULL; + else + return find_type(name, current_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; + return find_sub_namespace(lookup_namespace, name) != NULL; }
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t)
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
Either parse a non-qualified name directly from the current (or global) namespace, or start parsing a qualified name.
Qualified name parsing uses the lookup namespace stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
- Either parse a non-qualified name directly from
the current (or global) namespace, or start parsing a qualified name.
- Qualified name parsing uses the lookup namespace
stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
- Either parse a non-qualified name directly from
the current (or global) namespace, or start parsing a qualified name.
- Qualified name parsing uses the lookup namespace
stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
On 04.02.2021 11:52, Rémi Bernon wrote:
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
- Either parse a non-qualified name directly from
the current (or global) namespace, or start parsing a qualified name.
- Qualified name parsing uses the lookup namespace
stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
If we need to support that then yes, it would be problematic. But should we support that at all? Unless I'm missing something, widl does not have a reason to understand cast expressions. Does midl have some concept of casts?
Jacek
On 2/4/21 12:48 PM, Jacek Caban wrote:
On 04.02.2021 11:52, Rémi Bernon wrote:
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
- Either parse a non-qualified name directly from
the current (or global) namespace, or start parsing a qualified name.
- Qualified name parsing uses the lookup namespace
stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
If we need to support that then yes, it would be problematic. But should we support that at all? Unless I'm missing something, widl does not have a reason to understand cast expressions. Does midl have some concept of casts?
Jacek
Well there are examples in Wine IDLs where casts are used, like for instance in oleidl.idl, when initializing constants.
MIDL supports the following code for instance, which would be harder to parse without help from the lexer:
[] interface ITest { typedef int T1; const int V1 = 0x00000001; const int V2 = (V1)+0x00000001; const int V3 = (T1)+0x00000001; }
On 04.02.2021 13:00, Rémi Bernon wrote:
On 2/4/21 12:48 PM, Jacek Caban wrote:
On 04.02.2021 11:52, Rémi Bernon wrote:
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote:
And make qualified name lookup more robust:
- Either parse a non-qualified name directly from
the current (or global) namespace, or start parsing a qualified name.
- Qualified name parsing uses the lookup namespace
stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
If we need to support that then yes, it would be problematic. But should we support that at all? Unless I'm missing something, widl does not have a reason to understand cast expressions. Does midl have some concept of casts?
Jacek
Well there are examples in Wine IDLs where casts are used, like for instance in oleidl.idl, when initializing constants.
MIDL supports the following code for instance, which would be harder to parse without help from the lexer:
[] interface ITest { typedef int T1; const int V1 = 0x00000001; const int V2 = (V1)+0x00000001; const int V3 = (T1)+0x00000001; }
Oh, right. So getting rid of lookup_namespace would be more problematic than I expected. Still, I think we can make it nicer. I will send comments to the original patch.
Jacek
On 2/4/21 1:35 PM, Jacek Caban wrote:
On 04.02.2021 13:00, Rémi Bernon wrote:
On 2/4/21 12:48 PM, Jacek Caban wrote:
On 04.02.2021 11:52, Rémi Bernon wrote:
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote:
On 02.02.2021 09:22, Rémi Bernon wrote: > And make qualified name lookup more robust: > > * Either parse a non-qualified name directly from > the current (or global) namespace, or start > parsing a qualified name. > > * Qualified name parsing uses the lookup namespace > stack only to find types or sub-namespaces.
I think it's a step in the right direction, but things like find_qualified_type_or_error() resetting lookup_namespace as a side effect does not look appealing.
I wonder if we could entirely get rid of global lookup_namespace variable. As far as parser is considered, namespace_pfx could just return a namespace type that we could use to find types. That leaves us with is_type() and is_namespace(), which are used in lexer. I'd say that it's not a job of lexer to distinguish between an identifier and a known type. Maybe we could just get rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser instead?
Thanks,
Jacek
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
If we need to support that then yes, it would be problematic. But should we support that at all? Unless I'm missing something, widl does not have a reason to understand cast expressions. Does midl have some concept of casts?
Jacek
Well there are examples in Wine IDLs where casts are used, like for instance in oleidl.idl, when initializing constants.
MIDL supports the following code for instance, which would be harder to parse without help from the lexer:
[] interface ITest { typedef int T1; const int V1 = 0x00000001; const int V2 = (V1)+0x00000001; const int V3 = (T1)+0x00000001; }
Oh, right. So getting rid of lookup_namespace would be more problematic than I expected. Still, I think we can make it nicer. I will send comments to the original patch.
Jacek
I think getting rid of lookup_namespace is possible without too much trouble, but with some prior refactoring, that I started here:
https://github.com/rbernon/wine/compare/master...wip/widl-refactor/v1.patch
What will be hard is to fold the aKNOWNTYPE / aIDENTIFIER token.
On 04.02.2021 13:45, Rémi Bernon wrote:
On 2/4/21 1:35 PM, Jacek Caban wrote:
On 04.02.2021 13:00, Rémi Bernon wrote:
On 2/4/21 12:48 PM, Jacek Caban wrote:
On 04.02.2021 11:52, Rémi Bernon wrote:
On 2/3/21 4:30 PM, Rémi Bernon wrote:
On 2/3/21 4:22 PM, Jacek Caban wrote: > On 02.02.2021 09:22, Rémi Bernon wrote: >> And make qualified name lookup more robust: >> >> * Either parse a non-qualified name directly from >> the current (or global) namespace, or start >> parsing a qualified name. >> >> * Qualified name parsing uses the lookup namespace >> stack only to find types or sub-namespaces. > > > I think it's a step in the right direction, but things like > find_qualified_type_or_error() resetting lookup_namespace as a > side effect does not look appealing. > > > I wonder if we could entirely get rid of global lookup_namespace > variable. As far as parser is considered, namespace_pfx could > just return a namespace type that we could use to find types. > That leaves us with is_type() and is_namespace(), which are used > in lexer. I'd say that it's not a job of lexer to distinguish > between an identifier and a known type. Maybe we could just get > rid of aNAMESPACE and aKNOWNTYPE and deal with that in parser > instead? > > > Thanks, > > Jacek >
It may be better with a bit of refactoring but I was wary of changing existing logic too much, especially as this is WinRT only, so I just tried to build upon what was already there (with the lookup_namespace introduction earlier, and this change now).
I could have a better look I guess.
So I can probably clean this up a bit and get rid of the lookup_namespace mechanism, but I think the lexer interaction trick is going to be much more difficult to replace.
For instance, the aIDENTIFIER / aKNOWNTYPE tokens help making expressions parsing unambiguous. Consider the following expression:
'(' aIDENTIFIER ')' '&' aIDENTIFIER
I think it's hard (if not impossible, but I'm definitely no bison expert) to write a rule that can decide to parse it as a CAST ADDRESSOF expression, or as an AND expression depending on whether the identifiers are known types or not.
Note that the CAST expression rule also needs to specify an operator precedence modifier, which I don't know how to make dependent on the rule actions.
Also, there's the same conflicts happening in WinRT between qualified type names and member accesses.
From what I understand from bison documentation, there's a GLR mode that can be used to solve this kind of situation, but I'm not sure if it's the right or only solution.
If we need to support that then yes, it would be problematic. But should we support that at all? Unless I'm missing something, widl does not have a reason to understand cast expressions. Does midl have some concept of casts?
Jacek
Well there are examples in Wine IDLs where casts are used, like for instance in oleidl.idl, when initializing constants.
MIDL supports the following code for instance, which would be harder to parse without help from the lexer:
[] interface ITest { typedef int T1; const int V1 = 0x00000001; const int V2 = (V1)+0x00000001; const int V3 = (T1)+0x00000001; }
Oh, right. So getting rid of lookup_namespace would be more problematic than I expected. Still, I think we can make it nicer. I will send comments to the original patch.
Jacek
I think getting rid of lookup_namespace is possible without too much trouble, but with some prior refactoring, that I started here:
https://github.com/rbernon/wine/compare/master...wip/widl-refactor/v1.patch
What will be hard is to fold the aKNOWNTYPE / aIDENTIFIER token.
Great, thanks. The new series seems good after a quick look.
Jacek
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 7e20d30e7f0..264fa7f906c 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 1e3e254ec8c..3b7953ae19c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -176,6 +176,7 @@ static typelib_t *current_typelib; %token GREATEREQUAL LESSEQUAL %token LOGICALOR LOGICALAND %token ELLIPSIS +%token tACTIVATABLE %token tAGGREGATABLE %token tAGILE %token tALLNODES tALLOCATE tANNOTATION @@ -542,6 +543,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); } @@ -2243,6 +2245,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 264fa7f906c..af09b550317 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 3b7953ae19c..2ff5e0b5b3c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -286,6 +286,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 <type> interfacehdr %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list @@ -542,6 +543,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); } @@ -640,6 +646,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); } @@ -2339,6 +2346,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,
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; + } } } }