[pypy-commit] creflect default: Anonymous structure, but directly from a 'typedef'

arigo noreply at buildbot.pypy.org
Tue Sep 16 15:30:10 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r44:c1f276dfda7b
Date: 2014-09-16 11:54 +0200
http://bitbucket.org/cffi/creflect/changeset/c1f276dfda7b/

Log:	Anonymous structure, but directly from a 'typedef'

diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -55,6 +55,7 @@
         self.cdefblock = cdefblock
         self.first_lineno = first_lineno
         self._struct_union_enum_decl = {}
+        self._count_anonymous_struct = 0
 
     def to_ast(self):
         cparser = pycparser.CParser()
@@ -173,15 +174,18 @@
             #
             if isinstance(type, pycparser.c_ast.Struct):
                 # 'struct foobar'
-                return self._get_struct_union_enum_type('struct', type, name)
+                return self._get_struct_union_enum_type('struct', type, const,
+                                                        name)
             #
             if isinstance(type, pycparser.c_ast.Union):
                 # 'union foobar'
-                return self._get_struct_union_enum_type('union', type, name)
+                return self._get_struct_union_enum_type('union', type, const,
+                                                        name)
             #
             if isinstance(type, pycparser.c_ast.Enum):
                 # 'enum foobar'
-                return self._get_struct_union_enum_type('enum', type, name)
+                return self._get_struct_union_enum_type('enum', type, const,
+                                                        name)
         #
         if isinstance(typenode, pycparser.c_ast.FuncDecl):
             # a function type
@@ -189,18 +193,22 @@
         #
         # nested anonymous structs or unions end up here
         if isinstance(typenode, pycparser.c_ast.Struct):
-            return self._get_struct_union_enum_type('struct', typenode, name,
-                                                    nested=True)
+            return self._get_struct_union_enum_type('struct', typenode, const,
+                                                    name, nested=True)
         if isinstance(typenode, pycparser.c_ast.Union):
-            return self._get_struct_union_enum_type('union', typenode, name,
-                                                    nested=True)
+            return self._get_struct_union_enum_type('union', typenode, const,
+                                                    name, nested=True)
         #
         raise api.FFIError(":%d: bad or unsupported type declaration" %
                 typenode.coord.line)
 
-    def _get_struct_union_enum_type(self, kind, type, const):
+    def _get_struct_union_enum_type(self, kind, type, const, approx_name=None):
         name = type.name
-        assert name   # XXX
+        if not name:
+            if not approx_name:
+                self._count_anonymous_struct += 1
+                approx_name = '%d' % (self._count_anonymous_struct,)
+            name = '$%s' % approx_name
         result = model.StructOrUnionOrEnum(kind, name, const)
         #
         # get the type declaration or create it if needed
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -241,7 +241,7 @@
         self.kind = kind
         self.name = name
         self.const = const
-        self.c_name_with_marker = '%s %s&' % (self.kind, self.name)
+        self.c_name_with_marker = '%s %s &' % (self.kind, self.name)
         if const:
             self.c_name_with_marker = 'const ' + self.c_name_with_marker
 
@@ -351,16 +351,20 @@
 
     def write_declaration(self, funcblock):
         tp = "%s %s" % (self.type.kind, self.type.name)
-        extra1 = "(long long)sizeof(%s)" % (tp,)    # total size
+        realtp = tp
+        if self.type.name.startswith('$'):
+            realtp = self.type.name[1:]
+            assert not realtp.isdigit()    # XXX
+        extra1 = "(long long)sizeof(%s)" % (realtp,)    # total size
         extra2 = ("(long long)(((char *)&((struct{char a; %s b;} *)0)->b)"
-                  " - (char *)0)" % (tp,))          # alignment
+                  " - (char *)0)" % (realtp,))          # alignment
         funcblock.sprintf(tp + r" {/*%lld,%lld*/\n",
                           extra="%s, %s" % (extra1, extra2),
                           extralength=40)
         #
         for fldname, fldtype in zip(self.fldnames, self.fldtypes):
             block = CodeBlock(funcblock.tr)
-            inspect = TypeInspector(block, tp, fldname)
+            inspect = TypeInspector(block, realtp, fldname)
             inspect.start()
             # get the offset of the field
             arraylevels = 0
@@ -375,11 +379,12 @@
                     comment = " (%dx)" % arraylevels
                 comment = inspect.get_comment(0, False, "an array%s" % comment)
                 block.writedecl("long long o = offsetof(%s, %s%s);%s"
-                                % (tp, fldname, "[0]" * arraylevels, comment))
+                                % (realtp, fldname, "[0]" * arraylevels,
+                                   comment))
             else:
                 comment = inspect.get_comment(0, False, "not an array")
                 block.writedecl("long long o = ((char *)&((%s *)0)->%s)"
-                                " - (char *)0;%s" % (tp, fldname, comment))
+                                " - (char *)0;%s" % (realtp, fldname, comment))
             #
             block.sprintf("  /*%lld*/", extra="o", extralength=20)
             block.sprintf_add_right(r';\n')
