Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This makes the following kind of changes to the generated header files, according to the contract and version specified on each type:
--- a/windows.foundation.h +++ b/windows.foundation.h @@ -35,11 +35,13 @@ namespace ABI { /* Headers for imported files */
#include <inspectable.h> +#include <windowscontracts.h>
#ifdef __cplusplus extern "C" { #endif
+#if WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION >= 0x10000 #ifdef __cplusplus } /* extern "C" */ namespace ABI { @@ -138,6 +140,8 @@ enum __x_ABI_CWindows_CFoundation_CPropertyType { }; #endif
+#endif /* WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION >= 0x10000 */ +#if WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION >= 0x10000 #ifdef __cplusplus } /* extern "C" */ namespace ABI {
include/windows.foundation.idl | 14 +++---- tools/widl/header.c | 72 ++++++++++++++++++++++++++++++++-- tools/widl/parser.l | 1 + tools/widl/parser.y | 10 +++++ tools/widl/widltypes.h | 1 + 5 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 2a38e9f671b..5e17062f399 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -28,7 +28,7 @@ import "windowscontracts.idl";
namespace Windows { namespace Foundation { - [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] enum PropertyType { Empty = 0, UInt8 = 1, @@ -73,19 +73,19 @@ namespace Windows { OtherTypeArray = 1044 };
- [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] struct Point { FLOAT X; FLOAT Y; };
- [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] struct Size { FLOAT Width; FLOAT Height; };
- [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] struct Rect { FLOAT X; FLOAT Y; @@ -93,18 +93,18 @@ namespace Windows { FLOAT Height; };
- [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] struct DateTime { INT64 UniversalTime; };
- [version(0x06020000)] + [contract(Windows.Foundation.FoundationContract, 1.0)] struct TimeSpan { INT64 Duration; };
[ - version(0x06030000), + contract(Windows.Foundation.FoundationContract, 1.0), uuid(96369f54-8eb6-48f0-abce-c1b211e627c3) ] interface IStringable : IInspectable diff --git a/tools/widl/header.c b/tools/widl/header.c index 657ce50c679..223ab5c5ca9 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -45,6 +45,11 @@ generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name, enum name_type name_type);
+static void write_winrt_type_comments(FILE *header, const type_t *type); + +static void write_apicontract_guard_start(FILE *header, const expr_t *expr); +static void write_apicontract_guard_end(FILE *header, const expr_t *expr); + static void indent(FILE *h, int delta) { int c; @@ -218,7 +223,9 @@ static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) }
LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { + expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); if (!v || !v->declspec.type) continue; + if (contract) write_apicontract_guard_start(h, contract);
indent(h, 0); name = v->name; @@ -252,6 +259,7 @@ static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) } write_type_v(h, &v->declspec, TRUE, v->declonly, name, name_type); fprintf(h, ";\n"); + if (contract) write_apicontract_guard_end(h, contract); } }
@@ -261,6 +269,8 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) if (!enums) return; LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) { + expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); + if (contract) write_apicontract_guard_start(h, contract); if (v->name) { indent(h, 0); if(!enum_name) @@ -273,8 +283,9 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) } } if (list_next( enums, &v->entry )) fprintf(h, ",\n"); + else fprintf(h, "\n"); + if (contract) write_apicontract_guard_end(h, contract); } - fprintf(h, "\n"); }
int needs_space_after(type_t *t) @@ -563,7 +574,9 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) int in_namespace = t->namespace && !is_global_namespace(t->namespace); int save_written = t->written; decl_spec_t ds = {.type = t}; + expr_t *contract = get_attrp(t->attrs, ATTR_CONTRACT);
+ if (contract) write_apicontract_guard_start(f, contract); if(in_namespace) { fprintf(f, "#ifdef __cplusplus\n"); fprintf(f, "} /* extern "C" */\n"); @@ -581,6 +594,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) fprintf(f, ";\n"); fprintf(f, "#endif\n\n"); } + if (contract) write_apicontract_guard_end(f, contract); }
void write_type_decl(FILE *f, const decl_spec_t *t, const char *name) @@ -1468,12 +1482,55 @@ static char *format_apicontract_macro(const type_t *type) return name; }
+static void write_winrt_type_comments(FILE *header, const type_t *type) +{ + expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); + fprintf(header, " *\n"); + if (contract) + { + const type_t *type = contract->u.tref.type; + char *name = format_namespace(type->namespace, "", ".", type->name, NULL); + int ver = contract->ref->u.lval; + fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); + free(name); + } +} + +static void write_apicontract_guard_start(FILE *header, const expr_t *expr) +{ + const type_t *type; + char *name; + int ver; + if (!winrt_mode) return; + type = expr->u.tref.type; + ver = expr->ref->u.lval; + name = format_apicontract_macro(type); + fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); + free(name); +} + +static void write_apicontract_guard_end(FILE *header, const expr_t *expr) +{ + const type_t *type; + char *name; + int ver; + if (!winrt_mode) return; + type = expr->u.tref.type; + ver = expr->ref->u.lval; + name = format_apicontract_macro(type); + fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); + free(name); +} + static void write_com_interface_start(FILE *header, const type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); + if (winrt_mode) write_winrt_type_comments(header, iface); fprintf(header, " */\n"); + if (contract) write_apicontract_guard_start(header, contract); fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : ""); fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); } @@ -1482,6 +1539,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); type_t *type;
if (uuid) @@ -1559,17 +1617,22 @@ static void write_com_interface_end(FILE *header, type_t *iface) write_locals(header, iface, FALSE); fprintf(header, "\n"); } - fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->c_name, dispinterface ? "DISP" : ""); + fprintf(header, "#endif /* __%s_%sINTERFACE_DEFINED__ */\n", iface->c_name, dispinterface ? "DISP" : ""); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); }
static void write_rpc_interface_start(FILE *header, const type_t *iface) { unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + if (winrt_mode) write_winrt_type_comments(header, iface); fprintf(header, " */\n"); + if (contract) write_apicontract_guard_start(header, contract); fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); if (var) @@ -1594,7 +1657,10 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface)
static void write_rpc_interface_end(FILE *header, const type_t *iface) { - fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); + fprintf(header, "\n#endif /* __%s_INTERFACE_DEFINED__ */\n", iface->name); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); }
static void write_coclass(FILE *header, type_t *cocl) diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 6a9bb65a483..9dce03577c6 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -339,6 +339,7 @@ static const struct keyword attr_keywords[] = {"context_handle", tCONTEXTHANDLE, 0}, {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0}, {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0}, + {"contract", tCONTRACT, 1}, {"contractversion", tCONTRACTVERSION, 1}, {"control", tCONTROL, 0}, {"custom", tCUSTOM, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 5b4bd518a0b..1d413ca74f4 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -181,6 +181,7 @@ static typelib_t *current_typelib; %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE %token tCONTEXTHANDLESERIALIZE +%token tCONTRACT %token tCONTRACTVERSION %token tCONTROL tCPPQUOTE %token tCUSTOM @@ -271,6 +272,7 @@ static typelib_t *current_typelib; %type <str_list> str_list %type <expr> m_expr expr expr_const expr_int_const array m_bitfield %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const +%type <expr> contract_req %type <type> interfacehdr %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list @@ -508,6 +510,12 @@ contract_ver: | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } ;
+contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICONTRACT) + error_loc("type %s is not an apicontract\n", $1->type->name); + $$ = make_exprl(EXPR_NUM, $3); + $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); + } + attribute: { $$ = NULL; } | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } @@ -523,6 +531,7 @@ attribute: { $$ = NULL; } | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } + | tCONTRACT '(' contract_req ')' { $$ = make_attrp(ATTR_CONTRACT, $3); } | tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); } | tCONTROL { $$ = make_attr(ATTR_CONTROL); } | tCUSTOM '(' uuid_string ',' expr_const ')' { $$ = make_custom_attr($3, $5); } @@ -2180,6 +2189,7 @@ struct allowed_attr allowed_attr[] = /* 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" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 878650d9c27..d5862426ad4 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -84,6 +84,7 @@ enum attr_type ATTR_CODE, ATTR_COMMSTATUS, ATTR_CONTEXTHANDLE, + ATTR_CONTRACT, ATTR_CONTRACTVERSION, ATTR_CONTROL, ATTR_CUSTOM,