mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-06 05:30:50 +00:00
widl: Implement callback conformance.
This commit is contained in:
parent
ba0d6bd0f7
commit
b59c995c89
|
@ -295,7 +295,7 @@ static void write_stubdescdecl(type_t *iface)
|
|||
}
|
||||
|
||||
|
||||
static void write_stubdescriptor(type_t *iface)
|
||||
static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
|
||||
{
|
||||
char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
|
||||
|
||||
|
@ -311,7 +311,10 @@ static void write_stubdescriptor(type_t *iface)
|
|||
print_client("&%s__MIDL_AutoBindHandle,\n", iface->name);
|
||||
print_client("0,\n");
|
||||
print_client("0,\n");
|
||||
print_client("0,\n");
|
||||
if (expr_eval_routines)
|
||||
print_client("ExprEvalRoutines,\n");
|
||||
else
|
||||
print_client("0,\n");
|
||||
print_client("0,\n");
|
||||
print_client("__MIDL_TypeFormatString.Format,\n");
|
||||
print_client("1, /* -error bounds_check flag */\n");
|
||||
|
@ -466,6 +469,8 @@ void write_client(ifref_t *ifaces)
|
|||
|
||||
if (iface->iface->funcs)
|
||||
{
|
||||
int expr_eval_routines;
|
||||
|
||||
write_formatstringsdecl(iface->iface);
|
||||
write_implicithandledecl(iface->iface);
|
||||
|
||||
|
@ -474,19 +479,23 @@ void write_client(ifref_t *ifaces)
|
|||
write_bindinghandledecl(iface->iface);
|
||||
|
||||
write_function_stubs(iface->iface);
|
||||
write_stubdescriptor(iface->iface);
|
||||
|
||||
print_client("#if !defined(__RPC_WIN32__)\n");
|
||||
print_client("#error Invalid build platform for this stub.\n");
|
||||
print_client("#endif\n");
|
||||
fprintf(client, "\n");
|
||||
|
||||
write_procformatstring(client, iface->iface);
|
||||
write_typeformatstring(client, iface->iface);
|
||||
|
||||
fprintf(client, "\n");
|
||||
|
||||
expr_eval_routines = write_expr_eval_routines(client, iface->iface->name);
|
||||
if (expr_eval_routines)
|
||||
write_expr_eval_routine_list(client, iface->iface->name);
|
||||
write_stubdescriptor(iface->iface, expr_eval_routines);
|
||||
}
|
||||
|
||||
print_client("#if !defined(__RPC_WIN32__)\n");
|
||||
print_client("#error Invalid build platform for this stub.\n");
|
||||
print_client("#endif\n");
|
||||
fprintf(client, "\n");
|
||||
|
||||
write_procformatstring(client, iface->iface);
|
||||
write_typeformatstring(client, iface->iface);
|
||||
|
||||
fprintf(client, "\n");
|
||||
|
||||
iface = PREV_LINK(iface);
|
||||
}
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ static void write_stubdescdecl(type_t *iface)
|
|||
}
|
||||
|
||||
|
||||
static void write_stubdescriptor(type_t *iface)
|
||||
static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
|
||||
{
|
||||
print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
|
||||
print_server("{\n");
|
||||
|
@ -396,7 +396,10 @@ static void write_stubdescriptor(type_t *iface)
|
|||
print_server("0,\n");
|
||||
print_server("0,\n");
|
||||
print_server("0,\n");
|
||||
print_server("0,\n");
|
||||
if (expr_eval_routines)
|
||||
print_server("ExprEvalRoutines,\n");
|
||||
else
|
||||
print_server("0,\n");
|
||||
print_server("0,\n");
|
||||
print_server("__MIDL_TypeFormatString.Format,\n");
|
||||
print_server("1, /* -error bounds_check flag */\n");
|
||||
|
@ -538,26 +541,32 @@ void write_server(ifref_t *ifaces)
|
|||
|
||||
if (iface->iface->funcs)
|
||||
{
|
||||
int expr_eval_routines;
|
||||
|
||||
write_formatstringsdecl(iface->iface);
|
||||
write_serverinterfacedecl(iface->iface);
|
||||
write_stubdescdecl(iface->iface);
|
||||
|
||||
write_function_stubs(iface->iface);
|
||||
|
||||
write_stubdescriptor(iface->iface);
|
||||
print_server("#if !defined(__RPC_WIN32__)\n");
|
||||
print_server("#error Invalid build platform for this stub.\n");
|
||||
print_server("#endif\n");
|
||||
fprintf(server, "\n");
|
||||
|
||||
write_procformatstring(server, iface->iface);
|
||||
write_typeformatstring(server, iface->iface);
|
||||
|
||||
fprintf(server, "\n");
|
||||
|
||||
expr_eval_routines = write_expr_eval_routines(server, iface->iface->name);
|
||||
if (expr_eval_routines)
|
||||
write_expr_eval_routine_list(server, iface->iface->name);
|
||||
|
||||
write_stubdescriptor(iface->iface, expr_eval_routines);
|
||||
write_dispatchtable(iface->iface);
|
||||
}
|
||||
|
||||
print_server("#if !defined(__RPC_WIN32__)\n");
|
||||
print_server("#error Invalid build platform for this stub.\n");
|
||||
print_server("#endif\n");
|
||||
fprintf(server, "\n");
|
||||
|
||||
write_procformatstring(server, iface->iface);
|
||||
write_typeformatstring(server, iface->iface);
|
||||
|
||||
fprintf(server, "\n");
|
||||
|
||||
iface = PREV_LINK(iface);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,14 +38,29 @@
|
|||
#include "parser.h"
|
||||
#include "header.h"
|
||||
#include "windef.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "widl.h"
|
||||
#include "typegen.h"
|
||||
|
||||
static const func_t *current_func;
|
||||
static const var_t *current_fields;
|
||||
static const type_t *current_structure;
|
||||
|
||||
/* name of the structure variable for structure callbacks */
|
||||
#define STRUCT_EXPR_EVAL_VAR "pS"
|
||||
|
||||
static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
|
||||
|
||||
struct expr_eval_routine
|
||||
{
|
||||
struct list entry;
|
||||
const type_t *structure;
|
||||
size_t structure_size;
|
||||
const expr_t *expr;
|
||||
};
|
||||
|
||||
static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array);
|
||||
static size_t fields_memsize(const var_t *v);
|
||||
|
||||
static int print_file(FILE *file, int indent, const char *format, ...)
|
||||
{
|
||||
|
@ -218,11 +233,12 @@ void write_procformatstring(FILE *file, type_t *iface)
|
|||
}
|
||||
|
||||
/* write conformance / variance descriptor */
|
||||
static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const var_t *fields, const expr_t *expr)
|
||||
static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
|
||||
{
|
||||
unsigned char operator_type = 0;
|
||||
const char *operator_string = "no operators";
|
||||
const expr_t *subexpr = expr;
|
||||
unsigned char correlation_type;
|
||||
|
||||
if (!file) return 4; /* optimisation for sizing pass */
|
||||
|
||||
|
@ -271,17 +287,16 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const var_t
|
|||
|
||||
if (subexpr->type == EXPR_IDENTIFIER)
|
||||
{
|
||||
unsigned char correlation_type;
|
||||
const type_t *correlation_variable = NULL;
|
||||
unsigned char param_type = 0;
|
||||
const char *param_type_string = NULL;
|
||||
size_t offset;
|
||||
|
||||
if (fields)
|
||||
if (structure)
|
||||
{
|
||||
const var_t *var;
|
||||
|
||||
for (offset = 0, var = fields; var; var = NEXT_LINK(var))
|
||||
for (offset = 0, var = structure->fields; var; var = NEXT_LINK(var))
|
||||
{
|
||||
offset -= type_memsize(var->type, var->ptr_level, var->array);
|
||||
if (!strcmp(var->name, subexpr->u.sval))
|
||||
|
@ -365,7 +380,38 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const var_t
|
|||
offset);
|
||||
}
|
||||
else
|
||||
error("write_conf_or_var_desc: expression type %d\n", subexpr->type);
|
||||
{
|
||||
unsigned int callback_offset = 0;
|
||||
struct list *cursor;
|
||||
|
||||
LIST_FOR_EACH(cursor, &expr_eval_routines)
|
||||
callback_offset++;
|
||||
|
||||
if (callback_offset > USHRT_MAX)
|
||||
error("Maximum number of callback routines reached\n");
|
||||
|
||||
if (structure)
|
||||
{
|
||||
struct expr_eval_routine *eval = xmalloc(sizeof(*eval));
|
||||
eval->structure = structure;
|
||||
eval->structure_size = fields_memsize(structure->fields);
|
||||
eval->expr = expr;
|
||||
list_add_tail(&expr_eval_routines, &eval->entry);
|
||||
|
||||
correlation_type = RPC_FC_NORMAL_CONFORMANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("write_conf_or_var_desc: expression type %d\n", subexpr->type);
|
||||
correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
|
||||
}
|
||||
|
||||
print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
|
||||
correlation_type,
|
||||
correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
|
||||
print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
|
||||
print_file(file, 2, "NdrShort(0x%x), /* %u */\n", callback_offset, callback_offset);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
@ -589,7 +635,7 @@ static size_t write_array_tfs(FILE *file, const attr_t *attrs,
|
|||
typestring_size += 2;
|
||||
|
||||
typestring_size += write_conf_or_var_desc(file, current_func,
|
||||
current_fields,
|
||||
current_structure,
|
||||
length_is);
|
||||
|
||||
/* FIXME: write out pointer descriptor if necessary */
|
||||
|
@ -614,7 +660,7 @@ static size_t write_array_tfs(FILE *file, const attr_t *attrs,
|
|||
typestring_size = 4;
|
||||
|
||||
typestring_size += write_conf_or_var_desc(file, current_func,
|
||||
current_fields, size_is);
|
||||
current_structure, size_is);
|
||||
|
||||
/* FIXME: write out pointer descriptor if necessary */
|
||||
|
||||
|
@ -638,9 +684,9 @@ static size_t write_array_tfs(FILE *file, const attr_t *attrs,
|
|||
typestring_size = 4;
|
||||
|
||||
typestring_size += write_conf_or_var_desc(file, current_func,
|
||||
current_fields, size_is);
|
||||
current_structure, size_is);
|
||||
typestring_size += write_conf_or_var_desc(file, current_func,
|
||||
current_fields,
|
||||
current_structure,
|
||||
length_is);
|
||||
|
||||
/* FIXME: write out pointer descriptor if necessary */
|
||||
|
@ -714,12 +760,10 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, const char *name)
|
|||
typestring_size = 7;
|
||||
|
||||
array = find_array_or_string_in_struct(type);
|
||||
/* assumes array points to the start of the linked list, which is true
|
||||
* if the array is the last member of the struct */
|
||||
current_fields = array;
|
||||
current_structure = type;
|
||||
typestring_size += write_array_tfs(file, array->attrs, array->type,
|
||||
array->array, array->name);
|
||||
current_fields = NULL;
|
||||
current_structure = NULL;
|
||||
|
||||
return typestring_size;
|
||||
case RPC_FC_CVSTRUCT:
|
||||
|
@ -740,16 +784,14 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, const char *name)
|
|||
typestring_size = 7;
|
||||
|
||||
array = find_array_or_string_in_struct(type);
|
||||
/* assumes array points to the start of the linked list, which is true
|
||||
* if the array is the last member of the struct */
|
||||
current_fields = array;
|
||||
current_structure = type;
|
||||
if (is_attr(array->attrs, ATTR_STRING))
|
||||
typestring_size += write_string_tfs(file, array->attrs, array->type,
|
||||
array->array, array->name);
|
||||
else
|
||||
typestring_size += write_array_tfs(file, array->attrs, array->type,
|
||||
array->array, array->name);
|
||||
current_fields = NULL;
|
||||
current_structure = NULL;
|
||||
|
||||
return typestring_size;
|
||||
default:
|
||||
|
@ -1118,7 +1160,7 @@ void marshall_arguments(FILE *file, int indent, func_t *func,
|
|||
fprintf(file, " *)_StubMsg.Buffer = ");
|
||||
write_name(file, var);
|
||||
fprintf(file, ";\n");
|
||||
fprintf(file, "_StubMsg.Buffer += sizeof(");
|
||||
print_file(file, indent, "_StubMsg.Buffer += sizeof(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, ");\n");
|
||||
|
||||
|
@ -1289,7 +1331,7 @@ void unmarshall_arguments(FILE *file, int indent, func_t *func,
|
|||
fprintf(file, " = *(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, " *)_StubMsg.Buffer;\n");
|
||||
fprintf(file, "_StubMsg.Buffer += sizeof(");
|
||||
print_file(file, indent, "_StubMsg.Buffer += sizeof(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, ");\n");
|
||||
|
||||
|
@ -1348,3 +1390,138 @@ size_t get_size_typeformatstring_var(const var_t *var)
|
|||
{
|
||||
return write_typeformatstring_var(NULL, 0, var);
|
||||
}
|
||||
|
||||
static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
|
||||
const var_t *fields, const char *structvar)
|
||||
{
|
||||
switch (e->type) {
|
||||
case EXPR_VOID:
|
||||
break;
|
||||
case EXPR_NUM:
|
||||
fprintf(h, "%ld", e->u.lval);
|
||||
break;
|
||||
case EXPR_HEXNUM:
|
||||
fprintf(h, "0x%lx", e->u.lval);
|
||||
break;
|
||||
case EXPR_IDENTIFIER:
|
||||
{
|
||||
const var_t *field;
|
||||
for (field = fields; field; field = NEXT_LINK(field))
|
||||
{
|
||||
if (!strcmp(e->u.sval, field->name))
|
||||
{
|
||||
fprintf(h, "%s->%s", structvar, e->u.sval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!field) error("no field found for identifier %s\n", e->u.sval);
|
||||
break;
|
||||
}
|
||||
case EXPR_NEG:
|
||||
fprintf(h, "-");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
break;
|
||||
case EXPR_NOT:
|
||||
fprintf(h, "~");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
break;
|
||||
case EXPR_PPTR:
|
||||
fprintf(h, "*");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
break;
|
||||
case EXPR_CAST:
|
||||
fprintf(h, "(");
|
||||
write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
|
||||
fprintf(h, ")");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
break;
|
||||
case EXPR_SIZEOF:
|
||||
fprintf(h, "sizeof(");
|
||||
write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
|
||||
fprintf(h, ")");
|
||||
break;
|
||||
case EXPR_SHL:
|
||||
case EXPR_SHR:
|
||||
case EXPR_MUL:
|
||||
case EXPR_DIV:
|
||||
case EXPR_ADD:
|
||||
case EXPR_SUB:
|
||||
case EXPR_AND:
|
||||
case EXPR_OR:
|
||||
if (brackets) fprintf(h, "(");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
switch (e->type) {
|
||||
case EXPR_SHL: fprintf(h, " << "); break;
|
||||
case EXPR_SHR: fprintf(h, " >> "); break;
|
||||
case EXPR_MUL: fprintf(h, " * "); break;
|
||||
case EXPR_DIV: fprintf(h, " / "); break;
|
||||
case EXPR_ADD: fprintf(h, " + "); break;
|
||||
case EXPR_SUB: fprintf(h, " - "); break;
|
||||
case EXPR_AND: fprintf(h, " & "); break;
|
||||
case EXPR_OR: fprintf(h, " | "); break;
|
||||
default: break;
|
||||
}
|
||||
write_struct_expr(h, e->u.ext, 1, fields, structvar);
|
||||
if (brackets) fprintf(h, ")");
|
||||
break;
|
||||
case EXPR_COND:
|
||||
if (brackets) fprintf(h, "(");
|
||||
write_struct_expr(h, e->ref, 1, fields, structvar);
|
||||
fprintf(h, " ? ");
|
||||
write_struct_expr(h, e->u.ext, 1, fields, structvar);
|
||||
fprintf(h, " : ");
|
||||
write_struct_expr(h, e->ext2, 1, fields, structvar);
|
||||
if (brackets) fprintf(h, ")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int write_expr_eval_routines(FILE *file, const char *iface)
|
||||
{
|
||||
int result = 0;
|
||||
struct expr_eval_routine *eval;
|
||||
unsigned short callback_offset = 0;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
|
||||
{
|
||||
int indent = 0;
|
||||
result = 1;
|
||||
print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
|
||||
iface, eval->structure->name, callback_offset);
|
||||
print_file(file, indent, "{\n");
|
||||
indent++;
|
||||
print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
|
||||
eval->structure->name, eval->structure->name, eval->structure_size);
|
||||
fprintf(file, "\n");
|
||||
print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
|
||||
print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
|
||||
write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
|
||||
fprintf(file, ";\n");
|
||||
indent--;
|
||||
print_file(file, indent, "}\n\n");
|
||||
callback_offset++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void write_expr_eval_routine_list(FILE *file, const char *iface)
|
||||
{
|
||||
struct expr_eval_routine *eval;
|
||||
struct expr_eval_routine *cursor;
|
||||
unsigned short callback_offset = 0;
|
||||
|
||||
fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
|
||||
fprintf(file, "{\n");
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
|
||||
{
|
||||
print_file(file, 1, "%s_%sExprEval_%04u,\n",
|
||||
iface, eval->structure->name, callback_offset);
|
||||
|
||||
callback_offset++;
|
||||
list_remove(&eval->entry);
|
||||
free(eval);
|
||||
}
|
||||
|
||||
fprintf(file, "};\n\n");
|
||||
}
|
||||
|
|
|
@ -34,3 +34,5 @@ void marshall_arguments(FILE *file, int indent, func_t *func, unsigned int *type
|
|||
void unmarshall_arguments(FILE *file, int indent, func_t *func, unsigned int *type_offset, enum pass pass);
|
||||
size_t get_size_procformatstring_var(const var_t *var);
|
||||
size_t get_size_typeformatstring_var(const var_t *var);
|
||||
int write_expr_eval_routines(FILE *file, const char *iface);
|
||||
void write_expr_eval_routine_list(FILE *file, const char *iface);
|
||||
|
|
Loading…
Reference in a new issue