widl [2/2]: Implement pointer descriptions for complex structures
Dan Hipschman
dsh at linux.ucla.edu
Mon Sep 17 19:01:35 CDT 2007
This patch implements pointer descriptions for complex structures, which
is going to be needed a lot for oaidl.idl, and other things.
---
dlls/rpcrt4/tests/server.c | 16 ++++++++++++++++
dlls/rpcrt4/tests/server.idl | 15 +++++++++++++++
tools/widl/parser.y | 1 +
tools/widl/typegen.c | 38 +++++++++++++++++++++++++++++++-------
tools/widl/widltypes.h | 1 +
5 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 879e0d1..2ed6de7 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -350,6 +350,12 @@ s_sum_padded(padded_t *p)
return p->i + p->c;
}
+int
+s_sum_bogus(bogus_t *b)
+{
+ return *b->h.p1 + *b->p2 + *b->p3 + b->c;
+}
+
void
s_stop(void)
{
@@ -399,6 +405,7 @@ basic_tests(void)
pints_t pints;
ptypes_t ptypes;
padded_t padded;
+ bogus_t bogus;
int i1, i2, i3, *pi2, *pi3, **ppi3;
double u, v;
float s, t;
@@ -476,6 +483,15 @@ basic_tests(void)
padded.i = -3;
padded.c = 8;
ok(sum_padded(&padded) == 5, "RPC sum_padded\n");
+
+ i1 = 14;
+ i2 = -7;
+ i3 = -4;
+ bogus.h.p1 = &i1;
+ bogus.p2 = &i2;
+ bogus.p3 = &i3;
+ bogus.c = 9;
+ ok(sum_bogus(&bogus) == 12, "RPC sum_bogus\n");
}
static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index d84637c..44bb945 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -208,5 +208,20 @@ interface IServer
int sum_padded(padded_t *p);
+ typedef struct
+ {
+ int *p1;
+ } bogus_helper_t;
+
+ typedef struct
+ {
+ bogus_helper_t h;
+ int *p2;
+ int *p3;
+ char c;
+ } bogus_t;
+
+ int sum_bogus(bogus_t *b);
+
void stop(void);
}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index ac24038..fbaf9a7 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1249,6 +1249,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
t->size_is = NULL;
t->length_is = NULL;
t->typestring_offset = 0;
+ t->ptrdesc = 0;
t->declarray = FALSE;
t->ignore = (parse_only != 0);
t->is_const = FALSE;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index c11ebd5..fc02f0c 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -100,6 +100,7 @@ const char *string_of_type(unsigned char type)
case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
+ case RPC_FC_POINTER: return "FC_POINTER";
default:
error("string_of_type: unknown type 0x%02x\n", type);
return NULL;
@@ -912,7 +913,8 @@ static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
*tfsoff += 2;
}
-static void write_member_type(FILE *file, type_t *type, const var_t *field,
+static void write_member_type(FILE *file, const type_t *cont,
+ const attr_list_t *attrs, const type_t *type,
unsigned int *corroff, unsigned int *tfsoff)
{
if (is_embedded_complex(type))
@@ -920,7 +922,7 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field,
size_t absoff;
short reloff;
- if (is_union(type->type) && is_attr(field->attrs, ATTR_SWITCHIS))
+ if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
{
absoff = *corroff;
*corroff += 8;
@@ -940,7 +942,10 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field,
}
else if (is_ptr(type))
{
- print_file(file, 2, "0x8,\t/* FC_LONG */\n");
+ unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
+ ? RPC_FC_POINTER
+ : RPC_FC_LONG);
+ print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
*tfsoff += 1;
}
else if (!write_base_type(file, type, tfsoff))
@@ -1515,7 +1520,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
*typestring_offset += 1;
}
- write_member_type(file, type->ref, NULL, NULL, typestring_offset);
+ write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
write_end(file, typestring_offset);
}
else
@@ -1573,7 +1578,8 @@ static void write_struct_members(FILE *file, const type_t *type,
offset = (offset + (align - 1)) & ~(align - 1);
*typestring_offset += 1;
}
- write_member_type(file, ft, field, corroff, typestring_offset);
+ write_member_type(file, type, field->attrs, field->type, corroff,
+ typestring_offset);
offset += size;
}
}
@@ -1649,8 +1655,12 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
if (type->type == RPC_FC_BOGUS_STRUCT)
{
-
- print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
+ /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
+ nothing is written to file yet. On the actual writing pass,
+ this will have been updated. */
+ short reloff = type->ptrdesc - *tfsoff;
+ print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+ reloff, reloff, type->ptrdesc);
*tfsoff += 2;
}
else if ((type->type == RPC_FC_PSTRUCT) ||
@@ -1667,6 +1677,20 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
write_struct_members(file, type, &corroff, tfsoff);
+ if (type->type == RPC_FC_BOGUS_STRUCT)
+ {
+ const var_list_t *fs = type->fields;
+ const var_t *f;
+
+ type->ptrdesc = *tfsoff;
+ if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
+ {
+ type_t *ft = f->type;
+ if (is_ptr(ft))
+ write_pointer_tfs(file, ft, tfsoff);
+ }
+ }
+
current_structure = save_current_structure;
return start_offset;
}
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index d514d54..2b1aaa9 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -214,6 +214,7 @@ struct _type_t {
expr_t *size_is, *length_is;
type_t *orig; /* dup'd types */
unsigned int typestring_offset;
+ unsigned int ptrdesc; /* used for complex structs */
int typelib_idx;
unsigned int declarray : 1; /* if declared as an array */
unsigned int ignore : 1;
More information about the wine-patches
mailing list