---
tools/widl/expr.c | 1 +
tools/widl/header.c | 42 ++++++++++++++++++++++-----
tools/widl/parser.y | 72 ++++++++++++++++++++++++++++++++++++++++--------
tools/widl/typegen.c | 4 ++-
tools/widl/typelib.c | 4 ++
tools/widl/typetree.c | 50 +++++++++++++++++++++++++++++++++
tools/widl/typetree.h | 16 ++++++++++
tools/widl/widltypes.h | 9 ++++++
8 files changed, 177 insertions(+), 21 deletions(-)
[d2f9a585c46a547e49b9438447b92c82a82bf707.diff]
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index 1e6f1ed..cfe672d 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -380,6 +380,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
case TYPE_INTERFACE:
case TYPE_POINTER:
case TYPE_ARRAY:
+ case TYPE_BITFIELD:
/* nothing to do */
break;
case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 26ee4b6..a0582f2 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -295,6 +295,9 @@ void write_type_left(FILE *h, type_t *t, int declonly)
case TYPE_VOID:
fprintf(h, "void");
break;
+ case TYPE_BITFIELD:
+ write_type_left(h, type_bitfield_get_field(t), declonly);
+ break;
case TYPE_ALIAS:
case TYPE_FUNCTION:
/* handled elsewhere */
@@ -308,15 +311,38 @@ void write_type_right(FILE *h, type_t *t, int is_field)
{
if (!h) return;
- if (type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t)) {
- if (is_conformant_array(t)) {
- fprintf(h, "[%s]", is_field ? "1" : "");
- t = type_array_get_element(t);
+ switch (type_get_type(t))
+ {
+ case TYPE_ARRAY:
+ if (!type_array_is_decl_as_ptr(t))
+ {
+ if (is_conformant_array(t))
+ {
+ fprintf(h, "[%s]", is_field ? "1" : "");
+ t = type_array_get_element(t);
+ }
+ for ( ;
+ type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t);
+ t = type_array_get_element(t))
+ fprintf(h, "[%u]", type_array_get_dim(t));
}
- for ( ;
- type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t);
- t = type_array_get_element(t))
- fprintf(h, "[%u]", type_array_get_dim(t));
+ break;
+ case TYPE_BITFIELD:
+ fprintf(h, " : %lu", type_bitfield_get_bits(t)->cval);
+ break;
+ case TYPE_VOID:
+ case TYPE_BASIC:
+ case TYPE_ENUM:
+ case TYPE_STRUCT:
+ case TYPE_ENCAPSULATED_UNION:
+ case TYPE_UNION:
+ case TYPE_ALIAS:
+ case TYPE_MODULE:
+ case TYPE_COCLASS:
+ case TYPE_FUNCTION:
+ case TYPE_INTERFACE:
+ case TYPE_POINTER:
+ break;
}
}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index a493024..9e1598e 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -278,7 +278,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%type <attr> attribute type_qualifier function_specifier
%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
%type <str_list> str_list
-%type <expr> m_expr expr expr_const expr_int_const array
+%type <expr> m_expr expr expr_const expr_int_const array m_bitfield
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <ifinfo> interfacehdr
%type <stgclass> storage_cls_spec
@@ -294,9 +294,9 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%type <var> arg ne_union_field union_field s_field case enum declaration
%type <var_list> m_args args fields ne_union_fields cases enums enum_list dispint_props field
%type <var> m_ident ident
-%type <declarator> declarator direct_declarator init_declarator
+%type <declarator> declarator direct_declarator init_declarator struct_declarator
%type <declarator> m_any_declarator any_declarator any_declarator_no_ident any_direct_declarator
-%type <declarator_list> declarator_list
+%type <declarator_list> declarator_list struct_declarator_list
%type <func> funcdef
%type <type> coclass coclasshdr coclassdef
%type <num> pointer_type version
@@ -679,7 +679,7 @@ fields: { $$ = NULL; }
| fields field { $$ = append_var_list($1, $2); }
;
-field: m_attributes decl_spec declarator_list ';'
+field: m_attributes decl_spec struct_declarator_list ';'
{ const char *first = LIST_ENTRY(list_head($3), declarator_t, entry)->var->name;
check_field_attrs(first, $1);
$$ = set_var_types($1, $2, $3);
@@ -980,6 +980,22 @@ declarator_list:
| declarator_list ',' declarator { $$ = append_declarator( $1, $3 ); }
;
+m_bitfield: { $$ = NULL; }
+ | ':' expr_const { $$ = $2; }
+ ;
+
+struct_declarator: any_declarator m_bitfield { $$ = $1; $$->bits = $2;
+ if (!$$->bits && !$$->var->name)
+ error_loc("unnamed fields are not allowed");
+ }
+ ;
+
+struct_declarator_list:
+ struct_declarator { $$ = append_declarator( NULL, $1 ); }
+ | struct_declarator_list ',' struct_declarator
+ { $$ = append_declarator( $1, $3 ); }
+ ;
+
init_declarator:
declarator { $$ = $1; }
| declarator '=' expr_const { $$ = $1; $1->var->eval = $3; }
@@ -1529,6 +1545,9 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
error_loc("calling convention applied to non-function-pointer type\n");
}
+ if (decl->bits)
+ v->type = type_new_bitfield(v->type, decl->bits);
+
return v;
}
@@ -1620,6 +1639,7 @@ static declarator_t *make_declarator(var_t *var)
d->type = NULL;
d->func_type = NULL;
d->array = NULL;
+ d->bits = NULL;
return d;
}
@@ -2211,6 +2231,7 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_COCLASS:
case TYPE_FUNCTION:
case TYPE_INTERFACE:
+ case TYPE_BITFIELD:
return FALSE;
}
return FALSE;
@@ -2254,24 +2275,30 @@ static void check_field_common(const type_t *container_type,
{
type_t *type = arg->type;
int more_to_do;
- const char *container_type_name = NULL;
+ const char *container_type_name;
+ const char *var_type;
- switch (type_get_type_detect_alias(type))
+ switch (type_get_type(container_type))
{
case TYPE_STRUCT:
container_type_name = "struct";
+ var_type = "field";
break;
case TYPE_UNION:
container_type_name = "union";
+ var_type = "arm";
break;
case TYPE_ENCAPSULATED_UNION:
container_type_name = "encapsulated union";
+ var_type = "arm";
break;
case TYPE_FUNCTION:
container_type_name = "function";
+ var_type = "parameter";
break;
default:
- break;
+ /* should be no other container types */
+ assert(0);
}
if (is_attr(arg->attrs, ATTR_LENGTHIS) &&
@@ -2331,24 +2358,35 @@ static void check_field_common(const type_t *container_type,
check_remoting_fields(arg, type);
break;
case TGT_INVALID:
+ {
+ const char *reason = "is invalid";
switch (type_get_type(type))
{
case TYPE_VOID:
- error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot derive from void *\n",
- arg->name, container_type_name, container_name);
+ reason = "cannot derive from void *";
break;
case TYPE_FUNCTION:
- error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot be a function pointer\n",
- arg->name, container_type_name, container_name);
+ reason = "cannot be a function pointer";
+ break;
+ case TYPE_BITFIELD:
+ reason = "cannot be a bit-field";
break;
case TYPE_COCLASS:
+ reason = "cannot be a class";
+ break;
case TYPE_INTERFACE:
+ reason = "cannot be a non-pointer to an interface";
+ break;
case TYPE_MODULE:
- /* FIXME */
+ reason = "cannot be a module";
break;
default:
break;
}
+ error_loc_info(&arg->loc_info, "%s \'%s\' of %s \'%s\' %s\n",
+ var_type, arg->name, container_type_name, container_name, reason);
+ break;
+ }
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
/* FIXME */
@@ -2452,6 +2490,16 @@ static void check_remoting_args(const var_t *func)
check_field_common(func->type, funcname, arg);
}
+
+ if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID)
+ {
+ var_t var;
+ var = *func;
+ var.type = type_function_get_rettype(func->type);
+ var.name = xstrdup("return value");
+ check_field_common(func->type, funcname, &var);
+ free(var.name);
+ }
}
static void add_explicit_handle_if_necessary(var_t *func)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 3e71100..f601ab3 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -244,6 +244,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_MODULE:
case TYPE_VOID:
case TYPE_ALIAS:
+ case TYPE_BITFIELD:
break;
}
return TGT_INVALID;
@@ -1294,10 +1295,11 @@ unsigned int type_memsize(const type_t *t, unsigned int *align)
case TYPE_COCLASS:
case TYPE_MODULE:
case TYPE_FUNCTION:
+ case TYPE_BITFIELD:
/* these types should not be encountered here due to language
* restrictions (interface, void, coclass, module), logical
* restrictions (alias - due to type_get_type call above) or
- * checking restrictions (function). */
+ * checking restrictions (function, bitfield). */
assert(0);
}
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index b4dd771..9c24f15 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -244,6 +244,10 @@ unsigned short get_type_vt(type_t *t)
case TYPE_FUNCTION:
error("get_type_vt: functions not supported\n");
break;
+
+ case TYPE_BITFIELD:
+ error("get_type_vt: bitfields not supported\n");
+ break;
}
return 0;
}
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index c91869b..19bb4b3 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -302,6 +302,56 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
return t;
}
+static int is_valid_bitfield_type(const type_t *type)
+{
+ switch (type_get_type(type))
+ {
+ case TYPE_ENUM:
+ return TRUE;
+ case TYPE_BASIC:
+ switch (type_basic_get_type(type))
+ {
+ case TYPE_BASIC_INT8:
+ case TYPE_BASIC_INT16:
+ case TYPE_BASIC_INT32:
+ case TYPE_BASIC_INT64:
+ case TYPE_BASIC_INT:
+ case TYPE_BASIC_INT3264:
+ case TYPE_BASIC_CHAR:
+ case TYPE_BASIC_HYPER:
+ case TYPE_BASIC_BYTE:
+ case TYPE_BASIC_WCHAR:
+ case TYPE_BASIC_ERROR_STATUS_T:
+ return TRUE;
+ case TYPE_BASIC_FLOAT:
+ case TYPE_BASIC_DOUBLE:
+ case TYPE_BASIC_HANDLE:
+ return FALSE;
+ }
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+type_t *type_new_bitfield(type_t *field, const expr_t *bits)
+{
+ type_t *t;
+
+ if (!is_valid_bitfield_type(field))
+ error_loc("bit-field has invalid type\n");
+
+ if (bits->cval < 0)
+ error_loc("negative width for bit-field\n");
+
+ /* FIXME: validate bits->cval <= memsize(field) * 8 */
+
+ t = make_type(TYPE_BITFIELD);
+ t->details.bitfield.field = field;
+ t->details.bitfield.bits = bits;
+ return t;
+}
+
static int compute_method_indexes(type_t *iface)
{
int idx;
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index fb0401b..591406b 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -39,6 +39,7 @@ type_t *type_new_enum(const char *name, int defined, var_list_t *enums);
type_t *type_new_struct(char *name, int defined, var_list_t *fields);
type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields);
type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases);
+type_t *type_new_bitfield(type_t *field_type, const expr_t *bits);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods);
void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface);
@@ -190,6 +191,7 @@ static inline int type_is_complete(const type_t *type)
case TYPE_COCLASS:
case TYPE_POINTER:
case TYPE_ARRAY:
+ case TYPE_BITFIELD:
return TRUE;
}
return FALSE;
@@ -283,4 +285,18 @@ static inline unsigned char type_pointer_get_default_fc(const type_t *type)
return type->details.pointer.def_fc;
}
+static inline type_t *type_bitfield_get_field(const type_t *type)
+{
+ type = type_get_real_type(type);
+ assert(type_get_type(type) == TYPE_BITFIELD);
+ return type->details.bitfield.field;
+}
+
+static inline const expr_t *type_bitfield_get_bits(const type_t *type)
+{
+ type = type_get_real_type(type);
+ assert(type_get_type(type) == TYPE_BITFIELD);
+ return type->details.bitfield.bits;
+}
+
#endif /* WIDL_TYPE_TREE_H */
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index d5a4c43..f4ee7f0 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -343,6 +343,12 @@ struct pointer_details
unsigned char def_fc;
};
+struct bitfield_details
+{
+ struct _type_t *field;
+ const expr_t *bits;
+};
+
enum type_type
{
TYPE_VOID,
@@ -358,6 +364,7 @@ enum type_type
TYPE_INTERFACE,
TYPE_POINTER,
TYPE_ARRAY,
+ TYPE_BITFIELD,
};
struct _type_t {
@@ -375,6 +382,7 @@ struct _type_t {
struct coclass_details coclass;
struct basic_details basic;
struct pointer_details pointer;
+ struct bitfield_details bitfield;
} details;
type_t *orig; /* dup'd types */
unsigned int typestring_offset;
@@ -408,6 +416,7 @@ struct _declarator_t {
type_t *type;
type_t *func_type;
array_dims_t *array;
+ expr_t *bits;
/* parser-internal */
struct list entry;