diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in index 358756cae57..453276c55d5 100644 --- a/tools/widl/Makefile.in +++ b/tools/widl/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ server.c \ typegen.c \ typelib.c \ + typetree.c \ utils.c \ widl.c \ write_msft.c diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 3b668ef07e7..efe1769e7b1 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -32,6 +32,7 @@ #include "utils.h" #include "expr.h" #include "header.h" +#include "typetree.h" expr_t *make_expr(enum expr_type type) { @@ -362,17 +363,14 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, *found_in_cont_type = 0; - if (cont_type && (cont_type->type == RPC_FC_FUNCTION || is_struct(cont_type->type))) - fields = cont_type->fields_or_args; - else if (cont_type && is_union(cont_type->type)) + if (cont_type) { - if (cont_type->type == RPC_FC_ENCAPSULATED_UNION) - { - const var_t *uv = LIST_ENTRY(list_tail(cont_type->fields_or_args), const var_t, entry); - fields = uv->type->fields_or_args; - } - else - fields = cont_type->fields_or_args; + if (cont_type->type == RPC_FC_FUNCTION) + fields = type_function_get_args(cont_type); + else if (is_struct(cont_type->type)) + fields = type_struct_get_fields(cont_type); + else if (is_union(cont_type->type)) + fields = type_union_get_cases(cont_type); } if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) diff --git a/tools/widl/header.c b/tools/widl/header.c index 83fef7fcbdc..73612b35a7c 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -34,6 +34,7 @@ #include "parser.h" #include "header.h" #include "expr.h" +#include "typetree.h" typedef struct _user_type_t generic_handle_t; @@ -209,7 +210,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) else fprintf(h, "enum {\n"); t->written = TRUE; indentation++; - write_enums(h, t->fields_or_args); + write_enums(h, type_enum_get_values(t)); indent(h, -1); fprintf(h, "}"); } @@ -227,7 +228,10 @@ void write_type_left(FILE *h, type_t *t, int declonly) else fprintf(h, "struct {\n"); t->written = TRUE; indentation++; - write_fields(h, t->fields_or_args); + if (t->type == RPC_FC_ENCAPSULATED_UNION) + write_fields(h, type_encapsulated_union_get_fields(t)); + else + write_fields(h, type_struct_get_fields(t)); indent(h, -1); fprintf(h, "}"); } @@ -239,7 +243,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) else fprintf(h, "union {\n"); t->written = TRUE; indentation++; - write_fields(h, t->fields_or_args); + write_fields(h, type_union_get_cases(t)); indent(h, -1); fprintf(h, "}"); } @@ -308,7 +312,7 @@ void write_type_v(FILE *h, type_t *t, int is_field, int declonly, if (pt->type == RPC_FC_FUNCTION) { if (ptr_level) fputc(')', h); fputc('(', h); - write_args(h, pt->fields_or_args, NULL, 0, FALSE); + write_args(h, type_function_get_args(pt), NULL, 0, FALSE); fputc(')', h); } else write_type_right(h, t, is_field); @@ -409,7 +413,14 @@ void check_for_additional_prototype_types(const var_list_t *list) } else { - check_for_additional_prototype_types(type->fields_or_args); + var_list_t *vars = NULL; + if (type->type == RPC_FC_ENUM16 || type->type == RPC_FC_ENUM32) + vars = type_enum_get_values(type); + else if (is_struct(type->type)) + vars = type_struct_get_fields(type); + else if (is_union(type->type)) + vars = type_union_get_cases(type); + check_for_additional_prototype_types(vars); } } } diff --git a/tools/widl/parser.h b/tools/widl/parser.h index 71f08dc994a..72d551c5d3d 100644 --- a/tools/widl/parser.h +++ b/tools/widl/parser.h @@ -45,4 +45,6 @@ void pop_import(void); int is_type(const char *name); +void check_functions(const type_t *iface); + #endif diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 47aef8630ec..8a3d2c70ead 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -39,6 +39,7 @@ #include "typelib.h" #include "typegen.h" #include "expr.h" +#include "typetree.h" #if defined(YYBYACC) /* Berkeley yacc (byacc) doesn't seem to know about these */ @@ -122,10 +123,13 @@ static type_t *make_safearray(type_t *type); static type_t *make_builtin(char *name); static type_t *make_int(int sign); static typelib_t *make_library(const char *name, const attr_list_t *attrs); -static type_t *make_func_type(var_list_t *args); -static type_t *make_pointer_type(type_t *ref, attr_list_t *attrs); static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type); +static type_t *type_new_enum(var_t *name, var_list_t *enums); +static type_t *type_new_struct(var_t *name, var_list_t *fields); +static type_t *type_new_nonencapsulated_union(var_t *name, var_list_t *fields); +static type_t *type_new_encapsulated_union(var_t *name, var_t *switch_field, var_t *union_field, var_list_t *cases); + static type_t *reg_type(type_t *type, const char *name, int t); static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); static type_t *find_type_or_error(const char *name, int t); @@ -140,11 +144,9 @@ static void write_clsid(type_t *cls); static void write_diid(type_t *iface); static void write_iid(type_t *iface); -static int compute_method_indexes(type_t *iface); static char *gen_name(void); static statement_t *process_typedefs(var_list_t *names); static void check_arg(var_t *arg); -static void check_functions(const type_t *iface); static void check_all_user_types(const statement_list_t *stmts); static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs); static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs); @@ -642,10 +644,7 @@ enum: ident '=' expr_int_const { $$ = reg_const($1); } ; -enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM); - $$->kind = TKIND_ENUM; - $$->fields_or_args = $4; - $$->defined = TRUE; +enumdef: tENUM t_ident '{' enums '}' { $$ = type_new_enum($2, $4); if(in_typelib) add_typelib_entry($$); } @@ -886,8 +885,6 @@ dispinterfacehdr: attributes dispinterface { attr_t *attrs; check_def($$); attrs = make_attr(ATTR_DISPINTERFACE); $$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs ); - $$->ref = find_type("IDispatch", 0); - if (!$$->ref) error_loc("IDispatch is undefined\n"); $$->defined = TRUE; if (!parse_only && do_header) write_forward($$); } @@ -905,16 +902,14 @@ dispinterfacedef: dispinterfacehdr '{' dispint_props dispint_meths '}' { $$ = $1; - $$->fields_or_args = $3; - $$->funcs = $4; + type_dispinterface_define($$, $3, $4); if (!parse_only && do_header) write_interface($$); if (!parse_only && do_idfile) write_diid($$); is_in_interface = FALSE; } | dispinterfacehdr '{' interface ';' '}' { $$ = $1; - $$->fields_or_args = $3->fields_or_args; - $$->funcs = $3->funcs; + type_dispinterface_define_from_iface($$, $3); if (!parse_only && do_header) write_interface($$); if (!parse_only && do_idfile) write_diid($$); is_in_interface = FALSE; @@ -944,10 +939,7 @@ interfacehdr: attributes interface { $$.interface = $2; interfacedef: interfacehdr inherit '{' int_statements '}' semicolon_opt { $$ = $1.interface; - $$->ref = $2; - $$->funcs = $4; - check_functions($$); - compute_method_indexes($$); + type_interface_define($$, $2, $4); if (!parse_only && do_header) write_interface($$); if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE); if (!parse_only && do_idfile) write_iid($$); @@ -959,10 +951,7 @@ interfacedef: interfacehdr inherit | interfacehdr ':' aIDENTIFIER '{' import int_statements '}' semicolon_opt { $$ = $1.interface; - $$->ref = find_type_or_error2($3, 0); - if (!$$->ref) error_loc("base class '%s' not found in import\n", $3); - $$->funcs = $6; - compute_method_indexes($$); + type_interface_define($$, find_type_or_error2($3, 0), $6); if (!parse_only && do_header) write_interface($$); if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE); if (!parse_only && do_idfile) write_iid($$); @@ -1028,7 +1017,7 @@ decl_spec_no_type: declarator: '*' m_type_qual_list declarator %prec PPTR - { $$ = $3; $$->type = append_ptrchain_type($$->type, make_pointer_type(NULL, $2)); } + { $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(NULL, $2)); } | callconv declarator { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } | direct_declarator ; @@ -1038,7 +1027,7 @@ direct_declarator: | '(' declarator ')' { $$ = $2; } | direct_declarator array { $$ = $1; $$->array = append_array($$->array, $2); } | direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_ptrchain_type($$->type, make_func_type($3)); + $$->func_type = append_ptrchain_type($$->type, type_new_function($3)); $$->type = NULL; } ; @@ -1059,11 +1048,7 @@ pointer_type: | tPTR { $$ = RPC_FC_FP; } ; -structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT); - check_def($$); - $$->kind = TKIND_RECORD; - $$->fields_or_args = $4; - $$->defined = TRUE; +structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, $4); if(in_typelib) add_typelib_entry($$); } @@ -1088,27 +1073,10 @@ typedef: tTYPEDEF m_attributes decl_spec declarator_list ; uniondef: tUNION t_ident '{' ne_union_fields '}' - { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION); - check_def($$); - $$->kind = TKIND_UNION; - $$->fields_or_args = $4; - $$->defined = TRUE; - } + { $$ = type_new_nonencapsulated_union($2, $4); } | tUNION t_ident tSWITCH '(' s_field ')' - m_ident '{' cases '}' { var_t *u = $7; - $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); - check_def($$); - $$->kind = TKIND_UNION; - if (!u) u = make_var( xstrdup("tagged_union") ); - u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); - u->type->kind = TKIND_UNION; - u->type->fields_or_args = $9; - u->type->defined = TRUE; - $$->fields_or_args = append_var( $$->fields_or_args, $5 ); - $$->fields_or_args = append_var( $$->fields_or_args, u ); - $$->defined = TRUE; - } + m_ident '{' cases '}' { $$ = type_new_encapsulated_union($2, $5, $7, $9); } ; version: @@ -1403,18 +1371,57 @@ type_t *make_type(unsigned char type, type_t *ref) return t; } -static type_t *make_func_type(var_list_t *args) +static type_t *type_new_enum(var_t *name, var_list_t *enums) { - type_t *t = make_type(RPC_FC_FUNCTION, NULL); - t->fields_or_args = args; + type_t *t = get_typev(RPC_FC_ENUM16, name, tsENUM); + t->kind = TKIND_ENUM; + t->fields_or_args = enums; + t->defined = TRUE; + return t; +} + +static type_t *type_new_struct(var_t *name, var_list_t *fields) +{ + type_t *t = get_typev(RPC_FC_STRUCT, name, tsSTRUCT); + t->kind = TKIND_RECORD; + t->fields_or_args = fields; + t->defined = TRUE; return t; } -static type_t *make_pointer_type(type_t *ref, attr_list_t *attrs) +static type_t *type_new_nonencapsulated_union(var_t *name, var_list_t *fields) { - type_t *t = make_type(pointer_default, ref); - t->attrs = attrs; - return t; + type_t *t = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, name, tsUNION); + t->kind = TKIND_UNION; + t->fields_or_args = fields; + t->defined = TRUE; + return t; +} + +static type_t *type_new_encapsulated_union(var_t *name, var_t *switch_field, var_t *union_field, var_list_t *cases) +{ + type_t *t = get_typev(RPC_FC_ENCAPSULATED_UNION, name, tsUNION); + t->kind = TKIND_UNION; + if (!union_field) union_field = make_var( xstrdup("tagged_union") ); + union_field->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); + union_field->type->kind = TKIND_UNION; + union_field->type->fields_or_args = cases; + union_field->type->defined = TRUE; + t->fields_or_args = append_var( NULL, switch_field ); + t->fields_or_args = append_var( t->fields_or_args, union_field ); + t->defined = TRUE; + return t; +} + +static void function_add_head_arg(func_t *func, var_t *arg) +{ + if (!func->def->type->fields_or_args) + { + func->def->type->fields_or_args = xmalloc( sizeof(*func->def->type->fields_or_args) ); + list_init( func->def->type->fields_or_args ); + } + list_add_head( func->def->type->fields_or_args, &arg->entry ); + func->args = func->def->type->fields_or_args; } static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type) @@ -2008,26 +2015,6 @@ static void write_iid(type_t *iface) write_guid(idfile, "IID", iface->name, uuid); } -static int compute_method_indexes(type_t *iface) -{ - int idx; - func_t *f; - - if (iface->ref) - idx = compute_method_indexes(iface->ref); - else - idx = 0; - - if (!iface->funcs) - return idx; - - LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry ) - if (! is_callas(f->def->attrs)) - f->idx = idx++; - - return idx; -} - static char *gen_name(void) { static const char format[] = "__WIDL_%s_generated_name_%08lX"; @@ -2482,21 +2469,13 @@ static void check_remoting_fields(const var_t *var, type_t *type) if (is_struct(type->type)) { - if (type->defined) - fields = type->fields_or_args; + if (type_is_defined(type)) + fields = type_struct_get_fields(type); else error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name); } else if (is_union(type->type)) - { - if (type->type == RPC_FC_ENCAPSULATED_UNION) - { - const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry); - fields = uv->type->fields_or_args; - } - else - fields = type->fields_or_args; - } + fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) if (field->type) check_field_common(type, type->name, field); @@ -2569,19 +2548,13 @@ static void add_explicit_handle_if_necessary(func_t *func) var_t *idl_handle = make_var(xstrdup("IDL_handle")); idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN)); idl_handle->type = find_type_or_error("handle_t", 0); - if (!func->def->type->fields_or_args) - { - func->def->type->fields_or_args = xmalloc( sizeof(*func->def->type->fields_or_args) ); - list_init( func->def->type->fields_or_args ); - } - list_add_head( func->def->type->fields_or_args, &idl_handle->entry ); - func->args = func->def->type->fields_or_args; + function_add_head_arg(func, idl_handle); } } } } -static void check_functions(const type_t *iface) +void check_functions(const type_t *iface) { if (is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE) && iface->funcs) { diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 0406eb98d2d..daabbd6ca70 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -36,7 +36,7 @@ #include "utils.h" #include "parser.h" #include "header.h" -#include "wine/list.h" +#include "typetree.h" #include "typegen.h" #include "expr.h" @@ -126,13 +126,16 @@ static int get_struct_type(const type_t *type) int has_conformance = 0; int has_variance = 0; var_t *field; + var_list_t *fields; if (type->type != RPC_FC_STRUCT) return type->type; - if (get_padding(type->fields_or_args)) + fields = type_struct_get_fields(type); + + if (get_padding(fields)) return RPC_FC_BOGUS_STRUCT; - if (type->fields_or_args) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) { type_t *t = field->type; @@ -174,7 +177,7 @@ static int get_struct_type(const type_t *type) if (is_conformant_array(field->type)) { has_conformance = 1; - if (field->type->declarray && list_next(type->fields_or_args, &field->entry)) + if (field->type->declarray && list_next(fields, &field->entry)) error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", field->name); } @@ -247,7 +250,7 @@ static int get_struct_type(const type_t *type) case RPC_FC_CPSTRUCT: has_conformance = 1; - if (list_next( type->fields_or_args, &field->entry )) + if (list_next( fields, &field->entry )) error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", field->name); has_pointer = 1; @@ -255,7 +258,7 @@ static int get_struct_type(const type_t *type) case RPC_FC_CSTRUCT: has_conformance = 1; - if (list_next( type->fields_or_args, &field->entry )) + if (list_next( fields, &field->entry )) error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", field->name); break; @@ -378,8 +381,9 @@ static int type_has_pointers(const type_t *type) return type_has_pointers(type->ref); else if (is_struct(type->type)) { + var_list_t *fields = type_struct_get_fields(type); const var_t *field; - if (type->fields_or_args) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, const var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { if (type_has_pointers(field->type)) return TRUE; @@ -389,13 +393,7 @@ static int type_has_pointers(const type_t *type) { var_list_t *fields; const var_t *field; - if (type->type == RPC_FC_ENCAPSULATED_UNION) - { - const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry); - fields = uv->type->fields_or_args; - } - else - fields = type->fields_or_args; + fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { if (field->type && type_has_pointers(field->type)) @@ -418,8 +416,9 @@ static int type_has_full_pointer(const type_t *type) return type_has_full_pointer(type->ref); else if (is_struct(type->type)) { + var_list_t *fields = type_struct_get_fields(type); const var_t *field; - if (type->fields_or_args) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, const var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { if (type_has_full_pointer(field->type)) return TRUE; @@ -429,13 +428,7 @@ static int type_has_full_pointer(const type_t *type) { var_list_t *fields; const var_t *field; - if (type->type == RPC_FC_ENCAPSULATED_UNION) - { - const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry); - fields = uv->type->fields_or_args; - } - else - fields = type->fields_or_args; + fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { if (field->type && type_has_full_pointer(field->type)) @@ -861,8 +854,9 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure, unsigned char param_type = 0; size_t offset = 0; const var_t *var; + var_list_t *fields = type_struct_get_fields(structure); - if (structure->fields_or_args) LIST_FOR_EACH_ENTRY( var, structure->fields_or_args, const var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) { unsigned int align = 0; /* FIXME: take alignment into account */ @@ -1073,11 +1067,13 @@ size_t type_memsize(const type_t *t, unsigned int *align) case RPC_FC_CSTRUCT: case RPC_FC_PSTRUCT: case RPC_FC_BOGUS_STRUCT: - size = fields_memsize(t->fields_or_args, align); + size = fields_memsize(type_struct_get_fields(t), align); break; case RPC_FC_ENCAPSULATED_UNION: + size = fields_memsize(type_encapsulated_union_get_fields(t), align); + break; case RPC_FC_NON_ENCAPSULATED_UNION: - size = union_memsize(t->fields_or_args, align); + size = union_memsize(type_union_get_cases(t), align); break; case RPC_FC_SMFARRAY: case RPC_FC_LGFARRAY: @@ -1295,7 +1291,7 @@ static void write_end(FILE *file, unsigned int *tfsoff) static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) { unsigned int offset = 0; - var_list_t *fs = type->fields_or_args; + var_list_t *fs = type_struct_get_fields(type); var_t *f; if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) @@ -1372,7 +1368,7 @@ static int write_no_repeat_pointer_descriptions( if (is_non_complex_struct(type)) { const var_t *v; - LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) + LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) { if (offset_in_memory && offset_in_buffer) { @@ -1450,7 +1446,7 @@ static int write_pointer_description_offsets( { /* otherwise search for interesting fields to parse */ const var_t *v; - LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) + LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) { if (offset_in_memory && offset_in_buffer) { @@ -1526,7 +1522,7 @@ static int write_fixed_array_pointer_descriptions( else if (is_struct(type->type)) { const var_t *v; - LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) + LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) { if (offset_in_memory && offset_in_buffer) { @@ -1645,7 +1641,7 @@ static int write_varying_array_pointer_descriptions( else if (is_struct(type->type)) { const var_t *v; - LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) + LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) { if (offset_in_memory && offset_in_buffer) { @@ -1938,14 +1934,15 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type static const var_t *find_array_or_string_in_struct(const type_t *type) { + const var_list_t *fields = type_struct_get_fields(type); const var_t *last_field; const type_t *ft; int real_type; - if (!type->fields_or_args || list_empty(type->fields_or_args)) + if (!fields || list_empty(fields)) return NULL; - last_field = LIST_ENTRY( list_tail(type->fields_or_args), const var_t, entry ); + last_field = LIST_ENTRY( list_tail(fields), const var_t, entry ); ft = last_field->type; if (ft->declarray && is_conformant_array(ft)) @@ -1965,8 +1962,9 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned short offset = 0; int salign = -1; int padding; + var_list_t *fields = type_struct_get_fields(type); - if (type->fields_or_args) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, const var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { type_t *ft = field->type; if (!ft->declarray || !is_conformant_array(ft)) @@ -2024,6 +2022,7 @@ static size_t write_struct_tfs(FILE *file, type_t *type, unsigned int corroff; var_t *f; int real_type = get_struct_type( type ); + var_list_t *fields = type_struct_get_fields(type); guard_rec(type); current_structure = type; @@ -2033,7 +2032,7 @@ static size_t write_struct_tfs(FILE *file, type_t *type, error("structure size for %s exceeds %d bytes by %d bytes\n", name, USHRT_MAX, total_size - USHRT_MAX); - if (type->fields_or_args) LIST_FOR_EACH_ENTRY(f, type->fields_or_args, var_t, entry) + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff); if (!has_pointers) has_pointers = type_has_pointers(type); @@ -2098,11 +2097,10 @@ static size_t write_struct_tfs(FILE *file, type_t *type, if (real_type == RPC_FC_BOGUS_STRUCT) { - const var_list_t *fs = type->fields_or_args; const var_t *f; type->ptrdesc = *tfsoff; - if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry) + if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) { type_t *ft = f->type; if (is_ptr(ft)) @@ -2206,13 +2204,7 @@ static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) guard_rec(type); - if (type->type == RPC_FC_ENCAPSULATED_UNION) - { - const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry); - fields = uv->type->fields_or_args; - } - else - fields = type->fields_or_args; + fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) { @@ -2228,7 +2220,7 @@ static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) print_start_tfs_comment(file, type, start_offset); if (type->type == RPC_FC_ENCAPSULATED_UNION) { - const var_t *sv = LIST_ENTRY(list_head(type->fields_or_args), const var_t, entry); + const var_t *sv = type_union_get_switch_value(type); const type_t *st = sv->type; switch (st->type) @@ -2720,8 +2712,8 @@ static unsigned int get_required_buffer_size_type( return 0; case RPC_FC_STRUCT: - if (!type->fields_or_args) return 0; - return fields_memsize(type->fields_or_args, alignment); + if (!type_struct_get_fields(type)) return 0; + return fields_memsize(type_struct_get_fields(type), alignment); case RPC_FC_RP: return diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c new file mode 100644 index 00000000000..07b145e7b14 --- /dev/null +++ b/tools/widl/typetree.c @@ -0,0 +1,90 @@ +/* + * IDL Type Tree + * + * Copyright 2008 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "typetree.h" +#include "header.h" + +type_t *type_new_function(var_list_t *args) +{ + type_t *t = make_type(RPC_FC_FUNCTION, NULL); + t->fields_or_args = args; + return t; +} + +type_t *type_new_pointer(type_t *ref, attr_list_t *attrs) +{ + type_t *t = make_type(pointer_default, ref); + t->attrs = attrs; + return t; +} + +static int compute_method_indexes(type_t *iface) +{ + int idx; + func_t *f; + + if (iface->ref) + idx = compute_method_indexes(iface->ref); + else + idx = 0; + + if (!iface->funcs) + return idx; + + LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry ) + if (! is_callas(f->def->attrs)) + f->idx = idx++; + + return idx; +} + +void type_interface_define(type_t *iface, type_t *inherit, func_list_t *funcs) +{ + iface->ref = inherit; + iface->funcs = funcs; + iface->defined = TRUE; + check_functions(iface); + compute_method_indexes(iface); +} + +void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods) +{ + iface->ref = find_type("IDispatch", 0); + if (!iface->ref) error_loc("IDispatch is undefined\n"); + iface->funcs = NULL; + iface->fields_or_args = props; + iface->funcs = methods; + iface->defined = TRUE; + check_functions(iface); + compute_method_indexes(iface); +} + +void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) +{ + type_dispinterface_define(dispiface, iface->fields_or_args, iface->funcs); +} diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h new file mode 100644 index 00000000000..9f1a8d2d30b --- /dev/null +++ b/tools/widl/typetree.h @@ -0,0 +1,93 @@ +/* + * IDL Type Tree + * + * Copyright 2008 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "widltypes.h" +#include + +#ifndef WIDL_TYPE_TREE_H +#define WIDL_TYPE_TREE_H + +type_t *type_new_function(var_list_t *args); +type_t *type_new_pointer(type_t *ref, attr_list_t *attrs); +void type_interface_define(type_t *iface, type_t *inherit, func_list_t *funcs); +void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods); +void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); + +static inline var_list_t *type_struct_get_fields(const type_t *type) +{ + assert(is_struct(type->type)); + return type->fields_or_args; +} + +static inline var_list_t *type_function_get_args(const type_t *type) +{ + assert(type->type == RPC_FC_FUNCTION); + return type->fields_or_args; +} + +static inline var_list_t *type_enum_get_values(const type_t *type) +{ + assert(type->type == RPC_FC_ENUM16 || type->type == RPC_FC_ENUM32); + return type->fields_or_args; +} + +static inline var_t *type_union_get_switch_value(const type_t *type) +{ + assert(type->type == RPC_FC_ENCAPSULATED_UNION); + return LIST_ENTRY(list_head(type->fields_or_args), var_t, entry); +} + +static inline var_list_t *type_encapsulated_union_get_fields(const type_t *type) +{ + assert(type->type == RPC_FC_ENCAPSULATED_UNION); + return type->fields_or_args; +} + +static inline var_list_t *type_union_get_cases(const type_t *type) +{ + assert(type->type == RPC_FC_ENCAPSULATED_UNION || + type->type == RPC_FC_NON_ENCAPSULATED_UNION); + if (type->type == RPC_FC_ENCAPSULATED_UNION) + { + const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry); + return uv->type->fields_or_args; + } + else + return type->fields_or_args; +} + +static inline var_list_t *type_dispiface_get_props(const type_t *type) +{ + assert(type->type == RPC_FC_IP); + return type->fields_or_args; +} + +static inline var_list_t *type_dispiface_get_methods(const type_t *type) +{ + assert(type->type == RPC_FC_IP); + return type->funcs; +} + +static inline int type_is_defined(const type_t *type) +{ + return type->defined; +} + +#endif /* WIDL_TYPE_TREE_H */ diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 4f1fc1c9116..564deade097 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -22,6 +22,7 @@ #define __WIDL_WIDLTYPES_H #include +#include #include "guiddef.h" #include "wine/rpcfc.h" #include "wine/list.h" diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 30ed2510a36..234021661f1 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -51,6 +51,7 @@ #include "utils.h" #include "header.h" #include "hash.h" +#include "typetree.h" enum MSFT_segment_index { MSFT_SEG_TYPEINFO = 0, /* type information */ @@ -1968,14 +1969,14 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte if (dispinterface->funcs) LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) idx++; - if (dispinterface->fields_or_args) - LIST_FOR_EACH_ENTRY( var, dispinterface->fields_or_args, var_t, entry ) + if (type_dispiface_get_props(dispinterface)) + LIST_FOR_EACH_ENTRY( var, type_dispiface_get_props(dispinterface), var_t, entry ) add_var_desc(msft_typeinfo, idx++, var); - if (dispinterface->funcs) + if (type_dispiface_get_methods(dispinterface)) { idx = 0; - LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) + LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), const func_t, entry ) if(add_func_desc(msft_typeinfo, func, idx) == S_OK) idx++; } @@ -2052,8 +2053,8 @@ static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs); msft_typeinfo->typeinfo->size = 0; - if (structure->fields_or_args) - LIST_FOR_EACH_ENTRY( cur, structure->fields_or_args, var_t, entry ) + if (type_struct_get_fields(structure)) + LIST_FOR_EACH_ENTRY( cur, type_struct_get_fields(structure), var_t, entry ) add_var_desc(msft_typeinfo, idx++, cur); } @@ -2067,8 +2068,8 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration) msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs); msft_typeinfo->typeinfo->size = 0; - if (enumeration->fields_or_args) - LIST_FOR_EACH_ENTRY( cur, enumeration->fields_or_args, var_t, entry ) + if (type_enum_get_values(enumeration)) + LIST_FOR_EACH_ENTRY( cur, type_enum_get_values(enumeration), var_t, entry ) add_var_desc(msft_typeinfo, idx++, cur); }