summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2014-03-05 09:19:21 +0100
committerArmin Rigo <arigo@tunes.org>2014-03-05 09:19:21 +0100
commit8b01a1c68ffdcedb1822967fdd57ccdd7f3cdb0e (patch)
tree94c839f20ac0acacfd375b70af24d2f7b710cc42
parentdc7ee4dc153b181165da10d645f6eb32e00de0d4 (diff)
downloadcffi-8b01a1c68ffdcedb1822967fdd57ccdd7f3cdb0e.tar.gz
Clean up 'sflags'. It was failing because suddenly passing a value
of 0 as argument was not equivalent to not passing any argument at all.
-rw-r--r--c/_cffi_backend.c51
-rw-r--r--c/test_c.py73
2 files changed, 74 insertions, 50 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index bf675c2..401c91c 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3583,10 +3583,40 @@ _add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype,
return cf; /* borrowed reference */
}
-#define SF_MSVC_BITFIELDS 1
-#define SF_GCC_ARM_BITFIELDS 2
-#define SF_GCC_BIG_ENDIAN 4
-#define SF_PACKED 8
+#define SF_MSVC_BITFIELDS 0x01
+#define SF_GCC_ARM_BITFIELDS 0x02
+#define SF_GCC_X86_BITFIELDS 0x10
+
+#define SF_GCC_BIG_ENDIAN 0x04
+#define SF_GCC_LITTLE_ENDIAN 0x40
+
+#define SF_PACKED 0x08
+
+static int complete_sflags(int sflags)
+{
+ /* add one of the SF_xxx_BITFIELDS flags if none is specified */
+ if (!(sflags & (SF_MSVC_BITFIELDS | SF_GCC_ARM_BITFIELDS |
+ SF_GCC_X86_BITFIELDS))) {
+#ifdef MS_WIN32
+ sflags |= SF_MSVC_BITFIELDS;
+#else
+# ifdef __arm__
+ sflags |= SF_GCC_ARM_BITFIELDS;
+# else
+ sflags |= SF_GCC_X86_BITFIELDS;
+# endif
+#endif
+ }
+ /* add one of SF_GCC_xx_ENDIAN if none is specified */
+ if (!(sflags & (SF_GCC_BIG_ENDIAN | SF_GCC_LITTLE_ENDIAN))) {
+ int _check_endian = 1;
+ if (*(char *)&_check_endian == 0)
+ sflags |= SF_GCC_BIG_ENDIAN;
+ else
+ sflags |= SF_GCC_LITTLE_ENDIAN;
+ }
+ return sflags;
+}
static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
{
@@ -3598,18 +3628,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
int totalalignment = -1;
CFieldObject **previous;
int prev_bitfield_size, prev_bitfield_free;
-#ifdef MS_WIN32
- int sflags = SF_MSVC_BITFIELDS;
-#else
-# ifdef __arm__
- int sflags = SF_GCC_ARM_BITFIELDS;
-# else
int sflags = 0;
-# endif
- int _check_endian = 1;
- if (*(char *)&_check_endian == 0)
- sflags |= SF_GCC_BIG_ENDIAN;
-#endif
if (!PyArg_ParseTuple(args, "O!O!|Onii:complete_struct_or_union",
&CTypeDescr_Type, &ct,
@@ -3617,6 +3636,8 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
&ignored, &totalsize, &totalalignment, &sflags))
return NULL;
+ sflags = complete_sflags(sflags);
+
if ((ct->ct_flags & (CT_STRUCT|CT_IS_OPAQUE)) ==
(CT_STRUCT|CT_IS_OPAQUE)) {
is_union = 0;
diff --git a/c/test_c.py b/c/test_c.py
index 0c62995..1d59192 100644
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2897,7 +2897,7 @@ def _test_bitfield_details(flag):
('b1', BInt, 9),
('b2', BUInt, 7),
('c', BChar, -1)], -1, -1, -1, flag)
- if flag % 2 == 0: # gcc, any variant
+ if not (flag & SF_MSVC_BITFIELDS): # gcc, any variant
assert typeoffsetof(BStruct, 'c') == (BChar, 3)
assert sizeof(BStruct) == 4
else: # msvc
@@ -2912,20 +2912,20 @@ def _test_bitfield_details(flag):
p.c = b'\x9D'
raw = buffer(p)[:]
if sys.byteorder == 'little':
- if flag == 0 or flag == 2: # gcc, little endian
- assert raw == b'A7\xC7\x9D'
- elif flag == 1: # msvc
+ if flag & SF_MSVC_BITFIELDS:
assert raw == b'A\x00\x00\x007\xC7\x00\x00\x9D\x00\x00\x00'
- elif flag == 4: # gcc, big endian
+ elif flag & SF_GCC_LITTLE_ENDIAN:
+ assert raw == b'A7\xC7\x9D'
+ elif flag & SF_GCC_BIG_ENDIAN:
assert raw == b'A\xE3\x9B\x9D'
else:
raise AssertionError("bad flag")
else:
- if flag == 0 or flag == 2: # gcc
- assert raw == b'A\xC77\x9D'
- elif flag == 1: # msvc
+ if flag & SF_MSVC_BITFIELDS:
assert raw == b'A\x00\x00\x00\x00\x00\xC77\x9D\x00\x00\x00'
- elif flag == 4: # gcc, big endian
+ elif flag & SF_GCC_LITTLE_ENDIAN:
+ assert raw == b'A\xC77\x9D'
+ elif flag & SF_GCC_BIG_ENDIAN:
assert raw == b'A\x9B\xE3\x9D'
else:
raise AssertionError("bad flag")
@@ -2935,18 +2935,15 @@ def _test_bitfield_details(flag):
('', BShort, 9),
('c', BChar, -1)], -1, -1, -1, flag)
assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- if flag == 0: # gcc
- assert sizeof(BStruct) == 5
- assert alignof(BStruct) == 1
- elif flag == 1: # msvc
+ if flag & SF_MSVC_BITFIELDS:
assert sizeof(BStruct) == 6
assert alignof(BStruct) == 2
- elif flag == 2: # gcc ARM
- assert sizeof(BStruct) == 6
- assert alignof(BStruct) == 2
- elif flag == 4: # gcc, big endian
+ elif flag & SF_GCC_X86_BITFIELDS:
assert sizeof(BStruct) == 5
assert alignof(BStruct) == 1
+ elif flag & SF_GCC_ARM_BITFIELDS:
+ assert sizeof(BStruct) == 6
+ assert alignof(BStruct) == 2
else:
raise AssertionError("bad flag")
#
@@ -2955,37 +2952,43 @@ def _test_bitfield_details(flag):
('', BInt, 0),
('', BInt, 0),
('c', BChar, -1)], -1, -1, -1, flag)
- if flag == 0: # gcc
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- assert sizeof(BStruct) == 5
- assert alignof(BStruct) == 1
- elif flag == 1: # msvc
+ if flag & SF_MSVC_BITFIELDS:
assert typeoffsetof(BStruct, 'c') == (BChar, 1)
assert sizeof(BStruct) == 2
assert alignof(BStruct) == 1
- elif flag == 2: # gcc ARM
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- assert sizeof(BStruct) == 8
- assert alignof(BStruct) == 4
- elif flag == 4: # gcc, big endian
+ elif flag & SF_GCC_X86_BITFIELDS:
assert typeoffsetof(BStruct, 'c') == (BChar, 4)
assert sizeof(BStruct) == 5
assert alignof(BStruct) == 1
+ elif flag & SF_GCC_ARM_BITFIELDS:
+ assert typeoffsetof(BStruct, 'c') == (BChar, 4)
+ assert sizeof(BStruct) == 8
+ assert alignof(BStruct) == 4
else:
raise AssertionError("bad flag")
-def test_bitfield_as_gcc():
- _test_bitfield_details(flag=0)
+SF_MSVC_BITFIELDS = 0x01
+SF_GCC_ARM_BITFIELDS = 0x02
+SF_GCC_X86_BITFIELDS = 0x10
+
+SF_GCC_BIG_ENDIAN = 0x04
+SF_GCC_LITTLE_ENDIAN = 0x40
+
+SF_PACKED = 0x08
+
+def test_bitfield_as_x86_gcc():
+ _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
def test_bitfield_as_msvc():
- _test_bitfield_details(flag=1)
+ _test_bitfield_details(flag=SF_MSVC_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
def test_bitfield_as_arm_gcc():
- _test_bitfield_details(flag=2)
+ _test_bitfield_details(flag=SF_GCC_ARM_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-def test_bitfield_as_big_endian():
- _test_bitfield_details(flag=4)
+def test_bitfield_as_ppc_gcc():
+ # PowerPC uses the same format as X86, but is big-endian
+ _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_BIG_ENDIAN)
def test_struct_array_no_length():
@@ -3161,7 +3164,7 @@ def test_packed():
complete_struct_or_union(BStruct, [('a1', BLong, -1),
('a2', BChar, -1),
('a3', BShort, -1)],
- None, -1, -1, 8) # SF_PACKED==8
+ None, -1, -1, SF_PACKED)
d = BStruct.fields
assert len(d) == 3
assert d[0][0] == 'a1'
@@ -3190,7 +3193,7 @@ def test_packed_with_bitfields():
complete_struct_or_union,
BStruct, [('a1', BLong, 30),
('a2', BChar, 5)],
- None, -1, -1, 8) # SF_PACKED==8
+ None, -1, -1, SF_PACKED)
def test_version():
# this test is here mostly for PyPy