[pypy-commit] creflect default: enums

arigo noreply at buildbot.pypy.org
Sat Dec 6 21:40:21 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r192:d43293d10be7
Date: 2014-12-06 21:40 +0100
http://bitbucket.org/cffi/creflect/changeset/d43293d10be7/

Log:	enums

diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -256,7 +256,7 @@
 
     def get_struct_union_enum_type(self, kind, type, approx_name=None):
         name = type.name or approx_name
-        if not name or name.startswith('$$$'):
+        if kind != 'enum' and (not name or name.startswith('$$$')):
             self.parse_error("not implemented: anonymous 'struct' elsewhere "
                              "than in 'typedef struct { ... } typename;' or "
                              "'typedef struct { ... } *typename;'", type)
@@ -270,7 +270,7 @@
             if kind == 'struct' or kind == 'union':
                 typedecl = model.StructOrUnionDecl(result)
             elif kind == 'enum':
-                typedecl = XXX
+                typedecl = model.EnumDecl(result)
             else:
                 raise AssertionError("kind = %r" % (kind,))
             self.struct_union_enum_decl[key] = typedecl
@@ -280,8 +280,12 @@
         #
         # is there a 'type.decls'?  If yes, then this is the place in the
         # C sources that declare the fields.
-        if type.decls is not None:
-            self.add_fields_declaration(typedecl, type.decls)
+        if kind == 'struct' or kind == 'union':
+            if type.decls is not None:
+                self.add_fields_declaration(typedecl, type.decls)
+        if kind == 'enum':
+            if type.values is not None:
+                self.add_enum_values_declaration(typedecl, type.values)
         if must_add:
             self.declarations.append(typedecl)
         return result
@@ -312,6 +316,13 @@
                 raise NotImplementedError("%s: using both bitfields and '...;'"
                                           % (tp,))
 
+    def add_enum_values_declaration(self, typedecl, values):
+        for enumerator in values.enumerators:
+            self.declarations.append(
+                model.ConstDecl(enumerator.name,
+                                model.QualType(model.int_type)))
+        typedecl.complete = True
+
     def parse_constant(self, constant):
         return int(constant.value)   # xxx
 
