widl [2/3]: Handle pointers to conformant arrays (e.g., "[size_is(, n)] int **p; ").
Dan Hipschman
dsh at linux.ucla.edu
Fri Nov 2 17:24:08 CDT 2007
This patch gets widl to handle pointers to conformant arrays. For example:
[size_is(, n)] int **p;
This appears in dcom.idl, so it's going to be needed.
---
dlls/rpcrt4/tests/server.c | 10 ++++++++++
dlls/rpcrt4/tests/server.idl | 2 ++
tools/widl/header.h | 3 ++-
tools/widl/typegen.c | 37 ++++++++++++++++++++++++++++++++++++-
4 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index a82fe91..b01967d 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -481,6 +481,12 @@ s_get_name(name_t *name)
name->name[name->size - 1] = 0;
}
+int
+s_sum_pcarr2(int n, int **pa)
+{
+ return s_sum_conf_array(*pa, n);
+}
+
void
s_stop(void)
{
@@ -812,6 +818,7 @@ pointer_tests(void)
bstr_t bstr = &bstr_data[1];
name_t name;
void *buffer;
+ int *pa2;
ok(test_list_length(list) == 3, "RPC test_list_length\n");
ok(square_puint(p1) == 121, "RPC square_puint\n");
@@ -862,6 +869,9 @@ pointer_tests(void)
todo_wine
ok(name.name == buffer, "[in,out] pointer should have stayed as %p but instead changed to %p\n", name.name, buffer);
HeapFree(GetProcessHeap(), 0, name.name);
+
+ pa2 = a;
+ ok(sum_pcarr2(4, &pa2) == 10, "RPC sum_pcarr2\n");
}
static int
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 15402ee..c566b8f 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -297,5 +297,7 @@ cpp_quote("#endif")
} name_t;
void get_name([in,out] name_t *name);
+ int sum_pcarr2(int n, [size_is(, n)] int **pa);
+
void stop(void);
}
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 47564de..41784a0 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -29,6 +29,7 @@ extern void *get_attrp(const attr_list_t *list, enum attr_type t);
extern unsigned long get_attrv(const attr_list_t *list, enum attr_type t);
extern int is_void(const type_t *t);
extern int is_conformant_array(const type_t *t);
+extern int is_declptr(const type_t *t);
extern void write_name(FILE *h, const var_t *v);
extern void write_prefix_name(FILE *h, const char *prefix, const var_t *v);
extern const char* get_name(const var_t *v);
@@ -67,7 +68,7 @@ extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
static inline int last_ptr(const type_t *type)
{
- return is_ptr(type) && !is_ptr(type->ref);
+ return is_ptr(type) && !is_declptr(type->ref);
}
static inline int last_array(const type_t *type)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f6d5536..a9cd2eb 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -1420,7 +1420,7 @@ static void write_pointer_description(FILE *file, type_t *type,
&offset_in_memory, &offset_in_buffer, typestring_offset);
}
-static int is_declptr(const type_t *t)
+int is_declptr(const type_t *t)
{
return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
}
@@ -2083,6 +2083,14 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f
size_t off;
off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
+ /* Top level pointers to conformant arrays may be handled specially
+ since we can bypass the pointer, but if the array is burried
+ beneath another pointer (e.g., "[size_is(,n)] int **p" then we
+ always need to write the pointer. */
+ if (!ptr_type && var->type != type)
+ /* FIXME: This should use pointer_default, but the information
+ isn't kept around for arrays. */
+ ptr_type = RPC_FC_UP;
if (ptr_type && ptr_type != RPC_FC_RP)
{
unsigned int absoff = type->typestring_offset;
@@ -2711,6 +2719,13 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
{
unsigned char tc = type->type;
const char *array_type = "FixedArray";
+ type_t *st;
+
+ for (st = type->ref; is_ptr(st) || is_array(st); st = st->ref)
+ if (st->size_is)
+ error("in function %s: multidimensional conformant arrays"
+ " not supported at the top level\n",
+ func->def->name);
if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
{
@@ -2826,8 +2841,28 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
else
{
const var_t *iid;
+ expr_t *sx = NULL;
+ type_t *st;
+
+ for (st = type->ref; is_ptr(st) || is_array(st); st = st->ref)
+ if (st->size_is)
+ {
+ if (!sx)
+ sx = st->size_is;
+ else
+ error("in function %s: multidimensional conformant"
+ " arrays not supported at the top level\n",
+ func->def->name);
+ }
+
if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
+ else if (sx)
+ {
+ print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
+ write_expr(file, sx, 1);
+ fprintf(file, ";\n\n");
+ }
if (var->type->ref->type == RPC_FC_IP)
print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
else
More information about the wine-patches
mailing list