[pypy-commit] cffi cffi-1.0: the '[...]' syntax
arigo
noreply at buildbot.pypy.org
Sat Apr 18 12:10:26 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1748:28722032dd52
Date: 2015-04-18 12:11 +0200
http://bitbucket.org/cffi/cffi/changeset/28722032dd52/
Log: the '[...]' syntax
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -222,7 +222,7 @@
elif length == '...':
brackets = '&[/*...*/]'
else:
- brackets = '&[%d]' % length
+ brackets = '&[%s]' % length
self.c_name_with_marker = (
self.item.c_name_with_marker.replace('&', brackets))
diff --git a/new/_cffi_include.h b/new/_cffi_include.h
--- a/new/_cffi_include.h
+++ b/new/_cffi_include.h
@@ -159,6 +159,8 @@
assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
(CTypeDescrObject *)_cffi_types[index])
+#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
+
static int _cffi_init(void)
{
diff --git a/new/recompiler.py b/new/recompiler.py
--- a/new/recompiler.py
+++ b/new/recompiler.py
@@ -369,11 +369,19 @@
# ----------
# named structs or unions
+ def _field_type(self, tp_struct, field_name, tp_field):
+ if isinstance(tp_field, model.ArrayType) and tp_field.length == '...':
+ ptr_struct_name = tp_struct.get_c_name('*')
+ actual_length = '_cffi_array_len(((%s)0)->%s)' % (
+ ptr_struct_name, field_name)
+ tp_field = model.ArrayType(tp_field.item, actual_length)
+ return tp_field
+
def _generate_cpy_struct_collecttype(self, tp, name):
self._do_collect_type(tp)
if tp.fldtypes is not None:
- for tp1 in tp.fldtypes:
- self._do_collect_type(tp1)
+ for name1, tp1 in zip(tp.fldnames, tp.fldtypes):
+ self._do_collect_type(self._field_type(tp, name1, tp1))
def _generate_cpy_struct_decl(self, tp, name):
if tp.fldtypes is not None:
@@ -390,6 +398,7 @@
if tp.fldtypes is not None:
c_field = [name]
for fldname, fldtype in zip(tp.fldnames, tp.fldtypes):
+ fldtype = self._field_type(tp, fldname, fldtype)
spaces = " " * len(fldname)
c_field.append(
' { "%s", offsetof(%s, %s),\n' % (
@@ -483,13 +492,20 @@
# ----------
# global variables
+ def _global_type(self, tp, global_name):
+ if isinstance(tp, model.ArrayType) and tp.length == '...':
+ actual_length = '_cffi_array_len(%s)' % (global_name,)
+ tp = model.ArrayType(tp.item, actual_length)
+ return tp
+
def _generate_cpy_variable_collecttype(self, tp, name):
- self._do_collect_type(tp)
+ self._do_collect_type(self._global_type(tp, name))
def _generate_cpy_variable_decl(self, tp, name):
pass
def _generate_cpy_variable_ctx(self, tp, name):
+ tp = self._global_type(tp, name)
type_index = self._typesdict[tp]
self._lsts["global"].append(
' { "%s", &%s, _CFFI_OP(_CFFI_OP_GLOBAL_VAR, %d)},'
@@ -528,10 +544,15 @@
item_index = self._typesdict[tp.item]
if tp.length is None:
self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index)
+ elif tp.length == '...':
+ raise ffiplatform.VerificationError(
+ "type %s badly placed: the '...' array length can only be "
+ "used on global arrays or on fields of structures" % (
+ str(tp).replace('/*...*/', '...'),))
else:
assert self.cffi_types[index + 1] == 'LEN'
self.cffi_types[index] = CffiOp(OP_ARRAY, item_index)
- self.cffi_types[index + 1] = CffiOp(None, '%d' % (tp.length,))
+ self.cffi_types[index + 1] = CffiOp(None, str(tp.length))
def _emit_bytecode_StructType(self, tp, index):
struct_index = self._struct_unions[tp]
diff --git a/new/test_recompiler.py b/new/test_recompiler.py
--- a/new/test_recompiler.py
+++ b/new/test_recompiler.py
@@ -219,3 +219,26 @@
ffi2.typeof("struct foo_s*(*)()"))
assert ffi1.typeof("void(*)(struct foo_s*)") is not (
ffi2.typeof("void(*)(struct foo_s*)"))
+
+def test_dotdotdot_length_of_array_field():
+ ffi = FFI()
+ ffi.cdef("struct foo_s { int a[...]; int b[...]; };")
+ verify(ffi, 'test_dotdotdot_length_of_array_field',
+ "struct foo_s { int a[42]; int b[11]; };")
+ assert ffi.sizeof("struct foo_s") == (42 + 11) * 4
+ p = ffi.new("struct foo_s *")
+ assert p.a[41] == p.b[10] == 0
+ py.test.raises(IndexError, "p.a[42]")
+ py.test.raises(IndexError, "p.b[11]")
+
+def test_dotdotdot_global_array():
+ ffi = FFI()
+ ffi.cdef("int aa[...]; int bb[...];")
+ lib = verify(ffi, 'test_dotdotdot_global_array',
+ "int aa[41]; int bb[12];")
+ assert ffi.sizeof(lib.aa) == 41 * 4
+ assert ffi.sizeof(lib.bb) == 12 * 4
+ assert lib.aa[40] == lib.bb[11] == 0
+ py.test.raises(IndexError, "lib.aa[41]")
+ py.test.raises(IndexError, "lib.bb[12]")
+
More information about the pypy-commit
mailing list