widl: Add padding to the end of complex structures
Dan Hipschman
dsh at linux.ucla.edu
Thu Sep 13 20:04:32 CDT 2007
This patch adds padding to the end of complex structures. This is needed
by oaidl.idl:
$ fgrep -c STRUCTPAD dlls/oleaut32/oaidl_p.c
6
Tested on wine and windows.
---
dlls/rpcrt4/tests/server.c | 11 +++++++++++
dlls/rpcrt4/tests/server.idl | 8 ++++++++
tools/widl/parser.y | 3 +++
tools/widl/typegen.c | 36 ++++++++++++++++++++++++++++++++++++
tools/widl/typegen.h | 1 +
5 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index cd21468..879e0d1 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -344,6 +344,12 @@ s_sum_aligns(aligns_t *a)
return a->c + a->i + a->s + a->d;
}
+int
+s_sum_padded(padded_t *p)
+{
+ return p->i + p->c;
+}
+
void
s_stop(void)
{
@@ -392,6 +398,7 @@ basic_tests(void)
static aligns_t aligns = {3, 4, 5, 6.0};
pints_t pints;
ptypes_t ptypes;
+ padded_t padded;
int i1, i2, i3, *pi2, *pi3, **ppi3;
double u, v;
float s, t;
@@ -465,6 +472,10 @@ basic_tests(void)
ok(enum_ord(E4) == 4, "RPC enum_ord\n");
ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n");
+
+ padded.i = -3;
+ padded.c = 8;
+ ok(sum_padded(&padded) == 5, "RPC sum_padded\n");
}
static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 3ee40ae..d84637c 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -200,5 +200,13 @@ interface IServer
double sum_aligns(aligns_t *a);
+ typedef struct
+ {
+ int i;
+ char c;
+ } padded_t;
+
+ int sum_padded(padded_t *p);
+
void stop(void);
}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 5b4c5ff..5d99c5a 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1679,6 +1679,9 @@ static int get_struct_type(var_list_t *fields)
int has_variance = 0;
var_t *field;
+ if (get_padding(fields))
+ return RPC_FC_BOGUS_STRUCT;
+
if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
{
type_t *t = field->type;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f0c298b..02b2cbc 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -726,6 +726,29 @@ static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
return maxs;
}
+int get_padding(const var_list_t *fields)
+{
+ unsigned short offset = 0;
+ int salign = -1;
+ const var_t *f;
+
+ if (!fields)
+ return 0;
+
+ LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
+ {
+ type_t *ft = f->type;
+ unsigned int align = 0;
+ size_t size = type_memsize(ft, &align);
+ if (salign == -1)
+ salign = align;
+ offset = (offset + (align - 1)) & ~(align - 1);
+ offset += size;
+ }
+
+ return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
+}
+
size_t type_memsize(const type_t *t, unsigned int *align)
{
size_t size = 0;
@@ -1518,6 +1541,8 @@ static void write_struct_members(FILE *file, const type_t *type,
{
const var_t *field;
unsigned short offset = 0;
+ int salign = -1;
+ int padding;
if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
{
@@ -1526,6 +1551,8 @@ static void write_struct_members(FILE *file, const type_t *type,
{
unsigned int align = 0;
size_t size = type_memsize(ft, &align);
+ if (salign == -1)
+ salign = align;
if ((align - 1) & offset)
{
unsigned char fc = 0;
@@ -1549,6 +1576,15 @@ static void write_struct_members(FILE *file, const type_t *type,
}
}
+ padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
+ if (padding)
+ {
+ print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
+ RPC_FC_STRUCTPAD1 + padding - 1,
+ padding);
+ *typestring_offset += 1;
+ }
+
write_end(file, typestring_offset);
}
diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h
index eefecd7..448e503 100644
--- a/tools/widl/typegen.h
+++ b/tools/widl/typegen.h
@@ -55,3 +55,4 @@ size_t type_memsize(const type_t *t, unsigned int *align);
int decl_indirect(const type_t *t);
void write_parameters_init(FILE *file, int indent, const func_t *func);
void print(FILE *file, int indent, const char *format, va_list ap);
+int get_padding(const var_list_t *fields);
More information about the wine-patches
mailing list