diff --git a/test/codegen/struct-001.c b/test/codegen/struct-001.c
--- a/test/codegen/struct-001.c
+++ b/test/codegen/struct-001.c
@@ -1,6 +1,6 @@
 struct foo_s {
   int aa;
-  int bb;
+  unsigned int bb;
 };
 
 # ____________________________________________________________
diff --git a/test/codegen/struct-005.c b/test/codegen/struct-005.c
new file mode 100644
--- /dev/null
+++ b/test/codegen/struct-005.c
@@ -0,0 +1,60 @@
+typedef struct { int aa; } foo_t;
+
+# ____________________________________________________________
+
+int teststruct_005(char *r)
+{
+    if (!r)
+        return 70 + 30 + 18 + 6 + 4 + 30;
+    r += sprintf(r, "struct $foo_t {/*%lld,%lld*/\n", (long long)sizeof(foo_t), (long long)(((char *)&((struct{char a; foo_t b;} *)0)->b) - (char *)0));
+    {
+        foo_t *p1;
+        long long o = ((char *)&((foo_t *)0)->aa) - (char *)0;  /* check that 'foo_t::aa' is not an array */
+        char b[sizeof(p1->aa)];
+        r += sprintf(r, "  /*%lld*/", o);
+        p1 = (void *)(((char *)b) - o);
+        (void)(p1->aa << 1);  /* check that 'foo_t::aa' is an integer type */
+        p1->aa = -1;  /* check that 'foo_t::aa' is not declared 'const' */
+        if (p1->aa > 0) {
+            if (sizeof(p1->aa) == 1 && p1->aa == 1)
+                r += sprintf(r, "_Bool");
+            else if (sizeof(p1->aa) == sizeof(unsigned int))
+                r += sprintf(r, "unsigned int");
+            else if (sizeof(p1->aa) == sizeof(unsigned short))
+                r += sprintf(r, "unsigned short");
+            else if (sizeof(p1->aa) == sizeof(unsigned char))
+                r += sprintf(r, "unsigned char");
+            else if (sizeof(p1->aa) == sizeof(unsigned long))
+                r += sprintf(r, "unsigned long");
+            else if (sizeof(p1->aa) == sizeof(unsigned long long))
+                r += sprintf(r, "unsigned long long");
+            else
+                r += sprintf(r, "uint%u_t", (int)sizeof(p1->aa) * 8);
+        }
+        else {
+            if (sizeof(p1->aa) == sizeof(int))
+                r += sprintf(r, "int");
+            else if (sizeof(p1->aa) == sizeof(short))
+                r += sprintf(r, "short");
+            else if (sizeof(p1->aa) == sizeof(signed char))
+                r += sprintf(r, "signed char");
+            else if (sizeof(p1->aa) == sizeof(long))
+                r += sprintf(r, "long");
+            else if (sizeof(p1->aa) == sizeof(long long))
+                r += sprintf(r, "long long");
+            else
+                r += sprintf(r, "int%u_t", (int)sizeof(p1->aa) * 8);
+        }
+        r += sprintf(r, " aa;\n");
+    }
+    r += sprintf(r, "};\n");
+    {
+        r += sprintf(r, "typedef struct $foo_t foo_t;\n");
+    }
+    return 0;
+}
+
+#expect struct $foo_t {
+#expect   int aa;
+#expect };
+#expect typedef struct $foo_t foo_t;
diff --git a/test/test_cgcompile.py b/test/test_cgcompile.py
--- a/test/test_cgcompile.py
+++ b/test/test_cgcompile.py
@@ -12,13 +12,17 @@
     #
     expected = []
     for line in inputlines:
-        if line.startswith('# _______'):
-            break
-        line = line.split('//')[0].strip()
-        if line:
-            expected.append(line)
-    else:
-        raise ValueError("no '# _______' found in %r" % (filename,))
+        if line.startswith('#expect'):
+            expected.append(line[8:].rstrip())
+    if not expected:
+        for line in inputlines:
+            if line.startswith('# _______'):
+                break
+            line = line.split('//')[0].rstrip()
+            if line:
+                expected.append(line)
+        else:
+            raise ValueError("no '# _______' found in %r" % (filename,))
     #
     basename = os.path.splitext(filename)[0]
     infile = str(udir.join('cg-' + filename))
@@ -64,7 +68,7 @@
     err = g.close()
     assert not err
     r_remove_addr = re.compile(r"/[*][-0-9a-fx,]+[*]/")
-    got = [r_remove_addr.sub('', line.strip()) for line in lines]
+    got = [r_remove_addr.sub('', line.rstrip()) for line in lines]
     compare_lists(got, expected)
 
 


More information about the pypy-commit mailing list