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";
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
......
......@@ -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)
......
......@@ -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},
......
......@@ -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" },
......
......@@ -84,6 +84,7 @@ enum attr_type
ATTR_CODE,
ATTR_COMMSTATUS,
ATTR_CONTEXTHANDLE,
ATTR_CONTRACT,
ATTR_CONTRACTVERSION,
ATTR_CONTROL,
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