diff --git a/creflect/creflect_debug_print.c b/creflect/creflect_debug_print.c
--- a/creflect/creflect_debug_print.c
+++ b/creflect/creflect_debug_print.c
@@ -202,7 +202,8 @@
 static void tst_complete_enum(_crx_builder_t *cb, _crx_type_t *t,
                               _crx_type_t *inttype)
 {
-    abort();
+    assert(memcmp(t->text, "ENUM ", 5) == 0);
+    printf("%s = %s\n", t->text, inttype->text);
 }
 
 static void tst_define_type(_crx_builder_t *cb, const char *name,
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -249,6 +249,8 @@
         block.writeline('cb->define_num_const(cb, "%s", %s, &v);' % (
             varname, t1))
 
+int_type = PrimitiveType('int')
+
 
 class FunctionType(BaseType):
     _attrs_ = ('args', 'result', 'ellipsis')
@@ -730,6 +732,40 @@
         funcblock.writeline('             %s, %d);' % (d1, len(self.fldnames)))
 
 
+class EnumDecl(object):
+
+    def __init__(self, type):
+        self.type = type
+        self.complete = False
+
+    def write_declaration(self, funcblock):
+        if not self.complete or self.type.name is None:
+            return     # opaque
+        tp = "%s %s" % (self.type.kind, self.type.name)
+        block = CodeBlock(funcblock)
+        if not self.type.name.startswith('$'):
+            realtp = tp
+        else:
+            realtp = self.type.name[1:]
+        if not realtp.startswith('$'):
+            expr = '(%s)-1' % realtp
+        else:
+            # xxx obscure case: "typedef enum e *t;"
+            ptrtp = realtp[1:]
+            assert not ptrtp.startswith('$')
+            block.writedecl("%s p1;" % (ptrtp,))
+            block.writedecl("char b[sizeof(*p1)];")
+            block.writeline("memset(b, -1, sizeof(b));")
+            block.writeline("p1 = (%s)b;" % (ptrtp,))
+            expr = '*p1'
+        #
+        t1 = self.type.get_type_var(block)
+        t2 = block.write_crx_type_var('_CRX_INT_TYPE(cb, %s, _crx_sc_int)' %
+                                          (expr,))
+        block.writeline('cb->complete_enum(cb, %s, %s);' % (t1, t2))
+        funcblock.write_subblock(block)
+
+
 class TypeDefDecl(object):
     def __init__(self, name, qualtype):
         self.name = name
diff --git a/creflect/test/codegen/enum-001.c b/creflect/test/codegen/enum-001.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-001.c
@@ -0,0 +1,13 @@
+typedef enum myname_e foo_t;    // unusual, but valid C
+
+# ____________________________________________________________
+
+void testenum_001(_crx_builder_t *cb)
+{
+    _crx_type_t *t1;
+    {
+        t1 = cb->get_enum_type(cb, "myname_e");
+        cb->define_type(cb, "foo_t", t1, 0);
+#expect TYPEDEF foo_t = ENUM myname_e
+    }
+}
diff --git a/creflect/test/codegen/enum-002.c b/creflect/test/codegen/enum-002.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-002.c
@@ -0,0 +1,22 @@
+enum { AA, BB };     /* anonymous */
+
+# ____________________________________________________________
+
+void testenum_002(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = int 0
+    }
+    {
+        _crx_num_const_t v;
+        (void)((BB) << 1);  /* check that 'BB' is an integer */
+        t2 = _CRX_INT_CONST(cb, BB, &v, 1);
+        cb->define_num_const(cb, "BB", t2, &v);
+#expect NUMCONST BB = int 1
+    }
+}
diff --git a/creflect/test/codegen/enum-002b.c b/creflect/test/codegen/enum-002b.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-002b.c
@@ -0,0 +1,28 @@
+
+enum { AA=(10+10), BB=-4 };
+
+# ____________________________________________________________
+
+#define AA   100
+#define BB   200
+
+# ____________________________________________________________
+
+void testenum_002b(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = int 100
+    }
+    {
+        _crx_num_const_t v;
+        (void)((BB) << 1);  /* check that 'BB' is an integer */
+        t2 = _CRX_INT_CONST(cb, BB, &v, 1);
+        cb->define_num_const(cb, "BB", t2, &v);
+#expect NUMCONST BB = int 200
+    }
+}
diff --git a/creflect/test/codegen/enum-003.c b/creflect/test/codegen/enum-003.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-003.c
@@ -0,0 +1,23 @@
+enum myname_e { AA };
+/* note that with GCC, "enum myname_e" is equivalent to "unsigned int",
+   but AA itself is a constant of type "int", obscurely */
+
+# ____________________________________________________________
+
+void testenum_003(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2, *t3;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = int 0
+    }
+    {
+        t2 = cb->get_enum_type(cb, "myname_e");
+        t3 = _CRX_INT_TYPE(cb, (enum myname_e)-1, _crx_sc_int);
+        cb->complete_enum(cb, t2, t3);
+#expect ENUM myname_e = unsigned int
+    }
+}
diff --git a/creflect/test/codegen/enum-003b.c b/creflect/test/codegen/enum-003b.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-003b.c
@@ -0,0 +1,28 @@
+enum myname_e { AA=0x80000000U, BB=3U };
+
+# ____________________________________________________________
+
+void testenum_003b(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2, *t3, *t4;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = unsigned int 2147483648
+    }
+    {
+        _crx_num_const_t v;
+        (void)((BB) << 1);  /* check that 'BB' is an integer */
+        t2 = _CRX_INT_CONST(cb, BB, &v, 1);
+        cb->define_num_const(cb, "BB", t2, &v);
+#expect NUMCONST BB = int 3
+    }
+    {
+        t3 = cb->get_enum_type(cb, "myname_e");
+        t4 = _CRX_INT_TYPE(cb, (enum myname_e)-1, _crx_sc_int);
+        cb->complete_enum(cb, t3, t4);
+#expect ENUM myname_e = unsigned int
+    }
+}
diff --git a/creflect/test/codegen/enum-003c.c b/creflect/test/codegen/enum-003c.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-003c.c
@@ -0,0 +1,21 @@
+enum myname_e { AA=-3L };
+
+# ____________________________________________________________
+
+void testenum_003c(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2, *t3;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = int -3
+    }
+    {
+        t2 = cb->get_enum_type(cb, "myname_e");
+        t3 = _CRX_INT_TYPE(cb, (enum myname_e)-1, _crx_sc_int);
+        cb->complete_enum(cb, t2, t3);
+#expect ENUM myname_e = int
+    }
+}
diff --git a/creflect/test/codegen/enum-004.c b/creflect/test/codegen/enum-004.c
new file mode 100644
--- /dev/null
+++ b/creflect/test/codegen/enum-004.c
@@ -0,0 +1,34 @@
+typedef enum { AA } *foo_t;
+
+# ____________________________________________________________
+
+void testenum_004(_crx_builder_t *cb)
+{
+    _crx_type_t *t1, *t2, *t3, *t4;
+    {
+        _crx_num_const_t v;
+        (void)((AA) << 1);  /* check that 'AA' is an integer */
+        t1 = _CRX_INT_CONST(cb, AA, &v, 1);
+        cb->define_num_const(cb, "AA", t1, &v);
+#expect NUMCONST AA = int 0
+    }
+    {
+        foo_t p1;
+        char b[sizeof(*p1)];
+        memset(b, -1, sizeof(b));
+        p1 = (foo_t)b;
+        t2 = cb->get_enum_type(cb, "$$foo_t");
+        t3 = _CRX_INT_TYPE(cb, *p1, _crx_sc_int);
+        cb->complete_enum(cb, t2, t3);
+#expect ENUM $$foo_t = unsigned int
+    }
+    {
+        foo_t *p1;
+        char *p2;
+        p1 = (void *)&p2;
+        *p1 = (void *)0;    /* check that 'foo_t' is a pointer type */
+        t4 = cb->get_pointer_type(cb, t2, 0);
+        cb->define_type(cb, "foo_t", t4, 0);
+#expect TYPEDEF foo_t = PTR ENUM $$foo_t
+    }
+}


More information about the pypy-commit mailing list