widl: Add support for top-level conformances.

This commit is contained in:
Alexandre Julliard 2011-05-26 21:34:51 +02:00
parent d8059aee3a
commit c2406be6d4
3 changed files with 116 additions and 56 deletions

View File

@ -47,13 +47,16 @@
#define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1)))
static const type_t *current_structure;
static const var_t *current_func;
static const type_t *current_iface;
static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
struct expr_eval_routine
{
struct list entry;
const type_t *structure;
const type_t *iface;
const type_t *cont_type;
char *name;
unsigned int baseoff;
const expr_t *expr;
};
@ -1031,14 +1034,16 @@ static int write_base_type(FILE *file, const type_t *type, int convert_to_signed
}
/* write conformance / variance descriptor */
static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
unsigned int baseoff, const type_t *type,
const expr_t *expr)
{
unsigned char operator_type = 0;
unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
const char *conftype_string = "";
const char *conftype_string = "field";
const expr_t *subexpr;
const type_t *iface = NULL;
const char *name;
if (!expr)
{
@ -1061,20 +1066,22 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
return 4;
}
if (!structure)
if (!cont_type) /* top-level conformance */
{
/* Top-level conformance calculations are done inline. */
print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
RPC_FC_TOP_LEVEL_CONFORMANCE);
print_file (file, 2, "0x0,\n");
print_file (file, 2, "NdrFcShort(0x0),\n");
return 4;
conftype = RPC_FC_TOP_LEVEL_CONFORMANCE;
conftype_string = "parameter";
cont_type = current_func->type;
name = current_func->name;
iface = current_iface;
}
else
{
name = cont_type->name;
if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type)))
{
conftype = RPC_FC_POINTER_CONFORMANCE;
conftype_string = "field pointer, ";
conftype_string = "field pointer";
}
}
subexpr = expr;
@ -1122,23 +1129,45 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
unsigned char param_type = 0;
unsigned int offset = 0;
const var_t *var;
var_list_t *fields = type_struct_get_fields(structure);
struct expr_loc expr_loc;
if (type_get_type(cont_type) == TYPE_FUNCTION)
{
var_list_t *args = type_get_function_args( cont_type );
if (is_object( iface )) offset += pointer_size;
if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
{
if (var->name && !strcmp(var->name, subexpr->u.sval))
{
expr_loc.v = var;
correlation_variable = var->type;
break;
}
offset += get_stack_size( var->type, var->attrs, NULL );
}
}
else
{
var_list_t *fields = type_struct_get_fields( cont_type );
if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
{
unsigned int size = field_memsize( var->type, &offset );
if (var->name && !strcmp(var->name, subexpr->u.sval))
{
expr_loc.v = var;
correlation_variable = var->type;
break;
}
offset += size;
}
if (!correlation_variable)
error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
subexpr->u.sval);
}
correlation_variable = expr_resolve_type(NULL, structure, expr);
if (!correlation_variable)
error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
expr_loc.attr = NULL;
correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr);
offset -= baseoff;
@ -1193,9 +1222,9 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
return 0;
}
print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
conftype | param_type, conftype_string, string_of_type(param_type));
print_file(file, 2, "0x%x, /* %s */\n", operator_type,
print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n",
conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type));
print_file(file, 2, "0x%x,\t/* %s */\n", operator_type,
operator_type ? string_of_type(operator_type) : "no operators");
print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n",
(unsigned short)offset, offset);
@ -1208,9 +1237,10 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
{
if (eval->structure == structure ||
(eval->structure->name && structure->name &&
!strcmp(eval->structure->name, structure->name) &&
if (eval->cont_type == cont_type ||
(type_get_type( eval->cont_type ) == type_get_type( cont_type ) &&
eval->iface == iface &&
eval->name && name && !strcmp(eval->name, name) &&
!compare_expr(eval->expr, expr)))
{
found = 1;
@ -1222,7 +1252,9 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
if (!found)
{
eval = xmalloc (sizeof(*eval));
eval->structure = structure;
eval->iface = iface;
eval->cont_type = cont_type;
eval->name = xstrdup( name );
eval->baseoff = baseoff;
eval->expr = expr;
list_add_tail (&expr_eval_routines, &eval->entry);
@ -1231,8 +1263,8 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
if (callback_offset > USHRT_MAX)
error("Maximum number of callback routines reached\n");
print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name);
print_file(file, 2, "0x%x,\t/* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset);
}
return 4;
@ -1327,6 +1359,7 @@ static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *al
break;
case RPC_FC_INT3264:
case RPC_FC_UINT3264:
case RPC_FC_BIND_PRIMITIVE:
assert( pointer_size );
size = pointer_size;
if (size > *align) *align = size;
@ -2685,7 +2718,8 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
*tfsoff += 2;
}
static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
type_t *type, unsigned int *tfsoff)
{
unsigned int start_offset;
unsigned int size;
@ -2755,7 +2789,7 @@ static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfso
}
else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
{
static const expr_t dummy_expr; /* FIXME */
const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
unsigned char fc;
@ -2788,8 +2822,7 @@ static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfso
print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
fc, string_of_type(fc));
*tfsoff += 2;
*tfsoff += write_conf_or_var_desc(file, NULL, *tfsoff, st, &dummy_expr );
*tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
*tfsoff += 2;
print_file(file, 0, "/* %u */\n", *tfsoff);
@ -3014,7 +3047,7 @@ static unsigned int write_type_tfs(FILE *file, int indent,
case TGT_STRUCT:
return write_struct_tfs(file, type, name, typeformat_offset);
case TGT_UNION:
return write_union_tfs(file, type, typeformat_offset);
return write_union_tfs(file, attrs, type, typeformat_offset);
case TGT_ENUM:
case TGT_BASIC:
/* nothing to do */
@ -3085,6 +3118,7 @@ static unsigned int process_tfs_stmts(FILE *file, const statement_list_t *stmts,
STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) )
{
const var_t *func = stmt_func->u.var;
current_func = func;
if (is_local(func->attrs)) continue;
if (!is_void(type_function_get_rettype(func->type)))
@ -4150,20 +4184,46 @@ int write_expr_eval_routines(FILE *file, const char *iface)
LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
{
const char *name = eval->structure->name;
const char *name = eval->name;
result = 1;
print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
iface, name, callback_offset);
print_file(file, 0, "{\n");
if (type_get_type( eval->cont_type ) == TYPE_FUNCTION)
{
const var_list_t *args = type_get_function_args( eval->cont_type );
const var_t *arg;
print_file(file, 1, "struct _PARAM_STRUCT\n" );
print_file(file, 1, "{\n" );
if (is_object( eval->iface )) print_file(file, 2, "%s *This;\n", eval->iface->name );
if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
{
print_file(file, 2, "%s", "");
write_type_left( file, (type_t *)arg->type, TRUE );
if (needs_space_after( arg->type )) fputc( ' ', file );
if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file );
/* FIXME: should check for large args being passed by pointer */
if (is_array( arg->type ) || is_ptr( arg->type ) || type_memsize( arg->type ) == pointer_size)
fprintf( file, "%s;\n", arg->name );
else
fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size );
}
print_file(file, 1, "} *pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop;\n" );
}
else
{
print_file(file, 1, "%s", "");
write_type_left(file, (type_t *)eval->structure, TRUE);
write_type_left(file, (type_t *)eval->cont_type, TRUE);
fprintf(file, " *%s = (", var_name);
write_type_left(file, (type_t *)eval->structure, TRUE);
write_type_left(file, (type_t *)eval->cont_type, TRUE);
fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
}
print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)");
write_expr(file, eval->expr, 1, 1, var_name_expr, eval->structure, "");
write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, "");
fprintf(file, ";\n");
print_file(file, 0, "}\n\n");
callback_offset++;
@ -4182,10 +4242,10 @@ void write_expr_eval_routine_list(FILE *file, const char *iface)
LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
{
const char *name = eval->structure->name;
print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, eval->name, callback_offset);
callback_offset++;
list_remove(&eval->entry);
free(eval->name);
free(eval);
}

View File

@ -136,7 +136,7 @@ int line_number = 1;
static FILE *idfile;
size_t pointer_size = 0;
unsigned int pointer_size = 0;
syskind_t typelib_kind = sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32;
time_t now;

View File

@ -66,7 +66,7 @@ extern char *regscript_name;
extern char *regscript_token;
extern const char *prefix_client;
extern const char *prefix_server;
extern size_t pointer_size;
extern unsigned int pointer_size;
extern time_t now;
extern int line_number;