Commit 978b4d4f authored by Dan Hipschman's avatar Dan Hipschman Committed by Alexandre Julliard

widl: Represent arrays with type_t.

parent f5baddf8
...@@ -162,6 +162,47 @@ s_test_list_length(test_list_t *list) ...@@ -162,6 +162,47 @@ s_test_list_length(test_list_t *list)
: 0); : 0);
} }
int
s_sum_fixed_int_3d(int m[2][3][4])
{
int i, j, k;
int sum = 0;
for (i = 0; i < 2; ++i)
for (j = 0; j < 3; ++j)
for (k = 0; k < 4; ++k)
sum += m[i][j][k];
return sum;
}
int
s_sum_conf_array(int x[], int n)
{
int *p = x, *end = p + n;
int sum = 0;
while (p < end)
sum += *p++;
return sum;
}
int
s_sum_var_array(int x[20], int n)
{
ok(0 <= n, "RPC sum_var_array\n");
ok(n <= 20, "RPC sum_var_array\n");
return s_sum_conf_array(x, n);
}
int
s_dot_two_vectors(vector_t vs[2])
{
return vs[0].x * vs[1].x + vs[0].y * vs[1].y + vs[0].z * vs[1].z;
}
void void
s_stop(void) s_stop(void)
{ {
...@@ -336,6 +377,41 @@ pointer_tests(void) ...@@ -336,6 +377,41 @@ pointer_tests(void)
} }
static void static void
array_tests(void)
{
static int m[2][3][4] =
{
{{1, 2, 3, 4}, {-1, -3, -5, -7}, {0, 2, 4, 6}},
{{1, -2, 3, -4}, {2, 3, 5, 7}, {-4, -1, -14, 4114}}
};
static int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
static vector_t vs[2] = {{1, -2, 3}, {4, -5, -6}};
ok(sum_fixed_int_3d(m) == 4116, "RPC sum_fixed_int_3d\n");
ok(sum_conf_array(c, 10) == 45, "RPC sum_conf_array\n");
ok(sum_conf_array(&c[5], 2) == 11, "RPC sum_conf_array\n");
ok(sum_conf_array(&c[7], 1) == 7, "RPC sum_conf_array\n");
ok(sum_conf_array(&c[2], 0) == 0, "RPC sum_conf_array\n");
ok(sum_var_array(c, 10) == 45, "RPC sum_conf_array\n");
ok(sum_var_array(&c[5], 2) == 11, "RPC sum_conf_array\n");
ok(sum_var_array(&c[7], 1) == 7, "RPC sum_conf_array\n");
ok(sum_var_array(&c[2], 0) == 0, "RPC sum_conf_array\n");
ok(dot_two_vectors(vs) == -4, "RPC dot_two_vectors\n");
}
static void
run_tests(void)
{
basic_tests();
union_tests();
pointer_tests();
array_tests();
}
static void
client(const char *test) client(const char *test)
{ {
if (strcmp(test, "tcp_basic") == 0) if (strcmp(test, "tcp_basic") == 0)
...@@ -348,9 +424,7 @@ client(const char *test) ...@@ -348,9 +424,7 @@ client(const char *test)
ok(RPC_S_OK == RpcStringBindingCompose(NULL, iptcp, address, port, NULL, &binding), "RpcStringBindingCompose\n"); ok(RPC_S_OK == RpcStringBindingCompose(NULL, iptcp, address, port, NULL, &binding), "RpcStringBindingCompose\n");
ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n"); ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n");
basic_tests(); run_tests();
union_tests();
pointer_tests();
ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n"); ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n");
ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n"); ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n");
...@@ -365,9 +439,7 @@ client(const char *test) ...@@ -365,9 +439,7 @@ client(const char *test)
ok(RPC_S_OK == RpcStringBindingCompose(NULL, np, address, pipe, NULL, &binding), "RpcStringBindingCompose\n"); ok(RPC_S_OK == RpcStringBindingCompose(NULL, np, address, pipe, NULL, &binding), "RpcStringBindingCompose\n");
ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n"); ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n");
basic_tests(); run_tests();
union_tests();
pointer_tests();
stop(); stop();
ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n"); ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n");
......
...@@ -108,5 +108,9 @@ interface IServer ...@@ -108,5 +108,9 @@ interface IServer
} test_list_t; } test_list_t;
int test_list_length(test_list_t *ls); int test_list_length(test_list_t *ls);
int sum_fixed_int_3d(int m[2][3][4]);
int sum_conf_array([size_is(n)] int x[], int n);
int sum_var_array([length_is(n)] int x[20], int n);
int dot_two_vectors(vector_t vs[2]);
void stop(void); void stop(void);
} }
...@@ -115,8 +115,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) ...@@ -115,8 +115,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
} }
} }
write_type(client, def->type); write_type_left(client, def->type);
fprintf(client, " "); if (needs_space_after(def->type))
fprintf(client, " ");
write_prefix_name(client, prefix_client, def); write_prefix_name(client, prefix_client, def);
fprintf(client, "(\n"); fprintf(client, "(\n");
indent++; indent++;
...@@ -135,7 +136,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) ...@@ -135,7 +136,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
if (!is_void(def->type)) if (!is_void(def->type))
{ {
print_client(""); print_client("");
write_type(client, def->type); write_type_left(client, def->type);
fprintf(client, " _RetVal;\n"); fprintf(client, " _RetVal;\n");
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
...@@ -96,22 +97,9 @@ int is_void(const type_t *t) ...@@ -96,22 +97,9 @@ int is_void(const type_t *t)
return 0; return 0;
} }
int is_conformant_array( const array_dims_t *array ) int is_conformant_array(const type_t *t)
{ {
expr_t *dim; return t->type == RPC_FC_CARRAY || t->type == RPC_FC_CVARRAY;
if (!array) return 0;
dim = LIST_ENTRY( list_head( array ), expr_t, entry );
return !dim->is_const;
}
int is_non_void(const expr_list_t *list)
{
const expr_t *expr;
if (list)
LIST_FOR_EACH_ENTRY( expr, list, const expr_t, entry )
if (expr->type != EXPR_VOID) return 1;
return 0;
} }
void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
...@@ -141,34 +129,12 @@ void write_prefix_name(FILE *h, const char *prefix, const var_t *v) ...@@ -141,34 +129,12 @@ void write_prefix_name(FILE *h, const char *prefix, const var_t *v)
write_name(h, v); write_name(h, v);
} }
void write_array(FILE *h, array_dims_t *dims, int field)
{
expr_t *v;
if (!dims) return;
fprintf(h, "[");
LIST_FOR_EACH_ENTRY( v, dims, expr_t, entry )
{
if (v->is_const)
fprintf(h, "%ld", v->cval); /* statically sized array */
else
if (field) fprintf(h, "1"); /* dynamically sized array */
if (list_next( dims, &v->entry ))
fprintf(h, ", ");
}
fprintf(h, "]");
}
static void write_field(FILE *h, var_t *v) static void write_field(FILE *h, var_t *v)
{ {
if (!v) return; if (!v) return;
if (v->type) { if (v->type) {
indent(h, 0); const char *name = v->name;
write_type(h, v->type); if (name == NULL) {
if (v->name)
fprintf(h, " %s", v->name);
else {
/* not all C/C++ compilers support anonymous structs and unions */
switch (v->type->type) { switch (v->type->type) {
case RPC_FC_STRUCT: case RPC_FC_STRUCT:
case RPC_FC_CVSTRUCT: case RPC_FC_CVSTRUCT:
...@@ -177,17 +143,18 @@ static void write_field(FILE *h, var_t *v) ...@@ -177,17 +143,18 @@ static void write_field(FILE *h, var_t *v)
case RPC_FC_PSTRUCT: case RPC_FC_PSTRUCT:
case RPC_FC_BOGUS_STRUCT: case RPC_FC_BOGUS_STRUCT:
case RPC_FC_ENCAPSULATED_UNION: case RPC_FC_ENCAPSULATED_UNION:
fprintf(h, " DUMMYSTRUCTNAME"); name = "DUMMYSTRUCTNAME";
break; break;
case RPC_FC_NON_ENCAPSULATED_UNION: case RPC_FC_NON_ENCAPSULATED_UNION:
fprintf(h, " DUMMYUNIONNAME"); name = "DUMMYUNIONNAME";
break; break;
default: default:
/* ? */ /* ? */
break; break;
} }
} }
write_array(h, v->array, 1); indent(h, 0);
write_type(h, v->type, TRUE, "%s", name);
fprintf(h, ";\n"); fprintf(h, ";\n");
} }
} }
...@@ -218,16 +185,18 @@ static void write_enums(FILE *h, var_list_t *enums) ...@@ -218,16 +185,18 @@ static void write_enums(FILE *h, var_list_t *enums)
fprintf(h, "\n"); fprintf(h, "\n");
} }
static int needs_space_after(type_t *t) int needs_space_after(type_t *t)
{ {
return t->kind == TKIND_ALIAS || ! is_ptr(t); return (t->kind == TKIND_ALIAS
|| (!is_ptr(t) && (!is_conformant_array(t) || t->declarray)));
} }
void write_type(FILE *h, type_t *t) void write_type_left(FILE *h, type_t *t)
{ {
if (t->is_const) fprintf(h, "const "); if (t->is_const) fprintf(h, "const ");
if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name); if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
else if (t->declarray) write_type_left(h, t->ref);
else { else {
if (t->sign > 0) fprintf(h, "signed "); if (t->sign > 0) fprintf(h, "signed ");
else if (t->sign < 0) fprintf(h, "unsigned "); else if (t->sign < 0) fprintf(h, "unsigned ");
...@@ -279,7 +248,9 @@ void write_type(FILE *h, type_t *t) ...@@ -279,7 +248,9 @@ void write_type(FILE *h, type_t *t)
case RPC_FC_UP: case RPC_FC_UP:
case RPC_FC_FP: case RPC_FC_FP:
case RPC_FC_OP: case RPC_FC_OP:
if (t->ref) write_type(h, t->ref); case RPC_FC_CARRAY:
case RPC_FC_CVARRAY:
write_type_left(h, t->ref);
fprintf(h, "%s*", needs_space_after(t->ref) ? " " : ""); fprintf(h, "%s*", needs_space_after(t->ref) ? " " : "");
break; break;
default: default:
...@@ -288,6 +259,32 @@ void write_type(FILE *h, type_t *t) ...@@ -288,6 +259,32 @@ void write_type(FILE *h, type_t *t)
} }
} }
void write_type_right(FILE *h, type_t *t, int is_field)
{
if (t->declarray) {
if (is_conformant_array(t)) {
fprintf(h, "[%s]", is_field ? "1" : "");
t = t->ref;
}
for ( ; t->declarray; t = t->ref)
fprintf(h, "[%lu]", t->dim);
}
}
void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...)
{
write_type_left(h, t);
if (fmt) {
va_list args;
va_start(args, fmt);
if (needs_space_after(t))
fprintf(h, " ");
vfprintf(h, fmt, args);
va_end(args);
}
write_type_right(h, t, is_field);
}
struct user_type struct user_type
{ {
...@@ -354,8 +351,8 @@ void write_user_types(void) ...@@ -354,8 +351,8 @@ void write_user_types(void)
void write_typedef(type_t *type) void write_typedef(type_t *type)
{ {
fprintf(header, "typedef "); fprintf(header, "typedef ");
write_type(header, type->orig); write_type(header, type->orig, FALSE, "%s", type->name);
fprintf(header, "%s%s;\n", needs_space_after(type->orig) ? " " : "", type->name); fprintf(header, ";\n");
} }
void write_expr(FILE *h, const expr_t *e, int brackets) void write_expr(FILE *h, const expr_t *e, int brackets)
...@@ -392,13 +389,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets) ...@@ -392,13 +389,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets)
break; break;
case EXPR_CAST: case EXPR_CAST:
fprintf(h, "("); fprintf(h, "(");
write_type(h, e->u.tref); write_type(h, e->u.tref, FALSE, NULL);
fprintf(h, ")"); fprintf(h, ")");
write_expr(h, e->ref, 1); write_expr(h, e->ref, 1);
break; break;
case EXPR_SIZEOF: case EXPR_SIZEOF:
fprintf(h, "sizeof("); fprintf(h, "sizeof(");
write_type(h, e->u.tref); write_type(h, e->u.tref, FALSE, NULL);
fprintf(h, ")"); fprintf(h, ")");
break; break;
case EXPR_SHL: case EXPR_SHL:
...@@ -447,9 +444,7 @@ void write_constdef(const var_t *v) ...@@ -447,9 +444,7 @@ void write_constdef(const var_t *v)
void write_externdef(const var_t *v) void write_externdef(const var_t *v)
{ {
fprintf(header, "extern const "); fprintf(header, "extern const ");
write_type(header, v->type); write_type(header, v->type, FALSE, "%s", v->name);
if (v->name)
fprintf(header, " %s", v->name);
fprintf(header, ";\n\n"); fprintf(header, ";\n\n");
} }
...@@ -573,9 +568,9 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i ...@@ -573,9 +568,9 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
} }
else fprintf(h, ","); else fprintf(h, ",");
} }
write_type(h, arg->type);
if (arg->args) if (arg->args)
{ {
write_type_left(h, arg->type);
fprintf(h, " (STDMETHODCALLTYPE *"); fprintf(h, " (STDMETHODCALLTYPE *");
write_name(h,arg); write_name(h,arg);
fprintf(h, ")("); fprintf(h, ")(");
...@@ -583,12 +578,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i ...@@ -583,12 +578,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
fprintf(h, ")"); fprintf(h, ")");
} }
else else
{ write_type(h, arg->type, FALSE, "%s", arg->name);
if (needs_space_after(arg->type))
fprintf(h, " ");
write_name(h, arg);
}
write_array(h, arg->array, 0);
count++; count++;
} }
if (do_indent) indentation--; if (do_indent) indentation--;
...@@ -606,7 +596,7 @@ static void write_cpp_method_def(const type_t *iface) ...@@ -606,7 +596,7 @@ static void write_cpp_method_def(const type_t *iface)
if (!is_callas(def->attrs)) { if (!is_callas(def->attrs)) {
indent(header, 0); indent(header, 0);
fprintf(header, "virtual "); fprintf(header, "virtual ");
write_type(header, def->type); write_type_left(header, def->type);
fprintf(header, " STDMETHODCALLTYPE "); fprintf(header, " STDMETHODCALLTYPE ");
write_name(header, def); write_name(header, def);
fprintf(header, "(\n"); fprintf(header, "(\n");
...@@ -631,7 +621,7 @@ static void do_write_c_method_def(const type_t *iface, const char *name) ...@@ -631,7 +621,7 @@ static void do_write_c_method_def(const type_t *iface, const char *name)
const var_t *def = cur->def; const var_t *def = cur->def;
if (!is_callas(def->attrs)) { if (!is_callas(def->attrs)) {
indent(header, 0); indent(header, 0);
write_type(header, def->type); write_type_left(header, def->type);
fprintf(header, " (STDMETHODCALLTYPE *"); fprintf(header, " (STDMETHODCALLTYPE *");
write_name(header, def); write_name(header, def);
fprintf(header, ")(\n"); fprintf(header, ")(\n");
...@@ -664,7 +654,7 @@ static void write_method_proto(const type_t *iface) ...@@ -664,7 +654,7 @@ static void write_method_proto(const type_t *iface)
if (!is_local(def->attrs)) { if (!is_local(def->attrs)) {
/* proxy prototype */ /* proxy prototype */
write_type(header, def->type); write_type_left(header, def->type);
fprintf(header, " CALLBACK %s_", iface->name); fprintf(header, " CALLBACK %s_", iface->name);
write_name(header, def); write_name(header, def);
fprintf(header, "_Proxy(\n"); fprintf(header, "_Proxy(\n");
...@@ -687,14 +677,14 @@ static void write_method_proto(const type_t *iface) ...@@ -687,14 +677,14 @@ static void write_method_proto(const type_t *iface)
if (&m->entry != iface->funcs) { if (&m->entry != iface->funcs) {
const var_t *mdef = m->def; const var_t *mdef = m->def;
/* proxy prototype - use local prototype */ /* proxy prototype - use local prototype */
write_type(header, mdef->type); write_type_left(header, mdef->type);
fprintf(header, " CALLBACK %s_", iface->name); fprintf(header, " CALLBACK %s_", iface->name);
write_name(header, mdef); write_name(header, mdef);
fprintf(header, "_Proxy(\n"); fprintf(header, "_Proxy(\n");
write_args(header, m->args, iface->name, 1, TRUE); write_args(header, m->args, iface->name, 1, TRUE);
fprintf(header, ");\n"); fprintf(header, ");\n");
/* stub prototype - use remotable prototype */ /* stub prototype - use remotable prototype */
write_type(header, def->type); write_type_left(header, def->type);
fprintf(header, " __RPC_STUB %s_", iface->name); fprintf(header, " __RPC_STUB %s_", iface->name);
write_name(header, mdef); write_name(header, mdef);
fprintf(header, "_Stub(\n"); fprintf(header, "_Stub(\n");
...@@ -713,7 +703,7 @@ static void write_function_proto(const type_t *iface, const func_t *fun, const c ...@@ -713,7 +703,7 @@ static void write_function_proto(const type_t *iface, const func_t *fun, const c
var_t *def = fun->def; var_t *def = fun->def;
/* FIXME: do we need to handle call_as? */ /* FIXME: do we need to handle call_as? */
write_type(header, def->type); write_type_left(header, def->type);
fprintf(header, " "); fprintf(header, " ");
write_prefix_name(header, prefix, def); write_prefix_name(header, prefix, def);
fprintf(header, "(\n"); fprintf(header, "(\n");
......
...@@ -28,11 +28,14 @@ extern int is_attr(const attr_list_t *list, enum attr_type t); ...@@ -28,11 +28,14 @@ extern int is_attr(const attr_list_t *list, enum attr_type t);
extern void *get_attrp(const attr_list_t *list, enum attr_type t); 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 unsigned long get_attrv(const attr_list_t *list, enum attr_type t);
extern int is_void(const type_t *t); extern int is_void(const type_t *t);
extern int is_conformant_array( const array_dims_t *array ); extern int is_conformant_array(const type_t *t);
extern int is_non_void(const expr_list_t *list);
extern void write_name(FILE *h, const var_t *v); 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 void write_prefix_name(FILE *h, const char *prefix, const var_t *v);
extern void write_type(FILE *h, type_t *t); extern const char* get_name(const var_t *v);
extern void write_type_left(FILE *h, type_t *t);
extern void write_type_right(FILE *h, type_t *t, int is_field);
extern void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...);
extern int needs_space_after(type_t *t);
extern int is_object(const attr_list_t *list); extern int is_object(const attr_list_t *list);
extern int is_local(const attr_list_t *list); extern int is_local(const attr_list_t *list);
extern const var_t *is_callas(const attr_list_t *list); extern const var_t *is_callas(const attr_list_t *list);
...@@ -59,16 +62,14 @@ static inline int last_ptr(const type_t *type) ...@@ -59,16 +62,14 @@ static inline int last_ptr(const type_t *type)
return is_ptr(type) && !is_ptr(type->ref); return is_ptr(type) && !is_ptr(type->ref);
} }
static inline int is_string_type(const attr_list_t *attrs, const type_t *type, const array_dims_t *array) static inline int last_array(const type_t *type)
{ {
return (is_attr(attrs, ATTR_STRING) && return is_array(type) && !is_array(type->ref);
((last_ptr(type) && !array) || (!is_ptr(type) && array)));
} }
static inline int is_array_type(const attr_list_t *attrs, const type_t *type, const array_dims_t *array) static inline int is_string_type(const attr_list_t *attrs, const type_t *type)
{ {
return ((last_ptr(type) && !array && is_attr(attrs, ATTR_SIZEIS)) || return is_attr(attrs, ATTR_STRING) && (last_ptr(type) || last_array(type));
(!is_ptr(type) && array));
} }
#endif #endif
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "parser.h" #include "parser.h"
#include "header.h" #include "header.h"
#include "typelib.h" #include "typelib.h"
#include "typegen.h"
#if defined(YYBYACC) #if defined(YYBYACC)
/* Berkeley yacc (byacc) doesn't seem to know about these */ /* Berkeley yacc (byacc) doesn't seem to know about these */
...@@ -303,12 +304,24 @@ int_statements: { $$ = NULL; } ...@@ -303,12 +304,24 @@ int_statements: { $$ = NULL; }
statement: ';' {} statement: ';' {}
| constdef ';' { if (!parse_only && do_header) { write_constdef($1); } } | constdef ';' { if (!parse_only && do_header) { write_constdef($1); } }
| cppquote {} | cppquote {}
| enumdef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } | enumdef ';' { if (!parse_only && do_header) {
write_type(header, $1, FALSE, NULL);
fprintf(header, ";\n\n");
}
}
| externdef ';' { if (!parse_only && do_header) { write_externdef($1); } } | externdef ';' { if (!parse_only && do_header) { write_externdef($1); } }
| import {} | import {}
| structdef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } | structdef ';' { if (!parse_only && do_header) {
write_type(header, $1, FALSE, NULL);
fprintf(header, ";\n\n");
}
}
| typedef ';' {} | typedef ';' {}
| uniondef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } | uniondef ';' { if (!parse_only && do_header) {
write_type(header, $1, FALSE, NULL);
fprintf(header, ";\n\n");
}
}
; ;
cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only && do_header) fprintf(header, "%s\n", $3); } cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only && do_header) fprintf(header, "%s\n", $3); }
...@@ -346,18 +359,18 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); } ...@@ -346,18 +359,18 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); }
/* split into two rules to get bison to resolve a tVOID conflict */ /* split into two rules to get bison to resolve a tVOID conflict */
arg: attributes type pident array { $$ = $3->var; arg: attributes type pident array { $$ = $3->var;
$$->attrs = $1;
set_type($$, $2, $3->ptr_level, $4); set_type($$, $2, $3->ptr_level, $4);
free($3); free($3);
$$->attrs = $1;
} }
| type pident array { $$ = $2->var; | type pident array { $$ = $2->var;
set_type($$, $1, $2->ptr_level, $3); set_type($$, $1, $2->ptr_level, $3);
free($2); free($2);
} }
| attributes type pident '(' m_args ')' { $$ = $3->var; | attributes type pident '(' m_args ')' { $$ = $3->var;
$$->attrs = $1;
set_type($$, $2, $3->ptr_level - 1, NULL); set_type($$, $2, $3->ptr_level - 1, NULL);
free($3); free($3);
$$->attrs = $1;
$$->args = $5; $$->args = $5;
} }
| type pident '(' m_args ')' { $$ = $2->var; | type pident '(' m_args ')' { $$ = $2->var;
...@@ -597,18 +610,18 @@ field: s_field ';' { $$ = $1; } ...@@ -597,18 +610,18 @@ field: s_field ';' { $$ = $1; }
; ;
s_field: m_attributes type pident array { $$ = $3->var; s_field: m_attributes type pident array { $$ = $3->var;
$$->attrs = $1;
set_type($$, $2, $3->ptr_level, $4); set_type($$, $2, $3->ptr_level, $4);
free($3); free($3);
$$->attrs = $1;
} }
; ;
funcdef: funcdef:
m_attributes type callconv pident m_attributes type callconv pident
'(' m_args ')' { var_t *v = $4->var; '(' m_args ')' { var_t *v = $4->var;
v->attrs = $1;
set_type(v, $2, $4->ptr_level, NULL); set_type(v, $2, $4->ptr_level, NULL);
free($4); free($4);
v->attrs = $1;
$$ = make_func(v, $6); $$ = make_func(v, $6);
if (is_attr(v->attrs, ATTR_IN)) { if (is_attr(v->attrs, ATTR_IN)) {
yyerror("inapplicable attribute [in] for function '%s'",$$->def->name); yyerror("inapplicable attribute [in] for function '%s'",$$->def->name);
...@@ -1199,7 +1212,11 @@ static type_t *make_type(unsigned char type, type_t *ref) ...@@ -1199,7 +1212,11 @@ static type_t *make_type(unsigned char type, type_t *ref)
t->funcs = NULL; t->funcs = NULL;
t->fields = NULL; t->fields = NULL;
t->ifaces = NULL; t->ifaces = NULL;
t->dim = 0;
t->size_is = NULL;
t->length_is = NULL;
t->typestring_offset = 0; t->typestring_offset = 0;
t->declarray = FALSE;
t->ignore = (parse_only != 0); t->ignore = (parse_only != 0);
t->is_const = FALSE; t->is_const = FALSE;
t->sign = 0; t->sign = 0;
...@@ -1213,11 +1230,106 @@ static type_t *make_type(unsigned char type, type_t *ref) ...@@ -1213,11 +1230,106 @@ static type_t *make_type(unsigned char type, type_t *ref)
static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr) static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr)
{ {
expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS);
expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS);
int sizeless, has_varconf;
expr_t *dim;
type_t *atype, **ptype;
v->type = type; v->type = type;
v->array = arr;
for ( ; 0 < ptr_level; --ptr_level) for ( ; 0 < ptr_level; --ptr_level)
v->type = make_type(RPC_FC_RP, v->type); v->type = make_type(RPC_FC_RP, v->type);
sizeless = FALSE;
if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry)
{
if (sizeless)
error("%s: only the first array dimension can be unspecified\n", v->name);
if (dim->is_const)
{
unsigned int align = 0;
size_t size = type_memsize(v->type, &align);
if (dim->cval <= 0)
error("%s: array dimension must be positive\n", v->name);
if (0xffffffffuL / size < (unsigned long) dim->cval)
error("%s: total array size is too large", v->name);
else if (0xffffuL < size * dim->cval)
v->type = make_type(RPC_FC_LGFARRAY, v->type);
else
v->type = make_type(RPC_FC_SMFARRAY, v->type);
}
else
{
sizeless = TRUE;
v->type = make_type(RPC_FC_CARRAY, v->type);
}
v->type->declarray = TRUE;
v->type->dim = dim->cval;
}
ptype = &v->type;
has_varconf = FALSE;
if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
{
if (dim->type != EXPR_VOID)
{
has_varconf = TRUE;
atype = *ptype = duptype(*ptype, 0);
if (atype->type == RPC_FC_SMFARRAY || atype->type == RPC_FC_LGFARRAY)
error("%s: cannot specify size_is for a fixed sized array\n", v->name);
if (atype->type != RPC_FC_CARRAY && !is_ptr(atype))
error("%s: size_is attribute applied to illegal type\n", v->name);
atype->type = RPC_FC_CARRAY;
atype->size_is = dim;
}
ptype = &(*ptype)->ref;
if (*ptype == NULL)
error("%s: too many expressions in size_is attribute\n", v->name);
}
ptype = &v->type;
if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
{
if (dim->type != EXPR_VOID)
{
has_varconf = TRUE;
atype = *ptype = duptype(*ptype, 0);
if (atype->type == RPC_FC_SMFARRAY)
atype->type = RPC_FC_SMVARRAY;
else if (atype->type == RPC_FC_LGFARRAY)
atype->type = RPC_FC_LGVARRAY;
else if (atype->type == RPC_FC_CARRAY)
atype->type = RPC_FC_CVARRAY;
else
error("%s: length_is attribute applied to illegal type\n", v->name);
atype->length_is = dim;
}
ptype = &(*ptype)->ref;
if (*ptype == NULL)
error("%s: too many expressions in length_is attribute\n", v->name);
}
if (has_varconf && !last_array(v->type))
{
ptype = &v->type;
for (ptype = &v->type; is_array(*ptype); ptype = &(*ptype)->ref)
{
*ptype = duptype(*ptype, 0);
(*ptype)->type = RPC_FC_BOGUS_ARRAY;
}
}
} }
static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface)
...@@ -1259,7 +1371,6 @@ static var_t *make_var(char *name) ...@@ -1259,7 +1371,6 @@ static var_t *make_var(char *name)
v->type = NULL; v->type = NULL;
v->args = NULL; v->args = NULL;
v->attrs = NULL; v->attrs = NULL;
v->array = NULL;
v->eval = NULL; v->eval = NULL;
v->corrdesc = 0; v->corrdesc = 0;
return v; return v;
...@@ -1513,24 +1624,29 @@ static int get_struct_type(var_list_t *fields) ...@@ -1513,24 +1624,29 @@ static int get_struct_type(var_list_t *fields)
continue; continue;
} }
if (is_string_type(field->attrs, field->type, field->array)) if (field->type->declarray)
{ {
has_conformance = 1; if (is_string_type(field->attrs, field->type))
has_variance = 1; {
continue; has_conformance = 1;
} has_variance = 1;
continue;
}
if (is_array_type(field->attrs, field->type, field->array)) if (is_array(field->type->ref))
{ return RPC_FC_BOGUS_STRUCT;
if (field->array && is_conformant_array(field->array))
if (is_conformant_array(field->type))
{ {
has_conformance = 1; has_conformance = 1;
if (list_next( fields, &field->entry )) if (field->type->declarray && list_next(fields, &field->entry))
yyerror("field '%s' deriving from a conformant array must be the last field in the structure", yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
field->name); field->name);
} }
if (is_attr(field->attrs, ATTR_LENGTHIS)) if (field->type->length_is)
has_variance = 1; has_variance = 1;
t = field->type->ref;
} }
switch (t->type) switch (t->type)
...@@ -1565,13 +1681,9 @@ static int get_struct_type(var_list_t *fields) ...@@ -1565,13 +1681,9 @@ static int get_struct_type(var_list_t *fields)
case RPC_FC_UP: case RPC_FC_UP:
case RPC_FC_FP: case RPC_FC_FP:
case RPC_FC_OP: case RPC_FC_OP:
has_pointer = 1;
break;
case RPC_FC_CARRAY: case RPC_FC_CARRAY:
has_conformance = 1; case RPC_FC_CVARRAY:
if (list_next( fields, &field->entry )) has_pointer = 1;
yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
field->name);
break; break;
/* /*
......
...@@ -261,7 +261,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, ...@@ -261,7 +261,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx,
int has_ret = !is_void(def->type); int has_ret = !is_void(def->type);
indent = 0; indent = 0;
write_type(proxy, def->type); write_type_left(proxy, def->type);
print_proxy( " STDMETHODCALLTYPE %s_", iface->name); print_proxy( " STDMETHODCALLTYPE %s_", iface->name);
write_name(proxy, def); write_name(proxy, def);
print_proxy( "_Proxy(\n"); print_proxy( "_Proxy(\n");
...@@ -272,7 +272,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, ...@@ -272,7 +272,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx,
/* local variables */ /* local variables */
if (has_ret) { if (has_ret) {
print_proxy( "" ); print_proxy( "" );
write_type(proxy, def->type); write_type_left(proxy, def->type);
print_proxy( " _RetVal;\n"); print_proxy( " _RetVal;\n");
} }
print_proxy( "RPC_MESSAGE _RpcMessage;\n" ); print_proxy( "RPC_MESSAGE _RpcMessage;\n" );
...@@ -408,7 +408,7 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas, ...@@ -408,7 +408,7 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas,
LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry )
{ {
fprintf(proxy, ", "); fprintf(proxy, ", ");
if (arg->array) if (arg->type->declarray)
fprintf(proxy, "*"); fprintf(proxy, "*");
write_name(proxy, arg); write_name(proxy, arg);
} }
......
...@@ -207,7 +207,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) ...@@ -207,7 +207,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
else else
fprintf(server, ",\n"); fprintf(server, ",\n");
print_server(""); print_server("");
if (var->array) if (var->type->declarray)
fprintf(server, "*"); fprintf(server, "*");
write_name(server, var); write_name(server, var);
} }
......
...@@ -49,3 +49,4 @@ void declare_stub_args( FILE *file, int indent, const func_t *func ); ...@@ -49,3 +49,4 @@ void declare_stub_args( FILE *file, int indent, const func_t *func );
int write_expr_eval_routines(FILE *file, const char *iface); int write_expr_eval_routines(FILE *file, const char *iface);
void write_expr_eval_routine_list(FILE *file, const char *iface); void write_expr_eval_routine_list(FILE *file, const char *iface);
void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ); void write_endpoints( FILE *f, const char *prefix, const str_list_t *list );
size_t type_memsize(const type_t *t, unsigned int *align);
...@@ -69,6 +69,7 @@ type_t *alias(type_t *t, const char *name) ...@@ -69,6 +69,7 @@ type_t *alias(type_t *t, const char *name)
a->name = xstrdup(name); a->name = xstrdup(name);
a->kind = TKIND_ALIAS; a->kind = TKIND_ALIAS;
a->attrs = NULL; a->attrs = NULL;
a->declarray = FALSE;
return a; return a;
} }
...@@ -82,6 +83,23 @@ int is_ptr(const type_t *t) ...@@ -82,6 +83,23 @@ int is_ptr(const type_t *t)
|| c == RPC_FC_OP; || c == RPC_FC_OP;
} }
int is_array(const type_t *t)
{
switch (t->type)
{
case RPC_FC_SMFARRAY:
case RPC_FC_LGFARRAY:
case RPC_FC_SMVARRAY:
case RPC_FC_LGVARRAY:
case RPC_FC_CARRAY:
case RPC_FC_CVARRAY:
case RPC_FC_BOGUS_ARRAY:
return TRUE;
default:
return FALSE;
}
}
/* List of oleauto types that should be recognized by name. /* List of oleauto types that should be recognized by name.
* (most of) these seem to be intrinsic types in mktyplib. */ * (most of) these seem to be intrinsic types in mktyplib. */
......
...@@ -206,9 +206,12 @@ struct _type_t { ...@@ -206,9 +206,12 @@ struct _type_t {
func_list_t *funcs; /* interfaces and modules */ func_list_t *funcs; /* interfaces and modules */
var_list_t *fields; /* interfaces, structures and enumerations */ var_list_t *fields; /* interfaces, structures and enumerations */
ifref_list_t *ifaces; /* coclasses */ ifref_list_t *ifaces; /* coclasses */
unsigned long dim; /* array dimension */
expr_t *size_is, *length_is;
type_t *orig; /* dup'd types */ type_t *orig; /* dup'd types */
unsigned int typestring_offset; unsigned int typestring_offset;
int typelib_idx; int typelib_idx;
unsigned int declarray : 1; /* if declared as an array */
unsigned int ignore : 1; unsigned int ignore : 1;
unsigned int is_const : 1; unsigned int is_const : 1;
unsigned int defined : 1; unsigned int defined : 1;
...@@ -220,7 +223,6 @@ struct _type_t { ...@@ -220,7 +223,6 @@ struct _type_t {
struct _var_t { struct _var_t {
char *name; char *name;
array_dims_t *array;
type_t *type; type_t *type;
var_list_t *args; /* for function pointers */ var_list_t *args; /* for function pointers */
attr_list_t *attrs; attr_list_t *attrs;
...@@ -300,6 +302,7 @@ type_t *duptype(type_t *t, int dupname); ...@@ -300,6 +302,7 @@ type_t *duptype(type_t *t, int dupname);
type_t *alias(type_t *t, const char *name); type_t *alias(type_t *t, const char *name);
int is_ptr(const type_t *t); int is_ptr(const type_t *t);
int is_array(const type_t *t);
int is_var_ptr(const var_t *v); int is_var_ptr(const var_t *v);
int cant_be_null(const var_t *v); int cant_be_null(const var_t *v);
......
...@@ -1071,6 +1071,45 @@ static int encode_var( ...@@ -1071,6 +1071,45 @@ static int encode_var(
chat("encode_var: var %p type %p type->name %s type->ref %p\n", chat("encode_var: var %p type %p type->name %s type->ref %p\n",
var, type, type->name ? type->name : "NULL", type->ref); var, type, type->name ? type->name : "NULL", type->ref);
if (type->declarray) {
int num_dims, elements = 1, arrayoffset;
type_t *atype;
int *arraydata;
num_dims = 0;
for (atype = type; atype->declarray; atype = atype->ref)
++num_dims;
chat("array with %d dimensions\n", num_dims);
encode_var(typelib, atype, var, &target_type, width, alignment, NULL);
arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
arraydata[0] = target_type;
arraydata[1] = num_dims;
arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
arraydata += 2;
for (atype = type; atype->declarray; atype = atype->ref)
{
arraydata[0] = atype->dim;
arraydata[1] = 0;
arraydata += 2;
elements *= atype->dim;
}
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
typedata[0] = (0x7ffe << 16) | VT_CARRAY;
typedata[1] = arrayoffset;
*encoded_type = typeoffset;
*width = *width * elements;
*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
return 0;
}
vt = get_type_vt(type); vt = get_type_vt(type);
if (vt == VT_PTR) { if (vt == VT_PTR) {
int skip_ptr = encode_var(typelib, type->ref, var, &target_type, NULL, NULL, &child_size); int skip_ptr = encode_var(typelib, type->ref, var, &target_type, NULL, NULL, &child_size);
...@@ -1114,44 +1153,6 @@ static int encode_var( ...@@ -1114,44 +1153,6 @@ static int encode_var(
return 0; return 0;
} }
if(var->array) {
expr_t *dim;
array_dims_t *array_save;
int num_dims = list_count( var->array ), elements = 1, arrayoffset;
int *arraydata;
chat("array with %d dimensions\n", num_dims);
array_save = var->array;
var->array = NULL;
encode_var(typelib, type, var, &target_type, width, alignment, NULL);
var->array = array_save;
arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
arraydata[0] = target_type;
arraydata[1] = num_dims;
arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
arraydata += 2;
LIST_FOR_EACH_ENTRY( dim, var->array, expr_t, entry )
{
arraydata[0] = dim->cval;
arraydata[1] = 0;
arraydata += 2;
elements *= dim->cval;
}
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
typedata[0] = (0x7ffe << 16) | VT_CARRAY;
typedata[1] = arrayoffset;
*encoded_type = typeoffset;
*width = *width * elements;
*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
return 0;
}
dump_type(type); dump_type(type);
encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size); encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
...@@ -1557,7 +1558,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) ...@@ -1557,7 +1558,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
char *namedata; char *namedata;
int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff; int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff;
chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array); chat("add_var_desc(%d, %s)\n", index, var->name);
id = 0x40000000 + index; id = 0x40000000 + index;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment