Dan Hipschman : widl: Detect conformant arrays of user types correctly.
Alexandre Julliard
julliard at winehq.org
Thu Oct 18 07:59:33 CDT 2007
Module: wine
Branch: master
Commit: 1d0f9378bc855652bf45db0e29b07fa85724dbd1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1d0f9378bc855652bf45db0e29b07fa85724dbd1
Author: Dan Hipschman <dsh at linux.ucla.edu>
Date: Wed Oct 17 18:06:26 2007 -0700
widl: Detect conformant arrays of user types correctly.
---
dlls/rpcrt4/tests/server.c | 54 ++++++++++++++++++++++++++++++++++++++++++
dlls/rpcrt4/tests/server.idl | 16 ++++++++++++
tools/widl/header.c | 4 ++-
tools/widl/parser.y | 41 ++++++++++++++------------------
tools/widl/typegen.c | 16 ++++++++++++
5 files changed, 107 insertions(+), 24 deletions(-)
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index d8ecff0..97f2e23 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -48,6 +48,14 @@ midl_user_free(void __RPC_FAR *p)
free(p);
}
+static char *
+xstrdup(const char *s)
+{
+ char *d = HeapAlloc(GetProcessHeap(), 0, strlen(s) + 1);
+ strcpy(d, s);
+ return d;
+}
+
int
s_int_return(void)
{
@@ -264,6 +272,26 @@ s_square_puint(puint_t p)
}
int
+s_sum_puints(puints_t *p)
+{
+ int sum = 0;
+ int i;
+ for (i = 0; i < p->n; ++i)
+ sum += atoi(p->ps[i]);
+ return sum;
+}
+
+int
+s_sum_cpuints(cpuints_t *p)
+{
+ int sum = 0;
+ int i;
+ for (i = 0; i < p->n; ++i)
+ sum += atoi(p->ps[i]);
+ return sum;
+}
+
+int
s_dot_copy_vectors(vector_t u, vector_t v)
{
return u.x * v.x + u.y * v.y + u.z * v.z;
@@ -724,9 +752,35 @@ pointer_tests(void)
test_list_t *list = make_list(make_list(make_list(null_list())));
test_us_t tus = {{p1}};
int *pa[4];
+ puints_t pus;
+ cpuints_t cpus;
ok(test_list_length(list) == 3, "RPC test_list_length\n");
ok(square_puint(p1) == 121, "RPC square_puint\n");
+ pus.n = 4;
+ pus.ps = HeapAlloc(GetProcessHeap(), 0, pus.n * sizeof pus.ps[0]);
+ pus.ps[0] = xstrdup("5");
+ pus.ps[1] = xstrdup("6");
+ pus.ps[2] = xstrdup("7");
+ pus.ps[3] = xstrdup("8");
+ ok(sum_puints(&pus) == 26, "RPC sum_puints\n");
+ HeapFree(GetProcessHeap(), 0, pus.ps[0]);
+ HeapFree(GetProcessHeap(), 0, pus.ps[1]);
+ HeapFree(GetProcessHeap(), 0, pus.ps[2]);
+ HeapFree(GetProcessHeap(), 0, pus.ps[3]);
+ HeapFree(GetProcessHeap(), 0, pus.ps);
+ cpus.n = 4;
+ cpus.ps = HeapAlloc(GetProcessHeap(), 0, cpus.n * sizeof cpus.ps[0]);
+ cpus.ps[0] = xstrdup("5");
+ cpus.ps[1] = xstrdup("6");
+ cpus.ps[2] = xstrdup("7");
+ cpus.ps[3] = xstrdup("8");
+ ok(sum_cpuints(&cpus) == 26, "RPC sum_puints\n");
+ HeapFree(GetProcessHeap(), 0, cpus.ps[0]);
+ HeapFree(GetProcessHeap(), 0, cpus.ps[1]);
+ HeapFree(GetProcessHeap(), 0, cpus.ps[2]);
+ HeapFree(GetProcessHeap(), 0, cpus.ps[3]);
+ HeapFree(GetProcessHeap(), 0, cpus.ps);
ok(square_test_us(&tus) == 121, "RPC square_test_us\n");
pa[0] = &a[0];
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 6233a1f..807bf44 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -153,6 +153,22 @@ cpp_quote("#endif")
typedef [wire_marshal(int)] void *puint_t;
int square_puint(puint_t p);
+
+ typedef struct
+ {
+ [size_is(n)] puint_t *ps;
+ int n;
+ } puints_t;
+
+ /* Same thing as puints_t, but make it complex (needs padding). */
+ typedef struct
+ {
+ [size_is(n)] puint_t *ps;
+ char n;
+ } cpuints_t;
+
+ int sum_puints(puints_t *p);
+ int sum_cpuints(cpuints_t *p);
int dot_copy_vectors(vector_t u, vector_t v);
typedef struct wire_us *wire_us_t;
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 2643f49..8de9b9f 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -101,7 +101,9 @@ int is_void(const type_t *t)
int is_conformant_array(const type_t *t)
{
- return t->type == RPC_FC_CARRAY || t->type == RPC_FC_CVARRAY;
+ return t->type == RPC_FC_CARRAY
+ || t->type == RPC_FC_CVARRAY
+ || (t->type == RPC_FC_BOGUS_ARRAY && t->size_is);
}
void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 96e9891..6a93995 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1434,24 +1434,24 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr,
if (is_array(v->type))
{
const type_t *rt = v->type->ref;
- switch (rt->type)
- {
- case RPC_FC_BOGUS_STRUCT:
- case RPC_FC_NON_ENCAPSULATED_UNION:
- case RPC_FC_ENCAPSULATED_UNION:
- case RPC_FC_ENUM16:
+ if (is_user_type(rt))
v->type->type = RPC_FC_BOGUS_ARRAY;
- break;
- /* FC_RP should be above, but widl overuses these, and will break things. */
- case RPC_FC_UP:
- case RPC_FC_RP:
- if (rt->ref->type == RPC_FC_IP)
- v->type->type = RPC_FC_BOGUS_ARRAY;
- break;
- default:
- if (is_user_type(rt))
- v->type->type = RPC_FC_BOGUS_ARRAY;
- }
+ else
+ switch (rt->type)
+ {
+ case RPC_FC_BOGUS_STRUCT:
+ case RPC_FC_NON_ENCAPSULATED_UNION:
+ case RPC_FC_ENCAPSULATED_UNION:
+ case RPC_FC_ENUM16:
+ v->type->type = RPC_FC_BOGUS_ARRAY;
+ break;
+ /* FC_RP should be above, but widl overuses these, and will break things. */
+ case RPC_FC_UP:
+ case RPC_FC_RP:
+ if (rt->ref->type == RPC_FC_IP)
+ v->type->type = RPC_FC_BOGUS_ARRAY;
+ break;
+ }
}
}
@@ -1859,6 +1859,7 @@ static int get_struct_type(var_list_t *fields)
case RPC_FC_OP:
case RPC_FC_CARRAY:
case RPC_FC_CVARRAY:
+ case RPC_FC_BOGUS_ARRAY:
has_pointer = 1;
break;
@@ -1897,15 +1898,9 @@ static int get_struct_type(var_list_t *fields)
/* fallthru - treat it as complex */
/* as soon as we see one of these these members, it's bogus... */
- case RPC_FC_IP:
case RPC_FC_ENCAPSULATED_UNION:
case RPC_FC_NON_ENCAPSULATED_UNION:
- case RPC_FC_TRANSMIT_AS:
- case RPC_FC_REPRESENT_AS:
- case RPC_FC_PAD:
- case RPC_FC_EMBEDDED_COMPLEX:
case RPC_FC_BOGUS_STRUCT:
- case RPC_FC_BOGUS_ARRAY:
return RPC_FC_BOGUS_STRUCT;
}
}
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 53ec78c..2245524 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -1744,6 +1744,22 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
type_t *ft = f->type;
if (is_ptr(ft))
write_pointer_tfs(file, ft, tfsoff);
+ else if (!ft->declarray && is_conformant_array(ft))
+ {
+ unsigned int absoff = ft->typestring_offset;
+ short reloff = absoff - (*tfsoff + 2);
+ int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
+ /* FIXME: We need to store pointer attributes for arrays
+ so we don't lose pointer_default info. */
+ if (ptr_type == 0)
+ ptr_type = RPC_FC_UP;
+ print_file(file, 0, "/* %d */\n", *tfsoff);
+ print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
+ string_of_type(ptr_type));
+ print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+ reloff, reloff, absoff);
+ *tfsoff += 4;
+ }
}
if (type->ptrdesc == *tfsoff)
type->ptrdesc = 0;
More information about the wine-cvs
mailing list