diff --git a/tools/widl/header.c b/tools/widl/header.c index 597d76d4ed1..5332d5fe292 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -129,6 +129,11 @@ static void write_field(FILE *h, var_t *v) /* not all C/C++ compilers support anonymous structs and unions */ switch (v->type->type) { case RPC_FC_STRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_BOGUS_STRUCT: case RPC_FC_ENCAPSULATED_UNION: fprintf(h, " DUMMYSTRUCTNAME"); break; @@ -241,6 +246,11 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) else fprintf(h, "handle_t"); break; case RPC_FC_STRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_BOGUS_STRUCT: case RPC_FC_ENCAPSULATED_UNION: if (t->defined && !t->written) { if (t->name) fprintf(h, "struct %s {\n", t->name); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 204b6269db5..001c6f4218c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -89,6 +89,7 @@ static type_t *find_type(char *name, int t); static type_t *find_type2(char *name, int t); static type_t *get_type(unsigned char type, char *name, int t); static type_t *get_typev(unsigned char type, var_t *name, int t); +static int get_struct_type(var_t *fields); static var_t *reg_const(var_t *var); static var_t *find_const(char *name, int f); @@ -676,6 +677,8 @@ pointer_type: ; structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT); + /* overwrite RPC_FC_STRUCT with a more exact type */ + $$->type = get_struct_type( $4 ); $$->fields = $4; $$->defined = TRUE; } @@ -1066,10 +1069,8 @@ static type_t *reg_type(type_t *type, char *name, int t) /* determine pointer type from attrs */ static unsigned char get_pointer_type( type_t *type ) { - if( is_attr( type->attrs, ATTR_SIZEIS ) ) - return RPC_FC_CARRAY; - if( type->fields ) - return RPC_FC_CSTRUCT; + int t = get_attrv( type->attrs, ATTR_POINTERTYPE ); + if( t ) return t; return RPC_FC_FP; } @@ -1160,6 +1161,112 @@ static type_t *get_typev(unsigned char type, var_t *name, int t) return get_type(type, sname, t); } +static int get_struct_type(var_t *field) +{ + int has_pointer = 0; + int has_conformant_array = 0; + int has_conformant_string = 0; + + while (field) + { + type_t *t = field->type; + + /* get the base type */ + while( (t->type == 0) && t->ref ) + t = t->ref; + + switch (t->type) + { + /* + * RPC_FC_BYTE, RPC_FC_STRUCT, etc + * Simple types don't effect the type of struct. + * A struct containing a simple struct is still a simple struct. + * So long as we can block copy the data, we return RPC_FC_STRUCT. + */ + case 0: /* void pointer */ + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + case RPC_FC_HYPER: + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_STRUCT: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + break; + + case RPC_FC_UP: + case RPC_FC_FP: + has_pointer = 1; + break; + case RPC_FC_CARRAY: + has_conformant_array = 1; + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + has_conformant_string = 1; + break; + + /* + * Propagate member attributes + * a struct should be at least as complex as its member + */ + case RPC_FC_CVSTRUCT: + has_conformant_string = 1; + has_pointer = 1; + break; + + case RPC_FC_CPSTRUCT: + has_conformant_array = 1; + has_pointer = 1; + break; + + case RPC_FC_CSTRUCT: + has_conformant_array = 1; + break; + + case RPC_FC_PSTRUCT: + has_pointer = 1; + break; + + default: + fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n", + field->name, t->type); + /* 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: + return RPC_FC_BOGUS_STRUCT; + } + field = NEXT_LINK(field); + } + + if( has_conformant_string && has_pointer ) + return RPC_FC_CVSTRUCT; + if( has_conformant_array && has_pointer ) + return RPC_FC_CPSTRUCT; + if( has_conformant_array ) + return RPC_FC_CSTRUCT; + if( has_pointer ) + return RPC_FC_PSTRUCT; + return RPC_FC_STRUCT; +} + /***** constant repository *****/ struct rconst {