Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This is the continuation of my WinRT support patches, tracked in [1].
I've left the DECLSPEC_SELECTANY runtimeclass string constants aside for now, and I'll add them to the generated headers in a separate patch.
A previous version of whole series is already in Wine Staging, and it has been successfully used [2] by Steve Lhomme robux4@ycbcr.xyz for VLC, and who also contributed fixes that I've merged in the series.
[1] https://bugs.winehq.org/show_bug.cgi?id=49998 [2] https://github.com/robUx4/mingw-w64/commits/vlc_winrt/12
This IDL is used by windows.media.speech.dll, which is itself required by Flight Simulator. It will here be used as an illustration and test case for WIDL WinRT features.
include/Makefile.in | 1 + include/windows.media.speechsynthesis.idl | 47 +++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 include/windows.media.speechsynthesis.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 74a1d8e0c89..096fb4554e5 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -745,6 +745,7 @@ SOURCES = \ windef.h \ windns.h \ windows.foundation.idl \ + windows.media.speechsynthesis.idl \ windows.h \ windowscontracts.idl \ windowsx.h \ diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl new file mode 100644 index 00000000000..7a1de5fcba6 --- /dev/null +++ b/include/windows.media.speechsynthesis.idl @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "windows.foundation.idl"; + +namespace Windows { + namespace Media { + namespace SpeechSynthesis { + typedef enum VoiceGender VoiceGender; + interface IInstalledVoicesStatic; + interface IVoiceInformation; + } + } +} + +namespace Windows { + namespace Media { + namespace SpeechSynthesis { + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum VoiceGender + { + Male = 0, + Female = 1 + }; + } + } +}
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 4 ++++ tools/widl/parser.y | 18 ++++++++++++++++-- tools/widl/widltypes.h | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 223ab5c5ca9..21f8528c31d 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); } + switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR)) + { + case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break; + case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break; + case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break; + default: break; + } }
static void write_apicontract_guard_start(FILE *header, const expr_t *expr) diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 9dce03577c6..01c6f800a08 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[] = { {"aggregatable", tAGGREGATABLE, 0}, + {"agile", tAGILE, 1}, {"all_nodes", tALLNODES, 0}, {"allocate", tALLOCATE, 0}, {"annotation", tANNOTATION, 0}, @@ -381,12 +382,14 @@ static const struct keyword attr_keywords[] = {"length_is", tLENGTHIS, 0}, {"licensed", tLICENSED, 0}, {"local", tLOCAL, 0}, + {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0}, {"noncreatable", tNONCREATABLE, 0}, + {"none", tNONE, 1}, {"nonextensible", tNONEXTENSIBLE, 0}, {"notify", tNOTIFY, 0}, {"notify_flag", tNOTIFYFLAG, 0}, @@ -416,6 +419,7 @@ static const struct keyword attr_keywords[] = {"single_node", tSINGLENODE, 0}, {"size_is", tSIZEIS, 0}, {"source", tSOURCE, 0}, + {"standard", tSTANDARD, 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 b729d772fcd..48f180cdb49 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -174,7 +174,9 @@ static typelib_t *current_typelib; %token GREATEREQUAL LESSEQUAL %token LOGICALOR LOGICALAND %token ELLIPSIS -%token tAGGREGATABLE tALLNODES tALLOCATE tANNOTATION +%token tAGGREGATABLE +%token tAGILE +%token tALLNODES tALLOCATE tANNOTATION %token tAPICONTRACT %token tAPPOBJECT tASYNC tASYNCUUID %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT @@ -216,12 +218,14 @@ static typelib_t *current_typelib; %token tLENGTHIS tLIBRARY %token tLICENSED tLOCAL %token tLONG +%token tMARSHALINGBEHAVIOR %token tMAYBE tMESSAGE %token tMETHODS %token tMODULE %token tNAMESPACE %token tNOCODE tNONBROWSABLE %token tNONCREATABLE +%token tNONE %token tNONEXTENSIBLE %token tNOTIFY tNOTIFYFLAG %token tNULL @@ -247,6 +251,7 @@ static typelib_t *current_typelib; %token tSIZEIS tSIZEOF %token tSMALL %token tSOURCE +%token tSTANDARD %token tSTATIC %token tSTDCALL %token tSTRICTCONTEXTHANDLE @@ -299,7 +304,7 @@ static typelib_t *current_typelib; %type <type> coclass coclasshdr coclassdef %type <type> apicontract %type <num> contract_ver -%type <num> pointer_type threading_type version +%type <num> pointer_type threading_type marshaling_behavior version %type <str> libraryhdr callconv cppquote importlib import t_ident %type <uuid> uuid_string %type <import> import_start @@ -505,6 +510,12 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); } | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } ;
+marshaling_behavior: + tAGILE { $$ = MARSHALING_AGILE; } + | tNONE { $$ = MARSHALING_NONE; } + | tSTANDARD { $$ = MARSHALING_STANDARD; } + ; + contract_ver: aNUM { $$ = MAKEVERSION(0, $1); } | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } @@ -572,6 +583,8 @@ attribute: { $$ = NULL; } | tLCID { $$ = make_attr(ATTR_PARAMLCID); } | tLICENSED { $$ = make_attr(ATTR_LICENSED); } | tLOCAL { $$ = make_attr(ATTR_LOCAL); } + | tMARSHALINGBEHAVIOR '(' marshaling_behavior ')' + { $$ = make_attrv(ATTR_MARSHALING_BEHAVIOR, $3); } | tMAYBE { $$ = make_attr(ATTR_MAYBE); } | tMESSAGE { $$ = make_attr(ATTR_MESSAGE); } | tNOCODE { $$ = make_attr(ATTR_NOCODE); } @@ -2230,6 +2243,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, + /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" }, /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index d5862426ad4..6c130d4701e 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -125,6 +125,7 @@ enum attr_type ATTR_LIBLCID, ATTR_LICENSED, ATTR_LOCAL, + ATTR_MARSHALING_BEHAVIOR, ATTR_MAYBE, ATTR_MESSAGE, ATTR_NOCODE, @@ -271,6 +272,14 @@ enum threading_type THREADING_BOTH };
+enum marshaling_type +{ + MARSHALING_INVALID = 0, + MARSHALING_NONE, + MARSHALING_AGILE, + MARSHALING_STANDARD, +}; + enum type_basic_type { TYPE_BASIC_INT8 = 1,
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 4 ++++ tools/widl/parser.y | 18 ++++++++++++++++-- tools/widl/widltypes.h | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 223ab5c5ca9..21f8528c31d 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); }
- switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR))
- {
case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break;
case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break;
case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break;
default: break;
- }
}
I guess I should have asked this earlier, but is there a point in writing these comments?
static void write_apicontract_guard_start(FILE *header, const expr_t *expr) diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 9dce03577c6..01c6f800a08 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[] = { {"aggregatable", tAGGREGATABLE, 0},
- {"agile", tAGILE, 1}, {"all_nodes", tALLNODES, 0}, {"allocate", tALLOCATE, 0}, {"annotation", tANNOTATION, 0},
@@ -381,12 +382,14 @@ static const struct keyword attr_keywords[] = {"length_is", tLENGTHIS, 0}, {"licensed", tLICENSED, 0}, {"local", tLOCAL, 0},
- {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0}, {"noncreatable", tNONCREATABLE, 0},
- {"none", tNONE, 1}, {"nonextensible", tNONEXTENSIBLE, 0}, {"notify", tNOTIFY, 0}, {"notify_flag", tNOTIFYFLAG, 0},
@@ -416,6 +419,7 @@ static const struct keyword attr_keywords[] = {"single_node", tSINGLENODE, 0}, {"size_is", tSIZEIS, 0}, {"source", tSOURCE, 0},
- {"standard", tSTANDARD, 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 b729d772fcd..48f180cdb49 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -174,7 +174,9 @@ static typelib_t *current_typelib; %token GREATEREQUAL LESSEQUAL %token LOGICALOR LOGICALAND %token ELLIPSIS -%token tAGGREGATABLE tALLNODES tALLOCATE tANNOTATION +%token tAGGREGATABLE +%token tAGILE +%token tALLNODES tALLOCATE tANNOTATION %token tAPICONTRACT %token tAPPOBJECT tASYNC tASYNCUUID %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT @@ -216,12 +218,14 @@ static typelib_t *current_typelib; %token tLENGTHIS tLIBRARY %token tLICENSED tLOCAL %token tLONG +%token tMARSHALINGBEHAVIOR %token tMAYBE tMESSAGE %token tMETHODS %token tMODULE %token tNAMESPACE %token tNOCODE tNONBROWSABLE %token tNONCREATABLE +%token tNONE %token tNONEXTENSIBLE %token tNOTIFY tNOTIFYFLAG %token tNULL @@ -247,6 +251,7 @@ static typelib_t *current_typelib; %token tSIZEIS tSIZEOF %token tSMALL %token tSOURCE +%token tSTANDARD %token tSTATIC %token tSTDCALL %token tSTRICTCONTEXTHANDLE @@ -299,7 +304,7 @@ static typelib_t *current_typelib; %type <type> coclass coclasshdr coclassdef %type <type> apicontract %type <num> contract_ver -%type <num> pointer_type threading_type version +%type <num> pointer_type threading_type marshaling_behavior version %type <str> libraryhdr callconv cppquote importlib import t_ident %type <uuid> uuid_string %type <import> import_start @@ -505,6 +510,12 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); } | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } ;
+marshaling_behavior:
tAGILE { $$ = MARSHALING_AGILE; }
- | tNONE { $$ = MARSHALING_NONE; }
- | tSTANDARD { $$ = MARSHALING_STANDARD; }
- ;
contract_ver: aNUM { $$ = MAKEVERSION(0, $1); } | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } @@ -572,6 +583,8 @@ attribute: { $$ = NULL; } | tLCID { $$ = make_attr(ATTR_PARAMLCID); } | tLICENSED { $$ = make_attr(ATTR_LICENSED); } | tLOCAL { $$ = make_attr(ATTR_LOCAL); }
- | tMARSHALINGBEHAVIOR '(' marshaling_behavior ')'
| tMAYBE { $$ = make_attr(ATTR_MAYBE); } | tMESSAGE { $$ = make_attr(ATTR_MESSAGE); } | tNOCODE { $$ = make_attr(ATTR_NOCODE); }{ $$ = make_attrv(ATTR_MARSHALING_BEHAVIOR, $3); }
@@ -2230,6 +2243,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" }, /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index d5862426ad4..6c130d4701e 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -125,6 +125,7 @@ enum attr_type ATTR_LIBLCID, ATTR_LICENSED, ATTR_LOCAL,
- ATTR_MARSHALING_BEHAVIOR, ATTR_MAYBE, ATTR_MESSAGE, ATTR_NOCODE,
@@ -271,6 +272,14 @@ enum threading_type THREADING_BOTH };
+enum marshaling_type +{
- MARSHALING_INVALID = 0,
- MARSHALING_NONE,
- MARSHALING_AGILE,
- MARSHALING_STANDARD,
+};
enum type_basic_type { TYPE_BASIC_INT8 = 1,
On 1/19/21 6:34 PM, Zebediah Figura (she/her) wrote:
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 4 ++++ tools/widl/parser.y | 18 ++++++++++++++++-- tools/widl/widltypes.h | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 223ab5c5ca9..21f8528c31d 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); }
- switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR))
- {
case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break;
case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break;
case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break;
default: break;
- } }
I guess I should have asked this earlier, but is there a point in writing these comments?
Probably not, but MIDL does it.
On 1/19/21 11:42 AM, Rémi Bernon wrote:
On 1/19/21 6:34 PM, Zebediah Figura (she/her) wrote:
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 4 ++++ tools/widl/parser.y | 18 ++++++++++++++++-- tools/widl/widltypes.h | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 223ab5c5ca9..21f8528c31d 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); } + switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR)) + { + case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break; + case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break; + case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break; + default: break; + } }
I guess I should have asked this earlier, but is there a point in writing these comments?
Probably not, but MIDL does it.
MIDL does a lot of things we don't, especially where comments are concerned. I'm not aware of it being a copyright concern to avoid matching MIDL exactly (though I'm also not aware if it not being one), but I also doubt we should write extra code to match MIDL where it doesn't impact the actual C compiler.
As a WinRT specific alias to free-threaded model.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 1 + tools/widl/parser.y | 2 ++ 3 files changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 21f8528c31d..b6cf43e7228 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); } + switch (get_attrv(type->attrs, ATTR_THREADING)) + { + case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; + case THREADING_BOTH: fprintf(header, " * Class Threading Model: Both Single and Multi Threaded Apartment\n *\n"); break; + case THREADING_FREE: fprintf(header, " * Class Threading Model: Multi Threaded Apartment\n *\n"); break; + default: break; + } switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR)) { case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break; diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 01c6f800a08..067966a85d4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -385,6 +385,7 @@ static const struct keyword attr_keywords[] = {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0}, + {"mta" , tMTA, 1}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 48f180cdb49..4ce84cc2440 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -222,6 +222,7 @@ static typelib_t *current_typelib; %token tMAYBE tMESSAGE %token tMETHODS %token tMODULE +%token tMTA %token tNAMESPACE %token tNOCODE tNONBROWSABLE %token tNONCREATABLE @@ -1154,6 +1155,7 @@ threading_type: | tSINGLE { $$ = THREADING_SINGLE; } | tFREE { $$ = THREADING_FREE; } | tBOTH { $$ = THREADING_BOTH; } + | tMTA { $$ = THREADING_FREE; } ;
pointer_type:
Hi Rémi,
On 19/01/2021 14:04, Rémi Bernon wrote:
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 01c6f800a08..067966a85d4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -385,6 +385,7 @@ static const struct keyword attr_keywords[] = {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0},
- {"mta" , tMTA, 1}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0},
I think that currently threading attribute is used only as widl extension for registration code. It probably predates midl winrt, but it looks like it's mostly compatible. Maybe we should make the extension more compatible with winrt, eg. migrate our code to use 'mta' instead or 'free' (instead of making mta winrt-only)?
Also, as Zebediah pointed out, generated header comments are not necessarily something we want. At very least, you could extract those parts of the series into a separated patch so we can discus it from there. They don't really belong to parsing part of their support anyway. FWIW, as header/IDL user, I think that the right place to look for those things are IDL files, not generated headers, so comments there are not very useful anyway. If we want to provide more informational comments in headers, I would suggest to print IDL attributes in IDL syntax in comments instead.
Thanks,
Jacek
On 1/25/21 12:17 PM, Jacek Caban wrote:
Hi Rémi,
On 19/01/2021 14:04, Rémi Bernon wrote:
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 01c6f800a08..067966a85d4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -385,6 +385,7 @@ static const struct keyword attr_keywords[] = {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0}, + {"mta" , tMTA, 1}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0},
I think that currently threading attribute is used only as widl extension for registration code. It probably predates midl winrt, but it looks like it's mostly compatible. Maybe we should make the extension more compatible with winrt, eg. migrate our code to use 'mta' instead or 'free' (instead of making mta winrt-only)?
Ah sorry, I missed your message and resent the series with just the comments removed. I guess if there's some refactoring to be done it can still be done later and remove the WinRT-only flag?
Also, as Zebediah pointed out, generated header comments are not necessarily something we want. At very least, you could extract those parts of the series into a separated patch so we can discus it from there. They don't really belong to parsing part of their support anyway. FWIW, as header/IDL user, I think that the right place to look for those things are IDL files, not generated headers, so comments there are not very useful anyway. If we want to provide more informational comments in headers, I would suggest to print IDL attributes in IDL syntax in comments instead.
Yes, I removed them. I don't think they are very useful anyway, they are simply used to translate the IDL attributes into something readable in the generated header.
Jacek Caban jacek@codeweavers.com writes:
Hi Rémi,
On 19/01/2021 14:04, Rémi Bernon wrote:
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 01c6f800a08..067966a85d4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -385,6 +385,7 @@ static const struct keyword attr_keywords[] = {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0},
- {"mta" , tMTA, 1}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0},
I think that currently threading attribute is used only as widl extension for registration code. It probably predates midl winrt, but it looks like it's mostly compatible. Maybe we should make the extension more compatible with winrt, eg. migrate our code to use 'mta' instead or 'free' (instead of making mta winrt-only)?
The current support was modeled after the C++ attributes:
https://docs.microsoft.com/en-us/cpp/windows/attributes/threading-cpp?view=m...
so it may make sense to keep 'free' as an alias. OTOH we don't seem to be using it in the existing code anyway.
On 25.01.2021 14:12, Alexandre Julliard wrote:
On 19/01/2021 14:04, Rémi Bernon wrote:
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 01c6f800a08..067966a85d4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -385,6 +385,7 @@ static const struct keyword attr_keywords[] = {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, {"maybe", tMAYBE, 0}, {"message", tMESSAGE, 0},
- {"mta" , tMTA, 1}, {"neutral", tNEUTRAL, 0}, {"nocode", tNOCODE, 0}, {"nonbrowsable", tNONBROWSABLE, 0},
I think that currently threading attribute is used only as widl extension for registration code. It probably predates midl winrt, but it looks like it's mostly compatible. Maybe we should make the extension more compatible with winrt, eg. migrate our code to use 'mta' instead or 'free' (instead of making mta winrt-only)?
The current support was modeled after the C++ attributes:
https://docs.microsoft.com/en-us/cpp/windows/attributes/threading-cpp?view=m...
so it may make sense to keep 'free' as an alias. OTOH we don't seem to be using it in the existing code anyway.
Sure, but even if we keep the alias, it seems right to always expose 'mta' together with threading attribute rather than having it winrt-only.
Jacek
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 7 +++++++ tools/widl/parser.l | 1 + tools/widl/parser.y | 3 +++ tools/widl/widltypes.h | 1 + 4 files changed, 12 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index b6cf43e7228..b13bc1bee79 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1485,6 +1485,7 @@ static char *format_apicontract_macro(const type_t *type) static void write_winrt_type_comments(FILE *header, const type_t *type) { expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); + type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO); fprintf(header, " *\n"); if (contract) { @@ -1494,6 +1495,12 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); free(name); } + if (exclusiveto) + { + char *name = format_namespace(exclusiveto->namespace, "", ".", exclusiveto->name, NULL); + fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); + free(name); + } switch (get_attrv(type->attrs, ATTR_THREADING)) { case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 067966a85d4..de25b7d12c4 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -358,6 +358,7 @@ static const struct keyword attr_keywords[] = {"encode", tENCODE, 0}, {"endpoint", tENDPOINT, 0}, {"entry", tENTRY, 0}, + {"exclusiveto", tEXCLUSIVETO, 1}, {"explicit_handle", tEXPLICITHANDLE, 0}, {"fault_status", tFAULTSTATUS, 0}, {"force_allocate", tFORCEALLOCATE, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 4ce84cc2440..351bbd12107 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -196,6 +196,7 @@ static typelib_t *current_typelib; %token tDLLNAME tDONTFREE tDOUBLE tDUAL %token tENABLEALLOCATE tENCODE tENDPOINT %token tENTRY tENUM tERRORSTATUST +%token tEXCLUSIVETO %token tEXPLICITHANDLE tEXTERN %token tFALSE %token tFASTCALL tFAULTSTATUS @@ -561,6 +562,7 @@ attribute: { $$ = NULL; } | tENCODE { $$ = make_attr(ATTR_ENCODE); } | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } + | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } @@ -2223,6 +2225,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, + /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 6c130d4701e..fbaabfbc8c3 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -103,6 +103,7 @@ enum attr_type ATTR_ENCODE, ATTR_ENDPOINT, ATTR_ENTRY, + ATTR_EXCLUSIVETO, ATTR_EXPLICIT_HANDLE, ATTR_FAULTSTATUS, ATTR_FORCEALLOCATE,
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.media.speechsynthesis.idl | 25 ++ tools/widl/expr.c | 1 + tools/widl/header.c | 61 ++++- tools/widl/parser.l | 1 + tools/widl/parser.y | 269 +++++++++++++--------- tools/widl/typegen.c | 4 + tools/widl/typelib.c | 1 + tools/widl/typetree.c | 17 ++ tools/widl/typetree.h | 24 ++ tools/widl/widltypes.h | 7 + 10 files changed, 296 insertions(+), 114 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 7a1de5fcba6..90bc9f279c6 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -29,6 +29,8 @@ namespace Windows { typedef enum VoiceGender VoiceGender; interface IInstalledVoicesStatic; interface IVoiceInformation; + runtimeclass VoiceInformation; + runtimeclass SpeechSynthesizer; } } } @@ -42,6 +44,29 @@ namespace Windows { Male = 0, Female = 1 }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation), + uuid(b127d6a4-1291-4604-aa9c-83134083352c) + ] + interface IVoiceInformation : IInspectable + { + [propget] HRESULT DisplayName([out] [retval] HSTRING* value); + [propget] HRESULT Id([out] [retval] HSTRING* value); + [propget] HRESULT Language([out] [retval] HSTRING* value); + [propget] HRESULT Description([out] [retval] HSTRING* value); + [propget] HRESULT Gender([out] [retval] VoiceGender* value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass VoiceInformation + { + [default] interface IVoiceInformation; + } } } } diff --git a/tools/widl/expr.c b/tools/widl/expr.c index be8311cfb7f..13bd5a889aa 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -463,6 +463,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_ARRAY: case TYPE_BITFIELD: case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: /* nothing to do */ break; case TYPE_ALIAS: diff --git a/tools/widl/header.c b/tools/widl/header.c index b13bc1bee79..3af83191103 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -465,6 +465,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_RUNTIMECLASS: + fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type)); + break; case TYPE_VOID: fprintf(h, "void"); break; @@ -547,6 +550,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_MODULE: case TYPE_COCLASS: case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: /* not supposed to be here */ @@ -1033,7 +1037,8 @@ static int is_aggregate_return(const var_t *func) { enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type)); return type == TYPE_STRUCT || type == TYPE_UNION || - type == TYPE_COCLASS || type == TYPE_INTERFACE; + type == TYPE_COCLASS || type == TYPE_INTERFACE || + type == TYPE_RUNTIMECLASS; }
static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) @@ -1501,6 +1506,21 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); free(name); } + if (type_get_type(type) == TYPE_RUNTIMECLASS) + { + ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); + ifref_t *entry; + fprintf(header, " * Class implements the following interfaces:\n"); + LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) + { + char *name = format_namespace(entry->iface->namespace, "", ".", entry->iface->name, NULL); + fprintf(header, " * %s", name); + if (is_attr(entry->attrs, ATTR_DEFAULT)) fprintf(header, " ** Default Interface **"); + fprintf(header, "\n"); + free(name); + } + fprintf(header, " *\n"); + } switch (get_attrv(type->attrs, ATTR_THREADING)) { case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; @@ -1728,6 +1748,41 @@ static void write_apicontract(FILE *header, type_t *apicontract) free(name); }
+static void write_runtimeclass(FILE *header, type_t *runtimeclass) +{ + expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT); + size_t i, len; + char *name, *c_name; + name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL); + c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL); + fprintf(header, "/*\n"); + fprintf(header, " * Class %s\n", name); + write_winrt_type_comments(header, runtimeclass); + fprintf(header, " */\n"); + 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, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name); + free(c_name); + free(name); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); +} + +static void write_runtimeclass_forward(FILE *header, type_t *runtimeclass) +{ + fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", runtimeclass->c_name); + fprintf(header, "#define __%s_FWD_DEFINED__\n", runtimeclass->c_name); + fprintf(header, "#ifdef __cplusplus\n"); + write_namespace_start(header, runtimeclass->namespace); + write_line(header, 0, "class %s;", runtimeclass->name); + write_namespace_end(header, runtimeclass->namespace); + fprintf(header, "#else\n"); + fprintf(header, "typedef struct %s %s;\n", runtimeclass->c_name, runtimeclass->c_name); + fprintf(header, "#endif /* defined __cplusplus */\n"); + fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", runtimeclass->c_name); +} + static void write_import(FILE *header, const char *fname) { char *hname, *p; @@ -1792,6 +1847,8 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) } else if (type_get_type(stmt->u.type) == TYPE_COCLASS) write_coclass_forward(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) + write_runtimeclass_forward(header, stmt->u.type); break; case STMT_TYPEREF: case STMT_IMPORTLIB: @@ -1848,6 +1905,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_coclass(header, stmt->u.type); else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT) write_apicontract(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) + write_runtimeclass(header, stmt->u.type); else { write_type_definition(header, stmt->u.type, stmt->declonly); diff --git a/tools/widl/parser.l b/tools/widl/parser.l index de25b7d12c4..80a6bc38afb 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}, + {"runtimeclass", tRUNTIMECLASS, 1}, {"short", tSHORT, 0}, {"signed", tSIGNED, 0}, {"sizeof", tSIZEOF, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 351bbd12107..d12caa06b63 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -100,6 +100,7 @@ static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs); +static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs); const char *get_attr_display_name(enum attr_type type); static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func); @@ -247,6 +248,7 @@ static typelib_t *current_typelib; %token tREQUESTEDIT %token tRESTRICTED %token tRETVAL +%token tRUNTIMECLASS %token tSAFEARRAY %token tSHORT %token tSIGNED tSINGLENODE @@ -292,8 +294,8 @@ static typelib_t *current_typelib; %type <type> base_type int_std %type <type> enumdef structdef uniondef typedecl %type <type> type qualified_seq qualified_type -%type <ifref> coclass_int -%type <ifref_list> coclass_ints +%type <ifref> class_interface +%type <ifref_list> class_interfaces %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 @@ -304,6 +306,7 @@ static typelib_t *current_typelib; %type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator %type <declarator_list> declarator_list struct_declarator_list %type <type> coclass coclasshdr coclassdef +%type <type> runtimeclass runtimeclass_hdr runtimeclass_def %type <type> apicontract %type <num> contract_ver %type <num> pointer_type threading_type marshaling_behavior version @@ -364,6 +367,9 @@ gbl_statements: { $$ = NULL; } } | gbl_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements statement { $$ = append_statement($1, $2); } @@ -380,6 +386,9 @@ imp_statements: { $$ = NULL; } } | imp_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); } + | imp_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | imp_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } | imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | imp_statements statement { $$ = append_statement($1, $2); } | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } @@ -562,7 +571,9 @@ attribute: { $$ = NULL; } | tENCODE { $$ = make_attr(ATTR_ENCODE); } | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } - | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } + | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS) + error_loc("type %s is not a runtimeclass\n", $3->type->name); + $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } @@ -897,10 +908,29 @@ coclasshdr: attributes coclass { $$ = $2; } ;
-coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt +coclassdef: coclasshdr '{' class_interfaces '}' semicolon_opt { $$ = type_coclass_define($1, $3); } ;
+runtimeclass: + tRUNTIMECLASS aIDENTIFIER { $$ = type_new_runtimeclass($2, current_namespace); } + | tRUNTIMECLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); + if (type_get_type_detect_alias($$) != TYPE_RUNTIMECLASS) + error_loc("%s was not declared a runtimeclass at %s:%d\n", $2, + $$->loc_info.input_name, $$->loc_info.line_number); + } + ; + +runtimeclass_hdr: attributes runtimeclass { $$ = $2; + check_def($$); + $$->attrs = check_runtimeclass_attrs($2->name, $1); + } + ; + +runtimeclass_def: runtimeclass_hdr '{' class_interfaces '}' semicolon_opt + { $$ = type_runtimeclass_define($1, $3); } + ; + apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}' { $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0); check_def($$); @@ -912,11 +942,11 @@ namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } | tNAMESPACE aNAMESPACE { $$ = $2; } ;
-coclass_ints: { $$ = NULL; } - | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); } +class_interfaces: { $$ = NULL; } + | class_interfaces class_interface { $$ = append_ifref( $1, $2 ); } ;
-coclass_int: +class_interface: m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } ;
@@ -2185,117 +2215,118 @@ struct allowed_attr unsigned int on_module : 1; unsigned int on_coclass : 1; unsigned int on_apicontract : 1; + unsigned int on_runtimeclass : 1; const char *display_name; };
struct allowed_attr allowed_attr[] = { - /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC <display name> } */ - /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" }, - /* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 0, 1, 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, "annotation" }, - /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "appobject" }, - /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, - /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" }, - /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, - /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, - /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, - /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, - /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, - /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "case" }, - /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, - /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, - /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, - /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" }, - /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" }, - /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" }, - /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "custom" }, - /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, - /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" }, - /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, - /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, - /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, - /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "defaultvtable" }, - /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, - /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, - /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, - /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "dllname" }, - /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, - /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, - /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, - /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, - /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, - /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, - /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, - /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, - /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, - /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, - /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" }, - /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" }, - /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" }, - /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" }, - /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" }, - /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" }, - /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" }, - /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, - /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ignore" }, - /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" }, - /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, - /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, - /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, - /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, - /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" }, - /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, - /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, - /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, - /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" }, - /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, - /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, - /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, - /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, - /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "noncreatable" }, - /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, - /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, - /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, - /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, - /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" }, - /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, - /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, - /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, - /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, - /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, - /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, - /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, - /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ref, unique or ptr" }, - /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "progid" }, - /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, - /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, - /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, - /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, - /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, - /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" }, - /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" }, - /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, - /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, - /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" }, - /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 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, "size_is" }, - /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" }, - /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 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, "string" }, - /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" }, - /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" }, - /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" }, - /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, - /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, - /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, - /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, - /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" }, - /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, - /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, - /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" }, - /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" }, - /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, + /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */ + /* 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" }, + /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, + /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, + /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" }, + /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, + /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, + /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, + /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, + /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" }, + /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, + /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" }, + /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" }, + /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "custom" }, + /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, + /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" }, + /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, + /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, + /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, + /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" }, + /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, + /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, + /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" }, + /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, + /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, + /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, + /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, + /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, + /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, + /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, + /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, + /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, + /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" }, + /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" }, + /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" }, + /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" }, + /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" }, + /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" }, + /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, + /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" }, + /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" }, + /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, + /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, + /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, + /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, + /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" }, + /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" }, + /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" }, + /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, + /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" }, + /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, + /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, + /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, + /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, + /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" }, + /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, + /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, + /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, + /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, + /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" }, + /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, + /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, + /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, + /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, + /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, + /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, + /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, + /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" }, + /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" }, + /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, + /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, + /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, + /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, + /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, + /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" }, + /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" }, + /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, + /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, + /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" }, + /* 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_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" }, + /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" }, + /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" }, + /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, + /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, + /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, + /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, + /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" }, + /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, + /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, + /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" }, + /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" }, + /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, };
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) @@ -2510,6 +2541,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs) return attrs; }
+static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs) +{ + const attr_t *attr; + if (!attrs) return attrs; + LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) + if (!allowed_attr[attr->type].on_runtimeclass) + error_loc("inapplicable attribute %s for runtimeclass %s\n", + allowed_attr[attr->type].display_name, name); + return attrs; +} + static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs) { const attr_t *attr; @@ -2559,6 +2601,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_FUNCTION: case TYPE_INTERFACE: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: return FALSE; case TYPE_APICONTRACT: /* not supposed to be here */ diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 5d0f24be06f..2e9be0748c1 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -353,6 +353,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att return TGT_ENUM; 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_RUNTIMECLASS || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) return TGT_IFACE_POINTER; else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) @@ -373,6 +374,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_VOID: case TYPE_ALIAS: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: /* not supposed to be here */ @@ -1971,6 +1973,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_FUNCTION: case TYPE_BITFIELD: case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: /* 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 @@ -2073,6 +2076,7 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_FUNCTION: case TYPE_BITFIELD: case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: /* 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 faf76440f93..ace6424e3a0 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -218,6 +218,7 @@ unsigned short get_type_vt(type_t *t) case TYPE_MODULE: case TYPE_UNION: case TYPE_ENCAPSULATED_UNION: + case TYPE_RUNTIMECLASS: return VT_USERDEFINED;
case TYPE_VOID: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index df883576915..107a2d36a2f 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -215,6 +215,16 @@ type_t *type_new_coclass(char *name) return type; }
+type_t *type_new_runtimeclass(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_RUNTIMECLASS, name, NULL, 0); + if (type->type_type != TYPE_RUNTIMECLASS || type->defined) + error_loc("%s: redefinition error; original definition was at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->name = name; + type->namespace = namespace; + return type; +}
type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, unsigned int dim, expr_t *size_is, expr_t *length_is) @@ -509,6 +519,13 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces) return coclass; }
+type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces) +{ + runtimeclass->details.runtimeclass.ifaces = ifaces; + runtimeclass->defined = TRUE; + return runtimeclass; +} + 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 7abec41a8fd..951084cf875 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -44,11 +44,13 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields); type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); +type_t *type_new_runtimeclass(char *name, struct namespace *namespace); void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts); void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); void type_module_define(type_t *module, statement_list_t *stmts); type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces); +type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces); 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); @@ -222,6 +224,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_POINTER: case TYPE_ARRAY: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: return TRUE; case TYPE_APICONTRACT: assert(0); @@ -322,6 +325,27 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) return type->details.coclass.ifaces; }
+static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_RUNTIMECLASS); + return type->details.runtimeclass.ifaces; +} + +static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) +{ + ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); + ifref_t *entry; + attr_t *attr; + + LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) + LIST_FOR_EACH_ENTRY(attr, entry->attrs, attr_t, entry) + if (attr->type == ATTR_DEFAULT) return entry->iface; + + assert(0); + return NULL; +} + static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index fbaabfbc8c3..46a44dac039 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -425,6 +425,11 @@ struct alias_details struct _decl_spec_t aliasee; };
+struct runtimeclass_details +{ + ifref_list_t *ifaces; +}; + #define HASHMAX 64
struct namespace { @@ -452,6 +457,7 @@ enum type_type TYPE_ARRAY, TYPE_BITFIELD, TYPE_APICONTRACT, + TYPE_RUNTIMECLASS, };
struct _type_t { @@ -472,6 +478,7 @@ struct _type_t { struct pointer_details pointer; struct bitfield_details bitfield; struct alias_details alias; + struct runtimeclass_details runtimeclass; } details; const char *c_name; unsigned int typestring_offset;
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
include/windows.media.speechsynthesis.idl | 25 ++ tools/widl/expr.c | 1 + tools/widl/header.c | 61 ++++- tools/widl/parser.l | 1 + tools/widl/parser.y | 269 +++++++++++++--------- tools/widl/typegen.c | 4 + tools/widl/typelib.c | 1 + tools/widl/typetree.c | 17 ++ tools/widl/typetree.h | 24 ++ tools/widl/widltypes.h | 7 + 10 files changed, 296 insertions(+), 114 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 7a1de5fcba6..90bc9f279c6 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -29,6 +29,8 @@ namespace Windows { typedef enum VoiceGender VoiceGender; interface IInstalledVoicesStatic; interface IVoiceInformation;
runtimeclass VoiceInformation;
}runtimeclass SpeechSynthesizer; }
} @@ -42,6 +44,29 @@ namespace Windows { Male = 0, Female = 1 };
[
contract(Windows.Foundation.UniversalApiContract, 1.0),
exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation),
uuid(b127d6a4-1291-4604-aa9c-83134083352c)
]
interface IVoiceInformation : IInspectable
{
[propget] HRESULT DisplayName([out] [retval] HSTRING* value);
[propget] HRESULT Id([out] [retval] HSTRING* value);
[propget] HRESULT Language([out] [retval] HSTRING* value);
[propget] HRESULT Description([out] [retval] HSTRING* value);
[propget] HRESULT Gender([out] [retval] VoiceGender* value);
}
[
contract(Windows.Foundation.UniversalApiContract, 1.0),
marshaling_behavior(agile)
]
runtimeclass VoiceInformation
{
[default] interface IVoiceInformation;
}} }
}
Does this need to be part of this patch?
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index be8311cfb7f..13bd5a889aa 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -463,6 +463,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_ARRAY: case TYPE_BITFIELD: case TYPE_APICONTRACT:
case TYPE_RUNTIMECLASS: /* nothing to do */ break; case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c index b13bc1bee79..3af83191103 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -465,6 +465,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_RUNTIMECLASS:
fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type));
break; case TYPE_VOID: fprintf(h, "void"); break;
@@ -547,6 +550,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_MODULE: case TYPE_COCLASS: case TYPE_INTERFACE:
- case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: /* not supposed to be here */
@@ -1033,7 +1037,8 @@ static int is_aggregate_return(const var_t *func) { enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type)); return type == TYPE_STRUCT || type == TYPE_UNION ||
type == TYPE_COCLASS || type == TYPE_INTERFACE;
type == TYPE_COCLASS || type == TYPE_INTERFACE ||
type == TYPE_RUNTIMECLASS;
}
static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) @@ -1501,6 +1506,21 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); free(name); }
- if (type_get_type(type) == TYPE_RUNTIMECLASS)
- {
ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type);
ifref_t *entry;
fprintf(header, " * Class implements the following interfaces:\n");
LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry)
{
char *name = format_namespace(entry->iface->namespace, "", ".", entry->iface->name, NULL);
fprintf(header, " * %s", name);
if (is_attr(entry->attrs, ATTR_DEFAULT)) fprintf(header, " ** Default Interface **");
fprintf(header, "\n");
free(name);
}
fprintf(header, " *\n");
- } switch (get_attrv(type->attrs, ATTR_THREADING)) { case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break;
@@ -1728,6 +1748,41 @@ static void write_apicontract(FILE *header, type_t *apicontract) free(name); }
+static void write_runtimeclass(FILE *header, type_t *runtimeclass) +{
- expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT);
- size_t i, len;
- char *name, *c_name;
- name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL);
- c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL);
- fprintf(header, "/*\n");
- fprintf(header, " * Class %s\n", name);
- write_winrt_type_comments(header, runtimeclass);
- fprintf(header, " */\n");
- 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, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name);
- free(c_name);
- free(name);
- if (contract) write_apicontract_guard_end(header, contract);
- fprintf(header, "\n");
+}
+static void write_runtimeclass_forward(FILE *header, type_t *runtimeclass) +{
- fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", runtimeclass->c_name);
- fprintf(header, "#define __%s_FWD_DEFINED__\n", runtimeclass->c_name);
- fprintf(header, "#ifdef __cplusplus\n");
- write_namespace_start(header, runtimeclass->namespace);
- write_line(header, 0, "class %s;", runtimeclass->name);
- write_namespace_end(header, runtimeclass->namespace);
- fprintf(header, "#else\n");
- fprintf(header, "typedef struct %s %s;\n", runtimeclass->c_name, runtimeclass->c_name);
- fprintf(header, "#endif /* defined __cplusplus */\n");
- fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", runtimeclass->c_name);
+}
static void write_import(FILE *header, const char *fname) { char *hname, *p; @@ -1792,6 +1847,8 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) } else if (type_get_type(stmt->u.type) == TYPE_COCLASS) write_coclass_forward(header, stmt->u.type);
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
write_runtimeclass_forward(header, stmt->u.type); break; case STMT_TYPEREF: case STMT_IMPORTLIB:
@@ -1848,6 +1905,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_coclass(header, stmt->u.type); else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT) write_apicontract(header, stmt->u.type);
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
write_runtimeclass(header, stmt->u.type); else { write_type_definition(header, stmt->u.type, stmt->declonly);
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index de25b7d12c4..80a6bc38afb 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},
- {"runtimeclass", tRUNTIMECLASS, 1}, {"short", tSHORT, 0}, {"signed", tSIGNED, 0}, {"sizeof", tSIZEOF, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 351bbd12107..d12caa06b63 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -100,6 +100,7 @@ static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs); +static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs); const char *get_attr_display_name(enum attr_type type); static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func); @@ -247,6 +248,7 @@ static typelib_t *current_typelib; %token tREQUESTEDIT %token tRESTRICTED %token tRETVAL +%token tRUNTIMECLASS %token tSAFEARRAY %token tSHORT %token tSIGNED tSINGLENODE @@ -292,8 +294,8 @@ static typelib_t *current_typelib; %type <type> base_type int_std %type <type> enumdef structdef uniondef typedecl %type <type> type qualified_seq qualified_type -%type <ifref> coclass_int -%type <ifref_list> coclass_ints +%type <ifref> class_interface +%type <ifref_list> class_interfaces %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 @@ -304,6 +306,7 @@ static typelib_t *current_typelib; %type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator %type <declarator_list> declarator_list struct_declarator_list %type <type> coclass coclasshdr coclassdef +%type <type> runtimeclass runtimeclass_hdr runtimeclass_def %type <type> apicontract %type <num> contract_ver %type <num> pointer_type threading_type marshaling_behavior version @@ -364,6 +367,9 @@ gbl_statements: { $$ = NULL; } } | gbl_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); }
- | gbl_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); }
- | gbl_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2));
| gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements statement { $$ = append_statement($1, $2); }reg_type($2, $2->name, current_namespace, 0); }
@@ -380,6 +386,9 @@ imp_statements: { $$ = NULL; } } | imp_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); }
- | imp_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); }
- | imp_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2));
| imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | imp_statements statement { $$ = append_statement($1, $2); } | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); }reg_type($2, $2->name, current_namespace, 0); }
@@ -562,7 +571,9 @@ attribute: { $$ = NULL; } | tENCODE { $$ = make_attr(ATTR_ENCODE); } | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); }
- | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
- | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS)
error_loc("type %s is not a runtimeclass\n", $3->type->name);
| tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); }$$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
@@ -897,10 +908,29 @@ coclasshdr: attributes coclass { $$ = $2; } ;
-coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt +coclassdef: coclasshdr '{' class_interfaces '}' semicolon_opt { $$ = type_coclass_define($1, $3); } ;
+runtimeclass:
tRUNTIMECLASS aIDENTIFIER { $$ = type_new_runtimeclass($2, current_namespace); }
- | tRUNTIMECLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
if (type_get_type_detect_alias($$) != TYPE_RUNTIMECLASS)
error_loc("%s was not declared a runtimeclass at %s:%d\n", $2,
$$->loc_info.input_name, $$->loc_info.line_number);
}
- ;
+runtimeclass_hdr: attributes runtimeclass { $$ = $2;
check_def($$);
$$->attrs = check_runtimeclass_attrs($2->name, $1);
}
- ;
+runtimeclass_def: runtimeclass_hdr '{' class_interfaces '}' semicolon_opt
{ $$ = type_runtimeclass_define($1, $3); }
- ;
apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}' { $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0); check_def($$); @@ -912,11 +942,11 @@ namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } | tNAMESPACE aNAMESPACE { $$ = $2; } ;
-coclass_ints: { $$ = NULL; }
- | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); }
+class_interfaces: { $$ = NULL; }
- | class_interfaces class_interface { $$ = append_ifref( $1, $2 ); } ;
-coclass_int: +class_interface: m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } ;
@@ -2185,117 +2215,118 @@ struct allowed_attr unsigned int on_module : 1; unsigned int on_coclass : 1; unsigned int on_apicontract : 1;
- unsigned int on_runtimeclass : 1; const char *display_name;
};
struct allowed_attr allowed_attr[] = {
- /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC <display name> } */
- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" },
- /* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 0, 1, 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, "annotation" },
- /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "appobject" },
- /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
- /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" },
- /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" },
- /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" },
- /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" },
- /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" },
- /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
- /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "case" },
- /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
- /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
- /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" },
- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" },
- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" },
- /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "custom" },
- /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
- /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" },
- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" },
- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" },
- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" },
- /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "defaultvtable" },
- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" },
- /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" },
- /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "dllname" },
- /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" },
- /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" },
- /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" },
- /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" },
- /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
- /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" },
- /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" },
- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" },
- /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
- /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" },
- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" },
- /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" },
- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" },
- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" },
- /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" },
- /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" },
- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" },
- /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ignore" },
- /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" },
- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
- /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
- /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
- /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" },
- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" },
- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" },
- /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" },
- /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" },
- /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" },
- /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" },
- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" },
- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "noncreatable" },
- /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" },
- /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" },
- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" },
- /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" },
- /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" },
- /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" },
- /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" },
- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" },
- /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" },
- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" },
- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" },
- /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ref, unique or ptr" },
- /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "progid" },
- /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" },
- /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" },
- /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" },
- /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" },
- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
- /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" },
- /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" },
- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" },
- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" },
- /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" },
- /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 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, "size_is" },
- /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" },
- /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 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, "string" },
- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" },
- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" },
- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" },
- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" },
- /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" },
- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" },
- /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" },
- /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" },
- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" },
- /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" },
- /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" },
- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" },
- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
- /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
- /* 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" },
- /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" },
- /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
- /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" },
- /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" },
- /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" },
- /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" },
- /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" },
- /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
- /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" },
- /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
- /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
- /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" },
- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" },
- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" },
- /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "custom" },
- /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
- /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" },
- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" },
- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" },
- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" },
- /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" },
- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" },
- /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" },
- /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" },
- /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" },
- /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" },
- /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" },
- /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" },
- /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
- /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" },
- /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" },
- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" },
- /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
- /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" },
- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" },
- /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" },
- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" },
- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" },
- /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" },
- /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" },
- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" },
- /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" },
- /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" },
- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
- /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
- /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
- /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" },
- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" },
- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" },
- /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" },
- /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" },
- /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" },
- /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" },
- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" },
- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" },
- /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" },
- /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" },
- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" },
- /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" },
- /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" },
- /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" },
- /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" },
- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" },
- /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" },
- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" },
- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" },
- /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" },
- /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" },
- /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" },
- /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" },
- /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" },
- /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" },
- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
- /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" },
- /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" },
- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" },
- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" },
- /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" },
- /* 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_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" },
- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" },
- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" },
- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" },
- /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" },
- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" },
- /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" },
- /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" },
- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" },
- /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" },
- /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" },
- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" },
- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
};
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) @@ -2510,6 +2541,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs) return attrs; }
+static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs) +{
- const attr_t *attr;
- if (!attrs) return attrs;
- LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
if (!allowed_attr[attr->type].on_runtimeclass)
error_loc("inapplicable attribute %s for runtimeclass %s\n",
allowed_attr[attr->type].display_name, name);
- return attrs;
+}
static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs) { const attr_t *attr; @@ -2559,6 +2601,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_FUNCTION: case TYPE_INTERFACE: case TYPE_BITFIELD:
- case TYPE_RUNTIMECLASS: return FALSE; case TYPE_APICONTRACT: /* not supposed to be here */
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 5d0f24be06f..2e9be0748c1 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -353,6 +353,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att return TGT_ENUM; 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_RUNTIMECLASS || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) return TGT_IFACE_POINTER; else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE))
@@ -373,6 +374,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_VOID: case TYPE_ALIAS: case TYPE_BITFIELD:
- case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: /* not supposed to be here */
@@ -1971,6 +1973,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_FUNCTION: case TYPE_BITFIELD: case TYPE_APICONTRACT:
- case TYPE_RUNTIMECLASS: /* 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
@@ -2073,6 +2076,7 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_FUNCTION: case TYPE_BITFIELD: case TYPE_APICONTRACT:
- case TYPE_RUNTIMECLASS: /* 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 faf76440f93..ace6424e3a0 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -218,6 +218,7 @@ unsigned short get_type_vt(type_t *t) case TYPE_MODULE: case TYPE_UNION: case TYPE_ENCAPSULATED_UNION:
case TYPE_RUNTIMECLASS: return VT_USERDEFINED;
case TYPE_VOID:
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index df883576915..107a2d36a2f 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -215,6 +215,16 @@ type_t *type_new_coclass(char *name) return type; }
+type_t *type_new_runtimeclass(char *name, struct namespace *namespace) +{
- type_t *type = get_type(TYPE_RUNTIMECLASS, name, NULL, 0);
- if (type->type_type != TYPE_RUNTIMECLASS || type->defined)
error_loc("%s: redefinition error; original definition was at %s:%d\n",
type->name, type->loc_info.input_name, type->loc_info.line_number);
- type->name = name;
- type->namespace = namespace;
- return type;
+}
type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, unsigned int dim, expr_t *size_is, expr_t *length_is) @@ -509,6 +519,13 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces) return coclass; }
+type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces) +{
- runtimeclass->details.runtimeclass.ifaces = ifaces;
- runtimeclass->defined = TRUE;
- return runtimeclass;
+}
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 7abec41a8fd..951084cf875 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -44,11 +44,13 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields); type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); +type_t *type_new_runtimeclass(char *name, struct namespace *namespace); void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts); void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); void type_module_define(type_t *module, statement_list_t *stmts); type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces); +type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces); 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); @@ -222,6 +224,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_POINTER: case TYPE_ARRAY: case TYPE_BITFIELD:
- case TYPE_RUNTIMECLASS: return TRUE; case TYPE_APICONTRACT: assert(0);
@@ -322,6 +325,27 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) return type->details.coclass.ifaces; }
+static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type) +{
- type = type_get_real_type(type);
- assert(type_get_type(type) == TYPE_RUNTIMECLASS);
- return type->details.runtimeclass.ifaces;
+}
+static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) +{
- ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type);
- ifref_t *entry;
- attr_t *attr;
- LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry)
LIST_FOR_EACH_ENTRY(attr, entry->attrs, attr_t, entry)
if (attr->type == ATTR_DEFAULT) return entry->iface;
- assert(0);
- return NULL;
+}
static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index fbaabfbc8c3..46a44dac039 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -425,6 +425,11 @@ struct alias_details struct _decl_spec_t aliasee; };
+struct runtimeclass_details +{
- ifref_list_t *ifaces;
+};
#define HASHMAX 64
struct namespace { @@ -452,6 +457,7 @@ enum type_type TYPE_ARRAY, TYPE_BITFIELD, TYPE_APICONTRACT,
- TYPE_RUNTIMECLASS,
};
struct _type_t { @@ -472,6 +478,7 @@ struct _type_t { struct pointer_details pointer; struct bitfield_details bitfield; struct alias_details alias;
- struct runtimeclass_details runtimeclass; } details; const char *c_name; unsigned int typestring_offset;
On 1/19/21 6:32 PM, Zebediah Figura (she/her) wrote:
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
include/windows.media.speechsynthesis.idl | 25 ++ tools/widl/expr.c | 1 + tools/widl/header.c | 61 ++++- tools/widl/parser.l | 1 + tools/widl/parser.y | 269 +++++++++++++--------- tools/widl/typegen.c | 4 + tools/widl/typelib.c | 1 + tools/widl/typetree.c | 17 ++ tools/widl/typetree.h | 24 ++ tools/widl/widltypes.h | 7 + 10 files changed, 296 insertions(+), 114 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 7a1de5fcba6..90bc9f279c6 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -29,6 +29,8 @@ namespace Windows { typedef enum VoiceGender VoiceGender; interface IInstalledVoicesStatic; interface IVoiceInformation;
runtimeclass VoiceInformation;
}runtimeclass SpeechSynthesizer; } }
@@ -42,6 +44,29 @@ namespace Windows { Male = 0, Female = 1 };
[
contract(Windows.Foundation.UniversalApiContract, 1.0),
exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation),
uuid(b127d6a4-1291-4604-aa9c-83134083352c)
]
interface IVoiceInformation : IInspectable
{
[propget] HRESULT DisplayName([out] [retval] HSTRING* value);
[propget] HRESULT Id([out] [retval] HSTRING* value);
[propget] HRESULT Language([out] [retval] HSTRING* value);
[propget] HRESULT Description([out] [retval] HSTRING* value);
[propget] HRESULT Gender([out] [retval] VoiceGender* value);
}
[
contract(Windows.Foundation.UniversalApiContract, 1.0),
marshaling_behavior(agile)
]
runtimeclass VoiceInformation
{
[default] interface IVoiceInformation;
}} } }
Does this need to be part of this patch?
Not necessarily part of it, do you mean move it to a separate patch?
It's there to illustrate the new features the widl changes enable, and make sure widl can parse and generate a proper header. Also it makes it possible to diff the generated headers on every widl change.
With that in mind I agree that it'd perhaps be better to move the new attributes parsing support after runtimeclass can be parsed, adding them to the idl iteratively, but I didn't want to add the runtimeclass without the attributes it's supposed to have.
On 1/19/21 11:39 AM, Rémi Bernon wrote:
On 1/19/21 6:32 PM, Zebediah Figura (she/her) wrote:
On 1/19/21 7:04 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
include/windows.media.speechsynthesis.idl | 25 ++ tools/widl/expr.c | 1 + tools/widl/header.c | 61 ++++- tools/widl/parser.l | 1 + tools/widl/parser.y | 269 +++++++++++++--------- tools/widl/typegen.c | 4 + tools/widl/typelib.c | 1 + tools/widl/typetree.c | 17 ++ tools/widl/typetree.h | 24 ++ tools/widl/widltypes.h | 7 + 10 files changed, 296 insertions(+), 114 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 7a1de5fcba6..90bc9f279c6 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -29,6 +29,8 @@ namespace Windows { typedef enum VoiceGender VoiceGender; interface IInstalledVoicesStatic; interface IVoiceInformation; + runtimeclass VoiceInformation; + runtimeclass SpeechSynthesizer; } } } @@ -42,6 +44,29 @@ namespace Windows { Male = 0, Female = 1 };
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation), + uuid(b127d6a4-1291-4604-aa9c-83134083352c) + ] + interface IVoiceInformation : IInspectable + { + [propget] HRESULT DisplayName([out] [retval] HSTRING* value); + [propget] HRESULT Id([out] [retval] HSTRING* value); + [propget] HRESULT Language([out] [retval] HSTRING* value); + [propget] HRESULT Description([out] [retval] HSTRING* value); + [propget] HRESULT Gender([out] [retval] VoiceGender* value); + }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass VoiceInformation + { + [default] interface IVoiceInformation; + } } } }
Does this need to be part of this patch?
Not necessarily part of it, do you mean move it to a separate patch?
It's there to illustrate the new features the widl changes enable, and make sure widl can parse and generate a proper header. Also it makes it possible to diff the generated headers on every widl change.
With that in mind I agree that it'd perhaps be better to move the new attributes parsing support after runtimeclass can be parsed, adding them to the idl iteratively, but I didn't want to add the runtimeclass without the attributes it's supposed to have.
I guess it seems to me that the IDL would demonstrate it just as well in a separate patch. Granted, it's nitpicking anyway.