Needed to build windows.ui.composition.idl.
Example:
` [ composable(Windows.UI.Composition.ICompositionEasingFunctionFactory, public, Windows.Foundation.UniversalApiContract, 2.0), contract(Windows.Foundation.UniversalApiContract, 2.0), marshaling_behavior(agile), static(Windows.UI.Composition.ICompositionEasingFunctionStatics, Windows.Foundation.UniversalApiContract, 12.0), threading(both) ] runtimeclass CompositionEasingFunction : Windows.UI.Composition.CompositionObject { [default] interface Windows.UI.Composition.ICompositionEasingFunction; } `
Some WinRT headers use `protected` rather than `public` for the composable attribute like windows.ui.xaml.media.idl:2304
`[composable(Windows.UI.Xaml.Media.ICacheModeFactory, protected, Windows.Foundation.UniversalApiContract, 1.0)]`
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed to build windows.ui.composition.idl. --- tools/widl/attribute.c | 2 ++ tools/widl/parser.l | 2 ++ tools/widl/parser.y | 17 +++++++++++++++++ tools/widl/register.c | 2 +- tools/widl/widltypes.h | 2 ++ 5 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/tools/widl/attribute.c b/tools/widl/attribute.c index 92c6f1a44fa..b9aa99c9228 100644 --- a/tools/widl/attribute.c +++ b/tools/widl/attribute.c @@ -145,6 +145,7 @@ struct allowed_attr allowed_attr[] = /* 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_COMPOSABLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "composable" }, /* 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" }, @@ -215,6 +216,7 @@ struct allowed_attr allowed_attr[] = /* 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_PROTECTED */ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "protected" }, /* 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" }, diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 3ea03a7a26f..445efd2d458 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -245,6 +245,7 @@ static void winrt_enable( int ns_prefix ) callback { return tCALLBACK; } code { return tCODE; } comm_status { return tCOMMSTATUS; } + composable { return token_winrt( tCOMPOSABLE, yytext, yylval ); } context_handle { return tCONTEXTHANDLE; } context_handle_noserialize { return tCONTEXTHANDLENOSERIALIZE; } context_handle_serialize { return tCONTEXTHANDLENOSERIALIZE; } @@ -319,6 +320,7 @@ static void winrt_enable( int ns_prefix ) propget { return tPROPGET; } propput { return tPROPPUT; } propputref { return tPROPPUTREF; } + protected { return tPROTECTED; } proxy { return tPROXY; } ptr { return tPTR; } public { return tPUBLIC; } diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 5567d94559e..a30a6cc04a9 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -186,6 +186,7 @@ void pop_import( PARSER_LTYPE *yylloc ); %token tAPPOBJECT tASYNC tASYNCUUID %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT %token tCALLAS tCALLBACK tCASE tCHAR tCOCLASS tCODE tCOMMSTATUS +%token tCOMPOSABLE %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE %token tCONTEXTHANDLESERIALIZE %token tCONTRACT @@ -249,6 +250,7 @@ void pop_import( PARSER_LTYPE *yylloc ); %token tPRAGMA_WARNING %token tPROGID tPROPERTIES %token tPROPGET tPROPPUT tPROPPUTREF +%token tPROTECTED %token tPROXY tPTR %token tPUBLIC %token tRANGE @@ -294,6 +296,7 @@ void pop_import( PARSER_LTYPE *yylloc ); %type <expr> contract_req %type <expr> static_attr %type <expr> activatable_attr +%type <expr> composable_attr %type <type> delegatedef %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list @@ -611,6 +614,18 @@ activatable_attr: | contract_req { $$ = $1; } /* activatable on the default activation factory */ ;
+access + : tPUBLIC + | tPROTECTED + ; + +composable_attr: + decl_spec ',' access ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) + error_loc("type %s is not an interface\n", $1->type->name); + $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $5); + } + ; + attribute : %empty { $$ = NULL; } | tACTIVATABLE '(' activatable_attr ')' { $$ = attr_ptr( @$, ATTR_ACTIVATABLE, $3 ); } @@ -624,6 +639,7 @@ attribute | tCALLAS '(' ident ')' { $$ = attr_ptr( @$, ATTR_CALLAS, $3 ); } | tCASE '(' expr_list_int_const ')' { $$ = attr_ptr( @$, ATTR_CASE, $3 ); } | tCODE { $$ = attr_int( @$, ATTR_CODE, 0 ); } + | tCOMPOSABLE '(' composable_attr ')' { $$ = attr_ptr( @$, ATTR_COMPOSABLE, $3 ); } | tCOMMSTATUS { $$ = attr_int( @$, ATTR_COMMSTATUS, 0 ); } | tCONTEXTHANDLE { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); } | tCONTEXTHANDLENOSERIALIZE { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } @@ -703,6 +719,7 @@ attribute | tPROPGET { $$ = attr_int( @$, ATTR_PROPGET, 0 ); } | tPROPPUT { $$ = attr_int( @$, ATTR_PROPPUT, 0 ); } | tPROPPUTREF { $$ = attr_int( @$, ATTR_PROPPUTREF, 0 ); } + | tPROTECTED { $$ = attr_int( @$, ATTR_PROTECTED, 0 ); } | tPROXY { $$ = attr_int( @$, ATTR_PROXY, 0 ); } | tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } | tRANGE '(' expr_int_const ',' expr_int_const ')' diff --git a/tools/widl/register.c b/tools/widl/register.c index 6c00dfaf5a2..65d30a5c91c 100644 --- a/tools/widl/register.c +++ b/tools/widl/register.c @@ -190,7 +190,7 @@ static void write_runtimeclasses_registry( const statement_list_t *stmts ) { if (stmt->type != STMT_TYPE) continue; if (type_get_type((type = stmt->u.type)) != TYPE_RUNTIMECLASS) continue; - if (!get_attrp(type->attrs, ATTR_ACTIVATABLE) && !get_attrp(type->attrs, ATTR_STATIC)) continue; + if (!get_attrp(type->attrs, ATTR_ACTIVATABLE) && !get_attrp(type->attrs, ATTR_STATIC) && !get_attrp(type->attrs, ATTR_COMPOSABLE)) continue; put_str( indent, "ForceRemove %s\n", format_namespace( type->namespace, "", ".", type->name, NULL ) ); put_str( indent++, "{\n" ); put_str( indent, "val 'DllPath' = s '%%MODULE%%'\n" ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 652c0d822ee..ad6a4e0b7ec 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -84,6 +84,7 @@ enum attr_type ATTR_CASE, ATTR_CODE, ATTR_COMMSTATUS, + ATTR_COMPOSABLE, ATTR_CONTEXTHANDLE, ATTR_CONTRACT, ATTR_CONTRACTVERSION, @@ -154,6 +155,7 @@ enum attr_type ATTR_PROPGET, ATTR_PROPPUT, ATTR_PROPPUTREF, + ATTR_PROTECTED, ATTR_PROXY, ATTR_PUBLIC, ATTR_RANGE,
Rémi Bernon (@rbernon) commented about tools/widl/parser.y:
| tPROPGET { $$ = attr_int( @$, ATTR_PROPGET, 0 ); } | tPROPPUT { $$ = attr_int( @$, ATTR_PROPPUT, 0 ); } | tPROPPUTREF { $$ = attr_int( @$, ATTR_PROPPUTREF, 0 ); }
| tPROTECTED { $$ = attr_int( @$, ATTR_PROTECTED, 0 ); }
Would you mind splitting this, adding `protected` attribute parsing first and then `composable` attribute?
Rémi Bernon (@rbernon) commented about tools/widl/parser.y:
| contract_req { $$ = $1; } /* activatable on the default activation factory */ ;
+access
- : tPUBLIC
- | tPROTECTED
- ;
+composable_attr:
decl_spec ',' access ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE)
error_loc("type %s is not an interface\n", $1->type->name);
$$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $5);
}
- ;
```suggestion:-11+0 access_attr : tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } | tPROTECTED { $$ = attr_int( @$, ATTR_PROTECTED, 0 ); } ;
composable_attr : decl_spec ',' access_attr ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $1->type->name ); $$ = make_exprt( EXPR_MEMBER, declare_var( append_attr( NULL, $3 ), $1, make_declarator( NULL ), 0 ), $5 ); } ;
```
I'd suggest something like that, with `access_attr` type added at the top. This makes sure the `composable` attribute properties are all available somewhere in the expression.
Using an expression is probably fine for now, especially for consistency as other attributes are parsed the same, but I think that at some point we should instead have specific structs to describe attributes in a less obfuscated way.
Note also that I've started to progressively convert this file to using spaces only, and to use julliard style spacing too for readability. Tabs alignment gets often messed up and will look differently depending on the editor settings.