Author: Armin Rigo <ar...@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit