widl: Implement pointer descriptions for all embedded pointer types.

This commit is contained in:
Rob Shearman 2007-06-19 12:05:25 +01:00 committed by Alexandre Julliard
parent 5817e36634
commit 6ad13f3ed1
1 changed files with 351 additions and 27 deletions

View File

@ -125,6 +125,21 @@ int is_struct(unsigned char type)
}
}
static int is_non_complex_struct(const type_t *type)
{
switch (type->type)
{
case RPC_FC_STRUCT:
case RPC_FC_PSTRUCT:
case RPC_FC_CSTRUCT:
case RPC_FC_CPSTRUCT:
case RPC_FC_CVSTRUCT:
return 1;
default:
return 0;
}
}
int is_union(unsigned char type)
{
switch (type)
@ -976,44 +991,353 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
}
}
static size_t write_pointer_description(FILE *file, type_t *type, size_t mem_offset,
int level, unsigned int *typestring_offset)
static int write_no_repeat_pointer_descriptions(
FILE *file, const attr_list_t *attrs, type_t *type,
size_t *offset_in_memory, size_t *offset_in_buffer,
unsigned int *typestring_offset)
{
const var_t *v;
unsigned int align = 0;
int written = 0;
unsigned int align;
/* don't generate a pointer for first-level arrays since we want to
* descend into them to write their pointers, not stop here */
if (level == 0 && is_array(type))
if (is_ptr(type))
{
write_pointer_description(file, type->ref, mem_offset, level + 1,
typestring_offset);
}
else if (is_ptr(type))
{
print_file(file, 2, "0x46,\t/* FC_NO_REPEAT */\n");
print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
/* pointer instance */
print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
*typestring_offset += 6;
if (processed(type->ref) || is_base_type(type->ref->type))
write_pointer_tfs(file, type, typestring_offset);
else
error("write_pointer_description: type format string unknown\n");
}
else if (level == 0 && is_struct(type->type))
{
if (type->fields)
{
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
mem_offset
+= write_pointer_description(file, v->type, mem_offset,
level + 1, typestring_offset);
}
align = 0;
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
*offset_in_buffer += type_memsize(type, &align);
return 1;
}
return type_memsize(type, &align);
if (is_non_complex_struct(type))
{
const var_t *v;
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
written += write_no_repeat_pointer_descriptions(
file, v->attrs, v->type,
offset_in_memory, offset_in_buffer, typestring_offset);
}
else
{
align = 0;
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
*offset_in_buffer += type_memsize(type, &align);
}
return written;
}
static int write_pointer_description_offsets(
FILE *file, const attr_list_t *attrs, type_t *type,
size_t *offset_in_memory, size_t *offset_in_buffer,
unsigned int *typestring_offset)
{
int written = 0;
unsigned int align;
if (is_ptr(type))
{
if (offset_in_memory && offset_in_buffer)
{
/* pointer instance */
/* FIXME: sometimes from end of structure, sometimes from beginning */
print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
align = 0;
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
*offset_in_buffer += type_memsize(type, &align);
}
*typestring_offset += 4;
if (processed(type->ref) || is_base_type(type->ref->type))
write_pointer_tfs(file, type, typestring_offset);
else
error("write_pointer_description_offsets: type format string unknown\n");
return 1;
}
if (is_array(type))
{
return write_pointer_description_offsets(
file, attrs, type->ref, offset_in_memory, offset_in_buffer,
typestring_offset);
}
else if (is_non_complex_struct(type))
{
/* otherwise search for interesting fields to parse */
const var_t *v;
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
{
written += write_pointer_description_offsets(
file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
typestring_offset);
}
}
else
{
align = 0;
if (offset_in_memory)
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
if (offset_in_buffer)
*offset_in_buffer += type_memsize(type, &align);
}
return written;
}
/* Note: if file is NULL return value is number of pointers to write, else
* it is the number of type format characters written */
static int write_fixed_array_pointer_descriptions(
FILE *file, const attr_list_t *attrs, type_t *type,
size_t *offset_in_memory, size_t *offset_in_buffer,
unsigned int *typestring_offset)
{
unsigned int align;
int pointer_count = 0;
if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
{
unsigned int temp = 0;
/* unfortunately, this needs to be done in two passes to avoid
* writing out redundant FC_FIXED_REPEAT descriptions */
pointer_count = write_pointer_description_offsets(
NULL, attrs, type->ref, NULL, NULL, &temp);
if (pointer_count > 0)
{
unsigned int increment_size;
size_t offset_of_array_pointer_mem = 0;
size_t offset_of_array_pointer_buf = 0;
align = 0;
increment_size = type_memsize(type->ref, &align);
print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
*typestring_offset += 10;
pointer_count = write_pointer_description_offsets(
file, attrs, type, &offset_of_array_pointer_mem,
&offset_of_array_pointer_buf, typestring_offset);
}
}
else if (is_struct(type->type))
{
const var_t *v;
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
{
pointer_count += write_fixed_array_pointer_descriptions(
file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
typestring_offset);
}
}
else
{
align = 0;
if (offset_in_memory)
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
if (offset_in_buffer)
*offset_in_buffer += type_memsize(type, &align);
}
return pointer_count;
}
/* Note: if file is NULL return value is number of pointers to write, else
* it is the number of type format characters written */
static int write_conformant_array_pointer_descriptions(
FILE *file, const attr_list_t *attrs, type_t *type,
size_t *offset_in_memory, size_t *offset_in_buffer,
unsigned int *typestring_offset)
{
unsigned int align;
int pointer_count = 0;
if (is_conformant_array(type) && !type->length_is)
{
unsigned int temp = 0;
/* unfortunately, this needs to be done in two passes to avoid
* writing out redundant FC_VARIABLE_REPEAT descriptions */
pointer_count = write_pointer_description_offsets(
NULL, attrs, type->ref, NULL, NULL, &temp);
if (pointer_count > 0)
{
unsigned int increment_size;
size_t offset_of_array_pointer_mem = 0;
size_t offset_of_array_pointer_buf = 0;
align = 0;
increment_size = type_memsize(type->ref, &align);
if (increment_size > USHRT_MAX)
error("array size of %u bytes is too large\n", increment_size);
print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
*typestring_offset += 8;
pointer_count = write_pointer_description_offsets(
file, attrs, type->ref, &offset_of_array_pointer_mem,
&offset_of_array_pointer_buf, typestring_offset);
}
}
else if (is_struct(type->type))
{
const var_t *v;
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
{
pointer_count += write_conformant_array_pointer_descriptions(
file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
typestring_offset);
}
}
else
{
align = 0;
if (offset_in_memory)
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
if (offset_in_buffer)
*offset_in_buffer += type_memsize(type, &align);
}
return pointer_count;
}
/* Note: if file is NULL return value is number of pointers to write, else
* it is the number of type format characters written */
static int write_varying_array_pointer_descriptions(
FILE *file, const attr_list_t *attrs, type_t *type,
size_t *offset_in_memory, size_t *offset_in_buffer,
unsigned int *typestring_offset)
{
unsigned int align;
int pointer_count = 0;
/* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
if (is_array(type) && type->length_is)
{
unsigned int temp = 0;
/* unfortunately, this needs to be done in two passes to avoid
* writing out redundant FC_VARIABLE_REPEAT descriptions */
pointer_count = write_pointer_description_offsets(
NULL, attrs, type->ref, NULL, NULL, &temp);
if (pointer_count > 0)
{
unsigned int increment_size;
size_t offset_of_array_pointer_mem = 0;
size_t offset_of_array_pointer_buf = 0;
align = 0;
increment_size = type_memsize(type->ref, &align);
if (increment_size > USHRT_MAX)
error("array size of %u bytes is too large\n", increment_size);
print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
*typestring_offset += 8;
pointer_count = write_pointer_description_offsets(
file, attrs, type, &offset_of_array_pointer_mem,
&offset_of_array_pointer_buf, typestring_offset);
}
}
else if (is_struct(type->type))
{
const var_t *v;
LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
{
pointer_count += write_varying_array_pointer_descriptions(
file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
typestring_offset);
}
}
else
{
align = 0;
if (offset_in_memory)
*offset_in_memory += type_memsize(type, &align);
/* FIXME: is there a case where these two are different? */
align = 0;
if (offset_in_buffer)
*offset_in_buffer += type_memsize(type, &align);
}
return pointer_count;
}
static void write_pointer_description(FILE *file, type_t *type,
size_t mem_offset, int level,
unsigned int *typestring_offset)
{
size_t offset_in_buffer;
size_t offset_in_memory;
/* pass 1: search for single instance of a pointer (i.e. don't descend
* into arrays) */
offset_in_memory = 0;
offset_in_buffer = 0;
write_no_repeat_pointer_descriptions(
file, NULL, type,
&offset_in_memory, &offset_in_buffer, typestring_offset);
/* pass 2: search for pointers in fixed arrays */
offset_in_memory = 0;
offset_in_buffer = 0;
write_fixed_array_pointer_descriptions(
file, NULL, type,
&offset_in_memory, &offset_in_buffer, typestring_offset);
/* pass 3: search for pointers in conformant only arrays (but don't descend
* into conformant varying or varying arrays) */
offset_in_memory = 0;
offset_in_buffer = 0;
write_conformant_array_pointer_descriptions(
file, NULL, type,
&offset_in_memory, &offset_in_buffer, typestring_offset);
/* pass 4: search for pointers in varying arrays */
offset_in_memory = 0;
offset_in_buffer = 0;
write_varying_array_pointer_descriptions(
file, NULL, type,
&offset_in_memory, &offset_in_buffer, typestring_offset);
}
static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,