Commit 54035a21 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

widl: Support WinRT contract attribute.

parent ee490ee2
...@@ -28,7 +28,7 @@ import "windowscontracts.idl"; ...@@ -28,7 +28,7 @@ import "windowscontracts.idl";
namespace Windows { namespace Windows {
namespace Foundation { namespace Foundation {
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
enum PropertyType { enum PropertyType {
Empty = 0, Empty = 0,
UInt8 = 1, UInt8 = 1,
...@@ -73,19 +73,19 @@ namespace Windows { ...@@ -73,19 +73,19 @@ namespace Windows {
OtherTypeArray = 1044 OtherTypeArray = 1044
}; };
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Point { struct Point {
FLOAT X; FLOAT X;
FLOAT Y; FLOAT Y;
}; };
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Size { struct Size {
FLOAT Width; FLOAT Width;
FLOAT Height; FLOAT Height;
}; };
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Rect { struct Rect {
FLOAT X; FLOAT X;
FLOAT Y; FLOAT Y;
...@@ -93,18 +93,18 @@ namespace Windows { ...@@ -93,18 +93,18 @@ namespace Windows {
FLOAT Height; FLOAT Height;
}; };
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
struct DateTime { struct DateTime {
INT64 UniversalTime; INT64 UniversalTime;
}; };
[version(0x06020000)] [contract(Windows.Foundation.FoundationContract, 1.0)]
struct TimeSpan { struct TimeSpan {
INT64 Duration; INT64 Duration;
}; };
[ [
version(0x06030000), contract(Windows.Foundation.FoundationContract, 1.0),
uuid(96369f54-8eb6-48f0-abce-c1b211e627c3) uuid(96369f54-8eb6-48f0-abce-c1b211e627c3)
] ]
interface IStringable : IInspectable interface IStringable : IInspectable
......
...@@ -45,6 +45,11 @@ generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list); ...@@ -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_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) static void indent(FILE *h, int delta)
{ {
int c; int c;
...@@ -218,7 +223,9 @@ static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) ...@@ -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 ) { 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 (!v || !v->declspec.type) continue;
if (contract) write_apicontract_guard_start(h, contract);
indent(h, 0); indent(h, 0);
name = v->name; name = v->name;
...@@ -252,6 +259,7 @@ static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) ...@@ -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); write_type_v(h, &v->declspec, TRUE, v->declonly, name, name_type);
fprintf(h, ";\n"); 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) ...@@ -261,6 +269,8 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name)
if (!enums) return; if (!enums) return;
LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) 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) { if (v->name) {
indent(h, 0); indent(h, 0);
if(!enum_name) if(!enum_name)
...@@ -273,8 +283,9 @@ static void write_enums(FILE *h, var_list_t *enums, const char *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"); 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) int needs_space_after(type_t *t)
...@@ -563,7 +574,9 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) ...@@ -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 in_namespace = t->namespace && !is_global_namespace(t->namespace);
int save_written = t->written; int save_written = t->written;
decl_spec_t ds = {.type = t}; 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) { if(in_namespace) {
fprintf(f, "#ifdef __cplusplus\n"); fprintf(f, "#ifdef __cplusplus\n");
fprintf(f, "} /* extern \"C\" */\n"); fprintf(f, "} /* extern \"C\" */\n");
...@@ -581,6 +594,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) ...@@ -581,6 +594,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
fprintf(f, ";\n"); fprintf(f, ";\n");
fprintf(f, "#endif\n\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) 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) ...@@ -1468,12 +1482,55 @@ static char *format_apicontract_macro(const type_t *type)
return name; 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) static void write_com_interface_start(FILE *header, const type_t *iface)
{ {
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
fprintf(header, "/*****************************************************************************\n"); fprintf(header, "/*****************************************************************************\n");
fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : "");
if (winrt_mode) write_winrt_type_comments(header, iface);
fprintf(header, " */\n"); 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,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : "");
fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\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) ...@@ -1482,6 +1539,7 @@ static void write_com_interface_end(FILE *header, type_t *iface)
{ {
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
type_t *type; type_t *type;
if (uuid) if (uuid)
...@@ -1559,17 +1617,22 @@ static void write_com_interface_end(FILE *header, type_t *iface) ...@@ -1559,17 +1617,22 @@ static void write_com_interface_end(FILE *header, type_t *iface)
write_locals(header, iface, FALSE); write_locals(header, iface, FALSE);
fprintf(header, "\n"); 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) static void write_rpc_interface_start(FILE *header, const type_t *iface)
{ {
unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 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, "/*****************************************************************************\n");
fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 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"); fprintf(header, " */\n");
if (contract) write_apicontract_guard_start(header, contract);
fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
if (var) if (var)
...@@ -1594,7 +1657,10 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface) ...@@ -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) 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) static void write_coclass(FILE *header, type_t *cocl)
......
...@@ -339,6 +339,7 @@ static const struct keyword attr_keywords[] = ...@@ -339,6 +339,7 @@ static const struct keyword attr_keywords[] =
{"context_handle", tCONTEXTHANDLE, 0}, {"context_handle", tCONTEXTHANDLE, 0},
{"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0}, {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0},
{"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0}, {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0},
{"contract", tCONTRACT, 1},
{"contractversion", tCONTRACTVERSION, 1}, {"contractversion", tCONTRACTVERSION, 1},
{"control", tCONTROL, 0}, {"control", tCONTROL, 0},
{"custom", tCUSTOM, 0}, {"custom", tCUSTOM, 0},
......
...@@ -181,6 +181,7 @@ static typelib_t *current_typelib; ...@@ -181,6 +181,7 @@ static typelib_t *current_typelib;
%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
%token tCONTEXTHANDLESERIALIZE %token tCONTEXTHANDLESERIALIZE
%token tCONTRACT
%token tCONTRACTVERSION %token tCONTRACTVERSION
%token tCONTROL tCPPQUOTE %token tCONTROL tCPPQUOTE
%token tCUSTOM %token tCUSTOM
...@@ -271,6 +272,7 @@ static typelib_t *current_typelib; ...@@ -271,6 +272,7 @@ static typelib_t *current_typelib;
%type <str_list> str_list %type <str_list> str_list
%type <expr> m_expr expr expr_const expr_int_const array m_bitfield %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_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <expr> contract_req
%type <type> interfacehdr %type <type> interfacehdr
%type <stgclass> storage_cls_spec %type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list %type <type_qualifier> type_qualifier m_type_qual_list
...@@ -508,6 +510,12 @@ contract_ver: ...@@ -508,6 +510,12 @@ contract_ver:
| aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } | 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; } attribute: { $$ = NULL; }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
...@@ -523,6 +531,7 @@ attribute: { $$ = NULL; } ...@@ -523,6 +531,7 @@ attribute: { $$ = NULL; }
| tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
| tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
| tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_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); } | tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); }
| tCONTROL { $$ = make_attr(ATTR_CONTROL); } | tCONTROL { $$ = make_attr(ATTR_CONTROL); }
| tCUSTOM '(' uuid_string ',' expr_const ')' { $$ = make_custom_attr($3, $5); } | tCUSTOM '(' uuid_string ',' expr_const ')' { $$ = make_custom_attr($3, $5); }
...@@ -2180,6 +2189,7 @@ struct allowed_attr allowed_attr[] = ...@@ -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_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_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_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_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_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_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "custom" },
......
...@@ -84,6 +84,7 @@ enum attr_type ...@@ -84,6 +84,7 @@ enum attr_type
ATTR_CODE, ATTR_CODE,
ATTR_COMMSTATUS, ATTR_COMMSTATUS,
ATTR_CONTEXTHANDLE, ATTR_CONTEXTHANDLE,
ATTR_CONTRACT,
ATTR_CONTRACTVERSION, ATTR_CONTRACTVERSION,
ATTR_CONTROL, ATTR_CONTROL,
ATTR_CUSTOM, ATTR_CUSTOM,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment