[7/9] widl: Add support for bit-fields in non-remote structures.

View: New views
1 Messages — Rating Filter:   Alert me  

[7/9] widl: Add support for bit-fields in non-remote structures.

by Rob Shearman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

---
 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;