From 11416a20c903dcaa0bb31c52bf3d4b885ff604ac Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 1 Jun 2011 21:06:14 +0200 Subject: [PATCH] widl: Generate function headers in the proc format string for interpreted functions. --- tools/widl/client.c | 2 +- tools/widl/header.c | 20 ++++++++ tools/widl/header.h | 1 + tools/widl/proxy.c | 2 +- tools/widl/server.c | 2 +- tools/widl/typegen.c | 118 +++++++++++++++++++++++++++++++++++++++---- tools/widl/typegen.h | 2 +- 7 files changed, 133 insertions(+), 14 deletions(-) diff --git a/tools/widl/client.c b/tools/widl/client.c index a32661b8a9b..d422c3167c3 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -285,7 +285,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) } /* update proc_offset */ - *proc_offset += get_size_procformatstring_func( func ); + *proc_offset += get_size_procformatstring_func( iface, func ); indent--; print_client("}\n"); diff --git a/tools/widl/header.c b/tools/widl/header.c index 1a71cefb674..16ddfec2d4e 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -459,6 +459,26 @@ unsigned int get_context_handle_offset( const type_t *type ) return index; } +unsigned int get_generic_handle_offset( const type_t *type ) +{ + generic_handle_t *gh; + unsigned int index = 0; + + while (!is_attr( type->attrs, ATTR_HANDLE )) + { + if (type_is_alias( type )) type = type_alias_get_aliasee( type ); + else if (is_ptr( type )) type = type_pointer_get_ref( type ); + else error( "internal error: %s is not a generic handle\n", type->name ); + } + LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) + { + if (!strcmp( type->name, gh->name )) return index; + index++; + } + error( "internal error: %s is not registered as a generic handle\n", type->name ); + return index; +} + /* check for types which require additional prototypes to be generated in the * header */ void check_for_additional_prototype_types(const var_list_t *list) diff --git a/tools/widl/header.h b/tools/widl/header.h index ba282294436..5ad16d226b2 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -37,6 +37,7 @@ extern void write_type_right(FILE *h, type_t *t, int is_field); extern void write_type_decl(FILE *f, type_t *t, const char *name); extern void write_type_decl_left(FILE *f, type_t *t); extern unsigned int get_context_handle_offset( const type_t *type ); +extern unsigned int get_generic_handle_offset( const type_t *type ); extern int needs_space_after(type_t *t); extern int is_object(const type_t *iface); extern int is_local(const attr_list_t *list); diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index c945ac0e40c..35a10de1f57 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -602,7 +602,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) func->procstring_offset = *proc_offset; gen_proxy(iface, func, idx, *proc_offset); gen_stub(iface, func, cname, *proc_offset); - *proc_offset += get_size_procformatstring_func( func ); + *proc_offset += get_size_procformatstring_func( iface, func ); } } diff --git a/tools/widl/server.c b/tools/widl/server.c index 8e437cd9e26..d892aa3fe22 100644 --- a/tools/widl/server.c +++ b/tools/widl/server.c @@ -242,7 +242,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) /* update proc_offset */ func->procstring_offset = *proc_offset; - *proc_offset += get_size_procformatstring_func( func ); + *proc_offset += get_size_procformatstring_func( iface, func ); } } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 50a047d2afb..aabf25b4e21 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -392,6 +392,18 @@ static unsigned char get_contexthandle_flags( const type_t *iface, const attr_li return flags; } +static unsigned int get_rpc_flags( const attr_list_t *attrs ) +{ + unsigned int flags = 0; + + if (is_attr( attrs, ATTR_IDEMPOTENT )) flags |= 0x0001; + if (is_attr( attrs, ATTR_BROADCAST )) flags |= 0x0002; + if (is_attr( attrs, ATTR_MAYBE )) flags |= 0x0004; + if (is_attr( attrs, ATTR_MESSAGE )) flags |= 0x0100; + if (is_attr( attrs, ATTR_ASYNC )) flags |= 0x4000; + return flags; +} + unsigned char get_struct_fc(const type_t *type) { int has_pointer = 0; @@ -965,9 +977,92 @@ int is_interpreted_func( const type_t *iface, const var_t *func ) return (stub_mode != MODE_Os); } -static void write_procformatstring_func( FILE *file, int indent, - const var_t *func, unsigned int *offset ) +static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + const var_t *func, unsigned int *offset, + unsigned short num_proc ) { + var_t *var; + var_list_t *args = type_get_function_args( func->type ); + unsigned char explicit_fc, implicit_fc; + unsigned char handle_flags; + const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); + unsigned char oi_flags = RPC_FC_PROC_OIF_RPCFLAGS | RPC_FC_PROC_OIF_NEWINIT; + unsigned int rpc_flags = get_rpc_flags( func->attrs ); + unsigned int stack_size = 0; + unsigned short param_num = 0; + unsigned short handle_stack_offset = 0; + unsigned short handle_param_num = 0; + + if (is_full_pointer_function( func )) oi_flags |= RPC_FC_PROC_OIF_FULLPTR; + if (is_object( iface )) + { + oi_flags |= RPC_FC_PROC_OIF_OBJECT; + stack_size += pointer_size; + } + + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + { + if (var == handle_var) + { + handle_stack_offset = stack_size; + handle_param_num = param_num; + } + stack_size += get_stack_size( var->type, var->attrs, NULL ); + param_num++; + } + if (!is_void( type_function_get_rettype( func->type ))) stack_size += pointer_size; + + print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name ); + print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc, + implicit_fc ? string_of_type(implicit_fc) : "explicit handle" ); + print_file( file, indent, "0x%02x,\n", oi_flags ); + print_file( file, indent, "NdrFcLong(0x%x),\n", rpc_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* method %hu */\n", num_proc, num_proc ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack size = %hu */\n", stack_size, stack_size ); + *offset += 10; + + if (implicit_fc) return; + + switch (explicit_fc) + { + case RPC_FC_BIND_PRIMITIVE: + handle_flags = 0; + print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); + print_file( file, indent, "0x%02x,\n", handle_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", + handle_stack_offset, handle_stack_offset ); + *offset += 4; + break; + case RPC_FC_BIND_GENERIC: + handle_flags = type_memsize( handle_var->type ); + print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); + print_file( file, indent, "0x%02x,\n", handle_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", + handle_stack_offset, handle_stack_offset ); + print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) ); + print_file( file, indent, "0x%x,\t/* FC_PAD */\n", RPC_FC_PAD); + *offset += 6; + break; + case RPC_FC_BIND_CONTEXT: + handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type ); + print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); + print_file( file, indent, "0x%02x,\n", handle_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", + handle_stack_offset, handle_stack_offset ); + print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) ); + print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num ); + *offset += 6; + break; + } +} + +static void write_procformatstring_func( FILE *file, int indent, const type_t *iface, + const var_t *func, unsigned int *offset, + unsigned short num_proc ) +{ + if (is_interpreted_func( iface, func )) + write_proc_func_header( file, indent, iface, func, offset, num_proc ); + /* emit argument data */ if (type_get_function_args(func->type)) { @@ -1003,13 +1098,16 @@ static void write_procformatstring_stmts(FILE *file, int indent, const statement if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) { const statement_t *stmt_func; - if (!pred(stmt->u.type)) - continue; - STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) + const type_t *iface = stmt->u.type; + const type_t *parent = type_iface_get_inherit( iface ); + int count = parent ? count_methods( parent ) : 0; + + if (!pred(iface)) continue; + STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) { - const var_t *func = stmt_func->u.var; + var_t *func = stmt_func->u.var; if (is_local(func->attrs)) continue; - write_procformatstring_func( file, indent, func, offset ); + write_procformatstring_func( file, indent, iface, func, offset, count++ ); } } else if (stmt->type == STMT_LIBRARY) @@ -4024,10 +4122,10 @@ void write_remoting_arguments(FILE *file, int indent, const var_t *func, const c } -unsigned int get_size_procformatstring_func(const var_t *func) +unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func) { unsigned int offset = 0; - write_procformatstring_func( NULL, 0, func, &offset ); + write_procformatstring_func( NULL, 0, iface, func, &offset, 0 ); return offset; } @@ -4057,7 +4155,7 @@ unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_ { const var_t *func = stmt_func->u.var; if (!is_local(func->attrs)) - size += get_size_procformatstring_func( func ); + size += get_size_procformatstring_func( iface, func ); } } return size; diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h index f348bd3ca88..5920fb19128 100644 --- a/tools/widl/typegen.h +++ b/tools/widl/typegen.h @@ -70,7 +70,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, enum pass pass, const var_t *var, const char *varname); void write_remoting_arguments(FILE *file, int indent, const var_t *func, const char *local_var_prefix, enum pass pass, enum remoting_phase phase); -unsigned int get_size_procformatstring_func(const var_t *func); +unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func); unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_t pred); unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred); void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix );