widl: Implement NDR for struct field alignment.

This commit is contained in:
Dan Hipschman 2007-09-04 11:04:37 -07:00 committed by Alexandre Julliard
parent 3d036da6d3
commit 62fb623e14
3 changed files with 58 additions and 1 deletions

View File

@ -329,6 +329,12 @@ s_sum_toplev_conf_cond(int *x, int a, int b, int c)
return sum;
}
double
s_sum_aligns(aligns_t *a)
{
return a->c + a->i + a->s + a->d;
}
void
s_stop(void)
{
@ -374,6 +380,7 @@ basic_tests(void)
static pvectors_t pvecs = {&vec1, &pvec2};
static sp_inner_t spi = {42};
static sp_t sp = {-13, &spi};
static aligns_t aligns = {3, 4, 5, 6.0};
pints_t pints;
ptypes_t ptypes;
int i1, i2, i3, *pi2, *pi3, **ppi3;
@ -447,6 +454,8 @@ basic_tests(void)
ok(enum_ord(E2) == 2, "RPC enum_ord\n");
ok(enum_ord(E3) == 3, "RPC enum_ord\n");
ok(enum_ord(E4) == 4, "RPC enum_ord\n");
ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n");
}
static void

View File

@ -189,5 +189,15 @@ interface IServer
int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n);
int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c);
typedef struct
{
char c;
int i;
short s;
double d;
} aligns_t;
double sum_aligns(aligns_t *a);
void stop(void);
}

View File

@ -98,6 +98,8 @@ const char *string_of_type(unsigned char type)
case RPC_FC_CARRAY: return "FC_CARRAY";
case RPC_FC_CVARRAY: return "FC_CVARRAY";
case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
case RPC_FC_ALIGNM4: return "RPC_FC_ALIGNM4";
case RPC_FC_ALIGNM8: return "RPC_FC_ALIGNM8";
default:
error("string_of_type: unknown type 0x%02x\n", type);
return NULL;
@ -682,13 +684,25 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_
static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
{
int have_align = FALSE;
size_t size = 0;
const var_t *v;
if (!fields) return 0;
LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
size += type_memsize(v->type, align);
{
unsigned int falign = 0;
size_t fsize = type_memsize(v->type, &falign);
if (!have_align)
{
*align = falign;
have_align = TRUE;
}
size = (size + (falign - 1)) & ~(falign - 1);
size += fsize;
}
size = (size + (*align - 1)) & ~(*align - 1);
return size;
}
@ -1508,12 +1522,36 @@ static void write_struct_members(FILE *file, const type_t *type,
unsigned int *corroff, unsigned int *typestring_offset)
{
const var_t *field;
unsigned short offset = 0;
if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
{
type_t *ft = field->type;
if (!ft->declarray || !is_conformant_array(ft))
{
unsigned int align = 0;
size_t size = type_memsize(ft, &align);
if ((align - 1) & offset)
{
unsigned char fc = 0;
switch (align)
{
case 4:
fc = RPC_FC_ALIGNM4;
break;
case 8:
fc = RPC_FC_ALIGNM8;
break;
default:
error("write_struct_members: cannot align type %d", ft->type);
}
print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
offset = (offset + (align - 1)) & ~(align - 1);
*typestring_offset += 1;
}
write_member_type(file, ft, field, corroff, typestring_offset);
offset += size;
}
}
write_end(file, typestring_offset);