From 8df79f0c999c4736326f381b59de8b31cf894beb Mon Sep 17 00:00:00 2001 From: Dan Hipschman Date: Tue, 18 Sep 2007 15:28:49 -0700 Subject: [PATCH] widl: Implement pointer descriptions for complex structures. --- 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 879e0d10c3b..2ed6de7d726 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 d84637c0898..44bb94531f5 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 ac2403844f0..fbaf9a77137 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 71885c7e213..573d88b5f9d 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; @@ -918,7 +919,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)) @@ -926,7 +928,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; @@ -946,7 +948,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)) @@ -1521,7 +1526,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 @@ -1579,7 +1584,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; } } @@ -1655,8 +1661,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) || @@ -1673,6 +1683,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 d514d546b73..2b1aaa90182 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; -- 2.11.4.GIT