[pypy-commit] cffi linux-only: Progress on test_ffi_nonfull_struct(), but unfinished so far.

arigo noreply at buildbot.pypy.org
Fri Jun 8 15:50:09 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: linux-only
Changeset: r280:1420a9fb32b8
Date: 2012-06-08 15:49 +0200
http://bitbucket.org/cffi/cffi/changeset/1420a9fb32b8/

Log:	Progress on test_ffi_nonfull_struct(), but unfinished so far.

diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -83,6 +83,7 @@
     def _declare(self, name, obj):
         if name in self._declarations:
             raise api.FFIError("multiple declarations of %s" % (name,))
+        assert name != '__dotdotdot__'
         self._declarations[name] = obj
 
     def _get_type_pointer(self, type, const=False):
@@ -144,6 +145,8 @@
                 ident = ' '.join(names)
                 if ident == 'void':
                     return model.void_type
+                if ident == '__dotdotdot__':
+                    raise api.FFIError('bad usage of "..."')
                 return model.PrimitiveType(ident)
             #
             if isinstance(type, pycparser.c_ast.Struct):
@@ -250,10 +253,11 @@
         for decl in type.decls:
             if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and
                     ''.join(decl.type.names) == '__dotdotdot__'):
-                xxxx
                 # XXX pycparser is inconsistent: 'names' should be a list
                 # of strings, but is sometimes just one string.  Use
                 # str.join() as a way to cope with both.
+                tp.partial = True
+                continue
             if decl.bitsize is None:
                 bitsize = -1
             else:
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -26,7 +26,7 @@
         except KeyError:
             return self.new_backend_type(ffi, *args)
 
-    def verifier_declare(self, verifier, kind, name, f):
+    def verifier_declare(self, verifier, kind, name):
         # nothing to see here
         pass
 
@@ -78,9 +78,10 @@
     def new_backend_type(self, ffi, result, *args):
         return ffi._backend.new_function_type(args, result, self.ellipsis)
 
-    def verifier_declare(self, verifier, kind, name, f):
+    def verifier_declare(self, verifier, kind, name):
         if kind == 'function':
-            f.write('  { %s = %s; }\n' % (self.get_c_name('result'), name))
+            verifier.write('  { %s = %s; }\n' % (
+                self.get_c_name('result'), name))
 
 
 class PointerType(BaseType):
@@ -157,17 +158,42 @@
 
 class StructType(StructOrUnion):
     kind = 'struct'
+    partial = False
+
+    def check_not_partial(self):
+        if self.partial:
+            from . import ffiplatform
+            raise ffiplatform.VerificationMissing(self.get_c_name())
 
     def get_btype(self, ffi):
+        self.check_not_partial()
         return ffi._backend.new_struct_type(self.name)
 
-    def verifier_declare(self, verifier, name, f):
-        verifier._write_printf(f, 'BEGIN struct %s size(%%ld)' % self.name,
-                      'sizeof(struct %s)' % self.name)
-        for decl in decl.decls:
-            pass
-            #_write_printf(f, 'FIELD ofs(%s) size(%s)')
-        verifier._write_printf(f, 'END struct %s' % self.name)
+    def verifier_declare(self, verifier, kind, name):
+        if kind != 'struct':
+            return
+        if self.fldnames is None:
+            assert not self.partial
+            return
+        verifier.write('{')
+        verifier.write('struct __aligncheck__ { char x; struct %s y; };' %
+                       self.name)
+        verifier.write('struct %s __test__;' % self.name)
+        verifier.write_printf('BEGIN struct %s' % self.name)
+        verifier.write_printf('SIZE %ld %ld',
+                              '(long)sizeof(struct %s)' % self.name,
+                              '(long)offsetof(struct __aligncheck__, y)')
+        for fname, ftype, fbitsize in zip(self.fldnames, self.fldtypes,
+                                          self.fldbitsize):
+            if fbitsize < 0:
+                verifier.write_printf('FIELD ' + fname + ' %ld %ld',
+                                      '(long)offsetof(struct %s, %s)' %
+                                      (self.name, fname),
+                                      '(long)sizeof(__test__.%s)' % fname)
+            else:
+                assert 0, "XXX: bitfield"
+        verifier.write_printf('END')
+        verifier.write('}')
 
 class UnionType(StructOrUnion):
     kind = 'union'
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -3,23 +3,31 @@
 
 class Verifier(object):
 
-    def _write_printf(f, what, *args):
+    def write(self, what):
+        print >> self.f, '  ' + what
+
+    def write_printf(self, what, *args):
+        self.has_printf = True
         if not args:
-            f.write('  printf("%s\\n");\n' % (what,))
+            print >> self.f, '  printf("%s\\n");' % (what,)
         else:
-            f.write('  printf("%s\\n", %s);\n' % (what, ', '.join(args)))
+            print >> self.f, '  printf("%s\\n", %s);' % (
+                what, ', '.join(args))
 
     def verify(self, ffi, preamble, **kwargs):
         tst_file_base = ffiplatform._get_test_file_base()
+        self.has_printf = False
         with open(tst_file_base + '.c', 'w') as f:
             f.write('#include <stdio.h>\n')
             f.write('#include <stdint.h>\n')
             f.write('#include <stddef.h>\n')
             f.write(preamble + "\n\n")
             f.write('int main() {\n')
+            self.f = f
             for name, tp in ffi._parser._declarations.iteritems():
                 kind, realname = name.split(' ', 1)
-                tp.verifier_declare(self, kind, realname, f)
+                tp.verifier_declare(self, kind, realname)
+            del self.f
             f.write('  return 0;\n')
             f.write('}\n')
         err = os.system('gcc -Werror -c %s.c -o %s.o' %
diff --git a/testing/test_platform.py b/testing/test_platform.py
deleted file mode 100644
--- a/testing/test_platform.py
+++ /dev/null
@@ -1,19 +0,0 @@
-
-import py
-from cffi import FFI, VerificationMissing
-
-def test_ffi_nonfull_struct():
-    py.test.skip("XXX")
-    ffi = FFI()
-    ffi.cdef("""
-    struct sockaddr {
-       int sa_family;
-       ...;
-    };
-    """)
-    py.test.raises(VerificationMissing, ffi.sizeof, 'struct sockaddr')
-    ffi.verify('''
-    #include <sys/types.h>
-    #include <sys/socket.h>
-    ''')
-    assert ffi.sizeof('struct sockaddr') == 14 + ffi.sizeof(int)
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1,5 +1,6 @@
 import py
-from cffi import FFI, VerificationError
+from cffi import FFI, VerificationError, VerificationMissing
+
 
 def test_simple_verify():
     ffi = FFI()
@@ -21,3 +22,24 @@
     ffi = FFI()
     ffi.cdef("size_t strlen(const char *s);")
     ffi.verify("#include <string.h>")
+
+
+def test_ffi_nonfull_struct():
+    py.test.skip("XXX")
+    ffi = FFI()
+    ffi.cdef("""
+    struct foo_s {
+       int x;
+       ...;
+    };
+    """)
+    py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
+    py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
+    py.test.raises(VerificationMissing, ffi.new, 'struct foo_s')
+    ffi.verify("""
+    struct foo_s {
+       int a, b, x, c, d, e;
+    };
+    """)
+    assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof(int)
+    assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof(int)


More information about the pypy-commit mailing list