[PATCH 5/5] widl: Support WinRT runtimeclass type parsing.

Zebediah Figura (she/her) zfigura at codeweavers.com
Tue Jan 19 11:32:53 CST 2021



On 1/19/21 7:04 AM, Rémi Bernon wrote:
> Signed-off-by: Rémi Bernon <rbernon at 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));
> +	                                          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;
> 



More information about the wine-devel mailing list