widl: Add typegen_detect_type and use it.

Add typegen_detect_type for detecting types useful during
client/server/proxy code generation.
This commit is contained in:
Rob Shearman 2009-02-23 13:48:46 +00:00 committed by Alexandre Julliard
parent af0800729b
commit 2c6e611c8a
4 changed files with 442 additions and 358 deletions

View File

@ -2342,8 +2342,7 @@ static void check_field_common(const type_t *container_type,
const char *container_name, const var_t *arg) const char *container_name, const var_t *arg)
{ {
type_t *type = arg->type; type_t *type = arg->type;
int is_wire_marshal = 0; int more_to_do;
int is_context_handle = 0;
const char *container_type_name = NULL; const char *container_type_name = NULL;
switch (type_get_type_detect_alias(type)) switch (type_get_type_detect_alias(type))
@ -2410,35 +2409,56 @@ static void check_field_common(const type_t *container_type,
} }
} }
/* get fundamental type for the argument */ do
for (;;)
{ {
if (is_attr(type->attrs, ATTR_WIREMARSHAL)) more_to_do = FALSE;
{
is_wire_marshal = 1;
break;
}
if (is_attr(type->attrs, ATTR_CONTEXTHANDLE))
{
is_context_handle = 1;
break;
}
if (type_is_alias(type))
type = type_alias_get_aliasee(type);
else if (is_ptr(type))
type = type_pointer_get_ref(type);
else if (is_array(type))
type = type_array_get_element(type);
else
break;
}
if (type_get_type(type) == TYPE_VOID && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle) switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot derive from void *\n", arg->name, container_type_name, container_name); {
else if (type_get_type(type) == TYPE_FUNCTION) case TGT_STRUCT:
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot be a function pointer\n", arg->name, container_type_name, container_name); case TGT_UNION:
else if (!is_wire_marshal && (type_get_type(type) == TYPE_STRUCT || type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION)) check_remoting_fields(arg, type);
check_remoting_fields(arg, type); break;
case TGT_INVALID:
switch (type_get_type(type))
{
case TYPE_VOID:
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot derive from void *\n",
arg->name, container_type_name, container_name);
break;
case TYPE_FUNCTION:
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot be a function pointer\n",
arg->name, container_type_name, container_name);
break;
case TYPE_COCLASS:
case TYPE_INTERFACE:
case TYPE_MODULE:
/* FIXME */
break;
default:
break;
}
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
/* FIXME */
break;
case TGT_POINTER:
type = type_pointer_get_ref(type);
more_to_do = TRUE;
break;
case TGT_ARRAY:
type = type_array_get_element(type);
more_to_do = TRUE;
break;
case TGT_USER_TYPE:
case TGT_STRING:
case TGT_IFACE_POINTER:
case TGT_BASIC:
case TGT_ENUM:
/* nothing to do */
break;
}
} while (more_to_do);
} }
static void check_remoting_fields(const var_t *var, type_t *type) static void check_remoting_fields(const var_t *var, type_t *type)
@ -2475,36 +2495,37 @@ static void check_remoting_args(const var_t *func)
if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry ) if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry )
{ {
int ptr_level = 0;
const type_t *type = arg->type; const type_t *type = arg->type;
/* get pointer level and fundamental type for the argument */
for (;;)
{
if (is_attr(type->attrs, ATTR_WIREMARSHAL))
break;
if (is_attr(type->attrs, ATTR_CONTEXTHANDLE))
break;
if (type_is_alias(type))
type = type_alias_get_aliasee(type);
else if (is_ptr(type))
{
ptr_level++;
type = type_pointer_get_ref(type);
}
else
break;
}
/* check that [out] parameters have enough pointer levels */ /* check that [out] parameters have enough pointer levels */
if (is_attr(arg->attrs, ATTR_OUT)) if (is_attr(arg->attrs, ATTR_OUT))
{ {
if (!is_array(type)) switch (typegen_detect_type(type, arg->attrs, TDT_ALL_TYPES))
{ {
if (!ptr_level) case TGT_BASIC:
error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname); case TGT_ENUM:
if (type_get_type(type) == TYPE_INTERFACE && ptr_level == 1) case TGT_STRUCT:
error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname); case TGT_UNION:
case TGT_CTXT_HANDLE:
case TGT_USER_TYPE:
error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname);
break;
case TGT_IFACE_POINTER:
error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname);
break;
case TGT_STRING:
if (!is_array(type))
{
/* FIXME */
}
break;
case TGT_INVALID:
/* already error'd before we get here */
case TGT_CTXT_HANDLE_POINTER:
case TGT_POINTER:
case TGT_ARRAY:
/* OK */
break;
} }
} }

