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)
{
type_t *type = arg->type;
int is_wire_marshal = 0;
int is_context_handle = 0;
int more_to_do;
const char *container_type_name = NULL;
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 */
for (;;)
do
{
if (is_attr(type->attrs, ATTR_WIREMARSHAL))
{
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;
}
more_to_do = FALSE;
if (type_get_type(type) == TYPE_VOID && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle)
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)
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot be a function pointer\n", arg->name, container_type_name, container_name);
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);
switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
{
case TGT_STRUCT:
case TGT_UNION:
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)
@ -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 )
{
int ptr_level = 0;
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 */
if (is_attr(arg->attrs, ATTR_OUT))
{
if (!is_array(type))
switch (typegen_detect_type(type, arg->attrs, TDT_ALL_TYPES))
{
if (!ptr_level)
error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname);
if (type_get_type(type) == TYPE_INTERFACE && ptr_level == 1)
error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname);
case TGT_BASIC:
case TGT_ENUM:
case TGT_STRUCT:
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)
{
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)
@ -225,28 +228,29 @@ static void free_variable( const var_t *arg, const char *local_var_prefix )
return;
}
switch (type_get_type(type))
switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
{
case TYPE_ENUM:
case TYPE_BASIC:
case TGT_ENUM:
case TGT_BASIC:
break;
case TYPE_STRUCT:
case TGT_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;
case TYPE_POINTER:
case TYPE_INTERFACE:
if (type_get_type(type) == TYPE_INTERFACE || get_pointer_fc(type) == RPC_FC_FP)
case TGT_IFACE_POINTER:
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" );
}
/* 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, ");
fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
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;
}
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)
{
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 )
{
type_t *t = field->type;
enum typegen_type typegen_type;
if (is_user_type(t))
return RPC_FC_BOGUS_STRUCT;
typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
if (t->declarray)
if (typegen_type == TGT_ARRAY && t->declarray)
{
if (is_string_type(field->attrs, field->type))
{
@ -182,32 +225,26 @@ unsigned char get_struct_fc(const type_t *type)
has_variance = 1;
t = type_array_get_element(t);
typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
}
if (is_user_type(t))
return RPC_FC_BOGUS_STRUCT;
switch (type_get_type(t))
switch (typegen_type)
{
case TYPE_VOID:
case TYPE_ALIAS:
case TYPE_MODULE:
assert(0);
case TGT_USER_TYPE:
case TGT_IFACE_POINTER:
return RPC_FC_BOGUS_STRUCT;
case TGT_BASIC:
break;
case TYPE_BASIC:
break;
case TYPE_ENUM:
case TGT_ENUM:
if (get_enum_fc(t) == RPC_FC_ENUM16)
return RPC_FC_BOGUS_STRUCT;
break;
case TYPE_POINTER:
case TGT_POINTER:
if (get_pointer_fc(t) == RPC_FC_RP || pointer_size != 4)
return RPC_FC_BOGUS_STRUCT;
if (type_get_type(type_pointer_get_ref(t)) == TYPE_INTERFACE)
return RPC_FC_BOGUS_STRUCT;
has_pointer = 1;
break;
case TYPE_ARRAY:
case TGT_ARRAY:
{
unsigned int ptr_type = get_attrv(field->attrs, ATTR_POINTERTYPE);
if (!ptr_type || ptr_type == RPC_FC_RP)
@ -217,13 +254,9 @@ unsigned char get_struct_fc(const type_t *type)
has_pointer = 1;
break;
}
case TYPE_INTERFACE:
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TYPE_COCLASS:
case TYPE_FUNCTION:
case TGT_UNION:
return RPC_FC_BOGUS_STRUCT;
case TYPE_STRUCT:
case TGT_STRUCT:
{
unsigned char fc = get_struct_fc(t);
switch (fc)
@ -265,6 +298,14 @@ unsigned char get_struct_fc(const type_t *type)
}
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;
}
if (is_user_type(elem_type))
fc = RPC_FC_BOGUS_ARRAY;
else switch (type_get_type(elem_type))
switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS))
{
case TYPE_STRUCT:
case TGT_USER_TYPE:
fc = RPC_FC_BOGUS_ARRAY;
break;
case TGT_STRUCT:
switch (get_struct_fc(elem_type))
{
case RPC_FC_BOGUS_STRUCT:
@ -327,25 +369,29 @@ unsigned char get_array_fc(const type_t *type)
break;
}
break;
case TYPE_ENUM:
case TGT_ENUM:
/* 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 */
if (get_enum_fc(elem_type) == RPC_FC_ENUM16)
fc = RPC_FC_BOGUS_ARRAY;
break;
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TGT_UNION:
case TGT_IFACE_POINTER:
fc = RPC_FC_BOGUS_ARRAY;
break;
case TYPE_POINTER:
case TGT_POINTER:
/* ref pointers cannot just be block copied. unique pointers to
* interfaces need special treatment. either case means the array is
* complex */
if (get_pointer_fc(elem_type) == RPC_FC_RP ||
type_get_type(type_pointer_get_ref(elem_type)) == TYPE_INTERFACE)
if (get_pointer_fc(elem_type) == RPC_FC_RP)
fc = RPC_FC_BOGUS_ARRAY;
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 */
break;
}
@ -377,16 +423,16 @@ static int is_non_complex_struct(const type_t *type)
static int type_has_pointers(const type_t *type)
{
if (is_user_type(type))
return FALSE;
switch (type_get_type(type))
switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
{
case TYPE_POINTER:
case TGT_USER_TYPE:
return FALSE;
case TGT_POINTER:
return TRUE;
case TYPE_ARRAY:
case TGT_ARRAY:
/* FIXME: array can be pointer */
return type_has_pointers(type_array_get_element(type));
case TYPE_STRUCT:
case TGT_STRUCT:
{
var_list_t *fields = type_struct_get_fields(type);
const var_t *field;
@ -397,8 +443,7 @@ static int type_has_pointers(const type_t *type)
}
break;
}
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TGT_UNION:
{
var_list_t *fields;
const var_t *field;
@ -410,7 +455,13 @@ static int type_has_pointers(const type_t *type)
}
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;
}
@ -419,19 +470,19 @@ static int type_has_pointers(const type_t *type)
static int type_has_full_pointer(const type_t *type)
{
if (is_user_type(type))
return FALSE;
switch (type_get_type(type))
switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
{
case TYPE_POINTER:
case TGT_USER_TYPE:
return FALSE;
case TGT_POINTER:
if (get_pointer_fc(type) == RPC_FC_FP)
return TRUE;
else
return FALSE;
case TYPE_ARRAY:
case TGT_ARRAY:
/* FIXME: array can be full pointer */
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);
const var_t *field;
@ -442,8 +493,7 @@ static int type_has_full_pointer(const type_t *type)
}
break;
}
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TGT_UNION:
{
var_list_t *fields;
const var_t *field;
@ -455,7 +505,13 @@ static int type_has_full_pointer(const type_t *type)
}
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;
}
@ -519,18 +575,14 @@ int is_user_type(const type_t *t)
static int is_embedded_complex(const type_t *type)
{
if (is_user_type(type))
return TRUE;
switch (type_get_type(type))
switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES))
{
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TYPE_ARRAY:
case TGT_USER_TYPE:
case TGT_STRUCT:
case TGT_UNION:
case TGT_ARRAY:
case TGT_IFACE_POINTER:
return TRUE;
case TYPE_POINTER:
return type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE;
default:
return FALSE;
}
@ -2567,19 +2619,17 @@ static unsigned int write_typeformatstring_var(FILE *file, int indent, const var
{
unsigned int offset;
if (is_context_handle(type))
return write_contexthandle_tfs(file, type, var, typeformat_offset);
if (is_user_type(type))
switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES))
{
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);
return type->typestring_offset;
}
if (is_string_type(var->attrs, type))
case TGT_STRING:
return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
if (is_array(type))
case TGT_ARRAY:
{
int ptr_type;
unsigned int off;
@ -2607,75 +2657,68 @@ static unsigned int write_typeformatstring_var(FILE *file, int indent, const var
}
return off;
}
if (!is_ptr(type))
{
switch (type_get_type(type))
case TGT_STRUCT:
if (processed(type)) return type->typestring_offset;
return write_struct_tfs(file, type, var->name, typeformat_offset);
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:
if (processed(type)) return type->typestring_offset;
return write_struct_tfs(file, type, var->name, typeformat_offset);
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
if (processed(type)) return type->typestring_offset;
return write_union_tfs(file, type, typeformat_offset);
case TYPE_ENUM:
case TYPE_BASIC:
/* nothing to do */
return 0;
default:
error("write_typeformatstring_var: Unsupported type %d for variable %s\n",
type_get_type(type), var->name);
size_t 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);
switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
{
/* special case for pointers to base types */
case TGT_BASIC:
case TGT_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;
}
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))
{
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);
error("invalid type %s for var %s\n", type->name, var->name);
return 0;
}
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;
if (is_user_type(type))
switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
{
case TGT_USER_TYPE:
write_user_tfs(file, type, tfsoff);
}
else if (is_string_type(attrs, type))
{
break;
case TGT_STRING:
write_string_tfs(file, attrs, type, name, tfsoff);
}
else switch (type_get_type(type))
{
case TYPE_POINTER:
break;
case TGT_IFACE_POINTER:
write_ip_tfs(file, attrs, type, tfsoff);
break;
case TGT_POINTER:
{
type_t *ref = type_pointer_get_ref(type);
if (type_get_type(ref) == TYPE_INTERFACE
|| (type_get_type(ref) == TYPE_VOID
&& 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 (!processed(ref) && type_get_type(ref) != TYPE_BASIC)
retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
if (write_ptr)
write_pointer_tfs(file, type, tfsoff);
if (write_ptr)
write_pointer_tfs(file, type, tfsoff);
retmask |= 1;
}
retmask |= 1;
break;
}
case TYPE_ARRAY:
case TGT_ARRAY:
/* conformant arrays and strings are handled specially */
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;
}
break;
case TYPE_STRUCT:
case TGT_STRUCT:
if (!processed(type))
write_struct_tfs(file, type, name, tfsoff);
break;
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TGT_UNION:
if (!processed(type))
write_union_tfs(file, type, tfsoff);
break;
case TYPE_ENUM:
case TYPE_BASIC:
case TGT_ENUM:
case TGT_BASIC:
/* nothing to do */
break;
case TYPE_VOID:
case TYPE_ALIAS:
case TYPE_MODULE:
case TYPE_COCLASS:
case TYPE_FUNCTION:
case TYPE_INTERFACE:
assert(0);
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_INVALID:
error("invalid type %s for var %s\n", type->name, name);
break;
}
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(
const type_t *type, const char *name, unsigned int *alignment)
{
const char *uname;
const type_t *utype;
*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);
}
else
{
switch (type_get_type(type))
case TGT_BASIC:
switch (type_basic_get_fc(type))
{
case TYPE_BASIC:
switch (type_basic_get_fc(type))
{
case RPC_FC_BYTE:
case RPC_FC_CHAR:
case RPC_FC_USMALL:
case RPC_FC_SMALL:
*alignment = 4;
return 1;
case RPC_FC_BYTE:
case RPC_FC_CHAR:
case RPC_FC_USMALL:
case RPC_FC_SMALL:
*alignment = 4;
return 1;
case RPC_FC_WCHAR:
case RPC_FC_USHORT:
case RPC_FC_SHORT:
*alignment = 4;
return 2;
case RPC_FC_WCHAR:
case RPC_FC_USHORT:
case RPC_FC_SHORT:
*alignment = 4;
return 2;
case RPC_FC_ULONG:
case RPC_FC_LONG:
case RPC_FC_FLOAT:
case RPC_FC_ERROR_STATUS_T:
*alignment = 4;
return 4;
case RPC_FC_ULONG:
case RPC_FC_LONG:
case RPC_FC_FLOAT:
case RPC_FC_ERROR_STATUS_T:
*alignment = 4;
return 4;
case RPC_FC_HYPER:
case RPC_FC_DOUBLE:
*alignment = 8;
return 8;
case RPC_FC_HYPER:
case RPC_FC_DOUBLE:
*alignment = 8;
return 8;
case RPC_FC_IGNORE:
case RPC_FC_BIND_PRIMITIVE:
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);
case RPC_FC_IGNORE:
case RPC_FC_BIND_PRIMITIVE:
return 0;
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;
}
@ -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);
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 (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);
}
}
}
else if (is_user_type(var->type))
{
break;
case TGT_USER_TYPE:
print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset);
}
else if (is_string_type(var->attrs, var->type))
{
break;
case TGT_STRING:
if (phase == PHASE_FREE || pass == PASS_RETURN ||
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,
phase, var, start_offset);
}
}
else switch (type_get_type(type))
{
case TYPE_ARRAY:
break;
case TGT_ARRAY:
{
unsigned char tc = get_array_fc(type);
const char *array_type = "FixedArray";
@ -3365,11 +3408,11 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
}
break;
}
case TYPE_BASIC:
case TGT_BASIC:
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
break;
case TYPE_ENUM:
case TGT_ENUM:
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
{
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)));
}
break;
case TYPE_STRUCT:
case TGT_STRUCT:
switch (get_struct_fc(type))
{
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));
}
break;
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TGT_UNION:
{
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);
break;
}
case TYPE_POINTER:
case TGT_POINTER:
{
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))
@ -3503,29 +3545,23 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
case TYPE_ARRAY:
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break;
case TYPE_INTERFACE:
print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
break;
case TYPE_VOID:
case TYPE_ALIAS:
case TYPE_MODULE:
case TYPE_COCLASS:
case TYPE_FUNCTION:
case TYPE_INTERFACE:
assert(0);
break;
}
else if (type_get_type(ref) == TYPE_INTERFACE)
print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
else
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break;
}
case TYPE_VOID:
case TYPE_ALIAS:
case TYPE_MODULE:
case TYPE_COCLASS:
case TYPE_FUNCTION:
case TYPE_INTERFACE:
case TGT_IFACE_POINTER:
print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
break;
case TGT_INVALID:
assert(0);
break;
}

View File

@ -36,6 +36,28 @@ enum remoting_phase
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 *);
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);
unsigned char get_pointer_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);