diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 76d6f013c2c..b65dc91c753 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -210,6 +210,21 @@ s_sum_cs(cs_t *cs) return s_sum_conf_array(cs->ca, cs->n); } +int +s_sum_cps(cps_t *cps) +{ + int sum = 0; + int i; + + for (i = 0; i < *cps->pn; ++i) + sum += cps->ca1[i]; + + for (i = 0; i < 2 * cps->n; ++i) + sum += cps->ca2[i]; + + return sum; +} + void s_stop(void) { @@ -393,7 +408,9 @@ array_tests(void) }; static int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; static vector_t vs[2] = {{1, -2, 3}, {4, -5, -6}}; + cps_t cps; cs_t *cs; + int n; ok(sum_fixed_int_3d(m) == 4116, "RPC sum_fixed_int_3d\n"); @@ -417,6 +434,13 @@ array_tests(void) cs->ca[4] = -4; ok(sum_cs(cs) == 1, "RPC sum_cs\n"); HeapFree(GetProcessHeap(), 0, cs); + + n = 5; + cps.pn = &n; + cps.ca1 = &c[2]; + cps.n = 3; + cps.ca2 = &c[3]; + ok(sum_cps(&cps) == 53, "RPC sum_cps\n"); } static void diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index 213a8831d66..a7b3df7c4f9 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -119,7 +119,16 @@ interface IServer [size_is(n)] int ca[]; } cs_t; + typedef struct + { + int *pn; + [size_is(*pn)] int *ca1; + [size_is(n * 2)] int *ca2; + int n; + } cps_t; + int sum_cs(cs_t *cs); + int sum_cps(cps_t *cps); void stop(void); } diff --git a/tools/widl/parser.y b/tools/widl/parser.y index b5c18658042..b5826730ec8 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1387,7 +1387,6 @@ static var_t *make_var(char *name) v->args = NULL; v->attrs = NULL; v->eval = NULL; - v->corrdesc = 0; return v; } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 8f4c9264ec5..e3d529259ff 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -62,7 +62,7 @@ struct expr_eval_routine static size_t fields_memsize(const var_list_t *fields, unsigned int *align); static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff); static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, - const char *name, int level, unsigned int *tfsoff); + const char *name, int write_ptr, unsigned int *tfsoff); const char *string_of_type(unsigned char type) { @@ -160,32 +160,6 @@ static int is_embedded_complex(const type_t *type) return is_struct(tc) || is_union(tc) || is_array(type); } -static long field_offset(const type_t *strct, const char *name, var_t **pfield) -{ - long offset = 0; - var_list_t *fields = strct->fields; - var_t *f; - - if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) - { - unsigned int align = 0; - - if (f->name != NULL && strcmp(name, f->name) == 0) - { - if (pfield) *pfield = f; - return offset; - } - else - { - /* FIXME: handle possible padding */ - offset += type_memsize(f->type, &align); - } - } - - if (pfield) *pfield = NULL; - return -1; -} - static int compare_expr(const expr_t *a, const expr_t *b) { int ret; @@ -442,7 +416,8 @@ static int write_base_type(FILE *file, const type_t *type, unsigned int *typestr } /* write conformance / variance descriptor */ -static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr) +static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, + unsigned int baseoff, const expr_t *expr) { unsigned char operator_type = 0; const char *operator_string = "no operators"; @@ -526,18 +501,19 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_ if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry ) { unsigned int align = 0; - offset -= type_memsize(var->type, &align); /* FIXME: take alignment into account */ if (!strcmp(var->name, subexpr->u.sval)) { correlation_variable = var->type; break; } + offset += type_memsize(var->type, &align); } if (!correlation_variable) error("write_conf_or_var_desc: couldn't find variable %s in structure\n", subexpr->u.sval); + offset -= baseoff; correlation_type = RPC_FC_NORMAL_CONFORMANCE; } else @@ -819,7 +795,7 @@ static int processed(const type_t *type) } static void write_member_type(FILE *file, type_t *type, const var_t *field, - unsigned int *tfsoff) + unsigned int *corroff, unsigned int *tfsoff) { if (is_ptr(type)) { @@ -828,10 +804,19 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field, } else if (is_embedded_complex(type)) { - size_t absoff = (field && field->corrdesc - ? field->corrdesc - : type->typestring_offset); - short reloff = absoff - (*tfsoff + 2); + size_t absoff; + short reloff; + + if (is_union(type->type) && is_attr(field->attrs, ATTR_SWITCHIS)) + { + absoff = *corroff; + *corroff += 8; + } + else + { + absoff = type->typestring_offset; + } + reloff = absoff - (*tfsoff + 2); print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n"); /* FIXME: actually compute necessary padding */ @@ -855,6 +840,35 @@ static void write_end(FILE *file, unsigned int *tfsoff) *tfsoff += 1; } +static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) +{ + unsigned int offset = 0; + var_list_t *fs = type->fields; + var_t *f; + + if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) + { + unsigned int align = 0; + type_t *ft = f->type; + if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS)) + { + unsigned int absoff = ft->typestring_offset; + short reloff = absoff - (*tfsoff + 6); + print_file(file, 0, "/* %d */\n", *tfsoff); + print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type)); + print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG); + write_conf_or_var_desc(file, current_func, current_structure, offset, + get_attrp(f->attrs, ATTR_SWITCHIS)); + print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *tfsoff += 8; + } + + /* FIXME: take alignment into account */ + offset += type_memsize(ft, &align); + } +} + static size_t write_pointer_description(FILE *file, type_t *type, size_t mem_offset, int level, unsigned int *typestring_offset) { @@ -959,6 +973,8 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, } else if (type->size_is) { + unsigned int align = 0; + if (rtype == RPC_FC_CHAR) WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); else @@ -966,7 +982,12 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED); *typestring_offset += 2; - *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, type->size_is); + *typestring_offset += write_conf_or_var_desc( + file, current_func, current_structure, + (type->declarray && current_structure + ? type_memsize(current_structure, &align) + : 0), + type->size_is); return start_offset; } @@ -997,7 +1018,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type pointer_type = RPC_FC_RP; has_pointer = FALSE; - if (write_embedded_types(file, attrs, type, name, 0, typestring_offset)) + if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset)) has_pointer = TRUE; size = type_memsize(type, &align); @@ -1011,9 +1032,14 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); *typestring_offset += 2; + align = 0; if (type->type != RPC_FC_BOGUS_ARRAY) { unsigned char tc = type->type; + unsigned int baseoff + = type->declarray && current_structure + ? type_memsize(current_structure, &align) + : 0; if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY) { @@ -1028,8 +1054,8 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type if (is_conformant_array(type)) *typestring_offset - += write_conf_or_var_desc(file, current_func, - current_structure, size_is); + += write_conf_or_var_desc(file, current_func, current_structure, + baseoff, size_is); if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY) { @@ -1053,8 +1079,8 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type if (length_is) *typestring_offset - += write_conf_or_var_desc(file, current_func, - current_structure, length_is); + += write_conf_or_var_desc(file, current_func, current_structure, + baseoff, length_is); if (has_pointer) { @@ -1066,7 +1092,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, typestring_offset); + write_member_type(file, type->ref, NULL, NULL, typestring_offset); write_end(file, typestring_offset); } else @@ -1089,7 +1115,8 @@ static const var_t *find_array_or_string_in_struct(const type_t *type) return NULL; } -static void write_struct_members(FILE *file, const type_t *type, unsigned int *typestring_offset) +static void write_struct_members(FILE *file, const type_t *type, + unsigned int *corroff, unsigned int *typestring_offset) { const var_t *field; @@ -1097,7 +1124,7 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned int *t { type_t *ft = field->type; if (!ft->declarray || !is_conformant_array(ft)) - write_member_type(file, ft, field, typestring_offset); + write_member_type(file, ft, field, corroff, typestring_offset); } write_end(file, typestring_offset); @@ -1106,32 +1133,37 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned int *t static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff) { + const type_t *save_current_structure = current_structure; unsigned int total_size; const var_t *array; size_t start_offset; size_t array_offset; - int has_pointers; + int has_pointers = 0; unsigned int align = 0; + unsigned int corroff; + var_t *f; guard_rec(type); + current_structure = type; total_size = type_memsize(type, &align); if (total_size > USHRT_MAX) error("structure size for %s exceeds %d bytes by %d bytes\n", name, USHRT_MAX, total_size - USHRT_MAX); - has_pointers = write_embedded_types(file, NULL, type, name, 0, tfsoff); + if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry) + has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name, + FALSE, tfsoff); array = find_array_or_string_in_struct(type); if (array && !processed(array->type)) - { - current_structure = type; array_offset = is_attr(array->attrs, ATTR_STRING) ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff) : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); - current_structure = NULL; - } + + corroff = *tfsoff; + write_descriptors(file, type, tfsoff); start_offset = *tfsoff; update_tfsoff(type, start_offset, file); @@ -1171,10 +1203,9 @@ static size_t write_struct_tfs(FILE *file, type_t *type, *tfsoff += 1; } - current_structure = type; - write_struct_members(file, type, tfsoff); - current_structure = NULL; + write_struct_members(file, type, &corroff, tfsoff); + current_structure = save_current_structure; return start_offset; } @@ -1230,8 +1261,7 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff) *tfsoff += 2; } -static size_t write_union_tfs(FILE *file, type_t *type, const char *name, - unsigned int *tfsoff) +static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) { unsigned int align = 0; unsigned int start_offset; @@ -1244,14 +1274,13 @@ static size_t write_union_tfs(FILE *file, type_t *type, const char *name, guard_rec(type); - /* use a level of 1 so pointers always get written */ - write_embedded_types(file, NULL, type, name, 1, tfsoff); - if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) { expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); if (cases) nbranch += list_count(cases); + if (f->type) + write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); } start_offset = *tfsoff; @@ -1321,7 +1350,7 @@ static size_t write_ip_tfs(FILE *file, const func_t *func, const type_t *type, c expr.is_const = FALSE; print_file(file, 2, "0x2f, /* FC_IP */\n"); print_file(file, 2, "0x5c, /* FC_PAD */\n"); - *typeformat_offset += write_conf_or_var_desc(file, func, NULL, &expr) + 2; + *typeformat_offset += write_conf_or_var_desc(file, func, NULL, 0, &expr) + 2; } else { @@ -1404,7 +1433,7 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f return write_struct_tfs(file, type, var->name, typeformat_offset); case RPC_FC_ENCAPSULATED_UNION: case RPC_FC_NON_ENCAPSULATED_UNION: - return write_union_tfs(file, type, var->name, typeformat_offset); + return write_union_tfs(file, type, typeformat_offset); case RPC_FC_IGNORE: case RPC_FC_BIND_PRIMITIVE: /* nothing to do */ @@ -1475,92 +1504,19 @@ static void set_tfswrite(type_t *type, int val) } static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, - const char *name, int level, unsigned int *tfsoff) + const char *name, int write_ptr, unsigned int *tfsoff) { - var_list_t *fields = type->fields; int retmask = 0; - size_t offset = 0; - var_t *f; - if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) - { - unsigned int align = 0; - type_t *ft = f->type; - - if (!ft) continue; - else if (ft->type == RPC_FC_NON_ENCAPSULATED_UNION) - { - expr_t *swexp = get_attrp(f->attrs, ATTR_SWITCHIS); - const char *swname; - var_t *swvar; - size_t corroff; - unsigned char corrdesc, op = 0; - short creloff, ureloff; - - if (swexp == NULL) - error("union %s needs a switch_is attribute\n", f->name); - if (swexp->type != EXPR_IDENTIFIER) - error("%s: only identifiers are supported for switch_is at this time\n", - f->name); - - if (!processed(ft)) - write_union_tfs(file, ft, f->name, tfsoff); - - swname = swexp->u.sval; - corroff = field_offset(type, swname, &swvar); - corrdesc = swvar->type->type; - creloff = corroff - offset; - - f->corrdesc = *tfsoff; - ureloff = ft->typestring_offset - (f->corrdesc + 6); - print_file(file, 0, "/* %d */\n", f->corrdesc); - print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type)); - print_file(file, 2, "0x8,\t/* FIXME: support other switch types */\n"); - print_file(file, 2, "0x%x,\t/* Corr desc: %s */\n", - corrdesc, string_of_type(corrdesc & 0xf)); - print_file(file, 2, "0x%x,\n", op); - print_file(file, 2, "NdrFcShort(0x%hx),\t/* %hd */\n", creloff, creloff); - print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", - ureloff, ureloff, ft->typestring_offset); - *tfsoff += 8; - } - else - retmask |= write_embedded_types(file, attrs, ft, f->name, - level + 1, tfsoff); - - /* FIXME: this doesn't take alignment/padding into account */ - offset += type_memsize(ft, &align); - } - /* don't generate a pointer for first-level arrays since we want to - descend into them to write their pointers, not stop here */ - else if (level == 0 && is_array(type)) - { - return write_embedded_types(file, NULL, type->ref, name, level + 1, tfsoff); - } - else if (is_ptr(type)) + if (is_ptr(type)) { type_t *ref = type->ref; if (!processed(ref) && !is_base_type(ref->type)) - { - if (is_ptr(ref)) - { - retmask |= write_embedded_types(file, attrs, ref, name, - level + 1, tfsoff); - } - else if (is_struct(ref->type)) - { - write_struct_tfs(file, ref, name, tfsoff); - } - else - { - error("write_embedded_types: type format string unknown for %s (0x%x)\n", - name, ref->type); - } - } + retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff); - /* top-level pointers are handled inline */ - if (1 < level) + /* top-level pointers are handled inline for structures */ + if (write_ptr) write_pointer_tfs(file, type, tfsoff); retmask |= 1; @@ -1571,6 +1527,16 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty { write_array_tfs(file, attrs, type, name, tfsoff); } + else if (is_struct(type->type)) + { + if (!processed(type)) + write_struct_tfs(file, type, name, tfsoff); + } + else if (is_union(type->type)) + { + if (!processed(type)) + write_union_tfs(file, type, tfsoff); + } else if (!is_base_type(type->type)) error("write_embedded_types: unknown embedded type for %s (0x%x)\n", name, type->type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 0c8acadde5c..0fe453b311a 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -227,7 +227,6 @@ struct _var_t { var_list_t *args; /* for function pointers */ attr_list_t *attrs; expr_t *eval; - size_t corrdesc; /* offset to correlation descriptor (e.g., for unions) */ /* parser-internal */ struct list entry;