View File

@ -153,17 +153,20 @@ int is_var_ptr(const var_t *v)
int cant_be_null(const var_t *v) int cant_be_null(const var_t *v)
{ {
const type_t *type = v->type; switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS))
{
case TGT_ARRAY:
/* FIXME: work out pointer type */
return 0;
case TGT_IFACE_POINTER: /* FIXME */
case TGT_POINTER:
return (get_pointer_fc(v->type) == RPC_FC_RP);
case TGT_CTXT_HANDLE_POINTER:
return TRUE;
default:
return 0;
}
/* context handles have their own checking so they can be null for the
* purposes of null ref pointer checking */
if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE))
return 0;
if (is_user_type(type))
return 0;
return (get_pointer_fc(type) == RPC_FC_RP);
} }
static int need_delegation(const type_t *iface) static int need_delegation(const type_t *iface)
@ -225,28 +228,29 @@ static void free_variable( const var_t *arg, const char *local_var_prefix )
return; return;
} }
switch (type_get_type(type)) switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
{ {
case TYPE_ENUM: case TGT_ENUM:
case TYPE_BASIC: case TGT_BASIC:
break; break;
case TYPE_STRUCT: case TGT_STRUCT:
if (get_struct_fc(type) != RPC_FC_STRUCT) if (get_struct_fc(type) != RPC_FC_STRUCT)
print_proxy("/* FIXME: %s code for %s type %d missing */\n", __FUNCTION__, arg->name, type_get_type(type) ); print_proxy("/* FIXME: %s code for %s struct type 0x%x missing */\n", __FUNCTION__, arg->name, get_struct_fc(type) );
break; break;
case TYPE_POINTER: case TGT_IFACE_POINTER:
case TYPE_INTERFACE: iid = get_attrp( arg->attrs, ATTR_IIDIS );
if (type_get_type(type) == TYPE_INTERFACE || get_pointer_fc(type) == RPC_FC_FP) if( iid )
{
print_proxy( "__frame->_StubMsg.MaxCount = (ULONG_PTR) " );
write_expr(proxy, iid, 1, 1, NULL, NULL, local_var_prefix);
print_proxy( ";\n\n" );
}
/* fall through */
case TGT_POINTER:
if (get_pointer_fc(type) == RPC_FC_FP)
{ {
iid = get_attrp( arg->attrs, ATTR_IIDIS );
if( iid )
{
print_proxy( "__frame->_StubMsg.MaxCount = (ULONG_PTR) " );
write_expr(proxy, iid, 1, 1, NULL, NULL, local_var_prefix);
print_proxy( ";\n\n" );
}
print_proxy( "NdrClearOutParameters( &__frame->_StubMsg, "); print_proxy( "NdrClearOutParameters( &__frame->_StubMsg, ");
fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset ); fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
fprintf(proxy, "(void*)%s );\n", arg->name ); fprintf(proxy, "(void*)%s );\n", arg->name );

View File

@ -138,6 +138,49 @@ static unsigned char get_enum_fc(const type_t *type)
return RPC_FC_ENUM16; return RPC_FC_ENUM16;
} }
enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags)
{
if (is_user_type(type))
return TGT_USER_TYPE;
if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE))
return TGT_CTXT_HANDLE;
if (!(flags & TDT_IGNORE_STRINGS) && is_string_type(attrs, type))
return TGT_STRING;
switch (type_get_type(type))
{
case TYPE_BASIC:
return TGT_BASIC;
case TYPE_ENUM:
return TGT_ENUM;
case TYPE_POINTER:
if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE ||
(type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS)))
return TGT_IFACE_POINTER;
else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE))
return TGT_CTXT_HANDLE_POINTER;
else
return TGT_POINTER;
case TYPE_STRUCT:
return TGT_STRUCT;
case TYPE_ENCAPSULATED_UNION:
case TYPE_UNION:
return TGT_UNION;
case TYPE_ARRAY:
return TGT_ARRAY;
case TYPE_FUNCTION:
case TYPE_COCLASS:
case TYPE_INTERFACE:
case TYPE_MODULE:
case TYPE_VOID:
case TYPE_ALIAS:
break;
}
return TGT_INVALID;
}
unsigned char get_struct_fc(const type_t *type) unsigned char get_struct_fc(const type_t *type)
{ {
int has_pointer = 0; int has_pointer = 0;
@ -154,11 +197,11 @@ unsigned char get_struct_fc(const type_t *type)
if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
{ {
type_t *t = field->type; type_t *t = field->type;
enum typegen_type typegen_type;
if (is_user_type(t)) typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
return RPC_FC_BOGUS_STRUCT;
if (t->declarray) if (typegen_type == TGT_ARRAY && t->declarray)
{ {
if (is_string_type(field->attrs, field->type)) if (is_string_type(field->attrs, field->type))
{ {
@ -182,32 +225,26 @@ unsigned char get_struct_fc(const type_t *type)
has_variance = 1; has_variance = 1;
t = type_array_get_element(t); t = type_array_get_element(t);
typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
} }
if (is_user_type(t)) switch (typegen_type)
return RPC_FC_BOGUS_STRUCT;
switch (type_get_type(t))
{ {
case TYPE_VOID: case TGT_USER_TYPE:
case TYPE_ALIAS: case TGT_IFACE_POINTER:
case TYPE_MODULE: return RPC_FC_BOGUS_STRUCT;
assert(0); case TGT_BASIC:
break; break;
case TYPE_BASIC: case TGT_ENUM:
break;
case TYPE_ENUM:
if (get_enum_fc(t) == RPC_FC_ENUM16) if (get_enum_fc(t) == RPC_FC_ENUM16)
return RPC_FC_BOGUS_STRUCT; return RPC_FC_BOGUS_STRUCT;
break; break;
case TYPE_POINTER: case TGT_POINTER:
if (get_pointer_fc(t) == RPC_FC_RP || pointer_size != 4) if (get_pointer_fc(t) == RPC_FC_RP || pointer_size != 4)
return RPC_FC_BOGUS_STRUCT; return RPC_FC_BOGUS_STRUCT;
if (type_get_type(type_pointer_get_ref(t)) == TYPE_INTERFACE)
return RPC_FC_BOGUS_STRUCT;
has_pointer = 1; has_pointer = 1;
break; break;
case TYPE_ARRAY: case TGT_ARRAY:
{ {
unsigned int ptr_type = get_attrv(field->attrs, ATTR_POINTERTYPE); unsigned int ptr_type = get_attrv(field->attrs, ATTR_POINTERTYPE);
if (!ptr_type || ptr_type == RPC_FC_RP) if (!ptr_type || ptr_type == RPC_FC_RP)
@ -217,13 +254,9 @@ unsigned char get_struct_fc(const type_t *type)
has_pointer = 1; has_pointer = 1;
break; break;
} }
case TYPE_INTERFACE: case TGT_UNION:
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TYPE_COCLASS:
case TYPE_FUNCTION:
return RPC_FC_BOGUS_STRUCT; return RPC_FC_BOGUS_STRUCT;
case TYPE_STRUCT: case TGT_STRUCT:
{ {
unsigned char fc = get_struct_fc(t); unsigned char fc = get_struct_fc(t);
switch (fc) switch (fc)
@ -265,6 +298,14 @@ unsigned char get_struct_fc(const type_t *type)
} }
break; break;
} }
case TGT_STRING:
/* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */
case TGT_INVALID:
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
/* checking after parsing should mean that we don't get here. if we do,
* it's a checker bug */
assert(0);
} }
} }
@ -315,11 +356,12 @@ unsigned char get_array_fc(const type_t *type)
fc = RPC_FC_CVARRAY; fc = RPC_FC_CVARRAY;
} }
if (is_user_type(elem_type)) switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS))
fc = RPC_FC_BOGUS_ARRAY;
else switch (type_get_type(elem_type))
{ {
case TYPE_STRUCT: case TGT_USER_TYPE:
fc = RPC_FC_BOGUS_ARRAY;
break;
case TGT_STRUCT:
switch (get_struct_fc(elem_type)) switch (get_struct_fc(elem_type))
{ {
case RPC_FC_BOGUS_STRUCT: case RPC_FC_BOGUS_STRUCT:
@ -327,25 +369,29 @@ unsigned char get_array_fc(const type_t *type)
break; break;
} }
break; break;
case TYPE_ENUM: case TGT_ENUM:
/* is 16-bit enum - if so, wire size differs from mem size and so /* is 16-bit enum - if so, wire size differs from mem size and so
* the array cannot be block copied, which means the array is complex */ * the array cannot be block copied, which means the array is complex */
if (get_enum_fc(elem_type) == RPC_FC_ENUM16) if (get_enum_fc(elem_type) == RPC_FC_ENUM16)
fc = RPC_FC_BOGUS_ARRAY; fc = RPC_FC_BOGUS_ARRAY;
break; break;
case TYPE_UNION: case TGT_UNION:
case TYPE_ENCAPSULATED_UNION: case TGT_IFACE_POINTER:
fc = RPC_FC_BOGUS_ARRAY; fc = RPC_FC_BOGUS_ARRAY;
break; break;
case TYPE_POINTER: case TGT_POINTER:
/* ref pointers cannot just be block copied. unique pointers to /* ref pointers cannot just be block copied. unique pointers to
* interfaces need special treatment. either case means the array is * interfaces need special treatment. either case means the array is
* complex */ * complex */
if (get_pointer_fc(elem_type) == RPC_FC_RP || if (get_pointer_fc(elem_type) == RPC_FC_RP)
type_get_type(type_pointer_get_ref(elem_type)) == TYPE_INTERFACE)
fc = RPC_FC_BOGUS_ARRAY; fc = RPC_FC_BOGUS_ARRAY;
break; break;
default: case TGT_BASIC:
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_STRING:
case TGT_INVALID:
case TGT_ARRAY:
/* nothing to do for everything else */ /* nothing to do for everything else */
break; break;
} }
@ -377,16 +423,16 @@ static int is_non_complex_struct(const type_t *type)
static int type_has_pointers(const type_t *type) static int type_has_pointers(const type_t *type)
{ {
if (is_user_type(type)) switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
return FALSE;
switch (type_get_type(type))
{ {
case TYPE_POINTER: case TGT_USER_TYPE:
return FALSE;
case TGT_POINTER:
return TRUE; return TRUE;
case TYPE_ARRAY: case TGT_ARRAY:
/* FIXME: array can be pointer */
return type_has_pointers(type_array_get_element(type)); return type_has_pointers(type_array_get_element(type));
case TYPE_STRUCT: case TGT_STRUCT:
{ {
var_list_t *fields = type_struct_get_fields(type); var_list_t *fields = type_struct_get_fields(type);
const var_t *field; const var_t *field;
@ -397,8 +443,7 @@ static int type_has_pointers(const type_t *type)
} }
break; break;
} }
case TYPE_UNION: case TGT_UNION:
case TYPE_ENCAPSULATED_UNION:
{ {
var_list_t *fields; var_list_t *fields;
const var_t *field; const var_t *field;
@ -410,7 +455,13 @@ static int type_has_pointers(const type_t *type)
} }
break; break;
} }
default: case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_STRING:
case TGT_IFACE_POINTER:
case TGT_BASIC:
case TGT_ENUM:
case TGT_INVALID:
break; break;
} }
@ -419,19 +470,19 @@ static int type_has_pointers(const type_t *type)
static int type_has_full_pointer(const type_t *type) static int type_has_full_pointer(const type_t *type)
{ {
if (is_user_type(type)) switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
return FALSE;
switch (type_get_type(type))
{ {
case TYPE_POINTER: case TGT_USER_TYPE:
return FALSE;
case TGT_POINTER:
if (get_pointer_fc(type) == RPC_FC_FP) if (get_pointer_fc(type) == RPC_FC_FP)
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
case TYPE_ARRAY: case TGT_ARRAY:
/* FIXME: array can be full pointer */
return type_has_full_pointer(type_array_get_element(type)); return type_has_full_pointer(type_array_get_element(type));
case TYPE_STRUCT: case TGT_STRUCT:
{ {
var_list_t *fields = type_struct_get_fields(type); var_list_t *fields = type_struct_get_fields(type);
const var_t *field; const var_t *field;
@ -442,8 +493,7 @@ static int type_has_full_pointer(const type_t *type)
} }
break; break;
} }
case TYPE_UNION: case TGT_UNION:
case TYPE_ENCAPSULATED_UNION:
{ {
var_list_t *fields; var_list_t *fields;
const var_t *field; const var_t *field;
@ -455,7 +505,13 @@ static int type_has_full_pointer(const type_t *type)
} }
break; break;
} }
default: case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_STRING:
case TGT_IFACE_POINTER:
case TGT_BASIC:
case TGT_ENUM:
case TGT_INVALID:
break; break;
} }
@ -519,18 +575,14 @@ int is_user_type(const type_t *t)
static int is_embedded_complex(const type_t *type) static int is_embedded_complex(const type_t *type)
{ {
if (is_user_type(type)) switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES))
return TRUE;
switch (type_get_type(type))
{ {
case TYPE_STRUCT: case TGT_USER_TYPE:
case TYPE_UNION: case TGT_STRUCT:
case TYPE_ENCAPSULATED_UNION: case TGT_UNION:
case TYPE_ARRAY: case TGT_ARRAY:
case TGT_IFACE_POINTER:
return TRUE; return TRUE;
case TYPE_POINTER:
return type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE;
default: default:
return FALSE; return FALSE;
} }
@ -2567,19 +2619,17 @@ static unsigned int write_typeformatstring_var(FILE *file, int indent, const var
{ {
unsigned int offset; unsigned int offset;
if (is_context_handle(type)) switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES))
return write_contexthandle_tfs(file, type, var, typeformat_offset);
if (is_user_type(type))
{ {
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
return write_contexthandle_tfs(file, type, var, typeformat_offset);
case TGT_USER_TYPE:
write_user_tfs(file, type, typeformat_offset); write_user_tfs(file, type, typeformat_offset);
return type->typestring_offset; return type->typestring_offset;
} case TGT_STRING:
if (is_string_type(var->attrs, type))
return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset); return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
case TGT_ARRAY:
if (is_array(type))
{ {
int ptr_type; int ptr_type;
unsigned int off; unsigned int off;
@ -2607,75 +2657,68 @@ static unsigned int write_typeformatstring_var(FILE *file, int indent, const var
} }
return off; return off;
} }
case TGT_STRUCT:
if (!is_ptr(type)) if (processed(type)) return type->typestring_offset;
{ return write_struct_tfs(file, type, var->name, typeformat_offset);
switch (type_get_type(type)) case TGT_UNION:
if (processed(type)) return type->typestring_offset;
return write_union_tfs(file, type, typeformat_offset);
case TGT_ENUM:
case TGT_BASIC:
/* nothing to do */
return 0;
case TGT_IFACE_POINTER:
return write_ip_tfs(file, var->attrs, type, typeformat_offset);
case TGT_POINTER:
if (last_ptr(type))
{ {
case TYPE_STRUCT: size_t start_offset = *typeformat_offset;
if (processed(type)) return type->typestring_offset; int in_attr = is_attr(var->attrs, ATTR_IN);
return write_struct_tfs(file, type, var->name, typeformat_offset); int out_attr = is_attr(var->attrs, ATTR_OUT);
case TYPE_UNION: const type_t *ref = type_pointer_get_ref(type);
case TYPE_ENCAPSULATED_UNION:
if (processed(type)) return type->typestring_offset; switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
return write_union_tfs(file, type, typeformat_offset); {
case TYPE_ENUM: /* special case for pointers to base types */
case TYPE_BASIC: case TGT_BASIC:
/* nothing to do */ case TGT_ENUM:
return 0; {
default: unsigned char fc;
error("write_typeformatstring_var: Unsupported type %d for variable %s\n",
type_get_type(type), var->name); if (type_get_type(ref) == TYPE_ENUM)
fc = get_enum_fc(ref);
else
fc = type_basic_get_fc(ref);
print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
get_pointer_fc(type),
(!in_attr && out_attr) ? 0x0C : 0x08,
string_of_type(get_pointer_fc(type)),
(!in_attr && out_attr) ? "[allocated_on_stack] " : "");
print_file(file, indent, "0x%02x, /* %s */\n",
fc, string_of_type(fc));
print_file(file, indent, "0x5c, /* FC_PAD */\n");
*typeformat_offset += 4;
return start_offset;
}
default:
break;
}
} }
offset = write_typeformatstring_var(file, indent, func,
type_pointer_get_ref(type), var,
typeformat_offset);
if (file)
fprintf(file, "/* %2u */\n", *typeformat_offset);
return write_pointer_only_tfs(file, var->attrs, get_pointer_fc(type),
!last_ptr(type) ? 0x10 : 0,
offset, typeformat_offset);
case TGT_INVALID:
break;
} }
else if (last_ptr(type)) error("invalid type %s for var %s\n", type->name, var->name);
{ return 0;
unsigned int start_offset = *typeformat_offset;
int in_attr = is_attr(var->attrs, ATTR_IN);
int out_attr = is_attr(var->attrs, ATTR_OUT);
const type_t *ref = type_pointer_get_ref(type);
if (type_get_type(ref) == TYPE_INTERFACE
|| (type_get_type(ref) == TYPE_VOID
&& is_attr(var->attrs, ATTR_IIDIS)))
{
return write_ip_tfs(file, var->attrs, type, typeformat_offset);
}
/* special case for pointers to base types */
if (type_get_type(ref) == TYPE_BASIC ||
type_get_type(ref) == TYPE_ENUM)
{
unsigned char fc;
if (type_get_type(ref) == TYPE_ENUM)
fc = get_enum_fc(ref);
else
fc = type_basic_get_fc(ref);
print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
get_pointer_fc(type),
(!in_attr && out_attr) ? 0x0C : 0x08,
string_of_type(get_pointer_fc(type)),
(!in_attr && out_attr) ? "[allocated_on_stack] " : "");
print_file(file, indent, "0x%02x, /* %s */\n",
fc, string_of_type(fc));
print_file(file, indent, "0x5c, /* FC_PAD */\n");
*typeformat_offset += 4;
return start_offset;
}
}
assert(is_ptr(type));
offset = write_typeformatstring_var(file, indent, func,
type_pointer_get_ref(type), var,
typeformat_offset);
if (file)
fprintf(file, "/* %2u */\n", *typeformat_offset);
return write_pointer_only_tfs(file, var->attrs, get_pointer_fc(type),
!last_ptr(type) ? 0x10 : 0,
offset, typeformat_offset);
} }
static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
@ -2683,39 +2726,31 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty
{ {
int retmask = 0; int retmask = 0;
if (is_user_type(type)) switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
{ {
case TGT_USER_TYPE:
write_user_tfs(file, type, tfsoff); write_user_tfs(file, type, tfsoff);
} break;
else if (is_string_type(attrs, type)) case TGT_STRING:
{
write_string_tfs(file, attrs, type, name, tfsoff); write_string_tfs(file, attrs, type, name, tfsoff);
} break;
else switch (type_get_type(type)) case TGT_IFACE_POINTER:
{ write_ip_tfs(file, attrs, type, tfsoff);
case TYPE_POINTER: break;
case TGT_POINTER:
{ {
type_t *ref = type_pointer_get_ref(type); type_t *ref = type_pointer_get_ref(type);
if (type_get_type(ref) == TYPE_INTERFACE if (!processed(ref) && type_get_type(ref) != TYPE_BASIC)
|| (type_get_type(ref) == TYPE_VOID retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
&& is_attr(attrs, ATTR_IIDIS)))
{
write_ip_tfs(file, attrs, type, tfsoff);
}
else
{
if (!processed(ref) && type_get_type(ref) != TYPE_BASIC)
retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
if (write_ptr) if (write_ptr)
write_pointer_tfs(file, type, tfsoff); write_pointer_tfs(file, type, tfsoff);
retmask |= 1; retmask |= 1;
}
break; break;
} }
case TYPE_ARRAY: case TGT_ARRAY:
/* conformant arrays and strings are handled specially */ /* conformant arrays and strings are handled specially */
if (!type->declarray || !is_conformant_array(type)) if (!type->declarray || !is_conformant_array(type))
{ {
@ -2724,26 +2759,23 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty
retmask |= 1; retmask |= 1;
} }
break; break;
case TYPE_STRUCT: case TGT_STRUCT:
if (!processed(type)) if (!processed(type))
write_struct_tfs(file, type, name, tfsoff); write_struct_tfs(file, type, name, tfsoff);
break; break;
case TYPE_UNION: case TGT_UNION:
case TYPE_ENCAPSULATED_UNION:
if (!processed(type)) if (!processed(type))
write_union_tfs(file, type, tfsoff); write_union_tfs(file, type, tfsoff);
break; break;
case TYPE_ENUM: case TGT_ENUM:
case TYPE_BASIC: case TGT_BASIC:
/* nothing to do */ /* nothing to do */
break; break;
case TYPE_VOID: case TGT_CTXT_HANDLE:
case TYPE_ALIAS: case TGT_CTXT_HANDLE_POINTER:
case TYPE_MODULE: case TGT_INVALID:
case TYPE_COCLASS: error("invalid type %s for var %s\n", type->name, name);
case TYPE_FUNCTION: break;
case TYPE_INTERFACE:
assert(0);
} }
return retmask; return retmask;
@ -2839,95 +2871,108 @@ void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred
static unsigned int get_required_buffer_size_type( static unsigned int get_required_buffer_size_type(
const type_t *type, const char *name, unsigned int *alignment) const type_t *type, const char *name, unsigned int *alignment)
{ {
const char *uname;
const type_t *utype;
*alignment = 0; *alignment = 0;
if ((utype = get_user_type(type, &uname))) switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
{ {
case TGT_USER_TYPE:
{
const char *uname;
const type_t *utype = get_user_type(type, &uname);
return get_required_buffer_size_type(utype, uname, alignment); return get_required_buffer_size_type(utype, uname, alignment);
} }
else case TGT_BASIC:
{ switch (type_basic_get_fc(type))
switch (type_get_type(type))
{ {
case TYPE_BASIC: case RPC_FC_BYTE:
switch (type_basic_get_fc(type)) case RPC_FC_CHAR:
{ case RPC_FC_USMALL:
case RPC_FC_BYTE: case RPC_FC_SMALL:
case RPC_FC_CHAR: *alignment = 4;
case RPC_FC_USMALL: return 1;
case RPC_FC_SMALL:
*alignment = 4;
return 1;
case RPC_FC_WCHAR: case RPC_FC_WCHAR:
case RPC_FC_USHORT: case RPC_FC_USHORT:
case RPC_FC_SHORT: case RPC_FC_SHORT:
*alignment = 4; *alignment = 4;
return 2; return 2;
case RPC_FC_ULONG: case RPC_FC_ULONG:
case RPC_FC_LONG: case RPC_FC_LONG:
case RPC_FC_FLOAT: case RPC_FC_FLOAT:
case RPC_FC_ERROR_STATUS_T: case RPC_FC_ERROR_STATUS_T:
*alignment = 4; *alignment = 4;
return 4; return 4;
case RPC_FC_HYPER: case RPC_FC_HYPER:
case RPC_FC_DOUBLE: case RPC_FC_DOUBLE:
*alignment = 8; *alignment = 8;
return 8; return 8;
case RPC_FC_IGNORE: case RPC_FC_IGNORE:
case RPC_FC_BIND_PRIMITIVE: case RPC_FC_BIND_PRIMITIVE:
return 0; return 0;
default:
error("get_required_buffer_size: unknown basic type 0x%02x\n",
type_basic_get_fc(type));
return 0;
}
break;
case TYPE_ENUM:
switch (get_enum_fc(type))
{
case RPC_FC_ENUM32:
*alignment = 4;
return 4;
case RPC_FC_ENUM16:
*alignment = 4;
return 2;
}
break;
case TYPE_STRUCT:
if (get_struct_fc(type) == RPC_FC_STRUCT)
{
if (!type_struct_get_fields(type)) return 0;
return fields_memsize(type_struct_get_fields(type), alignment);
}
break;
case TYPE_POINTER:
if (get_pointer_fc(type) == RPC_FC_RP)
{
const type_t *ref = type_pointer_get_ref(type);
return (type_get_type(ref) == TYPE_BASIC ||
type_get_type(ref) == TYPE_ENUM ||
(type_get_type(ref) == TYPE_STRUCT && get_struct_fc(ref) == RPC_FC_STRUCT)) ?
get_required_buffer_size_type( ref, name, alignment ) : 0;
}
break;
case TYPE_ARRAY:
return type_array_get_dim(type) *
get_required_buffer_size_type(type_array_get_element(type), name, alignment);
default: default:
break; error("get_required_buffer_size: unknown basic type 0x%02x\n",
type_basic_get_fc(type));
return 0;
} }
break;
case TGT_ENUM:
switch (get_enum_fc(type))
{
case RPC_FC_ENUM32:
*alignment = 4;
return 4;
case RPC_FC_ENUM16:
*alignment = 4;
return 2;
}
break;
case TGT_STRUCT:
if (get_struct_fc(type) == RPC_FC_STRUCT)
{
if (!type_struct_get_fields(type)) return 0;
return fields_memsize(type_struct_get_fields(type), alignment);
}
break;
case TGT_POINTER:
if (get_pointer_fc(type) == RPC_FC_RP)
{
const type_t *ref = type_pointer_get_ref(type);
switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
{
case TGT_BASIC:
case TGT_ENUM:
return get_required_buffer_size_type( ref, name, alignment );
case TGT_STRUCT:
if (get_struct_fc(ref) == RPC_FC_STRUCT)
return get_required_buffer_size_type( ref, name, alignment );
break;
case TGT_USER_TYPE:
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_STRING:
case TGT_POINTER:
case TGT_ARRAY:
case TGT_IFACE_POINTER:
case TGT_UNION:
case TGT_INVALID:
break;
}
}
break;
case TGT_ARRAY:
/* FIXME: depends on pointer type */
return type_array_get_dim(type) *
get_required_buffer_size_type(type_array_get_element(type), name, alignment);
default:
break;
} }
return 0; return 0;
} }
@ -3252,8 +3297,10 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var); write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var);
if (is_context_handle(type)) switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES))
{ {
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
if (phase == PHASE_MARSHAL) if (phase == PHASE_MARSHAL)
{ {
if (pass == PASS_IN) if (pass == PASS_IN)
@ -3294,13 +3341,11 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
} }
} }
} break;
else if (is_user_type(var->type)) case TGT_USER_TYPE:
{
print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset); print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset);
} break;
else if (is_string_type(var->attrs, var->type)) case TGT_STRING:
{
if (phase == PHASE_FREE || pass == PASS_RETURN || if (phase == PHASE_FREE || pass == PASS_RETURN ||
pointer_type != RPC_FC_RP) pointer_type != RPC_FC_RP)
{ {
@ -3318,10 +3363,8 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
print_phase_function(file, indent, "ConformantString", local_var_prefix, print_phase_function(file, indent, "ConformantString", local_var_prefix,
phase, var, start_offset); phase, var, start_offset);
} }
} break;
else switch (type_get_type(type)) case TGT_ARRAY:
{
case TYPE_ARRAY:
{ {
unsigned char tc = get_array_fc(type); unsigned char tc = get_array_fc(type);
const char *array_type = "FixedArray"; const char *array_type = "FixedArray";
@ -3365,11 +3408,11 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
} }
break; break;
} }
case TYPE_BASIC: case TGT_BASIC:
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
break; break;
case TYPE_ENUM: case TGT_ENUM:
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
{ {
if (phase == PHASE_MARSHAL) if (phase == PHASE_MARSHAL)
@ -3383,7 +3426,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
print_file(file, indent+1, "0x%02x /* %s */);\n", get_enum_fc(type), string_of_type(get_enum_fc(type))); print_file(file, indent+1, "0x%02x /* %s */);\n", get_enum_fc(type), string_of_type(get_enum_fc(type)));
} }
break; break;
case TYPE_STRUCT: case TGT_STRUCT:
switch (get_struct_fc(type)) switch (get_struct_fc(type))
{ {
case RPC_FC_STRUCT: case RPC_FC_STRUCT:
@ -3407,8 +3450,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type)); error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type));
} }
break; break;
case TYPE_UNION: case TGT_UNION:
case TYPE_ENCAPSULATED_UNION:
{ {
const char *union_type = NULL; const char *union_type = NULL;
@ -3421,7 +3463,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
phase, var, start_offset); phase, var, start_offset);
break; break;
} }
case TYPE_POINTER: case TGT_POINTER:
{ {
const type_t *ref = type_pointer_get_ref(type); const type_t *ref = type_pointer_get_ref(type);
if (get_pointer_fc(type) == RPC_FC_RP && !is_user_type(ref)) switch (type_get_type(ref)) if (get_pointer_fc(type) == RPC_FC_RP && !is_user_type(ref)) switch (type_get_type(ref))
@ -3503,29 +3545,23 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
case TYPE_ARRAY: case TYPE_ARRAY:
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break; break;
case TYPE_INTERFACE:
print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
break;
case TYPE_VOID: case TYPE_VOID:
case TYPE_ALIAS: case TYPE_ALIAS:
case TYPE_MODULE: case TYPE_MODULE:
case TYPE_COCLASS: case TYPE_COCLASS:
case TYPE_FUNCTION: case TYPE_FUNCTION:
case TYPE_INTERFACE:
assert(0); assert(0);
break; break;
} }
else if (type_get_type(ref) == TYPE_INTERFACE)
print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
else else
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break; break;
} }
case TYPE_VOID: case TGT_IFACE_POINTER:
case TYPE_ALIAS: print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
case TYPE_MODULE: break;
case TYPE_COCLASS: case TGT_INVALID:
case TYPE_FUNCTION:
case TYPE_INTERFACE:
assert(0); assert(0);
break; break;
} }

