diff --git a/tools/widl/header.c b/tools/widl/header.c index ff382c12e3c..ad7fefba762 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -77,6 +77,14 @@ int is_void(const type_t *t, const var_t *v) return 0; } +int is_conformant_array( const array_dims_t *array ) +{ + expr_t *dim; + if (!array) return 0; + dim = LIST_ENTRY( list_head( array ), expr_t, entry ); + return !dim->is_const; +} + void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) { if (!uuid) return; @@ -112,19 +120,20 @@ const char* get_name(const var_t *v) return v->name; } -void write_array(FILE *h, const expr_t *v, int field) +void write_array(FILE *h, array_dims_t *dims, int field) { - if (!v) return; - while (NEXT_LINK(v)) v = NEXT_LINK(v); + expr_t *v; + + if (!dims) return; fprintf(h, "["); - while (v) { + 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 (PREV_LINK(v)) + if (list_next( dims, &v->entry )) fprintf(h, ", "); - v = PREV_LINK(v); } fprintf(h, "]"); } diff --git a/tools/widl/header.h b/tools/widl/header.h index e19f99d7409..748f14a408d 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -25,6 +25,7 @@ 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 unsigned long get_attrv(const attr_list_t *list, enum attr_type t); extern int is_void(const type_t *t, const var_t *v); +extern int is_conformant_array( const array_dims_t *array ); extern void write_name(FILE *h, const var_t *v); extern const char* get_name(const var_t *v); extern void write_type(FILE *h, type_t *t, const var_t *v, const char *n); @@ -32,7 +33,7 @@ extern int is_object(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 void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent); -extern void write_array(FILE *h, const expr_t *v, int field); +extern void write_array(FILE *h, array_dims_t *v, int field); extern void write_forward(type_t *iface); extern void write_interface(type_t *iface); extern void write_dispinterface(type_t *iface); @@ -49,13 +50,13 @@ extern int has_out_arg_or_return(const func_t *func); extern void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid); -static inline int is_string_type(const attr_list_t *attrs, int ptr_level, const expr_t *array) +static inline int is_string_type(const attr_list_t *attrs, int ptr_level, const array_dims_t *array) { return (is_attr(attrs, ATTR_STRING) && ((ptr_level == 1 && !array) || (ptr_level == 0 && array))); } -static inline int is_array_type(const attr_list_t *attrs, int ptr_level, const expr_t *array) +static inline int is_array_type(const attr_list_t *attrs, int ptr_level, const array_dims_t *array) { return ((ptr_level == 1 && !array && is_attr(attrs, ATTR_SIZEIS)) || (ptr_level == 0 && array)); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 2f672040314..1741b8398e5 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -76,10 +76,12 @@ static expr_t *make_expr1(enum expr_type type, expr_t *expr); static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2); static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3); static type_t *make_type(unsigned char type, type_t *ref); +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); +static array_dims_t *append_array(array_dims_t *list, expr_t *expr); static typeref_t *make_tref(char *name, type_t *ref); static typeref_t *uniq_tref(typeref_t *ref); static type_t *type_ref(typeref_t *ref); -static void set_type(var_t *v, typeref_t *ref, expr_t *arr); +static void set_type(var_t *v, typeref_t *ref, array_dims_t *arr); static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); static ifref_t *make_ifref(type_t *iface); static var_list_t *append_var(var_list_t *list, var_t *var); @@ -121,6 +123,8 @@ static void check_arg(var_t *arg); attr_t *attr; attr_list_t *attr_list; expr_t *expr; + expr_list_t *expr_list; + array_dims_t *array_dims; type_t *type; typeref_t *tref; var_t *var; @@ -219,8 +223,9 @@ static void check_arg(var_t *arg); %type attribute %type m_attributes attributes attrib_list -%type m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const -%type array array_list +%type m_expr expr expr_const +%type m_exprs /* exprs expr_list */ expr_list_const +%type array array_list %type inherit interface interfacehdr interfacedef interfacedec %type dispinterface dispinterfacehdr dispinterfacedef %type module modulehdr moduledef @@ -357,12 +362,12 @@ arg: attributes type pident array { $$ = $3; array: { $$ = NULL; } | '[' array_list ']' { $$ = $2; } - | '[' '*' ']' { $$ = make_expr(EXPR_VOID); } + | '[' '*' ']' { $$ = append_array( NULL, make_expr(EXPR_VOID) ); } ; -array_list: m_expr /* size of first dimension is optional */ - | array_list ',' expr { LINK($3, $1); $$ = $3; } - | array_list ']' '[' expr { LINK($4, $1); $$ = $4; } +array_list: m_expr /* size of first dimension is optional */ { $$ = append_array( NULL, $1 ); } + | array_list ',' expr { $$ = append_array( $1, $3 ); } + | array_list ']' '[' expr { $$ = append_array( $1, $4 ); } ; m_attributes: { $$ = NULL; } @@ -434,7 +439,9 @@ attribute: { $$ = NULL; } | tPROPPUT { $$ = make_attr(ATTR_PROPPUT); } | tPROPPUTREF { $$ = make_attr(ATTR_PROPPUTREF); } | tPUBLIC { $$ = make_attr(ATTR_PUBLIC); } - | tRANGE '(' expr_const ',' expr_const ')' { LINK($5, $3); $$ = make_attrp(ATTR_RANGE, $5); } + | tRANGE '(' expr_const ',' expr_const ')' { expr_list_t *list = append_expr( NULL, $3 ); + list = append_expr( list, $5 ); + $$ = make_attrp(ATTR_RANGE, list); } | tREADONLY { $$ = make_attr(ATTR_READONLY); } | tREQUESTEDIT { $$ = make_attr(ATTR_REQUESTEDIT); } | tRESTRICTED { $$ = make_attr(ATTR_RESTRICTED); } @@ -513,8 +520,8 @@ enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM } ; -m_exprs: m_expr - | m_exprs ',' m_expr { LINK($3, $1); $$ = $3; } +m_exprs: m_expr { $$ = append_expr( NULL, $1 ); } + | m_exprs ',' m_expr { $$ = append_expr( $1, $3 ); } ; /* @@ -553,8 +560,8 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | '(' expr ')' { $$ = $2; } ; -expr_list_const: expr_const - | expr_list_const ',' expr_const { LINK($3, $1); $$ = $3; } +expr_list_const: expr_const { $$ = append_expr( NULL, $1 ); } + | expr_list_const ',' expr_const { $$ = append_expr( $1, $3 ); } ; expr_const: expr { $$ = $1; @@ -951,7 +958,6 @@ static expr_t *make_expr(enum expr_type type) e->ref = NULL; e->u.lval = 0; e->is_const = FALSE; - INIT_LINK(e); return e; } @@ -962,7 +968,6 @@ static expr_t *make_exprl(enum expr_type type, long val) e->ref = NULL; e->u.lval = val; e->is_const = FALSE; - INIT_LINK(e); /* check for numeric constant */ if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) { /* make sure true/false value is valid */ @@ -981,7 +986,6 @@ static expr_t *make_exprs(enum expr_type type, char *val) e->ref = NULL; e->u.sval = val; e->is_const = FALSE; - INIT_LINK(e); /* check for predefined constants */ if (type == EXPR_IDENTIFIER) { var_t *c = find_const(val, 0); @@ -1003,7 +1007,6 @@ static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr) e->ref = expr; e->u.tref = tref; e->is_const = FALSE; - INIT_LINK(e); /* check for cast of constant expression */ if (type == EXPR_SIZEOF) { switch (tref->ref->type) { @@ -1049,7 +1052,6 @@ static expr_t *make_expr1(enum expr_type type, expr_t *expr) e->ref = expr; e->u.lval = 0; e->is_const = FALSE; - INIT_LINK(e); /* check for compile-time optimization */ if (expr->is_const) { e->is_const = TRUE; @@ -1076,7 +1078,6 @@ static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) e->ref = expr1; e->u.ext = expr2; e->is_const = FALSE; - INIT_LINK(e); /* check for compile-time optimization */ if (expr1->is_const && expr2->is_const) { e->is_const = TRUE; @@ -1122,7 +1123,6 @@ static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, exp e->u.ext = expr2; e->ext2 = expr3; e->is_const = FALSE; - INIT_LINK(e); /* check for compile-time optimization */ if (expr1->is_const && expr2->is_const && expr3->is_const) { e->is_const = TRUE; @@ -1138,6 +1138,30 @@ static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, exp return e; } +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + +static array_dims_t *append_array(array_dims_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + static type_t *make_type(unsigned char type, type_t *ref) { type_t *t = xmalloc(sizeof(type_t)); @@ -1157,7 +1181,6 @@ static type_t *make_type(unsigned char type, type_t *ref) t->written = FALSE; t->user_types_registered = FALSE; t->typelib_idx = -1; - INIT_LINK(t); return t; } @@ -1198,7 +1221,7 @@ static type_t *type_ref(typeref_t *ref) return t; } -static void set_type(var_t *v, typeref_t *ref, expr_t *arr) +static void set_type(var_t *v, typeref_t *ref, array_dims_t *arr) { v->type = ref->ref; v->tname = ref->name; @@ -1280,7 +1303,6 @@ static type_t *make_class(char *name) type_t *c = make_type(0, NULL); c->name = name; c->kind = TKIND_COCLASS; - INIT_LINK(c); return c; } @@ -1488,7 +1510,7 @@ static int get_struct_type(var_list_t *fields) if (is_array_type(field->attrs, 0, field->array)) { - if (field->array && !field->array->is_const) + if (field->array && is_conformant_array(field->array)) { has_conformance = 1; if (list_next( fields, &field->entry )) diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index af70a63252a..5bba033663a 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -59,7 +59,7 @@ struct expr_eval_routine const expr_t *expr; }; -static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array); +static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array); static size_t fields_memsize(const var_list_t *fields); static int compare_expr(const expr_t *a, const expr_t *b) @@ -537,7 +537,7 @@ static size_t fields_memsize(const var_list_t *fields) return size; } -static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array) +static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array) { size_t size = 0; @@ -586,10 +586,12 @@ static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array) if (array) { - if (array->is_const) - size *= array->cval; - else - size = 0; + expr_t *dim; + LIST_FOR_EACH_ENTRY( dim, array, expr_t, entry ) + if (dim->is_const) + size *= dim->cval; + else + size = 0; } return size; @@ -602,7 +604,7 @@ size_t get_type_memsize(const type_t *type) static int write_pointers(FILE *file, const attr_list_t *attrs, const type_t *type, int ptr_level, - const expr_t *array, int level, + const array_dims_t *array, int level, unsigned int *typestring_offset) { int pointers_written = 0; @@ -650,7 +652,7 @@ static int write_pointers(FILE *file, const attr_list_t *attrs, static size_t write_pointer_description(FILE *file, const attr_list_t *attrs, const type_t *type, int ptr_level, - const expr_t *array, int level, + const array_dims_t *array, int level, size_t typestring_offset) { size_t size = 0; @@ -700,7 +702,7 @@ static size_t write_pointer_description(FILE *file, const attr_list_t *attrs, } static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, - const type_t *type, const expr_t *array, + const type_t *type, const array_dims_t *array, const char *name, unsigned int *typestring_offset) { const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS); @@ -744,11 +746,13 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, *typestring_offset += 2; } - if (array && array->is_const) + if (array && !is_conformant_array(array)) { - if (array->cval > USHRT_MAX) + /* FIXME: multi-dimensional array */ + const expr_t *dim = LIST_ENTRY( list_head( array ), expr_t, entry ); + if (dim->cval > USHRT_MAX) error("array size for parameter %s exceeds %d bytes by %ld bytes\n", - name, USHRT_MAX, array->cval - USHRT_MAX); + name, USHRT_MAX, dim->cval - USHRT_MAX); if (rtype == RPC_FC_CHAR) WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset); @@ -757,7 +761,7 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", array->cval, array->cval); + print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", dim->cval, dim->cval); *typestring_offset += 2; return start_offset; @@ -789,13 +793,13 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, } static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, - const type_t *type, const expr_t *array, + const type_t *type, const array_dims_t *array, const char *name, unsigned int *typestring_offset) { const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS); const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS); int has_length = length_is && (length_is->type != EXPR_VOID); - int has_size = (size_is && (size_is->type != EXPR_VOID)) || !array->is_const; + int has_size = (size_is && (size_is->type != EXPR_VOID)) || is_conformant_array(array); size_t start_offset; int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); if (!pointer_type) @@ -807,13 +811,14 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "NdrFcShort(0x2),\n"); *typestring_offset += 4; - if (array && NEXT_LINK(array)) /* multi-dimensional array */ + if (array && list_count(array) > 1) /* multi-dimensional array */ { error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name); return 0; } else { + const expr_t *dim = LIST_ENTRY( list_head( array ), expr_t, entry ); size_t pointer_start_offset = *typestring_offset; int has_pointer = 0; @@ -866,7 +871,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, { /* varying array */ size_t element_size = type_memsize(type, 0, NULL); - size_t elements = array->cval; + size_t elements = dim->cval; size_t total_size = element_size * elements; if (total_size < USHRT_MAX) @@ -930,7 +935,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, *typestring_offset += write_conf_or_var_desc(file, current_func, current_structure, - size_is ? size_is : array); + size_is ? size_is : dim); if (has_pointer) { @@ -963,7 +968,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, *typestring_offset += write_conf_or_var_desc(file, current_func, current_structure, - size_is ? size_is : array); + size_is ? size_is : dim); *typestring_offset += write_conf_or_var_desc(file, current_func, current_structure, length_is); @@ -1486,7 +1491,7 @@ void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_obje } static unsigned int get_required_buffer_size_type( - const type_t *type, int ptr_level, const expr_t *array, + const type_t *type, int ptr_level, const array_dims_t *array, const char *name, unsigned int *alignment) { *alignment = 0; @@ -1770,7 +1775,7 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, length_is = get_attrp(var->attrs, ATTR_LENGTHIS); size_is = get_attrp(var->attrs, ATTR_SIZEIS); has_length = length_is && (length_is->type != EXPR_VOID); - has_size = (size_is && (size_is->type != EXPR_VOID)) || (var->array && !var->array->is_const); + has_size = (size_is && (size_is->type != EXPR_VOID)) || (var->array && is_conformant_array(var->array)); pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE); if (!pointer_type) @@ -1797,7 +1802,7 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, if (is_string_type(var->attrs, var->ptr_level, var->array)) { - if (var->array && var->array->is_const) + if (var->array && !is_conformant_array(var->array)) print_phase_function(file, indent, "NonConformantString", phase, var->name, *type_offset); else { @@ -1819,10 +1824,11 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, { const char *array_type; - if (var->array && NEXT_LINK(var->array)) /* multi-dimensional array */ + if (var->array && list_count(var->array) > 1) /* multi-dimensional array */ array_type = "ComplexArray"; else { + const expr_t *dim = LIST_ENTRY( list_head( var->array ), expr_t, entry ); if (!has_length && !has_size) array_type = "FixedArray"; else if (has_length && !has_size) @@ -1841,7 +1847,7 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, if (is_size_needed_for_phase(phase) && phase != PHASE_FREE) { print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)"); - write_expr(file, size_is ? size_is : var->array, 1); + write_expr(file, size_is ? size_is : dim, 1); fprintf(file, ";\n\n"); } array_type = "ConformantArray"; @@ -1851,7 +1857,7 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, if (is_size_needed_for_phase(phase)) { print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)"); - write_expr(file, size_is ? size_is : var->array, 1); + write_expr(file, size_is ? size_is : dim, 1); fprintf(file, ";\n"); print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */ print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)"); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index f24552f3efe..faaac6a27fc 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -48,26 +48,10 @@ typedef struct _typelib_t typelib_t; typedef struct list attr_list_t; typedef struct list func_list_t; +typedef struct list expr_list_t; typedef struct list var_list_t; typedef struct list ifref_list_t; - -#define DECL_LINK(type) \ - type *l_next; \ - type *l_prev - -#define LINK(x,y) do { x->l_next = y; x->l_prev = NULL; if (y) y->l_prev = x; } while (0) - -#define INIT_LINK(x) do { x->l_next = NULL; x->l_prev = NULL; } while (0) -#define NEXT_LINK(x) ((x)->l_next) -#define PREV_LINK(x) ((x)->l_prev) - -#define END_OF_LIST(list) \ - do { \ - if (list) { \ - while (NEXT_LINK(list)) \ - list = NEXT_LINK(list); \ - } \ - } while(0) +typedef struct list array_dims_t; enum attr_type { @@ -201,7 +185,7 @@ struct _expr_t { int is_const; long cval; /* parser-internal */ - DECL_LINK(expr_t); + struct list entry; }; struct _type_t { @@ -217,8 +201,6 @@ struct _type_t { int ignore, is_const, sign; int defined, written, user_types_registered; int typelib_idx; - /* parser-internal */ - DECL_LINK(type_t); }; struct _typeref_t { @@ -230,7 +212,7 @@ struct _typeref_t { struct _var_t { char *name; int ptr_level; - expr_t *array; + array_dims_t *array; type_t *type; var_list_t *args; /* for function pointers */ const char *tname; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index bc8db5ce7a0..6248c80a8f2 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1104,15 +1104,11 @@ static int encode_var( } if(var->array) { - expr_t *dim = var->array; - expr_t *array_save; - int num_dims = 1, elements = 1, arrayoffset; + expr_t *dim; + array_dims_t *array_save; + int num_dims = list_count( var->array ), elements = 1, arrayoffset; int *arraydata; - while(NEXT_LINK(dim)) { - dim = NEXT_LINK(dim); - num_dims++; - } chat("array with %d dimensions\n", num_dims); array_save = var->array; var->array = NULL; @@ -1126,12 +1122,12 @@ static int encode_var( arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16); arraydata += 2; - while(dim) { + LIST_FOR_EACH_ENTRY( dim, var->array, expr_t, entry ) + { arraydata[0] = dim->cval; arraydata[1] = 0; arraydata += 2; elements *= dim->cval; - dim = PREV_LINK(dim); } typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);