View File

@ -36,6 +36,28 @@ enum remoting_phase
PHASE_FREE PHASE_FREE
}; };
enum typegen_detect_flags
{
TDT_ALL_TYPES = 1 << 0,
TDT_IGNORE_STRINGS = 1 << 1,
};
enum typegen_type
{
TGT_INVALID,
TGT_USER_TYPE,
TGT_CTXT_HANDLE,
TGT_CTXT_HANDLE_POINTER,
TGT_STRING,
TGT_POINTER,
TGT_ARRAY,
TGT_IFACE_POINTER,
TGT_BASIC,
TGT_ENUM,
TGT_STRUCT,
TGT_UNION,
};
typedef int (*type_pred_t)(const type_t *); typedef int (*type_pred_t)(const type_t *);
void write_formatstringsdecl(FILE *f, int indent, const statement_list_t *stmts, type_pred_t pred); void write_formatstringsdecl(FILE *f, int indent, const statement_list_t *stmts, type_pred_t pred);
@ -68,3 +90,4 @@ void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_s
void write_full_pointer_free(FILE *file, int indent, const var_t *func); void write_full_pointer_free(FILE *file, int indent, const var_t *func);
unsigned char get_pointer_fc(const type_t *type); unsigned char get_pointer_fc(const type_t *type);
unsigned char get_struct_fc(const type_t *type); unsigned char get_struct_fc(const type_t *type);
enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags);