summaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rwxr-xr-xc/.libs_cffi_backend/libffi-9c61262e.so.8.1.0bin63080 -> 0 bytes
-rw-r--r--c/Android.bp44
-rw-r--r--c/_cffi_backend.c8083
-rwxr-xr-xc/_cffi_backend.sobin791800 -> 0 bytes
-rw-r--r--c/_dummy_file_cffi_backend.py0
-rw-r--r--c/_dummy_file_libffi.py0
-rw-r--r--c/call_python.c292
-rw-r--r--c/cdlopen.c362
-rw-r--r--c/cffi1_module.c216
-rw-r--r--c/cglob.c113
-rw-r--r--c/commontypes.c216
-rw-r--r--c/ffi_obj.c1221
-rw-r--r--c/file_emulator.h93
-rw-r--r--c/lib_obj.c716
-rw-r--r--c/libffi_arm64/README5
-rw-r--r--c/libffi_arm64/ffi.libbin7872 -> 0 bytes
-rw-r--r--c/libffi_arm64/include/ffi.h515
-rw-r--r--c/libffi_arm64/include/fficonfig.h215
-rw-r--r--c/libffi_arm64/include/ffitarget.h92
-rw-r--r--c/libffi_x86_x64/LICENSE20
-rw-r--r--c/libffi_x86_x64/README502
-rw-r--r--c/libffi_x86_x64/README.ctypes7
-rw-r--r--c/libffi_x86_x64/ffi.c495
-rw-r--r--c/libffi_x86_x64/ffi.h322
-rw-r--r--c/libffi_x86_x64/ffi_common.h77
-rw-r--r--c/libffi_x86_x64/fficonfig.h96
-rw-r--r--c/libffi_x86_x64/ffitarget.h85
-rw-r--r--c/libffi_x86_x64/prep_cif.c184
-rw-r--r--c/libffi_x86_x64/types.c104
-rw-r--r--c/libffi_x86_x64/win32.c162
-rw-r--r--c/libffi_x86_x64/win64.asm156
-rw-r--r--c/libffi_x86_x64/win64.objbin1176 -> 0 bytes
-rw-r--r--c/malloc_closure.h176
-rw-r--r--c/minibuffer.h408
-rw-r--r--c/misc_thread_common.h371
-rw-r--r--c/misc_thread_posix.h49
-rw-r--r--c/misc_win32.h242
-rw-r--r--c/parse_c_type.c847
-rw-r--r--c/realize_c_type.c820
-rw-r--r--c/test_c.py4575
-rw-r--r--c/wchar_helper.h246
-rw-r--r--c/wchar_helper_3.h149
42 files changed, 0 insertions, 22276 deletions
diff --git a/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0 b/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0
deleted file mode 100755
index 82b4232..0000000
--- a/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0
+++ /dev/null
Binary files differ
diff --git a/c/Android.bp b/c/Android.bp
deleted file mode 100644
index 96565df..0000000
--- a/c/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "external_python_cffi_license"
- // to get the below license kinds:
- // SPDX-license-identifier-MIT
- default_applicable_licenses: ["external_python_cffi_license"],
-}
-
-python_library {
- name: "py-cffi-backend",
- host_supported: true,
- srcs: [
- "_dummy_file_cffi_backend.py",
- ],
- data: [
- ":py-cffi-backend-files"
- ],
-}
-
-filegroup {
- name: "py-cffi-backend-files",
- srcs: [
- "_cffi_backend.so",
- ],
-}
-
-python_library {
- name: "py-cffi-backend-libffi",
- host_supported: true,
- srcs: [
- "_dummy_file_libffi.py",
- ],
- data: [
- ":py-cffi-backend-libffi-files"
- ],
-}
-
-filegroup {
- name: "py-cffi-backend-libffi-files",
- srcs: [
- ".libs_cffi_backend/libffi-9c61262e.so.8.1.0",
- ],
-}
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
deleted file mode 100644
index ffecbf9..0000000
--- a/c/_cffi_backend.c
+++ /dev/null
@@ -1,8083 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include "structmember.h"
-
-#define CFFI_VERSION "1.15.0"
-
-#ifdef MS_WIN32
-#include <windows.h>
-#include "misc_win32.h"
-#else
-#include <stddef.h>
-#include <stdint.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <ffi.h>
-#include <sys/mman.h>
-#endif
-
-/* this block of #ifs should be kept exactly identical between
- c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */
-#if defined(_MSC_VER)
-# include <malloc.h> /* for alloca() */
-# if _MSC_VER < 1600 /* MSVC < 2010 */
- typedef __int8 int8_t;
- typedef __int16 int16_t;
- typedef __int32 int32_t;
- typedef __int64 int64_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
- typedef unsigned __int64 uint64_t;
- typedef __int8 int_least8_t;
- typedef __int16 int_least16_t;
- typedef __int32 int_least32_t;
- typedef __int64 int_least64_t;
- typedef unsigned __int8 uint_least8_t;
- typedef unsigned __int16 uint_least16_t;
- typedef unsigned __int32 uint_least32_t;
- typedef unsigned __int64 uint_least64_t;
- typedef __int8 int_fast8_t;
- typedef __int16 int_fast16_t;
- typedef __int32 int_fast32_t;
- typedef __int64 int_fast64_t;
- typedef unsigned __int8 uint_fast8_t;
- typedef unsigned __int16 uint_fast16_t;
- typedef unsigned __int32 uint_fast32_t;
- typedef unsigned __int64 uint_fast64_t;
- typedef __int64 intmax_t;
- typedef unsigned __int64 uintmax_t;
-# else
-# include <stdint.h>
-# endif
-# if _MSC_VER < 1800 /* MSVC < 2013 */
- typedef unsigned char _Bool;
-# endif
-#else
-# include <stdint.h>
-# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
-# include <alloca.h>
-# endif
-#endif
-
-
-/* Define the following macro ONLY if you trust libffi's version of
- * ffi_closure_alloc() more than the code in malloc_closure.h.
- * IMPORTANT: DO NOT ENABLE THIS ON LINUX, unless you understand exactly
- * why I recommend against it and decide that you trust it more than my
- * analysis below.
- *
- * There are two versions of this code: one inside libffi itself, and
- * one inside malloc_closure.h here. Both should be fine as long as the
- * Linux distribution does _not_ enable extra security features. If it
- * does, then the code in malloc_closure.h will cleanly crash because
- * there is no reasonable way to obtain a read-write-execute memory
- * page. On the other hand, the code in libffi will appear to
- * work---but will actually randomly crash after a fork() if the child
- * does not immediately call exec(). This second crash is of the kind
- * that can be turned into an attack vector by a motivated attacker.
- * So, _enabling_ extra security features _opens_ an attack vector.
- * That sounds like a horribly bad idea to me, and is the reason for why
- * I prefer CFFI crashing cleanly.
- *
- * Currently, we use libffi's ffi_closure_alloc() on NetBSD. It is
- * known that on the NetBSD kernel, a different strategy is used which
- * should not be open to the fork() bug.
- *
- * This is also used on macOS, provided we are executing on macOS 10.15 or
- * above. It's a mess because it needs runtime checks in that case.
- */
-#ifdef __NetBSD__
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
-
-#elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE)
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1
-
-#else
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC 0
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 0
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
-
-#endif
-
-/* always includes this, even if it turns out not to be used on NetBSD
- because calls are behind "if (0)" */
-#include "malloc_closure.h"
-
-
-#if PY_MAJOR_VERSION >= 3
-# define STR_OR_BYTES "bytes"
-# define PyText_Type PyUnicode_Type
-# define PyText_Check PyUnicode_Check
-# define PyTextAny_Check PyUnicode_Check
-# define PyText_FromFormat PyUnicode_FromFormat
-# define PyText_AsUTF8 _PyUnicode_AsString /* PyUnicode_AsUTF8 in Py3.3 */
-# define PyText_AS_UTF8 _PyUnicode_AsString
-# if PY_VERSION_HEX >= 0x03030000
-# define PyText_GetSize PyUnicode_GetLength
-# else
-# define PyText_GetSize PyUnicode_GetSize
-# endif
-# define PyText_FromString PyUnicode_FromString
-# define PyText_FromStringAndSize PyUnicode_FromStringAndSize
-# define PyText_InternInPlace PyUnicode_InternInPlace
-# define PyText_InternFromString PyUnicode_InternFromString
-# define PyIntOrLong_Check PyLong_Check
-#else
-# define STR_OR_BYTES "str"
-# define PyText_Type PyString_Type
-# define PyText_Check PyString_Check
-# define PyTextAny_Check(op) (PyString_Check(op) || PyUnicode_Check(op))
-# define PyText_FromFormat PyString_FromFormat
-# define PyText_AsUTF8 PyString_AsString
-# define PyText_AS_UTF8 PyString_AS_STRING
-# define PyText_GetSize PyString_Size
-# define PyText_FromString PyString_FromString
-# define PyText_FromStringAndSize PyString_FromStringAndSize
-# define PyText_InternInPlace PyString_InternInPlace
-# define PyText_InternFromString PyString_InternFromString
-# define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-# define PyInt_FromLong PyLong_FromLong
-# define PyInt_FromSsize_t PyLong_FromSsize_t
-# define PyInt_AsSsize_t PyLong_AsSsize_t
-# define PyInt_AsLong PyLong_AsLong
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-/* This is the default on Python3 and constant has been removed. */
-# define Py_TPFLAGS_CHECKTYPES 0
-#endif
-
-#if PY_MAJOR_VERSION < 3
-# undef PyCapsule_GetPointer
-# undef PyCapsule_New
-# define PyCapsule_GetPointer(capsule, name) \
- (PyCObject_AsVoidPtr(capsule))
-# define PyCapsule_New(pointer, name, destructor) \
- (PyCObject_FromVoidPtr(pointer, destructor))
-#endif
-
-#if PY_VERSION_HEX < 0x030900a4
-# define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val))
-#endif
-
-#if PY_VERSION_HEX >= 0x03080000
-# define USE_WRITEUNRAISABLEMSG
-#endif
-
-/************************************************************/
-
-/* base type flag: exactly one of the following: */
-#define CT_PRIMITIVE_SIGNED 0x001 /* signed integer */
-#define CT_PRIMITIVE_UNSIGNED 0x002 /* unsigned integer */
-#define CT_PRIMITIVE_CHAR 0x004 /* char, wchar_t, charN_t */
-#define CT_PRIMITIVE_FLOAT 0x008 /* float, double, long double */
-#define CT_POINTER 0x010 /* pointer, excluding ptr-to-func */
-#define CT_ARRAY 0x020 /* array */
-#define CT_STRUCT 0x040 /* struct */
-#define CT_UNION 0x080 /* union */
-#define CT_FUNCTIONPTR 0x100 /* pointer to function */
-#define CT_VOID 0x200 /* void */
-#define CT_PRIMITIVE_COMPLEX 0x400 /* float _Complex, double _Complex */
-
-/* other flags that may also be set in addition to the base flag: */
-#define CT_IS_VOIDCHAR_PTR 0x00001000
-#define CT_PRIMITIVE_FITS_LONG 0x00002000
-#define CT_IS_OPAQUE 0x00004000
-#define CT_IS_ENUM 0x00008000
-#define CT_IS_PTR_TO_OWNED 0x00010000 /* only owned if CDataOwning_Type */
-#define CT_CUSTOM_FIELD_POS 0x00020000
-#define CT_IS_LONGDOUBLE 0x00040000
-#define CT_IS_BOOL 0x00080000
-#define CT_IS_FILE 0x00100000
-#define CT_IS_VOID_PTR 0x00200000
-#define CT_WITH_VAR_ARRAY 0x00400000 /* with open-ended array, anywhere */
-/* unused 0x00800000 */
-#define CT_LAZY_FIELD_LIST 0x01000000
-#define CT_WITH_PACKED_CHANGE 0x02000000
-#define CT_IS_SIGNED_WCHAR 0x04000000
-#define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \
- CT_PRIMITIVE_UNSIGNED | \
- CT_PRIMITIVE_CHAR | \
- CT_PRIMITIVE_FLOAT | \
- CT_PRIMITIVE_COMPLEX)
-
-typedef struct _ctypedescr {
- PyObject_VAR_HEAD
-
- struct _ctypedescr *ct_itemdescr; /* ptrs and arrays: the item type */
- PyObject *ct_stuff; /* structs: dict of the fields
- arrays: ctypedescr of the ptr type
- function: tuple(abi, ctres, ctargs..)
- enum: pair {"name":x},{x:"name"}
- ptrs: lazily, ctypedescr of array */
- void *ct_extra; /* structs: first field (not a ref!)
- function types: cif_description
- primitives: prebuilt "cif" object */
-
- PyObject *ct_weakreflist; /* weakref support */
-
- PyObject *ct_unique_key; /* key in unique_cache (a string, but not
- human-readable) */
-
- Py_ssize_t ct_size; /* size of instances, or -1 if unknown */
- Py_ssize_t ct_length; /* length of arrays, or -1 if unknown;
- or alignment of primitive and struct types;
- always -1 for pointers */
- int ct_flags; /* CT_xxx flags */
-
- int ct_name_position; /* index in ct_name of where to put a var name */
- char ct_name[1]; /* string, e.g. "int *" for pointers to ints */
-} CTypeDescrObject;
-
-typedef struct {
- PyObject_HEAD
- CTypeDescrObject *c_type;
- char *c_data;
- PyObject *c_weakreflist;
-} CDataObject;
-
-typedef struct cfieldobject_s {
- PyObject_HEAD
- CTypeDescrObject *cf_type;
- Py_ssize_t cf_offset;
- short cf_bitshift; /* >= 0: bitshift; or BS_REGULAR or BS_EMPTY_ARRAY */
- short cf_bitsize;
- unsigned char cf_flags; /* BF_... */
- struct cfieldobject_s *cf_next;
-} CFieldObject;
-#define BS_REGULAR (-1) /* a regular field, not with bitshift */
-#define BS_EMPTY_ARRAY (-2) /* a field declared 'type[0]' or 'type[]' */
-#define BF_IGNORE_IN_CTOR 0x01 /* union field not in the first place */
-
-static PyTypeObject CTypeDescr_Type;
-static PyTypeObject CField_Type;
-static PyTypeObject CData_Type;
-static PyTypeObject CDataOwning_Type;
-static PyTypeObject CDataOwningGC_Type;
-static PyTypeObject CDataFromBuf_Type;
-static PyTypeObject CDataGCP_Type;
-
-#define CTypeDescr_Check(ob) (Py_TYPE(ob) == &CTypeDescr_Type)
-#define CData_Check(ob) (Py_TYPE(ob) == &CData_Type || \
- Py_TYPE(ob) == &CDataOwning_Type || \
- Py_TYPE(ob) == &CDataOwningGC_Type || \
- Py_TYPE(ob) == &CDataFromBuf_Type || \
- Py_TYPE(ob) == &CDataGCP_Type)
-#define CDataOwn_Check(ob) (Py_TYPE(ob) == &CDataOwning_Type || \
- Py_TYPE(ob) == &CDataOwningGC_Type)
-
-typedef union {
- unsigned char m_char;
- unsigned short m_short;
- unsigned int m_int;
- unsigned long m_long;
- unsigned long long m_longlong;
- float m_float;
- double m_double;
- long double m_longdouble;
-} union_alignment;
-
-typedef struct {
- CDataObject head;
- union_alignment alignment;
-} CDataObject_casted_primitive;
-
-typedef struct {
- CDataObject head;
- union_alignment alignment;
-} CDataObject_own_nolength;
-
-typedef struct {
- CDataObject head;
- Py_ssize_t length;
- union_alignment alignment;
-} CDataObject_own_length;
-
-typedef struct {
- CDataObject head;
- PyObject *structobj; /* for ffi.new_handle() or ffi.new("struct *") */
-} CDataObject_own_structptr;
-
-typedef struct {
- CDataObject head;
- Py_ssize_t length; /* same as CDataObject_own_length up to here */
- Py_buffer *bufferview;
-} CDataObject_frombuf;
-
-typedef struct {
- CDataObject head;
- Py_ssize_t length; /* same as CDataObject_own_length up to here */
- PyObject *origobj;
- PyObject *destructor;
-} CDataObject_gcp;
-
-typedef struct {
- CDataObject head;
- ffi_closure *closure;
-} CDataObject_closure;
-
-typedef struct {
- ffi_cif cif;
- /* the following information is used when doing the call:
- - a buffer of size 'exchange_size' is malloced
- - the arguments are converted from Python objects to raw data
- - the i'th raw data is stored at 'buffer + exchange_offset_arg[1+i]'
- - the call is done
- - the result is read back from 'buffer + exchange_offset_arg[0]' */
- Py_ssize_t exchange_size;
- Py_ssize_t exchange_offset_arg[1];
-} cif_description_t;
-
-#define ADD_WRAPAROUND(x, y) ((Py_ssize_t)(((size_t)(x)) + ((size_t)(y))))
-#define MUL_WRAPAROUND(x, y) ((Py_ssize_t)(((size_t)(x)) * ((size_t)(y))))
-
-
-/* whenever running Python code, the errno is saved in this thread-local
- variable */
-#ifndef MS_WIN32
-# include "misc_thread_posix.h"
-#endif
-
-#include "minibuffer.h"
-
-#if PY_MAJOR_VERSION >= 3
-# include "file_emulator.h"
-#endif
-
-#ifdef PyUnicode_KIND /* Python >= 3.3 */
-# include "wchar_helper_3.h"
-#else
-# include "wchar_helper.h"
-#endif
-
-#include "../cffi/_cffi_errors.h"
-
-typedef struct _cffi_allocator_s {
- PyObject *ca_alloc, *ca_free;
- int ca_dont_clear;
-} cffi_allocator_t;
-static const cffi_allocator_t default_allocator = { NULL, NULL, 0 };
-static PyObject *FFIError;
-static PyObject *unique_cache;
-
-/************************************************************/
-
-static CTypeDescrObject *
-ctypedescr_new(int name_size)
-{
- CTypeDescrObject *ct = PyObject_GC_NewVar(CTypeDescrObject,
- &CTypeDescr_Type,
- name_size);
- if (ct == NULL)
- return NULL;
-
- ct->ct_itemdescr = NULL;
- ct->ct_stuff = NULL;
- ct->ct_weakreflist = NULL;
- ct->ct_unique_key = NULL;
- PyObject_GC_Track(ct);
- return ct;
-}
-
-static CTypeDescrObject *
-ctypedescr_new_on_top(CTypeDescrObject *ct_base, const char *extra_text,
- int extra_position)
-{
- int base_name_len = strlen(ct_base->ct_name);
- int extra_name_len = strlen(extra_text);
- CTypeDescrObject *ct = ctypedescr_new(base_name_len + extra_name_len + 1);
- char *p;
- if (ct == NULL)
- return NULL;
-
- Py_INCREF(ct_base);
- ct->ct_itemdescr = ct_base;
- ct->ct_name_position = ct_base->ct_name_position + extra_position;
-
- p = ct->ct_name;
- memcpy(p, ct_base->ct_name, ct_base->ct_name_position);
- p += ct_base->ct_name_position;
- memcpy(p, extra_text, extra_name_len);
- p += extra_name_len;
- memcpy(p, ct_base->ct_name + ct_base->ct_name_position,
- base_name_len - ct_base->ct_name_position + 1);
-
- return ct;
-}
-
-static PyObject *
-ctypedescr_repr(CTypeDescrObject *ct)
-{
- return PyText_FromFormat("<ctype '%s'>", ct->ct_name);
-}
-
-static void
-ctypedescr_dealloc(CTypeDescrObject *ct)
-{
- PyObject_GC_UnTrack(ct);
- if (ct->ct_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) ct);
-
- if (ct->ct_unique_key != NULL) {
- /* revive dead object temporarily for DelItem */
- Py_SET_REFCNT(ct, 43);
- PyDict_DelItem(unique_cache, ct->ct_unique_key);
- assert(Py_REFCNT(ct) == 42);
- Py_SET_REFCNT(ct, 0);
- Py_DECREF(ct->ct_unique_key);
- }
- Py_XDECREF(ct->ct_itemdescr);
- Py_XDECREF(ct->ct_stuff);
- if (ct->ct_flags & CT_FUNCTIONPTR)
- PyObject_Free(ct->ct_extra);
- Py_TYPE(ct)->tp_free((PyObject *)ct);
-}
-
-static int
-ctypedescr_traverse(CTypeDescrObject *ct, visitproc visit, void *arg)
-{
- Py_VISIT(ct->ct_itemdescr);
- Py_VISIT(ct->ct_stuff);
- return 0;
-}
-
-static int
-ctypedescr_clear(CTypeDescrObject *ct)
-{
- Py_CLEAR(ct->ct_itemdescr);
- Py_CLEAR(ct->ct_stuff);
- return 0;
-}
-
-
-static PyObject *nosuchattr(const char *attr)
-{
- PyErr_SetString(PyExc_AttributeError, attr);
- return NULL;
-}
-
-static PyObject *ctypeget_kind(CTypeDescrObject *ct, void *context)
-{
- char *result;
- if (ct->ct_flags & CT_PRIMITIVE_ANY) {
- if (ct->ct_flags & CT_IS_ENUM)
- result = "enum";
- else
- result = "primitive";
- }
- else if (ct->ct_flags & CT_POINTER) {
- result = "pointer";
- }
- else if (ct->ct_flags & CT_ARRAY) {
- result = "array";
- }
- else if (ct->ct_flags & CT_VOID) {
- result = "void";
- }
- else if (ct->ct_flags & CT_STRUCT) {
- result = "struct";
- }
- else if (ct->ct_flags & CT_UNION) {
- result = "union";
- }
- else if (ct->ct_flags & CT_FUNCTIONPTR) {
- result = "function";
- }
- else
- result = "?";
-
- return PyText_FromString(result);
-}
-
-static PyObject *ctypeget_cname(CTypeDescrObject *ct, void *context)
-{
- return PyText_FromString(ct->ct_name);
-}
-
-static PyObject *ctypeget_item(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & (CT_POINTER | CT_ARRAY)) {
- Py_INCREF(ct->ct_itemdescr);
- return (PyObject *)ct->ct_itemdescr;
- }
- return nosuchattr("item");
-}
-
-static PyObject *ctypeget_length(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_ARRAY) {
- if (ct->ct_length >= 0) {
- return PyInt_FromSsize_t(ct->ct_length);
- }
- else {
- Py_INCREF(Py_None);
- return Py_None;
- }
- }
- return nosuchattr("length");
-}
-
-static PyObject *
-get_field_name(CTypeDescrObject *ct, CFieldObject *cf); /* forward */
-
-/* returns 0 if the struct ctype is opaque, 1 if it is not, or -1 if
- an exception occurs */
-#define force_lazy_struct(ct) \
- ((ct)->ct_stuff != NULL ? 1 : do_realize_lazy_struct(ct))
-
-static int do_realize_lazy_struct(CTypeDescrObject *ct);
-/* forward, implemented in realize_c_type.c */
-
-static PyObject *ctypeget_fields(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & (CT_STRUCT | CT_UNION)) {
- if (!(ct->ct_flags & CT_IS_OPAQUE)) {
- CFieldObject *cf;
- PyObject *res;
- if (force_lazy_struct(ct) < 0)
- return NULL;
- res = PyList_New(0);
- if (res == NULL)
- return NULL;
- for (cf = (CFieldObject *)ct->ct_extra;
- cf != NULL; cf = cf->cf_next) {
- PyObject *o = PyTuple_Pack(2, get_field_name(ct, cf),
- (PyObject *)cf);
- int err = (o != NULL) ? PyList_Append(res, o) : -1;
- Py_XDECREF(o);
- if (err < 0) {
- Py_DECREF(res);
- return NULL;
- }
- }
- return res;
- }
- else {
- Py_INCREF(Py_None);
- return Py_None;
- }
- }
- return nosuchattr("fields");
-}
-
-static PyObject *ctypeget_args(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_FUNCTIONPTR) {
- PyObject *t = ct->ct_stuff;
- return PyTuple_GetSlice(t, 2, PyTuple_GET_SIZE(t));
- }
- return nosuchattr("args");
-}
-
-static PyObject *ctypeget_result(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_FUNCTIONPTR) {
- PyObject *res = PyTuple_GetItem(ct->ct_stuff, 1);
- Py_XINCREF(res);
- return res;
- }
- return nosuchattr("result");
-}
-
-static PyObject *ctypeget_ellipsis(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_FUNCTIONPTR) {
- PyObject *res = ct->ct_extra ? Py_False : Py_True;
- Py_INCREF(res);
- return res;
- }
- return nosuchattr("ellipsis");
-}
-
-static PyObject *ctypeget_abi(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_FUNCTIONPTR) {
- PyObject *res = PyTuple_GetItem(ct->ct_stuff, 0);
- Py_XINCREF(res);
- return res;
- }
- return nosuchattr("abi");
-}
-
-static PyObject *ctypeget_elements(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_IS_ENUM) {
- PyObject *res = PyTuple_GetItem(ct->ct_stuff, 1);
- if (res) res = PyDict_Copy(res);
- return res;
- }
- return nosuchattr("elements");
-}
-
-static PyObject *ctypeget_relements(CTypeDescrObject *ct, void *context)
-{
- if (ct->ct_flags & CT_IS_ENUM) {
- PyObject *res = PyTuple_GetItem(ct->ct_stuff, 0);
- if (res) res = PyDict_Copy(res);
- return res;
- }
- return nosuchattr("relements");
-}
-
-static PyGetSetDef ctypedescr_getsets[] = {
- {"kind", (getter)ctypeget_kind, NULL, "kind"},
- {"cname", (getter)ctypeget_cname, NULL, "C name"},
- {"item", (getter)ctypeget_item, NULL, "pointer to, or array of"},
- {"length", (getter)ctypeget_length, NULL, "array length or None"},
- {"fields", (getter)ctypeget_fields, NULL, "struct or union fields"},
- {"args", (getter)ctypeget_args, NULL, "function argument types"},
- {"result", (getter)ctypeget_result, NULL, "function result type"},
- {"ellipsis", (getter)ctypeget_ellipsis, NULL, "function has '...'"},
- {"abi", (getter)ctypeget_abi, NULL, "function ABI"},
- {"elements", (getter)ctypeget_elements, NULL, "enum elements"},
- {"relements", (getter)ctypeget_relements, NULL, "enum elements, reverse"},
- {NULL} /* sentinel */
-};
-
-static PyObject *
-ctypedescr_dir(PyObject *ct, PyObject *noarg)
-{
- int err;
- struct PyGetSetDef *gsdef;
- PyObject *res = PyList_New(0);
- if (res == NULL)
- return NULL;
-
- for (gsdef = ctypedescr_getsets; gsdef->name; gsdef++) {
- PyObject *x = PyObject_GetAttrString(ct, gsdef->name);
- if (x == NULL) {
- PyErr_Clear();
- }
- else {
- Py_DECREF(x);
- x = PyText_FromString(gsdef->name);
- err = (x != NULL) ? PyList_Append(res, x) : -1;
- Py_XDECREF(x);
- if (err < 0) {
- Py_DECREF(res);
- return NULL;
- }
- }
- }
- return res;
-}
-
-static PyMethodDef ctypedescr_methods[] = {
- {"__dir__", ctypedescr_dir, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject CTypeDescr_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.CType",
- offsetof(CTypeDescrObject, ct_name),
- sizeof(char),
- (destructor)ctypedescr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)ctypedescr_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)ctypedescr_traverse, /* tp_traverse */
- (inquiry)ctypedescr_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(CTypeDescrObject, ct_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- ctypedescr_methods, /* tp_methods */
- 0, /* tp_members */
- ctypedescr_getsets, /* tp_getset */
-};
-
-/************************************************************/
-
-static PyObject *
-get_field_name(CTypeDescrObject *ct, CFieldObject *cf)
-{
- Py_ssize_t i = 0;
- PyObject *d_key, *d_value;
- while (PyDict_Next(ct->ct_stuff, &i, &d_key, &d_value)) {
- if (d_value == (PyObject *)cf)
- return d_key;
- }
- Py_FatalError("_cffi_backend: get_field_name()");
- return NULL;
-}
-
-static void
-cfield_dealloc(CFieldObject *cf)
-{
- Py_DECREF(cf->cf_type);
- PyObject_Del(cf);
-}
-
-#undef OFF
-#define OFF(x) offsetof(CFieldObject, x)
-
-static PyMemberDef cfield_members[] = {
- {"type", T_OBJECT, OFF(cf_type), READONLY},
- {"offset", T_PYSSIZET, OFF(cf_offset), READONLY},
- {"bitshift", T_SHORT, OFF(cf_bitshift), READONLY},
- {"bitsize", T_SHORT, OFF(cf_bitsize), READONLY},
- {"flags", T_UBYTE, OFF(cf_flags), READONLY},
- {NULL} /* Sentinel */
-};
-#undef OFF
-
-static PyTypeObject CField_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.CField",
- sizeof(CFieldObject),
- 0,
- (destructor)cfield_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- cfield_members, /* tp_members */
-};
-
-/************************************************************/
-
-static int
-CDataObject_Or_PyFloat_Check(PyObject *ob)
-{
- return (PyFloat_Check(ob) ||
- (CData_Check(ob) &&
- (((CDataObject *)ob)->c_type->ct_flags & CT_PRIMITIVE_FLOAT)));
-}
-
-static PY_LONG_LONG
-_my_PyLong_AsLongLong(PyObject *ob)
-{
- /* (possibly) convert and cast a Python object to a long long.
- Like PyLong_AsLongLong(), this version accepts a Python int too, and
- does convertions from other types of objects. The difference is that
- this version refuses floats. */
-#if PY_MAJOR_VERSION < 3
- if (PyInt_Check(ob)) {
- return PyInt_AS_LONG(ob);
- }
- else
-#endif
- if (PyLong_Check(ob)) {
- return PyLong_AsLongLong(ob);
- }
- else {
- PyObject *io;
- PY_LONG_LONG res;
- PyNumberMethods *nb = ob->ob_type->tp_as_number;
-
- if (CDataObject_Or_PyFloat_Check(ob) ||
- nb == NULL || nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return -1;
- }
- io = (*nb->nb_int) (ob);
- if (io == NULL)
- return -1;
-
- if (PyIntOrLong_Check(io)) {
- res = _my_PyLong_AsLongLong(io);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "integer conversion failed");
- res = -1;
- }
- Py_DECREF(io);
- return res;
- }
-}
-
-static unsigned PY_LONG_LONG
-_my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict)
-{
- /* (possibly) convert and cast a Python object to an unsigned long long.
- Like PyLong_AsLongLong(), this version accepts a Python int too, and
- does convertions from other types of objects. If 'strict', complains
- with OverflowError and refuses floats. If '!strict', rounds floats
- and masks the result. */
-#if PY_MAJOR_VERSION < 3
- if (PyInt_Check(ob)) {
- long value1 = PyInt_AS_LONG(ob);
- if (strict && value1 < 0)
- goto negative;
- return (unsigned PY_LONG_LONG)(PY_LONG_LONG)value1;
- }
- else
-#endif
- if (PyLong_Check(ob)) {
- if (strict) {
- if (_PyLong_Sign(ob) < 0)
- goto negative;
- return PyLong_AsUnsignedLongLong(ob);
- }
- else {
- return PyLong_AsUnsignedLongLongMask(ob);
- }
- }
- else {
- PyObject *io;
- unsigned PY_LONG_LONG res;
- PyNumberMethods *nb = ob->ob_type->tp_as_number;
-
- if ((strict && CDataObject_Or_PyFloat_Check(ob)) ||
- nb == NULL || nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return (unsigned PY_LONG_LONG)-1;
- }
- io = (*nb->nb_int) (ob);
- if (io == NULL)
- return (unsigned PY_LONG_LONG)-1;
-
- if (PyIntOrLong_Check(io)) {
- res = _my_PyLong_AsUnsignedLongLong(io, strict);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "integer conversion failed");
- res = (unsigned PY_LONG_LONG)-1;
- }
- Py_DECREF(io);
- return res;
- }
-
- negative:
- PyErr_SetString(PyExc_OverflowError,
- "can't convert negative number to unsigned");
- return (unsigned PY_LONG_LONG)-1;
-}
-
-#define _read_raw_data(type) \
- do { \
- if (size == sizeof(type)) { \
- type r; \
- memcpy(&r, target, sizeof(type)); \
- return r; \
- } \
- } while(0)
-
-static PY_LONG_LONG
-read_raw_signed_data(char *target, int size)
-{
- _read_raw_data(signed char);
- _read_raw_data(short);
- _read_raw_data(int);
- _read_raw_data(long);
- _read_raw_data(PY_LONG_LONG);
- Py_FatalError("read_raw_signed_data: bad integer size");
- return 0;
-}
-
-static unsigned PY_LONG_LONG
-read_raw_unsigned_data(char *target, int size)
-{
- _read_raw_data(unsigned char);
- _read_raw_data(unsigned short);
- _read_raw_data(unsigned int);
- _read_raw_data(unsigned long);
- _read_raw_data(unsigned PY_LONG_LONG);
- Py_FatalError("read_raw_unsigned_data: bad integer size");
- return 0;
-}
-
-#ifdef __GNUC__
-/* This is a workaround for what I think is a GCC bug on several
- platforms. See issue #378. */
-__attribute__((noinline))
-#endif
-void _cffi_memcpy(char *target, const void *src, size_t size)
-{
- memcpy(target, src, size);
-}
-
-#define _write_raw_data(type) \
- do { \
- if (size == sizeof(type)) { \
- type r = (type)source; \
- _cffi_memcpy(target, &r, sizeof(type)); \
- return; \
- } \
- } while(0)
-
-static void
-write_raw_integer_data(char *target, unsigned PY_LONG_LONG source, int size)
-{
- _write_raw_data(unsigned char);
- _write_raw_data(unsigned short);
- _write_raw_data(unsigned int);
- _write_raw_data(unsigned long);
- _write_raw_data(unsigned PY_LONG_LONG);
- Py_FatalError("write_raw_integer_data: bad integer size");
-}
-
-static double
-read_raw_float_data(char *target, int size)
-{
- _read_raw_data(float);
- _read_raw_data(double);
- Py_FatalError("read_raw_float_data: bad float size");
- return 0;
-}
-
-static long double
-read_raw_longdouble_data(char *target)
-{
- int size = sizeof(long double);
- _read_raw_data(long double);
- Py_FatalError("read_raw_longdouble_data: bad long double size");
- return 0;
-}
-
-static Py_complex
-read_raw_complex_data(char *target, int size)
-{
- Py_complex r = {0.0, 0.0};
- if (size == 2*sizeof(float)) {
- float real_part, imag_part;
- memcpy(&real_part, target + 0, sizeof(float));
- memcpy(&imag_part, target + sizeof(float), sizeof(float));
- r.real = real_part;
- r.imag = imag_part;
- return r;
- }
- if (size == 2*sizeof(double)) {
- memcpy(&r, target, 2*sizeof(double));
- return r;
- }
- Py_FatalError("read_raw_complex_data: bad complex size");
- return r;
-}
-
-static void
-write_raw_float_data(char *target, double source, int size)
-{
- _write_raw_data(float);
- _write_raw_data(double);
- Py_FatalError("write_raw_float_data: bad float size");
-}
-
-static void
-write_raw_longdouble_data(char *target, long double source)
-{
- int size = sizeof(long double);
- _write_raw_data(long double);
-}
-
-#define _write_raw_complex_data(type) \
- do { \
- if (size == 2*sizeof(type)) { \
- type r = (type)source.real; \
- type i = (type)source.imag; \
- _cffi_memcpy(target, &r, sizeof(type)); \
- _cffi_memcpy(target+sizeof(type), &i, sizeof(type)); \
- return; \
- } \
- } while(0)
-
-static void
-write_raw_complex_data(char *target, Py_complex source, int size)
-{
- _write_raw_complex_data(float);
- _write_raw_complex_data(double);
- Py_FatalError("write_raw_complex_data: bad complex size");
-}
-
-static PyObject *
-new_simple_cdata(char *data, CTypeDescrObject *ct)
-{
- CDataObject *cd = PyObject_New(CDataObject, &CData_Type);
- if (cd == NULL)
- return NULL;
- Py_INCREF(ct);
- cd->c_data = data;
- cd->c_type = ct;
- cd->c_weakreflist = NULL;
- return (PyObject *)cd;
-}
-
-static PyObject *
-new_sized_cdata(char *data, CTypeDescrObject *ct, Py_ssize_t length)
-{
- CDataObject_own_length *scd;
-
- scd = (CDataObject_own_length *)PyObject_Malloc(
- offsetof(CDataObject_own_length, alignment));
- if (PyObject_Init((PyObject *)scd, &CData_Type) == NULL)
- return NULL;
- Py_INCREF(ct);
- scd->head.c_type = ct;
- scd->head.c_data = data;
- scd->head.c_weakreflist = NULL;
- scd->length = length;
- return (PyObject *)scd;
-}
-
-static CDataObject *_new_casted_primitive(CTypeDescrObject *ct); /*forward*/
-
-static PyObject *
-convert_to_object(char *data, CTypeDescrObject *ct)
-{
- if (!(ct->ct_flags & CT_PRIMITIVE_ANY)) {
- /* non-primitive types (check done just for performance) */
- if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
- char *ptrdata = *(char **)data;
- /*READ(data, sizeof(char *))*/
- return new_simple_cdata(ptrdata, ct);
- }
- else if (ct->ct_flags & CT_IS_OPAQUE) {
- PyErr_Format(PyExc_TypeError, "cdata '%s' is opaque",
- ct->ct_name);
- return NULL;
- }
- else if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
- return new_simple_cdata(data, ct);
- }
- else if (ct->ct_flags & CT_ARRAY) {
- if (ct->ct_length < 0) {
- /* we can't return a <cdata 'int[]'> here, because we don't
- know the length to give it. As a compromize, returns
- <cdata 'int *'> in this case. */
- ct = (CTypeDescrObject *)ct->ct_stuff;
- }
- return new_simple_cdata(data, ct);
- }
- }
- else if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
- PY_LONG_LONG value;
- /*READ(data, ct->ct_size)*/
- value = read_raw_signed_data(data, ct->ct_size);
- if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
- return PyInt_FromLong((long)value);
- else
- return PyLong_FromLongLong(value);
- }
- else if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
- unsigned PY_LONG_LONG value;
- /*READ(data, ct->ct_size)*/
- value = read_raw_unsigned_data(data, ct->ct_size);
-
- if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) {
- if (ct->ct_flags & CT_IS_BOOL) {
- PyObject *x;
- switch ((int)value) {
- case 0: x = Py_False; break;
- case 1: x = Py_True; break;
- default:
- PyErr_Format(PyExc_ValueError,
- "got a _Bool of value %d, expected 0 or 1",
- (int)value);
- return NULL;
- }
- Py_INCREF(x);
- return x;
- }
- return PyInt_FromLong((long)value);
- }
- else
- return PyLong_FromUnsignedLongLong(value);
- }
- else if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
- /*READ(data, ct->ct_size)*/
- if (!(ct->ct_flags & CT_IS_LONGDOUBLE)) {
- double value = read_raw_float_data(data, ct->ct_size);
- return PyFloat_FromDouble(value);
- }
- else {
- long double value = read_raw_longdouble_data(data);
- CDataObject *cd = _new_casted_primitive(ct);
- if (cd != NULL)
- write_raw_longdouble_data(cd->c_data, value);
- return (PyObject *)cd;
- }
- }
- else if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
- /*READ(data, ct->ct_size)*/
- switch (ct->ct_size) {
- case sizeof(char):
- return PyBytes_FromStringAndSize(data, 1);
- case 2:
- return _my_PyUnicode_FromChar16((cffi_char16_t *)data, 1);
- case 4:
- return _my_PyUnicode_FromChar32((cffi_char32_t *)data, 1);
- }
- }
- else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
- Py_complex value = read_raw_complex_data(data, ct->ct_size);
- return PyComplex_FromCComplex(value);
- }
-
- PyErr_Format(PyExc_SystemError,
- "convert_to_object: '%s'", ct->ct_name);
- return NULL;
-}
-
-static PyObject *
-convert_to_object_bitfield(char *data, CFieldObject *cf)
-{
- CTypeDescrObject *ct = cf->cf_type;
- /*READ(data, ct->ct_size)*/
-
- if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
- unsigned PY_LONG_LONG value, valuemask, shiftforsign;
- PY_LONG_LONG result;
-
- value = (unsigned PY_LONG_LONG)read_raw_signed_data(data, ct->ct_size);
- valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
- shiftforsign = 1ULL << (cf->cf_bitsize - 1);
- value = ((value >> cf->cf_bitshift) + shiftforsign) & valuemask;
- result = ((PY_LONG_LONG)value) - (PY_LONG_LONG)shiftforsign;
-
- if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
- return PyInt_FromLong((long)result);
- else
- return PyLong_FromLongLong(result);
- }
- else {
- unsigned PY_LONG_LONG value, valuemask;
-
- value = read_raw_unsigned_data(data, ct->ct_size);
- valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
- value = (value >> cf->cf_bitshift) & valuemask;
-
- if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
- return PyInt_FromLong((long)value);
- else
- return PyLong_FromUnsignedLongLong(value);
- }
-}
-
-static int _convert_overflow(PyObject *init, const char *ct_name)
-{
- PyObject *s;
- if (PyErr_Occurred()) /* already an exception pending */
- return -1;
- s = PyObject_Str(init);
- if (s == NULL)
- return -1;
- PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
- PyText_AS_UTF8(s), ct_name);
- Py_DECREF(s);
- return -1;
-}
-
-static int _convert_to_char(PyObject *init)
-{
- if (PyBytes_Check(init) && PyBytes_GET_SIZE(init) == 1) {
- return (unsigned char)(PyBytes_AS_STRING(init)[0]);
- }
- if (CData_Check(init) &&
- (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
- (((CDataObject *)init)->c_type->ct_size == sizeof(char))) {
- char *data = ((CDataObject *)init)->c_data;
- /*READ(data, 1)*/
- return *(unsigned char *)data;
- }
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype 'char' must be a "STR_OR_BYTES
- " of length 1, not %.200s", Py_TYPE(init)->tp_name);
- return -1;
-}
-
-static cffi_char16_t _convert_to_char16_t(PyObject *init)
-{
- char err_got[80];
- err_got[0] = 0;
-
- if (PyUnicode_Check(init)) {
- cffi_char16_t ordinal;
- if (_my_PyUnicode_AsSingleChar16(init, &ordinal, err_got) == 0)
- return ordinal;
- }
- if (CData_Check(init) &&
- (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
- (((CDataObject *)init)->c_type->ct_size == 2)) {
- char *data = ((CDataObject *)init)->c_data;
- /*READ(data, 2)*/
- return *(cffi_char16_t *)data;
- }
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype 'char16_t' must be a unicode string "
- "of length 1, not %.200s",
- err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got);
- return (cffi_char16_t)-1;
-}
-
-static cffi_char32_t _convert_to_char32_t(PyObject *init)
-{
- char err_got[80];
- err_got[0] = 0;
-
- if (PyUnicode_Check(init)) {
- cffi_char32_t ordinal;
- if (_my_PyUnicode_AsSingleChar32(init, &ordinal, err_got) == 0)
- return ordinal;
- }
- if (CData_Check(init) &&
- (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
- (((CDataObject *)init)->c_type->ct_size == 4)) {
- char *data = ((CDataObject *)init)->c_data;
- /*READ(data, 4)*/
- return *(cffi_char32_t *)data;
- }
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype 'char32_t' must be a unicode string "
- "of length 1, not %.200s",
- err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got);
- return (cffi_char32_t)-1;
-}
-
-static int _convert_error(PyObject *init, CTypeDescrObject *ct,
- const char *expected)
-{
- if (CData_Check(init)) {
- CTypeDescrObject *ct2 = ((CDataObject *)init)->c_type;
- if (strcmp(ct->ct_name, ct2->ct_name) != 0)
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype '%s' must be a %s, "
- "not cdata '%s'",
- ct->ct_name, expected, ct2->ct_name);
- else if (ct != ct2) {
- /* in case we'd give the error message "initializer for
- ctype 'A' must be a pointer to same type, not cdata
- 'B'", but with A=B, then give instead a different error
- message to try to clear up the confusion */
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype '%s' appears indeed to be '%s',"
- " but the types are different (check that you are not"
- " e.g. mixing up different ffi instances)",
- ct->ct_name, ct2->ct_name);
- }
- else
- {
- PyErr_Format(PyExc_SystemError,
- "initializer for ctype '%s' is correct, but we get "
- "an internal mismatch--please report a bug",
- ct->ct_name);
- }
- }
- else
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype '%s' must be a %s, "
- "not %.200s",
- ct->ct_name, expected, Py_TYPE(init)->tp_name);
- return -1;
-}
-
-static int /* forward */
-convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init);
-static int /* forward */
-convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init);
-
-static Py_ssize_t
-get_new_array_length(CTypeDescrObject *ctitem, PyObject **pvalue)
-{
- PyObject *value = *pvalue;
-
- if (PyList_Check(value) || PyTuple_Check(value)) {
- return PySequence_Fast_GET_SIZE(value);
- }
- else if (PyBytes_Check(value)) {
- /* from a string, we add the null terminator */
- return PyBytes_GET_SIZE(value) + 1;
- }
- else if (PyUnicode_Check(value)) {
- /* from a unicode, we add the null terminator */
- int length;
- if (ctitem->ct_size == 2)
- length = _my_PyUnicode_SizeAsChar16(value);
- else
- length = _my_PyUnicode_SizeAsChar32(value);
- return length + 1;
- }
- else {
- Py_ssize_t explicitlength;
- explicitlength = PyNumber_AsSsize_t(value, PyExc_OverflowError);
- if (explicitlength < 0) {
- if (PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError,
- "expected new array length or list/tuple/str, "
- "not %.200s", Py_TYPE(value)->tp_name);
- }
- else
- PyErr_SetString(PyExc_ValueError, "negative array length");
- return -1;
- }
- *pvalue = Py_None;
- return explicitlength;
- }
-}
-
-static int
-convert_field_from_object(char *data, CFieldObject *cf, PyObject *value)
-{
- data += cf->cf_offset;
- if (cf->cf_bitshift >= 0)
- return convert_from_object_bitfield(data, cf, value);
- else
- return convert_from_object(data, cf->cf_type, value);
-}
-
-static int
-add_varsize_length(Py_ssize_t offset, Py_ssize_t itemsize,
- Py_ssize_t varsizelength, Py_ssize_t *optvarsize)
-{
- /* update '*optvarsize' to account for an array of 'varsizelength'
- elements, each of size 'itemsize', that starts at 'offset'. */
- Py_ssize_t size = ADD_WRAPAROUND(offset,
- MUL_WRAPAROUND(itemsize, varsizelength));
- if (size < 0 ||
- ((size - offset) / itemsize) != varsizelength) {
- PyErr_SetString(PyExc_OverflowError,
- "array size would overflow a Py_ssize_t");
- return -1;
- }
- if (size > *optvarsize)
- *optvarsize = size;
- return 0;
-}
-
-static int
-convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init,
- Py_ssize_t *optvarsize); /* forward */
-
-static int
-convert_vfield_from_object(char *data, CFieldObject *cf, PyObject *value,
- Py_ssize_t *optvarsize)
-{
- /* a special case for var-sized C99 arrays */
- if ((cf->cf_type->ct_flags & CT_ARRAY) && cf->cf_type->ct_size < 0) {
- Py_ssize_t varsizelength = get_new_array_length(
- cf->cf_type->ct_itemdescr, &value);
- if (varsizelength < 0)
- return -1;
- if (optvarsize != NULL) {
- /* in this mode, the only purpose of this function is to compute
- the real size of the structure from a var-sized C99 array */
- assert(data == NULL);
- return add_varsize_length(cf->cf_offset,
- cf->cf_type->ct_itemdescr->ct_size,
- varsizelength,
- optvarsize);
- }
- /* if 'value' was only an integer, get_new_array_length() returns
- it and convert 'value' to be None. Detect if this was the case,
- and if so, stop here, leaving the content uninitialized
- (it should be zero-initialized from somewhere else). */
- if (value == Py_None)
- return 0;
- }
- if (optvarsize == NULL) {
- return convert_field_from_object(data, cf, value);
- }
- else if ((cf->cf_type->ct_flags & CT_WITH_VAR_ARRAY) != 0 &&
- !CData_Check(value)) {
- Py_ssize_t subsize = cf->cf_type->ct_size;
- if (convert_struct_from_object(NULL, cf->cf_type, value, &subsize) < 0)
- return -1;
- return add_varsize_length(cf->cf_offset, 1, subsize, optvarsize);
- }
- else
- return 0;
-}
-
-static int
-must_be_array_of_zero_or_one(const char *data, Py_ssize_t n)
-{
- Py_ssize_t i;
- for (i = 0; i < n; i++) {
- if (((unsigned char)data[i]) > 1) {
- PyErr_SetString(PyExc_ValueError,
- "an array of _Bool can only contain \\x00 or \\x01");
- return -1;
- }
- }
- return 0;
-}
-
-static Py_ssize_t
-get_array_length(CDataObject *cd)
-{
- if (cd->c_type->ct_length < 0)
- return ((CDataObject_own_length *)cd)->length;
- else
- return cd->c_type->ct_length;
-}
-
-static int
-convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
-{
- /* used by convert_from_object(), and also to decode lists/tuples/unicodes
- passed as function arguments. 'ct' is an CT_ARRAY in the first case
- and a CT_POINTER in the second case. */
- const char *expected;
- CTypeDescrObject *ctitem = ct->ct_itemdescr;
-
- if (PyList_Check(init) || PyTuple_Check(init)) {
- PyObject **items;
- Py_ssize_t i, n;
- n = PySequence_Fast_GET_SIZE(init);
- if (ct->ct_length >= 0 && n > ct->ct_length) {
- PyErr_Format(PyExc_IndexError,
- "too many initializers for '%s' (got %zd)",
- ct->ct_name, n);
- return -1;
- }
- items = PySequence_Fast_ITEMS(init);
- for (i=0; i<n; i++) {
- if (convert_from_object(data, ctitem, items[i]) < 0)
- return -1;
- data += ctitem->ct_size;
- }
- return 0;
- }
- else if ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) ||
- ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))
- && (ctitem->ct_size == sizeof(char)))) {
- if (ctitem->ct_size == sizeof(char)) {
- char *srcdata;
- Py_ssize_t n;
- if (!PyBytes_Check(init)) {
- expected = STR_OR_BYTES" or list or tuple";
- goto cannot_convert;
- }
- n = PyBytes_GET_SIZE(init);
- if (ct->ct_length >= 0 && n > ct->ct_length) {
- PyErr_Format(PyExc_IndexError,
- "initializer "STR_OR_BYTES" is too long for '%s' "
- "(got %zd characters)", ct->ct_name, n);
- return -1;
- }
- if (n != ct->ct_length)
- n++;
- srcdata = PyBytes_AS_STRING(init);
- if (ctitem->ct_flags & CT_IS_BOOL)
- if (must_be_array_of_zero_or_one(srcdata, n) < 0)
- return -1;
- memcpy(data, srcdata, n);
- return 0;
- }
- else {
- Py_ssize_t n;
- if (!PyUnicode_Check(init)) {
- expected = "unicode or list or tuple";
- goto cannot_convert;
- }
-
- if (ctitem->ct_size == 4)
- n = _my_PyUnicode_SizeAsChar32(init);
- else
- n = _my_PyUnicode_SizeAsChar16(init);
-
- if (ct->ct_length >= 0 && n > ct->ct_length) {
- PyErr_Format(PyExc_IndexError,
- "initializer unicode is too long for '%s' "
- "(got %zd characters)", ct->ct_name, n);
- return -1;
- }
- if (n != ct->ct_length)
- n++;
- if (ctitem->ct_size == 4)
- return _my_PyUnicode_AsChar32(init, (cffi_char32_t *)data, n);
- else
- return _my_PyUnicode_AsChar16(init, (cffi_char16_t *)data, n);
- }
- }
- else {
- expected = "list or tuple";
- goto cannot_convert;
- }
-
- cannot_convert:
- if ((ct->ct_flags & CT_ARRAY) && CData_Check(init))
- {
- CDataObject *cd = (CDataObject *)init;
- if (cd->c_type == ct)
- {
- Py_ssize_t n = get_array_length(cd);
- memcpy(data, cd->c_data, n * ctitem->ct_size);
- return 0;
- }
- }
- return _convert_error(init, ct, expected);
-}
-
-static int
-convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init,
- Py_ssize_t *optvarsize)
-{
- /* does not accept 'init' being already a CData */
- const char *expected;
-
- if (force_lazy_struct(ct) <= 0) {
- if (!PyErr_Occurred())
- PyErr_Format(PyExc_TypeError, "'%s' is opaque", ct->ct_name);
- return -1;
- }
-
- if (PyList_Check(init) || PyTuple_Check(init)) {
- PyObject **items = PySequence_Fast_ITEMS(init);
- Py_ssize_t i, n = PySequence_Fast_GET_SIZE(init);
- CFieldObject *cf = (CFieldObject *)ct->ct_extra;
-
- for (i=0; i<n; i++) {
- while (cf != NULL && (cf->cf_flags & BF_IGNORE_IN_CTOR))
- cf = cf->cf_next;
- if (cf == NULL) {
- PyErr_Format(PyExc_ValueError,
- "too many initializers for '%s' (got %zd)",
- ct->ct_name, n);
- return -1;
- }
- if (convert_vfield_from_object(data, cf, items[i], optvarsize) < 0)
- return -1;
- cf = cf->cf_next;
- }
- return 0;
- }
- if (PyDict_Check(init)) {
- PyObject *d_key, *d_value;
- Py_ssize_t i = 0;
- CFieldObject *cf;
-
- while (PyDict_Next(init, &i, &d_key, &d_value)) {
- cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, d_key);
- if (cf == NULL) {
- PyErr_SetObject(PyExc_KeyError, d_key);
- return -1;
- }
- if (convert_vfield_from_object(data, cf, d_value, optvarsize) < 0)
- return -1;
- }
- return 0;
- }
- expected = optvarsize == NULL ? "list or tuple or dict or struct-cdata"
- : "list or tuple or dict";
- return _convert_error(init, ct, expected);
-}
-
-#ifdef __GNUC__
-# if __GNUC__ >= 4
-/* Don't go inlining this huge function. Needed because occasionally
- it gets inlined in places where is causes a warning: call to
- __builtin___memcpy_chk will always overflow destination buffer
- (which is places where the 'ct' should never represent such a large
- primitive type anyway). */
-__attribute__((noinline))
-# endif
-#endif
-static int
-convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
-{
- const char *expected;
- char buf[sizeof(PY_LONG_LONG)];
-
- /*if (ct->ct_size > 0)*/
- /*WRITE(data, ct->ct_size)*/
-
- if (ct->ct_flags & CT_ARRAY) {
- return convert_array_from_object(data, ct, init);
- }
- if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
- char *ptrdata;
- CTypeDescrObject *ctinit;
-
- if (!CData_Check(init)) {
- expected = "cdata pointer";
- goto cannot_convert;
- }
- ctinit = ((CDataObject *)init)->c_type;
- if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR))) {
- if (ctinit->ct_flags & CT_ARRAY)
- ctinit = (CTypeDescrObject *)ctinit->ct_stuff;
- else {
- expected = "pointer or array";
- goto cannot_convert;
- }
- }
- if (ctinit != ct) {
- int combined_flags = ct->ct_flags | ctinit->ct_flags;
- if (combined_flags & CT_IS_VOID_PTR)
- ; /* accept "void *" as either source or target */
- else if (combined_flags & CT_IS_VOIDCHAR_PTR) {
- /* for backward compatibility, accept "char *" as either
- source of target. This is not what C does, though,
- so emit a warning that will eventually turn into an
- error. The warning is turned off if both types are
- pointers to single bytes. */
- char *msg = (ct->ct_flags & CT_IS_VOIDCHAR_PTR ?
- "implicit cast to 'char *' from a different pointer type: "
- "will be forbidden in the future (check that the types "
- "are as you expect; use an explicit ffi.cast() if they "
- "are correct)" :
- "implicit cast from 'char *' to a different pointer type: "
- "will be forbidden in the future (check that the types "
- "are as you expect; use an explicit ffi.cast() if they "
- "are correct)");
- if ((ct->ct_flags & ctinit->ct_flags & CT_POINTER) &&
- ct->ct_itemdescr->ct_size == 1 &&
- ctinit->ct_itemdescr->ct_size == 1) {
- /* no warning */
- }
- else if (PyErr_WarnEx(PyExc_UserWarning, msg, 1))
- return -1;
- }
- else {
- expected = "pointer to same type";
- goto cannot_convert;
- }
- }
- ptrdata = ((CDataObject *)init)->c_data;
-
- *(char **)data = ptrdata;
- return 0;
- }
- if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
- PY_LONG_LONG value = _my_PyLong_AsLongLong(init);
- if (value == -1 && PyErr_Occurred())
- return -1;
- write_raw_integer_data(buf, value, ct->ct_size);
- if (value != read_raw_signed_data(buf, ct->ct_size))
- goto overflow;
- write_raw_integer_data(data, value, ct->ct_size);
- return 0;
- }
- if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
- unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(init, 1);
- if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
- return -1;
- if (ct->ct_flags & CT_IS_BOOL) {
- if (value > 1ULL) /* value != 0 && value != 1 */
- goto overflow;
- }
- else {
- write_raw_integer_data(buf, value, ct->ct_size);
- if (value != read_raw_unsigned_data(buf, ct->ct_size))
- goto overflow;
- }
- write_raw_integer_data(data, value, ct->ct_size);
- return 0;
- }
- if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
- double value;
- if ((ct->ct_flags & CT_IS_LONGDOUBLE) &&
- CData_Check(init) &&
- (((CDataObject *)init)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
- long double lvalue;
- char *initdata = ((CDataObject *)init)->c_data;
- /*READ(initdata, sizeof(long double))*/
- lvalue = read_raw_longdouble_data(initdata);
- write_raw_longdouble_data(data, lvalue);
- return 0;
- }
- value = PyFloat_AsDouble(init);
- if (value == -1.0 && PyErr_Occurred())
- return -1;
- if (!(ct->ct_flags & CT_IS_LONGDOUBLE))
- write_raw_float_data(data, value, ct->ct_size);
- else
- write_raw_longdouble_data(data, (long double)value);
- return 0;
- }
- if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
- switch (ct->ct_size) {
- case sizeof(char): {
- int res = _convert_to_char(init);
- if (res < 0)
- return -1;
- data[0] = res;
- return 0;
- }
- case 2: {
- cffi_char16_t res = _convert_to_char16_t(init);
- if (res == (cffi_char16_t)-1 && PyErr_Occurred())
- return -1;
- *(cffi_char16_t *)data = res;
- return 0;
- }
- case 4: {
- cffi_char32_t res = _convert_to_char32_t(init);
- if (res == (cffi_char32_t)-1 && PyErr_Occurred())
- return -1;
- *(cffi_char32_t *)data = res;
- return 0;
- }
- }
- }
- if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
-
- if (CData_Check(init)) {
- if (((CDataObject *)init)->c_type == ct && ct->ct_size >= 0) {
- memcpy(data, ((CDataObject *)init)->c_data, ct->ct_size);
- return 0;
- }
- }
- return convert_struct_from_object(data, ct, init, NULL);
- }
- if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
- Py_complex value = PyComplex_AsCComplex(init);
- if (PyErr_Occurred())
- return -1;
- write_raw_complex_data(data, value, ct->ct_size);
- return 0;
- }
- PyErr_Format(PyExc_SystemError,
- "convert_from_object: '%s'", ct->ct_name);
- return -1;
-
- overflow:
- return _convert_overflow(init, ct->ct_name);
-
- cannot_convert:
- return _convert_error(init, ct, expected);
-}
-
-static int
-convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init)
-{
- CTypeDescrObject *ct = cf->cf_type;
- PY_LONG_LONG fmin, fmax, value = PyLong_AsLongLong(init);
- unsigned PY_LONG_LONG rawfielddata, rawvalue, rawmask;
- if (value == -1 && PyErr_Occurred())
- return -1;
-
- if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
- fmin = -(1LL << (cf->cf_bitsize-1));
- fmax = (1LL << (cf->cf_bitsize-1)) - 1LL;
- if (fmax == 0)
- fmax = 1; /* special case to let "int x:1" receive "1" */
- }
- else {
- fmin = 0LL;
- fmax = (PY_LONG_LONG)((1ULL << cf->cf_bitsize) - 1ULL);
- }
- if (value < fmin || value > fmax) {
- /* phew, PyErr_Format does not support "%lld" in Python 2.6 */
- PyObject *svalue = NULL, *sfmin = NULL, *sfmax = NULL;
- PyObject *lfmin = NULL, *lfmax = NULL;
- svalue = PyObject_Str(init);
- if (svalue == NULL) goto skip;
- lfmin = PyLong_FromLongLong(fmin);
- if (lfmin == NULL) goto skip;
- sfmin = PyObject_Str(lfmin);
- if (sfmin == NULL) goto skip;
- lfmax = PyLong_FromLongLong(fmax);
- if (lfmax == NULL) goto skip;
- sfmax = PyObject_Str(lfmax);
- if (sfmax == NULL) goto skip;
- PyErr_Format(PyExc_OverflowError,
- "value %s outside the range allowed by the "
- "bit field width: %s <= x <= %s",
- PyText_AS_UTF8(svalue),
- PyText_AS_UTF8(sfmin),
- PyText_AS_UTF8(sfmax));
- skip:
- Py_XDECREF(svalue);
- Py_XDECREF(sfmin);
- Py_XDECREF(sfmax);
- Py_XDECREF(lfmin);
- Py_XDECREF(lfmax);
- return -1;
- }
-
- rawmask = ((1ULL << cf->cf_bitsize) - 1ULL) << cf->cf_bitshift;
- rawvalue = ((unsigned PY_LONG_LONG)value) << cf->cf_bitshift;
- /*WRITE(data, ct->ct_size)*/
- rawfielddata = read_raw_unsigned_data(data, ct->ct_size);
- rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask);
- write_raw_integer_data(data, rawfielddata, ct->ct_size);
- return 0;
-}
-
-static int
-get_alignment(CTypeDescrObject *ct)
-{
- int align;
- retry:
- if ((ct->ct_flags & (CT_PRIMITIVE_ANY|CT_STRUCT|CT_UNION)) &&
- !(ct->ct_flags & CT_IS_OPAQUE)) {
- align = ct->ct_length;
- if (align == -1 && (ct->ct_flags & CT_LAZY_FIELD_LIST)) {
- force_lazy_struct(ct);
- align = ct->ct_length;
- }
- }
- else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
- struct aligncheck_ptr { char x; char *y; };
- align = offsetof(struct aligncheck_ptr, y);
- }
- else if (ct->ct_flags & CT_ARRAY) {
- ct = ct->ct_itemdescr;
- goto retry;
- }
- else {
- PyErr_Format(PyExc_ValueError, "ctype '%s' is of unknown alignment",
- ct->ct_name);
- return -1;
- }
-
- if ((align < 1) || (align & (align-1))) {
- PyErr_Format(PyExc_SystemError,
- "found for ctype '%s' bogus alignment '%d'",
- ct->ct_name, align);
- return -1;
- }
- return align;
-}
-
-static void cdata_dealloc(CDataObject *cd)
-{
- if (cd->c_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) cd);
-
- Py_DECREF(cd->c_type);
-#ifndef CFFI_MEM_LEAK /* never release anything, tests only */
- Py_TYPE(cd)->tp_free((PyObject *)cd);
-#endif
-}
-
-static void cdataowning_dealloc(CDataObject *cd)
-{
- assert(!(cd->c_type->ct_flags & (CT_IS_VOID_PTR | CT_FUNCTIONPTR)));
-
- if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
- /* for ffi.new("struct *") */
- Py_DECREF(((CDataObject_own_structptr *)cd)->structobj);
- }
-#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
- if (cd->c_type->ct_flags & (CT_PRIMITIVE_ANY | CT_STRUCT | CT_UNION)) {
- assert(cd->c_type->ct_size >= 0);
- memset(cd->c_data, 0xDD, cd->c_type->ct_size);
- }
- else if (cd->c_type->ct_flags & CT_ARRAY) {
- Py_ssize_t x = get_array_length(cd);
- assert(x >= 0);
- x *= cd->c_type->ct_itemdescr->ct_size;
- assert(x >= 0);
- memset(cd->c_data, 0xDD, x);
- }
-#endif
- cdata_dealloc(cd);
-}
-
-static void cdataowninggc_dealloc(CDataObject *cd)
-{
- PyObject_GC_UnTrack(cd);
-
- if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */
- PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
- Py_DECREF(x);
- }
- else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */
- ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
- PyObject *args = (PyObject *)(closure->user_data);
- Py_XDECREF(args);
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
- if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
- ffi_closure_free(closure);
- } else
-#endif
- cffi_closure_free(closure);
- }
- else {
- Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags");
- }
- cdata_dealloc(cd);
-}
-
-static void cdatafrombuf_dealloc(CDataObject *cd)
-{
- Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
- cdata_dealloc(cd);
-
- PyBuffer_Release(view);
- PyObject_Free(view);
-}
-
-static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg)
-{
- if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */
- PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
- Py_VISIT(x);
- }
- else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */
- ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
- PyObject *args = (PyObject *)(closure->user_data);
- Py_VISIT(args);
- }
- return 0;
-}
-
-static int cdatafrombuf_traverse(CDataObject *cd, visitproc visit, void *arg)
-{
- Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
- Py_VISIT(view->obj);
- return 0;
-}
-
-static int cdataowninggc_clear(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */
- CDataObject_own_structptr *cd1 = (CDataObject_own_structptr *)cd;
- PyObject *x = cd1->structobj;
- Py_INCREF(Py_None);
- cd1->structobj = Py_None;
- Py_DECREF(x);
- }
- else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */
- ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
- PyObject *args = (PyObject *)(closure->user_data);
- closure->user_data = NULL;
- Py_XDECREF(args);
- }
- return 0;
-}
-
-static int cdatafrombuf_clear(CDataObject *cd)
-{
- Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
- PyBuffer_Release(view);
- return 0;
-}
-
-/* forward */
-static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
- char *objdescr, PyObject *obj,
- char *extra_error_line);
-
-
-static void gcp_finalize(PyObject *destructor, PyObject *origobj)
-{
- /* NOTE: this decrements the reference count of the two arguments */
-
- if (destructor != NULL) {
- PyObject *result;
- PyObject *error_type, *error_value, *error_traceback;
-
- /* Save the current exception */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- result = PyObject_CallFunctionObjArgs(destructor, origobj, NULL);
- if (result != NULL) {
- Py_DECREF(result);
- }
- else {
- PyObject *t, *v, *tb;
- PyErr_Fetch(&t, &v, &tb);
- /* Don't use error capture here, because it is very much
- * like errors at __del__(), and these ones are not captured
- * either */
- /* ecap = _cffi_start_error_capture(); */
- _my_PyErr_WriteUnraisable(t, v, tb, "From callback for ffi.gc ",
- origobj, NULL);
- /* _cffi_stop_error_capture(ecap); */
- }
- Py_DECREF(destructor);
-
- /* Restore the saved exception */
- PyErr_Restore(error_type, error_value, error_traceback);
- }
- Py_XDECREF(origobj);
-}
-
-static void cdatagcp_finalize(CDataObject_gcp *cd)
-{
- PyObject *destructor = cd->destructor;
- PyObject *origobj = cd->origobj;
- cd->destructor = NULL;
- cd->origobj = NULL;
- gcp_finalize(destructor, origobj);
-}
-
-static void cdatagcp_dealloc(CDataObject_gcp *cd)
-{
- PyObject *destructor = cd->destructor;
- PyObject *origobj = cd->origobj;
- cdata_dealloc((CDataObject *)cd);
-
- gcp_finalize(destructor, origobj);
-}
-
-static int cdatagcp_traverse(CDataObject_gcp *cd, visitproc visit, void *arg)
-{
- Py_VISIT(cd->destructor);
- Py_VISIT(cd->origobj);
- return 0;
-}
-
-static PyObject *cdata_float(CDataObject *cd); /*forward*/
-
-static PyObject *convert_cdata_to_enum_string(CDataObject *cd, int both)
-{
- PyObject *d_key, *d_value;
- CTypeDescrObject *ct = cd->c_type;
-
- assert(ct->ct_flags & CT_IS_ENUM);
- d_key = convert_to_object(cd->c_data, ct);
- if (d_key == NULL)
- return NULL;
-
- d_value = PyDict_GetItem(PyTuple_GET_ITEM(ct->ct_stuff, 1), d_key);
- if (d_value != NULL) {
- if (both) {
- PyObject *o = PyObject_Str(d_key);
- if (o == NULL)
- d_value = NULL;
- else {
- d_value = PyText_FromFormat("%s: %s",
- PyText_AS_UTF8(o),
- PyText_AS_UTF8(d_value));
- Py_DECREF(o);
- }
- }
- else
- Py_INCREF(d_value);
- }
- else
- d_value = PyObject_Str(d_key);
- Py_DECREF(d_key);
- return d_value;
-}
-
-static PyObject *cdata_repr(CDataObject *cd)
-{
- char *extra;
- PyObject *result, *s;
-
- if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) {
- if (cd->c_type->ct_flags & CT_IS_ENUM) {
- s = convert_cdata_to_enum_string(cd, 1);
- }
- else if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE) {
- long double lvalue;
- char buffer[128]; /* big enough */
- /*READ(cd->c_data, sizeof(long double)*/
- lvalue = read_raw_longdouble_data(cd->c_data);
- sprintf(buffer, "%LE", lvalue);
- s = PyText_FromString(buffer);
- }
- else {
- PyObject *o = convert_to_object(cd->c_data, cd->c_type);
- if (o == NULL)
- return NULL;
- s = PyObject_Repr(o);
- Py_DECREF(o);
- }
- }
- else if ((cd->c_type->ct_flags & CT_ARRAY) && cd->c_type->ct_length < 0) {
- s = PyText_FromFormat("sliced length %zd", get_array_length(cd));
- }
- else {
- if (cd->c_data != NULL) {
- s = PyText_FromFormat("%p", cd->c_data);
- }
- else
- s = PyText_FromString("NULL");
- }
- if (s == NULL)
- return NULL;
- /* it's slightly confusing to get "<cdata 'struct foo' 0x...>" because the
- struct foo is not owned. Trying to make it clearer, write in this
- case "<cdata 'struct foo &' 0x...>". */
- if (cd->c_type->ct_flags & (CT_STRUCT|CT_UNION))
- extra = " &";
- else
- extra = "";
- result = PyText_FromFormat("<cdata '%s%s' %s>",
- cd->c_type->ct_name, extra,
- PyText_AsUTF8(s));
- Py_DECREF(s);
- return result;
-}
-
-static PyObject *_cdata_repr2(CDataObject *cd, char *text, PyObject *x)
-{
- PyObject *res, *s = PyObject_Repr(x);
- if (s == NULL)
- return NULL;
- res = PyText_FromFormat("<cdata '%s' %s %s>",
- cd->c_type->ct_name, text, PyText_AsUTF8(s));
- Py_DECREF(s);
- return res;
-}
-
-static Py_ssize_t _cdata_var_byte_size(CDataObject *cd)
-{
- /* If 'cd' is a 'struct foo' or 'struct foo *' allocated with
- ffi.new(), and if the struct foo contains a varsize array,
- then return the real allocated size. Otherwise, return -1. */
- if (!CDataOwn_Check(cd))
- return -1;
-
- if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
- cd = (CDataObject *)((CDataObject_own_structptr *)cd)->structobj;
- }
- if (cd->c_type->ct_flags & CT_WITH_VAR_ARRAY) {
- return ((CDataObject_own_length *)cd)->length;
- }
- return -1;
-}
-
-static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name)
-{
- Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
- const char *obj_tp_name;
- if (view->obj == NULL) {
- return PyText_FromFormat(
- "<cdata '%s' buffer RELEASED>",
- cd_type_name);
- }
-
- obj_tp_name = Py_TYPE(view->obj)->tp_name;
- if (cd->c_type->ct_flags & CT_ARRAY)
- {
- Py_ssize_t buflen = get_array_length(cd);
- return PyText_FromFormat(
- "<cdata '%s' buffer len %zd from '%.200s' object>",
- cd_type_name,
- buflen,
- obj_tp_name);
- }
- else
- {
- return PyText_FromFormat(
- "<cdata '%s' buffer from '%.200s' object>",
- cd_type_name,
- obj_tp_name);
- }
-}
-
-static PyObject *cdataowning_repr(CDataObject *cd)
-{
- Py_ssize_t size = _cdata_var_byte_size(cd);
- if (size < 0) {
- if (cd->c_type->ct_flags & CT_POINTER)
- size = cd->c_type->ct_itemdescr->ct_size;
- else if (cd->c_type->ct_flags & CT_ARRAY)
- size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
- else
- size = cd->c_type->ct_size;
- }
- return PyText_FromFormat("<cdata '%s' owning %zd bytes>",
- cd->c_type->ct_name, size);
-}
-
-static PyObject *cdataowninggc_repr(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */
- PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
- return _cdata_repr2(cd, "handle to", x);
- }
- else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */
- ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
- PyObject *args = (PyObject *)closure->user_data;
- if (args == NULL)
- return cdata_repr(cd);
- else
- return _cdata_repr2(cd, "calling", PyTuple_GET_ITEM(args, 1));
- }
- return cdataowning_repr(cd); /* but should be unreachable */
-}
-
-static PyObject *cdatafrombuf_repr(CDataObject *cd)
-{
- return _frombuf_repr(cd, cd->c_type->ct_name);
-}
-
-static int cdata_nonzero(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) {
- if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED |
- CT_PRIMITIVE_CHAR))
- return read_raw_unsigned_data(cd->c_data, cd->c_type->ct_size) != 0;
-
- if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
- if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE)
- return read_raw_longdouble_data(cd->c_data) != 0.0;
- return read_raw_float_data(cd->c_data, cd->c_type->ct_size) != 0.0;
- }
- if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) {
- Py_complex value = read_raw_complex_data(cd->c_data,
- cd->c_type->ct_size);
- return value.real != 0.0 || value.imag != 0.0;
- }
- }
- return cd->c_data != NULL;
-}
-
-static PyObject *cdata_int(CDataObject *cd)
-{
- if ((cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG))
- == (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG)) {
- /* this case is to handle enums, but also serves as a slight
- performance improvement for some other primitive types */
- long value;
- /*READ(cd->c_data, cd->c_type->ct_size)*/
- value = (long)read_raw_signed_data(cd->c_data, cd->c_type->ct_size);
- return PyInt_FromLong(value);
- }
- if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) {
- PyObject *result = convert_to_object(cd->c_data, cd->c_type);
- if (result != NULL && PyBool_Check(result))
- result = PyInt_FromLong(PyInt_AsLong(result));
- return result;
- }
- else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
- /*READ(cd->c_data, cd->c_type->ct_size)*/
- switch (cd->c_type->ct_size) {
- case sizeof(char):
- return PyInt_FromLong((unsigned char)cd->c_data[0]);
- case 2:
- return PyInt_FromLong((long)*(cffi_char16_t *)cd->c_data);
- case 4:
- if (cd->c_type->ct_flags & CT_IS_SIGNED_WCHAR)
- return PyInt_FromLong((long)*(int32_t *)cd->c_data);
- else if (sizeof(long) > 4)
- return PyInt_FromLong(*(uint32_t *)cd->c_data);
- else
- return PyLong_FromUnsignedLong(*(uint32_t *)cd->c_data);
- }
- }
- else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
- PyObject *o = cdata_float(cd);
-#if PY_MAJOR_VERSION < 3
- PyObject *r = o ? PyNumber_Int(o) : NULL;
-#else
- PyObject *r = o ? PyNumber_Long(o) : NULL;
-#endif
- Py_XDECREF(o);
- return r;
- }
- PyErr_Format(PyExc_TypeError, "int() not supported on cdata '%s'",
- cd->c_type->ct_name);
- return NULL;
-}
-
-#if PY_MAJOR_VERSION < 3
-static PyObject *cdata_long(CDataObject *cd)
-{
- PyObject *res = cdata_int(cd);
- if (res != NULL && PyInt_CheckExact(res)) {
- PyObject *o = PyLong_FromLong(PyInt_AS_LONG(res));
- Py_DECREF(res);
- res = o;
- }
- return res;
-}
-#endif
-
-static PyObject *cdata_float(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
- double value;
- /*READ(cd->c_data, cd->c_type->ct_size)*/
- if (!(cd->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
- value = read_raw_float_data(cd->c_data, cd->c_type->ct_size);
- }
- else {
- value = (double)read_raw_longdouble_data(cd->c_data);
- }
- return PyFloat_FromDouble(value);
- }
- PyErr_Format(PyExc_TypeError, "float() not supported on cdata '%s'",
- cd->c_type->ct_name);
- return NULL;
-}
-
-static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op)
-{
- int v_is_ptr, w_is_ptr;
- PyObject *pyres;
-
- assert(CData_Check(v));
-
- /* Comparisons involving a primitive cdata work differently than
- * comparisons involving a struct/array/pointer.
- *
- * If v or w is a struct/array/pointer, then the other must be too
- * (otherwise we return NotImplemented and leave the case to
- * Python). If both are, then we compare the addresses.
- *
- * If v and/or w is a primitive cdata, then we convert the cdata(s)
- * to regular Python objects and redo the comparison there.
- */
-
- v_is_ptr = !(((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY);
- w_is_ptr = CData_Check(w) &&
- !(((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY);
-
- if (v_is_ptr && w_is_ptr) {
- int res;
- char *v_cdata = ((CDataObject *)v)->c_data;
- char *w_cdata = ((CDataObject *)w)->c_data;
-
- switch (op) {
- case Py_EQ: res = (v_cdata == w_cdata); break;
- case Py_NE: res = (v_cdata != w_cdata); break;
- case Py_LT: res = (v_cdata < w_cdata); break;
- case Py_LE: res = (v_cdata <= w_cdata); break;
- case Py_GT: res = (v_cdata > w_cdata); break;
- case Py_GE: res = (v_cdata >= w_cdata); break;
- default: res = -1;
- }
- pyres = res ? Py_True : Py_False;
- }
- else if (v_is_ptr || w_is_ptr) {
- pyres = Py_NotImplemented;
- }
- else {
- PyObject *aa[2];
- int i;
-
- aa[0] = v; Py_INCREF(v);
- aa[1] = w; Py_INCREF(w);
- pyres = NULL;
-
- for (i = 0; i < 2; i++) {
- v = aa[i];
- if (!CData_Check(v))
- continue;
- w = convert_to_object(((CDataObject *)v)->c_data,
- ((CDataObject *)v)->c_type);
- if (w == NULL)
- goto error;
- if (CData_Check(w)) {
- Py_DECREF(w);
- PyErr_Format(PyExc_NotImplementedError,
- "cannot use <cdata '%s'> in a comparison",
- ((CDataObject *)v)->c_type->ct_name);
- goto error;
- }
- aa[i] = w;
- Py_DECREF(v);
- }
- pyres = PyObject_RichCompare(aa[0], aa[1], op);
- error:
- Py_DECREF(aa[1]);
- Py_DECREF(aa[0]);
- return pyres;
- }
-
- Py_INCREF(pyres);
- return pyres;
-}
-
-#if PY_MAJOR_VERSION < 3
-typedef long Py_hash_t;
-#endif
-
-static Py_hash_t cdata_hash(PyObject *v)
-{
- if (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) {
- PyObject *vv = convert_to_object(((CDataObject *)v)->c_data,
- ((CDataObject *)v)->c_type);
- if (vv == NULL)
- return -1;
- if (!CData_Check(vv)) {
- Py_hash_t hash = PyObject_Hash(vv);
- Py_DECREF(vv);
- return hash;
- }
- Py_DECREF(vv);
- }
- return _Py_HashPointer(((CDataObject *)v)->c_data);
-}
-
-static Py_ssize_t
-cdata_length(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_ARRAY) {
- return get_array_length(cd);
- }
- PyErr_Format(PyExc_TypeError, "cdata of type '%s' has no len()",
- cd->c_type->ct_name);
- return -1;
-}
-
-static char *
-_cdata_get_indexed_ptr(CDataObject *cd, PyObject *key)
-{
- Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
-
- if (cd->c_type->ct_flags & CT_POINTER) {
- if (CDataOwn_Check(cd)) {
- if (i != 0) {
- PyErr_Format(PyExc_IndexError,
- "cdata '%s' can only be indexed by 0",
- cd->c_type->ct_name);
- return NULL;
- }
- }
- else {
- if (cd->c_data == NULL) {
- PyErr_Format(PyExc_RuntimeError,
- "cannot dereference null pointer from cdata '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- }
- }
- else if (cd->c_type->ct_flags & CT_ARRAY) {
- if (i < 0) {
- PyErr_SetString(PyExc_IndexError,
- "negative index");
- return NULL;
- }
- if (i >= get_array_length(cd)) {
- PyErr_Format(PyExc_IndexError,
- "index too large for cdata '%s' (expected %zd < %zd)",
- cd->c_type->ct_name,
- i, get_array_length(cd));
- return NULL;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
- cd->c_type->ct_name);
- return NULL;
- }
- return cd->c_data + i * cd->c_type->ct_itemdescr->ct_size;
-}
-
-static PyObject *
-new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length); /* forward */
-
-static CTypeDescrObject *
-_cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[])
-{
- Py_ssize_t start, stop;
- CTypeDescrObject *ct;
-
- start = PyInt_AsSsize_t(slice->start);
- if (start == -1 && PyErr_Occurred()) {
- if (slice->start == Py_None)
- PyErr_SetString(PyExc_IndexError, "slice start must be specified");
- return NULL;
- }
- stop = PyInt_AsSsize_t(slice->stop);
- if (stop == -1 && PyErr_Occurred()) {
- if (slice->stop == Py_None)
- PyErr_SetString(PyExc_IndexError, "slice stop must be specified");
- return NULL;
- }
- if (slice->step != Py_None) {
- PyErr_SetString(PyExc_IndexError, "slice with step not supported");
- return NULL;
- }
- if (start > stop) {
- PyErr_SetString(PyExc_IndexError, "slice start > stop");
- return NULL;
- }
-
- ct = cd->c_type;
- if (ct->ct_flags & CT_ARRAY) {
- if (start < 0) {
- PyErr_SetString(PyExc_IndexError,
- "negative index");
- return NULL;
- }
- if (stop > get_array_length(cd)) {
- PyErr_Format(PyExc_IndexError,
- "index too large (expected %zd <= %zd)",
- stop, get_array_length(cd));
- return NULL;
- }
- ct = (CTypeDescrObject *)ct->ct_stuff;
- }
- else if (!(ct->ct_flags & CT_POINTER)) {
- PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
- ct->ct_name);
- return NULL;
- }
-
- bounds[0] = start;
- bounds[1] = stop - start;
- return ct;
-}
-
-static PyObject *
-cdata_slice(CDataObject *cd, PySliceObject *slice)
-{
- char *cdata;
- Py_ssize_t bounds[2];
- CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
- if (ct == NULL)
- return NULL;
-
- if (ct->ct_stuff == NULL) {
- ct->ct_stuff = new_array_type(ct, -1);
- if (ct->ct_stuff == NULL)
- return NULL;
- }
- ct = (CTypeDescrObject *)ct->ct_stuff;
-
- cdata = cd->c_data + ct->ct_itemdescr->ct_size * bounds[0];
- return new_sized_cdata(cdata, ct, bounds[1]);
-}
-
-static int
-cdata_ass_slice(CDataObject *cd, PySliceObject *slice, PyObject *v)
-{
- Py_ssize_t bounds[2], i, length, itemsize;
- PyObject *it, *item;
- PyObject *(*iternext)(PyObject *);
- char *cdata;
- int err;
- CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
- if (ct == NULL)
- return -1;
- ct = ct->ct_itemdescr;
- itemsize = ct->ct_size;
- cdata = cd->c_data + itemsize * bounds[0];
- length = bounds[1];
-
- if (CData_Check(v)) {
- CTypeDescrObject *ctv = ((CDataObject *)v)->c_type;
- if ((ctv->ct_flags & CT_ARRAY) && (ctv->ct_itemdescr == ct) &&
- (get_array_length((CDataObject *)v) == length)) {
- /* fast path: copying from exactly the correct type */
- memmove(cdata, ((CDataObject *)v)->c_data, itemsize * length);
- return 0;
- }
- }
-
- /* A fast path for <char[]>[0:N] = b"somestring" or bytearray, which
- also adds support for Python 3: otherwise, you get integers while
- enumerating the string, and you can't set them to characters :-/
- */
- if ((ct->ct_flags & CT_PRIMITIVE_CHAR) && itemsize == sizeof(char)) {
- char *src;
- Py_ssize_t srclen;
- if (PyBytes_Check(v)) {
- srclen = PyBytes_GET_SIZE(v);
- src = PyBytes_AS_STRING(v);
- }
- else if (PyByteArray_Check(v)) {
- srclen = PyByteArray_GET_SIZE(v);
- src = PyByteArray_AS_STRING(v);
- }
- else
- goto other_types;
-
- if (srclen != length) {
- PyErr_Format(PyExc_ValueError,
- "need a string of length %zd, got %zd",
- length, srclen);
- return -1;
- }
- memcpy(cdata, src, length);
- return 0;
- }
- other_types:
-
- it = PyObject_GetIter(v);
- if (it == NULL)
- return -1;
- iternext = *it->ob_type->tp_iternext;
-
- for (i = 0; i < length; i++) {
- item = iternext(it);
- if (item == NULL) {
- if (!PyErr_Occurred())
- PyErr_Format(PyExc_ValueError,
- "need %zd values to unpack, got %zd",
- length, i);
- goto error;
- }
- err = convert_from_object(cdata, ct, item);
- Py_DECREF(item);
- if (err < 0)
- goto error;
-
- cdata += itemsize;
- }
- item = iternext(it);
- if (item != NULL) {
- Py_DECREF(item);
- PyErr_Format(PyExc_ValueError,
- "got more than %zd values to unpack", length);
- }
- error:
- Py_DECREF(it);
- return PyErr_Occurred() ? -1 : 0;
-}
-
-static PyObject *
-cdataowning_subscript(CDataObject *cd, PyObject *key)
-{
- char *c;
- if (PySlice_Check(key))
- return cdata_slice(cd, (PySliceObject *)key);
-
- c = _cdata_get_indexed_ptr(cd, key);
- /* use 'mp_subscript' instead of 'sq_item' because we don't want
- negative indexes to be corrected automatically */
- if (c == NULL && PyErr_Occurred())
- return NULL;
-
- if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
- PyObject *res = ((CDataObject_own_structptr *)cd)->structobj;
- Py_INCREF(res);
- return res;
- }
- else {
- return convert_to_object(c, cd->c_type->ct_itemdescr);
- }
-}
-
-static PyObject *
-cdata_subscript(CDataObject *cd, PyObject *key)
-{
- char *c;
- if (PySlice_Check(key))
- return cdata_slice(cd, (PySliceObject *)key);
-
- c = _cdata_get_indexed_ptr(cd, key);
- /* use 'mp_subscript' instead of 'sq_item' because we don't want
- negative indexes to be corrected automatically */
- if (c == NULL && PyErr_Occurred())
- return NULL;
- return convert_to_object(c, cd->c_type->ct_itemdescr);
-}
-
-static int
-cdata_ass_sub(CDataObject *cd, PyObject *key, PyObject *v)
-{
- char *c;
- CTypeDescrObject *ctitem;
- if (PySlice_Check(key))
- return cdata_ass_slice(cd, (PySliceObject *)key, v);
-
- c = _cdata_get_indexed_ptr(cd, key);
- ctitem = cd->c_type->ct_itemdescr;
- /* use 'mp_ass_subscript' instead of 'sq_ass_item' because we don't want
- negative indexes to be corrected automatically */
- if (c == NULL && PyErr_Occurred())
- return -1;
- if (v == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "'del x[n]' not supported for cdata objects");
- return -1;
- }
- return convert_from_object(c, ctitem, v);
-}
-
-static PyObject *
-_cdata_add_or_sub(PyObject *v, PyObject *w, int sign)
-{
- Py_ssize_t i, itemsize;
- CDataObject *cd;
- CTypeDescrObject *ctptr;
-
- if (!CData_Check(v)) {
- PyObject *swap;
- assert(CData_Check(w));
- if (sign != 1)
- goto not_implemented;
- swap = v;
- v = w;
- w = swap;
- }
-
- i = PyNumber_AsSsize_t(w, PyExc_OverflowError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- i *= sign;
-
- cd = (CDataObject *)v;
- if (cd->c_type->ct_flags & CT_POINTER)
- ctptr = cd->c_type;
- else if (cd->c_type->ct_flags & CT_ARRAY) {
- ctptr = (CTypeDescrObject *)cd->c_type->ct_stuff;
- }
- else {
- PyErr_Format(PyExc_TypeError, "cannot add a cdata '%s' and a number",
- cd->c_type->ct_name);
- return NULL;
- }
- itemsize = ctptr->ct_itemdescr->ct_size;
- if (itemsize < 0) {
- if (ctptr->ct_flags & CT_IS_VOID_PTR) {
- itemsize = 1;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "ctype '%s' points to items of unknown size",
- cd->c_type->ct_name);
- return NULL;
- }
- }
- return new_simple_cdata(cd->c_data + i * itemsize, ctptr);
-
- not_implemented:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static PyObject *
-cdata_add(PyObject *v, PyObject *w)
-{
- return _cdata_add_or_sub(v, w, +1);
-}
-
-static PyObject *
-cdata_sub(PyObject *v, PyObject *w)
-{
- if (CData_Check(v) && CData_Check(w)) {
- CDataObject *cdv = (CDataObject *)v;
- CDataObject *cdw = (CDataObject *)w;
- CTypeDescrObject *ct = cdw->c_type;
- Py_ssize_t diff, itemsize;
-
- if (ct->ct_flags & CT_ARRAY) /* ptr_to_T - array_of_T: ok */
- ct = (CTypeDescrObject *)ct->ct_stuff;
-
- if (ct != cdv->c_type || !(ct->ct_flags & CT_POINTER) ||
- (ct->ct_itemdescr->ct_size <= 0 &&
- !(ct->ct_flags & CT_IS_VOID_PTR))) {
- PyErr_Format(PyExc_TypeError,
- "cannot subtract cdata '%s' and cdata '%s'",
- cdv->c_type->ct_name, ct->ct_name);
- return NULL;
- }
- itemsize = ct->ct_itemdescr->ct_size;
- diff = cdv->c_data - cdw->c_data;
- if (itemsize > 1) {
- if (diff % itemsize) {
- PyErr_SetString(PyExc_ValueError,
- "pointer subtraction: the distance between the two "
- "pointers is not a multiple of the item size");
- return NULL;
- }
- diff = diff / itemsize;
- }
-#if PY_MAJOR_VERSION < 3
- return PyInt_FromSsize_t(diff);
-#else
- return PyLong_FromSsize_t(diff);
-#endif
- }
-
- return _cdata_add_or_sub(v, w, -1);
-}
-
-static void
-_cdata_attr_errmsg(char *errmsg, CDataObject *cd, PyObject *attr)
-{
- const char *text;
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return;
- PyErr_Clear();
- text = PyText_AsUTF8(attr);
- if (text == NULL)
- return;
- PyErr_Format(PyExc_AttributeError, errmsg, cd->c_type->ct_name, text);
-}
-
-static PyObject *
-cdata_getattro(CDataObject *cd, PyObject *attr)
-{
- CFieldObject *cf;
- CTypeDescrObject *ct = cd->c_type;
- char *errmsg = "cdata '%s' has no attribute '%s'";
- PyObject *x;
-
- if (ct->ct_flags & CT_POINTER)
- ct = ct->ct_itemdescr;
-
- if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
- switch (force_lazy_struct(ct)) {
- case 1:
- cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, attr);
- if (cf != NULL) {
- /* read the field 'cf' */
- char *data = cd->c_data + cf->cf_offset;
- Py_ssize_t array_len, size;
-
- if (cf->cf_bitshift == BS_REGULAR) {
- return convert_to_object(data, cf->cf_type);
- }
- else if (cf->cf_bitshift != BS_EMPTY_ARRAY) {
- return convert_to_object_bitfield(data, cf);
- }
-
- /* variable-length array: */
- /* if reading variable length array from variable length
- struct, calculate array type from allocated length */
- size = _cdata_var_byte_size(cd) - cf->cf_offset;
- if (size >= 0) {
- array_len = size / cf->cf_type->ct_itemdescr->ct_size;
- return new_sized_cdata(data, cf->cf_type, array_len);
- }
- return new_simple_cdata(data,
- (CTypeDescrObject *)cf->cf_type->ct_stuff);
- }
- errmsg = "cdata '%s' has no field '%s'";
- break;
- case -1:
- return NULL;
- default:
- errmsg = "cdata '%s' points to an opaque type: cannot read fields";
- break;
- }
- }
- x = PyObject_GenericGetAttr((PyObject *)cd, attr);
- if (x == NULL)
- _cdata_attr_errmsg(errmsg, cd, attr);
- return x;
-}
-
-static int
-cdata_setattro(CDataObject *cd, PyObject *attr, PyObject *value)
-{
- CFieldObject *cf;
- CTypeDescrObject *ct = cd->c_type;
- char *errmsg = "cdata '%s' has no attribute '%s'";
- int x;
-
- if (ct->ct_flags & CT_POINTER)
- ct = ct->ct_itemdescr;
-
- if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
- switch (force_lazy_struct(ct)) {
- case 1:
- cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, attr);
- if (cf != NULL) {
- /* write the field 'cf' */
- if (value != NULL) {
- return convert_field_from_object(cd->c_data, cf, value);
- }
- else {
- PyErr_SetString(PyExc_AttributeError,
- "cannot delete struct field");
- return -1;
- }
- }
- errmsg = "cdata '%s' has no field '%s'";
- break;
- case -1:
- return -1;
- default:
- errmsg = "cdata '%s' points to an opaque type: cannot write fields";
- break;
- }
- }
- x = PyObject_GenericSetAttr((PyObject *)cd, attr, value);
- if (x < 0)
- _cdata_attr_errmsg(errmsg, cd, attr);
- return x;
-}
-
-static PyObject *
-convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/
-
-static cif_description_t *
-fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi);
- /*forward*/
-
-static PyObject *new_primitive_type(const char *name); /*forward*/
-
-static CTypeDescrObject *_get_ct_int(void)
-{
- static CTypeDescrObject *ct_int = NULL;
- if (ct_int == NULL) {
- ct_int = (CTypeDescrObject *)new_primitive_type("int");
- }
- return ct_int;
-}
-
-static Py_ssize_t
-_prepare_pointer_call_argument(CTypeDescrObject *ctptr, PyObject *init,
- char **output_data)
-{
- /* 'ctptr' is here a pointer type 'ITEM *'. Accept as argument an
- initializer for an array 'ITEM[]'. This includes the case of
- passing a Python byte string to a 'char *' argument.
-
- This function returns -1 if an error occurred,
- 0 if conversion succeeded (into *output_data),
- or N > 0 if conversion would require N bytes of storage.
- */
- Py_ssize_t length, datasize;
- CTypeDescrObject *ctitem;
-
- if (CData_Check(init))
- goto convert_default;
-
- ctitem = ctptr->ct_itemdescr;
- /* XXX some code duplication, how to avoid it? */
- if (PyBytes_Check(init)) {
- /* from a string: just returning the string here is fine.
- We assume that the C code won't modify the 'char *' data. */
- if ((ctptr->ct_flags & CT_IS_VOIDCHAR_PTR) ||
- ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))
- && (ctitem->ct_size == sizeof(char)))) {
-#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
- length = PyBytes_GET_SIZE(init) + 1;
-#else
- *output_data = PyBytes_AS_STRING(init);
- if (ctitem->ct_flags & CT_IS_BOOL)
- if (must_be_array_of_zero_or_one(*output_data,
- PyBytes_GET_SIZE(init)) < 0)
- return -1;
- return 0;
-#endif
- }
- else
- goto convert_default;
- }
- else if (PyList_Check(init) || PyTuple_Check(init)) {
- length = PySequence_Fast_GET_SIZE(init);
- }
- else if (PyUnicode_Check(init)) {
- /* from a unicode, we add the null terminator */
- if (ctitem->ct_size == 2)
- length = _my_PyUnicode_SizeAsChar16(init);
- else
- length = _my_PyUnicode_SizeAsChar32(init);
- length += 1;
- }
- else if ((ctitem->ct_flags & CT_IS_FILE) && PyFile_Check(init)) {
- *output_data = (char *)PyFile_AsFile(init);
- if (*output_data == NULL && PyErr_Occurred())
- return -1;
- return 0;
- }
- else {
- /* refuse to receive just an integer (and interpret it
- as the array size) */
- goto convert_default;
- }
-
- if (ctitem->ct_size <= 0)
- goto convert_default;
- datasize = MUL_WRAPAROUND(length, ctitem->ct_size);
- if ((datasize / ctitem->ct_size) != length) {
- PyErr_SetString(PyExc_OverflowError,
- "array size would overflow a Py_ssize_t");
- return -1;
- }
- if (datasize <= 0)
- datasize = 1;
- return datasize;
-
- convert_default:
- return convert_from_object((char *)output_data, ctptr, init);
-}
-
-static PyObject*
-cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds)
-{
- char *buffer;
- void** buffer_array;
- cif_description_t *cif_descr;
- Py_ssize_t i, nargs, nargs_declared;
- PyObject *signature, *res = NULL, *fvarargs;
- CTypeDescrObject *fresult;
- char *resultdata;
- char *errormsg;
- struct freeme_s {
- struct freeme_s *next;
- union_alignment alignment;
- } *freeme = NULL;
-
- if (!(cd->c_type->ct_flags & CT_FUNCTIONPTR)) {
- PyErr_Format(PyExc_TypeError, "cdata '%s' is not callable",
- cd->c_type->ct_name);
- return NULL;
- }
- if (cd->c_data == NULL) {
- PyErr_Format(PyExc_RuntimeError,
- "cannot call null pointer pointer from cdata '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- if (kwds != NULL && PyDict_Size(kwds) != 0) {
- PyErr_SetString(PyExc_TypeError,
- "a cdata function cannot be called with keyword arguments");
- return NULL;
- }
- signature = cd->c_type->ct_stuff;
- nargs = PyTuple_Size(args);
- if (nargs < 0)
- return NULL;
- nargs_declared = PyTuple_GET_SIZE(signature) - 2;
- fresult = (CTypeDescrObject *)PyTuple_GET_ITEM(signature, 1);
- fvarargs = NULL;
- buffer = NULL;
-
- cif_descr = (cif_description_t *)cd->c_type->ct_extra;
-
- if (cif_descr != NULL) {
- /* regular case: this function does not take '...' arguments */
- if (nargs != nargs_declared) {
- errormsg = "'%s' expects %zd arguments, got %zd";
- bad_number_of_arguments:
- PyErr_Format(PyExc_TypeError, errormsg,
- cd->c_type->ct_name, nargs_declared, nargs);
- goto error;
- }
- }
- else {
- /* call of a variadic function */
- ffi_abi fabi;
- if (nargs < nargs_declared) {
- errormsg = "'%s' expects at least %zd arguments, got %zd";
- goto bad_number_of_arguments;
- }
- fvarargs = PyTuple_New(nargs);
- if (fvarargs == NULL)
- goto error;
- for (i = 0; i < nargs_declared; i++) {
- PyObject *o = PyTuple_GET_ITEM(signature, 2 + i);
- Py_INCREF(o);
- PyTuple_SET_ITEM(fvarargs, i, o);
- }
- for (i = nargs_declared; i < nargs; i++) {
- PyObject *obj = PyTuple_GET_ITEM(args, i);
- CTypeDescrObject *ct;
-
- if (CData_Check(obj)) {
- ct = ((CDataObject *)obj)->c_type;
- if (ct->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_UNSIGNED |
- CT_PRIMITIVE_SIGNED)) {
- if (ct->ct_size < (Py_ssize_t)sizeof(int)) {
- ct = _get_ct_int();
- if (ct == NULL)
- goto error;
- }
- }
- else if (ct->ct_flags & CT_ARRAY) {
- ct = (CTypeDescrObject *)ct->ct_stuff;
- }
- Py_INCREF(ct);
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "argument %zd passed in the variadic part "
- "needs to be a cdata object (got %.200s)",
- i + 1, Py_TYPE(obj)->tp_name);
- goto error;
- }
- PyTuple_SET_ITEM(fvarargs, i, (PyObject *)ct);
- }
-#if PY_MAJOR_VERSION < 3
- fabi = PyInt_AS_LONG(PyTuple_GET_ITEM(signature, 0));
-#else
- fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
-#endif
- cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi);
- if (cif_descr == NULL)
- goto error;
- }
-
- buffer = PyObject_Malloc(cif_descr->exchange_size);
- if (buffer == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- buffer_array = (void **)buffer;
-
- for (i=0; i<nargs; i++) {
- CTypeDescrObject *argtype;
- char *data = buffer + cif_descr->exchange_offset_arg[1 + i];
- PyObject *obj = PyTuple_GET_ITEM(args, i);
-
- buffer_array[i] = data;
-
- if (i < nargs_declared)
- argtype = (CTypeDescrObject *)PyTuple_GET_ITEM(signature, 2 + i);
- else
- argtype = (CTypeDescrObject *)PyTuple_GET_ITEM(fvarargs, i);
-
- if (argtype->ct_flags & CT_POINTER) {
- char *tmpbuf;
- Py_ssize_t datasize = _prepare_pointer_call_argument(
- argtype, obj, (char **)data);
- if (datasize == 0)
- ; /* successfully filled '*data' */
- else if (datasize < 0)
- goto error;
- else {
- if (datasize <= 512) {
- tmpbuf = alloca(datasize);
- }
- else {
- struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc(
- offsetof(struct freeme_s, alignment) +
- (size_t)datasize);
- if (fp == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- fp->next = freeme;
- freeme = fp;
- tmpbuf = (char *)&fp->alignment;
- }
- memset(tmpbuf, 0, datasize);
- *(char **)data = tmpbuf;
- if (convert_array_from_object(tmpbuf, argtype, obj) < 0)
- goto error;
- }
- }
- else if (convert_from_object(data, argtype, obj) < 0)
- goto error;
- }
-
- resultdata = buffer + cif_descr->exchange_offset_arg[0];
- /*READ(cd->c_data, sizeof(void(*)(void)))*/
-
- Py_BEGIN_ALLOW_THREADS
- restore_errno();
- ffi_call(&cif_descr->cif, (void (*)(void))(cd->c_data),
- resultdata, buffer_array);
- save_errno();
- Py_END_ALLOW_THREADS
-
- if (fresult->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED)) {
-#ifdef WORDS_BIGENDIAN
- /* For results of precisely these types, libffi has a strange
- rule that they will be returned as a whole 'ffi_arg' if they
- are smaller. The difference only matters on big-endian. */
- if (fresult->ct_size < sizeof(ffi_arg))
- resultdata += (sizeof(ffi_arg) - fresult->ct_size);
-#endif
- res = convert_to_object(resultdata, fresult);
- }
- else if (fresult->ct_flags & CT_VOID) {
- res = Py_None;
- Py_INCREF(res);
- }
- else if (fresult->ct_flags & CT_STRUCT) {
- res = convert_struct_to_owning_object(resultdata, fresult);
- }
- else {
- res = convert_to_object(resultdata, fresult);
- }
- /* fall-through */
-
- error:
- while (freeme != NULL) {
- void *p = (void *)freeme;
- freeme = freeme->next;
- PyObject_Free(p);
- }
- if (buffer)
- PyObject_Free(buffer);
- if (fvarargs != NULL) {
- Py_DECREF(fvarargs);
- if (cif_descr != NULL) /* but only if fvarargs != NULL, if variadic */
- PyObject_Free(cif_descr);
- }
- return res;
-}
-
-static PyObject *cdata_dir(PyObject *cd, PyObject *noarg)
-{
- CTypeDescrObject *ct = ((CDataObject *)cd)->c_type;
-
- /* replace the type 'pointer-to-t' with just 't' */
- if (ct->ct_flags & CT_POINTER) {
- ct = ct->ct_itemdescr;
- }
- if ((ct->ct_flags & (CT_STRUCT | CT_UNION)) &&
- !(ct->ct_flags & CT_IS_OPAQUE)) {
-
- /* for non-opaque structs or unions */
- if (force_lazy_struct(ct) < 0)
- return NULL;
- return PyDict_Keys(ct->ct_stuff);
- }
- else {
- return PyList_New(0); /* empty list for the other cases */
- }
-}
-
-static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg)
-{
- CDataObject *cd = (CDataObject *)cd_;
-
- if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) {
- Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size);
- PyObject *op = PyComplex_FromCComplex(value);
- return op;
- }
- /* <cdata 'float'> or <cdata 'int'> cannot be directly converted by
- calling complex(), just like <cdata 'int'> cannot be directly
- converted by calling float() */
-
- PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'",
- cd->c_type->ct_name);
- return NULL;
-}
-
-static int explicit_release_case(PyObject *cd)
-{
- CTypeDescrObject *ct = ((CDataObject *)cd)->c_type;
- if (Py_TYPE(cd) == &CDataOwning_Type) {
- if ((ct->ct_flags & (CT_POINTER | CT_ARRAY)) != 0) /* ffi.new() */
- return 0;
- }
- else if (Py_TYPE(cd) == &CDataFromBuf_Type) {
- return 1; /* ffi.from_buffer() */
- }
- else if (Py_TYPE(cd) == &CDataGCP_Type) {
- return 2; /* ffi.gc() */
- }
- PyErr_SetString(PyExc_ValueError,
- "only 'cdata' object from ffi.new(), ffi.gc(), ffi.from_buffer() "
- "or ffi.new_allocator()() can be used with the 'with' keyword or "
- "ffi.release()");
- return -1;
-}
-
-static PyObject *cdata_enter(PyObject *cd, PyObject *noarg)
-{
- if (explicit_release_case(cd) < 0) /* only to check the ctype */
- return NULL;
- Py_INCREF(cd);
- return cd;
-}
-
-static PyObject *cdata_exit(PyObject *cd, PyObject *args)
-{
- /* 'args' ignored */
- CTypeDescrObject *ct;
- Py_buffer *view;
- switch (explicit_release_case(cd))
- {
- case 0: /* ffi.new() */
- /* no effect on CPython: raw memory is allocated with the
- same malloc() as the object itself, so it can't be
- released independently. If we use a custom allocator,
- then it's implemented with ffi.gc(). */
- ct = ((CDataObject *)cd)->c_type;
- if (ct->ct_flags & CT_IS_PTR_TO_OWNED) {
- PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
- if (Py_TYPE(x) == &CDataGCP_Type) {
- /* this is a special case for
- ffi.new_allocator()("struct-or-union *") */
- cdatagcp_finalize((CDataObject_gcp *)x);
- }
- }
- break;
-
- case 1: /* ffi.from_buffer() */
- view = ((CDataObject_frombuf *)cd)->bufferview;
- PyBuffer_Release(view);
- break;
-
- case 2: /* ffi.gc() or ffi.new_allocator()("not-struct-nor-union") */
- /* call the destructor immediately */
- cdatagcp_finalize((CDataObject_gcp *)cd);
- break;
-
- default:
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *cdata_iter(CDataObject *);
-
-static PyNumberMethods CData_as_number = {
- (binaryfunc)cdata_add, /*nb_add*/
- (binaryfunc)cdata_sub, /*nb_subtract*/
- 0, /*nb_multiply*/
-#if PY_MAJOR_VERSION < 3
- 0, /*nb_divide*/
-#endif
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- 0, /*nb_negative*/
- 0, /*nb_positive*/
- 0, /*nb_absolute*/
- (inquiry)cdata_nonzero, /*nb_nonzero*/
- 0, /*nb_invert*/
- 0, /*nb_lshift*/
- 0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
-#if PY_MAJOR_VERSION < 3
- 0, /*nb_coerce*/
-#endif
- (unaryfunc)cdata_int, /*nb_int*/
-#if PY_MAJOR_VERSION < 3
- (unaryfunc)cdata_long, /*nb_long*/
-#else
- 0,
-#endif
- (unaryfunc)cdata_float, /*nb_float*/
- 0, /*nb_oct*/
- 0, /*nb_hex*/
-};
-
-static PyMappingMethods CData_as_mapping = {
- (lenfunc)cdata_length, /*mp_length*/
- (binaryfunc)cdata_subscript, /*mp_subscript*/
- (objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
-};
-
-static PyMappingMethods CDataOwn_as_mapping = {
- (lenfunc)cdata_length, /*mp_length*/
- (binaryfunc)cdataowning_subscript, /*mp_subscript*/
- (objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
-};
-
-static PyMethodDef cdata_methods[] = {
- {"__dir__", cdata_dir, METH_NOARGS},
- {"__complex__", cdata_complex, METH_NOARGS},
- {"__enter__", cdata_enter, METH_NOARGS},
- {"__exit__", cdata_exit, METH_VARARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject CData_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend._CDataBase",
- sizeof(CDataObject),
- 0,
- (destructor)cdata_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)cdata_repr, /* tp_repr */
- &CData_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- &CData_as_mapping, /* tp_as_mapping */
- cdata_hash, /* tp_hash */
- (ternaryfunc)cdata_call, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)cdata_getattro, /* tp_getattro */
- (setattrofunc)cdata_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- "The internal base type for CData objects. Use FFI.CData to access "
- "it. Always check with isinstance(): subtypes are sometimes returned "
- "on CPython, for performance reasons.", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- cdata_richcompare, /* tp_richcompare */
- offsetof(CDataObject, c_weakreflist), /* tp_weaklistoffset */
- (getiterfunc)cdata_iter, /* tp_iter */
- 0, /* tp_iternext */
- cdata_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-static PyTypeObject CDataOwning_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__CDataOwn",
- sizeof(CDataObject),
- 0,
- (destructor)cdataowning_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)cdataowning_repr, /* tp_repr */
- 0, /* inherited */ /* tp_as_number */
- 0, /* tp_as_sequence */
- &CDataOwn_as_mapping, /* tp_as_mapping */
- 0, /* inherited */ /* tp_hash */
- 0, /* inherited */ /* tp_call */
- 0, /* tp_str */
- 0, /* inherited */ /* tp_getattro */
- 0, /* inherited */ /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- "This is an internal subtype of _CDataBase for performance only on "
- "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* inherited */ /* tp_richcompare */
- 0, /* inherited */ /* tp_weaklistoffset */
- 0, /* inherited */ /* tp_iter */
- 0, /* tp_iternext */
- 0, /* inherited */ /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &CData_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- free, /* tp_free */
-};
-
-static PyTypeObject CDataOwningGC_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__CDataOwnGC",
- sizeof(CDataObject_own_structptr),
- 0,
- (destructor)cdataowninggc_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)cdataowninggc_repr, /* tp_repr */
- 0, /* inherited */ /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* inherited */ /* tp_as_mapping */
- 0, /* inherited */ /* tp_hash */
- 0, /* inherited */ /* tp_call */
- 0, /* tp_str */
- 0, /* inherited */ /* tp_getattro */
- 0, /* inherited */ /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
- | Py_TPFLAGS_HAVE_GC,
- "This is an internal subtype of _CDataBase for performance only on "
- "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
- (traverseproc)cdataowninggc_traverse, /* tp_traverse */
- (inquiry)cdataowninggc_clear, /* tp_clear */
- 0, /* inherited */ /* tp_richcompare */
- 0, /* inherited */ /* tp_weaklistoffset */
- 0, /* inherited */ /* tp_iter */
- 0, /* tp_iternext */
- 0, /* inherited */ /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &CDataOwning_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-static PyTypeObject CDataFromBuf_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__CDataFromBuf",
- sizeof(CDataObject_frombuf),
- 0,
- (destructor)cdatafrombuf_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)cdatafrombuf_repr, /* tp_repr */
- 0, /* inherited */ /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* inherited */ /* tp_as_mapping */
- 0, /* inherited */ /* tp_hash */
- 0, /* inherited */ /* tp_call */
- 0, /* tp_str */
- 0, /* inherited */ /* tp_getattro */
- 0, /* inherited */ /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
- | Py_TPFLAGS_HAVE_GC,
- "This is an internal subtype of _CDataBase for performance only on "
- "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
- (traverseproc)cdatafrombuf_traverse, /* tp_traverse */
- (inquiry)cdatafrombuf_clear, /* tp_clear */
- 0, /* inherited */ /* tp_richcompare */
- 0, /* inherited */ /* tp_weaklistoffset */
- 0, /* inherited */ /* tp_iter */
- 0, /* tp_iternext */
- 0, /* inherited */ /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &CData_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-static PyTypeObject CDataGCP_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__CDataGCP",
- sizeof(CDataObject_gcp),
- 0,
- (destructor)cdatagcp_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* inherited */ /* tp_repr */
- 0, /* inherited */ /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* inherited */ /* tp_as_mapping */
- 0, /* inherited */ /* tp_hash */
- 0, /* inherited */ /* tp_call */
- 0, /* tp_str */
- 0, /* inherited */ /* tp_getattro */
- 0, /* inherited */ /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
-#ifdef Py_TPFLAGS_HAVE_FINALIZE
- | Py_TPFLAGS_HAVE_FINALIZE
-#endif
- | Py_TPFLAGS_HAVE_GC,
- "This is an internal subtype of _CDataBase for performance only on "
- "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
- (traverseproc)cdatagcp_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* inherited */ /* tp_richcompare */
- 0, /* inherited */ /* tp_weaklistoffset */
- 0, /* inherited */ /* tp_iter */
- 0, /* tp_iternext */
- 0, /* inherited */ /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &CData_Type, /* tp_base */
-#ifdef Py_TPFLAGS_HAVE_FINALIZE /* CPython >= 3.4 */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- 0, /* inherited */ /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* version_tag */
- (destructor)cdatagcp_finalize, /* tp_finalize */
-#endif
-};
-
-/************************************************************/
-
-typedef struct {
- PyObject_HEAD
- char *di_next, *di_stop;
- CDataObject *di_object;
- CTypeDescrObject *di_itemtype;
-} CDataIterObject;
-
-static PyObject *
-cdataiter_next(CDataIterObject *it)
-{
- char *result = it->di_next;
- if (result != it->di_stop) {
- it->di_next = result + it->di_itemtype->ct_size;
- return convert_to_object(result, it->di_itemtype);
- }
- return NULL;
-}
-
-static void
-cdataiter_dealloc(CDataIterObject *it)
-{
- Py_DECREF(it->di_object);
- PyObject_Del(it);
-}
-
-static PyTypeObject CDataIter_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__CData_iterator", /* tp_name */
- sizeof(CDataIterObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)cdataiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)cdataiter_next, /* tp_iternext */
-};
-
-static PyObject *
-cdata_iter(CDataObject *cd)
-{
- CDataIterObject *it;
-
- if (!(cd->c_type->ct_flags & CT_ARRAY)) {
- PyErr_Format(PyExc_TypeError, "cdata '%s' does not support iteration",
- cd->c_type->ct_name);
- return NULL;
- }
-
- it = PyObject_New(CDataIterObject, &CDataIter_Type);
- if (it == NULL)
- return NULL;
-
- Py_INCREF(cd);
- it->di_object = cd;
- it->di_itemtype = cd->c_type->ct_itemdescr;
- it->di_next = cd->c_data;
- it->di_stop = cd->c_data + get_array_length(cd) * it->di_itemtype->ct_size;
- return (PyObject *)it;
-}
-
-/************************************************************/
-
-static CDataObject *allocate_owning_object(Py_ssize_t size,
- CTypeDescrObject *ct,
- int dont_clear)
-{
- /* note: objects with &CDataOwning_Type are always allocated with
- either a plain malloc() or calloc(), and freed with free(). */
- CDataObject *cd;
- if (dont_clear)
- cd = malloc(size);
- else
- cd = calloc(size, 1);
- if (PyObject_Init((PyObject *)cd, &CDataOwning_Type) == NULL)
- return NULL;
-
- Py_INCREF(ct);
- cd->c_type = ct;
- cd->c_weakreflist = NULL;
- return cd;
-}
-
-static PyObject *
-convert_struct_to_owning_object(char *data, CTypeDescrObject *ct)
-{
- /* also accepts unions, for the API mode */
- CDataObject *cd;
- Py_ssize_t dataoffset = offsetof(CDataObject_own_nolength, alignment);
- Py_ssize_t datasize = ct->ct_size;
-
- if (datasize < 0) {
- PyErr_SetString(PyExc_TypeError,
- "return type is an opaque structure or union");
- return NULL;
- }
- if (ct->ct_flags & CT_WITH_VAR_ARRAY) {
- PyErr_SetString(PyExc_TypeError,
- "return type is a struct/union with a varsize array member");
- return NULL;
- }
- cd = allocate_owning_object(dataoffset + datasize, ct, /*dont_clear=*/1);
- if (cd == NULL)
- return NULL;
- cd->c_data = ((char *)cd) + dataoffset;
-
- memcpy(cd->c_data, data, datasize);
- return (PyObject *)cd;
-}
-
-static CDataObject *allocate_gcp_object(CDataObject *origobj,
- CTypeDescrObject *ct,
- PyObject *destructor)
-{
- CDataObject_gcp *cd = PyObject_GC_New(CDataObject_gcp, &CDataGCP_Type);
- if (cd == NULL)
- return NULL;
-
- Py_XINCREF(destructor);
- Py_INCREF(origobj);
- Py_INCREF(ct);
- cd->head.c_data = origobj->c_data;
- cd->head.c_type = ct;
- cd->head.c_weakreflist = NULL;
- cd->origobj = (PyObject *)origobj;
- cd->destructor = destructor;
-
- PyObject_GC_Track(cd);
- return (CDataObject *)cd;
-}
-
-static CDataObject *allocate_with_allocator(Py_ssize_t basesize,
- Py_ssize_t datasize,
- CTypeDescrObject *ct,
- const cffi_allocator_t *allocator)
-{
- CDataObject *cd;
-
- if (allocator->ca_alloc == NULL) {
- cd = allocate_owning_object(basesize + datasize, ct,
- allocator->ca_dont_clear);
- if (cd == NULL)
- return NULL;
- cd->c_data = ((char *)cd) + basesize;
- }
- else {
- PyObject *res = PyObject_CallFunction(allocator->ca_alloc, "n", datasize);
- if (res == NULL)
- return NULL;
-
- if (!CData_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "alloc() must return a cdata object (got %.200s)",
- Py_TYPE(res)->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- cd = (CDataObject *)res;
- if (!(cd->c_type->ct_flags & (CT_POINTER|CT_ARRAY))) {
- PyErr_Format(PyExc_TypeError,
- "alloc() must return a cdata pointer, not '%s'",
- cd->c_type->ct_name);
- Py_DECREF(res);
- return NULL;
- }
- if (!cd->c_data) {
- PyErr_SetString(PyExc_MemoryError, "alloc() returned NULL");
- Py_DECREF(res);
- return NULL;
- }
-
- cd = allocate_gcp_object(cd, ct, allocator->ca_free);
- Py_DECREF(res);
- if (!allocator->ca_dont_clear)
- memset(cd->c_data, 0, datasize);
- }
- return cd;
-}
-
-static PyObject *direct_newp(CTypeDescrObject *ct, PyObject *init,
- const cffi_allocator_t *allocator)
-{
- CTypeDescrObject *ctitem;
- CDataObject *cd;
- Py_ssize_t dataoffset, datasize, explicitlength;
-
- explicitlength = -1;
- if (ct->ct_flags & CT_POINTER) {
- dataoffset = offsetof(CDataObject_own_nolength, alignment);
- ctitem = ct->ct_itemdescr;
- datasize = ctitem->ct_size;
- if (datasize < 0) {
- PyErr_Format(PyExc_TypeError,
- "cannot instantiate ctype '%s' of unknown size",
- ctitem->ct_name);
- return NULL;
- }
- if (ctitem->ct_flags & CT_PRIMITIVE_CHAR)
- datasize *= 2; /* forcefully add another character: a null */
-
- if (ctitem->ct_flags & (CT_STRUCT | CT_UNION)) {
- if (force_lazy_struct(ctitem) < 0) /* for CT_WITH_VAR_ARRAY */
- return NULL;
-
- if (ctitem->ct_flags & CT_WITH_VAR_ARRAY) {
- assert(ct->ct_flags & CT_IS_PTR_TO_OWNED);
- dataoffset = offsetof(CDataObject_own_length, alignment);
-
- if (init != Py_None) {
- Py_ssize_t optvarsize = datasize;
- if (convert_struct_from_object(NULL, ctitem, init,
- &optvarsize) < 0)
- return NULL;
- datasize = optvarsize;
- }
- }
- }
- }
- else if (ct->ct_flags & CT_ARRAY) {
- dataoffset = offsetof(CDataObject_own_nolength, alignment);
- datasize = ct->ct_size;
- if (datasize < 0) {
- explicitlength = get_new_array_length(ct->ct_itemdescr, &init);
- if (explicitlength < 0)
- return NULL;
- ctitem = ct->ct_itemdescr;
- dataoffset = offsetof(CDataObject_own_length, alignment);
- datasize = MUL_WRAPAROUND(explicitlength, ctitem->ct_size);
- if (explicitlength > 0 &&
- (datasize / explicitlength) != ctitem->ct_size) {
- PyErr_SetString(PyExc_OverflowError,
- "array size would overflow a Py_ssize_t");
- return NULL;
- }
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "expected a pointer or array ctype, got '%s'",
- ct->ct_name);
- return NULL;
- }
-
- if (ct->ct_flags & CT_IS_PTR_TO_OWNED) {
- /* common case of ptr-to-struct (or ptr-to-union): for this case
- we build two objects instead of one, with the memory-owning
- one being really the struct (or union) and the returned one
- having a strong reference to it */
- CDataObject *cds;
-
- cds = allocate_with_allocator(dataoffset, datasize, ct->ct_itemdescr,
- allocator);
- if (cds == NULL)
- return NULL;
-
- cd = allocate_owning_object(sizeof(CDataObject_own_structptr), ct,
- /*dont_clear=*/1);
- if (cd == NULL) {
- Py_DECREF(cds);
- return NULL;
- }
- /* store the only reference to cds into cd */
- ((CDataObject_own_structptr *)cd)->structobj = (PyObject *)cds;
- /* store information about the allocated size of the struct */
- if (dataoffset == offsetof(CDataObject_own_length, alignment)) {
- ((CDataObject_own_length *)cds)->length = datasize;
- }
- assert(explicitlength < 0);
-
- cd->c_data = cds->c_data;
- }
- else {
- cd = allocate_with_allocator(dataoffset, datasize, ct, allocator);
- if (cd == NULL)
- return NULL;
-
- if (explicitlength >= 0)
- ((CDataObject_own_length*)cd)->length = explicitlength;
- }
-
- if (init != Py_None) {
- if (convert_from_object(cd->c_data,
- (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct, init) < 0) {
- Py_DECREF(cd);
- return NULL;
- }
- }
- return (PyObject *)cd;
-}
-
-static PyObject *b_newp(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *init = Py_None;
- if (!PyArg_ParseTuple(args, "O!|O:newp", &CTypeDescr_Type, &ct, &init))
- return NULL;
- return direct_newp(ct, init, &default_allocator);
-}
-
-static int
-_my_PyObject_AsBool(PyObject *ob)
-{
- /* convert and cast a Python object to a boolean. Accept an integer
- or a float object, up to a CData 'long double'. */
- PyObject *io;
- PyNumberMethods *nb;
- int res;
-
-#if PY_MAJOR_VERSION < 3
- if (PyInt_Check(ob)) {
- return PyInt_AS_LONG(ob) != 0;
- }
- else
-#endif
- if (PyLong_Check(ob)) {
- return _PyLong_Sign(ob) != 0;
- }
- else if (PyFloat_Check(ob)) {
- return PyFloat_AS_DOUBLE(ob) != 0.0;
- }
- else if (CData_Check(ob)) {
- CDataObject *cd = (CDataObject *)ob;
- if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
- /*READ(cd->c_data, cd->c_type->ct_size)*/
- if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE) {
- /* 'long double' objects: return the answer directly */
- return read_raw_longdouble_data(cd->c_data) != 0.0;
- }
- else {
- /* 'float'/'double' objects: return the answer directly */
- return read_raw_float_data(cd->c_data,
- cd->c_type->ct_size) != 0.0;
- }
- }
- }
- nb = ob->ob_type->tp_as_number;
- if (nb == NULL || (nb->nb_float == NULL && nb->nb_int == NULL)) {
- PyErr_SetString(PyExc_TypeError, "integer/float expected");
- return -1;
- }
- if (nb->nb_float && !CData_Check(ob))
- io = (*nb->nb_float) (ob);
- else
- io = (*nb->nb_int) (ob);
- if (io == NULL)
- return -1;
-
- if (PyIntOrLong_Check(io) || PyFloat_Check(io)) {
- res = _my_PyObject_AsBool(io);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "integer/float conversion failed");
- res = -1;
- }
- Py_DECREF(io);
- return res;
-}
-
-static CDataObject *_new_casted_primitive(CTypeDescrObject *ct)
-{
- int dataoffset = offsetof(CDataObject_casted_primitive, alignment);
- CDataObject *cd = (CDataObject *)PyObject_Malloc(dataoffset + ct->ct_size);
- if (PyObject_Init((PyObject *)cd, &CData_Type) == NULL)
- return NULL;
- Py_INCREF(ct);
- cd->c_type = ct;
- cd->c_data = ((char*)cd) + dataoffset;
- cd->c_weakreflist = NULL;
- return cd;
-}
-
-static CDataObject *cast_to_integer_or_char(CTypeDescrObject *ct, PyObject *ob)
-{
- unsigned PY_LONG_LONG value;
- CDataObject *cd;
-
- if (CData_Check(ob) &&
- ((CDataObject *)ob)->c_type->ct_flags &
- (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) {
- value = (Py_intptr_t)((CDataObject *)ob)->c_data;
- }
-#if PY_MAJOR_VERSION < 3
- else if (PyString_Check(ob)) {
- if (PyString_GET_SIZE(ob) != 1) {
- PyErr_Format(PyExc_TypeError,
- "cannot cast string of length %zd to ctype '%s'",
- PyString_GET_SIZE(ob), ct->ct_name);
- return NULL;
- }
- value = (unsigned char)PyString_AS_STRING(ob)[0];
- }
-#endif
- else if (PyUnicode_Check(ob)) {
- char err_buf[80];
- cffi_char32_t ordinal;
- if (_my_PyUnicode_AsSingleChar32(ob, &ordinal, err_buf) < 0) {
- PyErr_Format(PyExc_TypeError,
- "cannot cast %s to ctype '%s'", err_buf, ct->ct_name);
- return NULL;
- }
- /* the types char16_t and char32_t are both unsigned. However,
- wchar_t might be signed. In theory it does not matter,
- because 'ordinal' comes from a regular Python unicode. */
-#ifdef HAVE_WCHAR_H
- if (ct->ct_flags & CT_IS_SIGNED_WCHAR)
- value = (wchar_t)ordinal;
- else
-#endif
- value = ordinal;
- }
- else if (PyBytes_Check(ob)) {
- int res = _convert_to_char(ob);
- if (res < 0)
- return NULL;
- value = (unsigned char)res;
- }
- else if (ct->ct_flags & CT_IS_BOOL) {
- int res = _my_PyObject_AsBool(ob);
- if (res < 0)
- return NULL;
- value = res;
- }
- else {
- value = _my_PyLong_AsUnsignedLongLong(ob, 0);
- if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
- return NULL;
- }
- if (ct->ct_flags & CT_IS_BOOL)
- value = !!value;
- cd = _new_casted_primitive(ct);
- if (cd != NULL)
- write_raw_integer_data(cd->c_data, value, ct->ct_size);
- return cd;
-}
-
-/* returns -1 if cannot cast, 0 if we don't get a value, 1 if we do */
-static int check_bytes_for_float_compatible(PyObject *io, double *out_value)
-{
- if (PyBytes_Check(io)) {
- if (PyBytes_GET_SIZE(io) != 1)
- goto error;
- *out_value = (unsigned char)PyBytes_AS_STRING(io)[0];
- return 1;
- }
- else if (PyUnicode_Check(io)) {
- char ignored[80];
- cffi_char32_t ordinal;
- if (_my_PyUnicode_AsSingleChar32(io, &ordinal, ignored) < 0)
- goto error;
- /* the signness of the 32-bit version of wide chars should not
- * matter here, because 'ordinal' comes from a normal Python
- * unicode string */
- *out_value = ordinal;
- return 1;
- }
- *out_value = 0; /* silence a gcc warning if this function is inlined */
- return 0;
-
- error:
- Py_DECREF(io);
- *out_value = 0; /* silence a gcc warning if this function is inlined */
- return -1;
-}
-
-static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob)
-{
- CDataObject *cd;
-
- if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY) &&
- ct->ct_size >= 0) {
- /* cast to a pointer, to a funcptr, or to an array.
- Note that casting to an array is an extension to the C language,
- which seems to be necessary in order to sanely get a
- <cdata 'int[3]'> at some address. */
- unsigned PY_LONG_LONG value;
-
- if (CData_Check(ob)) {
- CDataObject *cdsrc = (CDataObject *)ob;
- if (cdsrc->c_type->ct_flags &
- (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) {
- return new_simple_cdata(cdsrc->c_data, ct);
- }
- }
- if ((ct->ct_flags & CT_POINTER) &&
- (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
- PyFile_Check(ob)) {
- FILE *f = PyFile_AsFile(ob);
- if (f == NULL && PyErr_Occurred())
- return NULL;
- return new_simple_cdata((char *)f, ct);
- }
- value = _my_PyLong_AsUnsignedLongLong(ob, 0);
- if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
- return NULL;
- return new_simple_cdata((char *)(Py_intptr_t)value, ct);
- }
- else if (ct->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED
- |CT_PRIMITIVE_CHAR)) {
- /* cast to an integer type or a char */
- return (PyObject *)cast_to_integer_or_char(ct, ob);
- }
- else if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
- /* cast to a float */
- double value;
- PyObject *io;
- int res;
-
- if (CData_Check(ob)) {
- CDataObject *cdsrc = (CDataObject *)ob;
-
- if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY))
- goto cannot_cast;
- io = convert_to_object(cdsrc->c_data, cdsrc->c_type);
- if (io == NULL)
- return NULL;
- }
- else {
- io = ob;
- Py_INCREF(io);
- }
-
- res = check_bytes_for_float_compatible(io, &value);
- if (res == -1)
- goto cannot_cast;
- if (res == 0) {
- if ((ct->ct_flags & CT_IS_LONGDOUBLE) &&
- CData_Check(io) &&
- (((CDataObject *)io)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
- long double lvalue;
- char *data = ((CDataObject *)io)->c_data;
- /*READ(data, sizeof(long double)*/
- lvalue = read_raw_longdouble_data(data);
- Py_DECREF(io);
- cd = _new_casted_primitive(ct);
- if (cd != NULL)
- write_raw_longdouble_data(cd->c_data, lvalue);
- return (PyObject *)cd;
- }
- value = PyFloat_AsDouble(io);
- }
- Py_DECREF(io);
- if (value == -1.0 && PyErr_Occurred())
- return NULL;
-
- cd = _new_casted_primitive(ct);
- if (cd != NULL) {
- if (!(ct->ct_flags & CT_IS_LONGDOUBLE))
- write_raw_float_data(cd->c_data, value, ct->ct_size);
- else
- write_raw_longdouble_data(cd->c_data, (long double)value);
- }
- return (PyObject *)cd;
- }
- else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
- /* cast to a complex */
- Py_complex value;
- PyObject *io;
- int res;
-
- if (CData_Check(ob)) {
- CDataObject *cdsrc = (CDataObject *)ob;
-
- if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY))
- goto cannot_cast;
- io = convert_to_object(cdsrc->c_data, cdsrc->c_type);
- if (io == NULL)
- return NULL;
- }
- else {
- io = ob;
- Py_INCREF(io);
- }
-
- res = check_bytes_for_float_compatible(io, &value.real);
- if (res == -1)
- goto cannot_cast;
- if (res == 1) {
- // got it from string
- value.imag = 0.0;
- } else {
- value = PyComplex_AsCComplex(io);
- }
- Py_DECREF(io);
- if (PyErr_Occurred()) {
- return NULL;
- }
- cd = _new_casted_primitive(ct);
- if (cd != NULL) {
- write_raw_complex_data(cd->c_data, value, ct->ct_size);
- }
- return (PyObject *)cd;
- }
- else {
- PyErr_Format(PyExc_TypeError, "cannot cast to ctype '%s'",
- ct->ct_name);
- return NULL;
- }
-
- cannot_cast:
- if (CData_Check(ob))
- PyErr_Format(PyExc_TypeError, "cannot cast ctype '%s' to ctype '%s'",
- ((CDataObject *)ob)->c_type->ct_name, ct->ct_name);
- else
- PyErr_Format(PyExc_TypeError,
- "cannot cast %.200s object to ctype '%s'",
- Py_TYPE(ob)->tp_name, ct->ct_name);
- return NULL;
-}
-
-static PyObject *b_cast(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *ob;
- if (!PyArg_ParseTuple(args, "O!O:cast", &CTypeDescr_Type, &ct, &ob))
- return NULL;
-
- return do_cast(ct, ob);
-}
-
-/************************************************************/
-
-typedef struct {
- PyObject_HEAD
- void *dl_handle;
- char *dl_name;
- int dl_auto_close;
-} DynLibObject;
-
-static void dl_dealloc(DynLibObject *dlobj)
-{
- if (dlobj->dl_handle != NULL && dlobj->dl_auto_close)
- dlclose(dlobj->dl_handle);
- free(dlobj->dl_name);
- PyObject_Del(dlobj);
-}
-
-static PyObject *dl_repr(DynLibObject *dlobj)
-{
- return PyText_FromFormat("<clibrary '%s'>", dlobj->dl_name);
-}
-
-static int dl_check_closed(DynLibObject *dlobj)
-{
- if (dlobj->dl_handle == NULL)
- {
- PyErr_Format(PyExc_ValueError, "library '%s' has already been closed",
- dlobj->dl_name);
- return -1;
- }
- return 0;
-}
-
-static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args)
-{
- CTypeDescrObject *ct;
- char *funcname;
- void *funcptr;
-
- if (!PyArg_ParseTuple(args, "O!s:load_function",
- &CTypeDescr_Type, &ct, &funcname))
- return NULL;
-
- if (dl_check_closed(dlobj) < 0)
- return NULL;
-
- if (!(ct->ct_flags & (CT_FUNCTIONPTR | CT_POINTER | CT_ARRAY))) {
- PyErr_Format(PyExc_TypeError,
- "function or pointer or array cdata expected, got '%s'",
- ct->ct_name);
- return NULL;
- }
- dlerror(); /* clear error condition */
- funcptr = dlsym(dlobj->dl_handle, funcname);
- if (funcptr == NULL) {
- const char *error = dlerror();
- PyErr_Format(PyExc_AttributeError,
- "function/symbol '%s' not found in library '%s': %s",
- funcname, dlobj->dl_name, error);
- return NULL;
- }
-
- if ((ct->ct_flags & CT_ARRAY) && ct->ct_length < 0) {
- ct = (CTypeDescrObject *)ct->ct_stuff;
- }
- return new_simple_cdata(funcptr, ct);
-}
-
-static PyObject *dl_read_variable(DynLibObject *dlobj, PyObject *args)
-{
- CTypeDescrObject *ct;
- char *varname;
- char *data;
-
- if (!PyArg_ParseTuple(args, "O!s:read_variable",
- &CTypeDescr_Type, &ct, &varname))
- return NULL;
-
- if (dl_check_closed(dlobj) < 0)
- return NULL;
-
- dlerror(); /* clear error condition */
- data = dlsym(dlobj->dl_handle, varname);
- if (data == NULL) {
- const char *error = dlerror();
- if (error != NULL) {
- PyErr_Format(PyExc_KeyError,
- "variable '%s' not found in library '%s': %s",
- varname, dlobj->dl_name, error);
- return NULL;
- }
- }
- return convert_to_object(data, ct);
-}
-
-static PyObject *dl_write_variable(DynLibObject *dlobj, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *value;
- char *varname;
- char *data;
-
- if (!PyArg_ParseTuple(args, "O!sO:write_variable",
- &CTypeDescr_Type, &ct, &varname, &value))
- return NULL;
-
- if (dl_check_closed(dlobj) < 0)
- return NULL;
-
- dlerror(); /* clear error condition */
- data = dlsym(dlobj->dl_handle, varname);
- if (data == NULL) {
- const char *error = dlerror();
- PyErr_Format(PyExc_KeyError,
- "variable '%s' not found in library '%s': %s",
- varname, dlobj->dl_name, error);
- return NULL;
- }
- if (convert_from_object(data, ct, value) < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *dl_close_lib(DynLibObject *dlobj, PyObject *no_args)
-{
- if (dlobj->dl_handle != NULL)
- {
- dlclose(dlobj->dl_handle);
- dlobj->dl_handle = NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef dl_methods[] = {
- {"load_function", (PyCFunction)dl_load_function, METH_VARARGS},
- {"read_variable", (PyCFunction)dl_read_variable, METH_VARARGS},
- {"write_variable", (PyCFunction)dl_write_variable, METH_VARARGS},
- {"close_lib", (PyCFunction)dl_close_lib, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject dl_type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.CLibrary", /* tp_name */
- sizeof(DynLibObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)dl_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)dl_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- dl_methods, /* tp_methods */
-};
-
-static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
- PyObject **p_temp, int *auto_close)
-{
- /* Logic to call the correct version of dlopen(). Returns NULL in case of error.
- Otherwise, '*p_printable_filename' will point to a printable char version of
- the filename (maybe utf-8-encoded). '*p_temp' will be set either to NULL or
- to a temporary object that must be freed after looking at printable_filename.
- */
- void *handle;
- char *filename_or_null;
- int flags = 0;
- *p_temp = NULL;
- *auto_close = 1;
-
- if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) {
- PyObject *dummy;
- if (!PyArg_ParseTuple(args, "|Oi:load_library",
- &dummy, &flags))
- return NULL;
- filename_or_null = NULL;
- *p_printable_filename = "<None>";
- }
- else if (CData_Check(PyTuple_GET_ITEM(args, 0)))
- {
- CDataObject *cd;
- if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags))
- return NULL;
- /* 'flags' is accepted but ignored in this case */
- if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) {
- PyErr_Format(PyExc_TypeError,
- "dlopen() takes a file name or 'void *' handle, not '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- handle = cd->c_data;
- if (handle == NULL) {
- PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)");
- return NULL;
- }
- *p_temp = PyText_FromFormat("%p", handle);
- *p_printable_filename = PyText_AsUTF8(*p_temp);
- *auto_close = 0;
- return handle;
- }
- else
- {
- PyObject *s = PyTuple_GET_ITEM(args, 0);
-#ifdef MS_WIN32
- PyObject *filename_unicode;
- if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
- {
- Py_ssize_t sz1;
- wchar_t *w1;
-#if PY_MAJOR_VERSION < 3
- s = PyUnicode_AsUTF8String(s);
- if (s == NULL)
- return NULL;
- *p_temp = s;
-#endif
- *p_printable_filename = PyText_AsUTF8(s);
- if (*p_printable_filename == NULL)
- return NULL;
-
- sz1 = PyUnicode_GetSize(filename_unicode) + 1;
- sz1 *= 2; /* should not be needed, but you never know */
- w1 = alloca(sizeof(wchar_t) * sz1);
- sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode,
- w1, sz1 - 1);
- if (sz1 < 0)
- return NULL;
- w1[sz1] = 0;
- handle = dlopenW(w1);
- goto got_handle;
- }
- PyErr_Clear();
-#endif
- if (!PyArg_ParseTuple(args, "et|i:load_library",
- Py_FileSystemDefaultEncoding, &filename_or_null, &flags))
- return NULL;
-#if PY_MAJOR_VERSION < 3
- if (PyUnicode_Check(s))
- {
- s = PyUnicode_AsUTF8String(s);
- if (s == NULL) {
- PyMem_Free(filename_or_null);
- return NULL;
- }
- *p_temp = s;
- }
-#endif
- *p_printable_filename = PyText_AsUTF8(s);
- if (*p_printable_filename == NULL) {
- PyMem_Free(filename_or_null);
- return NULL;
- }
- }
- if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
- flags |= RTLD_NOW;
-
-#ifdef MS_WIN32
- if (filename_or_null == NULL) {
- PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows");
- return NULL;
- }
-#endif
-
- handle = dlopen(filename_or_null, flags);
- PyMem_Free(filename_or_null);
-
-#ifdef MS_WIN32
- got_handle:
-#endif
- if (handle == NULL) {
- const char *error = dlerror();
- PyErr_Format(PyExc_OSError, "cannot load library '%s': %s",
- *p_printable_filename, error);
- return NULL;
- }
- return handle;
-}
-
-static PyObject *b_load_library(PyObject *self, PyObject *args)
-{
- const char *printable_filename;
- PyObject *temp;
- void *handle;
- DynLibObject *dlobj = NULL;
- int auto_close;
-
- handle = b_do_dlopen(args, &printable_filename, &temp, &auto_close);
- if (handle == NULL)
- goto error;
-
- dlobj = PyObject_New(DynLibObject, &dl_type);
- if (dlobj == NULL) {
- dlclose(handle);
- goto error;
- }
- dlobj->dl_handle = handle;
- dlobj->dl_name = strdup(printable_filename);
- dlobj->dl_auto_close = auto_close;
-
- error:
- Py_XDECREF(temp);
- return (PyObject *)dlobj;
-}
-
-/************************************************************/
-
-static PyObject *get_unique_type(CTypeDescrObject *x,
- const void *unique_key[], long keylength)
-{
- /* Replace the CTypeDescrObject 'x' with a standardized one.
- This either just returns x, or x is decrefed and a new reference
- to the already-existing equivalent is returned.
-
- In this function, 'x' always contains a reference that must be
- either decrefed or returned.
-
- Keys:
- void ["void"]
- primitive [&static_struct]
- pointer [ctype]
- array [ctype, length]
- funcptr [ctresult, ellipsis+abi, num_args, ctargs...]
- */
- PyObject *key, *y;
- void *pkey;
-
- key = PyBytes_FromStringAndSize(NULL, keylength * sizeof(void *));
- if (key == NULL)
- goto error;
-
- pkey = PyBytes_AS_STRING(key);
- memcpy(pkey, unique_key, keylength * sizeof(void *));
-
- y = PyDict_GetItem(unique_cache, key);
- if (y != NULL) {
- Py_DECREF(key);
- Py_INCREF(y);
- Py_DECREF(x);
- return y;
- }
- if (PyDict_SetItem(unique_cache, key, (PyObject *)x) < 0) {
- Py_DECREF(key);
- goto error;
- }
- /* Haaaack for our reference count hack: gcmodule.c must not see this
- dictionary. The problem is that any PyDict_SetItem() notices that
- 'x' is tracked and re-tracks the unique_cache dictionary. So here
- we re-untrack it again... */
- PyObject_GC_UnTrack(unique_cache);
-
- assert(x->ct_unique_key == NULL);
- x->ct_unique_key = key; /* the key will be freed in ctypedescr_dealloc() */
- /* the 'value' in unique_cache doesn't count as 1, but don't use
- Py_DECREF(x) here because it will confuse debug builds into thinking
- there was an extra DECREF in total. */
- ((PyObject *)x)->ob_refcnt--;
- return (PyObject *)x;
-
- error:
- Py_DECREF(x);
- return NULL;
-}
-
-/* according to the C standard, these types should be equivalent to the
- _Complex types for the purposes of storage (not arguments in calls!) */
-typedef float cffi_float_complex_t[2];
-typedef double cffi_double_complex_t[2];
-
-static PyObject *new_primitive_type(const char *name)
-{
-#define ENUM_PRIMITIVE_TYPES \
- EPTYPE(c, char, CT_PRIMITIVE_CHAR) \
- EPTYPE(s, short, CT_PRIMITIVE_SIGNED ) \
- EPTYPE(i, int, CT_PRIMITIVE_SIGNED ) \
- EPTYPE(l, long, CT_PRIMITIVE_SIGNED ) \
- EPTYPE(ll, long long, CT_PRIMITIVE_SIGNED ) \
- EPTYPE(sc, signed char, CT_PRIMITIVE_SIGNED ) \
- EPTYPE(uc, unsigned char, CT_PRIMITIVE_UNSIGNED ) \
- EPTYPE(us, unsigned short, CT_PRIMITIVE_UNSIGNED ) \
- EPTYPE(ui, unsigned int, CT_PRIMITIVE_UNSIGNED ) \
- EPTYPE(ul, unsigned long, CT_PRIMITIVE_UNSIGNED ) \
- EPTYPE(ull, unsigned long long, CT_PRIMITIVE_UNSIGNED ) \
- EPTYPE(f, float, CT_PRIMITIVE_FLOAT ) \
- EPTYPE(d, double, CT_PRIMITIVE_FLOAT ) \
- EPTYPE(ld, long double, CT_PRIMITIVE_FLOAT | CT_IS_LONGDOUBLE ) \
- EPTYPE2(fc, "float _Complex", cffi_float_complex_t, CT_PRIMITIVE_COMPLEX ) \
- EPTYPE2(dc, "double _Complex", cffi_double_complex_t, CT_PRIMITIVE_COMPLEX ) \
- ENUM_PRIMITIVE_TYPES_WCHAR \
- EPTYPE2(c16, "char16_t", cffi_char16_t, CT_PRIMITIVE_CHAR ) \
- EPTYPE2(c32, "char32_t", cffi_char32_t, CT_PRIMITIVE_CHAR ) \
- EPTYPE(b, _Bool, CT_PRIMITIVE_UNSIGNED | CT_IS_BOOL ) \
- /* the following types are not primitive in the C sense */ \
- EPTYPE(i8, int8_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(u8, uint8_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(i16, int16_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(u16, uint16_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(i32, int32_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(u32, uint32_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(i64, int64_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(u64, uint64_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(il8, int_least8_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(ul8, uint_least8_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(il16, int_least16_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(ul16, uint_least16_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(il32, int_least32_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(ul32, uint_least32_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(il64, int_least64_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(ul64, uint_least64_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(if8, int_fast8_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(uf8, uint_fast8_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(if16, int_fast16_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(uf16, uint_fast16_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(if32, int_fast32_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(uf32, uint_fast32_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(if64, int_fast64_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(uf64, uint_fast64_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(ip, intptr_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(up, uintptr_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(im, intmax_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(um, uintmax_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE(pd, ptrdiff_t, CT_PRIMITIVE_SIGNED) \
- EPTYPE(sz, size_t, CT_PRIMITIVE_UNSIGNED) \
- EPTYPE2(ssz, "ssize_t", Py_ssize_t, CT_PRIMITIVE_SIGNED)
-
-#ifdef HAVE_WCHAR_H
-# define ENUM_PRIMITIVE_TYPES_WCHAR \
- EPTYPE(wc, wchar_t, CT_PRIMITIVE_CHAR | \
- (((wchar_t)-1) > 0 ? 0 : CT_IS_SIGNED_WCHAR))
-#else
-# define ENUM_PRIMITIVE_TYPES_WCHAR /* nothing */
-#endif
-
-#define EPTYPE(code, typename, flags) EPTYPE2(code, #typename, typename, flags)
-
-#define EPTYPE2(code, export_name, typename, flags) \
- struct aligncheck_##code { char x; typename y; };
- ENUM_PRIMITIVE_TYPES
-#undef EPTYPE2
-
- CTypeDescrObject *td;
- static const struct descr_s { const char *name; int size, align, flags; }
- types[] = {
-#define EPTYPE2(code, export_name, typename, flags) \
- { export_name, \
- sizeof(typename), \
- offsetof(struct aligncheck_##code, y), \
- flags \
- },
- ENUM_PRIMITIVE_TYPES
-#undef EPTYPE2
-#undef EPTYPE
-#undef ENUM_PRIMITIVE_TYPES_WCHAR
-#undef ENUM_PRIMITIVE_TYPES
- { NULL }
- };
- const struct descr_s *ptypes;
- const void *unique_key[1];
- int name_size;
- ffi_type *ffitype;
-
- for (ptypes=types; ; ptypes++) {
- if (ptypes->name == NULL) {
-#ifndef HAVE_WCHAR_H
- if (strcmp(name, "wchar_t"))
- PyErr_SetString(PyExc_NotImplementedError, name);
- else
-#endif
- PyErr_SetString(PyExc_KeyError, name);
- return NULL;
- }
- if (strcmp(name, ptypes->name) == 0)
- break;
- }
-
- if (ptypes->flags & CT_PRIMITIVE_SIGNED) {
- switch (ptypes->size) {
- case 1: ffitype = &ffi_type_sint8; break;
- case 2: ffitype = &ffi_type_sint16; break;
- case 4: ffitype = &ffi_type_sint32; break;
- case 8: ffitype = &ffi_type_sint64; break;
- default: goto bad_ffi_type;
- }
- }
- else if (ptypes->flags & CT_PRIMITIVE_FLOAT) {
- if (strcmp(ptypes->name, "float") == 0)
- ffitype = &ffi_type_float;
- else if (strcmp(ptypes->name, "double") == 0)
- ffitype = &ffi_type_double;
- else if (strcmp(ptypes->name, "long double") == 0) {
- /* assume that if sizeof(double) == sizeof(long double), then
- the two types are equivalent for C. libffi bugs on Win64
- if a function's return type is ffi_type_longdouble... */
- if (sizeof(double) == sizeof(long double))
- ffitype = &ffi_type_double;
- else
- ffitype = &ffi_type_longdouble;
- }
- else
- goto bad_ffi_type;
- }
- else if (ptypes->flags & CT_PRIMITIVE_COMPLEX) {
- /* As of March 2017, still no libffi support for complex.
- It fails silently if we try to use ffi_type_complex_float
- or ffi_type_complex_double. Better not use it at all.
- */
- ffitype = NULL;
- }
- else {
- switch (ptypes->size) {
- case 1: ffitype = &ffi_type_uint8; break;
- case 2: ffitype = &ffi_type_uint16; break;
- case 4: ffitype = &ffi_type_uint32; break;
- case 8: ffitype = &ffi_type_uint64; break;
- default: goto bad_ffi_type;
- }
- }
-
- name_size = strlen(ptypes->name) + 1;
- td = ctypedescr_new(name_size);
- if (td == NULL)
- return NULL;
-
- memcpy(td->ct_name, name, name_size);
- td->ct_size = ptypes->size;
- td->ct_length = ptypes->align;
- td->ct_extra = ffitype;
- td->ct_flags = ptypes->flags;
- if (td->ct_flags & (CT_PRIMITIVE_SIGNED | CT_PRIMITIVE_CHAR)) {
- if (td->ct_size <= (Py_ssize_t)sizeof(long))
- td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
- }
- else if (td->ct_flags & CT_PRIMITIVE_UNSIGNED) {
- if (td->ct_size < (Py_ssize_t)sizeof(long))
- td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
- }
- td->ct_name_position = strlen(td->ct_name);
- unique_key[0] = ptypes;
- return get_unique_type(td, unique_key, 1);
-
- bad_ffi_type:
- PyErr_Format(PyExc_NotImplementedError,
- "primitive type '%s' has size %d; "
- "the supported sizes are 1, 2, 4, 8",
- name, (int)ptypes->size);
- return NULL;
-}
-
-static PyObject *b_new_primitive_type(PyObject *self, PyObject *args)
-{
- char *name;
- if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name))
- return NULL;
- return new_primitive_type(name);
-}
-
-static PyObject *new_pointer_type(CTypeDescrObject *ctitem)
-{
- CTypeDescrObject *td;
- const char *extra;
- const void *unique_key[1];
-
- if (ctitem->ct_flags & CT_ARRAY)
- extra = "(*)"; /* obscure case: see test_array_add */
- else
- extra = " *";
- td = ctypedescr_new_on_top(ctitem, extra, 2);
- if (td == NULL)
- return NULL;
-
- td->ct_size = sizeof(void *);
- td->ct_length = -1;
- td->ct_flags = CT_POINTER;
- if (ctitem->ct_flags & (CT_STRUCT|CT_UNION))
- td->ct_flags |= CT_IS_PTR_TO_OWNED;
- if (ctitem->ct_flags & CT_VOID)
- td->ct_flags |= CT_IS_VOID_PTR;
- if ((ctitem->ct_flags & CT_VOID) ||
- ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
- ctitem->ct_size == sizeof(char)))
- td->ct_flags |= CT_IS_VOIDCHAR_PTR; /* 'void *' or 'char *' only */
- unique_key[0] = ctitem;
- return get_unique_type(td, unique_key, 1);
-}
-
-static PyObject *b_new_pointer_type(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ctitem;
- if (!PyArg_ParseTuple(args, "O!:new_pointer_type",
- &CTypeDescr_Type, &ctitem))
- return NULL;
- return new_pointer_type(ctitem);
-}
-
-static PyObject *b_new_array_type(PyObject *self, PyObject *args)
-{
- PyObject *lengthobj;
- Py_ssize_t length;
- CTypeDescrObject *ctptr;
-
- if (!PyArg_ParseTuple(args, "O!O:new_array_type",
- &CTypeDescr_Type, &ctptr, &lengthobj))
- return NULL;
-
- if (lengthobj == Py_None) {
- length = -1;
- }
- else {
- length = PyNumber_AsSsize_t(lengthobj, PyExc_OverflowError);
- if (length < 0) {
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_ValueError, "negative array length");
- return NULL;
- }
- }
- return new_array_type(ctptr, length);
-}
-
-static PyObject *
-new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length)
-{
- CTypeDescrObject *td, *ctitem;
- char extra_text[32];
- Py_ssize_t arraysize;
- int flags = CT_ARRAY;
- const void *unique_key[2];
-
- if (!(ctptr->ct_flags & CT_POINTER)) {
- PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
- return NULL;
- }
- ctitem = ctptr->ct_itemdescr;
- if (ctitem->ct_size < 0) {
- PyErr_Format(PyExc_ValueError, "array item of unknown size: '%s'",
- ctitem->ct_name);
- return NULL;
- }
-
- if (length < 0) {
- sprintf(extra_text, "[]");
- length = -1;
- arraysize = -1;
- }
- else {
- sprintf(extra_text, "[%llu]", (unsigned PY_LONG_LONG)length);
- arraysize = MUL_WRAPAROUND(length, ctitem->ct_size);
- if (length > 0 && (arraysize / length) != ctitem->ct_size) {
- PyErr_SetString(PyExc_OverflowError,
- "array size would overflow a Py_ssize_t");
- return NULL;
- }
- }
- td = ctypedescr_new_on_top(ctitem, extra_text, 0);
- if (td == NULL)
- return NULL;
-
- Py_INCREF(ctptr);
- td->ct_stuff = (PyObject *)ctptr;
- td->ct_size = arraysize;
- td->ct_length = length;
- td->ct_flags = flags;
- unique_key[0] = ctptr;
- unique_key[1] = (void *)length;
- return get_unique_type(td, unique_key, 2);
-}
-
-static PyObject *new_void_type(void)
-{
- int name_size = strlen("void") + 1;
- const void *unique_key[1];
- CTypeDescrObject *td = ctypedescr_new(name_size);
- if (td == NULL)
- return NULL;
-
- memcpy(td->ct_name, "void", name_size);
- td->ct_size = -1;
- td->ct_flags = CT_VOID | CT_IS_OPAQUE;
- td->ct_name_position = strlen("void");
- unique_key[0] = "void";
- return get_unique_type(td, unique_key, 1);
-}
-
-static PyObject *b_new_void_type(PyObject *self, PyObject *args)
-{
- return new_void_type();
-}
-
-static PyObject *new_struct_or_union_type(const char *name, int flag)
-{
- int namelen = strlen(name);
- CTypeDescrObject *td = ctypedescr_new(namelen + 1);
- if (td == NULL)
- return NULL;
-
- td->ct_size = -1;
- td->ct_length = -1;
- td->ct_flags = flag | CT_IS_OPAQUE;
- td->ct_extra = NULL;
- memcpy(td->ct_name, name, namelen + 1);
- td->ct_name_position = namelen;
- return (PyObject *)td;
-}
-
-static PyObject *b_new_struct_type(PyObject *self, PyObject *args)
-{
- char *name;
- int flag;
- if (!PyArg_ParseTuple(args, "s:new_struct_type", &name))
- return NULL;
-
- flag = CT_STRUCT;
- if (strcmp(name, "struct _IO_FILE") == 0 || strcmp(name, "FILE") == 0)
- flag |= CT_IS_FILE;
- return new_struct_or_union_type(name, flag);
-}
-
-static PyObject *b_new_union_type(PyObject *self, PyObject *args)
-{
- char *name;
- if (!PyArg_ParseTuple(args, "s:new_union_type", &name))
- return NULL;
- return new_struct_or_union_type(name, CT_UNION);
-}
-
-static CFieldObject *
-_add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype,
- Py_ssize_t offset, int bitshift, int fbitsize, int flags)
-{
- int err;
- Py_ssize_t prev_size;
- CFieldObject *cf = PyObject_New(CFieldObject, &CField_Type);
- if (cf == NULL)
- return NULL;
-
- Py_INCREF(ftype);
- cf->cf_type = ftype;
- cf->cf_offset = offset;
- cf->cf_bitshift = bitshift;
- cf->cf_bitsize = fbitsize;
- cf->cf_flags = flags;
-
- Py_INCREF(fname);
- PyText_InternInPlace(&fname);
- prev_size = PyDict_Size(interned_fields);
- err = PyDict_SetItem(interned_fields, fname, (PyObject *)cf);
- Py_DECREF(fname);
- Py_DECREF(cf);
- if (err < 0)
- return NULL;
-
- if (PyDict_Size(interned_fields) != prev_size + 1) {
- PyErr_Format(PyExc_KeyError, "duplicate field name '%s'",
- PyText_AS_UTF8(fname));
- return NULL;
- }
- return cf; /* borrowed reference */
-}
-
-#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
-#define SF_STD_FIELD_POS 0x80
-
-#ifdef MS_WIN32
-# define SF_DEFAULT_PACKING 8
-#else
-# define SF_DEFAULT_PACKING 0x40000000 /* a huge power of two */
-#endif
-
-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
-# if defined(__APPLE__) && defined(__arm64__)
- sflags |= SF_GCC_X86_BITFIELDS;
-# elif defined(__arm__) || defined(__aarch64__)
- 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 int detect_custom_layout(CTypeDescrObject *ct, int sflags,
- Py_ssize_t cdef_value,
- Py_ssize_t compiler_value,
- const char *msg1, const char *txt,
- const char *msg2)
-{
- if (compiler_value != cdef_value) {
- if (sflags & SF_STD_FIELD_POS) {
- PyErr_Format(FFIError,
- "%s: %s%s%s (cdef says %zd, but C compiler says %zd)."
- " fix it or use \"...;\" as the last field in the "
- "cdef for %s to make it flexible",
- ct->ct_name, msg1, txt, msg2,
- cdef_value, compiler_value,
- ct->ct_name);
- return -1;
- }
- ct->ct_flags |= CT_CUSTOM_FIELD_POS;
- }
- return 0;
-}
-
-#define ROUNDUP_BYTES(bytes, bits) ((bytes) + ((bits) > 0))
-
-static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *fields, *interned_fields, *ignored;
- int is_union, alignment;
- Py_ssize_t byteoffset, i, nb_fields, byteoffsetmax, alignedsize;
- int bitoffset;
- Py_ssize_t byteoffsetorg;
- Py_ssize_t totalsize = -1;
- int totalalignment = -1;
- CFieldObject **previous;
- int prev_bitfield_size, prev_bitfield_free;
- int sflags = 0, fflags;
- int pack = 0;
-
- if (!PyArg_ParseTuple(args, "O!O!|Oniii:complete_struct_or_union",
- &CTypeDescr_Type, &ct,
- &PyList_Type, &fields,
- &ignored, &totalsize, &totalalignment, &sflags,
- &pack))
- return NULL;
-
- sflags = complete_sflags(sflags);
- if (sflags & SF_PACKED)
- pack = 1;
- else if (pack <= 0)
- pack = SF_DEFAULT_PACKING;
- else
- sflags |= SF_PACKED;
-
- if ((ct->ct_flags & (CT_STRUCT|CT_IS_OPAQUE)) ==
- (CT_STRUCT|CT_IS_OPAQUE)) {
- is_union = 0;
- }
- else if ((ct->ct_flags & (CT_UNION|CT_IS_OPAQUE)) ==
- (CT_UNION|CT_IS_OPAQUE)) {
- is_union = 1;
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "first arg must be a non-initialized struct or union ctype");
- return NULL;
- }
- ct->ct_flags &= ~(CT_CUSTOM_FIELD_POS | CT_WITH_PACKED_CHANGE);
-
- alignment = 1;
- byteoffset = 0; /* the real value is 'byteoffset+bitoffset*8', which */
- bitoffset = 0; /* counts the offset in bits */
- byteoffsetmax = 0; /* the maximum value of byteoffset-rounded-up-to-byte */
- prev_bitfield_size = 0;
- prev_bitfield_free = 0;
- nb_fields = PyList_GET_SIZE(fields);
- interned_fields = PyDict_New();
- if (interned_fields == NULL)
- return NULL;
-
- previous = (CFieldObject **)&ct->ct_extra;
-
- for (i=0; i<nb_fields; i++) {
- PyObject *fname;
- CTypeDescrObject *ftype;
- int fbitsize = -1, falign, falignorg, do_align;
- Py_ssize_t foffset = -1;
-
- if (!PyArg_ParseTuple(PyList_GET_ITEM(fields, i), "O!O!|in:list item",
- &PyText_Type, &fname,
- &CTypeDescr_Type, &ftype,
- &fbitsize, &foffset))
- goto error;
-
- if (ftype->ct_size < 0) {
- if ((ftype->ct_flags & CT_ARRAY) && fbitsize < 0
- && (i == nb_fields - 1 || foffset != -1)) {
- ct->ct_flags |= CT_WITH_VAR_ARRAY;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "field '%s.%s' has ctype '%s' of unknown size",
- ct->ct_name, PyText_AS_UTF8(fname),
- ftype->ct_name);
- goto error;
- }
- }
- else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
- if (force_lazy_struct(ftype) < 0) /* for CT_WITH_VAR_ARRAY */
- return NULL;
-
- /* GCC (or maybe C99) accepts var-sized struct fields that are not
- the last field of a larger struct. That's why there is no
- check here for "last field": we propagate the flag
- CT_WITH_VAR_ARRAY to any struct that contains either an open-
- ended array or another struct that recursively contains an
- open-ended array. */
- if (ftype->ct_flags & CT_WITH_VAR_ARRAY)
- ct->ct_flags |= CT_WITH_VAR_ARRAY;
- }
-
- if (is_union)
- byteoffset = bitoffset = 0; /* reset each field at offset 0 */
-
- /* update the total alignment requirement, but skip it if the
- field is an anonymous bitfield or if SF_PACKED */
- falignorg = get_alignment(ftype);
- if (falignorg < 0)
- goto error;
- falign = (pack < falignorg) ? pack : falignorg;
-
- do_align = 1;
- if (!(sflags & SF_GCC_ARM_BITFIELDS) && fbitsize >= 0) {
- if (!(sflags & SF_MSVC_BITFIELDS)) {
- /* GCC: anonymous bitfields (of any size) don't cause alignment */
- do_align = PyText_GetSize(fname) > 0;
- }
- else {
- /* MSVC: zero-sized bitfields don't cause alignment */
- do_align = fbitsize > 0;
- }
- }
- if (alignment < falign && do_align)
- alignment = falign;
-
- fflags = (is_union && i > 0) ? BF_IGNORE_IN_CTOR : 0;
-
- if (fbitsize < 0) {
- /* not a bitfield: common case */
- int bs_flag;
-
- if ((ftype->ct_flags & CT_ARRAY) && ftype->ct_length <= 0)
- bs_flag = BS_EMPTY_ARRAY;
- else
- bs_flag = BS_REGULAR;
-
- /* align this field to its own 'falign' by inserting padding */
-
- /* first, pad to the next byte,
- * then pad to 'falign' or 'falignorg' bytes */
- byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset);
- bitoffset = 0;
- byteoffsetorg = (byteoffset + falignorg-1) & ~(falignorg-1);
- byteoffset = (byteoffset + falign-1) & ~(falign-1);
-
- if (byteoffsetorg != byteoffset) {
- ct->ct_flags |= CT_WITH_PACKED_CHANGE;
- }
-
- if (foffset >= 0) {
- /* a forced field position: ignore the offset just computed,
- except to know if we must set CT_CUSTOM_FIELD_POS */
- if (detect_custom_layout(ct, sflags, byteoffset, foffset,
- "wrong offset for field '",
- PyText_AS_UTF8(fname), "'") < 0)
- goto error;
- byteoffset = foffset;
- }
-
- if (PyText_GetSize(fname) == 0 &&
- ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
- /* a nested anonymous struct or union */
- CFieldObject *cfsrc = (CFieldObject *)ftype->ct_extra;
- for (; cfsrc != NULL; cfsrc = cfsrc->cf_next) {
- /* broken complexity in the call to get_field_name(),
- but we'll assume you never do that with nested
- anonymous structures with thousand of fields */
- *previous = _add_field(interned_fields,
- get_field_name(ftype, cfsrc),
- cfsrc->cf_type,
- byteoffset + cfsrc->cf_offset,
- cfsrc->cf_bitshift,
- cfsrc->cf_bitsize,
- cfsrc->cf_flags | fflags);
- if (*previous == NULL)
- goto error;
- previous = &(*previous)->cf_next;
- }
- /* always forbid such structures from being passed by value */
- ct->ct_flags |= CT_CUSTOM_FIELD_POS;
- }
- else {
- *previous = _add_field(interned_fields, fname, ftype,
- byteoffset, bs_flag, -1, fflags);
- if (*previous == NULL)
- goto error;
- previous = &(*previous)->cf_next;
- }
- if (ftype->ct_size >= 0)
- byteoffset += ftype->ct_size;
- prev_bitfield_size = 0;
- }
- else {
- /* this is the case of a bitfield */
- Py_ssize_t field_offset_bytes;
- int bits_already_occupied, bitshift;
-
- if (foffset >= 0) {
- PyErr_Format(PyExc_TypeError,
- "field '%s.%s' is a bitfield, "
- "but a fixed offset is specified",
- ct->ct_name, PyText_AS_UTF8(fname));
- goto error;
- }
-
- if (!(ftype->ct_flags & (CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED |
- CT_PRIMITIVE_CHAR))) {
- PyErr_Format(PyExc_TypeError,
- "field '%s.%s' declared as '%s' cannot be a bit field",
- ct->ct_name, PyText_AS_UTF8(fname),
- ftype->ct_name);
- goto error;
- }
- if (fbitsize > 8 * ftype->ct_size) {
- PyErr_Format(PyExc_TypeError,
- "bit field '%s.%s' is declared '%s:%d', which "
- "exceeds the width of the type",
- ct->ct_name, PyText_AS_UTF8(fname),
- ftype->ct_name, fbitsize);
- goto error;
- }
-
- /* compute the starting position of the theoretical field
- that covers a complete 'ftype', inside of which we will
- locate the real bitfield */
- field_offset_bytes = byteoffset;
- field_offset_bytes &= ~(falign - 1);
-
- if (fbitsize == 0) {
- if (PyText_GetSize(fname) > 0) {
- PyErr_Format(PyExc_TypeError,
- "field '%s.%s' is declared with :0",
- ct->ct_name, PyText_AS_UTF8(fname));
- goto error;
- }
- if (!(sflags & SF_MSVC_BITFIELDS)) {
- /* GCC's notion of "ftype :0;" */
-
- /* pad byteoffset to a value aligned for "ftype" */
- if (ROUNDUP_BYTES(byteoffset, bitoffset) > field_offset_bytes) {
- field_offset_bytes += falign;
- assert(byteoffset < field_offset_bytes);
- }
- byteoffset = field_offset_bytes;
- bitoffset = 0;
- }
- else {
- /* MSVC's notion of "ftype :0;" */
-
- /* Mostly ignored. It seems they only serve as
- separator between other bitfields, to force them
- into separate words. */
- }
- prev_bitfield_size = 0;
- }
- else {
- if (!(sflags & SF_MSVC_BITFIELDS)) {
- /* GCC's algorithm */
-
- /* Can the field start at the offset given by 'boffset'? It
- can if it would entirely fit into an aligned ftype field. */
- bits_already_occupied = (byteoffset-field_offset_bytes) * 8
- + bitoffset;
-
- if (bits_already_occupied + fbitsize > 8 * ftype->ct_size) {
- /* it would not fit, we need to start at the next
- allowed position */
- if ((sflags & SF_PACKED) &&
- (bits_already_occupied & 7)) {
- PyErr_Format(PyExc_NotImplementedError,
- "with 'packed', gcc would compile field "
- "'%s.%s' to reuse some bits in the previous "
- "field", ct->ct_name, PyText_AS_UTF8(fname));
- goto error;
- }
- field_offset_bytes += falign;
- assert(byteoffset < field_offset_bytes);
- byteoffset = field_offset_bytes;
- bitoffset = 0;
- bitshift = 0;
- }
- else {
- bitshift = bits_already_occupied;
- assert(bitshift >= 0);
- }
- bitoffset += fbitsize;
- byteoffset += (bitoffset >> 3);
- bitoffset &= 7;
- }
- else {
- /* MSVC's algorithm */
-
- /* A bitfield is considered as taking the full width
- of their declared type. It can share some bits
- with the previous field only if it was also a
- bitfield and used a type of the same size. */
- if (prev_bitfield_size == ftype->ct_size &&
- prev_bitfield_free >= fbitsize) {
- /* yes: reuse */
- bitshift = 8 * prev_bitfield_size - prev_bitfield_free;
- }
- else {
- /* no: start a new full field */
- byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset);
- bitoffset = 0;
- /* align */
- byteoffset = (byteoffset + falign-1) & ~(falign-1);
- byteoffset += ftype->ct_size;
- bitshift = 0;
- prev_bitfield_size = ftype->ct_size;
- prev_bitfield_free = 8 * prev_bitfield_size;
- }
- prev_bitfield_free -= fbitsize;
- field_offset_bytes = byteoffset - ftype->ct_size;
- }
- if (sflags & SF_GCC_BIG_ENDIAN)
- bitshift = 8 * ftype->ct_size - fbitsize - bitshift;
-
- if (PyText_GetSize(fname) > 0) {
-
- *previous = _add_field(interned_fields, fname, ftype,
- field_offset_bytes, bitshift, fbitsize,
- fflags);
- if (*previous == NULL)
- goto error;
- previous = &(*previous)->cf_next;
- }
- }
- }
-
- assert(bitoffset == (bitoffset & 7));
- if (ROUNDUP_BYTES(byteoffset, bitoffset) > byteoffsetmax)
- byteoffsetmax = ROUNDUP_BYTES(byteoffset, bitoffset);
- }
- *previous = NULL;
-
- /* Like C, if the size of this structure would be zero, we compute it
- as 1 instead. But for ctypes support, we allow the manually-
- specified totalsize to be zero in this case. */
- alignedsize = (byteoffsetmax + alignment - 1) & ~(alignment-1);
- if (alignedsize == 0)
- alignedsize = 1;
-
- if (totalsize < 0) {
- totalsize = alignedsize;
- }
- else {
- if (detect_custom_layout(ct, sflags, alignedsize,
- totalsize, "wrong total size", "", "") < 0)
- goto error;
- if (totalsize < byteoffsetmax) {
- PyErr_Format(PyExc_TypeError,
- "%s cannot be of size %zd: there are fields at least "
- "up to %zd", ct->ct_name, totalsize, byteoffsetmax);
- goto error;
- }
- }
- if (totalalignment < 0) {
- totalalignment = alignment;
- }
- else {
- if (detect_custom_layout(ct, sflags, alignment, totalalignment,
- "wrong total alignment", "", "") < 0)
- goto error;
- }
-
- ct->ct_size = totalsize;
- ct->ct_length = totalalignment;
- ct->ct_stuff = interned_fields;
- ct->ct_flags &= ~CT_IS_OPAQUE;
-
- Py_INCREF(Py_None);
- return Py_None;
-
- error:
- ct->ct_extra = NULL;
- Py_DECREF(interned_fields);
- return NULL;
-}
-
-struct funcbuilder_s {
- Py_ssize_t nb_bytes;
- char *bufferp;
- ffi_type **atypes;
- ffi_type *rtype;
- Py_ssize_t nargs;
- CTypeDescrObject *fct;
-};
-
-static void *fb_alloc(struct funcbuilder_s *fb, Py_ssize_t size)
-{
- if (fb->bufferp == NULL) {
- fb->nb_bytes += size;
- return NULL;
- }
- else {
- char *result = fb->bufferp;
- fb->bufferp += size;
- return result;
- }
-}
-
-#define SUPPORTED_IN_API_MODE \
- " are only supported as %s if the function is " \
- "'API mode' and non-variadic (i.e. declared inside ffibuilder" \
- ".cdef()+ffibuilder.set_source() and not taking a final '...' " \
- "argument)"
-
-static ffi_type *fb_unsupported(CTypeDescrObject *ct, const char *place,
- const char *detail)
-{
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' not supported as %s. %s. "
- "Such structs" SUPPORTED_IN_API_MODE,
- ct->ct_name, place, detail, place);
- return NULL;
-}
-
-static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
- int is_result_type)
-{
- const char *place = is_result_type ? "return value" : "argument";
-
- if (ct->ct_flags & (CT_PRIMITIVE_ANY & ~CT_PRIMITIVE_COMPLEX)) {
- return (ffi_type *)ct->ct_extra;
- }
- else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
- return &ffi_type_pointer;
- }
- else if ((ct->ct_flags & CT_VOID) && is_result_type) {
- return &ffi_type_void;
- }
-
- if (ct->ct_size <= 0) {
- PyErr_Format(PyExc_TypeError,
- ct->ct_size < 0 ? "ctype '%s' has incomplete type"
- : "ctype '%s' has size 0",
- ct->ct_name);
- return NULL;
- }
- if (ct->ct_flags & CT_STRUCT) {
- ffi_type *ffistruct, *ffifield;
- ffi_type **elements;
- Py_ssize_t i, n, nflat;
- CFieldObject *cf;
-
- /* We can't pass a struct that was completed by verify().
- Issue: assume verify() is given "struct { long b; ...; }".
- Then it will complete it in the same way whether it is actually
- "struct { long a, b; }" or "struct { double a; long b; }".
- But on 64-bit UNIX, these two structs are passed by value
- differently: e.g. on x86-64, "b" ends up in register "rsi" in
- the first case and "rdi" in the second case.
-
- Another reason for CT_CUSTOM_FIELD_POS would be anonymous
- nested structures: we lost the information about having it
- here, so better safe (and forbid it) than sorry (and maybe
- crash). Note: it seems we only get in this case with
- ffi.verify().
- */
- if (force_lazy_struct(ct) < 0)
- return NULL;
- if (ct->ct_flags & CT_CUSTOM_FIELD_POS) {
- /* these NotImplementedErrors may be caught and ignored until
- a real call is made to a function of this type */
- return fb_unsupported(ct, place,
- "It is a struct declared with \"...;\", but the C "
- "calling convention may depend on the missing fields; "
- "or, it contains anonymous struct/unions");
- }
- /* Another reason: __attribute__((packed)) is not supported by libffi.
- */
- if (ct->ct_flags & CT_WITH_PACKED_CHANGE) {
- return fb_unsupported(ct, place,
- "It is a 'packed' structure, with a different layout than "
- "expected by libffi");
- }
-
- n = PyDict_Size(ct->ct_stuff);
- nflat = 0;
-
- /* walk the fields, expanding arrays into repetitions; first,
- only count how many flattened fields there are */
- cf = (CFieldObject *)ct->ct_extra;
- for (i=0; i<n; i++) {
- Py_ssize_t flat;
- CTypeDescrObject *ct1;
- assert(cf != NULL);
- if (cf->cf_bitshift >= 0) {
- return fb_unsupported(ct, place,
- "It is a struct with bit fields, which libffi does not "
- "support");
- }
- flat = 1;
- ct1 = cf->cf_type;
- while (ct1->ct_flags & CT_ARRAY) {
- flat *= ct1->ct_length;
- ct1 = ct1->ct_itemdescr;
- }
- if (flat <= 0) {
- return fb_unsupported(ct, place,
- "It is a struct with a zero-length array, which libffi "
- "does not support");
- }
- nflat += flat;
- cf = cf->cf_next;
- }
- assert(cf == NULL);
-
- /* next, allocate and fill the flattened list */
- elements = fb_alloc(fb, (nflat + 1) * sizeof(ffi_type*));
- nflat = 0;
- cf = (CFieldObject *)ct->ct_extra;
- for (i=0; i<n; i++) {
- Py_ssize_t j, flat = 1;
- CTypeDescrObject *ct = cf->cf_type;
- while (ct->ct_flags & CT_ARRAY) {
- flat *= ct->ct_length;
- ct = ct->ct_itemdescr;
- }
- ffifield = fb_fill_type(fb, ct, 0);
- if (PyErr_Occurred())
- return NULL;
- if (elements != NULL) {
- for (j=0; j<flat; j++)
- elements[nflat++] = ffifield;
- }
- cf = cf->cf_next;
- }
-
- /* finally, allocate the FFI_TYPE_STRUCT */
- ffistruct = fb_alloc(fb, sizeof(ffi_type));
- if (ffistruct != NULL) {
- elements[nflat] = NULL;
- ffistruct->size = ct->ct_size;
- ffistruct->alignment = ct->ct_length;
- ffistruct->type = FFI_TYPE_STRUCT;
- ffistruct->elements = elements;
- }
- return ffistruct;
- }
- else if (ct->ct_flags & CT_UNION) {
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' not supported as %s by libffi. "
- "Unions" SUPPORTED_IN_API_MODE,
- ct->ct_name, place, place);
- return NULL;
- }
- else {
- char *extra = "";
- if (ct->ct_flags & CT_PRIMITIVE_COMPLEX)
- extra = " (the support for complex types inside libffi "
- "is mostly missing at this point, so CFFI only "
- "supports complex types as arguments or return "
- "value in API-mode functions)";
-
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' (size %zd) not supported as %s%s",
- ct->ct_name, ct->ct_size, place, extra);
- return NULL;
- }
-}
-
-#define ALIGN_ARG(n) ((n) + 7) & ~7
-
-static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
- CTypeDescrObject *fresult)
-{
- Py_ssize_t i, nargs = PyTuple_GET_SIZE(fargs);
- Py_ssize_t exchange_offset;
- cif_description_t *cif_descr;
-
- /* ffi buffer: start with a cif_description */
- cif_descr = fb_alloc(fb, sizeof(cif_description_t) +
- nargs * sizeof(Py_ssize_t));
-
- /* ffi buffer: next comes an array of 'ffi_type*', one per argument */
- fb->atypes = fb_alloc(fb, nargs * sizeof(ffi_type*));
- fb->nargs = nargs;
-
- /* ffi buffer: next comes the result type */
- fb->rtype = fb_fill_type(fb, fresult, 1);
- if (PyErr_Occurred())
- return -1;
- if (cif_descr != NULL) {
- /* exchange data size */
- /* first, enough room for an array of 'nargs' pointers */
- exchange_offset = nargs * sizeof(void*);
- exchange_offset = ALIGN_ARG(exchange_offset);
- cif_descr->exchange_offset_arg[0] = exchange_offset;
- /* then enough room for the result --- which means at least
- sizeof(ffi_arg), according to the ffi docs */
- i = fb->rtype->size;
- if (i < (Py_ssize_t)sizeof(ffi_arg))
- i = sizeof(ffi_arg);
- exchange_offset += i;
- }
- else
- exchange_offset = 0; /* not used */
-
- /* loop over the arguments */
- for (i=0; i<nargs; i++) {
- CTypeDescrObject *farg;
- ffi_type *atype;
-
- farg = (CTypeDescrObject *)PyTuple_GET_ITEM(fargs, i);
- /* convert arrays to pointers */
- if (farg->ct_flags & CT_ARRAY)
- farg = (CTypeDescrObject *)farg->ct_stuff;
-
- /* ffi buffer: fill in the ffi for the i'th argument */
- assert(farg != NULL);
- atype = fb_fill_type(fb, farg, 0);
- if (PyErr_Occurred())
- return -1;
-
- if (fb->atypes != NULL) {
- fb->atypes[i] = atype;
- /* exchange data size */
- exchange_offset = ALIGN_ARG(exchange_offset);
- cif_descr->exchange_offset_arg[1 + i] = exchange_offset;
- exchange_offset += atype->size;
- }
- }
-
- if (cif_descr != NULL) {
- /* exchange data size */
- /* we also align it to the next multiple of 8, in an attempt to
- work around bugs(?) of libffi like #241 */
- cif_descr->exchange_size = ALIGN_ARG(exchange_offset);
- }
- return 0;
-}
-
-#undef ALIGN_ARG
-
-static void fb_cat_name(struct funcbuilder_s *fb, const char *piece,
- int piecelen)
-{
- if (fb->bufferp == NULL) {
- fb->nb_bytes += piecelen;
- }
- else {
- memcpy(fb->bufferp, piece, piecelen);
- fb->bufferp += piecelen;
- }
-}
-
-static int fb_build_name(struct funcbuilder_s *fb, const char *repl,
- CTypeDescrObject **pfargs, Py_ssize_t nargs,
- CTypeDescrObject *fresult, int ellipsis)
-{
- Py_ssize_t i;
- fb->nargs = nargs;
-
- /* name: the function type name we build here is, like in C, made
- as follows:
-
- RESULT_TYPE_HEAD (*)(ARG_1_TYPE, ARG_2_TYPE, etc) RESULT_TYPE_TAIL
- */
- fb_cat_name(fb, fresult->ct_name, fresult->ct_name_position);
- if (repl[0] != '(' &&
- fresult->ct_name[fresult->ct_name_position - 1] != '*')
- fb_cat_name(fb, " ", 1); /* add a space */
- fb_cat_name(fb, repl, strlen(repl));
- if (fb->fct) {
- i = strlen(repl) - 1; /* between '(*' and ')' */
- assert(repl[i] == ')');
- fb->fct->ct_name_position = fresult->ct_name_position + i;
- }
- fb_cat_name(fb, "(", 1);
-
- /* loop over the arguments */
- for (i=0; i<nargs; i++) {
- CTypeDescrObject *farg;
-
- farg = pfargs[i];
- if (!CTypeDescr_Check(farg)) {
- PyErr_SetString(PyExc_TypeError, "expected a tuple of ctypes");
- return -1;
- }
- /* name: concatenate the name of the i'th argument's type */
- if (i > 0)
- fb_cat_name(fb, ", ", 2);
- fb_cat_name(fb, farg->ct_name, strlen(farg->ct_name));
- }
-
- /* name: add the '...' if needed */
- if (ellipsis) {
- if (nargs > 0)
- fb_cat_name(fb, ", ", 2);
- fb_cat_name(fb, "...", 3);
- }
-
- /* name: concatenate the tail of the result type */
- fb_cat_name(fb, ")", 1);
- fb_cat_name(fb, fresult->ct_name + fresult->ct_name_position,
- strlen(fresult->ct_name) - fresult->ct_name_position + 1);
- return 0;
-}
-
-static CTypeDescrObject *fb_prepare_ctype(struct funcbuilder_s *fb,
- PyObject *fargs,
- CTypeDescrObject *fresult,
- int ellipsis, int fabi)
-{
- CTypeDescrObject *fct, **pfargs;
- Py_ssize_t nargs;
- char *repl = "(*)";
-
- fb->nb_bytes = 0;
- fb->bufferp = NULL;
- fb->fct = NULL;
-
- pfargs = (CTypeDescrObject **)&PyTuple_GET_ITEM(fargs, 0);
- nargs = PyTuple_GET_SIZE(fargs);
-#if defined(MS_WIN32) && !defined(_WIN64)
- if (fabi == FFI_STDCALL)
- repl = "(__stdcall *)";
-#endif
-
- /* compute the total size needed for the name */
- if (fb_build_name(fb, repl, pfargs, nargs, fresult, ellipsis) < 0)
- return NULL;
-
- /* allocate the function type */
- fct = ctypedescr_new(fb->nb_bytes);
- if (fct == NULL)
- return NULL;
- fb->fct = fct;
-
- /* call again fb_build_name() to really build the ct_name */
- fb->bufferp = fct->ct_name;
- if (fb_build_name(fb, repl, pfargs, nargs, fresult, ellipsis) < 0)
- goto error;
- assert(fb->bufferp == fct->ct_name + fb->nb_bytes);
-
- fct->ct_extra = NULL;
- fct->ct_size = sizeof(void(*)(void));
- fct->ct_flags = CT_FUNCTIONPTR;
- return fct;
-
- error:
- Py_DECREF(fct);
- return NULL;
-}
-
-static cif_description_t *fb_prepare_cif(PyObject *fargs,
- CTypeDescrObject *fresult,
- Py_ssize_t variadic_nargs_declared,
- ffi_abi fabi)
-
-{
- char *buffer;
- cif_description_t *cif_descr;
- struct funcbuilder_s funcbuffer;
- ffi_status status = (ffi_status)-1;
-
- funcbuffer.nb_bytes = 0;
- funcbuffer.bufferp = NULL;
-
- /* compute the total size needed in the buffer for libffi */
- if (fb_build(&funcbuffer, fargs, fresult) < 0)
- return NULL;
-
- /* allocate the buffer */
- buffer = PyObject_Malloc(funcbuffer.nb_bytes);
- if (buffer == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
-
- /* call again fb_build() to really build the libffi data structures */
- funcbuffer.bufferp = buffer;
- if (fb_build(&funcbuffer, fargs, fresult) < 0)
- goto error;
- assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes);
-
- cif_descr = (cif_description_t *)buffer;
-
- /* use `ffi_prep_cif_var` if necessary and available */
-#if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE
- if (variadic_nargs_declared >= 0) {
- if (CFFI_CHECK_FFI_PREP_CIF_VAR) {
- status = ffi_prep_cif_var(&cif_descr->cif, fabi,
- variadic_nargs_declared, funcbuffer.nargs,
- funcbuffer.rtype, funcbuffer.atypes);
- }
- }
-#endif
-
- if (status == (ffi_status)-1) {
- status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
- funcbuffer.rtype, funcbuffer.atypes);
- }
-
- if (status != FFI_OK) {
- PyErr_SetString(PyExc_SystemError,
- "libffi failed to build this function type");
- goto error;
- }
- return cif_descr;
-
- error:
- PyObject_Free(buffer);
- return NULL;
-}
-
-static PyObject *new_function_type(PyObject *fargs, /* tuple */
- CTypeDescrObject *fresult,
- int ellipsis, int fabi)
-{
- PyObject *fabiobj;
- CTypeDescrObject *fct;
- struct funcbuilder_s funcbuilder;
- Py_ssize_t i;
- const void **unique_key;
-
- if ((fresult->ct_size < 0 && !(fresult->ct_flags & CT_VOID)) ||
- (fresult->ct_flags & CT_ARRAY)) {
- char *msg;
- if (fresult->ct_flags & CT_IS_OPAQUE)
- msg = "result type '%s' is opaque";
- else
- msg = "invalid result type: '%s'";
- PyErr_Format(PyExc_TypeError, msg, fresult->ct_name);
- return NULL;
- }
-
- fct = fb_prepare_ctype(&funcbuilder, fargs, fresult, ellipsis, fabi);
- if (fct == NULL)
- return NULL;
-
- if (!ellipsis) {
- /* Functions with '...' varargs are stored without a cif_descr
- at all. The cif is computed on every call from the actual
- types passed in. For all other functions, the cif_descr
- is computed here. */
- cif_description_t *cif_descr;
-
- cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi);
- if (cif_descr == NULL) {
- if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
- PyErr_Clear(); /* will get the exception if we see an
- actual call */
- }
- else
- goto error;
- }
-
- fct->ct_extra = (char *)cif_descr;
- }
-
- /* build the signature, given by a tuple of ctype objects */
- fct->ct_stuff = PyTuple_New(2 + funcbuilder.nargs);
- if (fct->ct_stuff == NULL)
- goto error;
- fabiobj = PyInt_FromLong(fabi);
- if (fabiobj == NULL)
- goto error;
- PyTuple_SET_ITEM(fct->ct_stuff, 0, fabiobj);
-
- Py_INCREF(fresult);
- PyTuple_SET_ITEM(fct->ct_stuff, 1, (PyObject *)fresult);
- for (i=0; i<funcbuilder.nargs; i++) {
- PyObject *o = PyTuple_GET_ITEM(fargs, i);
- /* convert arrays into pointers */
- if (((CTypeDescrObject *)o)->ct_flags & CT_ARRAY)
- o = ((CTypeDescrObject *)o)->ct_stuff;
- Py_INCREF(o);
- PyTuple_SET_ITEM(fct->ct_stuff, 2 + i, o);
- }
-
- /* [ctresult, ellipsis+abi, num_args, ctargs...] */
- unique_key = alloca((3 + funcbuilder.nargs) * sizeof(void *));
- unique_key[0] = fresult;
- unique_key[1] = (const void *)(Py_ssize_t)((fabi << 1) | !!ellipsis);
- unique_key[2] = (const void *)(Py_ssize_t)(funcbuilder.nargs);
- for (i=0; i<funcbuilder.nargs; i++)
- unique_key[3 + i] = PyTuple_GET_ITEM(fct->ct_stuff, 2 + i);
- return get_unique_type(fct, unique_key, 3 + funcbuilder.nargs);
-
- error:
- Py_DECREF(fct);
- return NULL;
-}
-
-static PyObject *b_new_function_type(PyObject *self, PyObject *args)
-{
- PyObject *fargs;
- CTypeDescrObject *fresult;
- int ellipsis = 0, fabi = FFI_DEFAULT_ABI;
-
- if (!PyArg_ParseTuple(args, "O!O!|ii:new_function_type",
- &PyTuple_Type, &fargs,
- &CTypeDescr_Type, &fresult,
- &ellipsis,
- &fabi))
- return NULL;
-
- return new_function_type(fargs, fresult, ellipsis, fabi);
-}
-
-static int convert_from_object_fficallback(char *result,
- CTypeDescrObject *ctype,
- PyObject *pyobj,
- int encode_result_for_libffi)
-{
- /* work work work around a libffi irregularity: for integer return
- types we have to fill at least a complete 'ffi_arg'-sized result
- buffer. */
- if (ctype->ct_size < (Py_ssize_t)sizeof(ffi_arg)) {
- if (ctype->ct_flags & CT_VOID) {
- if (pyobj == Py_None) {
- return 0;
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "callback with the return type 'void' must return None");
- return -1;
- }
- }
- if (!encode_result_for_libffi)
- goto skip;
- if (ctype->ct_flags & CT_PRIMITIVE_SIGNED) {
- PY_LONG_LONG value;
- /* It's probably fine to always zero-extend, but you never
- know: maybe some code somewhere expects a negative
- 'short' result to be returned into EAX as a 32-bit
- negative number. Better safe than sorry. This code
- is about that case. Let's ignore this for enums.
- */
- /* do a first conversion only to detect overflows. This
- conversion produces stuff that is otherwise ignored. */
- if (convert_from_object(result, ctype, pyobj) < 0)
- return -1;
- /* manual inlining and tweaking of convert_from_object()
- in order to write a whole 'ffi_arg'. */
- value = _my_PyLong_AsLongLong(pyobj);
- if (value == -1 && PyErr_Occurred())
- return -1;
- write_raw_integer_data(result, value, sizeof(ffi_arg));
- return 0;
- }
- else if (ctype->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED |
- CT_POINTER | CT_FUNCTIONPTR)) {
- /* zero extension: fill the '*result' with zeros, and (on big-
- endian machines) correct the 'result' pointer to write to.
- We also do that for pointers, even though we're normally not
- in this branch because ctype->ct_size == sizeof(ffi_arg) for
- pointers---except on some architectures like x32 (issue #372).
- */
- memset(result, 0, sizeof(ffi_arg));
-#ifdef WORDS_BIGENDIAN
- result += (sizeof(ffi_arg) - ctype->ct_size);
-#endif
- }
- }
- skip:
- return convert_from_object(result, ctype, pyobj);
-}
-
-static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
- char *objdescr, PyObject *obj,
- char *extra_error_line)
-{
- /* like PyErr_WriteUnraisable(), but write a full traceback */
-#ifdef USE_WRITEUNRAISABLEMSG
-
- /* PyErr_WriteUnraisable actually writes the full traceback anyway
- from Python 3.4, but we can't really get the formatting of the
- custom text to be what we want. We can do better from Python
- 3.8 by calling the new _PyErr_WriteUnraisableMsg().
- Luckily it's also Python 3.8 that adds new functionality that
- people might want: the new sys.unraisablehook().
- */
- PyObject *s;
- int first_char;
- assert(objdescr != NULL && objdescr[0] != 0); /* non-empty */
- first_char = objdescr[0];
- if (first_char >= 'A' && first_char <= 'Z')
- first_char += 'a' - 'A'; /* lower() the very first character */
- if (extra_error_line == NULL)
- extra_error_line = "";
-
- if (obj != NULL)
- s = PyUnicode_FromFormat("%c%s%R%s",
- first_char, objdescr + 1, obj, extra_error_line);
- else
- s = PyUnicode_FromFormat("%c%s%s",
- first_char, objdescr + 1, extra_error_line);
-
- PyErr_Restore(t, v, tb);
- if (s != NULL) {
- _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL);
- Py_DECREF(s);
- }
- else
- PyErr_WriteUnraisable(obj); /* best effort */
- PyErr_Clear();
-
-#else
-
- /* version for Python 2.7 and < 3.8 */
- PyObject *f;
-#if PY_MAJOR_VERSION >= 3
- /* jump through hoops to ensure the tb is attached to v, on Python 3 */
- PyErr_NormalizeException(&t, &v, &tb);
- if (tb == NULL) {
- tb = Py_None;
- Py_INCREF(tb);
- }
- PyException_SetTraceback(v, tb);
-#endif
- f = PySys_GetObject("stderr");
- if (f != NULL) {
- if (obj != NULL) {
- PyFile_WriteString(objdescr, f);
- PyFile_WriteObject(obj, f, 0);
- PyFile_WriteString(":\n", f);
- }
- if (extra_error_line != NULL)
- PyFile_WriteString(extra_error_line, f);
- PyErr_Display(t, v, tb);
- }
- Py_XDECREF(t);
- Py_XDECREF(v);
- Py_XDECREF(tb);
-
-#endif
-}
-
-static void general_invoke_callback(int decode_args_from_libffi,
- void *result, char *args, void *userdata)
-{
- PyObject *cb_args = (PyObject *)userdata;
- CTypeDescrObject *ct = (CTypeDescrObject *)PyTuple_GET_ITEM(cb_args, 0);
- PyObject *signature = ct->ct_stuff;
- PyObject *py_ob = PyTuple_GET_ITEM(cb_args, 1);
- PyObject *py_args = NULL;
- PyObject *py_res = NULL;
- PyObject *py_rawerr;
- PyObject *onerror_cb;
- Py_ssize_t i, n;
- char *extra_error_line = NULL;
-
-#define SIGNATURE(i) ((CTypeDescrObject *)PyTuple_GET_ITEM(signature, i))
-
- Py_INCREF(cb_args);
-
- n = PyTuple_GET_SIZE(signature) - 2;
- py_args = PyTuple_New(n);
- if (py_args == NULL)
- goto error;
-
- for (i=0; i<n; i++) {
- char *a_src;
- PyObject *a;
- CTypeDescrObject *a_ct = SIGNATURE(2 + i);
-
- if (decode_args_from_libffi) {
- a_src = ((void **)args)[i];
- }
- else {
- a_src = args + i * 8;
- if (a_ct->ct_flags & (CT_IS_LONGDOUBLE | CT_STRUCT | CT_UNION))
- a_src = *(char **)a_src;
- }
- a = convert_to_object(a_src, a_ct);
- if (a == NULL)
- goto error;
- PyTuple_SET_ITEM(py_args, i, a);
- }
-
- py_res = PyObject_Call(py_ob, py_args, NULL);
- if (py_res == NULL)
- goto error;
- if (convert_from_object_fficallback(result, SIGNATURE(1), py_res,
- decode_args_from_libffi) < 0) {
-#ifdef USE_WRITEUNRAISABLEMSG
- extra_error_line = ", trying to convert the result back to C";
-#else
- extra_error_line = "Trying to convert the result back to C:\n";
-#endif
- goto error;
- }
- done:
- Py_XDECREF(py_args);
- Py_XDECREF(py_res);
- Py_DECREF(cb_args);
- return;
-
- error:
- if (SIGNATURE(1)->ct_size > 0) {
- py_rawerr = PyTuple_GET_ITEM(cb_args, 2);
- memcpy(result, PyBytes_AS_STRING(py_rawerr),
- PyBytes_GET_SIZE(py_rawerr));
- }
- onerror_cb = PyTuple_GET_ITEM(cb_args, 3);
- if (onerror_cb == Py_None) {
- PyObject *ecap, *t, *v, *tb;
- PyErr_Fetch(&t, &v, &tb);
- ecap = _cffi_start_error_capture();
- _my_PyErr_WriteUnraisable(t, v, tb, "From cffi callback ", py_ob,
- extra_error_line);
- _cffi_stop_error_capture(ecap);
- }
- else {
- PyObject *exc1, *val1, *tb1, *res1, *exc2, *val2, *tb2;
- PyErr_Fetch(&exc1, &val1, &tb1);
- PyErr_NormalizeException(&exc1, &val1, &tb1);
- res1 = PyObject_CallFunctionObjArgs(onerror_cb,
- exc1 ? exc1 : Py_None,
- val1 ? val1 : Py_None,
- tb1 ? tb1 : Py_None,
- NULL);
- if (res1 != NULL) {
- if (res1 != Py_None)
- convert_from_object_fficallback(result, SIGNATURE(1), res1,
- decode_args_from_libffi);
- Py_DECREF(res1);
- }
- if (!PyErr_Occurred()) {
- Py_XDECREF(exc1);
- Py_XDECREF(val1);
- Py_XDECREF(tb1);
- }
- else {
- /* double exception! print a double-traceback... */
- PyObject *ecap;
- PyErr_Fetch(&exc2, &val2, &tb2);
- ecap = _cffi_start_error_capture();
- _my_PyErr_WriteUnraisable(exc1, val1, tb1,
- "From cffi callback ", py_ob,
- extra_error_line);
-#ifdef USE_WRITEUNRAISABLEMSG
- _my_PyErr_WriteUnraisable(exc2, val2, tb2,
- "during handling of the above exception by 'onerror'",
- NULL, NULL);
-#else
- extra_error_line = ("\nDuring the call to 'onerror', "
- "another exception occurred:\n\n");
- _my_PyErr_WriteUnraisable(exc2, val2, tb2,
- NULL, NULL, extra_error_line);
-#endif
- _cffi_stop_error_capture(ecap);
- }
- }
- goto done;
-
-#undef SIGNATURE
-}
-
-static void invoke_callback(ffi_cif *cif, void *result, void **args,
- void *userdata)
-{
- save_errno();
- {
- PyGILState_STATE state = gil_ensure();
- general_invoke_callback(1, result, (char *)args, userdata);
- gil_release(state);
- }
- restore_errno();
-}
-
-static PyObject *prepare_callback_info_tuple(CTypeDescrObject *ct,
- PyObject *ob,
- PyObject *error_ob,
- PyObject *onerror_ob,
- int decode_args_from_libffi)
-{
- CTypeDescrObject *ctresult;
- PyObject *py_rawerr, *infotuple;
- Py_ssize_t size;
-
- if (!(ct->ct_flags & CT_FUNCTIONPTR)) {
- PyErr_Format(PyExc_TypeError, "expected a function ctype, got '%s'",
- ct->ct_name);
- return NULL;
- }
- if (!PyCallable_Check(ob)) {
- PyErr_Format(PyExc_TypeError,
- "expected a callable object, not %.200s",
- Py_TYPE(ob)->tp_name);
- return NULL;
- }
- if (onerror_ob != Py_None && !PyCallable_Check(onerror_ob)) {
- PyErr_Format(PyExc_TypeError,
- "expected a callable object for 'onerror', not %.200s",
- Py_TYPE(onerror_ob)->tp_name);
- return NULL;
- }
-
- ctresult = (CTypeDescrObject *)PyTuple_GET_ITEM(ct->ct_stuff, 1);
- size = ctresult->ct_size;
- if (size < (Py_ssize_t)sizeof(ffi_arg))
- size = sizeof(ffi_arg);
- py_rawerr = PyBytes_FromStringAndSize(NULL, size);
- if (py_rawerr == NULL)
- return NULL;
- memset(PyBytes_AS_STRING(py_rawerr), 0, size);
- if (error_ob != Py_None) {
- if (convert_from_object_fficallback(
- PyBytes_AS_STRING(py_rawerr), ctresult, error_ob,
- decode_args_from_libffi) < 0) {
- Py_DECREF(py_rawerr);
- return NULL;
- }
- }
- infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob);
- Py_DECREF(py_rawerr);
-
-#if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
- /* We must setup the GIL here, in case the callback is invoked in
- some other non-Pythonic thread. This is the same as ctypes.
- But PyEval_InitThreads() is always a no-op from CPython 3.7
- (the call from ctypes was removed some time later I think). */
- PyEval_InitThreads();
-#endif
-
- return infotuple;
-}
-
-/* messily try to silence a gcc/clang deprecation warning for
- ffi_prep_closure. Don't miss the "pragma pop" after the function.
- This is done around the whole function because very old GCCs don't
- support it inside a function. */
-#if defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-static PyObject *b_callback(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- CDataObject_closure *cd;
- PyObject *ob, *error_ob = Py_None, *onerror_ob = Py_None;
- PyObject *infotuple;
- cif_description_t *cif_descr;
- ffi_closure *closure;
- ffi_status status;
- void *closure_exec;
-
- if (!PyArg_ParseTuple(args, "O!O|OO:callback", &CTypeDescr_Type, &ct, &ob,
- &error_ob, &onerror_ob))
- return NULL;
-
- infotuple = prepare_callback_info_tuple(ct, ob, error_ob, onerror_ob, 1);
- if (infotuple == NULL)
- return NULL;
-
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
- if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
- closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec);
- } else
-#endif
- {
- closure = cffi_closure_alloc();
- closure_exec = closure;
- }
-
- if (closure == NULL) {
- Py_DECREF(infotuple);
- PyErr_SetString(PyExc_MemoryError,
- "Cannot allocate write+execute memory for ffi.callback(). "
- "You might be running on a system that prevents this. "
- "For more information, see "
- "https://cffi.readthedocs.io/en/latest/using.html#callbacks");
- return NULL;
- }
- cd = PyObject_GC_New(CDataObject_closure, &CDataOwningGC_Type);
- if (cd == NULL)
- goto error;
- Py_INCREF(ct);
- cd->head.c_type = ct;
- cd->head.c_data = (char *)closure_exec;
- cd->head.c_weakreflist = NULL;
- closure->user_data = NULL;
- cd->closure = closure;
-
- cif_descr = (cif_description_t *)ct->ct_extra;
- if (cif_descr == NULL) {
- PyErr_Format(PyExc_NotImplementedError,
- "%s: callback with unsupported argument or "
- "return type or with '...'", ct->ct_name);
- goto error;
- }
-
-#if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE
- if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) {
- status = ffi_prep_closure_loc(closure, &cif_descr->cif,
- invoke_callback, infotuple, closure_exec);
- }
- else
-#endif
- {
-#if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API
- PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing");
- goto error;
-#else
- status = ffi_prep_closure(closure, &cif_descr->cif,
- invoke_callback, infotuple);
-#endif
- }
-
- if (status != FFI_OK) {
- PyErr_SetString(PyExc_SystemError,
- "libffi failed to build this callback");
- goto error;
- }
-
- if (closure->user_data != infotuple) {
- /* Issue #266. Should not occur, but could, if we are using
- at runtime a version of libffi compiled with a different
- 'ffi_closure' structure than the one we expect from ffi.h
- (e.g. difference in details of the platform): a difference
- in FFI_TRAMPOLINE_SIZE means that the 'user_data' field
- ends up somewhere else, and so the test above fails.
- */
- PyErr_SetString(PyExc_SystemError,
- "ffi_prep_closure(): bad user_data (it seems that the "
- "version of the libffi library seen at runtime is "
- "different from the 'ffi.h' file seen at compile-time)");
- goto error;
- }
- PyObject_GC_Track(cd);
- return (PyObject *)cd;
-
- error:
- closure->user_data = NULL;
- if (cd == NULL) {
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
- if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
- ffi_closure_free(closure);
- }
- else
-#endif
- cffi_closure_free(closure);
- }
- else
- Py_DECREF(cd);
- Py_XDECREF(infotuple);
- return NULL;
-}
-#if defined(__clang__)
-# pragma clang diagnostic pop
-#elif defined(__GNUC__)
-# pragma GCC diagnostic pop
-#endif
-
-static PyObject *b_new_enum_type(PyObject *self, PyObject *args)
-{
- char *ename;
- PyObject *enumerators, *enumvalues;
- PyObject *dict1 = NULL, *dict2 = NULL, *combined = NULL, *tmpkey = NULL;
- int name_size;
- CTypeDescrObject *td, *basetd;
- Py_ssize_t i, n;
-
- if (!PyArg_ParseTuple(args, "sO!O!O!:new_enum_type",
- &ename,
- &PyTuple_Type, &enumerators,
- &PyTuple_Type, &enumvalues,
- &CTypeDescr_Type, &basetd))
- return NULL;
-
- n = PyTuple_GET_SIZE(enumerators);
- if (n != PyTuple_GET_SIZE(enumvalues)) {
- PyErr_SetString(PyExc_ValueError,
- "tuple args must have the same size");
- return NULL;
- }
-
- if (!(basetd->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))) {
- PyErr_SetString(PyExc_TypeError,
- "expected a primitive signed or unsigned base type");
- return NULL;
- }
-
- dict1 = PyDict_New();
- if (dict1 == NULL)
- goto error;
- dict2 = PyDict_New();
- if (dict2 == NULL)
- goto error;
-
- for (i=n; --i >= 0; ) {
- long long lvalue;
- PyObject *value = PyTuple_GET_ITEM(enumvalues, i);
- tmpkey = PyTuple_GET_ITEM(enumerators, i);
- Py_INCREF(tmpkey);
- if (!PyText_Check(tmpkey)) {
-#if PY_MAJOR_VERSION < 3
- if (PyUnicode_Check(tmpkey)) {
- const char *text = PyText_AsUTF8(tmpkey);
- if (text == NULL)
- goto error;
- Py_DECREF(tmpkey);
- tmpkey = PyString_FromString(text);
- if (tmpkey == NULL)
- goto error;
- }
- else
-#endif
- {
- PyErr_SetString(PyExc_TypeError,
- "enumerators must be a list of strings");
- goto error;
- }
- }
- if (convert_from_object((char*)&lvalue, basetd, value) < 0)
- goto error; /* out-of-range or badly typed 'value' */
- if (PyDict_SetItem(dict1, tmpkey, value) < 0)
- goto error;
- if (PyDict_SetItem(dict2, value, tmpkey) < 0)
- goto error;
- Py_DECREF(tmpkey);
- tmpkey = NULL;
- }
-
- combined = PyTuple_Pack(2, dict1, dict2);
- if (combined == NULL)
- goto error;
-
- Py_CLEAR(dict2);
- Py_CLEAR(dict1);
-
- name_size = strlen(ename) + 1;
- td = ctypedescr_new(name_size);
- if (td == NULL)
- goto error;
-
- memcpy(td->ct_name, ename, name_size);
- td->ct_stuff = combined;
- td->ct_size = basetd->ct_size;
- td->ct_length = basetd->ct_length; /* alignment */
- td->ct_extra = basetd->ct_extra; /* ffi type */
- td->ct_flags = basetd->ct_flags | CT_IS_ENUM;
- td->ct_name_position = name_size - 1;
- return (PyObject *)td;
-
- error:
- Py_XDECREF(tmpkey);
- Py_XDECREF(combined);
- Py_XDECREF(dict2);
- Py_XDECREF(dict1);
- return NULL;
-}
-
-static PyObject *b_alignof(PyObject *self, PyObject *arg)
-{
- int align;
- if (!CTypeDescr_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "expected a 'ctype' object");
- return NULL;
- }
- align = get_alignment((CTypeDescrObject *)arg);
- if (align < 0)
- return NULL;
- return PyInt_FromLong(align);
-}
-
-static Py_ssize_t direct_sizeof_cdata(CDataObject *cd)
-{
- Py_ssize_t size;
- if (cd->c_type->ct_flags & CT_ARRAY)
- size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
- else {
- size = -1;
- if (cd->c_type->ct_flags & (CT_STRUCT | CT_UNION))
- size = _cdata_var_byte_size(cd);
- if (size < 0)
- size = cd->c_type->ct_size;
- }
- return size;
-}
-
-static PyObject *b_sizeof(PyObject *self, PyObject *arg)
-{
- Py_ssize_t size;
-
- if (CData_Check(arg)) {
- size = direct_sizeof_cdata((CDataObject *)arg);
- }
- else if (CTypeDescr_Check(arg)) {
- size = ((CTypeDescrObject *)arg)->ct_size;
- if (size < 0) {
- PyErr_Format(PyExc_ValueError, "ctype '%s' is of unknown size",
- ((CTypeDescrObject *)arg)->ct_name);
- return NULL;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "expected a 'cdata' or 'ctype' object");
- return NULL;
- }
- return PyInt_FromSsize_t(size);
-}
-
-static PyObject *b_typeof(PyObject *self, PyObject *arg)
-{
- PyObject *res;
-
- if (!CData_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
- return NULL;
- }
- res = (PyObject *)((CDataObject *)arg)->c_type;
- Py_INCREF(res);
- return res;
-}
-
-static CTypeDescrObject *direct_typeoffsetof(CTypeDescrObject *ct,
- PyObject *fieldname,
- int following, Py_ssize_t *offset)
-{
- /* Does not return a new reference! */
- CTypeDescrObject *res;
- CFieldObject *cf;
-
- if (PyTextAny_Check(fieldname)) {
- if (!following && (ct->ct_flags & CT_POINTER))
- ct = ct->ct_itemdescr;
- if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
- PyErr_SetString(PyExc_TypeError,
- "with a field name argument, expected a "
- "struct or union ctype");
- return NULL;
- }
- if (force_lazy_struct(ct) <= 0) {
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError, "struct/union is opaque");
- return NULL;
- }
- cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, fieldname);
- if (cf == NULL) {
- PyErr_SetObject(PyExc_KeyError, fieldname);
- return NULL;
- }
- if (cf->cf_bitshift >= 0) {
- PyErr_SetString(PyExc_TypeError, "not supported for bitfields");
- return NULL;
- }
- res = cf->cf_type;
- *offset = cf->cf_offset;
- }
- else {
- Py_ssize_t index = PyInt_AsSsize_t(fieldname);
- if (index < 0 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "field name or array index expected");
- return NULL;
- }
-
- if (!(ct->ct_flags & (CT_ARRAY|CT_POINTER)) ||
- ct->ct_itemdescr->ct_size < 0) {
- PyErr_SetString(PyExc_TypeError, "with an integer argument, "
- "expected an array ctype or a "
- "pointer to non-opaque");
- return NULL;
- }
- res = ct->ct_itemdescr;
- *offset = MUL_WRAPAROUND(index, ct->ct_itemdescr->ct_size);
- if ((*offset / ct->ct_itemdescr->ct_size) != index) {
- PyErr_SetString(PyExc_OverflowError,
- "array offset would overflow a Py_ssize_t");
- return NULL;
- }
- }
- return res;
-}
-
-static PyObject *b_typeoffsetof(PyObject *self, PyObject *args)
-{
- PyObject *res, *fieldname;
- CTypeDescrObject *ct;
- Py_ssize_t offset;
- int following = 0;
-
- if (!PyArg_ParseTuple(args, "O!O|i:typeoffsetof",
- &CTypeDescr_Type, &ct, &fieldname, &following))
- return NULL;
-
- res = (PyObject *)direct_typeoffsetof(ct, fieldname, following, &offset);
- if (res == NULL)
- return NULL;
-
- return Py_BuildValue("(On)", res, offset);
-}
-
-static PyObject *b_rawaddressof(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- CDataObject *cd;
- Py_ssize_t offset;
- int accepted_flags;
-
- if (!PyArg_ParseTuple(args, "O!O!n:rawaddressof",
- &CTypeDescr_Type, &ct,
- &CData_Type, &cd,
- &offset))
- return NULL;
-
- accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER;
- if ((cd->c_type->ct_flags & accepted_flags) == 0) {
- PyErr_SetString(PyExc_TypeError,
- "expected a cdata struct/union/array/pointer object");
- return NULL;
- }
- if ((ct->ct_flags & CT_POINTER) == 0) {
- PyErr_SetString(PyExc_TypeError,
- "expected a pointer ctype");
- return NULL;
- }
- return new_simple_cdata(cd->c_data + offset, ct);
-}
-
-static PyObject *b_getcname(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- char *replace_with, *p, *s;
- Py_ssize_t namelen, replacelen;
-
- if (!PyArg_ParseTuple(args, "O!s:getcname",
- &CTypeDescr_Type, &ct, &replace_with))
- return NULL;
-
- namelen = strlen(ct->ct_name);
- replacelen = strlen(replace_with);
- s = p = alloca(namelen + replacelen + 1);
- memcpy(p, ct->ct_name, ct->ct_name_position);
- p += ct->ct_name_position;
- memcpy(p, replace_with, replacelen);
- p += replacelen;
- memcpy(p, ct->ct_name + ct->ct_name_position,
- namelen - ct->ct_name_position);
-
- return PyText_FromStringAndSize(s, namelen + replacelen);
-}
-
-static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds)
-{
- CDataObject *cd;
- Py_ssize_t maxlen = -1;
- static char *keywords[] = {"cdata", "maxlen", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:string", keywords,
- &CData_Type, &cd, &maxlen))
- return NULL;
-
- if (cd->c_type->ct_itemdescr != NULL &&
- cd->c_type->ct_itemdescr->ct_flags & (CT_PRIMITIVE_CHAR |
- CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED) &&
- !(cd->c_type->ct_itemdescr->ct_flags & CT_IS_BOOL)) {
- Py_ssize_t length = maxlen;
- if (cd->c_data == NULL) {
- PyObject *s = cdata_repr(cd);
- if (s != NULL) {
- PyErr_Format(PyExc_RuntimeError,
- "cannot use string() on %s",
- PyText_AS_UTF8(s));
- Py_DECREF(s);
- }
- return NULL;
- }
- if (length < 0 && cd->c_type->ct_flags & CT_ARRAY) {
- length = get_array_length(cd);
- }
- if (cd->c_type->ct_itemdescr->ct_size == sizeof(char)) {
- const char *start = cd->c_data;
- if (length < 0) {
- /*READ(start, 1)*/
- length = strlen(start);
- /*READ(start, length)*/
- }
- else {
- const char *end;
- /*READ(start, length)*/
- end = (const char *)memchr(start, 0, length);
- if (end != NULL)
- length = end - start;
- }
- return PyBytes_FromStringAndSize(start, length);
- }
- else if (cd->c_type->ct_itemdescr->ct_flags & CT_PRIMITIVE_CHAR) {
- switch (cd->c_type->ct_itemdescr->ct_size) {
- case 2: {
- const cffi_char16_t *start = (cffi_char16_t *)cd->c_data;
- if (length < 0) {
- /*READ(start, 2)*/
- length = 0;
- while (start[length])
- length++;
- /*READ(start, 2 * length)*/
- }
- else {
- /*READ(start, 2 * length)*/
- maxlen = length;
- length = 0;
- while (length < maxlen && start[length])
- length++;
- }
- return _my_PyUnicode_FromChar16(start, length);
- }
- case 4: {
- const cffi_char32_t *start = (cffi_char32_t *)cd->c_data;
- if (length < 0) {
- /*READ(start, 4)*/
- length = 0;
- while (start[length])
- length++;
- /*READ(start, 4 * length)*/
- }
- else {
- /*READ(start, 4 * length)*/
- maxlen = length;
- length = 0;
- while (length < maxlen && start[length])
- length++;
- }
- return _my_PyUnicode_FromChar32(start, length);
- }
- }
- }
- }
- else if (cd->c_type->ct_flags & CT_IS_ENUM) {
- return convert_cdata_to_enum_string(cd, 0);
- }
- else if (cd->c_type->ct_flags & CT_IS_BOOL) {
- /* fall through to TypeError */
- }
- else if (cd->c_type->ct_flags & (CT_PRIMITIVE_CHAR |
- CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED)) {
- /*READ(cd->c_data, cd->c_type->ct_size)*/
- if (cd->c_type->ct_size == sizeof(char))
- return PyBytes_FromStringAndSize(cd->c_data, 1);
- else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
- switch (cd->c_type->ct_size) {
- case 2:
- return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data, 1);
- case 4:
- return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data, 1);
- }
- }
- }
- PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument",
- cd->c_type->ct_name);
- return NULL;
-}
-
-static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds)
-{
- CDataObject *cd;
- CTypeDescrObject *ctitem;
- Py_ssize_t i, length, itemsize;
- PyObject *result;
- char *src;
- int casenum;
- static char *keywords[] = {"cdata", "length", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!n:unpack", keywords,
- &CData_Type, &cd, &length))
- return NULL;
-
- if (!(cd->c_type->ct_flags & (CT_ARRAY|CT_POINTER))) {
- PyErr_Format(PyExc_TypeError,
- "expected a pointer or array, got '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- if (length < 0) {
- PyErr_SetString(PyExc_ValueError, "'length' cannot be negative");
- return NULL;
- }
- if (cd->c_data == NULL) {
- PyObject *s = cdata_repr(cd);
- if (s != NULL) {
- PyErr_Format(PyExc_RuntimeError,
- "cannot use unpack() on %s",
- PyText_AS_UTF8(s));
- Py_DECREF(s);
- }
- return NULL;
- }
-
- /* byte- and unicode strings */
- ctitem = cd->c_type->ct_itemdescr;
- if (ctitem->ct_flags & CT_PRIMITIVE_CHAR) {
- switch (ctitem->ct_size) {
- case sizeof(char):
- return PyBytes_FromStringAndSize(cd->c_data, length);
- case 2:
- return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data,length);
- case 4:
- return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data,length);
- }
- }
-
- /* else, the result is a list. This implementation should be
- equivalent to but much faster than '[p[i] for i in range(length)]'.
- (Note that on PyPy, 'list(p[0:length])' should be equally fast,
- but arguably, finding out that there *is* such an unexpected way
- to write things down is the real problem.)
- */
- result = PyList_New(length);
- if (result == NULL)
- return NULL;
-
- src = cd->c_data;
- itemsize = ctitem->ct_size;
- if (itemsize < 0) {
- Py_DECREF(result);
- PyErr_Format(PyExc_ValueError, "'%s' points to items of unknown size",
- cd->c_type->ct_name);
- return NULL;
- }
-
- /* Determine some common fast-paths for the loop below. The case -1
- is the fall-back, which always gives the right answer. */
-
-#define ALIGNMENT_CHECK(align) \
- (((align) & ((align) - 1)) == 0 && \
- (((uintptr_t)src) & ((align) - 1)) == 0)
-
- casenum = -1;
-
- if ((ctitem->ct_flags & CT_PRIMITIVE_ANY) &&
- ALIGNMENT_CHECK(ctitem->ct_length)) {
- /* Source data is fully aligned; we can directly read without
- memcpy(). The unaligned case is expected to be rare; in
- this situation it is ok to fall back to the general
- convert_to_object() in the loop. For now we also use this
- fall-back for types that are too large.
- */
- if (ctitem->ct_flags & CT_PRIMITIVE_SIGNED) {
- if (itemsize == sizeof(long)) casenum = 3;
- else if (itemsize == sizeof(int)) casenum = 2;
- else if (itemsize == sizeof(short)) casenum = 1;
- else if (itemsize == sizeof(signed char)) casenum = 0;
- }
- else if (ctitem->ct_flags & CT_PRIMITIVE_UNSIGNED) {
- /* Note: we never pick case 6 if sizeof(int) == sizeof(long),
- so that case 6 below can assume that the 'unsigned int' result
- would always fit in a 'signed long'. */
- if (ctitem->ct_flags & CT_IS_BOOL) casenum = 11;
- else if (itemsize == sizeof(unsigned long)) casenum = 7;
- else if (itemsize == sizeof(unsigned int)) casenum = 6;
- else if (itemsize == sizeof(unsigned short)) casenum = 5;
- else if (itemsize == sizeof(unsigned char)) casenum = 4;
- }
- else if (ctitem->ct_flags & CT_PRIMITIVE_FLOAT) {
- if (itemsize == sizeof(double)) casenum = 9;
- else if (itemsize == sizeof(float)) casenum = 8;
- }
- }
- else if (ctitem->ct_flags & (CT_POINTER | CT_FUNCTIONPTR)) {
- casenum = 10; /* any pointer */
- }
-#undef ALIGNMENT_CHECK
-
- for (i = 0; i < length; i++) {
- PyObject *x;
- switch (casenum) {
- /* general case */
- default: x = convert_to_object(src, ctitem); break;
-
- /* special cases for performance only */
- case 0: x = PyInt_FromLong(*(signed char *)src); break;
- case 1: x = PyInt_FromLong(*(short *)src); break;
- case 2: x = PyInt_FromLong(*(int *)src); break;
- case 3: x = PyInt_FromLong(*(long *)src); break;
- case 4: x = PyInt_FromLong(*(unsigned char *)src); break;
- case 5: x = PyInt_FromLong(*(unsigned short *)src); break;
- case 6: x = PyInt_FromLong((long)*(unsigned int *)src); break;
- case 7: x = PyLong_FromUnsignedLong(*(unsigned long *)src); break;
- case 8: x = PyFloat_FromDouble(*(float *)src); break;
- case 9: x = PyFloat_FromDouble(*(double *)src); break;
- case 10: x = new_simple_cdata(*(char **)src, ctitem); break;
- case 11:
- switch (*(unsigned char *)src) {
- case 0: x = Py_False; Py_INCREF(x); break;
- case 1: x = Py_True; Py_INCREF(x); break;
- default: x = convert_to_object(src, ctitem); /* error */
- }
- break;
- }
- if (x == NULL) {
- Py_DECREF(result);
- return NULL;
- }
- PyList_SET_ITEM(result, i, x);
- src += itemsize;
- }
- return result;
-}
-
-static PyObject *
-b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- /* this is the constructor of the type implemented in minibuffer.h */
- CDataObject *cd;
- Py_ssize_t size = -1;
- static char *keywords[] = {"cdata", "size", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:buffer", keywords,
- &CData_Type, &cd, &size))
- return NULL;
-
- if (size < 0)
- size = _cdata_var_byte_size(cd);
-
- if (cd->c_type->ct_flags & CT_POINTER) {
- if (size < 0)
- size = cd->c_type->ct_itemdescr->ct_size;
- }
- else if (cd->c_type->ct_flags & CT_ARRAY) {
- if (size < 0)
- size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "expected a pointer or array cdata, got '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- if (size < 0) {
- PyErr_Format(PyExc_TypeError,
- "don't know the size pointed to by '%s'",
- cd->c_type->ct_name);
- return NULL;
- }
- /*WRITE(cd->c_data, size)*/
- return minibuffer_new(cd->c_data, size, (PyObject *)cd);
-}
-
-static PyObject *b_get_errno(PyObject *self, PyObject *noarg)
-{
- int err;
- restore_errno_only();
- err = errno;
- errno = 0;
- return PyInt_FromLong(err);
-}
-
-static PyObject *b_set_errno(PyObject *self, PyObject *arg)
-{
- long ival = PyInt_AsLong(arg);
- if (ival == -1 && PyErr_Occurred())
- return NULL;
- else if (ival < INT_MIN || ival > INT_MAX) {
- PyErr_SetString(PyExc_OverflowError, "errno value too large");
- return NULL;
- }
- errno = (int)ival;
- save_errno_only();
- errno = 0;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *newp_handle(CTypeDescrObject *ct_voidp, PyObject *x)
-{
- CDataObject_own_structptr *cd;
- cd = (CDataObject_own_structptr *)PyObject_GC_New(CDataObject_own_structptr,
- &CDataOwningGC_Type);
- if (cd == NULL)
- return NULL;
- Py_INCREF(ct_voidp); /* must be "void *" */
- cd->head.c_type = ct_voidp;
- cd->head.c_data = (char *)cd;
- cd->head.c_weakreflist = NULL;
- Py_INCREF(x);
- cd->structobj = x;
- PyObject_GC_Track(cd);
- return (PyObject *)cd;
-}
-
-static PyObject *b_newp_handle(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *x;
- if (!PyArg_ParseTuple(args, "O!O", &CTypeDescr_Type, &ct, &x))
- return NULL;
-
- if (!(ct->ct_flags & CT_IS_VOID_PTR)) {
- PyErr_Format(PyExc_TypeError, "needs 'void *', got '%s'", ct->ct_name);
- return NULL;
- }
-
- return newp_handle(ct, x);
-}
-
-static PyObject *b_from_handle(PyObject *self, PyObject *arg)
-{
- CTypeDescrObject *ct;
- CDataObject_own_structptr *orgcd;
- PyObject *x;
- if (!CData_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
- return NULL;
- }
- ct = ((CDataObject *)arg)->c_type;
- if (!(ct->ct_flags & CT_IS_VOIDCHAR_PTR)) {
- PyErr_Format(PyExc_TypeError,
- "expected a 'cdata' object with a 'void *' out of "
- "new_handle(), got '%s'", ct->ct_name);
- return NULL;
- }
- orgcd = (CDataObject_own_structptr *)((CDataObject *)arg)->c_data;
- if (!orgcd) {
- PyErr_SetString(PyExc_RuntimeError,
- "cannot use from_handle() on NULL pointer");
- return NULL;
- }
- if (Py_REFCNT(orgcd) <= 0 || Py_TYPE(orgcd) != &CDataOwningGC_Type) {
- Py_FatalError("ffi.from_handle() detected that the address passed "
- "points to garbage. If it is really the result of "
- "ffi.new_handle(), then the Python object has already "
- "been garbage collected");
- }
- x = orgcd->structobj;
- Py_INCREF(x);
- return x;
-}
-
-static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view,
- int writable_only)
-{
-#if PY_MAJOR_VERSION < 3
- /* Some objects only support the buffer interface and CPython doesn't
- translate it into the memoryview interface, mess. Hack a very
- minimal content for 'view'. Don't care if the other fields are
- uninitialized: we only call PyBuffer_Release(), which only reads
- 'view->obj'. */
- PyBufferProcs *pb = x->ob_type->tp_as_buffer;
- if (pb && !pb->bf_releasebuffer) {
- /* we used to try all three in some vaguely sensible order,
- i.e. first the write. But trying to call the write on a
- read-only buffer fails with TypeError. So we use a less-
- sensible order now. See test_from_buffer_more_cases.
-
- If 'writable_only', we only try bf_getwritebuffer.
- */
- readbufferproc proc = NULL;
- if (!writable_only) {
- proc = (readbufferproc)pb->bf_getreadbuffer;
- if (!proc)
- proc = (readbufferproc)pb->bf_getcharbuffer;
- }
- if (!proc)
- proc = (readbufferproc)pb->bf_getwritebuffer;
-
- if (proc && pb->bf_getsegcount) {
- if ((*pb->bf_getsegcount)(x, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
- return -1;
- }
- view->len = (*proc)(x, 0, &view->buf);
- if (view->len < 0)
- return -1;
- view->obj = x;
- Py_INCREF(x);
- return 0;
- }
- }
-#endif
-
- if (PyObject_GetBuffer(x, view, writable_only ? PyBUF_WRITABLE
- : PyBUF_SIMPLE) < 0)
- return -1;
-
- if (!PyBuffer_IsContiguous(view, 'A')) {
- PyBuffer_Release(view);
- PyErr_SetString(PyExc_TypeError, "contiguous buffer expected");
- return -1;
- }
- return 0;
-}
-
-static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x,
- int require_writable)
-{
- CDataObject *cd;
- Py_buffer *view;
- Py_ssize_t arraylength, minimumlength = 0;
-
- if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) {
- PyErr_Format(PyExc_TypeError,
- "expected a pointer or array ctype, got '%s'",
- ct->ct_name);
- return NULL;
- }
-
- /* PyPy 5.7 can obtain buffers for string (python 2)
- or bytes (python 3). from_buffer(u"foo") is disallowed.
- */
- if (PyUnicode_Check(x)) {
- PyErr_SetString(PyExc_TypeError,
- "from_buffer() cannot return the address "
- "of a unicode object");
- return NULL;
- }
-
- view = PyObject_Malloc(sizeof(Py_buffer));
- if (view == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0)
- goto error1;
-
- if (ct->ct_flags & CT_POINTER)
- {
- arraylength = view->len; /* number of bytes, not used so far */
- }
- else {
- /* ct->ct_flags & CT_ARRAY */
- if (ct->ct_length >= 0) {
- /* it's an array with a fixed length; make sure that the
- buffer contains enough bytes. */
- minimumlength = ct->ct_size;
- arraylength = ct->ct_length;
- }
- else {
- /* it's an open 'array[]' */
- if (ct->ct_itemdescr->ct_size == 1) {
- /* fast path, performance only */
- arraylength = view->len;
- }
- else if (ct->ct_itemdescr->ct_size > 0) {
- /* give it as many items as fit the buffer. Ignore a
- partial last element. */
- arraylength = view->len / ct->ct_itemdescr->ct_size;
- }
- else {
- /* it's an array 'empty[]'. Unsupported obscure case:
- the problem is that setting the length of the result
- to anything large (like SSIZE_T_MAX) is dangerous,
- because if someone tries to loop over it, it will
- turn effectively into an infinite loop. */
- PyErr_Format(PyExc_ZeroDivisionError,
- "from_buffer('%s', ..): the actual length of the array "
- "cannot be computed", ct->ct_name);
- goto error2;
- }
- }
- }
- if (view->len < minimumlength) {
- PyErr_Format(PyExc_ValueError,
- "buffer is too small (%zd bytes) for '%s' (%zd bytes)",
- view->len, ct->ct_name, minimumlength);
- goto error2;
- }
-
- cd = (CDataObject *)PyObject_GC_New(CDataObject_frombuf,
- &CDataFromBuf_Type);
- if (cd == NULL)
- goto error2;
-
- Py_INCREF(ct);
- cd->c_type = ct;
- cd->c_data = view->buf;
- cd->c_weakreflist = NULL;
- ((CDataObject_frombuf *)cd)->length = arraylength;
- ((CDataObject_frombuf *)cd)->bufferview = view;
- PyObject_GC_Track(cd);
- return (PyObject *)cd;
-
- error2:
- PyBuffer_Release(view);
- error1:
- PyObject_Free(view);
- return NULL;
-}
-
-static PyObject *b_from_buffer(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *x;
- int require_writable = 0;
-
- if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x,
- &require_writable))
- return NULL;
-
- return direct_from_buffer(ct, x, require_writable);
-}
-
-static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only)
-{
- if (CData_Check(x)) {
- CTypeDescrObject *ct = ((CDataObject *)x)->c_type;
- if (!(ct->ct_flags & (CT_POINTER|CT_ARRAY))) {
- PyErr_Format(PyExc_TypeError,
- "expected a pointer or array ctype, got '%s'",
- ct->ct_name);
- return -1;
- }
- view->buf = ((CDataObject *)x)->c_data;
- view->obj = NULL;
- return 0;
- }
- else {
- return _my_PyObject_GetContiguousBuffer(x, view, writable_only);
- }
-}
-
-static PyObject *b_memmove(PyObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *dest_obj, *src_obj;
- Py_buffer dest_view, src_view;
- Py_ssize_t n;
- static char *keywords[] = {"dest", "src", "n", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOn", keywords,
- &dest_obj, &src_obj, &n))
- return NULL;
- if (n < 0) {
- PyErr_SetString(PyExc_ValueError, "negative size");
- return NULL;
- }
-
- if (_fetch_as_buffer(src_obj, &src_view, 0) < 0) {
- return NULL;
- }
- if (_fetch_as_buffer(dest_obj, &dest_view, 1) < 0) {
- PyBuffer_Release(&src_view);
- return NULL;
- }
-
- memmove(dest_view.buf, src_view.buf, n);
-
- PyBuffer_Release(&dest_view);
- PyBuffer_Release(&src_view);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *b__get_types(PyObject *self, PyObject *noarg)
-{
- return PyTuple_Pack(2, (PyObject *)&CData_Type,
- (PyObject *)&CTypeDescr_Type);
-}
-
-/* forward, in commontypes.c */
-static PyObject *b__get_common_types(PyObject *self, PyObject *arg);
-
-static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds)
-{
- CDataObject *cd;
- CDataObject *origobj;
- PyObject *destructor;
- Py_ssize_t ignored; /* for pypy */
- static char *keywords[] = {"cdata", "destructor", "size", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|n:gc", keywords,
- &CData_Type, &origobj, &destructor,
- &ignored))
- return NULL;
-
- if (destructor == Py_None) {
- if (!PyObject_TypeCheck(origobj, &CDataGCP_Type)) {
- PyErr_SetString(PyExc_TypeError,
- "Can remove destructor only on a object "
- "previously returned by ffi.gc()");
- return NULL;
- }
- Py_CLEAR(((CDataObject_gcp *)origobj)->destructor);
- Py_RETURN_NONE;
- }
-
- cd = allocate_gcp_object(origobj, origobj->c_type, destructor);
- return (PyObject *)cd;
-}
-
-static PyObject *b_release(PyObject *self, PyObject *arg)
-{
- if (!CData_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
- return NULL;
- }
- return cdata_exit(arg, NULL);
-}
-
-/************************************************************/
-
-static char _testfunc0(char a, char b)
-{
- return a + b;
-}
-static long _testfunc1(int a, long b)
-{
- return (long)a + b;
-}
-static PY_LONG_LONG _testfunc2(PY_LONG_LONG a, PY_LONG_LONG b)
-{
- return a + b;
-}
-static double _testfunc3(float a, double b)
-{
- return a + b;
-}
-static float _testfunc4(float a, double b)
-{
- return (float)(a + b);
-}
-static void _testfunc5(void)
-{
- errno = errno + 15;
-}
-static int *_testfunc6(int *x)
-{
- static int y;
- y = *x - 1000;
- return &y;
-}
-struct _testfunc7_s { unsigned char a1; short a2; };
-static short _testfunc7(struct _testfunc7_s inlined)
-{
- return inlined.a1 + inlined.a2;
-}
-static int _testfunc9(int num, ...)
-{
- va_list vargs;
- int i, total = 0;
- va_start(vargs, num);
- for (i=0; i<num; i++) {
- int value = va_arg(vargs, int);
- if (value == 0)
- value = -66666666;
- total += value;
- }
- va_end(vargs);
- return total;
-}
-
-static struct _testfunc7_s _testfunc10(int n)
-{
- struct _testfunc7_s result;
- result.a1 = n;
- result.a2 = n * n;
- return result;
-}
-
-struct _testfunc11_s { int a1, a2; };
-static struct _testfunc11_s _testfunc11(int n)
-{
- struct _testfunc11_s result;
- result.a1 = n;
- result.a2 = n * n;
- return result;
-}
-
-struct _testfunc12_s { double a1; };
-static struct _testfunc12_s _testfunc12(int n)
-{
- struct _testfunc12_s result;
- result.a1 = n;
- return result;
-}
-
-struct _testfunc13_s { int a1, a2, a3; };
-static struct _testfunc13_s _testfunc13(int n)
-{
- struct _testfunc13_s result;
- result.a1 = n;
- result.a2 = n * n;
- result.a3 = n * n * n;
- return result;
-}
-
-struct _testfunc14_s { float a1; };
-static struct _testfunc14_s _testfunc14(int n)
-{
- struct _testfunc14_s result;
- result.a1 = (float)n;
- return result;
-}
-
-struct _testfunc15_s { float a1; int a2; };
-static struct _testfunc15_s _testfunc15(int n)
-{
- struct _testfunc15_s result;
- result.a1 = (float)n;
- result.a2 = n * n;
- return result;
-}
-
-struct _testfunc16_s { float a1, a2; };
-static struct _testfunc16_s _testfunc16(int n)
-{
- struct _testfunc16_s result;
- result.a1 = (float)n;
- result.a2 = -(float)n;
- return result;
-}
-
-struct _testfunc17_s { int a1; float a2; };
-static struct _testfunc17_s _testfunc17(int n)
-{
- struct _testfunc17_s result;
- result.a1 = n;
- result.a2 = (float)n * (float)n;
- return result;
-}
-
-static int _testfunc18(struct _testfunc17_s *ptr)
-{
- return ptr->a1 + (int)ptr->a2;
-}
-
-static long double _testfunc19(long double x, int count)
-{
- int i;
- for (i=0; i<count; i++) {
- x = 4*x - x*x;
- }
- return x;
-}
-
-static short _testfunc20(struct _testfunc7_s *ptr)
-{
- return ptr->a1 + ptr->a2;
-}
-
-struct _testfunc21_s { int a, b, c, d, e, f, g, h, i, j; };
-static int _testfunc21(struct _testfunc21_s inlined)
-{
- return ((inlined.a << 0) +
- (inlined.b << 1) +
- (inlined.c << 2) +
- (inlined.d << 3) +
- (inlined.e << 4) +
- (inlined.f << 5) +
- (inlined.g << 6) +
- (inlined.h << 7) +
- (inlined.i << 8) +
- (inlined.j << 9));
-}
-
-struct _testfunc22_s { int a[10]; };
-static struct _testfunc22_s _testfunc22(struct _testfunc22_s s1,
- struct _testfunc22_s s2)
-{
- struct _testfunc22_s result;
- int i;
- for (i=0; i<10; i++)
- result.a[i] = s1.a[i] - s2.a[i];
- return result;
-}
-
-static int _testfunc23(char *p)
-{
- if (p)
- return 1000 * p[0];
- return -42;
-}
-
-#if 0 /* libffi doesn't properly support complexes currently */
- /* also, MSVC might not support _Complex... */
- /* if this is enabled one day, remember to also add _Complex
- * arguments in addition to return values. */
-static float _Complex _testfunc24(float a, float b)
-{
- return a + I*2.0*b;
-}
-static double _Complex _testfunc25(double a, double b)
-{
- return a + I*2.0*b;
-}
-#endif
-
-static PyObject *b__testfunc(PyObject *self, PyObject *args)
-{
- /* for testing only */
- int i;
- void *f;
- if (!PyArg_ParseTuple(args, "i:_testfunc", &i))
- return NULL;
- switch (i) {
- case 0: f = &_testfunc0; break;
- case 1: f = &_testfunc1; break;
- case 2: f = &_testfunc2; break;
- case 3: f = &_testfunc3; break;
- case 4: f = &_testfunc4; break;
- case 5: f = &_testfunc5; break;
- case 6: f = &_testfunc6; break;
- case 7: f = &_testfunc7; break;
- case 8: f = stderr; break;
- case 9: f = &_testfunc9; break;
- case 10: f = &_testfunc10; break;
- case 11: f = &_testfunc11; break;
- case 12: f = &_testfunc12; break;
- case 13: f = &_testfunc13; break;
- case 14: f = &_testfunc14; break;
- case 15: f = &_testfunc15; break;
- case 16: f = &_testfunc16; break;
- case 17: f = &_testfunc17; break;
- case 18: f = &_testfunc18; break;
- case 19: f = &_testfunc19; break;
- case 20: f = &_testfunc20; break;
- case 21: f = &_testfunc21; break;
- case 22: f = &_testfunc22; break;
- case 23: f = &_testfunc23; break;
-#if 0
- case 24: f = &_testfunc24; break;
- case 25: f = &_testfunc25; break;
-#endif
- default:
- PyErr_SetNone(PyExc_ValueError);
- return NULL;
- }
- return PyLong_FromVoidPtr(f);
-}
-
-#if PY_MAJOR_VERSION < 3
-static Py_ssize_t _test_segcountproc(PyObject *o, Py_ssize_t *ignored)
-{
- return 1;
-}
-static Py_ssize_t _test_getreadbuf(PyObject *o, Py_ssize_t i, void **r)
-{
- static char buf[] = "RDB";
- *r = buf;
- return 3;
-}
-static Py_ssize_t _test_getwritebuf(PyObject *o, Py_ssize_t i, void **r)
-{
- static char buf[] = "WRB";
- *r = buf;
- return 3;
-}
-static Py_ssize_t _test_getcharbuf(PyObject *o, Py_ssize_t i, char **r)
-{
- static char buf[] = "CHB";
- *r = buf;
- return 3;
-}
-#endif
-static int _test_getbuf(PyObject *self, Py_buffer *view, int flags)
-{
- static char buf[] = "GTB";
- return PyBuffer_FillInfo(view, self, buf, 3, /*readonly=*/0, flags);
-}
-static int _test_getbuf_ro(PyObject *self, Py_buffer *view, int flags)
-{
- static char buf[] = "ROB";
- return PyBuffer_FillInfo(view, self, buf, 3, /*readonly=*/1, flags);
-}
-
-
-static PyObject *b__testbuff(PyObject *self, PyObject *args)
-{
- /* for testing only */
- int methods;
- PyTypeObject *obj;
- if (!PyArg_ParseTuple(args, "O!i|_testbuff", &PyType_Type, &obj, &methods))
- return NULL;
-
- assert(obj->tp_as_buffer != NULL);
-
-#if PY_MAJOR_VERSION < 3
- obj->tp_as_buffer->bf_getsegcount = &_test_segcountproc;
- obj->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER;
- obj->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
- if (methods & 1) obj->tp_as_buffer->bf_getreadbuffer = &_test_getreadbuf;
- if (methods & 2) obj->tp_as_buffer->bf_getwritebuffer = &_test_getwritebuf;
- if (methods & 4) obj->tp_as_buffer->bf_getcharbuffer = &_test_getcharbuf;
-#endif
- if (methods & 8) obj->tp_as_buffer->bf_getbuffer = &_test_getbuf;
- if (methods & 16) obj->tp_as_buffer->bf_getbuffer = &_test_getbuf_ro;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *b_init_cffi_1_0_external_module(PyObject *, PyObject *);
-/* forward, see cffi1_module.c */
-
-
-static PyMethodDef FFIBackendMethods[] = {
- {"load_library", b_load_library, METH_VARARGS},
- {"new_primitive_type", b_new_primitive_type, METH_VARARGS},
- {"new_pointer_type", b_new_pointer_type, METH_VARARGS},
- {"new_array_type", b_new_array_type, METH_VARARGS},
- {"new_void_type", b_new_void_type, METH_NOARGS},
- {"new_struct_type", b_new_struct_type, METH_VARARGS},
- {"new_union_type", b_new_union_type, METH_VARARGS},
- {"complete_struct_or_union", b_complete_struct_or_union, METH_VARARGS},
- {"new_function_type", b_new_function_type, METH_VARARGS},
- {"new_enum_type", b_new_enum_type, METH_VARARGS},
- {"newp", b_newp, METH_VARARGS},
- {"cast", b_cast, METH_VARARGS},
- {"callback", b_callback, METH_VARARGS},
- {"alignof", b_alignof, METH_O},
- {"sizeof", b_sizeof, METH_O},
- {"typeof", b_typeof, METH_O},
- {"typeoffsetof", b_typeoffsetof, METH_VARARGS},
- {"rawaddressof", b_rawaddressof, METH_VARARGS},
- {"getcname", b_getcname, METH_VARARGS},
- {"string", (PyCFunction)b_string, METH_VARARGS | METH_KEYWORDS},
- {"unpack", (PyCFunction)b_unpack, METH_VARARGS | METH_KEYWORDS},
- {"get_errno", b_get_errno, METH_NOARGS},
- {"set_errno", b_set_errno, METH_O},
- {"newp_handle", b_newp_handle, METH_VARARGS},
- {"from_handle", b_from_handle, METH_O},
- {"from_buffer", b_from_buffer, METH_VARARGS},
- {"memmove", (PyCFunction)b_memmove, METH_VARARGS | METH_KEYWORDS},
- {"gcp", (PyCFunction)b_gcp, METH_VARARGS | METH_KEYWORDS},
- {"release", b_release, METH_O},
-#ifdef MS_WIN32
- {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS},
-#endif
- {"_get_types", b__get_types, METH_NOARGS},
- {"_get_common_types", b__get_common_types, METH_O},
- {"_testfunc", b__testfunc, METH_VARARGS},
- {"_testbuff", b__testbuff, METH_VARARGS},
- {"_init_cffi_1_0_external_module", b_init_cffi_1_0_external_module, METH_O},
- {NULL, NULL} /* Sentinel */
-};
-
-/************************************************************/
-/* Functions used by '_cffi_N.so', the generated modules */
-
-#define _cffi_to_c_SIGNED_FN(RETURNTYPE, SIZE) \
-static RETURNTYPE _cffi_to_c_i##SIZE(PyObject *obj) { \
- PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj); \
- if ((tmp > (PY_LONG_LONG)((1ULL<<(SIZE-1)) - 1)) || \
- (tmp < (PY_LONG_LONG)(0ULL-(1ULL<<(SIZE-1))))) \
- if (!PyErr_Occurred()) \
- return (RETURNTYPE)_convert_overflow(obj, #SIZE "-bit int"); \
- return (RETURNTYPE)tmp; \
-}
-
-#define _cffi_to_c_UNSIGNED_FN(RETURNTYPE, SIZE) \
-static RETURNTYPE _cffi_to_c_u##SIZE(PyObject *obj) { \
- unsigned PY_LONG_LONG tmp = _my_PyLong_AsUnsignedLongLong(obj, 1); \
- if (tmp > ~(((unsigned PY_LONG_LONG)-2) << (SIZE-1))) \
- if (!PyErr_Occurred()) \
- return (RETURNTYPE)_convert_overflow(obj, \
- #SIZE "-bit unsigned int"); \
- return (RETURNTYPE)tmp; \
-}
-
-_cffi_to_c_SIGNED_FN(int, 8)
-_cffi_to_c_SIGNED_FN(int, 16)
-_cffi_to_c_SIGNED_FN(int, 32)
-_cffi_to_c_SIGNED_FN(PY_LONG_LONG, 64)
-_cffi_to_c_UNSIGNED_FN(int, 8)
-_cffi_to_c_UNSIGNED_FN(int, 16)
-_cffi_to_c_UNSIGNED_FN(unsigned int, 32)
-_cffi_to_c_UNSIGNED_FN(unsigned PY_LONG_LONG, 64)
-
-static PyObject *_cffi_from_c_pointer(char *ptr, CTypeDescrObject *ct)
-{
- return convert_to_object((char *)&ptr, ct);
-}
-
-static char *_cffi_to_c_pointer(PyObject *obj, CTypeDescrObject *ct)
-{
- char *result;
- if (convert_from_object((char *)&result, ct, obj) < 0) {
- if ((ct->ct_flags & CT_POINTER) &&
- (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
- PyFile_Check(obj)) {
- PyErr_Clear();
- return (char *)PyFile_AsFile(obj);
- }
- return NULL;
- }
- return result;
-}
-
-static long double _cffi_to_c_long_double(PyObject *obj)
-{
- if (CData_Check(obj) &&
- (((CDataObject *)obj)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
- char *data = ((CDataObject *)obj)->c_data;
- /*READ(data, sizeof(long double))*/
- return read_raw_longdouble_data(data);
- }
- else
- return PyFloat_AsDouble(obj);
-}
-
-static _Bool _cffi_to_c__Bool(PyObject *obj)
-{
- PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj);
- if (tmp == 0)
- return 0;
- else if (tmp == 1)
- return 1;
- else if (PyErr_Occurred())
- return (_Bool)-1;
- else
- return (_Bool)_convert_overflow(obj, "_Bool");
-}
-
-static PyObject *_cffi_get_struct_layout(Py_ssize_t nums[])
-{
- PyObject *result;
- int count = 0;
- while (nums[count] >= 0)
- count++;
-
- result = PyList_New(count);
- if (result == NULL)
- return NULL;
-
- while (--count >= 0) {
- PyObject *o = PyInt_FromSsize_t(nums[count]);
- if (o == NULL) {
- Py_DECREF(result);
- return NULL;
- }
- PyList_SET_ITEM(result, count, o);
- }
- return result;
-}
-
-static PyObject *_cffi_from_c_char(char x) {
- return PyBytes_FromStringAndSize(&x, 1);
-}
-
-/* backward-compatibility hack: instead of _cffi_to_c_char16_t() and
- * _cffi_to_c_char32_t(), we have _cffi_to_c_wchar_t() handling whatever
- * size is wchar_t, and _cffi_to_c_wchar3216_t() handling the opposite.
- */
-#ifdef HAVE_WCHAR_H
-typedef wchar_t cffi_wchar_t;
-#else
-typedef uint16_t cffi_wchar_t; /* random pick... */
-#endif
-
-static cffi_wchar_t _cffi_to_c_wchar_t(PyObject *init)
-{
- if (sizeof(cffi_wchar_t) == 2)
- return (cffi_wchar_t)_convert_to_char16_t(init);
- else
- return (cffi_wchar_t)_convert_to_char32_t(init);
-}
-static PyObject *_cffi_from_c_wchar_t(cffi_wchar_t x) {
- if (sizeof(cffi_wchar_t) == 2) {
- cffi_char16_t input = x;
- return _my_PyUnicode_FromChar16(&input, 1);
- }
- else {
- cffi_char32_t input = x;
- return _my_PyUnicode_FromChar32(&input, 1);
- }
-}
-static int _cffi_to_c_wchar3216_t(PyObject *init)
-{
- if (sizeof(cffi_wchar_t) == 4)
- return (int)_convert_to_char16_t(init);
- else
- return (int)_convert_to_char32_t(init);
-}
-static PyObject *_cffi_from_c_wchar3216_t(int x) {
- if (sizeof(cffi_wchar_t) == 4) {
- cffi_char16_t input = x;
- return _my_PyUnicode_FromChar16(&input, 1);
- }
- else {
- cffi_char32_t input = x;
- return _my_PyUnicode_FromChar32(&input, 1);
- }
-}
-
-struct _cffi_externpy_s; /* forward declaration */
-static void cffi_call_python(struct _cffi_externpy_s *, char *args);
-
-static void *cffi_exports[] = {
- NULL,
- _cffi_to_c_i8,
- _cffi_to_c_u8,
- _cffi_to_c_i16,
- _cffi_to_c_u16,
- _cffi_to_c_i32,
- _cffi_to_c_u32,
- _cffi_to_c_i64,
- _cffi_to_c_u64,
- _convert_to_char,
- _cffi_from_c_pointer,
- _cffi_to_c_pointer,
- _cffi_get_struct_layout,
- restore_errno,
- save_errno,
- _cffi_from_c_char,
- convert_to_object,
- convert_from_object,
- convert_struct_to_owning_object,
- _cffi_to_c_wchar_t,
- _cffi_from_c_wchar_t,
- _cffi_to_c_long_double,
- _cffi_to_c__Bool,
- _prepare_pointer_call_argument,
- convert_array_from_object,
- cffi_call_python,
- _cffi_to_c_wchar3216_t,
- _cffi_from_c_wchar3216_t,
-};
-
-static struct { const char *name; int value; } all_dlopen_flags[] = {
- { "RTLD_LAZY", RTLD_LAZY },
- { "RTLD_NOW", RTLD_NOW },
- { "RTLD_GLOBAL", RTLD_GLOBAL },
-#ifdef RTLD_LOCAL
- { "RTLD_LOCAL", RTLD_LOCAL },
-#else
- { "RTLD_LOCAL", 0 },
-#endif
-#ifdef RTLD_NODELETE
- { "RTLD_NODELETE", RTLD_NODELETE },
-#endif
-#ifdef RTLD_NOLOAD
- { "RTLD_NOLOAD", RTLD_NOLOAD },
-#endif
-#ifdef RTLD_DEEPBIND
- { "RTLD_DEEPBIND", RTLD_DEEPBIND },
-#endif
- { NULL, 0 }
-};
-
-
-/************************************************************/
-
-#include "cffi1_module.c"
-
-/************************************************************/
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef FFIBackendModuleDef = {
- PyModuleDef_HEAD_INIT,
- "_cffi_backend",
- NULL,
- -1,
- FFIBackendMethods,
- NULL, NULL, NULL, NULL
-};
-#define INITERROR return NULL
-
-PyMODINIT_FUNC
-PyInit__cffi_backend(void)
-#else
-#define INITERROR return
-
-PyMODINIT_FUNC
-init_cffi_backend(void)
-#endif
-{
- PyObject *m, *v;
- int i;
- static char init_done = 0;
- static PyTypeObject *all_types[] = {
- &dl_type,
- &CTypeDescr_Type,
- &CField_Type,
- &CData_Type,
- &CDataOwning_Type,
- &CDataOwningGC_Type,
- &CDataFromBuf_Type,
- &CDataGCP_Type,
- &CDataIter_Type,
- &MiniBuffer_Type,
- &FFI_Type,
- &Lib_Type,
- &GlobSupport_Type,
- NULL
- };
-
- v = PySys_GetObject("version");
- if (v == NULL || !PyText_Check(v) ||
- strncmp(PyText_AS_UTF8(v), PY_VERSION, 3) != 0) {
- PyErr_Format(PyExc_ImportError,
- "this module was compiled for Python %c%c%c",
- PY_VERSION[0], PY_VERSION[1], PY_VERSION[2]);
- INITERROR;
- }
-
-#if PY_MAJOR_VERSION >= 3
- m = PyModule_Create(&FFIBackendModuleDef);
-#else
- m = Py_InitModule("_cffi_backend", FFIBackendMethods);
-#endif
-
- if (m == NULL)
- INITERROR;
-
- if (unique_cache == NULL) {
- unique_cache = PyDict_New();
- if (unique_cache == NULL)
- INITERROR;
- }
-
- /* readify all types and add them to the module */
- for (i = 0; all_types[i] != NULL; i++) {
- PyTypeObject *tp = all_types[i];
- PyObject *tpo = (PyObject *)tp;
- if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
- PyErr_Format(PyExc_ImportError,
- "'%s' is an ill-formed type name", tp->tp_name);
- INITERROR;
- }
- if (PyType_Ready(tp) < 0)
- INITERROR;
-
- Py_INCREF(tpo);
- if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
- INITERROR;
- }
-
- if (!init_done) {
- v = PyText_FromString("_cffi_backend");
- if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict,
- "__module__", v) < 0)
- INITERROR;
- v = PyText_FromString("<cdata>");
- if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict,
- "__name__", v) < 0)
- INITERROR;
- init_done = 1;
- }
-
- /* this is for backward compatibility only */
- v = PyCapsule_New((void *)cffi_exports, "cffi", NULL);
- if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
- INITERROR;
-
- v = PyText_FromString(CFFI_VERSION);
- if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0)
- INITERROR;
-
- if (PyModule_AddIntConstant(m, "FFI_DEFAULT_ABI", FFI_DEFAULT_ABI) < 0 ||
-#if defined(MS_WIN32) && !defined(_WIN64)
- PyModule_AddIntConstant(m, "FFI_STDCALL", FFI_STDCALL) < 0 ||
-#endif
- PyModule_AddIntConstant(m, "FFI_CDECL", FFI_DEFAULT_ABI) < 0 ||
-
-#ifdef MS_WIN32
-# ifdef _WIN64
- PyModule_AddIntConstant(m, "_WIN", 64) < 0 || /* win64 */
-# else
- PyModule_AddIntConstant(m, "_WIN", 32) < 0 || /* win32 */
-# endif
-#endif
- 0)
- INITERROR;
-
- for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
- if (PyModule_AddIntConstant(m,
- all_dlopen_flags[i].name,
- all_dlopen_flags[i].value) < 0)
- INITERROR;
- }
-
- init_cffi_tls();
- if (PyErr_Occurred())
- INITERROR;
- init_cffi_tls_zombie();
- if (PyErr_Occurred())
- INITERROR;
-
- if (init_ffi_lib(m) < 0)
- INITERROR;
-
-#if PY_MAJOR_VERSION >= 3
- if (init_file_emulator() < 0)
- INITERROR;
- return m;
-#endif
-}
diff --git a/c/_cffi_backend.so b/c/_cffi_backend.so
deleted file mode 100755
index 31f7528..0000000
--- a/c/_cffi_backend.so
+++ /dev/null
Binary files differ
diff --git a/c/_dummy_file_cffi_backend.py b/c/_dummy_file_cffi_backend.py
deleted file mode 100644
index e69de29..0000000
--- a/c/_dummy_file_cffi_backend.py
+++ /dev/null
diff --git a/c/_dummy_file_libffi.py b/c/_dummy_file_libffi.py
deleted file mode 100644
index e69de29..0000000
--- a/c/_dummy_file_libffi.py
+++ /dev/null
diff --git a/c/call_python.c b/c/call_python.c
deleted file mode 100644
index d3d2e17..0000000
--- a/c/call_python.c
+++ /dev/null
@@ -1,292 +0,0 @@
-#if PY_VERSION_HEX >= 0x03080000
-# define HAVE_PYINTERPSTATE_GETDICT
-#endif
-
-
-static PyObject *_current_interp_key(void)
-{
- PyInterpreterState *interp = PyThreadState_GET()->interp;
-#ifdef HAVE_PYINTERPSTATE_GETDICT
- return PyInterpreterState_GetDict(interp); /* shared reference */
-#else
- return interp->modules;
-#endif
-}
-
-static PyObject *_get_interpstate_dict(void)
-{
- /* Hack around to return a dict that is subinterpreter-local.
- Does not return a new reference. Returns NULL in case of
- error, but without setting any exception. (If called late
- during shutdown, we *can't* set an exception!)
- */
- static PyObject *attr_name = NULL;
- PyThreadState *tstate;
- PyObject *d, *interpdict;
- int err;
- PyInterpreterState *interp;
-
- tstate = PyThreadState_GET();
- if (tstate == NULL) {
- /* no thread state! */
- return NULL;
- }
-
- interp = tstate->interp;
-#ifdef HAVE_PYINTERPSTATE_GETDICT
- interpdict = PyInterpreterState_GetDict(interp); /* shared reference */
-#else
- interpdict = interp->builtins;
-#endif
- if (interpdict == NULL) {
- /* subinterpreter was cleared already, or is being cleared right now,
- to a point that is too much for us to continue */
- return NULL;
- }
-
- /* from there on, we know the (sub-)interpreter is still valid */
-
- if (attr_name == NULL) {
- attr_name = PyText_InternFromString("__cffi_backend_extern_py");
- if (attr_name == NULL)
- goto error;
- }
-
- d = PyDict_GetItem(interpdict, attr_name);
- if (d == NULL) {
- d = PyDict_New();
- if (d == NULL)
- goto error;
- err = PyDict_SetItem(interpdict, attr_name, d);
- Py_DECREF(d); /* if successful, there is one ref left in interpdict */
- if (err < 0)
- goto error;
- }
- return d;
-
- error:
- PyErr_Clear(); /* typically a MemoryError */
- return NULL;
-}
-
-static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
-{
- const char *s;
- PyObject *error, *onerror, *infotuple, *old1;
- int index, err;
- const struct _cffi_global_s *g;
- struct _cffi_externpy_s *externpy;
- CTypeDescrObject *ct;
- FFIObject *ffi;
- builder_c_t *types_builder;
- PyObject *name = NULL;
- PyObject *interpstate_dict;
- PyObject *interpstate_key;
-
- if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
- return NULL;
-
- if (s == NULL) {
- name = PyObject_GetAttrString(fn, "__name__");
- if (name == NULL)
- return NULL;
- s = PyText_AsUTF8(name);
- if (s == NULL) {
- Py_DECREF(name);
- return NULL;
- }
- }
-
- types_builder = &ffi->types_builder;
- index = search_in_globals(&types_builder->ctx, s, strlen(s));
- if (index < 0)
- goto not_found;
- g = &types_builder->ctx.globals[index];
- if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
- goto not_found;
- Py_XDECREF(name);
-
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
-
- infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
- Py_DECREF(ct);
- if (infotuple == NULL)
- return NULL;
-
- /* don't directly attach infotuple to externpy: in the presence of
- subinterpreters, each time we switch to a different
- subinterpreter and call the C function, it will notice the
- change and look up infotuple from the interpstate_dict.
- */
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL) {
- Py_DECREF(infotuple);
- return PyErr_NoMemory();
- }
-
- externpy = (struct _cffi_externpy_s *)g->address;
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL) {
- Py_DECREF(infotuple);
- return NULL;
- }
-
- err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
- Py_DECREF(interpstate_key);
- Py_DECREF(infotuple); /* interpstate_dict owns the last ref */
- if (err < 0)
- return NULL;
-
- /* force _update_cache_to_call_python() to be called the next time
- the C function invokes cffi_call_python, to update the cache */
- old1 = externpy->reserved1;
- externpy->reserved1 = Py_None; /* a non-NULL value */
- Py_INCREF(Py_None);
- Py_XDECREF(old1);
-
- /* return the function object unmodified */
- Py_INCREF(fn);
- return fn;
-
- not_found:
- PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
- "function with this name", s);
- Py_XDECREF(name);
- return NULL;
-}
-
-
-static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
-{
- PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
- PyObject *old2;
-
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL)
- return 4; /* oops, shutdown issue? */
-
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL)
- goto error;
-
- infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
- Py_DECREF(interpstate_key);
- if (infotuple == NULL)
- return 3; /* no ffi.def_extern() from this subinterpreter */
-
- new1 = _current_interp_key();
- Py_INCREF(new1);
- Py_INCREF(infotuple);
- old1 = (PyObject *)externpy->reserved1;
- old2 = (PyObject *)externpy->reserved2;
- externpy->reserved1 = new1; /* holds a reference */
- externpy->reserved2 = infotuple; /* holds a reference (issue #246) */
- Py_XDECREF(old1);
- Py_XDECREF(old2);
-
- return 0; /* no error */
-
- error:
- PyErr_Clear();
- return 2; /* out of memory? */
-}
-
-#if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
- !defined(__amd64__) && !defined(__x86_64__) && \
- !defined(__i386__) && !defined(__i386))
-# if defined(HAVE_SYNC_SYNCHRONIZE)
-# define read_barrier() __sync_synchronize()
-# elif defined(_AIX)
-# define read_barrier() __lwsync()
-# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-# include <mbarrier.h>
-# define read_barrier() __compiler_barrier()
-# elif defined(__hpux)
-# define read_barrier() _Asm_mf()
-# else
-# define read_barrier() /* missing */
-# warning "no definition for read_barrier(), missing synchronization for\
- multi-thread initialization in embedded mode"
-# endif
-#else
-# define read_barrier() (void)0
-#endif
-
-static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
-{
- /* Invoked by the helpers generated from extern "Python" in the cdef.
-
- 'externpy' is a static structure that describes which of the
- extern "Python" functions is called. It has got fields 'name' and
- 'type_index' describing the function, and more reserved fields
- that are initially zero. These reserved fields are set up by
- ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
-
- 'args' is a pointer to an array of 8-byte entries. Each entry
- contains an argument. If an argument is less than 8 bytes, only
- the part at the beginning of the entry is initialized. If an
- argument is 'long double' or a struct/union, then it is passed
- by reference.
-
- 'args' is also used as the place to write the result to
- (directly, even if more than 8 bytes). In all cases, 'args' is
- at least 8 bytes in size.
- */
- int err = 0;
-
- /* This read barrier is needed for _embedding.h. It is paired
- with the write_barrier() there. Without this barrier, we can
- in theory see the following situation: the Python
- initialization code already ran (in another thread), and the
- '_cffi_call_python' function pointer directed execution here;
- but any number of other data could still be seen as
- uninitialized below. For example, 'externpy' would still
- contain NULLs even though it was correctly set up, or
- 'interpreter_lock' (the GIL inside CPython) would still be seen
- as NULL, or 'autoInterpreterState' (used by
- PyGILState_Ensure()) would be NULL or contain bogus fields.
- */
- read_barrier();
-
- save_errno();
-
- /* We need the infotuple here. We could always go through
- _update_cache_to_call_python(), but to avoid the extra dict
- lookups, we cache in (reserved1, reserved2) the last seen pair
- (interp->modules, infotuple). The first item in this tuple is
- a random PyObject that identifies the subinterpreter.
- */
- if (externpy->reserved1 == NULL) {
- /* Not initialized! We didn't call @ffi.def_extern() on this
- externpy object from any subinterpreter at all. */
- err = 1;
- }
- else {
- PyGILState_STATE state = gil_ensure();
- if (externpy->reserved1 != _current_interp_key()) {
- /* Update the (reserved1, reserved2) cache. This will fail
- if we didn't call @ffi.def_extern() in this particular
- subinterpreter. */
- err = _update_cache_to_call_python(externpy);
- }
- if (!err) {
- general_invoke_callback(0, args, args, externpy->reserved2);
- }
- gil_release(state);
- }
- if (err) {
- static const char *msg[] = {
- "no code was attached to it yet with @ffi.def_extern()",
- "got internal exception (out of memory?)",
- "@ffi.def_extern() was not called in the current subinterpreter",
- "got internal exception (shutdown issue?)",
- };
- fprintf(stderr, "extern \"Python\": function %s() called, "
- "but %s. Returning 0.\n", externpy->name, msg[err-1]);
- memset(args, 0, externpy->size_of_result);
- }
- restore_errno();
-}
diff --git a/c/cdlopen.c b/c/cdlopen.c
deleted file mode 100644
index 0ed319b..0000000
--- a/c/cdlopen.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/* ffi.dlopen() interface with dlopen()/dlsym()/dlclose() */
-
-static void *cdlopen_fetch(PyObject *libname, void *libhandle,
- const char *symbol)
-{
- void *address;
-
- if (libhandle == NULL) {
- PyErr_Format(FFIError, "library '%s' has been closed",
- PyText_AS_UTF8(libname));
- return NULL;
- }
-
- dlerror(); /* clear error condition */
- address = dlsym(libhandle, symbol);
- if (address == NULL) {
- const char *error = dlerror();
- PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s",
- symbol, PyText_AS_UTF8(libname), error);
- }
- return address;
-}
-
-static void cdlopen_close_ignore_errors(void *libhandle)
-{
- if (libhandle != NULL)
- dlclose(libhandle);
-}
-
-static int cdlopen_close(PyObject *libname, void *libhandle)
-{
- if (libhandle != NULL && dlclose(libhandle) != 0) {
- const char *error = dlerror();
- PyErr_Format(FFIError, "closing library '%s': %s",
- PyText_AS_UTF8(libname), error);
- return -1;
- }
- return 0;
-}
-
-static PyObject *ffi_dlopen(PyObject *self, PyObject *args)
-{
- const char *modname;
- PyObject *temp, *result = NULL;
- void *handle;
- int auto_close;
-
- handle = b_do_dlopen(args, &modname, &temp, &auto_close);
- if (handle != NULL)
- {
- result = (PyObject *)lib_internal_new((FFIObject *)self,
- modname, handle, auto_close);
- }
- Py_XDECREF(temp);
- return result;
-}
-
-static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
-{
- LibObject *lib;
- void *libhandle;
- if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib))
- return NULL;
-
- libhandle = lib->l_libhandle;
- if (libhandle != NULL)
- {
- lib->l_libhandle = NULL;
-
- /* Clear the dict to force further accesses to do cdlopen_fetch()
- again, and fail because the library was closed. */
- PyDict_Clear(lib->l_dict);
-
- if (cdlopen_close(lib->l_libname, libhandle) < 0)
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-
-static Py_ssize_t cdl_4bytes(char *src)
-{
- /* read 4 bytes in little-endian order; return it as a signed integer */
- signed char *ssrc = (signed char *)src;
- unsigned char *usrc = (unsigned char *)src;
- return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
-}
-
-static _cffi_opcode_t cdl_opcode(char *src)
-{
- return (_cffi_opcode_t)cdl_4bytes(src);
-}
-
-typedef struct {
- unsigned long long value;
- int neg;
-} cdl_intconst_t;
-
-static int _cdl_realize_global_int(struct _cffi_getconst_s *gc)
-{
- /* The 'address' field of 'struct _cffi_global_s' is set to point
- to this function in case ffiobj_init() sees constant integers.
- This fishes around after the 'ctx->globals' array, which is
- initialized to contain another array, this time of
- 'cdl_intconst_t' structures. We get the nth one and it tells
- us what to return.
- */
- cdl_intconst_t *ic;
- ic = (cdl_intconst_t *)(gc->ctx->globals + gc->ctx->num_globals);
- ic += gc->gindex;
- gc->value = ic->value;
- return ic->neg;
-}
-
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- FFIObject *ffi;
- static char *keywords[] = {"module_name", "_version", "_types",
- "_globals", "_struct_unions", "_enums",
- "_typenames", "_includes", NULL};
- char *ffiname = "?", *types = NULL, *building = NULL;
- Py_ssize_t version = -1;
- Py_ssize_t types_len = 0;
- PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
- PyObject *typenames = NULL, *includes = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "|sns#O!O!O!O!O!:FFI", keywords,
- &ffiname, &version, &types, &types_len,
- &PyTuple_Type, &globals,
- &PyTuple_Type, &struct_unions,
- &PyTuple_Type, &enums,
- &PyTuple_Type, &typenames,
- &PyTuple_Type, &includes))
- return -1;
-
- ffi = (FFIObject *)self;
- if (ffi->ctx_is_nonempty) {
- PyErr_SetString(PyExc_ValueError,
- "cannot call FFI.__init__() more than once");
- return -1;
- }
- ffi->ctx_is_nonempty = 1;
-
- if (version == -1 && types_len == 0)
- return 0;
- if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
- PyErr_Format(PyExc_ImportError,
- "cffi out-of-line Python module '%s' has unknown "
- "version %p", ffiname, (void *)version);
- return -1;
- }
-
- if (types_len > 0) {
- /* unpack a string of 4-byte entries into an array of _cffi_opcode_t */
- _cffi_opcode_t *ntypes;
- Py_ssize_t i, n = types_len / 4;
-
- building = PyMem_Malloc(n * sizeof(_cffi_opcode_t));
- if (building == NULL)
- goto error;
- ntypes = (_cffi_opcode_t *)building;
-
- for (i = 0; i < n; i++) {
- ntypes[i] = cdl_opcode(types);
- types += 4;
- }
- ffi->types_builder.ctx.types = ntypes;
- ffi->types_builder.ctx.num_types = n;
- building = NULL;
- }
-
- if (globals != NULL) {
- /* unpack a tuple alternating strings and ints, each two together
- describing one global_s entry with no specified address or size.
- The int is only used with integer constants. */
- struct _cffi_global_s *nglobs;
- cdl_intconst_t *nintconsts;
- Py_ssize_t i, n = PyTuple_GET_SIZE(globals) / 2;
-
- i = n * (sizeof(struct _cffi_global_s) + sizeof(cdl_intconst_t));
- building = PyMem_Malloc(i);
- if (building == NULL)
- goto error;
- memset(building, 0, i);
- nglobs = (struct _cffi_global_s *)building;
- nintconsts = (cdl_intconst_t *)(nglobs + n);
-
- for (i = 0; i < n; i++) {
- char *g = PyBytes_AS_STRING(PyTuple_GET_ITEM(globals, i * 2));
- nglobs[i].type_op = cdl_opcode(g); g += 4;
- nglobs[i].name = g;
- if (_CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_CONSTANT_INT ||
- _CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_ENUM) {
- PyObject *o = PyTuple_GET_ITEM(globals, i * 2 + 1);
- nglobs[i].address = &_cdl_realize_global_int;
-#if PY_MAJOR_VERSION < 3
- if (PyInt_Check(o)) {
- nintconsts[i].neg = PyInt_AS_LONG(o) <= 0;
- nintconsts[i].value = (long long)PyInt_AS_LONG(o);
- }
- else
-#endif
- {
- nintconsts[i].neg = PyObject_RichCompareBool(o, Py_False,
- Py_LE);
- nintconsts[i].value = PyLong_AsUnsignedLongLongMask(o);
- if (PyErr_Occurred())
- goto error;
- }
- }
- }
- ffi->types_builder.ctx.globals = nglobs;
- ffi->types_builder.ctx.num_globals = n;
- building = NULL;
- }
-
- if (struct_unions != NULL) {
- /* unpack a tuple of struct/unions, each described as a sub-tuple;
- the item 0 of each sub-tuple describes the struct/union, and
- the items 1..N-1 describe the fields, if any */
- struct _cffi_struct_union_s *nstructs;
- struct _cffi_field_s *nfields;
- Py_ssize_t i, n = PyTuple_GET_SIZE(struct_unions);
- Py_ssize_t nf = 0; /* total number of fields */
-
- for (i = 0; i < n; i++) {
- nf += PyTuple_GET_SIZE(PyTuple_GET_ITEM(struct_unions, i)) - 1;
- }
- i = (n * sizeof(struct _cffi_struct_union_s) +
- nf * sizeof(struct _cffi_field_s));
- building = PyMem_Malloc(i);
- if (building == NULL)
- goto error;
- memset(building, 0, i);
- nstructs = (struct _cffi_struct_union_s *)building;
- nfields = (struct _cffi_field_s *)(nstructs + n);
- nf = 0;
-
- for (i = 0; i < n; i++) {
- /* 'desc' is the tuple of strings (desc_struct, desc_field_1, ..) */
- PyObject *desc = PyTuple_GET_ITEM(struct_unions, i);
- Py_ssize_t j, nf1 = PyTuple_GET_SIZE(desc) - 1;
- char *s = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, 0));
- /* 's' is the first string, describing the struct/union */
- nstructs[i].type_index = cdl_4bytes(s); s += 4;
- nstructs[i].flags = cdl_4bytes(s); s += 4;
- nstructs[i].name = s;
- if (nstructs[i].flags & (_CFFI_F_OPAQUE | _CFFI_F_EXTERNAL)) {
- nstructs[i].size = (size_t)-1;
- nstructs[i].alignment = -1;
- nstructs[i].first_field_index = -1;
- nstructs[i].num_fields = 0;
- assert(nf1 == 0);
- }
- else {
- nstructs[i].size = (size_t)-2;
- nstructs[i].alignment = -2;
- nstructs[i].first_field_index = nf;
- nstructs[i].num_fields = nf1;
- }
- for (j = 0; j < nf1; j++) {
- char *f = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, j + 1));
- /* 'f' is one of the other strings beyond the first one,
- describing one field each */
- nfields[nf].field_type_op = cdl_opcode(f); f += 4;
- nfields[nf].field_offset = (size_t)-1;
- if (_CFFI_GETOP(nfields[nf].field_type_op) != _CFFI_OP_NOOP) {
- nfields[nf].field_size = cdl_4bytes(f); f += 4;
- }
- else {
- nfields[nf].field_size = (size_t)-1;
- }
- nfields[nf].name = f;
- nf++;
- }
- }
- ffi->types_builder.ctx.struct_unions = nstructs;
- ffi->types_builder.ctx.fields = nfields;
- ffi->types_builder.ctx.num_struct_unions = n;
- building = NULL;
- }
-
- if (enums != NULL) {
- /* unpack a tuple of strings, each of which describes one enum_s
- entry */
- struct _cffi_enum_s *nenums;
- Py_ssize_t i, n = PyTuple_GET_SIZE(enums);
-
- i = n * sizeof(struct _cffi_enum_s);
- building = PyMem_Malloc(i);
- if (building == NULL)
- goto error;
- memset(building, 0, i);
- nenums = (struct _cffi_enum_s *)building;
-
- for (i = 0; i < n; i++) {
- char *e = PyBytes_AS_STRING(PyTuple_GET_ITEM(enums, i));
- /* 'e' is a string describing the enum */
- nenums[i].type_index = cdl_4bytes(e); e += 4;
- nenums[i].type_prim = cdl_4bytes(e); e += 4;
- nenums[i].name = e; e += strlen(e) + 1;
- nenums[i].enumerators = e;
- }
- ffi->types_builder.ctx.enums = nenums;
- ffi->types_builder.ctx.num_enums = n;
- building = NULL;
- }
-
- if (typenames != NULL) {
- /* unpack a tuple of strings, each of which describes one typename_s
- entry */
- struct _cffi_typename_s *ntypenames;
- Py_ssize_t i, n = PyTuple_GET_SIZE(typenames);
-
- i = n * sizeof(struct _cffi_typename_s);
- building = PyMem_Malloc(i);
- if (building == NULL)
- goto error;
- memset(building, 0, i);
- ntypenames = (struct _cffi_typename_s *)building;
-
- for (i = 0; i < n; i++) {
- char *t = PyBytes_AS_STRING(PyTuple_GET_ITEM(typenames, i));
- /* 't' is a string describing the typename */
- ntypenames[i].type_index = cdl_4bytes(t); t += 4;
- ntypenames[i].name = t;
- }
- ffi->types_builder.ctx.typenames = ntypenames;
- ffi->types_builder.ctx.num_typenames = n;
- building = NULL;
- }
-
- if (includes != NULL) {
- PyObject *included_libs;
-
- included_libs = PyTuple_New(PyTuple_GET_SIZE(includes));
- if (included_libs == NULL)
- return -1;
-
- Py_INCREF(includes);
- ffi->types_builder.included_ffis = includes;
- ffi->types_builder.included_libs = included_libs;
- }
-
- /* Above, we took directly some "char *" strings out of the strings,
- typically from somewhere inside tuples. Keep them alive by
- incref'ing the whole input arguments. */
- Py_INCREF(args);
- Py_XINCREF(kwds);
- ffi->types_builder._keepalive1 = args;
- ffi->types_builder._keepalive2 = kwds;
- return 0;
-
- error:
- if (building != NULL)
- PyMem_Free(building);
- if (!PyErr_Occurred())
- PyErr_NoMemory();
- return -1;
-}
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
deleted file mode 100644
index 06a84fe..0000000
--- a/c/cffi1_module.c
+++ /dev/null
@@ -1,216 +0,0 @@
-
-#include "parse_c_type.c"
-#include "realize_c_type.c"
-
-#define CFFI_VERSION_MIN 0x2601
-#define CFFI_VERSION_CHAR16CHAR32 0x2801
-#define CFFI_VERSION_MAX 0x28FF
-
-typedef struct FFIObject_s FFIObject;
-typedef struct LibObject_s LibObject;
-
-static PyTypeObject FFI_Type; /* forward */
-static PyTypeObject Lib_Type; /* forward */
-
-#include "ffi_obj.c"
-#include "cglob.c"
-#include "lib_obj.c"
-#include "cdlopen.c"
-#include "commontypes.c"
-#include "call_python.c"
-
-
-static int init_ffi_lib(PyObject *m)
-{
- PyObject *x;
- int i, res;
- static char init_done = 0;
-
- if (!init_done) {
- if (init_global_types_dict(FFI_Type.tp_dict) < 0)
- return -1;
-
- FFIError = PyErr_NewException("ffi.error", NULL, NULL);
- if (FFIError == NULL)
- return -1;
- if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0)
- return -1;
- if (PyDict_SetItemString(FFI_Type.tp_dict, "CType",
- (PyObject *)&CTypeDescr_Type) < 0)
- return -1;
- if (PyDict_SetItemString(FFI_Type.tp_dict, "CData",
- (PyObject *)&CData_Type) < 0)
- return -1;
- if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer",
- (PyObject *)&MiniBuffer_Type) < 0)
- return -1;
-
- for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
- x = PyInt_FromLong(all_dlopen_flags[i].value);
- if (x == NULL)
- return -1;
- res = PyDict_SetItemString(FFI_Type.tp_dict,
- all_dlopen_flags[i].name, x);
- Py_DECREF(x);
- if (res < 0)
- return -1;
- }
- init_done = 1;
- }
- return 0;
-}
-
-static int make_included_tuples(char *module_name,
- const char *const *ctx_includes,
- PyObject **included_ffis,
- PyObject **included_libs)
-{
- Py_ssize_t num = 0;
- const char *const *p_include;
-
- if (ctx_includes == NULL)
- return 0;
-
- for (p_include = ctx_includes; *p_include; p_include++) {
- num++;
- }
- *included_ffis = PyTuple_New(num);
- *included_libs = PyTuple_New(num);
- if (*included_ffis == NULL || *included_libs == NULL)
- goto error;
-
- num = 0;
- for (p_include = ctx_includes; *p_include; p_include++) {
- PyObject *included_ffi, *included_lib;
- PyObject *m = PyImport_ImportModule(*p_include);
- if (m == NULL)
- goto import_error;
-
- included_ffi = PyObject_GetAttrString(m, "ffi");
- PyTuple_SET_ITEM(*included_ffis, num, included_ffi);
-
- included_lib = (included_ffi == NULL) ? NULL :
- PyObject_GetAttrString(m, "lib");
- PyTuple_SET_ITEM(*included_libs, num, included_lib);
-
- Py_DECREF(m);
- if (included_lib == NULL)
- goto import_error;
-
- if (!FFIObject_Check(included_ffi) ||
- !LibObject_Check(included_lib))
- goto import_error;
- num++;
- }
- return 0;
-
- import_error:
- PyErr_Format(PyExc_ImportError,
- "while loading %.200s: failed to import ffi, lib from %.200s",
- module_name, *p_include);
- error:
- Py_XDECREF(*included_ffis); *included_ffis = NULL;
- Py_XDECREF(*included_libs); *included_libs = NULL;
- return -1;
-}
-
-static PyObject *_my_Py_InitModule(char *module_name)
-{
-#if PY_MAJOR_VERSION >= 3
- struct PyModuleDef *module_def, local_module_def = {
- PyModuleDef_HEAD_INIT,
- module_name,
- NULL,
- -1,
- NULL, NULL, NULL, NULL, NULL
- };
- /* note: the 'module_def' is allocated dynamically and leaks,
- but anyway the C extension module can never be unloaded */
- module_def = PyMem_Malloc(sizeof(struct PyModuleDef));
- if (module_def == NULL)
- return PyErr_NoMemory();
- *module_def = local_module_def;
- return PyModule_Create(module_def);
-#else
- return Py_InitModule(module_name, NULL);
-#endif
-}
-
-static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg)
-{
- PyObject *m, *modules_dict;
- FFIObject *ffi;
- LibObject *lib;
- Py_ssize_t version, num_exports;
- char *module_name, *exports, *module_name_with_lib;
- void **raw;
- const struct _cffi_type_context_s *ctx;
-
- raw = (void **)PyLong_AsVoidPtr(arg);
- if (raw == NULL)
- return NULL;
-
- module_name = (char *)raw[0];
- version = (Py_ssize_t)raw[1];
- exports = (char *)raw[2];
- ctx = (const struct _cffi_type_context_s *)raw[3];
-
- if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
- if (!PyErr_Occurred())
- PyErr_Format(PyExc_ImportError,
- "cffi extension module '%s' uses an unknown version tag %p. "
- "This module might need a more recent version of cffi "
- "than the one currently installed, which is %s",
- module_name, (void *)version, CFFI_VERSION);
- return NULL;
- }
-
- /* initialize the exports array */
- num_exports = 25;
- if (ctx->flags & 1) /* set to mean that 'extern "Python"' is used */
- num_exports = 26;
- if (version >= CFFI_VERSION_CHAR16CHAR32)
- num_exports = 28;
- memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *));
-
- /* make the module object */
- m = _my_Py_InitModule(module_name);
- if (m == NULL)
- return NULL;
-
- /* build the FFI and Lib object inside this new module */
- ffi = ffi_internal_new(&FFI_Type, ctx);
- Py_XINCREF(ffi); /* make the ffi object really immortal */
- if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
- return NULL;
-
- lib = lib_internal_new(ffi, module_name, NULL, 0);
- if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0)
- return NULL;
-
- if (make_included_tuples(module_name, ctx->includes,
- &ffi->types_builder.included_ffis,
- &lib->l_types_builder->included_libs) < 0)
- return NULL;
-
- /* add manually 'module_name.lib' in sys.modules:
- see test_import_from_lib */
- modules_dict = PySys_GetObject("modules");
- if (!modules_dict)
- return NULL;
- module_name_with_lib = alloca(strlen(module_name) + 5);
- strcpy(module_name_with_lib, module_name);
- strcat(module_name_with_lib, ".lib");
- if (PyDict_SetItemString(modules_dict, module_name_with_lib,
- (PyObject *)lib) < 0)
- return NULL;
-
-#if PY_MAJOR_VERSION >= 3
- /* add manually 'module_name' in sys.modules: it seems that
- Py_InitModule() is not enough to do that */
- if (PyDict_SetItemString(modules_dict, module_name, m) < 0)
- return NULL;
-#endif
-
- return m;
-}
diff --git a/c/cglob.c b/c/cglob.c
deleted file mode 100644
index e97767c..0000000
--- a/c/cglob.c
+++ /dev/null
@@ -1,113 +0,0 @@
-
-typedef void *(*gs_fetch_addr_fn)(void);
-
-typedef struct {
- PyObject_HEAD
-
- PyObject *gs_name;
- CTypeDescrObject *gs_type;
- char *gs_data;
- gs_fetch_addr_fn gs_fetch_addr;
-
-} GlobSupportObject;
-
-static void glob_support_dealloc(GlobSupportObject *gs)
-{
- Py_DECREF(gs->gs_name);
- Py_DECREF(gs->gs_type);
- PyObject_Del(gs);
-}
-
-static PyTypeObject GlobSupport_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.__FFIGlobSupport",
- sizeof(GlobSupportObject),
- 0,
- (destructor)glob_support_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
-};
-
-#define GlobSupport_Check(ob) (Py_TYPE(ob) == &GlobSupport_Type)
-
-static PyObject *make_global_var(PyObject *name, CTypeDescrObject *type,
- char *addr, gs_fetch_addr_fn fetch_addr)
-{
- GlobSupportObject *gs = PyObject_New(GlobSupportObject, &GlobSupport_Type);
- if (gs == NULL)
- return NULL;
-
- Py_INCREF(name);
- Py_INCREF(type);
- gs->gs_name = name;
- gs->gs_type = type;
- gs->gs_data = addr;
- gs->gs_fetch_addr = fetch_addr;
- return (PyObject *)gs;
-}
-
-static void *fetch_global_var_addr(GlobSupportObject *gs)
-{
- void *data;
- if (gs->gs_data != NULL) {
- data = gs->gs_data;
- }
- else {
- Py_BEGIN_ALLOW_THREADS
- restore_errno();
- data = gs->gs_fetch_addr();
- save_errno();
- Py_END_ALLOW_THREADS
- }
- if (data == NULL) {
- PyErr_Format(FFIError, "global variable '%s' is at address NULL",
- PyText_AS_UTF8(gs->gs_name));
- return NULL;
- }
- return data;
-}
-
-static PyObject *read_global_var(GlobSupportObject *gs)
-{
- void *data = fetch_global_var_addr(gs);
- if (data == NULL)
- return NULL;
- return convert_to_object(data, gs->gs_type);
-}
-
-static int write_global_var(GlobSupportObject *gs, PyObject *obj)
-{
- void *data = fetch_global_var_addr(gs);
- if (data == NULL)
- return -1;
- return convert_from_object(data, gs->gs_type, obj);
-}
-
-static PyObject *cg_addressof_global_var(GlobSupportObject *gs)
-{
- void *data;
- PyObject *x, *ptrtype = new_pointer_type(gs->gs_type);
- if (ptrtype == NULL)
- return NULL;
-
- data = fetch_global_var_addr(gs);
- if (data != NULL)
- x = new_simple_cdata(data, (CTypeDescrObject *)ptrtype);
- else
- x = NULL;
- Py_DECREF(ptrtype);
- return x;
-}
diff --git a/c/commontypes.c b/c/commontypes.c
deleted file mode 100644
index a41c2fd..0000000
--- a/c/commontypes.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* This file must be kept in alphabetical order. See test_commontypes.py */
-
-#define EQ(key, value) key "\0" value /* string concatenation */
-#ifdef _WIN64
-# define W32_64(X,Y) Y
-# else
-# define W32_64(X,Y) X
-# endif
-
-
-static const char *common_simple_types[] = {
-
-#ifdef MS_WIN32 /* Windows types */
- EQ("ATOM", "WORD"),
- EQ("BOOL", "int"),
- EQ("BOOLEAN", "BYTE"),
- EQ("BYTE", "unsigned char"),
- EQ("CCHAR", "char"),
- EQ("CHAR", "char"),
- EQ("COLORREF", "DWORD"),
- EQ("DWORD", "unsigned long"),
- EQ("DWORD32", "unsigned int"),
- EQ("DWORD64", "unsigned long long"),
- EQ("DWORDLONG", "ULONGLONG"),
- EQ("DWORD_PTR", "ULONG_PTR"),
-#endif
-
- EQ("FILE", "struct _IO_FILE"),
-
-#ifdef MS_WIN32 /* more Windows types */
- EQ("FLOAT", "float"),
- EQ("HACCEL", "HANDLE"),
- EQ("HALF_PTR", W32_64("short","int")),
- EQ("HANDLE", "PVOID"),
- EQ("HBITMAP", "HANDLE"),
- EQ("HBRUSH", "HANDLE"),
- EQ("HCOLORSPACE", "HANDLE"),
- EQ("HCONV", "HANDLE"),
- EQ("HCONVLIST", "HANDLE"),
- EQ("HCURSOR", "HICON"),
- EQ("HDC", "HANDLE"),
- EQ("HDDEDATA", "HANDLE"),
- EQ("HDESK", "HANDLE"),
- EQ("HDROP", "HANDLE"),
- EQ("HDWP", "HANDLE"),
- EQ("HENHMETAFILE", "HANDLE"),
- EQ("HFILE", "int"),
- EQ("HFONT", "HANDLE"),
- EQ("HGDIOBJ", "HANDLE"),
- EQ("HGLOBAL", "HANDLE"),
- EQ("HHOOK", "HANDLE"),
- EQ("HICON", "HANDLE"),
- EQ("HINSTANCE", "HANDLE"),
- EQ("HKEY", "HANDLE"),
- EQ("HKL", "HANDLE"),
- EQ("HLOCAL", "HANDLE"),
- EQ("HMENU", "HANDLE"),
- EQ("HMETAFILE", "HANDLE"),
- EQ("HMODULE", "HINSTANCE"),
- EQ("HMONITOR", "HANDLE"),
- EQ("HPALETTE", "HANDLE"),
- EQ("HPEN", "HANDLE"),
- EQ("HRESULT", "LONG"),
- EQ("HRGN", "HANDLE"),
- EQ("HRSRC", "HANDLE"),
- EQ("HSZ", "HANDLE"),
- EQ("HWND", "HANDLE"),
- EQ("INT", "int"),
- EQ("INT16", "short"),
- EQ("INT32", "int"),
- EQ("INT64", "long long"),
- EQ("INT8", "signed char"),
- EQ("INT_PTR", W32_64("int","long long")),
- EQ("LANGID", "WORD"),
- EQ("LCID", "DWORD"),
- EQ("LCTYPE", "DWORD"),
- EQ("LGRPID", "DWORD"),
- EQ("LONG", "long"),
- EQ("LONG32", "int"),
- EQ("LONG64", "long long"),
- EQ("LONGLONG", "long long"),
- EQ("LONG_PTR", W32_64("long","long long")),
- EQ("LPARAM", "LONG_PTR"),
- EQ("LPBOOL", "BOOL *"),
- EQ("LPBYTE", "BYTE *"),
- EQ("LPCOLORREF", "DWORD *"),
- EQ("LPCSTR", "const char *"),
- EQ("LPCVOID", "const void *"),
- EQ("LPCWSTR", "const WCHAR *"),
- EQ("LPDWORD", "DWORD *"),
- EQ("LPHANDLE", "HANDLE *"),
- EQ("LPINT", "int *"),
- EQ("LPLONG", "long *"),
- EQ("LPSTR", "CHAR *"),
- EQ("LPVOID", "void *"),
- EQ("LPWORD", "WORD *"),
- EQ("LPWSTR", "WCHAR *"),
- EQ("LRESULT", "LONG_PTR"),
- EQ("PBOOL", "BOOL *"),
- EQ("PBOOLEAN", "BOOLEAN *"),
- EQ("PBYTE", "BYTE *"),
- EQ("PCHAR", "CHAR *"),
- EQ("PCSTR", "const CHAR *"),
- EQ("PCWSTR", "const WCHAR *"),
- EQ("PDWORD", "DWORD *"),
- EQ("PDWORD32", "DWORD32 *"),
- EQ("PDWORD64", "DWORD64 *"),
- EQ("PDWORDLONG", "DWORDLONG *"),
- EQ("PDWORD_PTR", "DWORD_PTR *"),
- EQ("PFLOAT", "FLOAT *"),
- EQ("PHALF_PTR", "HALF_PTR *"),
- EQ("PHANDLE", "HANDLE *"),
- EQ("PHKEY", "HKEY *"),
- EQ("PINT", "int *"),
- EQ("PINT16", "INT16 *"),
- EQ("PINT32", "INT32 *"),
- EQ("PINT64", "INT64 *"),
- EQ("PINT8", "INT8 *"),
- EQ("PINT_PTR", "INT_PTR *"),
- EQ("PLCID", "PDWORD"),
- EQ("PLONG", "LONG *"),
- EQ("PLONG32", "LONG32 *"),
- EQ("PLONG64", "LONG64 *"),
- EQ("PLONGLONG", "LONGLONG *"),
- EQ("PLONG_PTR", "LONG_PTR *"),
- EQ("PSHORT", "SHORT *"),
- EQ("PSIZE_T", "SIZE_T *"),
- EQ("PSSIZE_T", "SSIZE_T *"),
- EQ("PSTR", "CHAR *"),
- EQ("PUCHAR", "UCHAR *"),
- EQ("PUHALF_PTR", "UHALF_PTR *"),
- EQ("PUINT", "UINT *"),
- EQ("PUINT16", "UINT16 *"),
- EQ("PUINT32", "UINT32 *"),
- EQ("PUINT64", "UINT64 *"),
- EQ("PUINT8", "UINT8 *"),
- EQ("PUINT_PTR", "UINT_PTR *"),
- EQ("PULONG", "ULONG *"),
- EQ("PULONG32", "ULONG32 *"),
- EQ("PULONG64", "ULONG64 *"),
- EQ("PULONGLONG", "ULONGLONG *"),
- EQ("PULONG_PTR", "ULONG_PTR *"),
- EQ("PUSHORT", "USHORT *"),
- EQ("PVOID", "void *"),
- EQ("PWCHAR", "WCHAR *"),
- EQ("PWORD", "WORD *"),
- EQ("PWSTR", "WCHAR *"),
- EQ("QWORD", "unsigned long long"),
- EQ("SC_HANDLE", "HANDLE"),
- EQ("SC_LOCK", "LPVOID"),
- EQ("SERVICE_STATUS_HANDLE", "HANDLE"),
- EQ("SHORT", "short"),
- EQ("SIZE_T", "ULONG_PTR"),
- EQ("SSIZE_T", "LONG_PTR"),
- EQ("UCHAR", "unsigned char"),
- EQ("UHALF_PTR", W32_64("unsigned short","unsigned int")),
- EQ("UINT", "unsigned int"),
- EQ("UINT16", "unsigned short"),
- EQ("UINT32", "unsigned int"),
- EQ("UINT64", "unsigned long long"),
- EQ("UINT8", "unsigned char"),
- EQ("UINT_PTR", W32_64("unsigned int","unsigned long long")),
- EQ("ULONG", "unsigned long"),
- EQ("ULONG32", "unsigned int"),
- EQ("ULONG64", "unsigned long long"),
- EQ("ULONGLONG", "unsigned long long"),
- EQ("ULONG_PTR", W32_64("unsigned long","unsigned long long")),
- EQ("USHORT", "unsigned short"),
- EQ("USN", "LONGLONG"),
- EQ("VOID", "void"),
- EQ("WCHAR", "wchar_t"),
- EQ("WINSTA", "HANDLE"),
- EQ("WORD", "unsigned short"),
- EQ("WPARAM", "UINT_PTR"),
-#endif
-
- EQ("bool", "_Bool"),
-};
-
-
-#undef EQ
-#undef W32_64
-
-#define num_common_simple_types \
- (sizeof(common_simple_types) / sizeof(common_simple_types[0]))
-
-
-static const char *get_common_type(const char *search, size_t search_len)
-{
- const char *entry;
- int index = search_sorted(common_simple_types, sizeof(const char *),
- num_common_simple_types, search, search_len);
- if (index < 0)
- return NULL;
-
- entry = common_simple_types[index];
- return entry + strlen(entry) + 1;
-}
-
-static PyObject *b__get_common_types(PyObject *self, PyObject *arg)
-{
- int err;
- size_t i;
- for (i = 0; i < num_common_simple_types; i++) {
- const char *s = common_simple_types[i];
- PyObject *o = PyText_FromString(s + strlen(s) + 1);
- if (o == NULL)
- return NULL;
- err = PyDict_SetItemString(arg, s, o);
- Py_DECREF(o);
- if (err < 0)
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
deleted file mode 100644
index f154146..0000000
--- a/c/ffi_obj.c
+++ /dev/null
@@ -1,1221 +0,0 @@
-
-/* An FFI object has methods like ffi.new(). It is also a container
- for the type declarations (typedefs and structs) that you can use,
- say in ffi.new().
-
- CTypeDescrObjects are internally stored in the dict 'types_dict'.
- The types_dict is lazily filled with CTypeDescrObjects made from
- reading a _cffi_type_context_s structure.
-
- In "modern" mode, the FFI instance is made by the C extension
- module originally created by recompile(). The _cffi_type_context_s
- structure comes from global data in the C extension module.
-
- In "compatibility" mode, an FFI instance is created explicitly by
- the user, and its _cffi_type_context_s is initially empty. You
- need to call ffi.cdef() to add more information to it.
-*/
-
-#define FFI_COMPLEXITY_OUTPUT 1200 /* xxx should grow as needed */
-
-#define FFIObject_Check(op) PyObject_TypeCheck(op, &FFI_Type)
-#define LibObject_Check(ob) ((Py_TYPE(ob) == &Lib_Type))
-
-struct FFIObject_s {
- PyObject_HEAD
- PyObject *gc_wrefs, *gc_wrefs_freelist;
- PyObject *init_once_cache;
- struct _cffi_parse_info_s info;
- char ctx_is_static, ctx_is_nonempty;
- builder_c_t types_builder;
-};
-
-static FFIObject *ffi_internal_new(PyTypeObject *ffitype,
- const struct _cffi_type_context_s *static_ctx)
-{
- static _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT];
-
- FFIObject *ffi;
- if (static_ctx != NULL) {
- ffi = (FFIObject *)PyObject_GC_New(FFIObject, ffitype);
- /* we don't call PyObject_GC_Track() here: from _cffi_init_module()
- it is not needed, because in this case the ffi object is immortal */
- }
- else {
- ffi = (FFIObject *)ffitype->tp_alloc(ffitype, 0);
- }
- if (ffi == NULL)
- return NULL;
-
- if (init_builder_c(&ffi->types_builder, static_ctx) < 0) {
- Py_DECREF(ffi);
- return NULL;
- }
- ffi->gc_wrefs = NULL;
- ffi->gc_wrefs_freelist = NULL;
- ffi->init_once_cache = NULL;
- ffi->info.ctx = &ffi->types_builder.ctx;
- ffi->info.output = internal_output;
- ffi->info.output_size = FFI_COMPLEXITY_OUTPUT;
- ffi->ctx_is_static = (static_ctx != NULL);
- ffi->ctx_is_nonempty = (static_ctx != NULL);
- return ffi;
-}
-
-static void ffi_dealloc(FFIObject *ffi)
-{
- PyObject_GC_UnTrack(ffi);
- Py_XDECREF(ffi->gc_wrefs);
- Py_XDECREF(ffi->gc_wrefs_freelist);
- Py_XDECREF(ffi->init_once_cache);
-
- free_builder_c(&ffi->types_builder, ffi->ctx_is_static);
-
- Py_TYPE(ffi)->tp_free((PyObject *)ffi);
-}
-
-static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg)
-{
- Py_VISIT(ffi->types_builder.types_dict);
- Py_VISIT(ffi->types_builder.included_ffis);
- Py_VISIT(ffi->types_builder.included_libs);
- Py_VISIT(ffi->gc_wrefs);
- return 0;
-}
-
-static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- /* user-facing initialization code, for explicit FFI() calls */
- return (PyObject *)ffi_internal_new(type, NULL);
-}
-
-/* forward, declared in cdlopen.c because it's mostly useful for this case */
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
-
-static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name,
- int recursion)
-{
- int index;
-
- index = search_in_globals(&ffi->types_builder.ctx, name, strlen(name));
- if (index >= 0) {
- const struct _cffi_global_s *g;
- g = &ffi->types_builder.ctx.globals[index];
-
- switch (_CFFI_GETOP(g->type_op)) {
- case _CFFI_OP_CONSTANT_INT:
- case _CFFI_OP_ENUM:
- return realize_global_int(&ffi->types_builder, index);
-
- default:
- PyErr_Format(FFIError,
- "function, global variable or non-integer constant "
- "'%.200s' must be fetched from its original 'lib' "
- "object", name);
- return NULL;
- }
- }
-
- if (ffi->types_builder.included_ffis != NULL) {
- Py_ssize_t i;
- PyObject *included_ffis = ffi->types_builder.included_ffis;
-
- if (recursion > 100) {
- PyErr_SetString(PyExc_RuntimeError,
- "recursion overflow in ffi.include() delegations");
- return NULL;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
- FFIObject *ffi1;
- PyObject *x;
-
- ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
- x = ffi_fetch_int_constant(ffi1, name, recursion + 1);
- if (x != NULL || PyErr_Occurred())
- return x;
- }
- }
- return NULL; /* no exception set, means "not found" */
-}
-
-#define ACCEPT_STRING 1
-#define ACCEPT_CTYPE 2
-#define ACCEPT_CDATA 4
-#define ACCEPT_ALL (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA)
-#define CONSIDER_FN_AS_FNPTR 8
-
-static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, const char *input_text)
-{
- size_t length = strlen(input_text);
- char *extra;
-
- if (length > 500) {
- extra = "";
- }
- else {
- char *p;
- size_t i, num_spaces = ffi->info.error_location;
- extra = alloca(length + num_spaces + 4);
- p = extra;
- *p++ = '\n';
- for (i = 0; i < length; i++) {
- if (' ' <= input_text[i] && input_text[i] < 0x7f)
- *p++ = input_text[i];
- else if (input_text[i] == '\t' || input_text[i] == '\n')
- *p++ = ' ';
- else
- *p++ = '?';
- }
- *p++ = '\n';
- memset(p, ' ', num_spaces);
- p += num_spaces;
- *p++ = '^';
- *p++ = 0;
- }
- PyErr_Format(FFIError, "%s%s", ffi->info.error_message, extra);
- return NULL;
-}
-
-static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg,
- int accept)
-{
- /* Returns the CTypeDescrObject from the user-supplied 'arg'.
- Does not return a new reference!
- */
- if ((accept & ACCEPT_STRING) && PyText_Check(arg)) {
- PyObject *types_dict = ffi->types_builder.types_dict;
- PyObject *x = PyDict_GetItem(types_dict, arg);
-
- if (x == NULL) {
- const char *input_text = PyText_AS_UTF8(arg);
- int err, index = parse_c_type(&ffi->info, input_text);
- if (index < 0)
- return _ffi_bad_type(ffi, input_text);
-
- x = realize_c_type_or_func(&ffi->types_builder,
- ffi->info.output, index);
- if (x == NULL)
- return NULL;
-
- /* Cache under the name given by 'arg', in addition to the
- fact that the same ct is probably already cached under
- its standardized name. In a few cases, it is not, e.g.
- if it is a primitive; for the purpose of this function,
- the important point is the following line, which makes
- sure that in any case the next _ffi_type() with the same
- 'arg' will succeed early, in PyDict_GetItem() above.
- */
- err = PyDict_SetItem(types_dict, arg, x);
- Py_DECREF(x); /* we know it was written in types_dict (unless out
- of mem), so there is at least that ref left */
- if (err < 0)
- return NULL;
- }
-
- if (CTypeDescr_Check(x))
- return (CTypeDescrObject *)x;
- else if (accept & CONSIDER_FN_AS_FNPTR)
- return unwrap_fn_as_fnptr(x);
- else
- return unexpected_fn_type(x);
- }
- else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) {
- return (CTypeDescrObject *)arg;
- }
- else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) {
- return ((CDataObject *)arg)->c_type;
- }
-#if PY_MAJOR_VERSION < 3
- else if (PyUnicode_Check(arg)) {
- CTypeDescrObject *result;
- arg = PyUnicode_AsASCIIString(arg);
- if (arg == NULL)
- return NULL;
- result = _ffi_type(ffi, arg, accept);
- Py_DECREF(arg);
- return result;
- }
-#endif
- else {
- const char *m1 = (accept & ACCEPT_STRING) ? "string" : "";
- const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : "";
- const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : "";
- const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : "";
- const char *s23 = (*m2 && *m3) ? " or " : "";
- PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'",
- m1, s12, m2, s23, m3,
- Py_TYPE(arg)->tp_name);
- return NULL;
- }
-}
-
-PyDoc_STRVAR(ffi_sizeof_doc,
-"Return the size in bytes of the argument.\n"
-"It can be a string naming a C type, or a 'cdata' instance.");
-
-static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg)
-{
- Py_ssize_t size;
-
- if (CData_Check(arg)) {
- size = direct_sizeof_cdata((CDataObject *)arg);
- }
- else {
- CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
- if (ct == NULL)
- return NULL;
- size = ct->ct_size;
- if (size < 0) {
- PyErr_Format(FFIError, "don't know the size of ctype '%s'",
- ct->ct_name);
- return NULL;
- }
- }
- return PyInt_FromSsize_t(size);
-}
-
-PyDoc_STRVAR(ffi_alignof_doc,
-"Return the natural alignment size in bytes of the argument.\n"
-"It can be a string naming a C type, or a 'cdata' instance.");
-
-static PyObject *ffi_alignof(FFIObject *self, PyObject *arg)
-{
- int align;
- CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
- if (ct == NULL)
- return NULL;
-
- align = get_alignment(ct);
- if (align < 0)
- return NULL;
- return PyInt_FromLong(align);
-}
-
-PyDoc_STRVAR(ffi_typeof_doc,
-"Parse the C type given as a string and return the\n"
-"corresponding <ctype> object.\n"
-"It can also be used on 'cdata' instance to get its C type.");
-
-static PyObject *_cpyextfunc_type_index(PyObject *x); /* forward */
-
-static PyObject *ffi_typeof(FFIObject *self, PyObject *arg)
-{
- PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA);
- if (x != NULL) {
- Py_INCREF(x);
- }
- else {
- x = _cpyextfunc_type_index(arg);
- }
- return x;
-}
-
-PyDoc_STRVAR(ffi_new_doc,
-"Allocate an instance according to the specified C type and return a\n"
-"pointer to it. The specified C type must be either a pointer or an\n"
-"array: ``new('X *')`` allocates an X and returns a pointer to it,\n"
-"whereas ``new('X[n]')`` allocates an array of n X'es and returns an\n"
-"array referencing it (which works mostly like a pointer, like in C).\n"
-"You can also use ``new('X[]', n)`` to allocate an array of a\n"
-"non-constant length n.\n"
-"\n"
-"The memory is initialized following the rules of declaring a global\n"
-"variable in C: by default it is zero-initialized, but an explicit\n"
-"initializer can be given which can be used to fill all or part of the\n"
-"memory.\n"
-"\n"
-"When the returned <cdata> object goes out of scope, the memory is\n"
-"freed. In other words the returned <cdata> object has ownership of\n"
-"the value of type 'cdecl' that it points to. This means that the raw\n"
-"data can be used as long as this object is kept alive, but must not be\n"
-"used for a longer time. Be careful about that when copying the\n"
-"pointer to the memory somewhere else, e.g. into another structure.");
-
-static PyObject *_ffi_new(FFIObject *self, PyObject *args, PyObject *kwds,
- const cffi_allocator_t *allocator)
-{
- CTypeDescrObject *ct;
- PyObject *arg, *init = Py_None;
- static char *keywords[] = {"cdecl", "init", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:new", keywords,
- &arg, &init))
- return NULL;
-
- ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
- if (ct == NULL)
- return NULL;
-
- return direct_newp(ct, init, allocator);
-}
-
-static PyObject *ffi_new(FFIObject *self, PyObject *args, PyObject *kwds)
-{
- return _ffi_new(self, args, kwds, &default_allocator);
-}
-
-static PyObject *_ffi_new_with_allocator(PyObject *allocator, PyObject *args,
- PyObject *kwds)
-{
- cffi_allocator_t alloc1;
- PyObject *my_alloc, *my_free;
- my_alloc = PyTuple_GET_ITEM(allocator, 1);
- my_free = PyTuple_GET_ITEM(allocator, 2);
- alloc1.ca_alloc = (my_alloc == Py_None ? NULL : my_alloc);
- alloc1.ca_free = (my_free == Py_None ? NULL : my_free);
- alloc1.ca_dont_clear = (PyTuple_GET_ITEM(allocator, 3) == Py_False);
-
- return _ffi_new((FFIObject *)PyTuple_GET_ITEM(allocator, 0),
- args, kwds, &alloc1);
-}
-
-PyDoc_STRVAR(ffi_new_allocator_doc,
-"Return a new allocator, i.e. a function that behaves like ffi.new()\n"
-"but uses the provided low-level 'alloc' and 'free' functions.\n"
-"\n"
-"'alloc' is called with the size as argument. If it returns NULL, a\n"
-"MemoryError is raised. 'free' is called with the result of 'alloc'\n"
-"as argument. Both can be either Python functions or directly C\n"
-"functions. If 'free' is None, then no free function is called.\n"
-"If both 'alloc' and 'free' are None, the default is used.\n"
-"\n"
-"If 'should_clear_after_alloc' is set to False, then the memory\n"
-"returned by 'alloc' is assumed to be already cleared (or you are\n"
-"fine with garbage); otherwise CFFI will clear it.");
-
-static PyObject *ffi_new_allocator(FFIObject *self, PyObject *args,
- PyObject *kwds)
-{
- PyObject *allocator, *result;
- PyObject *my_alloc = Py_None, *my_free = Py_None;
- int should_clear_after_alloc = 1;
- static char *keywords[] = {"alloc", "free", "should_clear_after_alloc",
- NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:new_allocator", keywords,
- &my_alloc, &my_free,
- &should_clear_after_alloc))
- return NULL;
-
- if (my_alloc == Py_None && my_free != Py_None) {
- PyErr_SetString(PyExc_TypeError, "cannot pass 'free' without 'alloc'");
- return NULL;
- }
-
- allocator = PyTuple_Pack(4,
- (PyObject *)self,
- my_alloc,
- my_free,
- PyBool_FromLong(should_clear_after_alloc));
- if (allocator == NULL)
- return NULL;
-
- {
- static PyMethodDef md = {"allocator",
- (PyCFunction)_ffi_new_with_allocator,
- METH_VARARGS | METH_KEYWORDS};
- result = PyCFunction_New(&md, allocator);
- }
- Py_DECREF(allocator);
- return result;
-}
-
-PyDoc_STRVAR(ffi_cast_doc,
-"Similar to a C cast: returns an instance of the named C\n"
-"type initialized with the given 'source'. The source is\n"
-"casted between integers or pointers of any type.");
-
-static PyObject *ffi_cast(FFIObject *self, PyObject *args)
-{
- CTypeDescrObject *ct;
- PyObject *ob, *arg;
- if (!PyArg_ParseTuple(args, "OO:cast", &arg, &ob))
- return NULL;
-
- ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
- if (ct == NULL)
- return NULL;
-
- return do_cast(ct, ob);
-}
-
-PyDoc_STRVAR(ffi_string_doc,
-"Return a Python string (or unicode string) from the 'cdata'. If\n"
-"'cdata' is a pointer or array of characters or bytes, returns the\n"
-"null-terminated string. The returned string extends until the first\n"
-"null character, or at most 'maxlen' characters. If 'cdata' is an\n"
-"array then 'maxlen' defaults to its length.\n"
-"\n"
-"If 'cdata' is a pointer or array of wchar_t, returns a unicode string\n"
-"following the same rules.\n"
-"\n"
-"If 'cdata' is a single character or byte or a wchar_t, returns it as a\n"
-"string or unicode string.\n"
-"\n"
-"If 'cdata' is an enum, returns the value of the enumerator as a\n"
-"string, or 'NUMBER' if the value is out of range.");
-
-#define ffi_string b_string /* ffi_string() => b_string()
- from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_unpack_doc,
-"Unpack an array of C data of the given length,\n"
-"returning a Python string/unicode/list.\n"
-"\n"
-"If 'cdata' is a pointer to 'char', returns a byte string.\n"
-"It does not stop at the first null. This is equivalent to:\n"
-"ffi.buffer(cdata, length)[:]\n"
-"\n"
-"If 'cdata' is a pointer to 'wchar_t', returns a unicode string.\n"
-"'length' is measured in wchar_t's; it is not the size in bytes.\n"
-"\n"
-"If 'cdata' is a pointer to anything else, returns a list of\n"
-"'length' items. This is a faster equivalent to:\n"
-"[cdata[i] for i in range(length)]");
-
-#define ffi_unpack b_unpack /* ffi_unpack() => b_unpack()
- from _cffi_backend.c */
-
-
-PyDoc_STRVAR(ffi_offsetof_doc,
-"Return the offset of the named field inside the given structure or\n"
-"array, which must be given as a C type name. You can give several\n"
-"field names in case of nested structures. You can also give numeric\n"
-"values which correspond to array items, in case of an array type.");
-
-static PyObject *ffi_offsetof(FFIObject *self, PyObject *args)
-{
- PyObject *arg;
- CTypeDescrObject *ct;
- Py_ssize_t i, offset;
-
- if (PyTuple_Size(args) < 2) {
- PyErr_SetString(PyExc_TypeError,
- "offsetof() expects at least 2 arguments");
- return NULL;
- }
-
- arg = PyTuple_GET_ITEM(args, 0);
- ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
- if (ct == NULL)
- return NULL;
-
- offset = 0;
- for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
- Py_ssize_t ofs1;
- ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i), i > 1, &ofs1);
- if (ct == NULL)
- return NULL;
- offset += ofs1;
- }
- return PyInt_FromSsize_t(offset);
-}
-
-PyDoc_STRVAR(ffi_addressof_doc,
-"Limited equivalent to the '&' operator in C:\n"
-"\n"
-"1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a\n"
-"pointer to this struct or union.\n"
-"\n"
-"2. ffi.addressof(<cdata>, field-or-index...) returns the address of a\n"
-"field or array item inside the given structure or array, recursively\n"
-"in case of nested structures or arrays.\n"
-"\n"
-"3. ffi.addressof(<library>, \"name\") returns the address of the named\n"
-"function or global variable.");
-
-static PyObject *address_of_global_var(PyObject *args); /* forward */
-
-static PyObject *ffi_addressof(FFIObject *self, PyObject *args)
-{
- PyObject *arg, *z, *result;
- CTypeDescrObject *ct;
- Py_ssize_t i, offset = 0;
- int accepted_flags;
-
- if (PyTuple_Size(args) < 1) {
- PyErr_SetString(PyExc_TypeError,
- "addressof() expects at least 1 argument");
- return NULL;
- }
-
- arg = PyTuple_GET_ITEM(args, 0);
- if (LibObject_Check(arg)) {
- /* case 3 in the docstring */
- return address_of_global_var(args);
- }
-
- ct = _ffi_type(self, arg, ACCEPT_CDATA);
- if (ct == NULL)
- return NULL;
-
- if (PyTuple_GET_SIZE(args) == 1) {
- /* case 1 in the docstring */
- accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY;
- if ((ct->ct_flags & accepted_flags) == 0) {
- PyErr_SetString(PyExc_TypeError,
- "expected a cdata struct/union/array object");
- return NULL;
- }
- }
- else {
- /* case 2 in the docstring */
- accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER;
- if ((ct->ct_flags & accepted_flags) == 0) {
- PyErr_SetString(PyExc_TypeError,
- "expected a cdata struct/union/array/pointer object");
- return NULL;
- }
- for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
- Py_ssize_t ofs1;
- ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i),
- i > 1, &ofs1);
- if (ct == NULL)
- return NULL;
- offset += ofs1;
- }
- }
-
- z = new_pointer_type(ct);
- if (z == NULL)
- return NULL;
-
- result = new_simple_cdata(((CDataObject *)arg)->c_data + offset,
- (CTypeDescrObject *)z);
- Py_DECREF(z);
- return result;
-}
-
-static PyObject *_combine_type_name_l(CTypeDescrObject *ct,
- size_t extra_text_len)
-{
- size_t base_name_len;
- PyObject *result;
- char *p;
-
- base_name_len = strlen(ct->ct_name);
- result = PyBytes_FromStringAndSize(NULL, base_name_len + extra_text_len);
- if (result == NULL)
- return NULL;
-
- p = PyBytes_AS_STRING(result);
- memcpy(p, ct->ct_name, ct->ct_name_position);
- p += ct->ct_name_position;
- p += extra_text_len;
- memcpy(p, ct->ct_name + ct->ct_name_position,
- base_name_len - ct->ct_name_position);
- return result;
-}
-
-PyDoc_STRVAR(ffi_getctype_doc,
-"Return a string giving the C type 'cdecl', which may be itself a\n"
-"string or a <ctype> object. If 'replace_with' is given, it gives\n"
-"extra text to append (or insert for more complicated C types), like a\n"
-"variable name, or '*' to get actually the C type 'pointer-to-cdecl'.");
-
-static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *c_decl, *res;
- char *p, *replace_with = "";
- int add_paren, add_space;
- CTypeDescrObject *ct;
- size_t replace_with_len;
- static char *keywords[] = {"cdecl", "replace_with", NULL};
-#if PY_MAJOR_VERSION >= 3
- PyObject *u;
-#endif
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords,
- &c_decl, &replace_with))
- return NULL;
-
- ct = _ffi_type(self, c_decl, ACCEPT_STRING|ACCEPT_CTYPE);
- if (ct == NULL)
- return NULL;
-
- while (replace_with[0] != 0 && isspace(replace_with[0]))
- replace_with++;
- replace_with_len = strlen(replace_with);
- while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1]))
- replace_with_len--;
-
- add_paren = (replace_with[0] == '*' &&
- ((ct->ct_flags & CT_ARRAY) != 0));
- add_space = (!add_paren && replace_with_len > 0 &&
- replace_with[0] != '[' && replace_with[0] != '(');
-
- res = _combine_type_name_l(ct, replace_with_len + add_space + 2*add_paren);
- if (res == NULL)
- return NULL;
-
- p = PyBytes_AS_STRING(res) + ct->ct_name_position;
- if (add_paren)
- *p++ = '(';
- if (add_space)
- *p++ = ' ';
- memcpy(p, replace_with, replace_with_len);
- if (add_paren)
- p[replace_with_len] = ')';
-
-#if PY_MAJOR_VERSION >= 3
- /* bytes -> unicode string */
- u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res),
- PyBytes_GET_SIZE(res),
- NULL);
- Py_DECREF(res);
- res = u;
-#endif
-
- return res;
-}
-
-PyDoc_STRVAR(ffi_new_handle_doc,
-"Return a non-NULL cdata of type 'void *' that contains an opaque\n"
-"reference to the argument, which can be any Python object. To cast it\n"
-"back to the original object, use from_handle(). You must keep alive\n"
-"the cdata object returned by new_handle()!");
-
-static PyObject *ffi_new_handle(FFIObject *self, PyObject *arg)
-{
- /* g_ct_voidp is equal to <ctype 'void *'> */
- return newp_handle(g_ct_voidp, arg);
-}
-
-PyDoc_STRVAR(ffi_from_handle_doc,
-"Cast a 'void *' back to a Python object. Must be used *only* on the\n"
-"pointers returned by new_handle(), and *only* as long as the exact\n"
-"cdata object returned by new_handle() is still alive (somewhere else\n"
-"in the program). Failure to follow these rules will crash.");
-
-#define ffi_from_handle b_from_handle /* ffi_from_handle => b_from_handle
- from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_from_buffer_doc,
-"Return a <cdata 'char[]'> that points to the data of the given Python\n"
-"object, which must support the buffer interface. Note that this is\n"
-"not meant to be used on the built-in types str or unicode\n"
-"(you can build 'char[]' arrays explicitly) but only on objects\n"
-"containing large quantities of raw data in some other format, like\n"
-"'array.array' or numpy arrays.");
-
-static PyObject *ffi_from_buffer(FFIObject *self, PyObject *args,
- PyObject *kwds)
-{
- PyObject *cdecl1, *python_buf = NULL;
- CTypeDescrObject *ct;
- int require_writable = 0;
- static char *keywords[] = {"cdecl", "python_buffer",
- "require_writable", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:from_buffer", keywords,
- &cdecl1, &python_buf, &require_writable))
- return NULL;
-
- if (python_buf == NULL) {
- python_buf = cdecl1;
- ct = g_ct_chararray;
- }
- else {
- ct = _ffi_type(self, cdecl1, ACCEPT_STRING|ACCEPT_CTYPE);
- if (ct == NULL)
- return NULL;
- }
- return direct_from_buffer(ct, python_buf, require_writable);
-}
-
-PyDoc_STRVAR(ffi_gc_doc,
-"Return a new cdata object that points to the same data.\n"
-"Later, when this new cdata object is garbage-collected,\n"
-"'destructor(old_cdata_object)' will be called.\n"
-"\n"
-"The optional 'size' gives an estimate of the size, used to\n"
-"trigger the garbage collection more eagerly. So far only used\n"
-"on PyPy. It tells the GC that the returned object keeps alive\n"
-"roughly 'size' bytes of external memory.");
-
-#define ffi_gc b_gcp /* ffi_gc() => b_gcp()
- from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_def_extern_doc,
-"A decorator. Attaches the decorated Python function to the C code\n"
-"generated for the 'extern \"Python\"' function of the same name.\n"
-"Calling the C function will then invoke the Python function.\n"
-"\n"
-"Optional arguments: 'name' is the name of the C function, if\n"
-"different from the Python function; and 'error' and 'onerror'\n"
-"handle what occurs if the Python function raises an exception\n"
-"(see the docs for details).");
-
-/* forward; see call_python.c */
-static PyObject *_ffi_def_extern_decorator(PyObject *, PyObject *);
-
-static PyObject *ffi_def_extern(FFIObject *self, PyObject *args,
- PyObject *kwds)
-{
- static PyMethodDef md = {"def_extern_decorator",
- (PyCFunction)_ffi_def_extern_decorator, METH_O};
- PyObject *name = Py_None, *error = Py_None;
- PyObject *res, *onerror = Py_None;
- static char *keywords[] = {"name", "error", "onerror", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", keywords,
- &name, &error, &onerror))
- return NULL;
-
- args = Py_BuildValue("(OOOO)", (PyObject *)self, name, error, onerror);
- if (args == NULL)
- return NULL;
-
- res = PyCFunction_New(&md, args);
- Py_DECREF(args);
- return res;
-}
-
-PyDoc_STRVAR(ffi_callback_doc,
-"Return a callback object or a decorator making such a callback object.\n"
-"'cdecl' must name a C function pointer type. The callback invokes the\n"
-"specified 'python_callable' (which may be provided either directly or\n"
-"via a decorator). Important: the callback object must be manually\n"
-"kept alive for as long as the callback may be invoked from the C code.");
-
-static PyObject *_ffi_callback_decorator(PyObject *outer_args, PyObject *fn)
-{
- PyObject *res, *old;
-
- old = PyTuple_GET_ITEM(outer_args, 1);
- PyTuple_SET_ITEM(outer_args, 1, fn);
- res = b_callback(NULL, outer_args);
- PyTuple_SET_ITEM(outer_args, 1, old);
- return res;
-}
-
-static PyObject *ffi_callback(FFIObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *c_decl, *python_callable = Py_None, *error = Py_None;
- PyObject *res, *onerror = Py_None;
- static char *keywords[] = {"cdecl", "python_callable", "error",
- "onerror", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", keywords,
- &c_decl, &python_callable, &error,
- &onerror))
- return NULL;
-
- c_decl = (PyObject *)_ffi_type(self, c_decl, ACCEPT_STRING | ACCEPT_CTYPE |
- CONSIDER_FN_AS_FNPTR);
- if (c_decl == NULL)
- return NULL;
-
- args = Py_BuildValue("(OOOO)", c_decl, python_callable, error, onerror);
- if (args == NULL)
- return NULL;
-
- if (python_callable != Py_None) {
- res = b_callback(NULL, args);
- }
- else {
- static PyMethodDef md = {"callback_decorator",
- (PyCFunction)_ffi_callback_decorator, METH_O};
- res = PyCFunction_New(&md, args);
- }
- Py_DECREF(args);
- return res;
-}
-
-#ifdef MS_WIN32
-PyDoc_STRVAR(ffi_getwinerror_doc,
-"Return either the GetLastError() or the error number given by the\n"
-"optional 'code' argument, as a tuple '(code, message)'.");
-
-#define ffi_getwinerror b_getwinerror /* ffi_getwinerror() => b_getwinerror()
- from misc_win32.h */
-#endif
-
-PyDoc_STRVAR(ffi_errno_doc, "the value of 'errno' from/to the C calls");
-
-static PyObject *ffi_get_errno(PyObject *self, void *closure)
-{
- /* xxx maybe think about how to make the saved errno local
- to an ffi instance */
- return b_get_errno(NULL, NULL);
-}
-
-static int ffi_set_errno(PyObject *self, PyObject *newval, void *closure)
-{
- PyObject *x = b_set_errno(NULL, newval);
- if (x == NULL)
- return -1;
- Py_DECREF(x);
- return 0;
-}
-
-PyDoc_STRVAR(ffi_dlopen_doc,
-"Load and return a dynamic library identified by 'name'. The standard\n"
-"C library can be loaded by passing None.\n"
-"\n"
-"Note that functions and types declared with 'ffi.cdef()' are not\n"
-"linked to a particular library, just like C headers. In the library\n"
-"we only look for the actual (untyped) symbols at the time of their\n"
-"first access.");
-
-PyDoc_STRVAR(ffi_dlclose_doc,
-"Close a library obtained with ffi.dlopen(). After this call, access to\n"
-"functions or variables from the library will fail (possibly with a\n"
-"segmentation fault).");
-
-static PyObject *ffi_dlopen(PyObject *self, PyObject *args); /* forward */
-static PyObject *ffi_dlclose(PyObject *self, PyObject *args); /* forward */
-
-PyDoc_STRVAR(ffi_int_const_doc,
-"Get the value of an integer constant.\n"
-"\n"
-"'ffi.integer_const(\"xxx\")' is equivalent to 'lib.xxx' if xxx names an\n"
-"integer constant. The point of this function is limited to use cases\n"
-"where you have an 'ffi' object but not any associated 'lib' object.");
-
-static PyObject *ffi_int_const(FFIObject *self, PyObject *args, PyObject *kwds)
-{
- char *name;
- PyObject *x;
- static char *keywords[] = {"name", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", keywords, &name))
- return NULL;
-
- x = ffi_fetch_int_constant(self, name, 0);
-
- if (x == NULL && !PyErr_Occurred()) {
- PyErr_Format(PyExc_AttributeError,
- "integer constant '%.200s' not found", name);
- }
- return x;
-}
-
-PyDoc_STRVAR(ffi_list_types_doc,
-"Returns the user type names known to this FFI instance.\n"
-"This returns a tuple containing three lists of names:\n"
-"(typedef_names, names_of_structs, names_of_unions)");
-
-static PyObject *ffi_list_types(FFIObject *self, PyObject *noargs)
-{
- Py_ssize_t i, n1 = self->types_builder.ctx.num_typenames;
- Py_ssize_t n23 = self->types_builder.ctx.num_struct_unions;
- PyObject *o, *lst[3] = {NULL, NULL, NULL}, *result = NULL;
-
- lst[0] = PyList_New(n1);
- if (lst[0] == NULL)
- goto error;
- lst[1] = PyList_New(0);
- if (lst[1] == NULL)
- goto error;
- lst[2] = PyList_New(0);
- if (lst[2] == NULL)
- goto error;
-
- for (i = 0; i < n1; i++) {
- o = PyText_FromString(self->types_builder.ctx.typenames[i].name);
- if (o == NULL)
- goto error;
- PyList_SET_ITEM(lst[0], i, o);
- }
-
- for (i = 0; i < n23; i++) {
- const struct _cffi_struct_union_s *s;
- int err, index;
-
- s = &self->types_builder.ctx.struct_unions[i];
- if (s->name[0] == '$')
- continue;
-
- o = PyText_FromString(s->name);
- if (o == NULL)
- goto error;
- index = (s->flags & _CFFI_F_UNION) ? 2 : 1;
- err = PyList_Append(lst[index], o);
- Py_DECREF(o);
- if (err < 0)
- goto error;
- }
- result = PyTuple_Pack(3, lst[0], lst[1], lst[2]);
- /* fall-through */
- error:
- Py_XDECREF(lst[2]);
- Py_XDECREF(lst[1]);
- Py_XDECREF(lst[0]);
- return result;
-}
-
-PyDoc_STRVAR(ffi_memmove_doc,
-"ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.\n"
-"\n"
-"Like the C function memmove(), the memory areas may overlap;\n"
-"apart from that it behaves like the C function memcpy().\n"
-"\n"
-"'src' can be any cdata ptr or array, or any Python buffer object.\n"
-"'dest' can be any cdata ptr or array, or a writable Python buffer\n"
-"object. The size to copy, 'n', is always measured in bytes.\n"
-"\n"
-"Unlike other methods, this one supports all Python buffer including\n"
-"byte strings and bytearrays---but it still does not support\n"
-"non-contiguous buffers.");
-
-#define ffi_memmove b_memmove /* ffi_memmove() => b_memmove()
- from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_init_once_doc,
-"init_once(function, tag): run function() once. More precisely,\n"
-"'function()' is called the first time we see a given 'tag'.\n"
-"\n"
-"The return value of function() is remembered and returned by the current\n"
-"and all future init_once() with the same tag. If init_once() is called\n"
-"from multiple threads in parallel, all calls block until the execution\n"
-"of function() is done. If function() raises an exception, it is\n"
-"propagated and nothing is cached.");
-
-#if PY_MAJOR_VERSION < 3
-/* PyCapsule_New is redefined to be PyCObject_FromVoidPtr in _cffi_backend,
- which gives 2.6 compatibility; but the destructor signature is different */
-static void _free_init_once_lock(void *lock)
-{
- PyThread_free_lock((PyThread_type_lock)lock);
-}
-#else
-static void _free_init_once_lock(PyObject *capsule)
-{
- PyThread_type_lock lock;
- lock = PyCapsule_GetPointer(capsule, "cffi_init_once_lock");
- if (lock != NULL)
- PyThread_free_lock(lock);
-}
-#endif
-
-static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds)
-{
- static char *keywords[] = {"func", "tag", NULL};
- PyObject *cache, *func, *tag, *tup, *res, *x, *lockobj;
- PyThread_type_lock lock;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", keywords, &func, &tag))
- return NULL;
-
- /* a lot of fun with reference counting and error checking
- in this function */
-
- /* atomically get or create a new dict (no GIL release) */
- cache = self->init_once_cache;
- if (cache == NULL) {
- cache = PyDict_New();
- if (cache == NULL)
- return NULL;
- self->init_once_cache = cache;
- }
-
- /* get the tuple from cache[tag], or make a new one: (False, lock) */
- tup = PyDict_GetItem(cache, tag);
- if (tup == NULL) {
- lock = PyThread_allocate_lock();
- if (lock == NULL)
- return NULL;
- x = PyCapsule_New(lock, "cffi_init_once_lock", _free_init_once_lock);
- if (x == NULL) {
- PyThread_free_lock(lock);
- return NULL;
- }
- tup = PyTuple_Pack(2, Py_False, x);
- Py_DECREF(x);
- if (tup == NULL)
- return NULL;
- x = tup;
-
- /* Possible corner case if 'tag' is an object overriding __eq__
- in pure Python: the GIL may be released when we are running it.
- We really need to call dict.setdefault(). */
- tup = PyObject_CallMethod(cache, "setdefault", "OO", tag, x);
- Py_DECREF(x);
- if (tup == NULL)
- return NULL;
-
- Py_DECREF(tup); /* there is still a ref inside the dict */
- }
-
- res = PyTuple_GET_ITEM(tup, 1);
- Py_INCREF(res);
-
- if (PyTuple_GET_ITEM(tup, 0) == Py_True) {
- /* tup == (True, result): return the result. */
- return res;
- }
-
- /* tup == (False, lock) */
- lockobj = res;
- lock = (PyThread_type_lock)PyCapsule_GetPointer(lockobj,
- "cffi_init_once_lock");
- if (lock == NULL) {
- Py_DECREF(lockobj);
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- PyThread_acquire_lock(lock, WAIT_LOCK);
- Py_END_ALLOW_THREADS
-
- x = PyDict_GetItem(cache, tag);
- if (x != NULL && PyTuple_GET_ITEM(x, 0) == Py_True) {
- /* the real result was put in the dict while we were waiting
- for PyThread_acquire_lock() above */
- res = PyTuple_GET_ITEM(x, 1);
- Py_INCREF(res);
- }
- else {
- res = PyObject_CallFunction(func, "");
- if (res != NULL) {
- tup = PyTuple_Pack(2, Py_True, res);
- if (tup == NULL || PyDict_SetItem(cache, tag, tup) < 0) {
- Py_DECREF(res);
- res = NULL;
- }
- Py_XDECREF(tup);
- }
- }
-
- PyThread_release_lock(lock);
- Py_DECREF(lockobj);
- return res;
-}
-
-PyDoc_STRVAR(ffi_release_doc,
-"Release now the resources held by a 'cdata' object from ffi.new(),\n"
-"ffi.gc() or ffi.from_buffer(). The cdata object must not be used\n"
-"afterwards.\n"
-"\n"
-"'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'.\n"
-"\n"
-"Note that on CPython this method has no effect (so far) on objects\n"
-"returned by ffi.new(), because the memory is allocated inline with the\n"
-"cdata object and cannot be freed independently. It might be fixed in\n"
-"future releases of cffi.");
-
-#define ffi_release b_release /* ffi_release() => b_release()
- from _cffi_backend.c */
-
-
-#define METH_VKW (METH_VARARGS | METH_KEYWORDS)
-static PyMethodDef ffi_methods[] = {
- {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS, ffi_addressof_doc},
- {"alignof", (PyCFunction)ffi_alignof, METH_O, ffi_alignof_doc},
- {"def_extern", (PyCFunction)ffi_def_extern, METH_VKW, ffi_def_extern_doc},
- {"callback", (PyCFunction)ffi_callback, METH_VKW, ffi_callback_doc},
- {"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc},
- {"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc},
- {"dlopen", (PyCFunction)ffi_dlopen, METH_VARARGS, ffi_dlopen_doc},
- {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW, ffi_from_buffer_doc},
- {"from_handle",(PyCFunction)ffi_from_handle,METH_O, ffi_from_handle_doc},
- {"gc", (PyCFunction)ffi_gc, METH_VKW, ffi_gc_doc},
- {"getctype", (PyCFunction)ffi_getctype, METH_VKW, ffi_getctype_doc},
-#ifdef MS_WIN32
- {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VKW, ffi_getwinerror_doc},
-#endif
- {"init_once", (PyCFunction)ffi_init_once, METH_VKW, ffi_init_once_doc},
- {"integer_const",(PyCFunction)ffi_int_const,METH_VKW, ffi_int_const_doc},
- {"list_types", (PyCFunction)ffi_list_types, METH_NOARGS, ffi_list_types_doc},
- {"memmove", (PyCFunction)ffi_memmove, METH_VKW, ffi_memmove_doc},
- {"new", (PyCFunction)ffi_new, METH_VKW, ffi_new_doc},
-{"new_allocator",(PyCFunction)ffi_new_allocator,METH_VKW,ffi_new_allocator_doc},
- {"new_handle", (PyCFunction)ffi_new_handle, METH_O, ffi_new_handle_doc},
- {"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS, ffi_offsetof_doc},
- {"release", (PyCFunction)ffi_release, METH_O, ffi_release_doc},
- {"sizeof", (PyCFunction)ffi_sizeof, METH_O, ffi_sizeof_doc},
- {"string", (PyCFunction)ffi_string, METH_VKW, ffi_string_doc},
- {"typeof", (PyCFunction)ffi_typeof, METH_O, ffi_typeof_doc},
- {"unpack", (PyCFunction)ffi_unpack, METH_VKW, ffi_unpack_doc},
- {NULL}
-};
-
-static PyGetSetDef ffi_getsets[] = {
- {"errno", ffi_get_errno, ffi_set_errno, ffi_errno_doc},
- {NULL}
-};
-
-static PyTypeObject FFI_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.FFI",
- sizeof(FFIObject),
- 0,
- (destructor)ffi_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)ffi_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- ffi_methods, /* tp_methods */
- 0, /* tp_members */
- ffi_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- ffiobj_init, /* tp_init */
- 0, /* tp_alloc */
- ffiobj_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-
-static PyObject *
-_fetch_external_struct_or_union(const struct _cffi_struct_union_s *s,
- PyObject *included_ffis, int recursion)
-{
- Py_ssize_t i;
-
- if (included_ffis == NULL)
- return NULL;
-
- if (recursion > 100) {
- PyErr_SetString(PyExc_RuntimeError,
- "recursion overflow in ffi.include() delegations");
- return NULL;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
- FFIObject *ffi1;
- const struct _cffi_struct_union_s *s1;
- int sindex;
- PyObject *x;
-
- ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
- sindex = search_in_struct_unions(&ffi1->types_builder.ctx, s->name,
- strlen(s->name));
- if (sindex < 0) /* not found at all */
- continue;
- s1 = &ffi1->types_builder.ctx.struct_unions[sindex];
- if ((s1->flags & (_CFFI_F_EXTERNAL | _CFFI_F_UNION))
- == (s->flags & _CFFI_F_UNION)) {
- /* s1 is not external, and the same kind (struct or union) as s */
- return _realize_c_struct_or_union(&ffi1->types_builder, sindex);
- }
- /* not found, look more recursively */
- x = _fetch_external_struct_or_union(
- s, ffi1->types_builder.included_ffis, recursion + 1);
- if (x != NULL || PyErr_Occurred())
- return x; /* either found, or got an error */
- }
- return NULL; /* not found at all, leave without an error */
-}
diff --git a/c/file_emulator.h b/c/file_emulator.h
deleted file mode 100644
index 82a34c0..0000000
--- a/c/file_emulator.h
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
-
-static PyObject *PyIOBase_TypeObj;
-
-static int init_file_emulator(void)
-{
- if (PyIOBase_TypeObj == NULL) {
- PyObject *io = PyImport_ImportModule("_io");
- if (io == NULL)
- return -1;
- PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
- if (PyIOBase_TypeObj == NULL)
- return -1;
- }
- return 0;
-}
-
-
-#define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
-
-
-static void _close_file_capsule(PyObject *ob_capsule)
-{
- FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
- if (f != NULL)
- fclose(f);
-}
-
-
-static FILE *PyFile_AsFile(PyObject *ob_file)
-{
- PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
- FILE *f;
- int fd;
- const char *mode;
-
- ob = PyObject_CallMethod(ob_file, "flush", NULL);
- if (ob == NULL)
- goto fail;
- Py_DECREF(ob);
-
- ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
- if (ob_capsule == NULL) {
- PyErr_Clear();
-
- fd = PyObject_AsFileDescriptor(ob_file);
- if (fd < 0)
- goto fail;
-
- ob_mode = PyObject_GetAttrString(ob_file, "mode");
- if (ob_mode == NULL)
- goto fail;
- mode = PyText_AsUTF8(ob_mode);
- if (mode == NULL)
- goto fail;
-
- fd = dup(fd);
- if (fd < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto fail;
- }
-
- f = fdopen(fd, mode);
- if (f == NULL) {
- close(fd);
- PyErr_SetFromErrno(PyExc_OSError);
- goto fail;
- }
- setbuf(f, NULL); /* non-buffered */
- Py_DECREF(ob_mode);
- ob_mode = NULL;
-
- ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
- if (ob_capsule == NULL) {
- fclose(f);
- goto fail;
- }
-
- if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
- goto fail;
- }
- else {
- f = PyCapsule_GetPointer(ob_capsule, "FILE");
- }
- Py_DECREF(ob_capsule); /* assumes still at least one reference */
- return f;
-
- fail:
- Py_XDECREF(ob_mode);
- Py_XDECREF(ob_capsule);
- return NULL;
-}
diff --git a/c/lib_obj.c b/c/lib_obj.c
deleted file mode 100644
index 38bf3d5..0000000
--- a/c/lib_obj.c
+++ /dev/null
@@ -1,716 +0,0 @@
-
-/* A Lib object is what is in the "lib" attribute of a C extension
- module originally created by recompile().
-
- A Lib object is special in the sense that it has a custom
- __getattr__ which returns C globals, functions and constants. The
- original idea was to raise AttributeError for anything else, even
- attrs like '__class__', but it breaks various things; now, standard
- attrs are returned, but in the unlikely case where a user cdef()s
- the same name, then the standard attr is hidden (and the various
- things like introspection might break).
-
- A Lib object has got a reference to the _cffi_type_context_s
- structure, which is used to create lazily the objects returned by
- __getattr__.
-*/
-
-struct CPyExtFunc_s {
- PyMethodDef md;
- void *direct_fn;
- int type_index;
- char doc[1];
-};
-
-struct LibObject_s {
- PyObject_HEAD
- builder_c_t *l_types_builder; /* same as the one on the ffi object */
- PyObject *l_dict; /* content, built lazily */
- PyObject *l_libname; /* some string that gives the name of the lib */
- FFIObject *l_ffi; /* reference back to the ffi object */
- void *l_libhandle; /* the dlopen()ed handle, if any */
- int l_auto_close; /* if we must dlclose() this handle */
-};
-
-static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
-{
- PyObject *y;
- LibObject *lo;
- PyCFunctionObject *fo;
-
- if (!PyCFunction_Check(x))
- return NULL;
- y = PyCFunction_GET_SELF(x);
- if (!LibObject_Check(y))
- return NULL;
-
- fo = (PyCFunctionObject *)x;
- lo = (LibObject *)y;
- if (lo->l_libname != fo->m_module)
- return NULL;
-
- return (struct CPyExtFunc_s *)(fo->m_ml);
-}
-
-static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
-{
- PyObject *tuple, *result;
- tuple = realize_c_type_or_func(lib->l_types_builder,
- lib->l_types_builder->ctx.types,
- exf->type_index);
- if (tuple == NULL)
- return NULL;
-
- /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
- object */
- result = PyTuple_GetItem(tuple, 0);
- Py_XINCREF(result);
- Py_DECREF(tuple);
- return result;
-}
-
-static PyObject *_cpyextfunc_type_index(PyObject *x)
-{
- struct CPyExtFunc_s *exf;
- LibObject *lib;
-
- assert(PyErr_Occurred());
- exf = _cpyextfunc_get(x);
- if (exf == NULL)
- return NULL; /* still the same exception is set */
-
- PyErr_Clear();
-
- lib = (LibObject *)PyCFunction_GET_SELF(x);
- return _cpyextfunc_type(lib, exf);
-}
-
-static void cdlopen_close_ignore_errors(void *libhandle); /* forward */
-static void *cdlopen_fetch(PyObject *libname, void *libhandle,
- const char *symbol);
-
-static void lib_dealloc(LibObject *lib)
-{
- PyObject_GC_UnTrack(lib);
- if (lib->l_auto_close)
- cdlopen_close_ignore_errors(lib->l_libhandle);
- Py_DECREF(lib->l_dict);
- Py_DECREF(lib->l_libname);
- Py_DECREF(lib->l_ffi);
- PyObject_GC_Del(lib);
-}
-
-static int lib_traverse(LibObject *lib, visitproc visit, void *arg)
-{
- Py_VISIT(lib->l_dict);
- Py_VISIT(lib->l_libname);
- Py_VISIT(lib->l_ffi);
- return 0;
-}
-
-static PyObject *lib_repr(LibObject *lib)
-{
- return PyText_FromFormat("<Lib object for '%.200s'>",
- PyText_AS_UTF8(lib->l_libname));
-}
-
-static PyObject *lib_build_cpython_func(LibObject *lib,
- const struct _cffi_global_s *g,
- const char *s, int flags)
-{
- /* First make sure the argument types and return type are really
- built. The C extension code can then assume that they are,
- by calling _cffi_type().
- */
- PyObject *result = NULL;
- CTypeDescrObject **pfargs = NULL;
- CTypeDescrObject *fresult;
- Py_ssize_t nargs = 0;
- struct CPyExtFunc_s *xfunc;
- int i, type_index = _CFFI_GETARG(g->type_op);
- _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
- static const char *const format = ";\n\nCFFI C function from %s.lib";
- const char *libname = PyText_AS_UTF8(lib->l_libname);
- struct funcbuilder_s funcbuilder;
-
- /* return type: */
- fresult = realize_c_func_return_type(lib->l_types_builder, opcodes,
- type_index);
- if (fresult == NULL)
- goto error;
-
- /* argument types: */
- /* note that if the arguments are already built, they have a
- pointer in the 'opcodes' array, and GETOP() returns a
- random even value. But OP_FUNCTION_END is odd, so the
- condition below still works correctly. */
- i = type_index + 1;
- while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END)
- i++;
- pfargs = alloca(sizeof(CTypeDescrObject *) * (i - type_index - 1));
- i = type_index + 1;
- while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
- CTypeDescrObject *ct = realize_c_type(lib->l_types_builder, opcodes, i);
- if (ct == NULL)
- goto error;
- pfargs[nargs++] = ct;
- i++;
- }
-
- memset(&funcbuilder, 0, sizeof(funcbuilder));
- if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
- goto error;
-
- /* The few bytes of memory we allocate here appear to leak, but
- this is not a real leak. Indeed, CPython never unloads its C
- extension modules. There is only one PyMem_Malloc() per real
- C function in a CFFI C extension module. That means that this
- PyMem_Malloc() could also have been written with a static
- global variable generated for each CPYTHON_BLTN defined in the
- C extension, and the effect would be the same (but a bit more
- complicated).
- */
- xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) +
- funcbuilder.nb_bytes +
- strlen(format) + strlen(libname));
- if (xfunc == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
- assert(g->address);
- xfunc->md.ml_meth = (PyCFunction)g->address;
- xfunc->md.ml_flags = flags;
- xfunc->md.ml_name = g->name;
- xfunc->md.ml_doc = xfunc->doc;
- xfunc->direct_fn = g->size_or_direct_fn;
- xfunc->type_index = type_index;
-
- /* build the docstring */
- funcbuilder.bufferp = xfunc->doc;
- if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
- goto error;
- sprintf(funcbuilder.bufferp - 1, format, libname);
- /* done building the docstring */
-
- result = PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
- /* fall-through */
- error:
- Py_XDECREF(fresult);
- while (nargs > 0) {
- --nargs;
- Py_DECREF(pfargs[nargs]);
- }
- return result;
-}
-
-static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
- int recursion)
-{
- /* does not return a new reference! */
- PyObject *x;
- int index;
- const struct _cffi_global_s *g;
- CTypeDescrObject *ct;
- builder_c_t *types_builder = lib->l_types_builder;
- const char *s = PyText_AsUTF8(name);
- if (s == NULL)
- return NULL;
-
- index = search_in_globals(&types_builder->ctx, s, strlen(s));
- if (index < 0) {
-
- if (types_builder->included_libs != NULL) {
- Py_ssize_t i;
- PyObject *included_ffis = types_builder->included_ffis;
- PyObject *included_libs = types_builder->included_libs;
-
- if (recursion > 100) {
- PyErr_SetString(PyExc_RuntimeError,
- "recursion overflow in ffi.include() delegations");
- return NULL;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
- LibObject *lib1;
-
- lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
- if (lib1 != NULL) {
- x = PyDict_GetItem(lib1->l_dict, name);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
- }
- x = lib_build_and_cache_attr(lib1, name, recursion + 1);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
- }
- }
- else {
- FFIObject *ffi1;
-
- ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
- if (ffi1 == NULL)
- return NULL;
- x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
- if (x != NULL)
- goto found;
- }
- if (PyErr_Occurred())
- return NULL;
- }
- }
-
- if (recursion > 0)
- return NULL; /* no error set, continue looking elsewhere */
-
- PyErr_Format(PyExc_AttributeError,
- "cffi library '%.200s' has no function, constant "
- "or global variable named '%.200s'",
- PyText_AS_UTF8(lib->l_libname), s);
- return NULL;
- }
-
- g = &types_builder->ctx.globals[index];
-
- switch (_CFFI_GETOP(g->type_op)) {
-
- case _CFFI_OP_CPYTHON_BLTN_V:
- x = lib_build_cpython_func(lib, g, s, METH_VARARGS);
- break;
-
- case _CFFI_OP_CPYTHON_BLTN_N:
- x = lib_build_cpython_func(lib, g, s, METH_NOARGS);
- break;
-
- case _CFFI_OP_CPYTHON_BLTN_O:
- x = lib_build_cpython_func(lib, g, s, METH_O);
- break;
-
- case _CFFI_OP_CONSTANT_INT:
- case _CFFI_OP_ENUM:
- {
- /* a constant integer whose value, in an "unsigned long long",
- is obtained by calling the function at g->address */
- x = realize_global_int(types_builder, index);
- break;
- }
-
- case _CFFI_OP_CONSTANT:
- case _CFFI_OP_DLOPEN_CONST:
- {
- /* a constant which is not of integer type */
- char *data;
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
-
- if (ct->ct_size <= 0) {
- PyErr_Format(FFIError, "constant '%s' is of type '%s', "
- "whose size is not known", s, ct->ct_name);
- return NULL;
- }
- if (g->address == NULL) {
- /* for dlopen() style */
- assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_DLOPEN_CONST);
- data = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (data == NULL)
- return NULL;
- }
- else {
- /* The few bytes of memory we allocate here appear to leak, but
- this is not a real leak. Indeed, CPython never unloads its C
- extension modules. There is only one PyMem_Malloc() per real
- non-integer C constant in a CFFI C extension module. That
- means that this PyMem_Malloc() could also have been written
- with a static global variable generated for each OP_CONSTANT
- defined in the C extension, and the effect would be the same
- (but a bit more complicated).
-
- Note that we used to do alloca(), but see issue #198. We
- could still do alloca(), or explicit PyMem_Free(), in some
- cases; but there is no point and it only makes the remaining
- less-common cases more suspicious.
- */
- assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT);
- data = PyMem_Malloc(ct->ct_size);
- if (data == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- ((void(*)(char*))g->address)(data);
- }
- x = convert_to_object(data, ct);
- Py_DECREF(ct);
- break;
- }
-
- case _CFFI_OP_GLOBAL_VAR:
- {
- /* global variable of the exact type specified here
- (nowadays, only used by the ABI mode or backward
- compatibility; see _CFFI_OP_GLOBAL_VAR_F for the API mode)
- */
- Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- if (g_size != ct->ct_size && g_size != 0 && ct->ct_size > 0) {
- PyErr_Format(FFIError,
- "global variable '%.200s' should be %zd bytes "
- "according to the cdef, but is actually %zd",
- s, ct->ct_size, g_size);
- x = NULL;
- }
- else {
- void *address = g->address;
- if (address == NULL) {
- /* for dlopen() style */
- address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (address == NULL)
- return NULL;
- }
- x = make_global_var(name, ct, address, NULL);
- }
- Py_DECREF(ct);
- break;
- }
-
- case _CFFI_OP_GLOBAL_VAR_F:
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- x = make_global_var(name, ct, NULL, (gs_fetch_addr_fn)g->address);
- Py_DECREF(ct);
- break;
-
- case _CFFI_OP_DLOPEN_FUNC:
- {
- /* For dlopen(): the function of the given 'name'. We use
- dlsym() to get the address of something in the dynamic
- library, which we interpret as being exactly a function of
- the specified type.
- */
- PyObject *ct1;
- void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (address == NULL)
- return NULL;
-
- ct1 = realize_c_type_or_func(types_builder,
- types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct1 == NULL)
- return NULL;
-
- assert(!CTypeDescr_Check(ct1)); /* must be a function */
- x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
-
- Py_DECREF(ct1);
- break;
- }
-
- case _CFFI_OP_EXTERN_PYTHON:
- /* for reading 'lib.bar' where bar is declared with extern "Python" */
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- x = convert_to_object((char *)&g->size_or_direct_fn, ct);
- Py_DECREF(ct);
- break;
-
- default:
- PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
- (int)_CFFI_GETOP(g->type_op));
- return NULL;
- }
-
- found:
- if (x != NULL) {
- int err = PyDict_SetItem(lib->l_dict, name, x);
- Py_DECREF(x);
- if (err < 0) /* else there is still one ref left in the dict */
- return NULL;
- }
- return x;
-}
-
-#define LIB_GET_OR_CACHE_ADDR(x, lib, name, error) \
- do { \
- x = PyDict_GetItem(lib->l_dict, name); \
- if (x == NULL) { \
- x = lib_build_and_cache_attr(lib, name, 0); \
- if (x == NULL) { \
- error; \
- } \
- } \
- } while (0)
-
-static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars)
-{
- const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
- int i, count = 0, total = lib->l_types_builder->ctx.num_globals;
- PyObject *s, *lst = PyList_New(total);
- if (lst == NULL)
- return NULL;
-
- for (i = 0; i < total; i++) {
- if (ignore_global_vars) {
- int op = _CFFI_GETOP(g[i].type_op);
- if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F)
- continue;
- }
- s = PyText_FromString(g[i].name);
- if (s == NULL)
- goto error;
- PyList_SET_ITEM(lst, count, s);
- count++;
- }
- if (PyList_SetSlice(lst, count, total, NULL) < 0)
- goto error;
- return lst;
-
- error:
- Py_DECREF(lst);
- return NULL;
-}
-
-static PyObject *_lib_dict(LibObject *lib)
-{
- const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
- int i, total = lib->l_types_builder->ctx.num_globals;
- PyObject *name, *x, *d = PyDict_New();
- if (d == NULL)
- return NULL;
-
- for (i = 0; i < total; i++) {
- name = PyText_FromString(g[i].name);
- if (name == NULL)
- goto error;
-
- LIB_GET_OR_CACHE_ADDR(x, lib, name, goto error);
-
- if (PyDict_SetItem(d, name, x) < 0)
- goto error;
- Py_DECREF(name);
- }
- return d;
-
- error:
- Py_XDECREF(name);
- Py_DECREF(d);
- return NULL;
-}
-
-static PyObject *lib_getattr(LibObject *lib, PyObject *name)
-{
- const char *p;
- PyObject *x;
- LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing);
-
- if (GlobSupport_Check(x)) {
- return read_global_var((GlobSupportObject *)x);
- }
- Py_INCREF(x);
- return x;
-
- missing:
- /*** ATTRIBUTEERROR IS SET HERE ***/
- p = PyText_AsUTF8(name);
- if (p == NULL)
- return NULL;
- if (strcmp(p, "__all__") == 0) {
- PyErr_Clear();
- return _lib_dir1(lib, 1);
- }
- if (strcmp(p, "__dict__") == 0) {
- PyErr_Clear();
- return _lib_dict(lib);
- }
- if (strcmp(p, "__class__") == 0) {
- PyErr_Clear();
- x = (PyObject *)&PyModule_Type;
- /* ^^^ used to be Py_TYPE(lib). But HAAAAAACK! That makes
- help() behave correctly. I couldn't find a more reasonable
- way. Urgh. */
- Py_INCREF(x);
- return x;
- }
- /* this hack is for Python 3.5, and also to give a more
- module-like behavior */
- if (strcmp(p, "__name__") == 0) {
- PyErr_Clear();
- return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname));
- }
-#if PY_MAJOR_VERSION >= 3
- if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) {
- /* some more module-like behavior hacks */
- PyErr_Clear();
- Py_INCREF(Py_None);
- return Py_None;
- }
-#endif
- return NULL;
-}
-
-static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val)
-{
- PyObject *x;
- LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1);
-
- if (val == NULL) {
- PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted");
- return -1;
- }
-
- if (GlobSupport_Check(x)) {
- return write_global_var((GlobSupportObject *)x, val);
- }
-
- PyErr_Format(PyExc_AttributeError,
- "cannot write to function or constant '%.200s'",
- PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
- return -1;
-}
-
-static PyObject *lib_dir(PyObject *self, PyObject *noarg)
-{
- return _lib_dir1((LibObject *)self, 0);
-}
-
-static PyMethodDef lib_methods[] = {
- {"__dir__", lib_dir, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject Lib_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.Lib",
- sizeof(LibObject),
- 0,
- (destructor)lib_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)lib_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)lib_getattr, /* tp_getattro */
- (setattrofunc)lib_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)lib_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- lib_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(LibObject, l_dict), /* tp_dictoffset */
-};
-
-static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name,
- void *dlopen_libhandle, int auto_close)
-{
- LibObject *lib;
- PyObject *libname, *dict;
-
- libname = PyText_FromString(module_name);
- if (libname == NULL)
- goto err1;
-
- dict = PyDict_New();
- if (dict == NULL)
- goto err2;
-
- lib = (LibObject *)PyType_GenericAlloc(&Lib_Type, 0);
- if (lib == NULL)
- goto err3;
-
- lib->l_types_builder = &ffi->types_builder;
- lib->l_dict = dict;
- lib->l_libname = libname;
- Py_INCREF(ffi);
- lib->l_ffi = ffi;
- lib->l_libhandle = dlopen_libhandle;
- lib->l_auto_close = auto_close;
- return lib;
-
- err3:
- Py_DECREF(dict);
- err2:
- Py_DECREF(libname);
- err1:
- if (auto_close)
- cdlopen_close_ignore_errors(dlopen_libhandle);
- return NULL;
-}
-
-static PyObject *address_of_global_var(PyObject *args)
-{
- LibObject *lib;
- PyObject *x, *o_varname;
- char *varname;
-
- if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname))
- return NULL;
-
- /* rebuild a string from 'varname', to do typechecks and to force
- a unicode back to a plain string (on python 2) */
- o_varname = PyText_FromString(varname);
- if (o_varname == NULL)
- return NULL;
-
- LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error);
- Py_DECREF(o_varname);
- if (GlobSupport_Check(x)) {
- return cg_addressof_global_var((GlobSupportObject *)x);
- }
- else {
- struct CPyExtFunc_s *exf = _cpyextfunc_get(x);
- if (exf != NULL) { /* an OP_CPYTHON_BLTN: '&func' returns a cdata */
- PyObject *ct;
- if (exf->direct_fn == NULL) {
- Py_INCREF(x); /* backward compatibility */
- return x;
- }
- ct = _cpyextfunc_type(lib, exf);
- if (ct == NULL)
- return NULL;
- x = new_simple_cdata(exf->direct_fn, (CTypeDescrObject *)ct);
- Py_DECREF(ct);
- return x;
- }
- if (CData_Check(x) && /* a constant functionptr cdata: 'f == &f' */
- (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0) {
- Py_INCREF(x);
- return x;
- }
- else {
- PyErr_Format(PyExc_AttributeError,
- "cannot take the address of the constant '%.200s'",
- varname);
- return NULL;
- }
- }
-
- error:
- Py_DECREF(o_varname);
- return NULL;
-}
diff --git a/c/libffi_arm64/README b/c/libffi_arm64/README
deleted file mode 100644
index 3b8f133..0000000
--- a/c/libffi_arm64/README
+++ /dev/null
@@ -1,5 +0,0 @@
-Libffi package for ARM64 is copied from cpython binary dependencies
-
-https://github.com/python/cpython-bin-deps/archive/libffi.zip
-
-The library file has been renamed from libffi-7.lib to ffi.lib to avoid special casing \ No newline at end of file
diff --git a/c/libffi_arm64/ffi.lib b/c/libffi_arm64/ffi.lib
deleted file mode 100644
index 4a8b84b..0000000
--- a/c/libffi_arm64/ffi.lib
+++ /dev/null
Binary files differ
diff --git a/c/libffi_arm64/include/ffi.h b/c/libffi_arm64/include/ffi.h
deleted file mode 100644
index d91c3e1..0000000
--- a/c/libffi_arm64/include/ffi.h
+++ /dev/null
@@ -1,515 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
- - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the ``Software''), to deal in the Software without
- restriction, including without limitation the rights to use, copy,
- modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------
- Most of the API is documented in doc/libffi.texi.
-
- The raw API is designed to bypass some of the argument packing and
- unpacking on architectures for which it can be avoided. Routines
- are provided to emulate the raw API if the underlying platform
- doesn't allow faster implementation.
-
- More details on the raw API can be found in:
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-
- and
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
- -------------------------------------------------------------------- */
-
-#ifndef LIBFFI_H
-#define LIBFFI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Specify which architecture libffi is configured for. */
-#ifndef ARM_WIN64
-#define ARM_WIN64
-#endif
-
-/* ---- System configuration information --------------------------------- */
-
-#include <ffitarget.h>
-
-#ifndef LIBFFI_ASM
-
-#if defined(_MSC_VER) && !defined(__clang__)
-#define __attribute__(X)
-#endif
-
-#include <stddef.h>
-#include <limits.h>
-
-/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
- But we can find it either under the correct ANSI name, or under GNU
- C's internal name. */
-
-#define FFI_64_BIT_MAX 9223372036854775807
-
-#ifdef LONG_LONG_MAX
-# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-#else
-# ifdef LLONG_MAX
-# define FFI_LONG_LONG_MAX LLONG_MAX
-# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-# undef FFI_64_BIT_MAX
-# define FFI_64_BIT_MAX 9223372036854775807LL
-# endif /* _AIX52 or newer */
-# else
-# ifdef __GNUC__
-# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-# endif
-# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-# ifndef __PPC64__
-# if defined (__IBMC__) || defined (__IBMCPP__)
-# define FFI_LONG_LONG_MAX LONGLONG_MAX
-# endif
-# endif /* __PPC64__ */
-# undef FFI_64_BIT_MAX
-# define FFI_64_BIT_MAX 9223372036854775807LL
-# endif
-# endif
-#endif
-
-/* The closure code assumes that this works on pointers, i.e. a size_t
- can hold a pointer. */
-
-typedef struct _ffi_type
-{
- size_t size;
- unsigned short alignment;
- unsigned short type;
- struct _ffi_type **elements;
-} ffi_type;
-
-/* Need minimal decorations for DLLs to work on Windows. GCC has
- autoimport and autoexport. Always mark externally visible symbols
- as dllimport for MSVC clients, even if it means an extra indirection
- when using the static version of the library.
- Besides, as a workaround, they can define FFI_BUILDING if they
- *know* they are going to link with the static library. */
-#if defined _MSC_VER
-# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
-# define FFI_API __declspec(dllexport)
-# elif !defined FFI_BUILDING /* Importing libffi.DLL */
-# define FFI_API __declspec(dllimport)
-# else /* Building/linking static library */
-# define FFI_API
-# endif
-#else
-# define FFI_API
-#endif
-
-/* The externally visible type declarations also need the MSVC DLL
- decorations, or they will not be exported from the object file. */
-#if defined LIBFFI_HIDE_BASIC_TYPES
-# define FFI_EXTERN FFI_API
-#else
-# define FFI_EXTERN extern FFI_API
-#endif
-
-#ifndef LIBFFI_HIDE_BASIC_TYPES
-#if SCHAR_MAX == 127
-# define ffi_type_uchar ffi_type_uint8
-# define ffi_type_schar ffi_type_sint8
-#else
- #error "char size not supported"
-#endif
-
-#if SHRT_MAX == 32767
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-#elif SHRT_MAX == 2147483647
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-#else
- #error "short size not supported"
-#endif
-
-#if INT_MAX == 32767
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-#elif INT_MAX == 2147483647
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-#elif INT_MAX == 9223372036854775807
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-#else
- #error "int size not supported"
-#endif
-
-#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
- #error "no 64-bit data type supported"
-# endif
-#elif LONG_MAX != FFI_64_BIT_MAX
- #error "long size not supported"
-#endif
-
-#if LONG_MAX == 2147483647
-# define ffi_type_ulong ffi_type_uint32
-# define ffi_type_slong ffi_type_sint32
-#elif LONG_MAX == FFI_64_BIT_MAX
-# define ffi_type_ulong ffi_type_uint64
-# define ffi_type_slong ffi_type_sint64
-#else
- #error "long size not supported"
-#endif
-
-/* These are defined in types.c. */
-FFI_EXTERN ffi_type ffi_type_void;
-FFI_EXTERN ffi_type ffi_type_uint8;
-FFI_EXTERN ffi_type ffi_type_sint8;
-FFI_EXTERN ffi_type ffi_type_uint16;
-FFI_EXTERN ffi_type ffi_type_sint16;
-FFI_EXTERN ffi_type ffi_type_uint32;
-FFI_EXTERN ffi_type ffi_type_sint32;
-FFI_EXTERN ffi_type ffi_type_uint64;
-FFI_EXTERN ffi_type ffi_type_sint64;
-FFI_EXTERN ffi_type ffi_type_float;
-FFI_EXTERN ffi_type ffi_type_double;
-FFI_EXTERN ffi_type ffi_type_pointer;
-
-#if 0
-FFI_EXTERN ffi_type ffi_type_longdouble;
-#else
-#define ffi_type_longdouble ffi_type_double
-#endif
-
-#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-FFI_EXTERN ffi_type ffi_type_complex_float;
-FFI_EXTERN ffi_type ffi_type_complex_double;
-#if 0
-FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-#else
-#define ffi_type_complex_longdouble ffi_type_complex_double
-#endif
-#endif
-#endif /* LIBFFI_HIDE_BASIC_TYPES */
-
-typedef enum {
- FFI_OK = 0,
- FFI_BAD_TYPEDEF,
- FFI_BAD_ABI
-} ffi_status;
-
-typedef struct {
- ffi_abi abi;
- unsigned nargs;
- ffi_type **arg_types;
- ffi_type *rtype;
- unsigned bytes;
- unsigned flags;
-#ifdef FFI_EXTRA_CIF_FIELDS
- FFI_EXTRA_CIF_FIELDS;
-#endif
-} ffi_cif;
-
-/* ---- Definitions for the raw API -------------------------------------- */
-
-#ifndef FFI_SIZEOF_ARG
-# if LONG_MAX == 2147483647
-# define FFI_SIZEOF_ARG 4
-# elif LONG_MAX == FFI_64_BIT_MAX
-# define FFI_SIZEOF_ARG 8
-# endif
-#endif
-
-#ifndef FFI_SIZEOF_JAVA_RAW
-# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-#endif
-
-typedef union {
- ffi_sarg sint;
- ffi_arg uint;
- float flt;
- char data[FFI_SIZEOF_ARG];
- void* ptr;
-} ffi_raw;
-
-#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-/* This is a special case for mips64/n32 ABI (and perhaps others) where
- sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
-typedef union {
- signed int sint;
- unsigned int uint;
- float flt;
- char data[FFI_SIZEOF_JAVA_RAW];
- void* ptr;
-} ffi_java_raw;
-#else
-typedef ffi_raw ffi_java_raw;
-#endif
-
-
-FFI_API
-void ffi_raw_call (ffi_cif *cif,
- void (*fn)(void),
- void *rvalue,
- ffi_raw *avalue);
-
-FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-FFI_API size_t ffi_raw_size (ffi_cif *cif);
-
-/* This is analogous to the raw API, except it uses Java parameter
- packing, even on 64-bit machines. I.e. on 64-bit machines longs
- and doubles are followed by an empty 64-bit word. */
-
-#if !FFI_NATIVE_RAW_API
-FFI_API
-void ffi_java_raw_call (ffi_cif *cif,
- void (*fn)(void),
- void *rvalue,
- ffi_java_raw *avalue);
-#endif
-
-FFI_API
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-FFI_API
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-FFI_API
-size_t ffi_java_raw_size (ffi_cif *cif);
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#if FFI_CLOSURES
-
-#ifdef _MSC_VER
-__declspec(align(8))
-#endif
-typedef struct {
-#if 0
- void *trampoline_table;
- void *trampoline_table_entry;
-#else
- char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
- ffi_cif *cif;
- void (*fun)(ffi_cif*,void*,void**,void*);
- void *user_data;
-} ffi_closure
-#ifdef __GNUC__
- __attribute__((aligned (8)))
-#endif
- ;
-
-#ifndef __GNUC__
-# ifdef __sgi
-# pragma pack 0
-# endif
-#endif
-
-FFI_API void *ffi_closure_alloc (size_t size, void **code);
-FFI_API void ffi_closure_free (void *);
-
-FFI_API ffi_status
-ffi_prep_closure (ffi_closure*,
- ffi_cif *,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data)
-#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
- __attribute__((deprecated ("use ffi_prep_closure_loc instead")))
-#elif defined(__GNUC__) && __GNUC__ >= 3
- __attribute__((deprecated))
-#endif
- ;
-
-FFI_API ffi_status
-ffi_prep_closure_loc (ffi_closure*,
- ffi_cif *,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data,
- void*codeloc);
-
-#ifdef __sgi
-# pragma pack 8
-#endif
-typedef struct {
-#if 0
- void *trampoline_table;
- void *trampoline_table_entry;
-#else
- char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
- ffi_cif *cif;
-
-#if !FFI_NATIVE_RAW_API
-
- /* If this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
- handler to do the transaltion, void** -> ffi_raw*. */
-
- void (*translate_args)(ffi_cif*,void*,void**,void*);
- void *this_closure;
-
-#endif
-
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
- void *user_data;
-
-} ffi_raw_closure;
-
-typedef struct {
-#if 0
- void *trampoline_table;
- void *trampoline_table_entry;
-#else
- char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
-
- ffi_cif *cif;
-
-#if !FFI_NATIVE_RAW_API
-
- /* If this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
- handler to do the translation, void** -> ffi_raw*. */
-
- void (*translate_args)(ffi_cif*,void*,void**,void*);
- void *this_closure;
-
-#endif
-
- void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
- void *user_data;
-
-} ffi_java_raw_closure;
-
-FFI_API ffi_status
-ffi_prep_raw_closure (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data);
-
-FFI_API ffi_status
-ffi_prep_raw_closure_loc (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data,
- void *codeloc);
-
-#if !FFI_NATIVE_RAW_API
-FFI_API ffi_status
-ffi_prep_java_raw_closure (ffi_java_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
- void *user_data);
-
-FFI_API ffi_status
-ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
- void *user_data,
- void *codeloc);
-#endif
-
-#endif /* FFI_CLOSURES */
-
-#if FFI_GO_CLOSURES
-
-typedef struct {
- void *tramp;
- ffi_cif *cif;
- void (*fun)(ffi_cif*,void*,void**,void*);
-} ffi_go_closure;
-
-FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
- void (*fun)(ffi_cif*,void*,void**,void*));
-
-FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
- void **avalue, void *closure);
-
-#endif /* FFI_GO_CLOSURES */
-
-/* ---- Public interface definition -------------------------------------- */
-
-FFI_API
-ffi_status ffi_prep_cif(ffi_cif *cif,
- ffi_abi abi,
- unsigned int nargs,
- ffi_type *rtype,
- ffi_type **atypes);
-
-FFI_API
-ffi_status ffi_prep_cif_var(ffi_cif *cif,
- ffi_abi abi,
- unsigned int nfixedargs,
- unsigned int ntotalargs,
- ffi_type *rtype,
- ffi_type **atypes);
-
-FFI_API
-void ffi_call(ffi_cif *cif,
- void (*fn)(void),
- void *rvalue,
- void **avalue);
-
-FFI_API
-ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
- size_t *offsets);
-
-/* Useful for eliminating compiler warnings. */
-#define FFI_FN(f) ((void (*)(void))f)
-
-/* ---- Definitions shared with assembly code ---------------------------- */
-
-#endif
-
-/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID 0
-#define FFI_TYPE_INT 1
-#define FFI_TYPE_FLOAT 2
-#define FFI_TYPE_DOUBLE 3
-#if 0
-#define FFI_TYPE_LONGDOUBLE 4
-#else
-#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-#endif
-#define FFI_TYPE_UINT8 5
-#define FFI_TYPE_SINT8 6
-#define FFI_TYPE_UINT16 7
-#define FFI_TYPE_SINT16 8
-#define FFI_TYPE_UINT32 9
-#define FFI_TYPE_SINT32 10
-#define FFI_TYPE_UINT64 11
-#define FFI_TYPE_SINT64 12
-#define FFI_TYPE_STRUCT 13
-#define FFI_TYPE_POINTER 14
-#define FFI_TYPE_COMPLEX 15
-
-/* This should always refer to the last type code (for sanity checks). */
-#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/c/libffi_arm64/include/fficonfig.h b/c/libffi_arm64/include/fficonfig.h
deleted file mode 100644
index 5768c29..0000000
--- a/c/libffi_arm64/include/fficonfig.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* fficonfig.h. Generated from fficonfig.h.in by configure. */
-/* fficonfig.h.in. Generated from configure.ac by autoheader. */
-
-/* Define if building universal (internal helper macro) */
-/* #undef AC_APPLE_UNIVERSAL_BUILD */
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #undef EH_FRAME_FLAGS */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
-
-/* Define this if you want to enable pax emulated trampolines */
-/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-
-/* Cannot use malloc on this target, so, we revert to alternative means */
-/* #undef FFI_MMAP_EXEC_WRIT */
-
-/* Define this if you do not want support for the raw API. */
-/* #undef FFI_NO_RAW_API */
-
-/* Define this if you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
-/* #undef HAVE_ALLOCA_H */
-
-/* Define if your assembler supports .cfi_* directives. */
-/* #undef HAVE_AS_CFI_PSEUDO_OP */
-
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if the compiler uses zarch features. */
-/* #undef HAVE_AS_S390_ZARCH */
-
-/* Define if your assembler and linker support unaligned PC relative relocs.
- */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports unwind section type. */
-/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-
-/* Define if your assembler supports PC relative relocs. */
-/* #undef HAVE_AS_X86_PCREL */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* Define if __attribute__((visibility("hidden"))) is supported. */
-/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define if you have the long double type and it is bigger than a double */
-/* #undef HAVE_LONG_DOUBLE */
-
-/* Define if you support more than one size of the long double type */
-/* #undef HAVE_LONG_DOUBLE_VARIANT */
-
-/* Define to 1 if you have the `memcpy' function. */
-/* #undef HAVE_MEMCPY */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkostemp' function. */
-/* #undef HAVE_MKOSTEMP */
-
-/* Define to 1 if you have the `mmap' function. */
-/* #undef HAVE_MMAP */
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-/* #undef HAVE_MMAP_ANON */
-
-/* Define if mmap of /dev/zero works. */
-/* #undef HAVE_MMAP_DEV_ZERO */
-
-/* Define if read-only mmap of a plain file works. */
-/* #undef HAVE_MMAP_FILE */
-
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-/* #undef HAVE_STRINGS_H */
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-/* #undef HAVE_SYS_MMAN_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
-
-/* Define to 1 if GNU symbol versioning is used for libatomic. */
-/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Name of package */
-#define PACKAGE "libffi"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libffi"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libffi 3.3-rc0"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libffi"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.3-rc0"
-
-/* The size of `double', as computed by sizeof. */
-#define SIZEOF_DOUBLE 8
-
-/* The size of `long double', as computed by sizeof. */
-#define SIZEOF_LONG_DOUBLE 8
-
-/* The size of `size_t', as computed by sizeof. */
-#define SIZEOF_SIZE_T 8
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if symbols are underscored. */
-/* #undef SYMBOL_UNDERSCORE */
-
-/* Define this if you are using Purify and want to suppress spurious messages.
- */
-/* #undef USING_PURIFY */
-
-/* Version number of package */
-#define VERSION "3.3-rc0"
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-# define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-/* # undef WORDS_BIGENDIAN */
-# endif
-#endif
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-
-#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-#ifdef LIBFFI_ASM
-#ifdef __APPLE__
-#define FFI_HIDDEN(name) .private_extern name
-#else
-#define FFI_HIDDEN(name) .hidden name
-#endif
-#else
-#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-#endif
-#else
-#ifdef LIBFFI_ASM
-#define FFI_HIDDEN(name)
-#else
-#define FFI_HIDDEN
-#endif
-#endif
-
diff --git a/c/libffi_arm64/include/ffitarget.h b/c/libffi_arm64/include/ffitarget.h
deleted file mode 100644
index ecb6d2d..0000000
--- a/c/libffi_arm64/include/ffitarget.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-#ifndef LIBFFI_H
-#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
-#endif
-
-#ifndef LIBFFI_ASM
-#ifdef __ILP32__
-#define FFI_SIZEOF_ARG 8
-#define FFI_SIZEOF_JAVA_RAW 4
-typedef unsigned long long ffi_arg;
-typedef signed long long ffi_sarg;
-#elif defined(_M_ARM64)
-#define FFI_SIZEOF_ARG 8
-typedef unsigned long long ffi_arg;
-typedef signed long long ffi_sarg;
-#else
-typedef unsigned long ffi_arg;
-typedef signed long ffi_sarg;
-#endif
-
-typedef enum ffi_abi
- {
- FFI_FIRST_ABI = 0,
- FFI_SYSV,
- FFI_LAST_ABI,
- FFI_DEFAULT_ABI = FFI_SYSV
- } ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-#define FFI_NATIVE_RAW_API 0
-
-#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE
-
-#ifdef __MACH__
-#define FFI_TRAMPOLINE_SIZE 16
-#define FFI_TRAMPOLINE_CLOSURE_OFFSET 16
-#else
-#error "No trampoline table implementation"
-#endif
-
-#else
-#define FFI_TRAMPOLINE_SIZE 24
-#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
-#endif
-
-#ifdef _M_ARM64
-#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic
-#endif
-
-/* ---- Internal ---- */
-
-#if defined (__APPLE__)
-#define FFI_TARGET_SPECIFIC_VARIADIC
-#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
-#elif !defined(_M_ARM64)
-/* iOS and Windows reserve x18 for the system. Disable Go closures until
- a new static chain is chosen. */
-#define FFI_GO_CLOSURES 1
-#endif
-
-#ifndef _M_ARM64
-/* No complex type on Windows */
-#define FFI_TARGET_HAS_COMPLEX_TYPE
-#endif
-
-#endif
diff --git a/c/libffi_x86_x64/LICENSE b/c/libffi_x86_x64/LICENSE
deleted file mode 100644
index f591795..0000000
--- a/c/libffi_x86_x64/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-libffi - Copyright (c) 1996-2003 Red Hat, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
diff --git a/c/libffi_x86_x64/README b/c/libffi_x86_x64/README
deleted file mode 100644
index 97a12cf..0000000
--- a/c/libffi_x86_x64/README
+++ /dev/null
@@ -1,502 +0,0 @@
-This directory contains the libffi package, which is not part of GCC but
-shipped with GCC as convenience.
-
-Copied without changes from CPython 2.7 head (e04e1f253ed8).
-
-Status
-======
-
-libffi-2.00 has not been released yet! This is a development snapshot!
-
-libffi-1.20 was released on October 5, 1998. Check the libffi web
-page for updates: <URL:http://sources.redhat.com/libffi/>.
-
-
-What is libffi?
-===============
-
-Compilers for high level languages generate code that follow certain
-conventions. These conventions are necessary, in part, for separate
-compilation to work. One such convention is the "calling
-convention". The "calling convention" is essentially a set of
-assumptions made by the compiler about where function arguments will
-be found on entry to a function. A "calling convention" also specifies
-where the return value for a function is found.
-
-Some programs may not know at the time of compilation what arguments
-are to be passed to a function. For instance, an interpreter may be
-told at run-time about the number and types of arguments used to call
-a given function. Libffi can be used in such programs to provide a
-bridge from the interpreter program to compiled code.
-
-The libffi library provides a portable, high level programming
-interface to various calling conventions. This allows a programmer to
-call any function specified by a call interface description at run
-time.
-
-Ffi stands for Foreign Function Interface. A foreign function
-interface is the popular name for the interface that allows code
-written in one language to call code written in another language. The
-libffi library really only provides the lowest, machine dependent
-layer of a fully featured foreign function interface. A layer must
-exist above libffi that handles type conversions for values passed
-between the two languages.
-
-
-Supported Platforms and Prerequisites
-=====================================
-
-Libffi has been ported to:
-
- SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
-
- Irix 5.3 & 6.2 (System V/o32 & n32)
-
- Intel x86 - Linux (System V ABI)
-
- Alpha - Linux and OSF/1
-
- m68k - Linux (System V ABI)
-
- PowerPC - Linux (System V ABI, Darwin, AIX)
-
- ARM - Linux (System V ABI)
-
-Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
-that other versions will work. Libffi has also been built and tested
-with the SGI compiler tools.
-
-On PowerPC, the tests failed (see the note below).
-
-You must use GNU make to build libffi. SGI's make will not work.
-Sun's probably won't either.
-
-If you port libffi to another platform, please let me know! I assume
-that some will be easy (x86 NetBSD), and others will be more difficult
-(HP).
-
-
-Installing libffi
-=================
-
-[Note: before actually performing any of these installation steps,
- you may wish to read the "Platform Specific Notes" below.]
-
-First you must configure the distribution for your particular
-system. Go to the directory you wish to build libffi in and run the
-"configure" program found in the root directory of the libffi source
-distribution.
-
-You may want to tell configure where to install the libffi library and
-header files. To do that, use the --prefix configure switch. Libffi
-will install under /usr/local by default.
-
-If you want to enable extra run-time debugging checks use the the
---enable-debug configure switch. This is useful when your program dies
-mysteriously while using libffi.
-
-Another useful configure switch is --enable-purify-safety. Using this
-will add some extra code which will suppress certain warnings when you
-are using Purify with libffi. Only use this switch when using
-Purify, as it will slow down the library.
-
-Configure has many other options. Use "configure --help" to see them all.
-
-Once configure has finished, type "make". Note that you must be using
-GNU make. SGI's make will not work. Sun's probably won't either.
-You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
-
-To ensure that libffi is working as advertised, type "make test".
-
-To install the library and header files, type "make install".
-
-
-Using libffi
-============
-
- The Basics
- ----------
-
-Libffi assumes that you have a pointer to the function you wish to
-call and that you know the number and types of arguments to pass it,
-as well as the return type of the function.
-
-The first thing you must do is create an ffi_cif object that matches
-the signature of the function you wish to call. The cif in ffi_cif
-stands for Call InterFace. To prepare a call interface object, use the
-following function:
-
-ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
- unsigned int nargs,
- ffi_type *rtype, ffi_type **atypes);
-
- CIF is a pointer to the call interface object you wish
- to initialize.
-
- ABI is an enum that specifies the calling convention
- to use for the call. FFI_DEFAULT_ABI defaults
- to the system's native calling convention. Other
- ABI's may be used with care. They are system
- specific.
-
- NARGS is the number of arguments this function accepts.
- libffi does not yet support vararg functions.
-
- RTYPE is a pointer to an ffi_type structure that represents
- the return type of the function. Ffi_type objects
- describe the types of values. libffi provides
- ffi_type objects for many of the native C types:
- signed int, unsigned int, signed char, unsigned char,
- etc. There is also a pointer ffi_type object and
- a void ffi_type. Use &ffi_type_void for functions that
- don't return values.
-
- ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
- If NARGS is 0, this is ignored.
-
-
-ffi_prep_cif will return a status code that you are responsible
-for checking. It will be one of the following:
-
- FFI_OK - All is good.
-
- FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
- came across is bad.
-
-
-Before making the call, the VALUES vector should be initialized
-with pointers to the appropriate argument values.
-
-To call the the function using the initialized ffi_cif, use the
-ffi_call function:
-
-void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
-
- CIF is a pointer to the ffi_cif initialized specifically
- for this function.
-
- FN is a pointer to the function you want to call.
-
- RVALUE is a pointer to a chunk of memory that is to hold the
- result of the function call. Currently, it must be
- at least one word in size (except for the n32 version
- under Irix 6.x, which must be a pointer to an 8 byte
- aligned value (a long long). It must also be at least
- word aligned (depending on the return type, and the
- system's alignment requirements). If RTYPE is
- &ffi_type_void, this is ignored. If RVALUE is NULL,
- the return value is discarded.
-
- AVALUES is a vector of void* that point to the memory locations
- holding the argument values for a call.
- If NARGS is 0, this is ignored.
-
-
-If you are expecting a return value from FN it will have been stored
-at RVALUE.
-
-
-
- An Example
- ----------
-
-Here is a trivial example that calls puts() a few times.
-
- #include <stdio.h>
- #include <ffi.h>
-
- int main()
- {
- ffi_cif cif;
- ffi_type *args[1];
- void *values[1];
- char *s;
- int rc;
-
- /* Initialize the argument info vectors */
- args[0] = &ffi_type_uint;
- values[0] = &s;
-
- /* Initialize the cif */
- if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_uint, args) == FFI_OK)
- {
- s = "Hello World!";
- ffi_call(&cif, puts, &rc, values);
- /* rc now holds the result of the call to puts */
-
- /* values holds a pointer to the function's arg, so to
- call puts() again all we need to do is change the
- value of s */
- s = "This is cool!";
- ffi_call(&cif, puts, &rc, values);
- }
-
- return 0;
- }
-
-
-
- Aggregate Types
- ---------------
-
-Although libffi has no special support for unions or bit-fields, it is
-perfectly happy passing structures back and forth. You must first
-describe the structure to libffi by creating a new ffi_type object
-for it. Here is the definition of ffi_type:
-
- typedef struct _ffi_type
- {
- unsigned size;
- short alignment;
- short type;
- struct _ffi_type **elements;
- } ffi_type;
-
-All structures must have type set to FFI_TYPE_STRUCT. You may set
-size and alignment to 0. These will be calculated and reset to the
-appropriate values by ffi_prep_cif().
-
-elements is a NULL terminated array of pointers to ffi_type objects
-that describe the type of the structure elements. These may, in turn,
-be structure elements.
-
-The following example initializes a ffi_type object representing the
-tm struct from Linux's time.h:
-
- struct tm {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_wday;
- int tm_yday;
- int tm_isdst;
- /* Those are for future use. */
- long int __tm_gmtoff__;
- __const char *__tm_zone__;
- };
-
- {
- ffi_type tm_type;
- ffi_type *tm_type_elements[12];
- int i;
-
- tm_type.size = tm_type.alignment = 0;
- tm_type.elements = &tm_type_elements;
-
- for (i = 0; i < 9; i++)
- tm_type_elements[i] = &ffi_type_sint;
-
- tm_type_elements[9] = &ffi_type_slong;
- tm_type_elements[10] = &ffi_type_pointer;
- tm_type_elements[11] = NULL;
-
- /* tm_type can now be used to represent tm argument types and
- return types for ffi_prep_cif() */
- }
-
-
-
-Platform Specific Notes
-=======================
-
- Intel x86
- ---------
-
-There are no known problems with the x86 port.
-
- Sun SPARC - SunOS 4.1.3 & Solaris 2.x
- -------------------------------------
-
-You must use GNU Make to build libffi on Sun platforms.
-
- MIPS - Irix 5.3 & 6.x
- ---------------------
-
-Irix 6.2 and better supports three different calling conventions: o32,
-n32 and n64. Currently, libffi only supports both o32 and n32 under
-Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
-configured for whichever calling convention it was built for.
-
-By default, the configure script will try to build libffi with the GNU
-development tools. To build libffi with the SGI development tools, set
-the environment variable CC to either "cc -32" or "cc -n32" before
-running configure under Irix 6.x (depending on whether you want an o32
-or n32 library), or just "cc" for Irix 5.3.
-
-With the n32 calling convention, when returning structures smaller
-than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
-Here's one way of forcing this:
-
- double struct_storage[2];
- my_small_struct *s = (my_small_struct *) struct_storage;
- /* Use s for RVALUE */
-
-If you don't do this you are liable to get spurious bus errors.
-
-"long long" values are not supported yet.
-
-You must use GNU Make to build libffi on SGI platforms.
-
- ARM - System V ABI
- ------------------
-
-The ARM port was performed on a NetWinder running ARM Linux ELF
-(2.0.31) and gcc 2.8.1.
-
-
-
- PowerPC System V ABI
- --------------------
-
-There are two `System V ABI's which libffi implements for PowerPC.
-They differ only in how small structures are returned from functions.
-
-In the FFI_SYSV version, structures that are 8 bytes or smaller are
-returned in registers. This is what GCC does when it is configured
-for solaris, and is what the System V ABI I have (dated September
-1995) says.
-
-In the FFI_GCC_SYSV version, all structures are returned the same way:
-by passing a pointer as the first argument to the function. This is
-what GCC does when it is configured for linux or a generic sysv
-target.
-
-EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
-inconsistency with the SysV ABI: When a procedure is called with many
-floating-point arguments, some of them get put on the stack. They are
-all supposed to be stored in double-precision format, even if they are
-only single-precision, but EGCS stores single-precision arguments as
-single-precision anyway. This causes one test to fail (the `many
-arguments' test).
-
-
-What's With The Crazy Comments?
-===============================
-
-You might notice a number of cryptic comments in the code, delimited
-by /*@ and @*/. These are annotations read by the program LCLint, a
-tool for statically checking C programs. You can read all about it at
-<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
-
-
-History
-=======
-
-1.20 Oct-5-98
- Raffaele Sena produces ARM port.
-
-1.19 Oct-5-98
- Fixed x86 long double and long long return support.
- m68k bug fixes from Andreas Schwab.
- Patch for DU assembler compatibility for the Alpha from Richard
- Henderson.
-
-1.18 Apr-17-98
- Bug fixes and MIPS configuration changes.
-
-1.17 Feb-24-98
- Bug fixes and m68k port from Andreas Schwab. PowerPC port from
- Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
-
-1.16 Feb-11-98
- Richard Henderson produces Alpha port.
-
-1.15 Dec-4-97
- Fixed an n32 ABI bug. New libtool, auto* support.
-
-1.14 May-13-97
- libtool is now used to generate shared and static libraries.
- Fixed a minor portability problem reported by Russ McManus
- <mcmanr@eq.gs.com>.
-
-1.13 Dec-2-96
- Added --enable-purify-safety to keep Purify from complaining
- about certain low level code.
- Sparc fix for calling functions with < 6 args.
- Linux x86 a.out fix.
-
-1.12 Nov-22-96
- Added missing ffi_type_void, needed for supporting void return
- types. Fixed test case for non MIPS machines. Cygnus Support
- is now Cygnus Solutions.
-
-1.11 Oct-30-96
- Added notes about GNU make.
-
-1.10 Oct-29-96
- Added configuration fix for non GNU compilers.
-
-1.09 Oct-29-96
- Added --enable-debug configure switch. Clean-ups based on LCLint
- feedback. ffi_mips.h is always installed. Many configuration
- fixes. Fixed ffitest.c for sparc builds.
-
-1.08 Oct-15-96
- Fixed n32 problem. Many clean-ups.
-
-1.07 Oct-14-96
- Gordon Irlam rewrites v8.S again. Bug fixes.
-
-1.06 Oct-14-96
- Gordon Irlam improved the sparc port.
-
-1.05 Oct-14-96
- Interface changes based on feedback.
-
-1.04 Oct-11-96
- Sparc port complete (modulo struct passing bug).
-
-1.03 Oct-10-96
- Passing struct args, and returning struct values works for
- all architectures/calling conventions. Expanded tests.
-
-1.02 Oct-9-96
- Added SGI n32 support. Fixed bugs in both o32 and Linux support.
- Added "make test".
-
-1.01 Oct-8-96
- Fixed float passing bug in mips version. Restructured some
- of the code. Builds cleanly with SGI tools.
-
-1.00 Oct-7-96
- First release. No public announcement.
-
-
-Authors & Credits
-=================
-
-libffi was written by Anthony Green <green@cygnus.com>.
-
-Portions of libffi were derived from Gianni Mariani's free gencall
-library for Silicon Graphics machines.
-
-The closure mechanism was designed and implemented by Kresten Krab
-Thorup.
-
-The Sparc port was derived from code contributed by the fine folks at
-Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
-made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
-
-The Alpha port was written by Richard Henderson at Cygnus Solutions.
-
-Andreas Schwab ported libffi to m68k Linux and provided a number of
-bug fixes.
-
-Geoffrey Keating ported libffi to the PowerPC.
-
-Raffaele Sena ported libffi to the ARM.
-
-Jesper Skov and Andrew Haley both did more than their fair share of
-stepping through the code and tracking down bugs.
-
-Thanks also to Tom Tromey for bug fixes and configuration help.
-
-Thanks to Jim Blandy, who provided some useful feedback on the libffi
-interface.
-
-If you have a problem, or have found a bug, please send a note to
-green@cygnus.com.
diff --git a/c/libffi_x86_x64/README.ctypes b/c/libffi_x86_x64/README.ctypes
deleted file mode 100644
index 17e8a40..0000000
--- a/c/libffi_x86_x64/README.ctypes
+++ /dev/null
@@ -1,7 +0,0 @@
-The purpose is to hack the libffi sources so that they can be compiled
-with MSVC, and to extend them so that they have the features I need
-for ctypes.
-
-I retrieved the libffi sources from the gcc cvs repository on
-2004-01-27. Then I did 'configure' in a 'build' subdirectory on a x86
-linux system, and copied the files I found useful.
diff --git a/c/libffi_x86_x64/ffi.c b/c/libffi_x86_x64/ffi.c
deleted file mode 100644
index b9e324f..0000000
--- a/c/libffi_x86_x64/ffi.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
- Copyright (c) 2002 Ranjit Mathew
- Copyright (c) 2002 Bo Thorsen
- Copyright (c) 2002 Roger Sayle
-
- x86 Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-extern void Py_FatalError(const char *msg);
-
-/*@-exportheader@*/
-void ffi_prep_args(char *stack, extended_cif *ecif)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
- argp = stack;
- if (ecif->cif->flags == FFI_TYPE_STRUCT)
- {
- *(void **) argp = ecif->rvalue;
- argp += sizeof(void *);
- }
-
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- i != 0;
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if ((sizeof(void *) - 1) & (size_t) argp)
- argp = (char *) ALIGN(argp, sizeof(void *));
-
- z = (*p_arg)->size;
- if (z < sizeof(int))
- {
- z = sizeof(int);
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_STRUCT:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
-#ifdef _WIN64
- else if (z != 1 && z != 2 && z != 4 && z != 8)
- {
- /* On Win64, if a single argument takes more than 8 bytes,
- then it is always passed by reference. */
- *(void **)argp = *p_argv;
- z = 8;
- }
-#endif
- else
- {
- memcpy(argp, *p_argv, z);
- }
- p_argv++;
- argp += z;
- }
-
- if (argp - stack > (long)ecif->cif->bytes)
- {
- Py_FatalError("FFI BUG: not enough stack space for arguments");
- }
- return;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- case FFI_TYPE_LONGDOUBLE:
- cif->flags = (unsigned) cif->rtype->type;
- break;
-
- case FFI_TYPE_STRUCT:
- /* MSVC returns small structures in registers. Put in cif->flags
- the value FFI_TYPE_STRUCT only if the structure is big enough;
- otherwise, put the 4- or 8-bytes integer type. */
- if (cif->rtype->size == 1 ||
- cif->rtype->size == 2 ||
- cif->rtype->size == 4)
- cif->flags = FFI_TYPE_INT;
- else if (cif->rtype->size == 8)
- cif->flags = FFI_TYPE_SINT64;
- else
- cif->flags = FFI_TYPE_STRUCT;
- break;
-
- case FFI_TYPE_UINT64:
-#ifdef _WIN64
- case FFI_TYPE_POINTER:
-#endif
- cif->flags = FFI_TYPE_SINT64;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-#ifdef _WIN32
-extern int
-ffi_call_x86(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-#endif
-
-#ifdef _WIN64
-extern int
-ffi_call_AMD64(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-#endif
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ void **avalue)
-{
- extended_cif ecif;
-
- ecif.cif = cif;
- ecif.avalue = avalue;
-
- /* If the return value is a struct and we don't have a return */
- /* value address then we need to make one */
-
- if ((rvalue == NULL) &&
- (cif->flags == FFI_TYPE_STRUCT))
- {
- /*@-sysunrecog@*/
- ecif.rvalue = alloca(cif->rtype->size);
- /*@=sysunrecog@*/
- }
- else
- ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
- {
-#if !defined(_WIN64)
- case FFI_SYSV:
- case FFI_STDCALL:
- return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- break;
-#else
- case FFI_SYSV:
- /*@-usedef@*/
- return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
-#endif
-
- default:
- FFI_ASSERT(0);
- break;
- }
- return -1; /* theller: Hrm. */
-}
-
-
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
- void** args, ffi_cif* cif);
-/* This function is jumped to by the trampoline */
-
-#ifdef _WIN64
-void *
-#else
-static void __fastcall
-#endif
-ffi_closure_SYSV (ffi_closure *closure, char *argp)
-{
- // this is our return value storage
- long double res;
-
- // our various things...
- ffi_cif *cif;
- void **arg_area;
- unsigned short rtype;
- void *resp = (void*)&res;
- void *args = argp + sizeof(void *);
-
- cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
-
- /* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
- * value on the stack; and if the function returns
- * a structure, it will re-set RESP to point to the
- * structure return address. */
-
- ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
-
- (closure->fun) (cif, resp, arg_area, closure->user_data);
-
- rtype = cif->flags;
-
-#if defined(_WIN32) && !defined(_WIN64)
-#ifdef _MSC_VER
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- _asm mov eax, resp ;
- _asm mov eax, [eax] ;
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- _asm mov eax, resp ;
- _asm fld DWORD PTR [eax] ;
-// asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
- {
- _asm mov eax, resp ;
- _asm fld QWORD PTR [eax] ;
-// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- _asm mov edx, resp ;
- _asm mov eax, [edx] ;
- _asm mov edx, [edx + 4] ;
-// asm ("movl 0(%0),%%eax;"
-// "movl 4(%0),%%edx"
-// : : "r"(resp)
-// : "eax", "edx");
- }
- else if (rtype == FFI_TYPE_STRUCT)
- {
- _asm mov eax, resp ;
- }
-#else
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
- {
- asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- asm ("movl 0(%0),%%eax;"
- "movl 4(%0),%%edx"
- : : "r"(resp)
- : "eax", "edx");
- }
- else if (rtype == FFI_TYPE_STRUCT)
- {
- asm ("movl %0,%%eax" : : "r" (resp) : "eax");
- }
-#endif
-#endif
-
-#ifdef _WIN64
- /* The result is returned in rax. This does the right thing for
- result types except for floats; we have to 'mov xmm0, rax' in the
- caller to correct this.
- */
- if (rtype == FFI_TYPE_STRUCT)
- return resp;
- return *(void **)resp;
-#endif
-}
-
-/*@-exportheader@*/
-static void
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
- void **avalue, ffi_cif *cif)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
- argp = stack;
-
- if ( cif->flags == FFI_TYPE_STRUCT ) {
- *rvalue = *(void **) argp;
- argp += 4;
- }
-
- p_argv = avalue;
-
- for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if ((sizeof(char *) - 1) & (size_t) argp) {
- argp = (char *) ALIGN(argp, sizeof(char*));
- }
-
- z = (*p_arg)->size;
-
- /* because we're little endian, this is what it turns into. */
-
-#ifdef _WIN64
- if (z != 1 && z != 2 && z != 4 && z != 8)
- {
- /* On Win64, if a single argument takes more than 8 bytes,
- then it is always passed by reference. */
- *p_argv = *((void**) argp);
- z = 8;
- }
- else
-#endif
- *p_argv = (void*) argp;
-
- p_argv++;
- argp += z;
- }
-
- return;
-}
-
-/* the cif must already be prep'ed */
-extern void ffi_closure_OUTER();
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data,
- void *codeloc)
-{
- short bytes;
- char *tramp;
-#ifdef _WIN64
- int mask = 0;
-#endif
- FFI_ASSERT (cif->abi == FFI_SYSV);
-
- if (cif->abi == FFI_SYSV)
- bytes = 0;
-#if !defined(_WIN64)
- else if (cif->abi == FFI_STDCALL)
- bytes = cif->bytes;
-#endif
- else
- return FFI_BAD_ABI;
-
- tramp = &closure->tramp[0];
-
-#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
-#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
-#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
-#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
-
-#ifdef _WIN64
- if (cif->nargs >= 1 &&
- (cif->arg_types[0]->type == FFI_TYPE_FLOAT
- || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
- mask |= 1;
- if (cif->nargs >= 2 &&
- (cif->arg_types[1]->type == FFI_TYPE_FLOAT
- || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
- mask |= 2;
- if (cif->nargs >= 3 &&
- (cif->arg_types[2]->type == FFI_TYPE_FLOAT
- || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
- mask |= 4;
- if (cif->nargs >= 4 &&
- (cif->arg_types[3]->type == FFI_TYPE_FLOAT
- || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
- mask |= 8;
-
- /* if we return a non-small struct, then the first argument is a pointer
- * to the return area, and all real arguments are shifted by one */
- if (cif->flags == FFI_TYPE_STRUCT)
- mask = (mask & ~8) << 1;
-
- /* 41 BB ---- mov r11d,mask */
- BYTES("\x41\xBB"); INT(mask);
-
- /* 48 B8 -------- mov rax, closure */
- BYTES("\x48\xB8"); POINTER(closure);
-
- /* 49 BA -------- mov r10, ffi_closure_OUTER */
- BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
-
- /* 41 FF E2 jmp r10 */
- BYTES("\x41\xFF\xE2");
-
-#else
-
- /* mov ecx, closure */
- BYTES("\xb9"); POINTER(closure);
-
- /* mov edx, esp */
- BYTES("\x8b\xd4");
-
- /* call ffi_closure_SYSV */
- BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
-
- /* ret bytes */
- BYTES("\xc2");
- SHORT(bytes);
-
-#endif
-
- if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
- Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
-
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
- return FFI_OK;
-}
diff --git a/c/libffi_x86_x64/ffi.h b/c/libffi_x86_x64/ffi.h
deleted file mode 100644
index 97cdb59..0000000
--- a/c/libffi_x86_x64/ffi.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------
- The basic API is described in the README file.
-
- The raw API is designed to bypass some of the argument packing
- and unpacking on architectures for which it can be avoided.
-
- The closure API allows interpreted functions to be packaged up
- inside a C function pointer, so that they can be called as C functions,
- with no understanding on the client side that they are interpreted.
- It can also be used in other cases in which it is necessary to package
- up a user specified parameter and a function pointer as a single
- function pointer.
-
- The closure API must be implemented in order to get its functionality,
- e.g. for use by gij. Routines are provided to emulate the raw API
- if the underlying platform doesn't allow faster implementation.
-
- More details on the raw and cloure API can be found in:
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-
- and
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
- -------------------------------------------------------------------- */
-
-#ifndef LIBFFI_H
-#define LIBFFI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Specify which architecture libffi is configured for. */
-//XXX #define X86
-
-/* ---- System configuration information --------------------------------- */
-
-#include <ffitarget.h>
-
-#ifndef LIBFFI_ASM
-
-#include <stddef.h>
-#include <limits.h>
-
-/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
- But we can find it either under the correct ANSI name, or under GNU
- C's internal name. */
-#ifdef LONG_LONG_MAX
-# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-#else
-# ifdef LLONG_MAX
-# define FFI_LONG_LONG_MAX LLONG_MAX
-# else
-# ifdef __GNUC__
-# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-# endif
-# ifdef _MSC_VER
-# define FFI_LONG_LONG_MAX _I64_MAX
-# endif
-# endif
-#endif
-
-#if SCHAR_MAX == 127
-# define ffi_type_uchar ffi_type_uint8
-# define ffi_type_schar ffi_type_sint8
-#else
- #error "char size not supported"
-#endif
-
-#if SHRT_MAX == 32767
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-#elif SHRT_MAX == 2147483647
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-#else
- #error "short size not supported"
-#endif
-
-#if INT_MAX == 32767
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-#elif INT_MAX == 2147483647
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-#elif INT_MAX == 9223372036854775807
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-#else
- #error "int size not supported"
-#endif
-
-#define ffi_type_ulong ffi_type_uint64
-#define ffi_type_slong ffi_type_sint64
-#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != 9223372036854775807
- #error "no 64-bit data type supported"
-# endif
-#elif LONG_MAX != 9223372036854775807
- #error "long size not supported"
-#endif
-
-/* The closure code assumes that this works on pointers, i.e. a size_t */
-/* can hold a pointer. */
-
-typedef struct _ffi_type
-{
- size_t size;
- unsigned short alignment;
- unsigned short type;
- /*@null@*/ struct _ffi_type **elements;
-} ffi_type;
-
-/* These are defined in types.c */
-extern ffi_type ffi_type_void;
-extern ffi_type ffi_type_uint8;
-extern ffi_type ffi_type_sint8;
-extern ffi_type ffi_type_uint16;
-extern ffi_type ffi_type_sint16;
-extern ffi_type ffi_type_uint32;
-extern ffi_type ffi_type_sint32;
-extern ffi_type ffi_type_uint64;
-extern ffi_type ffi_type_sint64;
-extern ffi_type ffi_type_float;
-extern ffi_type ffi_type_double;
-extern ffi_type ffi_type_longdouble;
-extern ffi_type ffi_type_pointer;
-
-
-typedef enum {
- FFI_OK = 0,
- FFI_BAD_TYPEDEF,
- FFI_BAD_ABI
-} ffi_status;
-
-typedef unsigned FFI_TYPE;
-
-typedef struct {
- ffi_abi abi;
- unsigned nargs;
- /*@dependent@*/ ffi_type **arg_types;
- /*@dependent@*/ ffi_type *rtype;
- unsigned bytes;
- unsigned flags;
-#ifdef FFI_EXTRA_CIF_FIELDS
- FFI_EXTRA_CIF_FIELDS;
-#endif
-} ffi_cif;
-
-/* ---- Definitions for the raw API -------------------------------------- */
-
-#ifdef _WIN64
-#define FFI_SIZEOF_ARG 8
-#else
-#define FFI_SIZEOF_ARG 4
-#endif
-
-typedef union {
- ffi_sarg sint;
- ffi_arg uint;
- float flt;
- char data[FFI_SIZEOF_ARG];
- void* ptr;
-} ffi_raw;
-
-void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_raw_size (ffi_cif *cif);
-
-/* This is analogous to the raw API, except it uses Java parameter */
-/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-/* longs and doubles are followed by an empty 64-bit word. */
-
-void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_java_raw_size (ffi_cif *cif);
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#if FFI_CLOSURES
-
-typedef struct {
- char tramp[FFI_TRAMPOLINE_SIZE];
- ffi_cif *cif;
- void (*fun)(ffi_cif*,void*,void**,void*);
- void *user_data;
-} ffi_closure;
-
-void ffi_closure_free(void *);
-void *ffi_closure_alloc (size_t size, void **code);
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure*,
- ffi_cif *,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data,
- void *codeloc);
-
-/* AR: for cffi we need the following API, and not the _loc version */
-#define ffi_prep_closure(a,b,c,d) ffi_prep_closure_loc(a,b,c,d,a)
-
-typedef struct {
- char tramp[FFI_TRAMPOLINE_SIZE];
-
- ffi_cif *cif;
-
-#if !FFI_NATIVE_RAW_API
-
- /* if this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
- handler to do the transaltion, void** -> ffi_raw*. */
-
- void (*translate_args)(ffi_cif*,void*,void**,void*);
- void *this_closure;
-
-#endif
-
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
- void *user_data;
-
-} ffi_raw_closure;
-
-ffi_status
-ffi_prep_raw_closure (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data);
-
-ffi_status
-ffi_prep_java_raw_closure (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data);
-
-#endif /* FFI_CLOSURES */
-
-/* ---- Public interface definition -------------------------------------- */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
- ffi_abi abi,
- unsigned int nargs,
- /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
- /*@dependent@*/ ffi_type **atypes);
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ void **avalue);
-
-/* Useful for eliminating compiler warnings */
-#define FFI_FN(f) ((void (*)())f)
-
-/* ---- Definitions shared with assembly code ---------------------------- */
-
-#endif
-
-/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID 0
-#define FFI_TYPE_INT 1
-#define FFI_TYPE_FLOAT 2
-#define FFI_TYPE_DOUBLE 3
-#if 1
-#define FFI_TYPE_LONGDOUBLE 4
-#else
-#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-#endif
-#define FFI_TYPE_UINT8 5
-#define FFI_TYPE_SINT8 6
-#define FFI_TYPE_UINT16 7
-#define FFI_TYPE_SINT16 8
-#define FFI_TYPE_UINT32 9
-#define FFI_TYPE_SINT32 10
-#define FFI_TYPE_UINT64 11
-#define FFI_TYPE_SINT64 12
-#define FFI_TYPE_STRUCT 13
-#define FFI_TYPE_POINTER 14
-
-/* This should always refer to the last type code (for sanity checks) */
-#define FFI_TYPE_LAST FFI_TYPE_POINTER
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/c/libffi_x86_x64/ffi_common.h b/c/libffi_x86_x64/ffi_common.h
deleted file mode 100644
index 43fb83b..0000000
--- a/c/libffi_x86_x64/ffi_common.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
-
- Common internal definitions and macros. Only necessary for building
- libffi.
- ----------------------------------------------------------------------- */
-
-#ifndef FFI_COMMON_H
-#define FFI_COMMON_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <fficonfig.h>
-#include <malloc.h>
-
-/* Check for the existence of memcpy. */
-#if STDC_HEADERS
-# include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-# define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-#if defined(FFI_DEBUG)
-#include <stdio.h>
-#endif
-
-#ifdef FFI_DEBUG
-/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
-void ffi_stop_here(void);
-void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
-
-#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
-#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
-#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
-#else
-#define FFI_ASSERT(x)
-#define FFI_ASSERT_AT(x, f, l)
-#define FFI_ASSERT_VALID_TYPE(x)
-#endif
-
-#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
-
-/* Extended cif, used in callback from assembly routine */
-typedef struct
-{
- /*@dependent@*/ ffi_cif *cif;
- /*@dependent@*/ void *rvalue;
- /*@dependent@*/ void **avalue;
-} extended_cif;
-
-/* Terse sized type definitions. */
-typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
-typedef signed int SINT8 __attribute__((__mode__(__QI__)));
-typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
-typedef signed int SINT16 __attribute__((__mode__(__HI__)));
-typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
-typedef signed int SINT32 __attribute__((__mode__(__SI__)));
-typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
-typedef signed int SINT64 __attribute__((__mode__(__DI__)));
-
-typedef float FLOAT32;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
diff --git a/c/libffi_x86_x64/fficonfig.h b/c/libffi_x86_x64/fficonfig.h
deleted file mode 100644
index c14f653..0000000
--- a/c/libffi_x86_x64/fficonfig.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
-
-/* fficonfig.h. Generated automatically by configure. */
-/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define this for MSVC, but not for mingw32! */
-#ifdef _MSC_VER
-#define __attribute__(x) /* */
-#endif
-#define alloca _alloca
-
-/*----------------------------------------------------------------*/
-
-/* Define if using alloca.c. */
-/* #undef C_ALLOCA */
-
-/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
- This function is required for alloca.c support on those systems. */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define if you have alloca, as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-/* #define HAVE_ALLOCA_H 1 */
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown
- */
-/* #undef STACK_DIRECTION */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you have the memcpy function. */
-#define HAVE_MEMCPY 1
-
-/* Define if read-only mmap of a plain file works. */
-//#define HAVE_MMAP_FILE 1
-
-/* Define if mmap of /dev/zero works. */
-//#define HAVE_MMAP_DEV_ZERO 1
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-//#define HAVE_MMAP_ANON 1
-
-/* The number of bytes in type double */
-#define SIZEOF_DOUBLE 8
-
-/* The number of bytes in type long double */
-#define SIZEOF_LONG_DOUBLE 12
-
-/* Define if you have the long double type and it is bigger than a double */
-#define HAVE_LONG_DOUBLE 1
-
-/* whether byteorder is bigendian */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define if the host machine stores words of multi-word integers in
- big-endian order. */
-/* #undef HOST_WORDS_BIG_ENDIAN */
-
-/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
-#define BYTEORDER 1234
-
-/* Define if your assembler and linker support unaligned PC relative relocs. */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Define this is you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
-
-/* Define this is you do not want support for the raw API. */
-/* #undef FFI_NO_RAW_API */
-
-/* Define this if you are using Purify and want to suppress spurious messages. */
-/* #undef USING_PURIFY */
-
diff --git a/c/libffi_x86_x64/ffitarget.h b/c/libffi_x86_x64/ffitarget.h
deleted file mode 100644
index 85f5ee8..0000000
--- a/c/libffi_x86_x64/ffitarget.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
- Target configuration macros for x86 and x86-64.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-/* ---- System specific configurations ----------------------------------- */
-
-#if defined (X86_64) && defined (__i386__)
-#undef X86_64
-#define X86
-#endif
-
-/* ---- Generic type definitions ----------------------------------------- */
-
-#ifndef LIBFFI_ASM
-#ifndef _WIN64
-typedef unsigned long ffi_arg;
-#else
-typedef unsigned __int64 ffi_arg;
-#endif
-typedef signed long ffi_sarg;
-
-typedef enum ffi_abi {
- FFI_FIRST_ABI = 0,
-
- /* ---- Intel x86 Win32 ---------- */
- FFI_SYSV,
-#ifndef _WIN64
- FFI_STDCALL,
-#endif
- /* TODO: Add fastcall support for the sake of completeness */
- FFI_DEFAULT_ABI = FFI_SYSV,
-
- /* ---- Intel x86 and AMD x86-64 - */
-/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
-/* FFI_SYSV, */
-/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */
-/* #ifdef __i386__ */
-/* FFI_DEFAULT_ABI = FFI_SYSV, */
-/* #else */
-/* FFI_DEFAULT_ABI = FFI_UNIX64, */
-/* #endif */
-/* #endif */
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
-} ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-
-#ifdef _WIN64
-#define FFI_TRAMPOLINE_SIZE 29
-#define FFI_NATIVE_RAW_API 0
-#else
-#define FFI_TRAMPOLINE_SIZE 15
-#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
-#endif
-
-#endif
-
diff --git a/c/libffi_x86_x64/prep_cif.c b/c/libffi_x86_x64/prep_cif.c
deleted file mode 100644
index df94a98..0000000
--- a/c/libffi_x86_x64/prep_cif.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-#include <stdlib.h>
-
-
-/* Round up to FFI_SIZEOF_ARG. */
-
-#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
-
-/* Perform machine independent initialization of aggregate type
- specifications. */
-
-static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
-{
- ffi_type **ptr;
-
- FFI_ASSERT(arg != NULL);
-
- /*@-usedef@*/
-
- FFI_ASSERT(arg->elements != NULL);
- FFI_ASSERT(arg->size == 0);
- FFI_ASSERT(arg->alignment == 0);
-
- ptr = &(arg->elements[0]);
-
- while ((*ptr) != NULL)
- {
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
- /* Perform a sanity check on the argument type */
- FFI_ASSERT_VALID_TYPE(*ptr);
-
- arg->size = ALIGN(arg->size, (*ptr)->alignment);
- arg->size += (*ptr)->size;
-
- arg->alignment = (arg->alignment > (*ptr)->alignment) ?
- arg->alignment : (*ptr)->alignment;
-
- ptr++;
- }
-
- /* Structure size includes tail padding. This is important for
- structures that fit in one register on ABIs like the PowerPC64
- Linux ABI that right justify small structs in a register.
- It's also needed for nested structure layout, for example
- struct A { long a; char b; }; struct B { struct A x; char y; };
- should find y at an offset of 2*sizeof(long) and result in a
- total size of 3*sizeof(long). */
- arg->size = ALIGN (arg->size, arg->alignment);
-
- if (arg->size == 0)
- return FFI_BAD_TYPEDEF;
- else
- return FFI_OK;
-
- /*@=usedef@*/
-}
-
-/* Perform machine independent ffi_cif preparation, then call
- machine dependent routine. */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
- ffi_abi abi, unsigned int nargs,
- /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
- /*@dependent@*/ ffi_type **atypes)
-{
- unsigned bytes = 0;
- unsigned int i;
- ffi_type **ptr;
-
- FFI_ASSERT(cif != NULL);
- FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
-
- cif->abi = abi;
- cif->arg_types = atypes;
- cif->nargs = nargs;
- cif->rtype = rtype;
-
- cif->flags = 0;
-
- /* Initialize the return type if necessary */
- /*@-usedef@*/
- if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
- return FFI_BAD_TYPEDEF;
- /*@=usedef@*/
-
- /* Perform a sanity check on the return type */
- FFI_ASSERT_VALID_TYPE(cif->rtype);
-
- /* x86-64 and s390 stack space allocation is handled in prep_machdep. */
-#if !defined M68K && !defined __x86_64__ && !defined S390
- /* Make space for the return structure pointer */
- if (cif->rtype->type == FFI_TYPE_STRUCT
-#ifdef _WIN32
- && (cif->rtype->size != 1) /* MSVC returns small structs in registers */
- && (cif->rtype->size != 2)
- && (cif->rtype->size != 4)
- && (cif->rtype->size != 8)
-#endif
-#ifdef SPARC
- && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-#endif
- )
- bytes = STACK_ARG_SIZE(sizeof(void*));
-#endif
-
- for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
- {
-
- /* Initialize any uninitialized aggregate type definitions */
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
- /* Perform a sanity check on the argument type, do this
- check after the initialization. */
- FFI_ASSERT_VALID_TYPE(*ptr);
-
-#if !defined __x86_64__ && !defined S390
-#ifdef SPARC
- if (((*ptr)->type == FFI_TYPE_STRUCT
- && ((*ptr)->size > 16 || cif->abi != FFI_V9))
- || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
- && cif->abi != FFI_V9))
- bytes += sizeof(void*);
- else
-#endif
- {
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
- /* Don't know if this is a libffi bug or not. At least on
- Windows with MSVC, function call parameters are *not*
- aligned in the same way as structure fields are, they are
- only aligned in integer boundaries.
-
- This doesn't do any harm for cdecl functions and closures,
- since the caller cleans up the stack, but it is wrong for
- stdcall functions where the callee cleans.
- */
-
- /* Add any padding if necessary */
- if (((*ptr)->alignment - 1) & bytes)
- bytes = ALIGN(bytes, (*ptr)->alignment);
-
-#endif
- bytes += STACK_ARG_SIZE((*ptr)->size);
- }
-#endif
- }
-
-#ifdef _WIN64
- /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
- if (bytes < 40)
- bytes = 40;
-#endif
-
- cif->bytes = bytes;
-
- /* Perform machine dependent cif processing */
- return ffi_prep_cif_machdep(cif);
-}
diff --git a/c/libffi_x86_x64/types.c b/c/libffi_x86_x64/types.c
deleted file mode 100644
index 4433ac2..0000000
--- a/c/libffi_x86_x64/types.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -----------------------------------------------------------------------
- types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
-
- Predefined ffi_types needed by libffi.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-/* Type definitions */
-
-#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
-#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
-
-/* Size and alignment are fake here. They must not be 0. */
-FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
-
-FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
-FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
-FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
-FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
-FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
-FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
-
-#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
- || defined IA64 || defined _WIN64
-
-FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
-
-#endif
-
-#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined SH
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
-
-#endif
-
-
-#if defined X86 || defined X86_WIN32 || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined SPARC
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-#ifdef SPARC64
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-#else
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
-#endif
-
-#elif defined X86_64
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
-
-#endif
-
diff --git a/c/libffi_x86_x64/win32.c b/c/libffi_x86_x64/win32.c
deleted file mode 100644
index d1149a8..0000000
--- a/c/libffi_x86_x64/win32.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -----------------------------------------------------------------------
- win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
- Copyright (c) 2001 John Beniton
- Copyright (c) 2002 Ranjit Mathew
-
-
- X86 Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-/* theller: almost verbatim translation from gas syntax to MSVC inline
- assembler code. */
-
-/* theller: ffi_call_x86 now returns an integer - the difference of the stack
- pointer before and after the function call. If everything is ok, zero is
- returned. If stdcall functions are passed the wrong number of arguments,
- the difference will be nonzero. */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-__declspec(naked) int
-ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
- extended_cif *ecif, /* 12 */
- unsigned bytes, /* 16 */
- unsigned flags, /* 20 */
- unsigned *rvalue, /* 24 */
- void (*fn)()) /* 28 */
-{
- _asm {
- push ebp
- mov ebp, esp
-
- push esi // NEW: this register must be preserved across function calls
-// XXX SAVE ESP NOW!
- mov esi, esp // save stack pointer before the call
-
-// Make room for all of the new args.
- mov ecx, [ebp+16]
- sub esp, ecx // sub esp, bytes
-
- mov eax, esp
-
-// Place all of the ffi_prep_args in position
- push [ebp + 12] // ecif
- push eax
- call [ebp + 8] // prepfunc
-
-// Return stack to previous state and call the function
- add esp, 8
-// FIXME: Align the stack to a 128-bit boundary to avoid
-// potential performance hits.
- call [ebp + 28]
-
-// Load ecif->cif->abi
- mov ecx, [ebp + 12]
- mov ecx, [ecx]ecif.cif
- mov ecx, [ecx]ecif.cif.abi
-
- cmp ecx, FFI_STDCALL
- je noclean
-// STDCALL: Remove the space we pushed for the args
- mov ecx, [ebp + 16]
- add esp, ecx
-// CDECL: Caller has already cleaned the stack
-noclean:
-// Check that esp has the same value as before!
- sub esi, esp
-
-// Load %ecx with the return type code
- mov ecx, [ebp + 20]
-
-// If the return value pointer is NULL, assume no return value.
-/*
- Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
- otherwise only one BYTE will be compared (instead of a DWORD)!
- */
- cmp DWORD PTR [ebp + 24], 0
- jne sc_retint
-
-// Even if there is no space for the return value, we are
-// obliged to handle floating-point values.
- cmp ecx, FFI_TYPE_FLOAT
- jne sc_noretval
-// fstp %st(0)
- fstp st(0)
-
- jmp sc_epilogue
-
-sc_retint:
- cmp ecx, FFI_TYPE_INT
- jne sc_retfloat
-// # Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp + 24]
- mov [ecx + 0], eax
- jmp sc_epilogue
-
-sc_retfloat:
- cmp ecx, FFI_TYPE_FLOAT
- jne sc_retdouble
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
-// fstps (%ecx)
- fstp DWORD PTR [ecx]
- jmp sc_epilogue
-
-sc_retdouble:
- cmp ecx, FFI_TYPE_DOUBLE
- jne sc_retlongdouble
-// movl 24(%ebp),%ecx
- mov ecx, [ebp+24]
- fstp QWORD PTR [ecx]
- jmp sc_epilogue
-
- jmp sc_retlongdouble // avoid warning about unused label
-sc_retlongdouble:
- cmp ecx, FFI_TYPE_LONGDOUBLE
- jne sc_retint64
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
-// fstpt (%ecx)
- fstp QWORD PTR [ecx] /* XXX ??? */
- jmp sc_epilogue
-
-sc_retint64:
- cmp ecx, FFI_TYPE_SINT64
- jne sc_retstruct
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
- mov [ecx+0], eax
- mov [ecx+4], edx
-
-sc_retstruct:
-// Nothing to do!
-
-sc_noretval:
-sc_epilogue:
- mov eax, esi
- pop esi // NEW restore: must be preserved across function calls
- mov esp, ebp
- pop ebp
- ret
- }
-}
diff --git a/c/libffi_x86_x64/win64.asm b/c/libffi_x86_x64/win64.asm
deleted file mode 100644
index 301188b..0000000
--- a/c/libffi_x86_x64/win64.asm
+++ /dev/null
@@ -1,156 +0,0 @@
-PUBLIC ffi_call_AMD64
-
-EXTRN __chkstk:NEAR
-EXTRN ffi_closure_SYSV:NEAR
-
-_TEXT SEGMENT
-
-;;; ffi_closure_OUTER will be called with these registers set:
-;;; rax points to 'closure'
-;;; r11 contains a bit mask that specifies which of the
-;;; first four parameters are float or double
-;;;
-;;; It must move the parameters passed in registers to their stack location,
-;;; call ffi_closure_SYSV for the actual work, then return the result.
-;;;
-ffi_closure_OUTER PROC FRAME
- ;; save actual arguments to their stack space.
- test r11, 1
- jne first_is_float
- mov QWORD PTR [rsp+8], rcx
- jmp second
-first_is_float:
- movlpd QWORD PTR [rsp+8], xmm0
-
-second:
- test r11, 2
- jne second_is_float
- mov QWORD PTR [rsp+16], rdx
- jmp third
-second_is_float:
- movlpd QWORD PTR [rsp+16], xmm1
-
-third:
- test r11, 4
- jne third_is_float
- mov QWORD PTR [rsp+24], r8
- jmp forth
-third_is_float:
- movlpd QWORD PTR [rsp+24], xmm2
-
-forth:
- test r11, 8
- jne forth_is_float
- mov QWORD PTR [rsp+32], r9
- jmp done
-forth_is_float:
- movlpd QWORD PTR [rsp+32], xmm3
-
-done:
-.ALLOCSTACK 40
- sub rsp, 40
-.ENDPROLOG
- mov rcx, rax ; context is first parameter
- mov rdx, rsp ; stack is second parameter
- add rdx, 40 ; correct our own area
- mov rax, ffi_closure_SYSV
- call rax ; call the real closure function
- ;; Here, code is missing that handles float return values
- add rsp, 40
- movd xmm0, rax ; In case the closure returned a float.
- ret 0
-ffi_closure_OUTER ENDP
-
-
-;;; ffi_call_AMD64
-
-stack$ = 0
-prepfunc$ = 32
-ecif$ = 40
-bytes$ = 48
-flags$ = 56
-rvalue$ = 64
-fn$ = 72
-
-ffi_call_AMD64 PROC FRAME
-
- mov QWORD PTR [rsp+32], r9
- mov QWORD PTR [rsp+24], r8
- mov QWORD PTR [rsp+16], rdx
- mov QWORD PTR [rsp+8], rcx
-.PUSHREG rbp
- push rbp
-.ALLOCSTACK 48
- sub rsp, 48 ; 00000030H
-.SETFRAME rbp, 32
- lea rbp, QWORD PTR [rsp+32]
-.ENDPROLOG
-
- mov eax, DWORD PTR bytes$[rbp]
- add rax, 15
- and rax, -16
- call __chkstk
- sub rsp, rax
- lea rax, QWORD PTR [rsp+32]
- mov QWORD PTR stack$[rbp], rax
-
- mov rdx, QWORD PTR ecif$[rbp]
- mov rcx, QWORD PTR stack$[rbp]
- call QWORD PTR prepfunc$[rbp]
-
- mov rsp, QWORD PTR stack$[rbp]
-
- movlpd xmm3, QWORD PTR [rsp+24]
- movd r9, xmm3
-
- movlpd xmm2, QWORD PTR [rsp+16]
- movd r8, xmm2
-
- movlpd xmm1, QWORD PTR [rsp+8]
- movd rdx, xmm1
-
- movlpd xmm0, QWORD PTR [rsp]
- movd rcx, xmm0
-
- call QWORD PTR fn$[rbp]
-ret_int$:
- cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
- jne ret_float$
-
- mov rcx, QWORD PTR rvalue$[rbp]
- mov DWORD PTR [rcx], eax
- jmp SHORT ret_nothing$
-
-ret_float$:
- cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
- jne SHORT ret_double$
-
- mov rax, QWORD PTR rvalue$[rbp]
- movlpd QWORD PTR [rax], xmm0
- jmp SHORT ret_nothing$
-
-ret_double$:
- cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
- jne SHORT ret_int64$
-
- mov rax, QWORD PTR rvalue$[rbp]
- movlpd QWORD PTR [rax], xmm0
- jmp SHORT ret_nothing$
-
-ret_int64$:
- cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
- jne ret_nothing$
-
- mov rcx, QWORD PTR rvalue$[rbp]
- mov QWORD PTR [rcx], rax
- jmp SHORT ret_nothing$
-
-ret_nothing$:
- xor eax, eax
-
- lea rsp, QWORD PTR [rbp+16]
- pop rbp
- ret 0
-ffi_call_AMD64 ENDP
-_TEXT ENDS
-END
diff --git a/c/libffi_x86_x64/win64.obj b/c/libffi_x86_x64/win64.obj
deleted file mode 100644
index 38d3cd1..0000000
--- a/c/libffi_x86_x64/win64.obj
+++ /dev/null
Binary files differ
diff --git a/c/malloc_closure.h b/c/malloc_closure.h
deleted file mode 100644
index bebb93d..0000000
--- a/c/malloc_closure.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * This file is from CPython's Modules/_ctypes/malloc_closure.c
- * and has received some edits.
- */
-
-#include <ffi.h>
-#ifdef MS_WIN32
-#include <windows.h>
-#else
-#include <sys/mman.h>
-#include <unistd.h>
-# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-# define MAP_ANONYMOUS MAP_ANON
-# endif
-#endif
-
-/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
-
- This is, apparently, an undocumented change to ffi_prep_closure():
- depending on the Linux kernel we're running on, we must give it a
- mmap that is either PROT_READ|PROT_WRITE|PROT_EXEC or only
- PROT_READ|PROT_WRITE. In the latter case, just trying to obtain a
- mmap with PROT_READ|PROT_WRITE|PROT_EXEC would kill our process(!),
- but in that situation libffi is fine with only PROT_READ|PROT_WRITE.
- There is nothing in the libffi API to know that, though, so we have
- to guess by parsing /proc/self/status. "Meh."
- */
-#ifdef __linux__
-#include <stdlib.h>
-
-static int emutramp_enabled = -1;
-
-static int
-emutramp_enabled_check (void)
-{
- char *buf = NULL;
- size_t len = 0;
- FILE *f;
- int ret;
- f = fopen ("/proc/self/status", "r");
- if (f == NULL)
- return 0;
- ret = 0;
-
- while (getline (&buf, &len, f) != -1)
- if (!strncmp (buf, "PaX:", 4))
- {
- char emutramp;
- if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
- ret = (emutramp == 'E');
- break;
- }
- free (buf);
- fclose (f);
- return ret;
-}
-
-#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
- : (emutramp_enabled = emutramp_enabled_check ()))
-#else
-#define is_emutramp_enabled() 0
-#endif
-
-
-/* 'allocate_num_pages' is dynamically adjusted starting from one
- page. It grows by a factor of PAGE_ALLOCATION_GROWTH_RATE. This is
- meant to handle both the common case of not needing a lot of pages,
- and the rare case of needing many of them. Systems in general have a
- limit of how many mmap'd blocks can be open.
-*/
-
-#define PAGE_ALLOCATION_GROWTH_RATE 1.3
-
-static Py_ssize_t allocate_num_pages = 0;
-
-/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */
-
-/******************************************************************/
-
-union mmaped_block {
- ffi_closure closure;
- union mmaped_block *next;
-};
-
-static union mmaped_block *free_list = 0;
-static Py_ssize_t _pagesize = 0;
-
-static void more_core(void)
-{
- union mmaped_block *item;
- Py_ssize_t count, i;
-
-/* determine the pagesize */
-#ifdef MS_WIN32
- if (!_pagesize) {
- SYSTEM_INFO systeminfo;
- GetSystemInfo(&systeminfo);
- _pagesize = systeminfo.dwPageSize;
- }
-#else
- if (!_pagesize) {
-#ifdef _SC_PAGESIZE
- _pagesize = sysconf(_SC_PAGESIZE);
-#else
- _pagesize = getpagesize();
-#endif
- }
-#endif
- if (_pagesize <= 0)
- _pagesize = 4096;
-
- /* bump 'allocate_num_pages' */
- allocate_num_pages = 1 + (
- (Py_ssize_t)(allocate_num_pages * PAGE_ALLOCATION_GROWTH_RATE));
-
- /* calculate the number of mmaped_blocks to allocate */
- count = (allocate_num_pages * _pagesize) / sizeof(union mmaped_block);
-
- /* allocate a memory block */
-#ifdef MS_WIN32
- item = (union mmaped_block *)VirtualAlloc(NULL,
- count * sizeof(union mmaped_block),
- MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
- if (item == NULL)
- return;
-#else
- {
- int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
- if (is_emutramp_enabled ())
- prot &= ~PROT_EXEC;
- item = (union mmaped_block *)mmap(NULL,
- allocate_num_pages * _pagesize,
- prot,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1,
- 0);
- if (item == (void *)MAP_FAILED)
- return;
- }
-#endif
-
-#ifdef MALLOC_CLOSURE_DEBUG
- printf("block at %p allocated (%ld bytes), %ld mmaped_blocks\n",
- item, (long)(allocate_num_pages * _pagesize), (long)count);
-#endif
- /* put them into the free list */
- for (i = 0; i < count; ++i) {
- item->next = free_list;
- free_list = item;
- ++item;
- }
-}
-
-/******************************************************************/
-
-/* put the item back into the free list */
-static void cffi_closure_free(ffi_closure *p)
-{
- union mmaped_block *item = (union mmaped_block *)p;
- item->next = free_list;
- free_list = item;
-}
-
-/* return one item from the free list, allocating more if needed */
-static ffi_closure *cffi_closure_alloc(void)
-{
- union mmaped_block *item;
- if (!free_list)
- more_core();
- if (!free_list)
- return NULL;
- item = free_list;
- free_list = item->next;
- return &item->closure;
-}
diff --git a/c/minibuffer.h b/c/minibuffer.h
deleted file mode 100644
index f3f5ca1..0000000
--- a/c/minibuffer.h
+++ /dev/null
@@ -1,408 +0,0 @@
-
-/* Implementation of a C object with the 'buffer' or 'memoryview'
- * interface at C-level (as approriate for the version of Python we're
- * compiling for), but only a minimal but *consistent* part of the
- * 'buffer' interface at application level.
- */
-
-typedef struct {
- PyObject_HEAD
- char *mb_data;
- Py_ssize_t mb_size;
- PyObject *mb_keepalive;
- PyObject *mb_weakreflist; /* weakref support */
-} MiniBufferObj;
-
-static Py_ssize_t mb_length(MiniBufferObj *self)
-{
- return self->mb_size;
-}
-
-static PyObject *mb_item(MiniBufferObj *self, Py_ssize_t idx)
-{
- if (idx < 0 || idx >= self->mb_size ) {
- PyErr_SetString(PyExc_IndexError, "buffer index out of range");
- return NULL;
- }
- return PyBytes_FromStringAndSize(self->mb_data + idx, 1);
-}
-
-static PyObject *mb_slice(MiniBufferObj *self,
- Py_ssize_t left, Py_ssize_t right)
-{
- Py_ssize_t size = self->mb_size;
- if (left < 0) left = 0;
- if (right > size) right = size;
- if (left > right) left = right;
- return PyBytes_FromStringAndSize(self->mb_data + left, right - left);
-}
-
-static int mb_ass_item(MiniBufferObj *self, Py_ssize_t idx, PyObject *other)
-{
- if (idx < 0 || idx >= self->mb_size) {
- PyErr_SetString(PyExc_IndexError,
- "buffer assignment index out of range");
- return -1;
- }
- if (PyBytes_Check(other) && PyBytes_GET_SIZE(other) == 1) {
- self->mb_data[idx] = PyBytes_AS_STRING(other)[0];
- return 0;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "must assign a "STR_OR_BYTES
- " of length 1, not %.200s", Py_TYPE(other)->tp_name);
- return -1;
- }
-}
-
-/* forward: from _cffi_backend.c */
-static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only);
-
-static int mb_ass_slice(MiniBufferObj *self,
- Py_ssize_t left, Py_ssize_t right, PyObject *other)
-{
- Py_ssize_t count;
- Py_ssize_t size = self->mb_size;
- Py_buffer src_view;
-
- if (_fetch_as_buffer(other, &src_view, 0) < 0)
- return -1;
-
- if (left < 0) left = 0;
- if (right > size) right = size;
- if (left > right) left = right;
-
- count = right - left;
- if (count != src_view.len) {
- PyBuffer_Release(&src_view);
- PyErr_SetString(PyExc_ValueError,
- "right operand length must match slice length");
- return -1;
- }
- memcpy(self->mb_data + left, src_view.buf, count);
- PyBuffer_Release(&src_view);
- return 0;
-}
-
-#if PY_MAJOR_VERSION < 3
-static Py_ssize_t mb_getdata(MiniBufferObj *self, Py_ssize_t idx, void **pp)
-{
- *pp = self->mb_data;
- return self->mb_size;
-}
-
-static Py_ssize_t mb_getsegcount(MiniBufferObj *self, Py_ssize_t *lenp)
-{
- if (lenp)
- *lenp = self->mb_size;
- return 1;
-}
-
-static PyObject *mb_str(MiniBufferObj *self)
-{
- /* Python 2: we want str(buffer) to behave like buffer[:], because
- that's what bytes(buffer) does on Python 3 and there is no way
- we can prevent this. */
- return PyString_FromStringAndSize(self->mb_data, self->mb_size);
-}
-#endif
-
-static int mb_getbuf(MiniBufferObj *self, Py_buffer *view, int flags)
-{
- return PyBuffer_FillInfo(view, (PyObject *)self,
- self->mb_data, self->mb_size,
- /*readonly=*/0, flags);
-}
-
-static PySequenceMethods mb_as_sequence = {
- (lenfunc)mb_length, /*sq_length*/
- (binaryfunc)0, /*sq_concat*/
- (ssizeargfunc)0, /*sq_repeat*/
- (ssizeargfunc)mb_item, /*sq_item*/
- (ssizessizeargfunc)mb_slice, /*sq_slice*/
- (ssizeobjargproc)mb_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)mb_ass_slice, /*sq_ass_slice*/
-};
-
-static PyBufferProcs mb_as_buffer = {
-#if PY_MAJOR_VERSION < 3
- (readbufferproc)mb_getdata,
- (writebufferproc)mb_getdata,
- (segcountproc)mb_getsegcount,
- (charbufferproc)mb_getdata,
-#endif
- (getbufferproc)mb_getbuf,
- (releasebufferproc)0,
-};
-
-static void
-mb_dealloc(MiniBufferObj *ob)
-{
- PyObject_GC_UnTrack(ob);
- if (ob->mb_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *)ob);
- Py_XDECREF(ob->mb_keepalive);
- Py_TYPE(ob)->tp_free((PyObject *)ob);
-}
-
-static int
-mb_traverse(MiniBufferObj *ob, visitproc visit, void *arg)
-{
- Py_VISIT(ob->mb_keepalive);
- return 0;
-}
-
-static int
-mb_clear(MiniBufferObj *ob)
-{
- Py_CLEAR(ob->mb_keepalive);
- return 0;
-}
-
-static PyObject *
-mb_richcompare(PyObject *self, PyObject *other, int op)
-{
- Py_ssize_t self_size, other_size;
- Py_buffer self_bytes, other_bytes;
- PyObject *res;
- Py_ssize_t minsize;
- int cmp, rc;
-
- /* Bytes can be compared to anything that supports the (binary)
- buffer API. Except that a comparison with Unicode is always an
- error, even if the comparison is for equality. */
- rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type);
- if (!rc)
- rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type);
- if (rc < 0)
- return NULL;
- if (rc) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
- PyErr_Clear();
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-
- }
- self_size = self_bytes.len;
-
- if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
- PyErr_Clear();
- PyBuffer_Release(&self_bytes);
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-
- }
- other_size = other_bytes.len;
-
- if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
- /* Shortcut: if the lengths differ, the objects differ */
- cmp = (op == Py_NE);
- }
- else {
- minsize = self_size;
- if (other_size < minsize)
- minsize = other_size;
-
- cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);
- /* In ISO C, memcmp() guarantees to use unsigned bytes! */
-
- if (cmp == 0) {
- if (self_size < other_size)
- cmp = -1;
- else if (self_size > other_size)
- cmp = 1;
- }
-
- switch (op) {
- case Py_LT: cmp = cmp < 0; break;
- case Py_LE: cmp = cmp <= 0; break;
- case Py_EQ: cmp = cmp == 0; break;
- case Py_NE: cmp = cmp != 0; break;
- case Py_GT: cmp = cmp > 0; break;
- case Py_GE: cmp = cmp >= 0; break;
- }
- }
-
- res = cmp ? Py_True : Py_False;
- PyBuffer_Release(&self_bytes);
- PyBuffer_Release(&other_bytes);
- Py_INCREF(res);
- return res;
-}
-
-#if PY_MAJOR_VERSION >= 3
-/* pfffffffffffff pages of copy-paste from listobject.c */
-
-/* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not
- be called, because C extension modules compiled with it differ
- on ABI between 3.6.0, 3.6.1 and 3.6.2. */
-#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION)
-#undef PySlice_GetIndicesEx
-#endif
-
-static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i;
- i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += self->mb_size;
- return mb_item(self, i);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx(item, self->mb_size,
- &start, &stop, &step, &slicelength) < 0)
- return NULL;
-
- if (step == 1)
- return mb_slice(self, start, stop);
- else {
- PyErr_SetString(PyExc_TypeError,
- "buffer doesn't support slicing with step != 1");
- return NULL;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "buffer indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return NULL;
- }
-}
-static int
-mb_ass_subscript(MiniBufferObj* self, PyObject* item, PyObject* value)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0)
- i += self->mb_size;
- return mb_ass_item(self, i, value);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx(item, self->mb_size,
- &start, &stop, &step, &slicelength) < 0) {
- return -1;
- }
-
- if (step == 1)
- return mb_ass_slice(self, start, stop, value);
- else {
- PyErr_SetString(PyExc_TypeError,
- "buffer doesn't support slicing with step != 1");
- return -1;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "buffer indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return -1;
- }
-}
-
-static PyMappingMethods mb_as_mapping = {
- (lenfunc)mb_length, /*mp_length*/
- (binaryfunc)mb_subscript, /*mp_subscript*/
- (objobjargproc)mb_ass_subscript, /*mp_ass_subscript*/
-};
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-# define MINIBUF_TPFLAGS 0
-#else
-# define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER)
-#endif
-
-PyDoc_STRVAR(ffi_buffer_doc,
-"ffi.buffer(cdata[, byte_size]):\n"
-"Return a read-write buffer object that references the raw C data\n"
-"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n"
-"array. Can be passed to functions expecting a buffer, or directly\n"
-"manipulated with:\n"
-"\n"
-" buf[:] get a copy of it in a regular string, or\n"
-" buf[idx] as a single character\n"
-" buf[:] = ...\n"
-" buf[idx] = ... change the content");
-
-static PyObject * /* forward, implemented in _cffi_backend.c */
-b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-
-static PyTypeObject MiniBuffer_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.buffer",
- sizeof(MiniBufferObj),
- 0,
- (destructor)mb_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- &mb_as_sequence, /* tp_as_sequence */
-#if PY_MAJOR_VERSION < 3
- 0, /* tp_as_mapping */
-#else
- &mb_as_mapping, /* tp_as_mapping */
-#endif
- 0, /* tp_hash */
- 0, /* tp_call */
-#if PY_MAJOR_VERSION < 3
- (reprfunc)mb_str, /* tp_str */
-#else
- 0, /* tp_str */
-#endif
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &mb_as_buffer, /* tp_as_buffer */
- (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- MINIBUF_TPFLAGS), /* tp_flags */
- ffi_buffer_doc, /* tp_doc */
- (traverseproc)mb_traverse, /* tp_traverse */
- (inquiry)mb_clear, /* tp_clear */
- (richcmpfunc)mb_richcompare, /* tp_richcompare */
- offsetof(MiniBufferObj, mb_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- b_buffer_new, /* tp_new */
- 0, /* tp_free */
-};
-
-static PyObject *minibuffer_new(char *data, Py_ssize_t size,
- PyObject *keepalive)
-{
- MiniBufferObj *ob = PyObject_GC_New(MiniBufferObj, &MiniBuffer_Type);
- if (ob != NULL) {
- ob->mb_data = data;
- ob->mb_size = size;
- ob->mb_keepalive = keepalive; Py_INCREF(keepalive);
- ob->mb_weakreflist = NULL;
- PyObject_GC_Track(ob);
- }
- return (PyObject *)ob;
-}
diff --git a/c/misc_thread_common.h b/c/misc_thread_common.h
deleted file mode 100644
index 66e2835..0000000
--- a/c/misc_thread_common.h
+++ /dev/null
@@ -1,371 +0,0 @@
-#ifndef WITH_THREAD
-# error "xxx no-thread configuration not tested, please report if you need that"
-#endif
-#include "pythread.h"
-
-
-struct cffi_tls_s {
- /* The current thread's ThreadCanaryObj. This is only non-null in
- case cffi builds the thread state here. It remains null if this
- thread had already a thread state provided by CPython. */
- struct thread_canary_s *local_thread_canary;
-
-#ifndef USE__THREAD
- /* The saved errno. If the C compiler supports '__thread', then
- we use that instead. */
- int saved_errno;
-#endif
-
-#ifdef MS_WIN32
- /* The saved lasterror, on Windows. */
- int saved_lasterror;
-#endif
-};
-
-static struct cffi_tls_s *get_cffi_tls(void); /* in misc_thread_posix.h
- or misc_win32.h */
-
-
-/* We try to keep the PyThreadState around in a thread not started by
- * Python but where cffi callbacks occur. If we didn't do that, then
- * the standard logic in PyGILState_Ensure() and PyGILState_Release()
- * would create a new PyThreadState and completely free it for every
- * single call. For some applications, this is a huge slow-down.
- *
- * As shown by issue #362, it is quite messy to do. The current
- * solution is to keep the PyThreadState alive by incrementing its
- * 'gilstate_counter'. We detect thread shut-down, and we put the
- * PyThreadState inside a list of zombies (we can't free it
- * immediately because we don't have the GIL at that point in time).
- * We also detect other pieces of code (notably Py_Finalize()) which
- * clear and free PyThreadStates under our feet, using ThreadCanaryObj.
- */
-
-#define TLS_ZOM_LOCK() PyThread_acquire_lock(cffi_zombie_lock, WAIT_LOCK)
-#define TLS_ZOM_UNLOCK() PyThread_release_lock(cffi_zombie_lock)
-static PyThread_type_lock cffi_zombie_lock = NULL;
-
-
-/* A 'canary' object is created in a thread when there is a callback
- invoked, and that thread has no PyThreadState so far. It is an
- object of reference count equal to 1, which is stored in the
- PyThreadState->dict. Two things can occur then:
-
- 1. The PyThreadState can be forcefully cleared by Py_Finalize().
- Then thread_canary_dealloc() is called, and we have to cancel
- the hacks we did to keep the PyThreadState alive.
-
- 2. The thread finishes. In that case, we put the canary in a list
- of zombies, and at some convenient time later when we have the
- GIL, we free all PyThreadStates in the zombie list.
-
- Some more fun comes from the fact that thread_canary_dealloc() can
- be called at a point where the canary is in the zombie list already.
- Also, the various pieces are freed at specific points in time, and
- we must make sure not to access already-freed structures:
-
- - the struct cffi_tls_s is valid until the thread shuts down, and
- then it is freed by cffi_thread_shutdown().
-
- - the canary is a normal Python object, but we have a borrowed
- reference to it from cffi_tls_s.local_thread_canary.
- */
-
-typedef struct thread_canary_s {
- PyObject_HEAD
- struct thread_canary_s *zombie_prev, *zombie_next;
- PyThreadState *tstate;
- struct cffi_tls_s *tls;
-} ThreadCanaryObj;
-
-static PyTypeObject ThreadCanary_Type; /* forward */
-static ThreadCanaryObj cffi_zombie_head;
-
-static void
-_thread_canary_detach_with_lock(ThreadCanaryObj *ob)
-{
- /* must be called with both the GIL and TLS_ZOM_LOCK. */
- ThreadCanaryObj *p, *n;
- p = ob->zombie_prev;
- n = ob->zombie_next;
- p->zombie_next = n;
- n->zombie_prev = p;
- ob->zombie_prev = NULL;
- ob->zombie_next = NULL;
-}
-
-static void
-thread_canary_dealloc(ThreadCanaryObj *ob)
-{
- /* this ThreadCanaryObj is being freed: if it is in the zombie
- chained list, remove it. Thread-safety: 'zombie_next' amd
- 'local_thread_canary' accesses need to be protected with
- the TLS_ZOM_LOCK.
- */
- TLS_ZOM_LOCK();
- if (ob->zombie_next != NULL) {
- //fprintf(stderr, "thread_canary_dealloc(%p): ZOMBIE\n", ob);
- _thread_canary_detach_with_lock(ob);
- }
- else {
- //fprintf(stderr, "thread_canary_dealloc(%p): not a zombie\n", ob);
- }
-
- if (ob->tls != NULL) {
- //fprintf(stderr, "thread_canary_dealloc(%p): was local_thread_canary\n", ob);
- assert(ob->tls->local_thread_canary == ob);
- ob->tls->local_thread_canary = NULL;
- }
- TLS_ZOM_UNLOCK();
-
- PyObject_Del((PyObject *)ob);
-}
-
-static void
-thread_canary_make_zombie(ThreadCanaryObj *ob)
-{
- /* This must be called without the GIL, but with the TLS_ZOM_LOCK.
- It must be called at most once for a given ThreadCanaryObj. */
- ThreadCanaryObj *last;
-
- //fprintf(stderr, "thread_canary_make_zombie(%p)\n", ob);
- if (ob->zombie_next)
- Py_FatalError("cffi: ThreadCanaryObj is already a zombie");
- last = cffi_zombie_head.zombie_prev;
- ob->zombie_next = &cffi_zombie_head;
- ob->zombie_prev = last;
- last->zombie_next = ob;
- cffi_zombie_head.zombie_prev = ob;
-}
-
-static void
-thread_canary_free_zombies(void)
-{
- /* This must be called with the GIL. */
- if (cffi_zombie_head.zombie_next == &cffi_zombie_head)
- return; /* fast path */
-
- while (1) {
- ThreadCanaryObj *ob;
- PyThreadState *tstate = NULL;
-
- TLS_ZOM_LOCK();
- ob = cffi_zombie_head.zombie_next;
- if (ob != &cffi_zombie_head) {
- tstate = ob->tstate;
- //fprintf(stderr, "thread_canary_free_zombie(%p) tstate=%p\n", ob, tstate);
- _thread_canary_detach_with_lock(ob);
- if (tstate == NULL)
- Py_FatalError("cffi: invalid ThreadCanaryObj->tstate");
- }
- TLS_ZOM_UNLOCK();
-
- if (tstate == NULL)
- break;
- PyThreadState_Clear(tstate); /* calls thread_canary_dealloc on 'ob',
- but now ob->zombie_next == NULL. */
- PyThreadState_Delete(tstate);
- //fprintf(stderr, "thread_canary_free_zombie: cleared and deleted tstate=%p\n", tstate);
- }
- //fprintf(stderr, "thread_canary_free_zombie: end\n");
-}
-
-static void
-thread_canary_register(PyThreadState *tstate)
-{
- /* called with the GIL; 'tstate' is the current PyThreadState. */
- ThreadCanaryObj *canary;
- PyObject *tdict;
- struct cffi_tls_s *tls;
- int err;
-
- /* first free the zombies, if any */
- thread_canary_free_zombies();
-
- tls = get_cffi_tls();
- if (tls == NULL)
- goto ignore_error;
-
- tdict = PyThreadState_GetDict();
- if (tdict == NULL)
- goto ignore_error;
-
- canary = PyObject_New(ThreadCanaryObj, &ThreadCanary_Type);
- //fprintf(stderr, "thread_canary_register(%p): tstate=%p tls=%p\n", canary, tstate, tls);
- if (canary == NULL)
- goto ignore_error;
- canary->zombie_prev = NULL;
- canary->zombie_next = NULL;
- canary->tstate = tstate;
- canary->tls = tls;
-
- err = PyDict_SetItemString(tdict, "cffi.thread.canary", (PyObject *)canary);
- Py_DECREF(canary);
- if (err < 0)
- goto ignore_error;
-
- /* thread-safety: we have the GIL here, and 'tstate' is the one that
- corresponds to our own thread. We are allocating a new 'canary'
- and setting it up for our own thread, both in 'tdict' (which owns
- the reference) and in 'tls->local_thread_canary' (which doesn't). */
- assert(Py_REFCNT(canary) == 1);
- tls->local_thread_canary = canary;
- tstate->gilstate_counter++;
- /* ^^^ this means 'tstate' will never be automatically freed by
- PyGILState_Release() */
- return;
-
- ignore_error:
- PyErr_Clear();
-}
-
-static PyTypeObject ThreadCanary_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_cffi_backend.thread_canary",
- sizeof(ThreadCanaryObj),
- 0,
- (destructor)thread_canary_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
-};
-
-static void init_cffi_tls_zombie(void)
-{
- cffi_zombie_head.zombie_next = &cffi_zombie_head;
- cffi_zombie_head.zombie_prev = &cffi_zombie_head;
- cffi_zombie_lock = PyThread_allocate_lock();
- if (cffi_zombie_lock == NULL)
- PyErr_SetString(PyExc_SystemError, "can't allocate cffi_zombie_lock");
-}
-
-static void cffi_thread_shutdown(void *p)
-{
- /* this function is called from misc_thread_posix or misc_win32
- when a thread is about to end. */
- struct cffi_tls_s *tls = (struct cffi_tls_s *)p;
-
- /* thread-safety: this field 'local_thread_canary' can be reset
- to NULL in parallel, protected by TLS_ZOM_LOCK. */
- TLS_ZOM_LOCK();
- if (tls->local_thread_canary != NULL) {
- tls->local_thread_canary->tls = NULL;
- thread_canary_make_zombie(tls->local_thread_canary);
- }
- TLS_ZOM_UNLOCK();
- //fprintf(stderr, "thread_shutdown(%p)\n", tls);
- free(tls);
-}
-
-/* USE__THREAD is defined by setup.py if it finds that it is
- syntactically valid to use "__thread" with this C compiler. */
-#ifdef USE__THREAD
-
-static __thread int cffi_saved_errno = 0;
-static void save_errno_only(void) { cffi_saved_errno = errno; }
-static void restore_errno_only(void) { errno = cffi_saved_errno; }
-
-#else
-
-static void save_errno_only(void)
-{
- int saved = errno;
- struct cffi_tls_s *tls = get_cffi_tls();
- if (tls != NULL)
- tls->saved_errno = saved;
-}
-
-static void restore_errno_only(void)
-{
- struct cffi_tls_s *tls = get_cffi_tls();
- if (tls != NULL)
- errno = tls->saved_errno;
-}
-
-#endif
-
-
-/* MESS. We can't use PyThreadState_GET(), because that calls
- PyThreadState_Get() which fails an assert if the result is NULL.
-
- * in Python 2.7 and <= 3.4, the variable _PyThreadState_Current
- is directly available, so use that.
-
- * in Python 3.5, the variable is available too, but it might be
- the case that the headers don't define it (this changed in 3.5.1).
- In case we're compiling with 3.5.x with x >= 1, we need to
- manually define this variable.
-
- * in Python >= 3.6 there is _PyThreadState_UncheckedGet().
- It was added in 3.5.2 but should never be used in 3.5.x
- because it is not available in 3.5.0 or 3.5.1.
-*/
-#if PY_VERSION_HEX >= 0x03050100 && PY_VERSION_HEX < 0x03060000
-PyAPI_DATA(void *volatile) _PyThreadState_Current;
-#endif
-
-static PyThreadState *get_current_ts(void)
-{
-#if PY_VERSION_HEX >= 0x03060000
- return _PyThreadState_UncheckedGet();
-#elif defined(_Py_atomic_load_relaxed)
- return (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
-#else
- return (PyThreadState*)_PyThreadState_Current; /* assume atomic read */
-#endif
-}
-
-static PyGILState_STATE gil_ensure(void)
-{
- /* Called at the start of a callback. Replacement for
- PyGILState_Ensure().
- */
- PyGILState_STATE result;
- PyThreadState *ts = PyGILState_GetThisThreadState();
-
- if (ts != NULL) {
- ts->gilstate_counter++;
- if (ts != get_current_ts()) {
- /* common case: 'ts' is our non-current thread state and
- we have to make it current and acquire the GIL */
- PyEval_RestoreThread(ts);
- return PyGILState_UNLOCKED;
- }
- else {
- return PyGILState_LOCKED;
- }
- }
- else {
- /* no thread state here so far. */
- result = PyGILState_Ensure();
- assert(result == PyGILState_UNLOCKED);
-
- ts = PyGILState_GetThisThreadState();
- assert(ts != NULL);
- assert(ts == get_current_ts());
- assert(ts->gilstate_counter >= 1);
-
- /* Use the ThreadCanary mechanism to keep 'ts' alive until the
- thread really shuts down */
- thread_canary_register(ts);
-
- return result;
- }
-}
-
-static void gil_release(PyGILState_STATE oldstate)
-{
- PyGILState_Release(oldstate);
-}
diff --git a/c/misc_thread_posix.h b/c/misc_thread_posix.h
deleted file mode 100644
index bcc0177..0000000
--- a/c/misc_thread_posix.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- Logic for a better replacement of PyGILState_Ensure().
-
- This version is ready to handle the case of a non-Python-started
- thread in which we do a large number of calls to CFFI callbacks. If
- we were to rely on PyGILState_Ensure() for that, we would constantly
- be creating and destroying PyThreadStates---it is slow, and
- PyThreadState_Delete() will actually walk the list of all thread
- states, making it O(n). :-(
-
- This version only creates one PyThreadState object the first time we
- see a given thread, and keep it alive until the thread is really
- shut down, using a destructor on the tls key.
-*/
-
-#include <pthread.h>
-#include "misc_thread_common.h"
-
-
-static pthread_key_t cffi_tls_key;
-
-static void init_cffi_tls(void)
-{
- if (pthread_key_create(&cffi_tls_key, &cffi_thread_shutdown) != 0)
- PyErr_SetString(PyExc_OSError, "pthread_key_create() failed");
-}
-
-static struct cffi_tls_s *_make_cffi_tls(void)
-{
- void *p = calloc(1, sizeof(struct cffi_tls_s));
- if (p == NULL)
- return NULL;
- if (pthread_setspecific(cffi_tls_key, p) != 0) {
- free(p);
- return NULL;
- }
- return p;
-}
-
-static struct cffi_tls_s *get_cffi_tls(void)
-{
- void *p = pthread_getspecific(cffi_tls_key);
- if (p == NULL)
- p = _make_cffi_tls();
- return (struct cffi_tls_s *)p;
-}
-
-#define save_errno save_errno_only
-#define restore_errno restore_errno_only
diff --git a/c/misc_win32.h b/c/misc_win32.h
deleted file mode 100644
index 156cf5d..0000000
--- a/c/misc_win32.h
+++ /dev/null
@@ -1,242 +0,0 @@
-#include <malloc.h> /* for alloca() */
-
-
-/************************************************************/
-/* errno and GetLastError support */
-
-#include "misc_thread_common.h"
-
-static DWORD cffi_tls_index = TLS_OUT_OF_INDEXES;
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL,
- DWORD reason_for_call,
- LPVOID reserved)
-{
- LPVOID p;
-
- switch (reason_for_call) {
-
- case DLL_THREAD_DETACH:
- if (cffi_tls_index != TLS_OUT_OF_INDEXES) {
- p = TlsGetValue(cffi_tls_index);
- if (p != NULL) {
- TlsSetValue(cffi_tls_index, NULL);
- cffi_thread_shutdown(p);
- }
- }
- break;
-
- default:
- break;
- }
- return TRUE;
-}
-
-static void init_cffi_tls(void)
-{
- if (cffi_tls_index == TLS_OUT_OF_INDEXES) {
- cffi_tls_index = TlsAlloc();
- if (cffi_tls_index == TLS_OUT_OF_INDEXES)
- PyErr_SetString(PyExc_WindowsError, "TlsAlloc() failed");
- }
-}
-
-static struct cffi_tls_s *get_cffi_tls(void)
-{
- LPVOID p = TlsGetValue(cffi_tls_index);
-
- if (p == NULL) {
- p = malloc(sizeof(struct cffi_tls_s));
- if (p == NULL)
- return NULL;
- memset(p, 0, sizeof(struct cffi_tls_s));
- TlsSetValue(cffi_tls_index, p);
- }
- return (struct cffi_tls_s *)p;
-}
-
-#ifdef USE__THREAD
-# error "unexpected USE__THREAD on Windows"
-#endif
-
-static void save_errno(void)
-{
- int current_err = errno;
- int current_lasterr = GetLastError();
- struct cffi_tls_s *p = get_cffi_tls();
- if (p != NULL) {
- p->saved_errno = current_err;
- p->saved_lasterror = current_lasterr;
- }
- /* else: cannot report the error */
-}
-
-static void restore_errno(void)
-{
- struct cffi_tls_s *p = get_cffi_tls();
- if (p != NULL) {
- SetLastError(p->saved_lasterror);
- errno = p->saved_errno;
- }
- /* else: cannot report the error */
-}
-
-/************************************************************/
-
-
-#if PY_MAJOR_VERSION >= 3
-static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
-{
- int err = -1;
- int len;
- WCHAR *s_buf = NULL; /* Free via LocalFree */
- PyObject *v, *message;
- static char *keywords[] = {"code", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
- return NULL;
-
- if (err == -1) {
- struct cffi_tls_s *p = get_cffi_tls();
- if (p == NULL)
- return PyErr_NoMemory();
- err = p->saved_lasterror;
- }
-
- len = FormatMessageW(
- /* Error API error */
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, /* no message source */
- err,
- MAKELANGID(LANG_NEUTRAL,
- SUBLANG_DEFAULT), /* Default language */
- (LPWSTR) &s_buf,
- 0, /* size not used */
- NULL); /* no args */
- if (len==0) {
- /* Only seen this in out of mem situations */
- message = PyUnicode_FromFormat("Windows Error 0x%X", err);
- } else {
- /* remove trailing cr/lf and dots */
- while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
- s_buf[--len] = L'\0';
- message = PyUnicode_FromWideChar(s_buf, len);
- }
- if (message != NULL) {
- v = Py_BuildValue("(iO)", err, message);
- Py_DECREF(message);
- }
- else
- v = NULL;
- LocalFree(s_buf);
- return v;
-}
-#else
-static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
-{
- int err = -1;
- int len;
- char *s;
- char *s_buf = NULL; /* Free via LocalFree */
- char s_small_buf[40]; /* Room for "Windows Error 0xFFFFFFFFFFFFFFFF" */
- PyObject *v;
- static char *keywords[] = {"code", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
- return NULL;
-
- if (err == -1) {
- struct cffi_tls_s *p = get_cffi_tls();
- if (p == NULL)
- return PyErr_NoMemory();
- err = p->saved_lasterror;
- }
-
- len = FormatMessage(
- /* Error API error */
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, /* no message source */
- err,
- MAKELANGID(LANG_NEUTRAL,
- SUBLANG_DEFAULT), /* Default language */
- (LPTSTR) &s_buf,
- 0, /* size not used */
- NULL); /* no args */
- if (len==0) {
- /* Only seen this in out of mem situations */
- sprintf(s_small_buf, "Windows Error 0x%X", err);
- s = s_small_buf;
- } else {
- s = s_buf;
- /* remove trailing cr/lf and dots */
- while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
- s[--len] = '\0';
- }
- v = Py_BuildValue("(is)", err, s);
- LocalFree(s_buf);
- return v;
-}
-#endif
-
-
-/************************************************************/
-/* Emulate dlopen()&co. from the Windows API */
-
-#define RTLD_LAZY 0
-#define RTLD_NOW 0
-#define RTLD_GLOBAL 0
-#define RTLD_LOCAL 0
-
-static void *dlopen(const char *filename, int flag)
-{
- return (void *)LoadLibraryA(filename);
-}
-
-static void *dlopenW(const wchar_t *filename)
-{
- return (void *)LoadLibraryW(filename);
-}
-
-static void *dlsym(void *handle, const char *symbol)
-{
- void *address = GetProcAddress((HMODULE)handle, symbol);
-#ifndef MS_WIN64
- if (!address) {
- /* If 'symbol' is not found, then try '_symbol@N' for N in
- (0, 4, 8, 12, ..., 124). Unlike ctypes, we try to do that
- for any symbol, although in theory it should only be done
- for __stdcall functions.
- */
- int i;
- char *mangled_name = alloca(1 + strlen(symbol) + 1 + 3 + 1);
- if (!mangled_name)
- return NULL;
- for (i = 0; i < 32; i++) {
- sprintf(mangled_name, "_%s@%d", symbol, i * 4);
- address = GetProcAddress((HMODULE)handle, mangled_name);
- if (address)
- break;
- }
- }
-#endif
- return address;
-}
-
-static int dlclose(void *handle)
-{
- return FreeLibrary((HMODULE)handle) ? 0 : -1;
-}
-
-static const char *dlerror(void)
-{
- static char buf[32];
- DWORD dw = GetLastError();
- if (dw == 0)
- return NULL;
- sprintf(buf, "error 0x%x", (unsigned int)dw);
- return buf;
-}
diff --git a/c/parse_c_type.c b/c/parse_c_type.c
deleted file mode 100644
index 698ef64..0000000
--- a/c/parse_c_type.c
+++ /dev/null
@@ -1,847 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#define _CFFI_INTERNAL
-#include "../cffi/parse_c_type.h"
-
-
-enum token_e {
- TOK_STAR='*',
- TOK_OPEN_PAREN='(',
- TOK_CLOSE_PAREN=')',
- TOK_OPEN_BRACKET='[',
- TOK_CLOSE_BRACKET=']',
- TOK_COMMA=',',
-
- TOK_START=256,
- TOK_END,
- TOK_ERROR,
- TOK_IDENTIFIER,
- TOK_INTEGER,
- TOK_DOTDOTDOT,
-
- /* keywords */
- TOK__BOOL,
- TOK_CHAR,
- TOK__COMPLEX,
- TOK_CONST,
- TOK_DOUBLE,
- TOK_ENUM,
- TOK_FLOAT,
- //TOK__IMAGINARY,
- TOK_INT,
- TOK_LONG,
- TOK_SHORT,
- TOK_SIGNED,
- TOK_STRUCT,
- TOK_UNION,
- TOK_UNSIGNED,
- TOK_VOID,
- TOK_VOLATILE,
-
- TOK_CDECL,
- TOK_STDCALL,
-};
-
-typedef struct {
- struct _cffi_parse_info_s *info;
- const char *input, *p;
- size_t size; // the next token is at 'p' and of length 'size'
- enum token_e kind;
- _cffi_opcode_t *output;
- size_t output_index;
-} token_t;
-
-static int is_space(char x)
-{
- return (x == ' ' || x == '\f' || x == '\n' || x == '\r' ||
- x == '\t' || x == '\v');
-}
-
-static int is_ident_first(char x)
-{
- return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_' ||
- x == '$'); /* '$' in names is supported here, for the struct
- names invented by cparser */
-}
-
-static int is_digit(char x)
-{
- return ('0' <= x && x <= '9');
-}
-
-static int is_hex_digit(char x)
-{
- return (('0' <= x && x <= '9') ||
- ('A' <= x && x <= 'F') ||
- ('a' <= x && x <= 'f'));
-}
-
-static int is_ident_next(char x)
-{
- return (is_ident_first(x) || is_digit(x));
-}
-
-static char get_following_char(token_t *tok)
-{
- const char *p = tok->p + tok->size;
- if (tok->kind == TOK_ERROR)
- return 0;
- while (is_space(*p))
- p++;
- return *p;
-}
-
-static int number_of_commas(token_t *tok)
-{
- const char *p = tok->p;
- int result = 0;
- int nesting = 0;
- while (1) {
- switch (*p++) {
- case ',': result += !nesting; break;
- case '(': nesting++; break;
- case ')': if ((--nesting) < 0) return result; break;
- case 0: return result;
- default: break;
- }
- }
-}
-
-static void next_token(token_t *tok)
-{
- const char *p = tok->p + tok->size;
- if (tok->kind == TOK_ERROR)
- return;
- while (!is_ident_first(*p)) {
- if (is_space(*p)) {
- p++;
- }
- else if (is_digit(*p)) {
- tok->kind = TOK_INTEGER;
- tok->p = p;
- tok->size = 1;
- if (p[1] == 'x' || p[1] == 'X')
- tok->size = 2;
- while (is_hex_digit(p[tok->size]))
- tok->size++;
- return;
- }
- else if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
- tok->kind = TOK_DOTDOTDOT;
- tok->p = p;
- tok->size = 3;
- return;
- }
- else if (*p) {
- tok->kind = *p;
- tok->p = p;
- tok->size = 1;
- return;
- }
- else {
- tok->kind = TOK_END;
- tok->p = p;
- tok->size = 0;
- return;
- }
- }
- tok->kind = TOK_IDENTIFIER;
- tok->p = p;
- tok->size = 1;
- while (is_ident_next(p[tok->size]))
- tok->size++;
-
- switch (*p) {
- case '_':
- if (tok->size == 5 && !memcmp(p, "_Bool", 5)) tok->kind = TOK__BOOL;
- if (tok->size == 7 && !memcmp(p,"__cdecl",7)) tok->kind = TOK_CDECL;
- if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL;
- if (tok->size == 8 && !memcmp(p,"_Complex",8)) tok->kind = TOK__COMPLEX;
- break;
- case 'c':
- if (tok->size == 4 && !memcmp(p, "char", 4)) tok->kind = TOK_CHAR;
- if (tok->size == 5 && !memcmp(p, "const", 5)) tok->kind = TOK_CONST;
- break;
- case 'd':
- if (tok->size == 6 && !memcmp(p, "double", 6)) tok->kind = TOK_DOUBLE;
- break;
- case 'e':
- if (tok->size == 4 && !memcmp(p, "enum", 4)) tok->kind = TOK_ENUM;
- break;
- case 'f':
- if (tok->size == 5 && !memcmp(p, "float", 5)) tok->kind = TOK_FLOAT;
- break;
- case 'i':
- if (tok->size == 3 && !memcmp(p, "int", 3)) tok->kind = TOK_INT;
- break;
- case 'l':
- if (tok->size == 4 && !memcmp(p, "long", 4)) tok->kind = TOK_LONG;
- break;
- case 's':
- if (tok->size == 5 && !memcmp(p, "short", 5)) tok->kind = TOK_SHORT;
- if (tok->size == 6 && !memcmp(p, "signed", 6)) tok->kind = TOK_SIGNED;
- if (tok->size == 6 && !memcmp(p, "struct", 6)) tok->kind = TOK_STRUCT;
- break;
- case 'u':
- if (tok->size == 5 && !memcmp(p, "union", 5)) tok->kind = TOK_UNION;
- if (tok->size == 8 && !memcmp(p,"unsigned",8)) tok->kind = TOK_UNSIGNED;
- break;
- case 'v':
- if (tok->size == 4 && !memcmp(p, "void", 4)) tok->kind = TOK_VOID;
- if (tok->size == 8 && !memcmp(p,"volatile",8)) tok->kind = TOK_VOLATILE;
- break;
- }
-}
-
-static int parse_error(token_t *tok, const char *msg)
-{
- if (tok->kind != TOK_ERROR) {
- tok->kind = TOK_ERROR;
- tok->info->error_location = tok->p - tok->input;
- tok->info->error_message = msg;
- }
- return -1;
-}
-
-static int write_ds(token_t *tok, _cffi_opcode_t ds)
-{
- size_t index = tok->output_index;
- if (index >= tok->info->output_size) {
- parse_error(tok, "internal type complexity limit reached");
- return -1;
- }
- tok->output[index] = ds;
- tok->output_index = index + 1;
- return index;
-}
-
-#define MAX_SSIZE_T (((size_t)-1) >> 1)
-
-static int parse_complete(token_t *tok);
-static const char *get_common_type(const char *search, size_t search_len);
-static int parse_common_type_replacement(token_t *tok, const char *replacement);
-
-static int parse_sequel(token_t *tok, int outer)
-{
- /* Emit opcodes for the "sequel", which is the optional part of a
- type declaration that follows the type name, i.e. everything
- with '*', '[ ]', '( )'. Returns the entry point index pointing
- the innermost opcode (the one that corresponds to the complete
- type). The 'outer' argument is the index of the opcode outside
- this "sequel".
- */
- int check_for_grouping, abi=0;
- _cffi_opcode_t result, *p_current;
-
- header:
- switch (tok->kind) {
- case TOK_STAR:
- outer = write_ds(tok, _CFFI_OP(_CFFI_OP_POINTER, outer));
- next_token(tok);
- goto header;
- case TOK_CONST:
- /* ignored for now */
- next_token(tok);
- goto header;
- case TOK_VOLATILE:
- /* ignored for now */
- next_token(tok);
- goto header;
- case TOK_CDECL:
- case TOK_STDCALL:
- /* must be in a function; checked below */
- abi = tok->kind;
- next_token(tok);
- goto header;
- default:
- break;
- }
-
- check_for_grouping = 1;
- if (tok->kind == TOK_IDENTIFIER) {
- next_token(tok); /* skip a potential variable name */
- check_for_grouping = 0;
- }
-
- result = 0;
- p_current = &result;
-
- while (tok->kind == TOK_OPEN_PAREN) {
- next_token(tok);
-
- if (tok->kind == TOK_CDECL || tok->kind == TOK_STDCALL) {
- abi = tok->kind;
- next_token(tok);
- }
-
- if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR ||
- tok->kind == TOK_CONST ||
- tok->kind == TOK_VOLATILE ||
- tok->kind == TOK_OPEN_BRACKET)) {
- /* just parentheses for grouping. Use a OP_NOOP to simplify */
- int x;
- assert(p_current == &result);
- x = tok->output_index;
- p_current = tok->output + x;
-
- write_ds(tok, _CFFI_OP(_CFFI_OP_NOOP, 0));
-
- x = parse_sequel(tok, x);
- result = _CFFI_OP(_CFFI_GETOP(0), x);
- }
- else {
- /* function type */
- int arg_total, base_index, arg_next, flags=0;
-
- if (abi == TOK_STDCALL) {
- flags = 2;
- /* note that an ellipsis below will overwrite this flags,
- which is the goal: variadic functions are always cdecl */
- }
- abi = 0;
-
- if (tok->kind == TOK_VOID && get_following_char(tok) == ')') {
- next_token(tok);
- }
-
- /* (over-)estimate 'arg_total'. May return 1 when it is really 0 */
- arg_total = number_of_commas(tok) + 1;
-
- *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
- p_current = tok->output + tok->output_index;
-
- base_index = write_ds(tok, _CFFI_OP(_CFFI_OP_FUNCTION, 0));
- if (base_index < 0)
- return -1;
- /* reserve (arg_total + 1) slots for the arguments and the
- final FUNCTION_END */
- for (arg_next = 0; arg_next <= arg_total; arg_next++)
- if (write_ds(tok, _CFFI_OP(0, 0)) < 0)
- return -1;
-
- arg_next = base_index + 1;
-
- if (tok->kind != TOK_CLOSE_PAREN) {
- while (1) {
- int arg;
- _cffi_opcode_t oarg;
-
- if (tok->kind == TOK_DOTDOTDOT) {
- flags = 1; /* ellipsis */
- next_token(tok);
- break;
- }
- arg = parse_complete(tok);
- switch (_CFFI_GETOP(tok->output[arg])) {
- case _CFFI_OP_ARRAY:
- case _CFFI_OP_OPEN_ARRAY:
- arg = _CFFI_GETARG(tok->output[arg]);
- /* fall-through */
- case _CFFI_OP_FUNCTION:
- oarg = _CFFI_OP(_CFFI_OP_POINTER, arg);
- break;
- default:
- oarg = _CFFI_OP(_CFFI_OP_NOOP, arg);
- break;
- }
- assert(arg_next - base_index <= arg_total);
- tok->output[arg_next++] = oarg;
- if (tok->kind != TOK_COMMA)
- break;
- next_token(tok);
- }
- }
- tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, flags);
- }
-
- if (tok->kind != TOK_CLOSE_PAREN)
- return parse_error(tok, "expected ')'");
- next_token(tok);
- }
-
- if (abi != 0)
- return parse_error(tok, "expected '('");
-
- while (tok->kind == TOK_OPEN_BRACKET) {
- *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
- p_current = tok->output + tok->output_index;
-
- next_token(tok);
- if (tok->kind != TOK_CLOSE_BRACKET) {
- size_t length;
- int gindex;
- char *endptr;
-
- switch (tok->kind) {
-
- case TOK_INTEGER:
- errno = 0;
- if (sizeof(length) > sizeof(unsigned long)) {
-#ifdef MS_WIN32
-# ifdef _WIN64
- length = _strtoui64(tok->p, &endptr, 0);
-# else
- abort(); /* unreachable */
-# endif
-#else
- length = strtoull(tok->p, &endptr, 0);
-#endif
- }
- else
- length = strtoul(tok->p, &endptr, 0);
- if (endptr != tok->p + tok->size)
- return parse_error(tok, "invalid number");
- if (errno == ERANGE || length > MAX_SSIZE_T)
- return parse_error(tok, "number too large");
- break;
-
- case TOK_IDENTIFIER:
- gindex = search_in_globals(tok->info->ctx, tok->p, tok->size);
- if (gindex >= 0) {
- const struct _cffi_global_s *g;
- g = &tok->info->ctx->globals[gindex];
- if (_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT_INT ||
- _CFFI_GETOP(g->type_op) == _CFFI_OP_ENUM) {
- int neg;
- struct _cffi_getconst_s gc;
- gc.ctx = tok->info->ctx;
- gc.gindex = gindex;
- neg = ((int(*)(struct _cffi_getconst_s*))g->address)
- (&gc);
- if (neg == 0 && gc.value > MAX_SSIZE_T)
- return parse_error(tok,
- "integer constant too large");
- if (neg == 0 || gc.value == 0) {
- length = (size_t)gc.value;
- break;
- }
- if (neg != 1)
- return parse_error(tok, "disagreement about"
- " this constant's value");
- }
- }
- /* fall-through to the default case */
- default:
- return parse_error(tok, "expected a positive integer constant");
- }
-
- next_token(tok);
-
- write_ds(tok, _CFFI_OP(_CFFI_OP_ARRAY, 0));
- write_ds(tok, (_cffi_opcode_t)length);
- }
- else
- write_ds(tok, _CFFI_OP(_CFFI_OP_OPEN_ARRAY, 0));
-
- if (tok->kind != TOK_CLOSE_BRACKET)
- return parse_error(tok, "expected ']'");
- next_token(tok);
- }
-
- *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), outer);
- return _CFFI_GETARG(result);
-}
-
-static int search_sorted(const char *const *base,
- size_t item_size, int array_len,
- const char *search, size_t search_len)
-{
- int left = 0, right = array_len;
- const char *baseptr = (const char *)base;
-
- while (left < right) {
- int middle = (left + right) / 2;
- const char *src = *(const char *const *)(baseptr + middle * item_size);
- int diff = strncmp(src, search, search_len);
- if (diff == 0 && src[search_len] == '\0')
- return middle;
- else if (diff >= 0)
- right = middle;
- else
- left = middle + 1;
- }
- return -1;
-}
-
-#define MAKE_SEARCH_FUNC(FIELD) \
- static \
- int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \
- const char *search, size_t search_len) \
- { \
- return search_sorted(&ctx->FIELD->name, sizeof(*ctx->FIELD), \
- ctx->num_##FIELD, search, search_len); \
- }
-
-MAKE_SEARCH_FUNC(globals)
-MAKE_SEARCH_FUNC(struct_unions)
-MAKE_SEARCH_FUNC(typenames)
-MAKE_SEARCH_FUNC(enums)
-
-#undef MAKE_SEARCH_FUNC
-
-
-static
-int search_standard_typename(const char *p, size_t size)
-{
- if (size < 6 || p[size-2] != '_' || p[size-1] != 't')
- return -1;
-
- switch (p[4]) {
-
- case '1':
- if (size == 8 && !memcmp(p, "uint16", 6)) return _CFFI_PRIM_UINT16;
- if (size == 8 && !memcmp(p, "char16", 6)) return _CFFI_PRIM_CHAR16;
- break;
-
- case '2':
- if (size == 7 && !memcmp(p, "int32", 5)) return _CFFI_PRIM_INT32;
- break;
-
- case '3':
- if (size == 8 && !memcmp(p, "uint32", 6)) return _CFFI_PRIM_UINT32;
- if (size == 8 && !memcmp(p, "char32", 6)) return _CFFI_PRIM_CHAR32;
- break;
-
- case '4':
- if (size == 7 && !memcmp(p, "int64", 5)) return _CFFI_PRIM_INT64;
- break;
-
- case '6':
- if (size == 8 && !memcmp(p, "uint64", 6)) return _CFFI_PRIM_UINT64;
- if (size == 7 && !memcmp(p, "int16", 5)) return _CFFI_PRIM_INT16;
- break;
-
- case '8':
- if (size == 7 && !memcmp(p, "uint8", 5)) return _CFFI_PRIM_UINT8;
- break;
-
- case 'a':
- if (size == 8 && !memcmp(p, "intmax", 6)) return _CFFI_PRIM_INTMAX;
- break;
-
- case 'e':
- if (size == 7 && !memcmp(p, "ssize", 5)) return _CFFI_PRIM_SSIZE;
- break;
-
- case 'f':
- if (size == 11 && !memcmp(p, "int_fast8", 9)) return _CFFI_PRIM_INT_FAST8;
- if (size == 12 && !memcmp(p, "int_fast16", 10)) return _CFFI_PRIM_INT_FAST16;
- if (size == 12 && !memcmp(p, "int_fast32", 10)) return _CFFI_PRIM_INT_FAST32;
- if (size == 12 && !memcmp(p, "int_fast64", 10)) return _CFFI_PRIM_INT_FAST64;
- break;
-
- case 'i':
- if (size == 9 && !memcmp(p, "ptrdiff", 7)) return _CFFI_PRIM_PTRDIFF;
- break;
-
- case 'l':
- if (size == 12 && !memcmp(p, "int_least8", 10)) return _CFFI_PRIM_INT_LEAST8;
- if (size == 13 && !memcmp(p, "int_least16", 11)) return _CFFI_PRIM_INT_LEAST16;
- if (size == 13 && !memcmp(p, "int_least32", 11)) return _CFFI_PRIM_INT_LEAST32;
- if (size == 13 && !memcmp(p, "int_least64", 11)) return _CFFI_PRIM_INT_LEAST64;
- break;
-
- case 'm':
- if (size == 9 && !memcmp(p, "uintmax", 7)) return _CFFI_PRIM_UINTMAX;
- break;
-
- case 'p':
- if (size == 9 && !memcmp(p, "uintptr", 7)) return _CFFI_PRIM_UINTPTR;
- break;
-
- case 'r':
- if (size == 7 && !memcmp(p, "wchar", 5)) return _CFFI_PRIM_WCHAR;
- break;
-
- case 't':
- if (size == 8 && !memcmp(p, "intptr", 6)) return _CFFI_PRIM_INTPTR;
- break;
-
- case '_':
- if (size == 6 && !memcmp(p, "size", 4)) return _CFFI_PRIM_SIZE;
- if (size == 6 && !memcmp(p, "int8", 4)) return _CFFI_PRIM_INT8;
- if (size >= 12) {
- switch (p[10]) {
- case '1':
- if (size == 14 && !memcmp(p, "uint_least16", 12)) return _CFFI_PRIM_UINT_LEAST16;
- break;
- case '2':
- if (size == 13 && !memcmp(p, "uint_fast32", 11)) return _CFFI_PRIM_UINT_FAST32;
- break;
- case '3':
- if (size == 14 && !memcmp(p, "uint_least32", 12)) return _CFFI_PRIM_UINT_LEAST32;
- break;
- case '4':
- if (size == 13 && !memcmp(p, "uint_fast64", 11)) return _CFFI_PRIM_UINT_FAST64;
- break;
- case '6':
- if (size == 14 && !memcmp(p, "uint_least64", 12)) return _CFFI_PRIM_UINT_LEAST64;
- if (size == 13 && !memcmp(p, "uint_fast16", 11)) return _CFFI_PRIM_UINT_FAST16;
- break;
- case '8':
- if (size == 13 && !memcmp(p, "uint_least8", 11)) return _CFFI_PRIM_UINT_LEAST8;
- break;
- case '_':
- if (size == 12 && !memcmp(p, "uint_fast8", 10)) return _CFFI_PRIM_UINT_FAST8;
- break;
- default:
- break;
- }
- }
- break;
-
- default:
- break;
- }
- return -1;
-}
-
-
-static int parse_complete(token_t *tok)
-{
- unsigned int t0;
- _cffi_opcode_t t1;
- _cffi_opcode_t t1complex;
- int modifiers_length, modifiers_sign;
-
- qualifiers:
- switch (tok->kind) {
- case TOK_CONST:
- /* ignored for now */
- next_token(tok);
- goto qualifiers;
- case TOK_VOLATILE:
- /* ignored for now */
- next_token(tok);
- goto qualifiers;
- default:
- ;
- }
-
- modifiers_length = 0;
- modifiers_sign = 0;
- modifiers:
- switch (tok->kind) {
-
- case TOK_SHORT:
- if (modifiers_length != 0)
- return parse_error(tok, "'short' after another 'short' or 'long'");
- modifiers_length--;
- next_token(tok);
- goto modifiers;
-
- case TOK_LONG:
- if (modifiers_length < 0)
- return parse_error(tok, "'long' after 'short'");
- if (modifiers_length >= 2)
- return parse_error(tok, "'long long long' is too long");
- modifiers_length++;
- next_token(tok);
- goto modifiers;
-
- case TOK_SIGNED:
- if (modifiers_sign)
- return parse_error(tok, "multiple 'signed' or 'unsigned'");
- modifiers_sign++;
- next_token(tok);
- goto modifiers;
-
- case TOK_UNSIGNED:
- if (modifiers_sign)
- return parse_error(tok, "multiple 'signed' or 'unsigned'");
- modifiers_sign--;
- next_token(tok);
- goto modifiers;
-
- default:
- break;
- }
-
- t1complex = 0;
-
- if (modifiers_length || modifiers_sign) {
-
- switch (tok->kind) {
-
- case TOK_VOID:
- case TOK__BOOL:
- case TOK_FLOAT:
- case TOK_STRUCT:
- case TOK_UNION:
- case TOK_ENUM:
- case TOK__COMPLEX:
- return parse_error(tok, "invalid combination of types");
-
- case TOK_DOUBLE:
- if (modifiers_sign != 0 || modifiers_length != 1)
- return parse_error(tok, "invalid combination of types");
- next_token(tok);
- t0 = _CFFI_PRIM_LONGDOUBLE;
- break;
-
- case TOK_CHAR:
- if (modifiers_length != 0)
- return parse_error(tok, "invalid combination of types");
- modifiers_length = -2;
- /* fall-through */
- case TOK_INT:
- next_token(tok);
- /* fall-through */
- default:
- if (modifiers_sign >= 0)
- switch (modifiers_length) {
- case -2: t0 = _CFFI_PRIM_SCHAR; break;
- case -1: t0 = _CFFI_PRIM_SHORT; break;
- case 1: t0 = _CFFI_PRIM_LONG; break;
- case 2: t0 = _CFFI_PRIM_LONGLONG; break;
- default: t0 = _CFFI_PRIM_INT; break;
- }
- else
- switch (modifiers_length) {
- case -2: t0 = _CFFI_PRIM_UCHAR; break;
- case -1: t0 = _CFFI_PRIM_USHORT; break;
- case 1: t0 = _CFFI_PRIM_ULONG; break;
- case 2: t0 = _CFFI_PRIM_ULONGLONG; break;
- default: t0 = _CFFI_PRIM_UINT; break;
- }
- }
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, t0);
- }
- else {
- switch (tok->kind) {
- case TOK_INT:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT);
- break;
- case TOK_CHAR:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_CHAR);
- break;
- case TOK_VOID:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_VOID);
- break;
- case TOK__BOOL:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_BOOL);
- break;
- case TOK_FLOAT:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT);
- t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOATCOMPLEX);
- break;
- case TOK_DOUBLE:
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE);
- t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLECOMPLEX);
- break;
- case TOK_IDENTIFIER:
- {
- const char *replacement;
- int n = search_in_typenames(tok->info->ctx, tok->p, tok->size);
- if (n >= 0) {
- t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n);
- break;
- }
- n = search_standard_typename(tok->p, tok->size);
- if (n >= 0) {
- t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n);
- break;
- }
- replacement = get_common_type(tok->p, tok->size);
- if (replacement != NULL) {
- n = parse_common_type_replacement(tok, replacement);
- if (n < 0)
- return parse_error(tok, "internal error, please report!");
- t1 = _CFFI_OP(_CFFI_OP_NOOP, n);
- break;
- }
- return parse_error(tok, "undefined type name");
- }
- case TOK_STRUCT:
- case TOK_UNION:
- {
- int n, kind = tok->kind;
- next_token(tok);
- if (tok->kind != TOK_IDENTIFIER)
- return parse_error(tok, "struct or union name expected");
-
- n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size);
- if (n < 0) {
- if (kind == TOK_STRUCT && tok->size == 8 &&
- !memcmp(tok->p, "_IO_FILE", 8))
- n = _CFFI__IO_FILE_STRUCT;
- else
- return parse_error(tok, "undefined struct/union name");
- }
- else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION)
- != 0) ^ (kind == TOK_UNION))
- return parse_error(tok, "wrong kind of tag: struct vs union");
-
- t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n);
- break;
- }
- case TOK_ENUM:
- {
- int n;
- next_token(tok);
- if (tok->kind != TOK_IDENTIFIER)
- return parse_error(tok, "enum name expected");
-
- n = search_in_enums(tok->info->ctx, tok->p, tok->size);
- if (n < 0)
- return parse_error(tok, "undefined enum name");
-
- t1 = _CFFI_OP(_CFFI_OP_ENUM, n);
- break;
- }
- default:
- return parse_error(tok, "identifier expected");
- }
- next_token(tok);
- }
- if (tok->kind == TOK__COMPLEX)
- {
- if (t1complex == 0)
- return parse_error(tok, "_Complex type combination unsupported");
- t1 = t1complex;
- next_token(tok);
- }
-
- return parse_sequel(tok, write_ds(tok, t1));
-}
-
-
-static
-int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index,
- const char *input)
-{
- int result;
- token_t token;
-
- token.info = info;
- token.kind = TOK_START;
- token.input = input;
- token.p = input;
- token.size = 0;
- token.output = info->output;
- token.output_index = *output_index;
-
- next_token(&token);
- result = parse_complete(&token);
-
- *output_index = token.output_index;
- if (token.kind != TOK_END)
- return parse_error(&token, "unexpected symbol");
- return result;
-}
-
-static
-int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
-{
- size_t output_index = 0;
- return parse_c_type_from(info, &output_index, input);
-}
-
-static
-int parse_common_type_replacement(token_t *tok, const char *replacement)
-{
- return parse_c_type_from(tok->info, &tok->output_index, replacement);
-}
diff --git a/c/realize_c_type.c b/c/realize_c_type.c
deleted file mode 100644
index 82629b7..0000000
--- a/c/realize_c_type.c
+++ /dev/null
@@ -1,820 +0,0 @@
-
-typedef struct {
- struct _cffi_type_context_s ctx; /* inlined substructure */
- PyObject *types_dict;
- PyObject *included_ffis;
- PyObject *included_libs;
- PyObject *_keepalive1;
- PyObject *_keepalive2;
-} builder_c_t;
-
-
-static PyObject *all_primitives[_CFFI__NUM_PRIM];
-static CTypeDescrObject *g_ct_voidp, *g_ct_chararray;
-
-static PyObject *build_primitive_type(int num); /* forward */
-
-#define primitive_in_range(num) ((num) >= 0 && (num) < _CFFI__NUM_PRIM)
-#define get_primitive_type(num) \
- ((primitive_in_range(num) && all_primitives[num] != NULL) ? \
- all_primitives[num] : build_primitive_type(num))
-
-static int init_global_types_dict(PyObject *ffi_type_dict)
-{
- int err;
- PyObject *ct_void, *ct_char, *ct2, *pnull;
- /* XXX some leaks in case these functions fail, but well,
- MemoryErrors during importing an extension module are kind
- of bad anyway */
-
- ct_void = get_primitive_type(_CFFI_PRIM_VOID); // 'void'
- if (ct_void == NULL)
- return -1;
-
- ct2 = new_pointer_type((CTypeDescrObject *)ct_void); // 'void *'
- if (ct2 == NULL)
- return -1;
- g_ct_voidp = (CTypeDescrObject *)ct2;
-
- ct_char = get_primitive_type(_CFFI_PRIM_CHAR); // 'char'
- if (ct_char == NULL)
- return -1;
-
- ct2 = new_pointer_type((CTypeDescrObject *)ct_char); // 'char *'
- if (ct2 == NULL)
- return -1;
-
- ct2 = new_array_type((CTypeDescrObject *)ct2, -1); // 'char[]'
- if (ct2 == NULL)
- return -1;
- g_ct_chararray = (CTypeDescrObject *)ct2;
-
- pnull = new_simple_cdata(NULL, g_ct_voidp);
- if (pnull == NULL)
- return -1;
- err = PyDict_SetItemString(ffi_type_dict, "NULL", pnull);
- Py_DECREF(pnull);
- return err;
-}
-
-static void free_builder_c(builder_c_t *builder, int ctx_is_static)
-{
- if (!ctx_is_static) {
- size_t i;
- const void *mem[] = {builder->ctx.types,
- builder->ctx.globals,
- builder->ctx.struct_unions,
- //builder->ctx.fields: allocated with struct_unions
- builder->ctx.enums,
- builder->ctx.typenames};
- for (i = 0; i < sizeof(mem) / sizeof(*mem); i++) {
- if (mem[i] != NULL)
- PyMem_Free((void *)mem[i]);
- }
- }
- Py_XDECREF(builder->included_ffis);
- Py_XDECREF(builder->included_libs);
- Py_XDECREF(builder->types_dict);
- Py_XDECREF(builder->_keepalive1);
- Py_XDECREF(builder->_keepalive2);
-}
-
-static int init_builder_c(builder_c_t *builder,
- const struct _cffi_type_context_s *ctx)
-{
- PyObject *ldict = PyDict_New();
- if (ldict == NULL)
- return -1;
-
- if (ctx)
- builder->ctx = *ctx;
- else
- memset(&builder->ctx, 0, sizeof(builder->ctx));
-
- builder->types_dict = ldict;
- builder->included_ffis = NULL;
- builder->included_libs = NULL;
- builder->_keepalive1 = NULL;
- builder->_keepalive2 = NULL;
- return 0;
-}
-
-static PyObject *build_primitive_type(int num)
-{
- /* XXX too many translations between here and new_primitive_type() */
- static const char *primitive_name[] = {
- NULL,
- "_Bool",
- "char",
- "signed char",
- "unsigned char",
- "short",
- "unsigned short",
- "int",
- "unsigned int",
- "long",
- "unsigned long",
- "long long",
- "unsigned long long",
- "float",
- "double",
- "long double",
- "wchar_t",
- "int8_t",
- "uint8_t",
- "int16_t",
- "uint16_t",
- "int32_t",
- "uint32_t",
- "int64_t",
- "uint64_t",
- "intptr_t",
- "uintptr_t",
- "ptrdiff_t",
- "size_t",
- "ssize_t",
- "int_least8_t",
- "uint_least8_t",
- "int_least16_t",
- "uint_least16_t",
- "int_least32_t",
- "uint_least32_t",
- "int_least64_t",
- "uint_least64_t",
- "int_fast8_t",
- "uint_fast8_t",
- "int_fast16_t",
- "uint_fast16_t",
- "int_fast32_t",
- "uint_fast32_t",
- "int_fast64_t",
- "uint_fast64_t",
- "intmax_t",
- "uintmax_t",
- "float _Complex",
- "double _Complex",
- "char16_t",
- "char32_t",
- };
- PyObject *x;
-
- assert(sizeof(primitive_name) == sizeof(*primitive_name) * _CFFI__NUM_PRIM);
- if (num == _CFFI_PRIM_VOID) {
- x = new_void_type();
- }
- else if (primitive_in_range(num) && primitive_name[num] != NULL) {
- x = new_primitive_type(primitive_name[num]);
- }
- else if (num == _CFFI__UNKNOWN_PRIM) {
- PyErr_SetString(FFIError, "primitive integer type with an unexpected "
- "size (or not an integer type at all)");
- return NULL;
- }
- else if (num == _CFFI__UNKNOWN_FLOAT_PRIM) {
- PyErr_SetString(FFIError, "primitive floating-point type with an "
- "unexpected size (or not a float type at all)");
- return NULL;
- }
- else if (num == _CFFI__UNKNOWN_LONG_DOUBLE) {
- PyErr_SetString(FFIError, "primitive floating-point type is "
- "'long double', not supported for now with "
- "the syntax 'typedef double... xxx;'");
- return NULL;
- }
- else {
- PyErr_Format(PyExc_NotImplementedError, "prim=%d", num);
- return NULL;
- }
-
- all_primitives[num] = x;
- return x;
-}
-
-static PyObject *realize_global_int(builder_c_t *builder, int gindex)
-{
- int neg;
- char got[64];
- unsigned long long value;
- struct _cffi_getconst_s gc;
- const struct _cffi_global_s *g = &builder->ctx.globals[gindex];
- gc.ctx = &builder->ctx;
- gc.gindex = gindex;
- /* note: we cast g->address to this function type; we do the same
- in parse_c_type:parse_sequel() too. Note that the called function
- may be declared simply with "unsigned long long *" as argument,
- which is fine as it is the first field in _cffi_getconst_s. */
- assert(&gc.value == (unsigned long long *)&gc);
- neg = ((int(*)(struct _cffi_getconst_s *))g->address)(&gc);
- value = gc.value;
-
- switch (neg) {
-
- case 0:
- if (value <= (unsigned long long)LONG_MAX)
- return PyInt_FromLong((long)value);
- else
- return PyLong_FromUnsignedLongLong(value);
-
- case 1:
- if ((long long)value >= (long long)LONG_MIN)
- return PyInt_FromLong((long)value);
- else
- return PyLong_FromLongLong((long long)value);
-
- default:
- break;
- }
- if (neg == 2)
- sprintf(got, "%llu (0x%llx)", value, value);
- else
- sprintf(got, "%lld", (long long)value);
- PyErr_Format(FFIError, "the C compiler says '%.200s' is equal to %s, "
- "but the cdef disagrees", g->name, got);
- return NULL;
-}
-
-static CTypeDescrObject *
-unwrap_fn_as_fnptr(PyObject *x)
-{
- assert(PyTuple_Check(x));
- return (CTypeDescrObject *)PyTuple_GET_ITEM(x, 0);
-}
-
-static CTypeDescrObject *
-unexpected_fn_type(PyObject *x)
-{
- CTypeDescrObject *ct = unwrap_fn_as_fnptr(x);
- char *text1 = ct->ct_name;
- char *text2 = text1 + ct->ct_name_position + 1;
- assert(text2[-3] == '(');
- text2[-3] = '\0';
- PyErr_Format(FFIError, "the type '%s%s' is a function type, not a "
- "pointer-to-function type", text1, text2);
- text2[-3] = '(';
- return NULL;
-}
-
-static PyObject *
-realize_c_type_or_func(builder_c_t *builder,
- _cffi_opcode_t opcodes[], int index); /* forward */
-
-
-/* Interpret an opcodes[] array. If opcodes == ctx->types, store all
- the intermediate types back in the opcodes[]. Returns a new
- reference.
-*/
-static CTypeDescrObject *
-realize_c_type(builder_c_t *builder, _cffi_opcode_t opcodes[], int index)
-{
- PyObject *x = realize_c_type_or_func(builder, opcodes, index);
- if (x == NULL || CTypeDescr_Check(x))
- return (CTypeDescrObject *)x;
- else {
- unexpected_fn_type(x);
- Py_DECREF(x);
- return NULL;
- }
-}
-
-static void _realize_name(char *target, const char *prefix, const char *srcname)
-{
- /* "xyz" => "struct xyz"
- "$xyz" => "xyz"
- "$1" => "struct $1"
- */
- if (srcname[0] == '$' && srcname[1] != '$' &&
- !('0' <= srcname[1] && srcname[1] <= '9')) {
- strcpy(target, &srcname[1]);
- }
- else {
- strcpy(target, prefix);
- strcat(target, srcname);
- }
-}
-
-static void _unrealize_name(char *target, const char *srcname)
-{
- /* reverse of _realize_name() */
- if (strncmp(srcname, "struct ", 7) == 0) {
- strcpy(target, &srcname[7]);
- }
- else if (strncmp(srcname, "union ", 6) == 0) {
- strcpy(target, &srcname[6]);
- }
- else if (strncmp(srcname, "enum ", 5) == 0) {
- strcpy(target, &srcname[5]);
- }
- else {
- strcpy(target, "$");
- strcat(target, srcname);
- }
-}
-
-static PyObject * /* forward */
-_fetch_external_struct_or_union(const struct _cffi_struct_union_s *s,
- PyObject *included_ffis, int recursion);
-
-static PyObject *
-_realize_c_struct_or_union(builder_c_t *builder, int sindex)
-{
- PyObject *x;
- _cffi_opcode_t op2;
- const struct _cffi_struct_union_s *s;
-
- if (sindex == _CFFI__IO_FILE_STRUCT) {
- /* returns a single global cached opaque type */
- static PyObject *file_struct = NULL;
- if (file_struct == NULL)
- file_struct = new_struct_or_union_type("FILE",
- CT_STRUCT | CT_IS_FILE);
- Py_XINCREF(file_struct);
- return file_struct;
- }
-
- s = &builder->ctx.struct_unions[sindex];
- op2 = builder->ctx.types[s->type_index];
- if ((((uintptr_t)op2) & 1) == 0) {
- x = (PyObject *)op2; /* found already in the "primary" slot */
- Py_INCREF(x);
- }
- else {
- CTypeDescrObject *ct = NULL;
-
- if (!(s->flags & _CFFI_F_EXTERNAL)) {
- int flags = (s->flags & _CFFI_F_UNION) ? CT_UNION : CT_STRUCT;
- char *name = alloca(8 + strlen(s->name));
- _realize_name(name,
- (s->flags & _CFFI_F_UNION) ? "union " : "struct ",
- s->name);
- if (strcmp(name, "struct _IO_FILE") == 0)
- x = _realize_c_struct_or_union(builder, _CFFI__IO_FILE_STRUCT);
- else
- x = new_struct_or_union_type(name, flags);
- if (x == NULL)
- return NULL;
-
- if (!(s->flags & _CFFI_F_OPAQUE)) {
- assert(s->first_field_index >= 0);
- ct = (CTypeDescrObject *)x;
- ct->ct_size = (Py_ssize_t)s->size;
- ct->ct_length = s->alignment; /* may be -1 */
- ct->ct_flags &= ~CT_IS_OPAQUE;
- ct->ct_flags |= CT_LAZY_FIELD_LIST;
- ct->ct_extra = builder;
- }
- else
- assert(s->first_field_index < 0);
- }
- else {
- assert(s->first_field_index < 0);
- x = _fetch_external_struct_or_union(s, builder->included_ffis, 0);
- if (x == NULL) {
- if (!PyErr_Occurred())
- PyErr_Format(FFIError, "'%s %.200s' should come from "
- "ffi.include() but was not found",
- (s->flags & _CFFI_F_UNION) ? "union"
- : "struct", s->name);
- return NULL;
- }
- if (!(s->flags & _CFFI_F_OPAQUE)) {
- if (((CTypeDescrObject *)x)->ct_flags & CT_IS_OPAQUE) {
- const char *prefix = (s->flags & _CFFI_F_UNION) ? "union"
- : "struct";
- PyErr_Format(PyExc_NotImplementedError,
- "'%s %.200s' is opaque in the ffi.include(), "
- "but no longer in the ffi doing the include "
- "(workaround: don't use ffi.include() but "
- "duplicate the declarations of everything "
- "using %s %.200s)",
- prefix, s->name, prefix, s->name);
- Py_DECREF(x);
- return NULL;
- }
- }
- }
-
- /* Update the "primary" OP_STRUCT_UNION slot */
- assert((((uintptr_t)x) & 1) == 0);
- assert(builder->ctx.types[s->type_index] == op2);
- Py_INCREF(x);
- builder->ctx.types[s->type_index] = x;
-
- if (ct != NULL && s->size == (size_t)-2) {
- /* oops, this struct is unnamed and we couldn't generate
- a C expression to get its size. We have to rely on
- complete_struct_or_union() to compute it now. */
- if (do_realize_lazy_struct(ct) < 0) {
- builder->ctx.types[s->type_index] = op2;
- return NULL;
- }
- }
- }
- return x;
-}
-
-static PyObject *
-realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op,
- _cffi_opcode_t opcodes[], int index)
-{
- PyObject *x, *y, *z;
- Py_ssize_t length = -1;
-
- switch (_CFFI_GETOP(op)) {
-
- case _CFFI_OP_PRIMITIVE:
- x = get_primitive_type(_CFFI_GETARG(op));
- Py_XINCREF(x);
- break;
-
- case _CFFI_OP_POINTER:
- y = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
- if (y == NULL)
- return NULL;
- if (CTypeDescr_Check(y)) {
- x = new_pointer_type((CTypeDescrObject *)y);
- }
- else {
- assert(PyTuple_Check(y)); /* from _CFFI_OP_FUNCTION */
- x = PyTuple_GET_ITEM(y, 0);
- Py_INCREF(x);
- }
- Py_DECREF(y);
- break;
-
- case _CFFI_OP_ARRAY:
- length = (Py_ssize_t)opcodes[index + 1];
- /* fall-through */
- case _CFFI_OP_OPEN_ARRAY:
- y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
- if (y == NULL)
- return NULL;
- z = new_pointer_type((CTypeDescrObject *)y);
- Py_DECREF(y);
- if (z == NULL)
- return NULL;
- x = new_array_type((CTypeDescrObject *)z, length);
- Py_DECREF(z);
- break;
-
- case _CFFI_OP_STRUCT_UNION:
- x = _realize_c_struct_or_union(builder, _CFFI_GETARG(op));
- break;
-
- case _CFFI_OP_ENUM:
- {
- const struct _cffi_enum_s *e;
- _cffi_opcode_t op2;
-
- e = &builder->ctx.enums[_CFFI_GETARG(op)];
- op2 = builder->ctx.types[e->type_index];
- if ((((uintptr_t)op2) & 1) == 0) {
- x = (PyObject *)op2;
- Py_INCREF(x);
- }
- else {
- PyObject *enumerators = NULL, *enumvalues = NULL, *tmp;
- Py_ssize_t i, j, n = 0;
- const char *p;
- int gindex;
- PyObject *args;
- PyObject *basetd = get_primitive_type(e->type_prim);
- if (basetd == NULL)
- return NULL;
-
- if (*e->enumerators != '\0') {
- n++;
- for (p = e->enumerators; *p != '\0'; p++)
- n += (*p == ',');
- }
- enumerators = PyTuple_New(n);
- if (enumerators == NULL)
- return NULL;
-
- enumvalues = PyTuple_New(n);
- if (enumvalues == NULL) {
- Py_DECREF(enumerators);
- return NULL;
- }
-
- p = e->enumerators;
- for (i = 0; i < n; i++) {
- j = 0;
- while (p[j] != ',' && p[j] != '\0')
- j++;
- tmp = PyText_FromStringAndSize(p, j);
- if (tmp == NULL)
- break;
- PyTuple_SET_ITEM(enumerators, i, tmp);
-
- gindex = search_in_globals(&builder->ctx, p, j);
- assert(gindex >= 0);
- assert(builder->ctx.globals[gindex].type_op ==
- _CFFI_OP(_CFFI_OP_ENUM, -1));
-
- tmp = realize_global_int(builder, gindex);
- if (tmp == NULL)
- break;
- PyTuple_SET_ITEM(enumvalues, i, tmp);
-
- p += j + 1;
- }
-
- args = NULL;
- if (!PyErr_Occurred()) {
- char *name = alloca(6 + strlen(e->name));
- _realize_name(name, "enum ", e->name);
- args = Py_BuildValue("(sOOO)", name, enumerators,
- enumvalues, basetd);
- }
- Py_DECREF(enumerators);
- Py_DECREF(enumvalues);
- if (args == NULL)
- return NULL;
-
- x = b_new_enum_type(NULL, args);
- Py_DECREF(args);
- if (x == NULL)
- return NULL;
-
- /* Update the "primary" _CFFI_OP_ENUM slot, which
- may be the same or a different slot than the "current" one */
- assert((((uintptr_t)x) & 1) == 0);
- assert(builder->ctx.types[e->type_index] == op2);
- Py_INCREF(x);
- builder->ctx.types[e->type_index] = x;
-
- /* Done, leave without updating the "current" slot because
- it may be done already above. If not, never mind, the
- next call to realize_c_type() will do it. */
- return x;
- }
- break;
- }
-
- case _CFFI_OP_FUNCTION:
- {
- PyObject *fargs;
- int i, base_index, num_args, ellipsis, abi;
-
- y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
- if (y == NULL)
- return NULL;
-
- base_index = index + 1;
- num_args = 0;
- /* note that if the arguments are already built, they have a
- pointer in the 'opcodes' array, and GETOP() returns a
- random even value. But OP_FUNCTION_END is odd, so the
- condition below still works correctly. */
- while (_CFFI_GETOP(opcodes[base_index + num_args]) !=
- _CFFI_OP_FUNCTION_END)
- num_args++;
-
- ellipsis = _CFFI_GETARG(opcodes[base_index + num_args]) & 0x01;
- abi = _CFFI_GETARG(opcodes[base_index + num_args]) & 0xFE;
- switch (abi) {
- case 0:
- abi = FFI_DEFAULT_ABI;
- break;
- case 2:
-#if defined(MS_WIN32) && !defined(_WIN64)
- abi = FFI_STDCALL;
-#else
- abi = FFI_DEFAULT_ABI;
-#endif
- break;
- default:
- PyErr_Format(FFIError, "abi number %d not supported", abi);
- Py_DECREF(y);
- return NULL;
- }
-
- fargs = PyTuple_New(num_args);
- if (fargs == NULL) {
- Py_DECREF(y);
- return NULL;
- }
-
- for (i = 0; i < num_args; i++) {
- z = (PyObject *)realize_c_type(builder, opcodes, base_index + i);
- if (z == NULL) {
- Py_DECREF(fargs);
- Py_DECREF(y);
- return NULL;
- }
- PyTuple_SET_ITEM(fargs, i, z);
- }
-
- z = new_function_type(fargs, (CTypeDescrObject *)y, ellipsis, abi);
- Py_DECREF(fargs);
- Py_DECREF(y);
- if (z == NULL)
- return NULL;
-
- x = PyTuple_Pack(1, z); /* hack: hide the CT_FUNCTIONPTR. it will
- be revealed again by the OP_POINTER */
- Py_DECREF(z);
- break;
- }
-
- case _CFFI_OP_NOOP:
- x = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
- break;
-
- case _CFFI_OP_TYPENAME:
- {
- /* essential: the TYPENAME opcode resolves the type index looked
- up in the 'ctx->typenames' array, but it does so in 'ctx->types'
- instead of in 'opcodes'! */
- int type_index = builder->ctx.typenames[_CFFI_GETARG(op)].type_index;
- x = realize_c_type_or_func(builder, builder->ctx.types, type_index);
- break;
- }
-
- default:
- PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op));
- return NULL;
- }
-
- return x;
-}
-
-static int _realize_recursion_level;
-
-static PyObject *
-realize_c_type_or_func(builder_c_t *builder,
- _cffi_opcode_t opcodes[], int index)
-{
- PyObject *x;
- _cffi_opcode_t op = opcodes[index];
-
- if ((((uintptr_t)op) & 1) == 0) {
- x = (PyObject *)op;
- Py_INCREF(x);
- return x;
- }
-
- if (_realize_recursion_level >= 1000) {
- PyErr_Format(PyExc_RuntimeError,
- "type-building recursion too deep or infinite. "
- "This is known to occur e.g. in ``struct s { void(*callable)"
- "(struct s); }''. Please report if you get this error and "
- "really need support for your case.");
- return NULL;
- }
- _realize_recursion_level++;
- x = realize_c_type_or_func_now(builder, op, opcodes, index);
- _realize_recursion_level--;
-
- if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) {
- assert((((uintptr_t)x) & 1) == 0);
- assert((((uintptr_t)opcodes[index]) & 1) == 1);
- Py_INCREF(x);
- opcodes[index] = x;
- }
- return x;
-}
-
-static CTypeDescrObject *
-realize_c_func_return_type(builder_c_t *builder,
- _cffi_opcode_t opcodes[], int index)
-{
- PyObject *x;
- _cffi_opcode_t op = opcodes[index];
-
- if ((((uintptr_t)op) & 1) == 0) {
- /* already built: assert that it is a function and fish
- for the return type */
- x = (PyObject *)op;
- assert(PyTuple_Check(x)); /* from _CFFI_OP_FUNCTION */
- x = PyTuple_GET_ITEM(x, 0);
- assert(CTypeDescr_Check(x));
- assert(((CTypeDescrObject *)x)->ct_flags & CT_FUNCTIONPTR);
- x = PyTuple_GET_ITEM(((CTypeDescrObject *)x)->ct_stuff, 1);
- assert(CTypeDescr_Check(x));
- Py_INCREF(x);
- return (CTypeDescrObject *)x;
- }
- else {
- assert(_CFFI_GETOP(op) == _CFFI_OP_FUNCTION);
- return realize_c_type(builder, opcodes, _CFFI_GETARG(opcodes[index]));
- }
-}
-
-static int do_realize_lazy_struct(CTypeDescrObject *ct)
-{
- /* This is called by force_lazy_struct() in _cffi_backend.c */
- assert(ct->ct_flags & (CT_STRUCT | CT_UNION));
-
- if (ct->ct_flags & CT_LAZY_FIELD_LIST) {
- builder_c_t *builder;
- char *p;
- int n, i, sflags;
- const struct _cffi_struct_union_s *s;
- const struct _cffi_field_s *fld;
- PyObject *fields, *args, *res;
-
- assert(!(ct->ct_flags & CT_IS_OPAQUE));
-
- builder = ct->ct_extra;
- assert(builder != NULL);
-
- p = alloca(2 + strlen(ct->ct_name));
- _unrealize_name(p, ct->ct_name);
-
- n = search_in_struct_unions(&builder->ctx, p, strlen(p));
- if (n < 0)
- Py_FatalError("lost a struct/union!");
-
- s = &builder->ctx.struct_unions[n];
- fld = &builder->ctx.fields[s->first_field_index];
-
- /* XXX painfully build all the Python objects that are the args
- to b_complete_struct_or_union() */
-
- fields = PyList_New(s->num_fields);
- if (fields == NULL)
- return -1;
-
- for (i = 0; i < s->num_fields; i++, fld++) {
- _cffi_opcode_t op = fld->field_type_op;
- int fbitsize = -1;
- PyObject *f;
- CTypeDescrObject *ctf;
-
- switch (_CFFI_GETOP(op)) {
-
- case _CFFI_OP_BITFIELD:
- assert(fld->field_size >= 0);
- fbitsize = (int)fld->field_size;
- /* fall-through */
- case _CFFI_OP_NOOP:
- ctf = realize_c_type(builder, builder->ctx.types,
- _CFFI_GETARG(op));
- break;
-
- default:
- Py_DECREF(fields);
- PyErr_Format(PyExc_NotImplementedError, "field op=%d",
- (int)_CFFI_GETOP(op));
- return -1;
- }
-
- if (ctf != NULL && fld->field_offset == (size_t)-1) {
- /* unnamed struct, with field positions and sizes entirely
- determined by complete_struct_or_union() and not checked.
- Or, bitfields (field_size >= 0), similarly not checked. */
- assert(fld->field_size == (size_t)-1 || fbitsize >= 0);
- }
- else if (ctf == NULL || detect_custom_layout(ct, SF_STD_FIELD_POS,
- ctf->ct_size, fld->field_size,
- "wrong size for field '",
- fld->name, "'") < 0) {
- Py_DECREF(fields);
- return -1;
- }
-
- f = Py_BuildValue("(sOin)", fld->name, ctf,
- fbitsize, (Py_ssize_t)fld->field_offset);
- if (f == NULL) {
- Py_DECREF(fields);
- return -1;
- }
- PyList_SET_ITEM(fields, i, f);
- }
-
- sflags = 0;
- if (s->flags & _CFFI_F_CHECK_FIELDS)
- sflags |= SF_STD_FIELD_POS;
- if (s->flags & _CFFI_F_PACKED)
- sflags |= SF_PACKED;
-
- args = Py_BuildValue("(OOOnii)", ct, fields, Py_None,
- (Py_ssize_t)s->size,
- s->alignment,
- sflags);
- Py_DECREF(fields);
- if (args == NULL)
- return -1;
-
- ct->ct_extra = NULL;
- ct->ct_flags |= CT_IS_OPAQUE;
- res = b_complete_struct_or_union(NULL, args);
- ct->ct_flags &= ~CT_IS_OPAQUE;
- Py_DECREF(args);
-
- if (res == NULL) {
- ct->ct_extra = builder;
- return -1;
- }
-
- assert(ct->ct_stuff != NULL);
- ct->ct_flags &= ~CT_LAZY_FIELD_LIST;
- Py_DECREF(res);
- return 1;
- }
- else {
- assert(ct->ct_flags & CT_IS_OPAQUE);
- return 0;
- }
-}
diff --git a/c/test_c.py b/c/test_c.py
deleted file mode 100644
index 654584d..0000000
--- a/c/test_c.py
+++ /dev/null
@@ -1,4575 +0,0 @@
-import py
-import pytest
-
-def _setup_path():
- import os, sys
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
-_setup_path()
-from _cffi_backend import *
-from _cffi_backend import _get_types, _get_common_types
-try:
- from _cffi_backend import _testfunc
-except ImportError:
- def _testfunc(num):
- pytest.skip("_testunc() not available")
-from _cffi_backend import __version__
-
-# ____________________________________________________________
-
-import sys
-assert __version__ == "1.15.0", ("This test_c.py file is for testing a version"
- " of cffi that differs from the one that we"
- " get from 'import _cffi_backend'")
-if sys.version_info < (3,):
- type_or_class = "type"
- mandatory_b_prefix = ''
- mandatory_u_prefix = 'u'
- bytechr = chr
- bitem2bchr = lambda x: x
- class U(object):
- def __add__(self, other):
- return eval('u'+repr(other).replace(r'\\u', r'\u')
- .replace(r'\\U', r'\U'))
- u = U()
- str2bytes = str
- strict_compare = False
-else:
- type_or_class = "class"
- long = int
- unicode = str
- unichr = chr
- mandatory_b_prefix = 'b'
- mandatory_u_prefix = ''
- bytechr = lambda n: bytes([n])
- bitem2bchr = bytechr
- u = ""
- str2bytes = lambda s: bytes(s, "ascii")
- strict_compare = True
-
-def size_of_int():
- BInt = new_primitive_type("int")
- return sizeof(BInt)
-
-def size_of_long():
- BLong = new_primitive_type("long")
- return sizeof(BLong)
-
-def size_of_ptr():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- return sizeof(BPtr)
-
-
-def find_and_load_library(name, flags=RTLD_NOW):
- import ctypes.util
- if name is None:
- path = None
- else:
- path = ctypes.util.find_library(name)
- if path is None and name == 'c':
- assert sys.platform == 'win32'
- assert (sys.version_info >= (3,) or
- '__pypy__' in sys.builtin_module_names)
- py.test.skip("dlopen(None) cannot work on Windows "
- "with PyPy or Python 3")
- return load_library(path, flags)
-
-def test_load_library():
- x = find_and_load_library('c')
- assert repr(x).startswith("<clibrary '")
- x = find_and_load_library('c', RTLD_NOW | RTLD_GLOBAL)
- assert repr(x).startswith("<clibrary '")
- x = find_and_load_library('c', RTLD_LAZY)
- assert repr(x).startswith("<clibrary '")
-
-def test_all_rtld_symbols():
- import sys
- FFI_DEFAULT_ABI # these symbols must be defined
- FFI_CDECL
- RTLD_LAZY
- RTLD_NOW
- RTLD_GLOBAL
- RTLD_LOCAL
- if sys.platform.startswith("linux"):
- RTLD_NODELETE
- RTLD_NOLOAD
- RTLD_DEEPBIND
-
-def test_new_primitive_type():
- py.test.raises(KeyError, new_primitive_type, "foo")
- p = new_primitive_type("signed char")
- assert repr(p) == "<ctype 'signed char'>"
-
-def check_dir(p, expected):
- got = [name for name in dir(p) if not name.startswith('_')]
- assert got == sorted(expected)
-
-def test_inspect_primitive_type():
- p = new_primitive_type("signed char")
- assert p.kind == "primitive"
- assert p.cname == "signed char"
- check_dir(p, ['cname', 'kind'])
-
-def test_cast_to_signed_char():
- p = new_primitive_type("signed char")
- x = cast(p, -65 + 17*256)
- assert repr(x) == "<cdata 'signed char' -65>"
- assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class
- assert int(x) == -65
- x = cast(p, -66 + (1<<199)*256)
- assert repr(x) == "<cdata 'signed char' -66>"
- assert int(x) == -66
- assert (x == cast(p, -66)) is True
- assert (x != cast(p, -66)) is False
- q = new_primitive_type("short")
- assert (x == cast(q, -66)) is True
- assert (x != cast(q, -66)) is False
-
-def test_sizeof_type():
- py.test.raises(TypeError, sizeof, 42.5)
- p = new_primitive_type("short")
- assert sizeof(p) == 2
-
-def test_integer_types():
- for name in ['signed char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type(name)
- size = sizeof(p)
- min = -(1 << (8*size-1))
- max = (1 << (8*size-1)) - 1
- assert int(cast(p, min)) == min
- assert int(cast(p, max)) == max
- assert int(cast(p, min - 1)) == max
- assert int(cast(p, max + 1)) == min
- py.test.raises(TypeError, cast, p, None)
- assert long(cast(p, min - 1)) == max
- assert int(cast(p, b'\x08')) == 8
- assert int(cast(p, u+'\x08')) == 8
- for name in ['char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type('unsigned ' + name)
- size = sizeof(p)
- max = (1 << (8*size)) - 1
- assert int(cast(p, 0)) == 0
- assert int(cast(p, max)) == max
- assert int(cast(p, -1)) == max
- assert int(cast(p, max + 1)) == 0
- assert long(cast(p, -1)) == max
- assert int(cast(p, b'\xFE')) == 254
- assert int(cast(p, u+'\xFE')) == 254
-
-def test_no_float_on_int_types():
- p = new_primitive_type('long')
- py.test.raises(TypeError, float, cast(p, 42))
- py.test.raises(TypeError, complex, cast(p, 42))
-
-def test_float_types():
- INF = 1E200 * 1E200
- for name in ["float", "double"]:
- p = new_primitive_type(name)
- assert bool(cast(p, 0)) is False # since 1.7
- assert bool(cast(p, -0.0)) is False # since 1.7
- assert bool(cast(p, 1e-42)) is True
- assert bool(cast(p, -1e-42)) is True
- assert bool(cast(p, INF))
- assert bool(cast(p, -INF))
- assert bool(cast(p, float("nan")))
- assert int(cast(p, -150)) == -150
- assert int(cast(p, 61.91)) == 61
- assert long(cast(p, 61.91)) == 61
- assert type(int(cast(p, 61.91))) is int
- assert type(int(cast(p, 1E22))) is long
- assert type(long(cast(p, 61.91))) is long
- assert type(long(cast(p, 1E22))) is long
- py.test.raises(OverflowError, int, cast(p, INF))
- py.test.raises(OverflowError, int, cast(p, -INF))
- assert float(cast(p, 1.25)) == 1.25
- assert float(cast(p, INF)) == INF
- assert float(cast(p, -INF)) == -INF
- if name == "float":
- assert float(cast(p, 1.1)) != 1.1 # rounding error
- assert float(cast(p, 1E200)) == INF # limited range
-
- assert cast(p, -1.1) == cast(p, -1.1)
- assert repr(float(cast(p, -0.0))) == '-0.0'
- assert float(cast(p, b'\x09')) == 9.0
- assert float(cast(p, u+'\x09')) == 9.0
- assert float(cast(p, True)) == 1.0
- py.test.raises(TypeError, cast, p, None)
-
-def test_complex_types():
- INF = 1E200 * 1E200
- for name in ["float", "double"]:
- p = new_primitive_type(name + " _Complex")
- assert bool(cast(p, 0)) is False
- assert bool(cast(p, INF))
- assert bool(cast(p, -INF))
- assert bool(cast(p, 0j)) is False
- assert bool(cast(p, INF*1j))
- assert bool(cast(p, -INF*1j))
- # "can't convert complex to float", like CPython's "float(0j)"
- py.test.raises(TypeError, int, cast(p, -150))
- py.test.raises(TypeError, long, cast(p, -150))
- py.test.raises(TypeError, float, cast(p, -150))
- assert complex(cast(p, 1.25)) == 1.25
- assert complex(cast(p, 1.25j)) == 1.25j
- assert complex(cast(p, complex(0,INF))) == complex(0,INF)
- assert complex(cast(p, -INF)) == -INF
- if name == "float":
- assert complex(cast(p, 1.1j)) != 1.1j # rounding error
- assert complex(cast(p, 1E200+3j)) == INF+3j # limited range
- assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range
-
- assert cast(p, -1.1j) == cast(p, -1.1j)
- assert repr(complex(cast(p, -0.0)).real) == '-0.0'
- #assert repr(complex(cast(p, -0j))) == '-0j' # http://bugs.python.org/issue29602
- assert complex(cast(p, b'\x09')) == 9.0 + 0j
- assert complex(cast(p, u+'\x09')) == 9.0 + 0j
- assert complex(cast(p, True)) == 1.0 + 0j
- py.test.raises(TypeError, cast, p, None)
- #
- py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j)
- #
- for basetype in ["char", "int", "uint64_t", "float",
- "double", "long double"]:
- baseobj = cast(new_primitive_type(basetype), 65)
- py.test.raises(TypeError, complex, baseobj)
- #
- BArray = new_array_type(new_pointer_type(p), 10)
- x = newp(BArray, None)
- x[5] = 12.34 + 56.78j
- assert type(x[5]) is complex
- assert abs(x[5] - (12.34 + 56.78j)) < 1e-5
- assert (x[5] == 12.34 + 56.78j) == (name == "double") # rounding error
- #
- class Foo:
- def __complex__(self):
- return 2 + 3j
- assert complex(Foo()) == 2 + 3j
- assert complex(cast(p, Foo())) == 2 + 3j
- py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j)
-
-def test_character_type():
- p = new_primitive_type("char")
- assert bool(cast(p, 'A')) is True
- assert bool(cast(p, '\x00')) is False # since 1.7
- assert cast(p, '\x00') == cast(p, -17*256)
- assert int(cast(p, 'A')) == 65
- assert long(cast(p, 'A')) == 65
- assert type(int(cast(p, 'A'))) is int
- assert type(long(cast(p, 'A'))) is long
- assert str(cast(p, 'A')) == repr(cast(p, 'A'))
- assert repr(cast(p, 'A')) == "<cdata 'char' %s'A'>" % mandatory_b_prefix
- assert repr(cast(p, 255)) == r"<cdata 'char' %s'\xff'>" % mandatory_b_prefix
- assert repr(cast(p, 0)) == r"<cdata 'char' %s'\x00'>" % mandatory_b_prefix
-
-def test_pointer_type():
- p = new_primitive_type("int")
- assert repr(p) == "<ctype 'int'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int *'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int * *'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int * * *'>"
-
-def test_inspect_pointer_type():
- p1 = new_primitive_type("int")
- p2 = new_pointer_type(p1)
- assert p2.kind == "pointer"
- assert p2.cname == "int *"
- assert p2.item is p1
- check_dir(p2, ['cname', 'kind', 'item'])
- p3 = new_pointer_type(p2)
- assert p3.item is p2
-
-def test_pointer_to_int():
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, newp, BInt)
- py.test.raises(TypeError, newp, BInt, None)
- BPtr = new_pointer_type(BInt)
- p = newp(BPtr)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- p = newp(BPtr, None)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- p = newp(BPtr, 5000)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- q = cast(BPtr, p)
- assert repr(q).startswith("<cdata 'int *' 0x")
- assert p == q
- assert hash(p) == hash(q)
- e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None)
- assert str(e.value) == (
- "expected new array length or list/tuple/str, not NoneType")
-
-def test_pointer_bool():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- p = cast(BPtr, 0)
- assert bool(p) is False
- p = cast(BPtr, 42)
- assert bool(p) is True
-
-def test_pointer_to_pointer():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- BPtrPtr = new_pointer_type(BPtr)
- p = newp(BPtrPtr, None)
- assert repr(p) == "<cdata 'int * *' owning %d bytes>" % size_of_ptr()
-
-def test_reading_pointer_to_int():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- p = newp(BPtr, None)
- assert p[0] == 0
- p = newp(BPtr, 5000)
- assert p[0] == 5000
- with pytest.raises(IndexError):
- p[1]
- with pytest.raises(IndexError):
- p[-1]
-
-def test_reading_pointer_to_float():
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, newp, BFloat, None)
- BPtr = new_pointer_type(BFloat)
- p = newp(BPtr, None)
- assert p[0] == 0.0 and type(p[0]) is float
- p = newp(BPtr, 1.25)
- assert p[0] == 1.25 and type(p[0]) is float
- p = newp(BPtr, 1.1)
- assert p[0] != 1.1 and abs(p[0] - 1.1) < 1E-5 # rounding errors
-
-def test_cast_float_to_int():
- for type in ["int", "unsigned int", "long", "unsigned long",
- "long long", "unsigned long long"]:
- p = new_primitive_type(type)
- assert int(cast(p, 4.2)) == 4
- py.test.raises(TypeError, newp, new_pointer_type(p), 4.2)
-
-def test_newp_integer_types():
- for name in ['signed char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type(name)
- pp = new_pointer_type(p)
- size = sizeof(p)
- min = -(1 << (8*size-1))
- max = (1 << (8*size-1)) - 1
- assert newp(pp, min)[0] == min
- assert newp(pp, max)[0] == max
- py.test.raises(OverflowError, newp, pp, min - 2 ** 32)
- py.test.raises(OverflowError, newp, pp, min - 2 ** 64)
- py.test.raises(OverflowError, newp, pp, max + 2 ** 32)
- py.test.raises(OverflowError, newp, pp, max + 2 ** 64)
- py.test.raises(OverflowError, newp, pp, min - 1)
- py.test.raises(OverflowError, newp, pp, max + 1)
- py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32)
- py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64)
- py.test.raises(OverflowError, newp, pp, max + 1)
- py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32)
- py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64)
- py.test.raises(TypeError, newp, pp, 1.0)
- for name in ['char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type('unsigned ' + name)
- pp = new_pointer_type(p)
- size = sizeof(p)
- max = (1 << (8*size)) - 1
- assert newp(pp, 0)[0] == 0
- assert newp(pp, max)[0] == max
- py.test.raises(OverflowError, newp, pp, -1)
- py.test.raises(OverflowError, newp, pp, max + 1)
-
-def test_reading_pointer_to_char():
- BChar = new_primitive_type("char")
- py.test.raises(TypeError, newp, BChar, None)
- BPtr = new_pointer_type(BChar)
- p = newp(BPtr, None)
- assert p[0] == b'\x00'
- p = newp(BPtr, b'A')
- assert p[0] == b'A'
- py.test.raises(TypeError, newp, BPtr, 65)
- py.test.raises(TypeError, newp, BPtr, b"foo")
- py.test.raises(TypeError, newp, BPtr, u+"foo")
- c = cast(BChar, b'A')
- assert str(c) == repr(c)
- assert int(c) == ord(b'A')
- py.test.raises(TypeError, cast, BChar, b'foo')
- py.test.raises(TypeError, cast, BChar, u+'foo')
- e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3)
- assert str(e.value) == (
- "expected new array length or list/tuple/str, not float")
-
-def test_reading_pointer_to_pointer():
- BVoidP = new_pointer_type(new_void_type())
- BCharP = new_pointer_type(new_primitive_type("char"))
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BIntPtrPtr = new_pointer_type(BIntPtr)
- q = newp(BIntPtr, 42)
- assert q[0] == 42
- p = newp(BIntPtrPtr, None)
- assert p[0] is not None
- assert p[0] == cast(BVoidP, 0)
- assert p[0] == cast(BCharP, 0)
- assert p[0] != None
- assert repr(p[0]) == "<cdata 'int *' NULL>"
- p[0] = q
- assert p[0] != cast(BVoidP, 0)
- assert p[0] != cast(BCharP, 0)
- assert p[0][0] == 42
- q[0] += 1
- assert p[0][0] == 43
- p = newp(BIntPtrPtr, q)
- assert p[0][0] == 43
-
-def test_load_standard_library():
- if sys.platform == "win32":
- py.test.raises(OSError, find_and_load_library, None)
- return
- x = find_and_load_library(None)
- BVoidP = new_pointer_type(new_void_type())
- assert x.load_function(BVoidP, 'strcpy')
- py.test.raises(AttributeError, x.load_function,
- BVoidP, 'xxx_this_function_does_not_exist')
- # the next one is from 'libm', not 'libc', but we assume
- # that it is already loaded too, so it should work
- assert x.load_function(BVoidP, 'sqrt')
- #
- x.close_lib()
- py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt')
- x.close_lib()
-
-def test_no_len_on_nonarray():
- p = new_primitive_type("int")
- py.test.raises(TypeError, len, cast(p, 42))
-
-def test_cmp_none():
- p = new_primitive_type("int")
- x = cast(p, 42)
- assert (x == None) is False
- assert (x != None) is True
- assert (x == ["hello"]) is False
- assert (x != ["hello"]) is True
- y = cast(p, 0)
- assert (y == None) is False
-
-def test_invalid_indexing():
- p = new_primitive_type("int")
- x = cast(p, 42)
- with pytest.raises(TypeError):
- x[0]
-
-def test_default_str():
- BChar = new_primitive_type("char")
- x = cast(BChar, 42)
- assert str(x) == repr(x)
- BInt = new_primitive_type("int")
- x = cast(BInt, 42)
- assert str(x) == repr(x)
- BArray = new_array_type(new_pointer_type(BInt), 10)
- x = newp(BArray, None)
- assert str(x) == repr(x)
-
-def test_default_unicode():
- BInt = new_primitive_type("int")
- x = cast(BInt, 42)
- assert unicode(x) == unicode(repr(x))
- BArray = new_array_type(new_pointer_type(BInt), 10)
- x = newp(BArray, None)
- assert unicode(x) == unicode(repr(x))
-
-def test_cast_from_cdataint():
- BInt = new_primitive_type("int")
- x = cast(BInt, 0)
- y = cast(new_pointer_type(BInt), x)
- assert bool(y) is False
- #
- x = cast(BInt, 42)
- y = cast(BInt, x)
- assert int(y) == 42
- y = cast(new_primitive_type("char"), x)
- assert int(y) == 42
- y = cast(new_primitive_type("float"), x)
- assert float(y) == 42.0
- #
- z = cast(BInt, 42.5)
- assert int(z) == 42
- z = cast(BInt, y)
- assert int(z) == 42
-
-def test_void_type():
- p = new_void_type()
- assert p.kind == "void"
- assert p.cname == "void"
- check_dir(p, ['kind', 'cname'])
-
-def test_array_type():
- p = new_primitive_type("int")
- assert repr(p) == "<ctype 'int'>"
- #
- py.test.raises(TypeError, new_array_type, new_pointer_type(p), "foo")
- py.test.raises(ValueError, new_array_type, new_pointer_type(p), -42)
- #
- p1 = new_array_type(new_pointer_type(p), None)
- assert repr(p1) == "<ctype 'int[]'>"
- py.test.raises(ValueError, new_array_type, new_pointer_type(p1), 42)
- #
- p1 = new_array_type(new_pointer_type(p), 42)
- p2 = new_array_type(new_pointer_type(p1), 25)
- assert repr(p2) == "<ctype 'int[25][42]'>"
- p2 = new_array_type(new_pointer_type(p1), None)
- assert repr(p2) == "<ctype 'int[][42]'>"
- #
- py.test.raises(OverflowError,
- new_array_type, new_pointer_type(p), sys.maxsize+1)
- py.test.raises(OverflowError,
- new_array_type, new_pointer_type(p), sys.maxsize // 3)
-
-def test_inspect_array_type():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- assert p1.kind == "array"
- assert p1.cname == "int[]"
- assert p1.item is p
- assert p1.length is None
- check_dir(p1, ['cname', 'kind', 'item', 'length'])
- p1 = new_array_type(new_pointer_type(p), 42)
- assert p1.kind == "array"
- assert p1.cname == "int[42]"
- assert p1.item is p
- assert p1.length == 42
- check_dir(p1, ['cname', 'kind', 'item', 'length'])
-
-def test_array_instance():
- LENGTH = 1423
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), LENGTH)
- a = newp(p1, None)
- assert repr(a) == "<cdata 'int[%d]' owning %d bytes>" % (
- LENGTH, LENGTH * size_of_int())
- assert len(a) == LENGTH
- for i in range(LENGTH):
- assert a[i] == 0
- with pytest.raises(IndexError):
- a[LENGTH]
- with pytest.raises(IndexError):
- a[-1]
- for i in range(LENGTH):
- a[i] = i * i + 1
- for i in range(LENGTH):
- assert a[i] == i * i + 1
- with pytest.raises(IndexError) as e:
- a[LENGTH+100] = 500
- assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value)
- py.test.raises(TypeError, int, a)
-
-def test_array_of_unknown_length_instance():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- py.test.raises(TypeError, newp, p1, None)
- py.test.raises(ValueError, newp, p1, -42)
- a = newp(p1, 42)
- assert len(a) == 42
- for i in range(42):
- a[i] -= i
- for i in range(42):
- assert a[i] == -i
- with pytest.raises(IndexError):
- a[42]
- with pytest.raises(IndexError):
- a[-1]
- with pytest.raises(IndexError):
- a[42] = 123
- with pytest.raises(IndexError):
- a[-1] = 456
-
-def test_array_of_unknown_length_instance_with_initializer():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- a = newp(p1, list(range(42)))
- assert len(a) == 42
- a = newp(p1, tuple(range(142)))
- assert len(a) == 142
-
-def test_array_initializer():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- a = newp(p1, list(range(100, 142)))
- for i in range(42):
- assert a[i] == 100 + i
- #
- p2 = new_array_type(new_pointer_type(p), 43)
- a = newp(p2, tuple(range(100, 142)))
- for i in range(42):
- assert a[i] == 100 + i
- assert a[42] == 0 # extra uninitialized item
-
-def test_array_add():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), 5) # int[5]
- p2 = new_array_type(new_pointer_type(p1), 3) # int[3][5]
- a = newp(p2, [list(range(n, n+5)) for n in [100, 200, 300]])
- assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
- 3*5*size_of_int(),)
- assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
- assert 0 + a == a + 0 != 1 + a == a + 1
- assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
- assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
- assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
- assert type(a[0][0]) is int
- assert type((a[0] + 0)[0]) is int
-
-def test_array_sub():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), 5) # int[5]
- a = newp(BArray, None)
- p = a + 1
- assert p - a == 1
- assert p - (a+0) == 1
- assert a == (p - 1)
- BPtr = new_pointer_type(new_primitive_type("short"))
- q = newp(BPtr, None)
- with pytest.raises(TypeError):
- p - q
- with pytest.raises(TypeError):
- q - p
- with pytest.raises(TypeError):
- a - q
- with pytest.raises(TypeError) as e:
- q - a
- assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
-
-def test_ptr_sub_unaligned():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- a = cast(BIntPtr, 1240)
- for bi in range(1430, 1438):
- b = cast(BIntPtr, bi)
- if ((bi - 1240) % size_of_int()) == 0:
- assert b - a == (bi - 1240) // size_of_int()
- assert a - b == (1240 - bi) // size_of_int()
- else:
- with pytest.raises(ValueError):
- b - a
- with pytest.raises(ValueError):
- a - b
-
-def test_cast_primitive_from_cdata():
- p = new_primitive_type("int")
- n = cast(p, cast(p, -42))
- assert int(n) == -42
- #
- p = new_primitive_type("unsigned int")
- n = cast(p, cast(p, 42))
- assert int(n) == 42
- #
- p = new_primitive_type("long long")
- n = cast(p, cast(p, -(1<<60)))
- assert int(n) == -(1<<60)
- #
- p = new_primitive_type("unsigned long long")
- n = cast(p, cast(p, 1<<63))
- assert int(n) == 1<<63
- #
- p = new_primitive_type("float")
- n = cast(p, cast(p, 42.5))
- assert float(n) == 42.5
- #
- p = new_primitive_type("char")
- n = cast(p, cast(p, "A"))
- assert int(n) == ord("A")
-
-def test_new_primitive_from_cdata():
- p = new_primitive_type("int")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, -42))
- assert n[0] == -42
- #
- p = new_primitive_type("unsigned int")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, 42))
- assert n[0] == 42
- #
- p = new_primitive_type("float")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, 42.5))
- assert n[0] == 42.5
- #
- p = new_primitive_type("char")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, "A"))
- assert n[0] == b"A"
-
-def test_cast_between_pointers():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntA = new_array_type(BIntP, None)
- a = newp(BIntA, [40, 41, 42, 43, 44])
- BShortP = new_pointer_type(new_primitive_type("short"))
- b = cast(BShortP, a)
- c = cast(BIntP, b)
- assert c[3] == 43
- BLongLong = new_primitive_type("long long")
- d = cast(BLongLong, c)
- e = cast(BIntP, d)
- assert e[3] == 43
- f = cast(BIntP, int(d))
- assert f[3] == 43
- #
- b = cast(BShortP, 0)
- assert not b
- c = cast(BIntP, b)
- assert not c
- assert int(cast(BLongLong, c)) == 0
-
-def test_alignof():
- BInt = new_primitive_type("int")
- assert alignof(BInt) == sizeof(BInt)
- BPtr = new_pointer_type(BInt)
- assert alignof(BPtr) == sizeof(BPtr)
- BArray = new_array_type(BPtr, None)
- assert alignof(BArray) == alignof(BInt)
-
-def test_new_struct_type():
- BStruct = new_struct_type("foo")
- assert repr(BStruct) == "<ctype 'foo'>"
- BStruct = new_struct_type("struct foo")
- assert repr(BStruct) == "<ctype 'struct foo'>"
- BPtr = new_pointer_type(BStruct)
- assert repr(BPtr) == "<ctype 'struct foo *'>"
- py.test.raises(ValueError, sizeof, BStruct)
- py.test.raises(ValueError, alignof, BStruct)
-
-def test_new_union_type():
- BUnion = new_union_type("union foo")
- assert repr(BUnion) == "<ctype 'union foo'>"
- BPtr = new_pointer_type(BUnion)
- assert repr(BPtr) == "<ctype 'union foo *'>"
-
-def test_complete_struct():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- assert BStruct.kind == "struct"
- assert BStruct.cname == "struct foo"
- assert BStruct.fields is None
- check_dir(BStruct, ['cname', 'kind', 'fields'])
- #
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BChar, -1),
- ('a3', BShort, -1)])
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BLong)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BShort
- assert d[2][1].offset == sizeof(BLong) + sizeof(BShort)
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
- assert sizeof(BStruct) == 2 * sizeof(BLong)
- assert alignof(BStruct) == alignof(BLong)
-
-def test_complete_union():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BUnion = new_union_type("union foo")
- assert BUnion.kind == "union"
- assert BUnion.cname == "union foo"
- assert BUnion.fields is None
- complete_struct_or_union(BUnion, [('a1', BLong, -1),
- ('a2', BChar, -1)])
- d = BUnion.fields
- assert len(d) == 2
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == 0
- assert sizeof(BUnion) == sizeof(BLong)
- assert alignof(BUnion) == alignof(BLong)
-
-def test_struct_instance():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- p = cast(BStructPtr, 42)
- with pytest.raises(AttributeError) as e:
- p.a1 # opaque
- assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
- "cannot read fields")
- with pytest.raises(AttributeError) as e:
- p.a1 = 10 # opaque
- assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
- "cannot write fields")
-
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- p = newp(BStructPtr, None)
- s = p[0]
- assert s.a1 == 0
- s.a2 = 123
- assert s.a1 == 0
- assert s.a2 == 123
- with pytest.raises(OverflowError):
- s.a1 = sys.maxsize+1
- assert s.a1 == 0
- with pytest.raises(AttributeError) as e:
- p.foobar
- assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- p.foobar = 42
- assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- s.foobar
- assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- s.foobar = 42
- assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
- j = cast(BInt, 42)
- with pytest.raises(AttributeError) as e:
- j.foobar
- assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
- with pytest.raises(AttributeError) as e:
- j.foobar = 42
- assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
- j = cast(new_pointer_type(BInt), 42)
- with pytest.raises(AttributeError) as e:
- j.foobar
- assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
- with pytest.raises(AttributeError) as e:
- j.foobar = 42
- assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
- pp = newp(new_pointer_type(BStructPtr), p)
- with pytest.raises(AttributeError) as e:
- pp.a1
- assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
- with pytest.raises(AttributeError) as e:
- pp.a1 = 42
- assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
-
-def test_union_instance():
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BUnion = new_union_type("union bar")
- complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
- p = newp(new_pointer_type(BUnion), [-42])
- bigval = -42 + (1 << (8*size_of_int()))
- assert p.a1 == -42
- assert p.a2 == bigval
- p = newp(new_pointer_type(BUnion), {'a2': bigval})
- assert p.a1 == -42
- assert p.a2 == bigval
- py.test.raises(OverflowError, newp, new_pointer_type(BUnion),
- {'a1': bigval})
- p = newp(new_pointer_type(BUnion), [])
- assert p.a1 == p.a2 == 0
-
-def test_struct_pointer():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- p = newp(BStructPtr, None)
- assert p.a1 == 0 # read/write via the pointer (C equivalent: '->')
- p.a2 = 123
- assert p.a1 == 0
- assert p.a2 == 123
-
-def test_struct_init_list():
- BVoidP = new_pointer_type(new_void_type())
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1),
- ('a3', BInt, -1),
- ('p4', BIntPtr, -1)])
- s = newp(BStructPtr, [123, 456])
- assert s.a1 == 123
- assert s.a2 == 456
- assert s.a3 == 0
- assert s.p4 == cast(BVoidP, 0)
- assert s.p4 != 0
- #
- s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
- assert s.a1 == 0
- assert s.a2 == 41122
- assert s.a3 == -123
- assert s.p4 == cast(BVoidP, 0)
- #
- py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0})
- #
- p = newp(BIntPtr, 14141)
- s = newp(BStructPtr, [12, 34, 56, p])
- assert s.p4 == p
- assert s.p4
- #
- s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)])
- assert s.p4 == cast(BVoidP, 0)
- assert not s.p4
- #
- py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
-
-def test_array_in_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BArrayInt5 = new_array_type(new_pointer_type(BInt), 5)
- complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)])
- s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]])
- assert s.a1[2] == 27
- assert repr(s.a1).startswith("<cdata 'int[5]' 0x")
-
-def test_offsetof():
- def offsetof(BType, fieldname):
- return typeoffsetof(BType, fieldname)[1]
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- py.test.raises(TypeError, offsetof, BInt, "abc")
- py.test.raises(TypeError, offsetof, BStruct, "abc")
- complete_struct_or_union(BStruct, [('abc', BInt, -1), ('def', BInt, -1)])
- assert offsetof(BStruct, 'abc') == 0
- assert offsetof(BStruct, 'def') == size_of_int()
- py.test.raises(KeyError, offsetof, BStruct, "ghi")
- assert offsetof(new_pointer_type(BStruct), "def") == size_of_int()
-
-def test_function_type():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
- BFunc2 = new_function_type((), BFunc, False)
- assert repr(BFunc2) == "<ctype 'int(*(*)())(int, int)'>"
-
-def test_inspect_function_type():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- assert BFunc.kind == "function"
- assert BFunc.cname == "int(*)(int, int)"
- assert BFunc.args == (BInt, BInt)
- assert BFunc.result is BInt
- assert BFunc.ellipsis is False
- assert BFunc.abi == FFI_DEFAULT_ABI
-
-def test_function_type_taking_struct():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc = new_function_type((BStruct,), BShort, False)
- assert repr(BFunc) == "<ctype 'short(*)(struct foo)'>"
-
-def test_function_void_result():
- BVoid = new_void_type()
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BVoid, False)
- assert repr(BFunc) == "<ctype 'void(*)(int, int)'>"
-
-def test_function_void_arg():
- BVoid = new_void_type()
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False)
-
-def test_call_function_0():
- BSignedChar = new_primitive_type("signed char")
- BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False)
- f = cast(BFunc0, _testfunc(0))
- assert f(40, 2) == 42
- assert f(-100, -100) == -200 + 256
- py.test.raises(OverflowError, f, 128, 0)
- py.test.raises(OverflowError, f, 0, 128)
-
-def test_call_function_0_pretend_bool_result():
- BSignedChar = new_primitive_type("signed char")
- BBool = new_primitive_type("_Bool")
- BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False)
- f = cast(BFunc0, _testfunc(0))
- assert f(40, -39) is True
- assert f(40, -40) is False
- py.test.raises(ValueError, f, 40, 2)
-
-def test_call_function_1():
- BInt = new_primitive_type("int")
- BLong = new_primitive_type("long")
- BFunc1 = new_function_type((BInt, BLong), BLong, False)
- f = cast(BFunc1, _testfunc(1))
- assert f(40, 2) == 42
- assert f(-100, -100) == -200
- int_max = (1 << (8*size_of_int()-1)) - 1
- long_max = (1 << (8*size_of_long()-1)) - 1
- if int_max == long_max:
- assert f(int_max, 1) == - int_max - 1
- else:
- assert f(int_max, 1) == int_max + 1
-
-def test_call_function_2():
- BLongLong = new_primitive_type("long long")
- BFunc2 = new_function_type((BLongLong, BLongLong), BLongLong, False)
- f = cast(BFunc2, _testfunc(2))
- longlong_max = (1 << (8*sizeof(BLongLong)-1)) - 1
- assert f(longlong_max - 42, 42) == longlong_max
- assert f(43, longlong_max - 42) == - longlong_max - 1
-
-def test_call_function_3():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BFunc3 = new_function_type((BFloat, BDouble), BDouble, False)
- f = cast(BFunc3, _testfunc(3))
- assert f(1.25, 5.1) == 1.25 + 5.1 # exact
- res = f(1.3, 5.1)
- assert res != 6.4 and abs(res - 6.4) < 1E-5 # inexact
-
-def test_call_function_4():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BFunc4 = new_function_type((BFloat, BDouble), BFloat, False)
- f = cast(BFunc4, _testfunc(4))
- res = f(1.25, 5.1)
- assert res != 6.35 and abs(res - 6.35) < 1E-5 # inexact
-
-def test_call_function_5():
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid, False)
- f = cast(BFunc5, _testfunc(5))
- f() # did not crash
-
-def test_call_function_6():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BFunc6 = new_function_type((BIntPtr,), BIntPtr, False)
- f = cast(BFunc6, _testfunc(6))
- x = newp(BIntPtr, 42)
- res = f(x)
- assert typeof(res) is BIntPtr
- assert res[0] == 42 - 1000
- #
- BIntArray = new_array_type(BIntPtr, None)
- BFunc6bis = new_function_type((BIntArray,), BIntPtr, False)
- f = cast(BFunc6bis, _testfunc(6))
- #
- res = f([142])
- assert typeof(res) is BIntPtr
- assert res[0] == 142 - 1000
- #
- res = f((143,))
- assert typeof(res) is BIntPtr
- assert res[0] == 143 - 1000
- #
- x = newp(BIntArray, [242])
- res = f(x)
- assert typeof(res) is BIntPtr
- assert res[0] == 242 - 1000
- #
- py.test.raises(TypeError, f, 123456)
- py.test.raises(TypeError, f, "foo")
- py.test.raises(TypeError, f, u+"bar")
-
-def test_call_function_7():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc7 = new_function_type((BStruct,), BShort, False)
- f = cast(BFunc7, _testfunc(7))
- res = f({'a1': b'A', 'a2': -4042})
- assert res == -4042 + ord(b'A')
- #
- x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
- res = f(x[0])
- assert res == -4042 + ord(b'A')
-
-def test_call_function_20():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc20 = new_function_type((BStructPtr,), BShort, False)
- f = cast(BFunc20, _testfunc(20))
- x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
- # can't pass a 'struct foo'
- py.test.raises(TypeError, f, x[0])
-
-def test_call_function_21():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- BFunc21 = new_function_type((BStruct,), BInt, False)
- f = cast(BFunc21, _testfunc(21))
- res = f(list(range(13, 3, -1)))
- lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
- assert res == sum(lst)
-
-def test_call_function_22():
- BInt = new_primitive_type("int")
- BArray10 = new_array_type(new_pointer_type(BInt), 10)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BArray10, -1)])
- BFunc22 = new_function_type((BStruct, BStruct), BStruct, False)
- f = cast(BFunc22, _testfunc(22))
- p1 = newp(BStructP, {'a': list(range(100, 110))})
- p2 = newp(BStructP, {'a': list(range(1000, 1100, 10))})
- res = f(p1[0], p2[0])
- for i in range(10):
- assert res.a[i] == p1.a[i] - p2.a[i]
-
-def test_call_function_23():
- BVoid = new_void_type() # declaring the function as int(void*)
- BVoidP = new_pointer_type(BVoid)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BVoidP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"foo")
- assert res == 1000 * ord(b'f')
- res = f(cast(BVoidP, 0)) # NULL
- assert res == -42
- py.test.raises(TypeError, f, None)
- py.test.raises(TypeError, f, 0)
- py.test.raises(TypeError, f, 0.0)
-
-def test_call_function_23_bis():
- # declaring the function as int(unsigned char*)
- BUChar = new_primitive_type("unsigned char")
- BUCharP = new_pointer_type(BUChar)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BUCharP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"foo")
- assert res == 1000 * ord(b'f')
-
-def test_call_function_23_bool_array():
- # declaring the function as int(_Bool*)
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BBoolP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"\x01\x01")
- assert res == 1000
- py.test.raises(ValueError, f, b"\x02\x02")
-
-def test_cannot_pass_struct_with_array_of_length_0():
- BInt = new_primitive_type("int")
- BArray0 = new_array_type(new_pointer_type(BInt), 0)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BArray0)])
- BFunc = new_function_type((BStruct,), BInt, False)
- py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123))
- BFunc2 = new_function_type((BInt,), BStruct, False)
- py.test.raises(NotImplementedError, cast(BFunc2, 123), 123)
-
-def test_call_function_9():
- BInt = new_primitive_type("int")
- BFunc9 = new_function_type((BInt,), BInt, True) # vararg
- f = cast(BFunc9, _testfunc(9))
- assert f(0) == 0
- assert f(1, cast(BInt, 42)) == 42
- assert f(2, cast(BInt, 40), cast(BInt, 2)) == 42
- py.test.raises(TypeError, f, 1, 42)
- py.test.raises(TypeError, f, 2, None)
- # promotion of chars and shorts to ints
- BSChar = new_primitive_type("signed char")
- BUChar = new_primitive_type("unsigned char")
- BSShort = new_primitive_type("short")
- assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192
-
-def test_call_function_24():
- BFloat = new_primitive_type("float")
- BFloatComplex = new_primitive_type("float _Complex")
- BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False)
- if 0: # libffi returning nonsense silently, so logic disabled for now
- f = cast(BFunc3, _testfunc(24))
- result = f(1.25, 5.1)
- assert type(result) == complex
- assert result.real == 1.25 # exact
- assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
- else:
- f = cast(BFunc3, _testfunc(9))
- py.test.raises(NotImplementedError, f, 12.3, 34.5)
-
-def test_call_function_25():
- BDouble = new_primitive_type("double")
- BDoubleComplex = new_primitive_type("double _Complex")
- BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False)
- if 0: # libffi returning nonsense silently, so logic disabled for now
- f = cast(BFunc3, _testfunc(25))
- result = f(1.25, 5.1)
- assert type(result) == complex
- assert result.real == 1.25 # exact
- assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact
- else:
- f = cast(BFunc3, _testfunc(9))
- py.test.raises(NotImplementedError, f, 12.3, 34.5)
-
-def test_cannot_call_with_a_autocompleted_struct():
- BSChar = new_primitive_type("signed char")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('c', BDouble, -1, 8),
- ('a', BSChar, -1, 2),
- ('b', BSChar, -1, 0)])
- BFunc = new_function_type((BStruct,), BDouble) # internally not callable
- dummy_func = cast(BFunc, 42)
- e = py.test.raises(NotImplementedError, dummy_func, "?")
- msg = ("ctype 'struct foo' not supported as argument. It is a struct "
- 'declared with "...;", but the C calling convention may depend '
- "on the missing fields; or, it contains anonymous struct/unions. "
- "Such structs are only supported as argument if the function is "
- "'API mode' and non-variadic (i.e. declared inside ffibuilder."
- "cdef()+ffibuilder.set_source() and not taking a final '...' "
- "argument)")
- assert str(e.value) == msg
-
-def test_new_charp():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- x = newp(BCharA, 42)
- assert len(x) == 42
- x = newp(BCharA, b"foobar")
- assert len(x) == 7
-
-def test_load_and_call_function():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BLong = new_primitive_type("long")
- BFunc = new_function_type((BCharP,), BLong, False)
- ll = find_and_load_library('c')
- strlen = ll.load_function(BFunc, "strlen")
- input = newp(new_array_type(BCharP, None), b"foobar")
- assert strlen(input) == 6
- #
- assert strlen(b"foobarbaz") == 9
- #
- BVoidP = new_pointer_type(new_void_type())
- strlenaddr = ll.load_function(BVoidP, "strlen")
- assert strlenaddr == cast(BVoidP, strlen)
-
-def test_read_variable():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BVoidP = new_pointer_type(new_void_type())
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BVoidP, "stderr")
- assert stderr == cast(BVoidP, _testfunc(8))
- #
- ll.close_lib()
- py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr")
-
-def test_read_variable_as_unknown_length_array():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BCharP = new_pointer_type(new_primitive_type("char"))
- BArray = new_array_type(BCharP, None)
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BArray, "stderr")
- assert repr(stderr).startswith("<cdata 'char *' 0x")
- # ^^ and not 'char[]', which is basically not allowed and would crash
-
-def test_write_variable():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BVoidP = new_pointer_type(new_void_type())
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BVoidP, "stderr")
- ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0))
- assert ll.read_variable(BVoidP, "stderr") is not None
- assert not ll.read_variable(BVoidP, "stderr")
- ll.write_variable(BVoidP, "stderr", stderr)
- assert ll.read_variable(BVoidP, "stderr") == stderr
- #
- ll.close_lib()
- py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr)
-
-def test_callback():
- BInt = new_primitive_type("int")
- def make_callback():
- def cb(n):
- return n + 1
- BFunc = new_function_type((BInt,), BInt, False)
- return callback(BFunc, cb, 42) # 'cb' and 'BFunc' go out of scope
- f = make_callback()
- assert f(-142) == -141
- assert repr(f).startswith(
- "<cdata 'int(*)(int)' calling <function ")
- assert "cb at 0x" in repr(f)
- e = py.test.raises(TypeError, f)
- assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0"
-
-def test_callback_exception():
- try:
- import cStringIO
- except ImportError:
- import io as cStringIO # Python 3
- import linecache
- def matches(istr, ipattern, ipattern38):
- if sys.version_info >= (3, 8):
- ipattern = ipattern38
- str, pattern = istr, ipattern
- while '$' in pattern:
- i = pattern.index('$')
- assert str[:i] == pattern[:i]
- j = str.find(pattern[i+1], i)
- assert i + 1 <= j <= str.find('\n', i)
- str = str[j:]
- pattern = pattern[i+1:]
- assert str == pattern
- return True
- def check_value(x):
- if x == 10000:
- raise ValueError(42)
- def Zcb1(x):
- check_value(x)
- return x * 3
- BShort = new_primitive_type("short")
- BFunc = new_function_type((BShort,), BShort, False)
- f = callback(BFunc, Zcb1, -42)
- #
- seen = []
- oops_result = None
- def oops(*args):
- seen.append(args)
- return oops_result
- ff = callback(BFunc, Zcb1, -42, oops)
- #
- orig_stderr = sys.stderr
- orig_getline = linecache.getline
- try:
- linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests
- sys.stderr = cStringIO.StringIO()
- if hasattr(sys, '__unraisablehook__'): # work around pytest
- sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons
- assert f(100) == 300
- assert sys.stderr.getvalue() == ''
- assert f(10000) == -42
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Traceback (most recent call last):
- File "$", line $, in Zcb1
- $
- File "$", line $, in check_value
- $
-ValueError: 42
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>:
-Traceback (most recent call last):
- File "$", line $, in Zcb1
- $
- File "$", line $, in check_value
- $
-ValueError: 42
-""")
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- assert f(bigvalue) == -42
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-""")
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- assert len(seen) == 0
- assert ff(bigvalue) == -42
- assert sys.stderr.getvalue() == ""
- assert len(seen) == 1
- exc, val, tb = seen[0]
- assert exc is OverflowError
- assert str(val) == "integer 60000 does not fit 'short'"
- #
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- del seen[:]
- oops_result = 81
- assert ff(bigvalue) == 81
- oops_result = None
- assert sys.stderr.getvalue() == ""
- assert len(seen) == 1
- exc, val, tb = seen[0]
- assert exc is OverflowError
- assert str(val) == "integer 60000 does not fit 'short'"
- #
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- del seen[:]
- oops_result = "xy" # not None and not an int!
- assert ff(bigvalue) == -42
- oops_result = None
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-
-During the call to 'onerror', another exception occurred:
-
-TypeError: $integer$
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-Exception ignored during handling of the above exception by 'onerror':
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-TypeError: $integer$
-""")
- #
- sys.stderr = cStringIO.StringIO()
- seen = "not a list" # this makes the oops() function crash
- assert ff(bigvalue) == -42
- # the $ after the AttributeError message are for the suggestions that
- # will be added in Python 3.10
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-
-During the call to 'onerror', another exception occurred:
-
-Traceback (most recent call last):
- File "$", line $, in oops
- $
-AttributeError: 'str' object has no attribute 'append$
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-Exception ignored during handling of the above exception by 'onerror':
-Traceback (most recent call last):
- File "$", line $, in oops
- $
-AttributeError: 'str' object has no attribute 'append$
-""")
- finally:
- sys.stderr = orig_stderr
- linecache.getline = orig_getline
-
-def test_callback_return_type():
- for rettype in ["signed char", "short", "int", "long", "long long",
- "unsigned char", "unsigned short", "unsigned int",
- "unsigned long", "unsigned long long"]:
- BRet = new_primitive_type(rettype)
- def cb(n):
- return n + 1
- BFunc = new_function_type((BRet,), BRet)
- f = callback(BFunc, cb, 42)
- assert f(41) == 42
- if rettype.startswith("unsigned "):
- min = 0
- max = (1 << (8*sizeof(BRet))) - 1
- else:
- min = -(1 << (8*sizeof(BRet)-1))
- max = (1 << (8*sizeof(BRet)-1)) - 1
- assert f(min) == min + 1
- assert f(max - 1) == max
- assert f(max) == 42
-
-def test_a_lot_of_callbacks():
- BIGNUM = 10000
- if 'PY_DOT_PY' in globals(): BIGNUM = 100 # tests on py.py
- #
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt,), BInt, False)
- def make_callback(m):
- def cb(n):
- return n + m
- return callback(BFunc, cb, 42) # 'cb' goes out of scope
- #
- flist = [make_callback(i) for i in range(BIGNUM)]
- for i, f in enumerate(flist):
- assert f(-142) == -142 + i
-
-def test_callback_receiving_tiny_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BSChar, -1)])
- def cb(s):
- return s.a + 10 * s.b
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, [-2, -4])
- n = f(p[0])
- assert n == -42
-
-def test_callback_returning_tiny_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BSChar, -1)])
- def cb(n):
- return newp(BStructPtr, [-n, -3*n])[0]
- BFunc = new_function_type((BInt,), BStruct)
- f = callback(BFunc, cb)
- s = f(10)
- assert typeof(s) is BStruct
- assert repr(s) == "<cdata 'struct foo' owning 2 bytes>"
- assert s.a == -10
- assert s.b == -30
-
-def test_callback_receiving_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BDouble, -1)])
- def cb(s):
- return s.a + int(s.b)
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, [-2, 44.444])
- n = f(p[0])
- assert n == 42
-
-def test_callback_returning_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BDouble, -1)])
- def cb(n):
- return newp(BStructPtr, [-n, 1E-42])[0]
- BFunc = new_function_type((BInt,), BStruct)
- f = callback(BFunc, cb)
- s = f(10)
- assert typeof(s) is BStruct
- assert repr(s) in ["<cdata 'struct foo' owning 12 bytes>",
- "<cdata 'struct foo' owning 16 bytes>"]
- assert s.a == -10
- assert s.b == 1E-42
-
-def test_callback_receiving_big_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- def cb(s):
- for i, name in enumerate("abcdefghij"):
- assert getattr(s, name) == 13 - i
- return 42
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, list(range(13, 3, -1)))
- n = f(p[0])
- assert n == 42
-
-def test_callback_returning_big_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- def cb():
- return newp(BStructPtr, list(range(13, 3, -1)))[0]
- BFunc = new_function_type((), BStruct)
- f = callback(BFunc, cb)
- s = f()
- assert typeof(s) is BStruct
- assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>",
- "<cdata 'struct foo' owning 80 bytes>"]
- for i, name in enumerate("abcdefghij"):
- assert getattr(s, name) == 13 - i
-
-def test_callback_returning_void():
- BVoid = new_void_type()
- BFunc = new_function_type((), BVoid, False)
- def cb():
- seen.append(42)
- f = callback(BFunc, cb)
- seen = []
- f()
- assert seen == [42]
- py.test.raises(TypeError, callback, BFunc, cb, -42)
-
-def test_enum_type():
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("foo", (), (), BUInt)
- assert repr(BEnum) == "<ctype 'foo'>"
- assert BEnum.kind == "enum"
- assert BEnum.cname == "foo"
- assert BEnum.elements == {}
- #
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- assert BEnum.kind == "enum"
- assert BEnum.cname == "enum foo"
- assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
- # 'elements' is not the real dict, but merely a copy
- BEnum.elements[2] = '??'
- assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
- #
- BEnum = new_enum_type("enum bar", ('ab', 'cd'), (5, 5), BUInt)
- assert BEnum.elements == {5: 'ab'}
- assert BEnum.relements == {'ab': 5, 'cd': 5}
-
-def test_cast_to_enum():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- assert sizeof(BEnum) == sizeof(BInt)
- e = cast(BEnum, 0)
- assert repr(e) == "<cdata 'enum foo' 0: def>"
- assert repr(cast(BEnum, -42)) == "<cdata 'enum foo' -42>"
- assert repr(cast(BEnum, -20)) == "<cdata 'enum foo' -20: ab>"
- assert string(e) == 'def'
- assert string(cast(BEnum, -20)) == 'ab'
- assert int(cast(BEnum, 1)) == 1
- assert int(cast(BEnum, 0)) == 0
- assert int(cast(BEnum, -242 + 2**128)) == -242
- assert string(cast(BEnum, -242 + 2**128)) == '-242'
- #
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("enum bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
- e = cast(BEnum, -1)
- assert repr(e) == "<cdata 'enum bar' 4294967295>" # unsigned int
- #
- BLong = new_primitive_type("long")
- BEnum = new_enum_type("enum baz", (), (), BLong)
- assert sizeof(BEnum) == sizeof(BLong)
- e = cast(BEnum, -1)
- assert repr(e) == "<cdata 'enum baz' -1>"
-
-def test_enum_with_non_injective_mapping():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('ab', 'cd'), (7, 7), BInt)
- e = cast(BEnum, 7)
- assert repr(e) == "<cdata 'enum foo' 7: ab>"
- assert string(e) == 'ab'
-
-def test_enum_in_struct():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- BStruct = new_struct_type("struct bar")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BEnum, -1)])
- p = newp(BStructPtr, [-20])
- assert p.a1 == -20
- p = newp(BStructPtr, [12])
- assert p.a1 == 12
- e = py.test.raises(TypeError, newp, BStructPtr, [None])
- msg = str(e.value)
- assert ("an integer is required" in msg or # CPython
- "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys
- "expected integer, got NoneType object" in msg) # newer PyPys
- with pytest.raises(TypeError):
- p.a1 = "def"
- if sys.version_info < (3,):
- BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt)
- assert string(cast(BEnum2, 5)) == 'abc'
- assert type(string(cast(BEnum2, 5))) is str
-
-def test_enum_overflow():
- max_uint = 2 ** (size_of_int()*8) - 1
- max_int = max_uint // 2
- max_ulong = 2 ** (size_of_long()*8) - 1
- max_long = max_ulong // 2
- for BPrimitive in [new_primitive_type("int"),
- new_primitive_type("unsigned int"),
- new_primitive_type("long"),
- new_primitive_type("unsigned long")]:
- for x in [max_uint, max_int, max_ulong, max_long]:
- for testcase in [x, x+1, -x-1, -x-2]:
- if int(cast(BPrimitive, testcase)) == testcase:
- # fits
- BEnum = new_enum_type("foo", ("AA",), (testcase,),
- BPrimitive)
- assert int(cast(BEnum, testcase)) == testcase
- else:
- # overflows
- py.test.raises(OverflowError, new_enum_type,
- "foo", ("AA",), (testcase,), BPrimitive)
-
-def test_callback_returning_enum():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- def cb(n):
- if n & 1:
- return cast(BEnum, n)
- else:
- return n
- BFunc = new_function_type((BInt,), BEnum)
- f = callback(BFunc, cb)
- assert f(0) == 0
- assert f(1) == 1
- assert f(-20) == -20
- assert f(20) == 20
- assert f(21) == 21
-
-def test_callback_returning_enum_unsigned():
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
- def cb(n):
- if n & 1:
- return cast(BEnum, n)
- else:
- return n
- BFunc = new_function_type((BInt,), BEnum)
- f = callback(BFunc, cb)
- assert f(0) == 0
- assert f(1) == 1
- assert f(-21) == 2**32 - 21
- assert f(20) == 20
- assert f(21) == 21
-
-def test_callback_returning_char():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- def cb(n):
- return bytechr(n)
- BFunc = new_function_type((BInt,), BChar)
- f = callback(BFunc, cb)
- assert f(0) == b'\x00'
- assert f(255) == b'\xFF'
-
-def _hacked_pypy_uni4():
- pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
- return 'PY_DOT_PY' in globals() and not pyuni4
-
-def test_callback_returning_wchar_t():
- BInt = new_primitive_type("int")
- BWChar = new_primitive_type("wchar_t")
- def cb(n):
- if n == -1:
- return u+'\U00012345'
- if n == -2:
- raise ValueError
- return unichr(n)
- BFunc = new_function_type((BInt,), BWChar)
- f = callback(BFunc, cb)
- assert f(0) == unichr(0)
- assert f(255) == unichr(255)
- assert f(0x1234) == u+'\u1234'
- if sizeof(BWChar) == 4 and not _hacked_pypy_uni4():
- assert f(-1) == u+'\U00012345'
- assert f(-2) == u+'\x00' # and an exception printed to stderr
-
-def test_struct_with_bitfields():
- BLong = new_primitive_type("long")
- BStruct = new_struct_type("struct foo")
- LONGBITS = 8 * sizeof(BLong)
- complete_struct_or_union(BStruct, [('a1', BLong, 1),
- ('a2', BLong, 2),
- ('a3', BLong, 3),
- ('a4', BLong, LONGBITS - 5)])
- d = BStruct.fields
- assert d[0][1].offset == d[1][1].offset == d[2][1].offset == 0
- assert d[3][1].offset == sizeof(BLong)
- def f(m, r):
- if sys.byteorder == 'little':
- return r
- else:
- return LONGBITS - m - r
- assert d[0][1].bitshift == f(1, 0)
- assert d[0][1].bitsize == 1
- assert d[1][1].bitshift == f(2, 1)
- assert d[1][1].bitsize == 2
- assert d[2][1].bitshift == f(3, 3)
- assert d[2][1].bitsize == 3
- assert d[3][1].bitshift == f(LONGBITS - 5, 0)
- assert d[3][1].bitsize == LONGBITS - 5
- assert sizeof(BStruct) == 2 * sizeof(BLong)
- assert alignof(BStruct) == alignof(BLong)
-
-def test_bitfield_instance():
- BInt = new_primitive_type("int")
- BUnsignedInt = new_primitive_type("unsigned int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 1),
- ('a2', BUnsignedInt, 2),
- ('a3', BInt, 3)])
- p = newp(new_pointer_type(BStruct), None)
- p.a1 = -1
- assert p.a1 == -1
- p.a1 = 0
- with pytest.raises(OverflowError):
- p.a1 = 2
- assert p.a1 == 0
- #
- p.a1 = -1
- p.a2 = 3
- p.a3 = -4
- with pytest.raises(OverflowError):
- p.a3 = 4
- with pytest.raises(OverflowError) as e:
- p.a3 = -5
- assert str(e.value) == ("value -5 outside the range allowed by the "
- "bit field width: -4 <= x <= 3")
- assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4
- #
- # special case for convenience: "int x:1", while normally signed,
- # allows also setting the value "1" (it still gets read back as -1)
- p.a1 = 1
- assert p.a1 == -1
- with pytest.raises(OverflowError) as e:
- p.a1 = -2
- assert str(e.value) == ("value -2 outside the range allowed by the "
- "bit field width: -1 <= x <= 1")
-
-def test_bitfield_instance_init():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 1)])
- p = newp(new_pointer_type(BStruct), [-1])
- assert p.a1 == -1
- p = newp(new_pointer_type(BStruct), {'a1': -1})
- assert p.a1 == -1
- #
- BUnion = new_union_type("union bar")
- complete_struct_or_union(BUnion, [('a1', BInt, 1)])
- p = newp(new_pointer_type(BUnion), [-1])
- assert p.a1 == -1
-
-def test_weakref():
- import _weakref
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- rlist = [_weakref.ref(BInt),
- _weakref.ref(newp(BPtr, 42)),
- _weakref.ref(cast(BPtr, 42)),
- _weakref.ref(cast(BInt, 42)),
- _weakref.ref(buffer(newp(BPtr, 42))),
- ]
- for i in range(5):
- import gc; gc.collect()
- if [r() for r in rlist] == [None for r in rlist]:
- break
-
-def test_no_inheritance():
- BInt = new_primitive_type("int")
- try:
- class foo(type(BInt)): pass
- except TypeError:
- pass
- else:
- raise AssertionError
- x = cast(BInt, 42)
- try:
- class foo(type(x)): pass
- except TypeError:
- pass
- else:
- raise AssertionError
-
-def test_assign_string():
- BChar = new_primitive_type("char")
- BArray1 = new_array_type(new_pointer_type(BChar), 5)
- BArray2 = new_array_type(new_pointer_type(BArray1), 5)
- a = newp(BArray2, [b"abc", b"de", b"ghij"])
- assert string(a[1]) == b"de"
- assert string(a[2]) == b"ghij"
- a[2] = b"."
- assert string(a[2]) == b"."
- a[2] = b"12345"
- assert string(a[2]) == b"12345"
- with pytest.raises(IndexError) as e:
- a[2] = b"123456"
- assert 'char[5]' in str(e.value)
- assert 'got 6 characters' in str(e.value)
-
-def test_add_error():
- x = cast(new_primitive_type("int"), 42)
- with pytest.raises(TypeError):
- x + 1
- with pytest.raises(TypeError):
- x - 1
-
-def test_void_errors():
- py.test.raises(ValueError, alignof, new_void_type())
- py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None)
-
-def test_too_many_items():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 5)
- py.test.raises(IndexError, newp, BArray, tuple(b'123456'))
- py.test.raises(IndexError, newp, BArray, list(b'123456'))
- py.test.raises(IndexError, newp, BArray, b'123456')
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [])
- py.test.raises(TypeError, newp, new_pointer_type(BStruct), b'')
- py.test.raises(ValueError, newp, new_pointer_type(BStruct), [b'1'])
-
-def test_more_type_errors():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 5)
- py.test.raises(TypeError, newp, BArray, 12.34)
- BArray = new_array_type(new_pointer_type(BInt), 5)
- py.test.raises(TypeError, newp, BArray, 12.34)
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, cast, BFloat, newp(BArray, None))
-
-def test_more_overflow_errors():
- BUInt = new_primitive_type("unsigned int")
- py.test.raises(OverflowError, newp, new_pointer_type(BUInt), -1)
- py.test.raises(OverflowError, newp, new_pointer_type(BUInt), 2**32)
-
-def test_newp_copying():
- """Test that we can do newp(<type>, <cdata of the given type>) for most
- types, including same-type arrays.
- """
- BInt = new_primitive_type("int")
- p = newp(new_pointer_type(BInt), cast(BInt, 42))
- assert p[0] == 42
- #
- BUInt = new_primitive_type("unsigned int")
- p = newp(new_pointer_type(BUInt), cast(BUInt, 42))
- assert p[0] == 42
- #
- BChar = new_primitive_type("char")
- p = newp(new_pointer_type(BChar), cast(BChar, '!'))
- assert p[0] == b'!'
- #
- BFloat = new_primitive_type("float")
- p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25))
- assert p[0] == 12.25
- #
- BStruct = new_struct_type("struct foo_s")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1)])
- s1 = newp(BStructPtr, [42])
- p1 = newp(new_pointer_type(BStructPtr), s1)
- assert p1[0] == s1
- #
- BArray = new_array_type(new_pointer_type(BInt), None)
- a1 = newp(BArray, [1, 2, 3, 4])
- py.test.raises(TypeError, newp, BArray, a1)
- BArray6 = new_array_type(new_pointer_type(BInt), 6)
- a1 = newp(BArray6, [10, 20, 30])
- a2 = newp(BArray6, a1)
- assert list(a2) == [10, 20, 30, 0, 0, 0]
- #
- s1 = newp(BStructPtr, [42])
- s2 = newp(BStructPtr, s1[0])
- assert s2.a1 == 42
- #
- BUnion = new_union_type("union foo_u")
- BUnionPtr = new_pointer_type(BUnion)
- complete_struct_or_union(BUnion, [('a1', BInt, -1)])
- u1 = newp(BUnionPtr, [42])
- u2 = newp(BUnionPtr, u1[0])
- assert u2.a1 == 42
- #
- BFunc = new_function_type((BInt,), BUInt)
- p1 = cast(BFunc, 42)
- p2 = newp(new_pointer_type(BFunc), p1)
- assert p2[0] == p1
-
-def test_string():
- BChar = new_primitive_type("char")
- assert string(cast(BChar, 42)) == b'*'
- assert string(cast(BChar, 0)) == b'\x00'
- BCharP = new_pointer_type(BChar)
- BArray = new_array_type(BCharP, 10)
- a = newp(BArray, b"hello")
- assert len(a) == 10
- assert string(a) == b"hello"
- p = a + 2
- assert string(p) == b"llo"
- assert string(newp(new_array_type(BCharP, 4), b"abcd")) == b"abcd"
- py.test.raises(RuntimeError, string, cast(BCharP, 0))
- assert string(a, 4) == b"hell"
- assert string(a, 5) == b"hello"
- assert string(a, 6) == b"hello"
-
-def test_string_byte():
- BByte = new_primitive_type("signed char")
- assert string(cast(BByte, 42)) == b'*'
- assert string(cast(BByte, 0)) == b'\x00'
- BArray = new_array_type(new_pointer_type(BByte), None)
- a = newp(BArray, [65, 66, 67])
- assert type(string(a)) is bytes and string(a) == b'ABC'
- #
- BByte = new_primitive_type("unsigned char")
- assert string(cast(BByte, 42)) == b'*'
- assert string(cast(BByte, 0)) == b'\x00'
- BArray = new_array_type(new_pointer_type(BByte), None)
- a = newp(BArray, [65, 66, 67])
- assert type(string(a)) is bytes and string(a) == b'ABC'
- if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
- assert string(a, 8).startswith(b'ABC') # may contain additional garbage
-
-def test_string_wchar():
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- _test_string_wchar_variant(typename)
-
-def _test_string_wchar_variant(typename):
- BWChar = new_primitive_type(typename)
- assert string(cast(BWChar, 42)) == u+'*'
- assert string(cast(BWChar, 0x4253)) == u+'\u4253'
- assert string(cast(BWChar, 0)) == u+'\x00'
- BArray = new_array_type(new_pointer_type(BWChar), None)
- a = newp(BArray, [u+'A', u+'B', u+'C'])
- assert type(string(a)) is unicode and string(a) == u+'ABC'
- if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
- try:
- # may contain additional garbage
- assert string(a, 8).startswith(u+'ABC')
- except ValueError: # garbage contains values > 0x10FFFF
- assert sizeof(BWChar) == 4
-
-def test_string_typeerror():
- BShort = new_primitive_type("short")
- BArray = new_array_type(new_pointer_type(BShort), None)
- a = newp(BArray, [65, 66, 67])
- py.test.raises(TypeError, string, a)
-
-def test_bug_convert_to_ptr():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BDouble = new_primitive_type("double")
- x = cast(BDouble, 42)
- py.test.raises(TypeError, newp, new_pointer_type(BCharP), x)
-
-def test_set_struct_fields():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharArray10 = new_array_type(BCharP, 10)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BCharArray10, -1)])
- p = newp(BStructPtr, None)
- assert string(p.a1) == b''
- p.a1 = b'foo'
- assert string(p.a1) == b'foo'
- assert list(p.a1) == [b'f', b'o', b'o'] + [b'\x00'] * 7
- p.a1 = [b'x', b'y']
- assert string(p.a1) == b'xyo'
-
-def test_invalid_function_result_types():
- BFunc = new_function_type((), new_void_type())
- BArray = new_array_type(new_pointer_type(BFunc), 5) # works
- new_function_type((), BFunc) # works
- new_function_type((), new_primitive_type("int"))
- new_function_type((), new_pointer_type(BFunc))
- BUnion = new_union_type("union foo_u")
- complete_struct_or_union(BUnion, [])
- BFunc = new_function_type((), BUnion)
- py.test.raises(NotImplementedError, cast(BFunc, 123))
- py.test.raises(TypeError, new_function_type, (), BArray)
-
-def test_struct_return_in_func():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo_s")
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc10 = new_function_type((BInt,), BStruct)
- f = cast(BFunc10, _testfunc(10))
- s = f(40)
- assert repr(s) == "<cdata 'struct foo_s' owning 4 bytes>"
- assert s.a1 == bytechr(40)
- assert s.a2 == 40 * 40
- #
- BStruct11 = new_struct_type("struct test11")
- complete_struct_or_union(BStruct11, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- BFunc11 = new_function_type((BInt,), BStruct11)
- f = cast(BFunc11, _testfunc(11))
- s = f(40)
- assert repr(s) == "<cdata 'struct test11' owning 8 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40 * 40
- #
- BStruct12 = new_struct_type("struct test12")
- complete_struct_or_union(BStruct12, [('a1', BDouble, -1),
- ])
- BFunc12 = new_function_type((BInt,), BStruct12)
- f = cast(BFunc12, _testfunc(12))
- s = f(40)
- assert repr(s) == "<cdata 'struct test12' owning 8 bytes>"
- assert s.a1 == 40.0
- #
- BStruct13 = new_struct_type("struct test13")
- complete_struct_or_union(BStruct13, [('a1', BInt, -1),
- ('a2', BInt, -1),
- ('a3', BInt, -1)])
- BFunc13 = new_function_type((BInt,), BStruct13)
- f = cast(BFunc13, _testfunc(13))
- s = f(40)
- assert repr(s) == "<cdata 'struct test13' owning 12 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40 * 40
- assert s.a3 == 40 * 40 * 40
- #
- BStruct14 = new_struct_type("struct test14")
- complete_struct_or_union(BStruct14, [('a1', BFloat, -1),
- ])
- BFunc14 = new_function_type((BInt,), BStruct14)
- f = cast(BFunc14, _testfunc(14))
- s = f(40)
- assert repr(s) == "<cdata 'struct test14' owning 4 bytes>"
- assert s.a1 == 40.0
- #
- BStruct15 = new_struct_type("struct test15")
- complete_struct_or_union(BStruct15, [('a1', BFloat, -1),
- ('a2', BInt, -1)])
- BFunc15 = new_function_type((BInt,), BStruct15)
- f = cast(BFunc15, _testfunc(15))
- s = f(40)
- assert repr(s) == "<cdata 'struct test15' owning 8 bytes>"
- assert s.a1 == 40.0
- assert s.a2 == 40 * 40
- #
- BStruct16 = new_struct_type("struct test16")
- complete_struct_or_union(BStruct16, [('a1', BFloat, -1),
- ('a2', BFloat, -1)])
- BFunc16 = new_function_type((BInt,), BStruct16)
- f = cast(BFunc16, _testfunc(16))
- s = f(40)
- assert repr(s) == "<cdata 'struct test16' owning 8 bytes>"
- assert s.a1 == 40.0
- assert s.a2 == -40.0
- #
- BStruct17 = new_struct_type("struct test17")
- complete_struct_or_union(BStruct17, [('a1', BInt, -1),
- ('a2', BFloat, -1)])
- BFunc17 = new_function_type((BInt,), BStruct17)
- f = cast(BFunc17, _testfunc(17))
- s = f(40)
- assert repr(s) == "<cdata 'struct test17' owning 8 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40.0 * 40.0
- #
- BStruct17Ptr = new_pointer_type(BStruct17)
- BFunc18 = new_function_type((BStruct17Ptr,), BInt)
- f = cast(BFunc18, _testfunc(18))
- x = f([[40, 2.5]])
- assert x == 42
- x = f([{'a2': 43.1}])
- assert x == 43
-
-def test_cast_with_functionptr():
- BFunc = new_function_type((), new_void_type())
- BFunc2 = new_function_type((), new_primitive_type("short"))
- BCharP = new_pointer_type(new_primitive_type("char"))
- BIntP = new_pointer_type(new_primitive_type("int"))
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BFunc, -1)])
- newp(BStructPtr, [cast(BFunc, 0)])
- newp(BStructPtr, [cast(BCharP, 0)])
- py.test.raises(TypeError, newp, BStructPtr, [cast(BIntP, 0)])
- py.test.raises(TypeError, newp, BStructPtr, [cast(BFunc2, 0)])
-
-def test_wchar():
- _test_wchar_variant("wchar_t")
- if sys.platform.startswith("linux"):
- BWChar = new_primitive_type("wchar_t")
- assert sizeof(BWChar) == 4
- # wchar_t is often signed on Linux, but not always (e.g. on ARM)
- assert int(cast(BWChar, -1)) in (-1, 4294967295)
-
-def test_char16():
- BChar16 = new_primitive_type("char16_t")
- assert sizeof(BChar16) == 2
- _test_wchar_variant("char16_t")
- assert int(cast(BChar16, -1)) == 0xffff # always unsigned
-
-def test_char32():
- BChar32 = new_primitive_type("char32_t")
- assert sizeof(BChar32) == 4
- _test_wchar_variant("char32_t")
- assert int(cast(BChar32, -1)) == 0xffffffff # always unsigned
-
-def _test_wchar_variant(typename):
- BWChar = new_primitive_type(typename)
- BInt = new_primitive_type("int")
- pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
- wchar4 = {2: False, 4: True}[sizeof(BWChar)]
- assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % (
- typename, mandatory_u_prefix)
- assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % (
- typename, mandatory_u_prefix)
- if not _hacked_pypy_uni4():
- if wchar4:
- x = cast(BWChar, 0x12345)
- assert str(x) == "<cdata '%s' %s'\U00012345'>" % (
- typename, mandatory_u_prefix)
- assert int(x) == 0x12345
- else:
- x = cast(BWChar, 0x18345)
- assert str(x) == "<cdata '%s' %s'\u8345'>" % (
- typename, mandatory_u_prefix)
- assert int(x) == 0x8345
- #
- BWCharP = new_pointer_type(BWChar)
- BStruct = new_struct_type("struct foo_s")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BWChar, -1),
- ('a2', BWCharP, -1)])
- s = newp(BStructPtr)
- s.a1 = u+'\x00'
- assert s.a1 == u+'\x00'
- with pytest.raises(TypeError):
- s.a1 = b'a'
- with pytest.raises(TypeError):
- s.a1 = bytechr(0xFF)
- s.a1 = u+'\u1234'
- assert s.a1 == u+'\u1234'
- if pyuni4:
- if wchar4:
- s.a1 = u+'\U00012345'
- assert s.a1 == u+'\U00012345'
- elif wchar4:
- if not _hacked_pypy_uni4():
- s.a1 = cast(BWChar, 0x12345)
- assert s.a1 == u+'\ud808\udf45'
- s.a1 = u+'\ud807\udf44'
- assert s.a1 == u+'\U00011f44'
- else:
- with pytest.raises(TypeError):
- s.a1 = u+'\U00012345'
- #
- BWCharArray = new_array_type(BWCharP, None)
- a = newp(BWCharArray, u+'hello \u1234 world')
- assert len(a) == 14 # including the final null
- assert string(a) == u+'hello \u1234 world'
- a[13] = u+'!'
- assert string(a) == u+'hello \u1234 world!'
- assert str(a) == repr(a)
- assert a[6] == u+'\u1234'
- a[6] = u+'-'
- assert string(a) == u+'hello - world!'
- assert str(a) == repr(a)
- #
- if wchar4 and not _hacked_pypy_uni4():
- u1 = u+'\U00012345\U00012346\U00012347'
- a = newp(BWCharArray, u1)
- assert len(a) == 4
- assert string(a) == u1
- assert len(list(a)) == 4
- expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)]
- assert list(a) == expected
- got = [a[i] for i in range(4)]
- assert got == expected
- with pytest.raises(IndexError):
- a[4]
- #
- w = cast(BWChar, 'a')
- assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'a'
- assert int(w) == ord('a')
- w = cast(BWChar, 0x1234)
- assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\u1234'
- assert int(w) == 0x1234
- w = cast(BWChar, u+'\u8234')
- assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\u8234'
- assert int(w) == 0x8234
- w = cast(BInt, u+'\u1234')
- assert repr(w) == "<cdata 'int' 4660>"
- if wchar4 and not _hacked_pypy_uni4():
- w = cast(BWChar, u+'\U00012345')
- assert repr(w) == "<cdata '%s' %s'\U00012345'>" % (
- typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\U00012345'
- assert int(w) == 0x12345
- w = cast(BInt, u+'\U00012345')
- assert repr(w) == "<cdata 'int' 74565>"
- py.test.raises(TypeError, cast, BInt, u+'')
- py.test.raises(TypeError, cast, BInt, u+'XX')
- assert int(cast(BInt, u+'a')) == ord('a')
- #
- a = newp(BWCharArray, u+'hello - world')
- p = cast(BWCharP, a)
- assert string(p) == u+'hello - world'
- p[6] = u+'\u2345'
- assert string(p) == u+'hello \u2345 world'
- #
- s = newp(BStructPtr, [u+'\u1234', p])
- assert s.a1 == u+'\u1234'
- assert s.a2 == p
- assert str(s.a2) == repr(s.a2)
- assert string(s.a2) == u+'hello \u2345 world'
- #
- q = cast(BWCharP, 0)
- assert str(q) == repr(q)
- py.test.raises(RuntimeError, string, q)
- #
- def cb(p):
- assert repr(p).startswith("<cdata '%s *' 0x" % typename)
- return len(string(p))
- BFunc = new_function_type((BWCharP,), BInt, False)
- f = callback(BFunc, cb, -42)
- assert f(u+'a\u1234b') == 3
- #
- if wchar4 and not pyuni4 and not _hacked_pypy_uni4():
- # try out-of-range wchar_t values
- x = cast(BWChar, 1114112)
- py.test.raises(ValueError, string, x)
- x = cast(BWChar, -1)
- py.test.raises(ValueError, string, x)
-
-def test_wchar_variants_mix():
- BWChar = new_primitive_type("wchar_t")
- BChar16 = new_primitive_type("char16_t")
- BChar32 = new_primitive_type("char32_t")
- assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe
- assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe
- assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345
- assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345
- #
- BChar16A = new_array_type(new_pointer_type(BChar16), None)
- BChar32A = new_array_type(new_pointer_type(BChar32), None)
- x = cast(BChar32, 'A')
- py.test.raises(TypeError, newp, BChar16A, [x])
- x = cast(BChar16, 'A')
- py.test.raises(TypeError, newp, BChar32A, [x])
- #
- a = newp(BChar16A, u+'\U00012345')
- assert len(a) == 3
- a = newp(BChar32A, u+'\U00012345')
- assert len(a) == 2 # even if the Python unicode string above is 2 chars
-
-def test_keepalive_struct():
- # exception to the no-keepalive rule: p=newp(BStructPtr) returns a
- # pointer owning the memory, and p[0] returns a pointer to the
- # struct that *also* owns the memory
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1),
- ('a2', new_primitive_type("int"), -1),
- ('a3', new_primitive_type("int"), -1)])
- p = newp(BStructPtr)
- assert repr(p) == "<cdata 'struct foo *' owning 12 bytes>"
- q = p[0]
- assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
- q.a1 = 123456
- assert p.a1 == 123456
- r = cast(BStructPtr, p)
- assert repr(r[0]).startswith("<cdata 'struct foo &' 0x")
- del p
- import gc; gc.collect()
- assert q.a1 == 123456
- assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
- assert q.a1 == 123456
-
-def test_nokeepalive_struct():
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- BStructPtrPtr = new_pointer_type(BStructPtr)
- complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1)])
- p = newp(BStructPtr)
- pp = newp(BStructPtrPtr)
- pp[0] = p
- s = pp[0][0]
- assert repr(s).startswith("<cdata 'struct foo &' 0x")
-
-def test_owning_repr():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), None) # int[]
- p = newp(BArray, 7)
- assert repr(p) == "<cdata 'int[]' owning 28 bytes>"
- assert sizeof(p) == 28
- #
- BArray = new_array_type(new_pointer_type(BInt), 7) # int[7]
- p = newp(BArray, None)
- assert repr(p) == "<cdata 'int[7]' owning 28 bytes>"
- assert sizeof(p) == 28
-
-def test_cannot_dereference_void():
- BVoidP = new_pointer_type(new_void_type())
- p = cast(BVoidP, 123456)
- with pytest.raises(TypeError):
- p[0]
- p = cast(BVoidP, 0)
- with pytest.raises((TypeError, RuntimeError)):
- p[0]
-
-def test_iter():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None) # int[]
- p = newp(BArray, 7)
- assert list(p) == list(iter(p)) == [0] * 7
- #
- py.test.raises(TypeError, iter, cast(BInt, 5))
- py.test.raises(TypeError, iter, cast(BIntP, 123456))
-
-def test_cmp():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BVoidP = new_pointer_type(new_void_type())
- p = newp(BIntP, 123)
- q = cast(BInt, 124)
- assert (p == q) is False
- assert (p != q) is True
- assert (q == p) is False
- assert (q != p) is True
- if strict_compare:
- with pytest.raises(TypeError): p < q
- with pytest.raises(TypeError): p <= q
- with pytest.raises(TypeError): q < p
- with pytest.raises(TypeError): q <= p
- with pytest.raises(TypeError): p > q
- with pytest.raises(TypeError): p >= q
- r = cast(BVoidP, p)
- assert (p < r) is False
- assert (p <= r) is True
- assert (p == r) is True
- assert (p != r) is False
- assert (p > r) is False
- assert (p >= r) is True
- s = newp(BIntP, 125)
- assert (p == s) is False
- assert (p != s) is True
- assert (p < s) is (p <= s) is (s > p) is (s >= p)
- assert (p > s) is (p >= s) is (s < p) is (s <= p)
- assert (p < s) ^ (p > s)
-
-def test_buffer():
- try:
- import __builtin__
- except ImportError:
- import builtins as __builtin__
- BShort = new_primitive_type("short")
- s = newp(new_pointer_type(BShort), 100)
- assert sizeof(s) == size_of_ptr()
- assert sizeof(BShort) == 2
- assert len(buffer(s)) == 2
- #
- BChar = new_primitive_type("char")
- BCharArray = new_array_type(new_pointer_type(BChar), None)
- c = newp(BCharArray, b"hi there")
- #
- buf = buffer(c)
- assert repr(buf).startswith('<_cffi_backend.buffer object at 0x')
- assert bytes(buf) == b"hi there\x00"
- assert type(buf) is buffer
- if sys.version_info < (3,):
- assert str(buf) == "hi there\x00"
- assert unicode(buf) == u+"hi there\x00"
- else:
- assert str(buf) == repr(buf)
- # --mb_length--
- assert len(buf) == len(b"hi there\x00")
- # --mb_item--
- for i in range(-12, 12):
- try:
- expected = b"hi there\x00"[i]
- except IndexError:
- with pytest.raises(IndexError):
- buf[i]
- else:
- assert buf[i] == bitem2bchr(expected)
- # --mb_slice--
- assert buf[:] == b"hi there\x00"
- for i in range(-12, 12):
- assert buf[i:] == b"hi there\x00"[i:]
- assert buf[:i] == b"hi there\x00"[:i]
- for j in range(-12, 12):
- assert buf[i:j] == b"hi there\x00"[i:j]
- # --misc--
- assert list(buf) == list(map(bitem2bchr, b"hi there\x00"))
- # --mb_as_buffer--
- if hasattr(__builtin__, 'buffer'): # Python <= 2.7
- py.test.raises(TypeError, __builtin__.buffer, c)
- bf1 = __builtin__.buffer(buf)
- assert len(bf1) == len(buf) and bf1[3] == "t"
- if hasattr(__builtin__, 'memoryview'): # Python >= 2.7
- py.test.raises(TypeError, memoryview, c)
- mv1 = memoryview(buf)
- assert len(mv1) == len(buf) and mv1[3] in (b"t", ord(b"t"))
- # --mb_ass_item--
- expected = list(map(bitem2bchr, b"hi there\x00"))
- for i in range(-12, 12):
- try:
- expected[i] = bytechr(i & 0xff)
- except IndexError:
- with pytest.raises(IndexError):
- buf[i] = bytechr(i & 0xff)
- else:
- buf[i] = bytechr(i & 0xff)
- assert list(buf) == expected
- # --mb_ass_slice--
- buf[:] = b"hi there\x00"
- assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00"))
- with pytest.raises(ValueError):
- buf[:] = b"shorter"
- with pytest.raises(ValueError):
- buf[:] = b"this is much too long!"
- buf[4:2] = b"" # no effect, but should work
- assert buf[:] == b"hi there\x00"
- buf[:2] = b"HI"
- assert buf[:] == b"HI there\x00"
- buf[:2] = b"hi"
- expected = list(map(bitem2bchr, b"hi there\x00"))
- x = 0
- for i in range(-12, 12):
- for j in range(-12, 12):
- start = i if i >= 0 else i + len(buf)
- stop = j if j >= 0 else j + len(buf)
- start = max(0, min(len(buf), start))
- stop = max(0, min(len(buf), stop))
- sample = bytechr(x & 0xff) * (stop - start)
- x += 1
- buf[i:j] = sample
- expected[i:j] = map(bitem2bchr, sample)
- assert list(buf) == expected
-
-def test_getcname():
- BUChar = new_primitive_type("unsigned char")
- BArray = new_array_type(new_pointer_type(BUChar), 123)
- assert getcname(BArray, "<-->") == "unsigned char<-->[123]"
-
-def test_errno():
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid)
- f = cast(BFunc5, _testfunc(5))
- set_errno(50)
- f()
- assert get_errno() == 65
- f(); f()
- assert get_errno() == 95
-
-def test_errno_callback():
- if globals().get('PY_DOT_PY'):
- py.test.skip("cannot run this test on py.py (e.g. fails on Windows)")
- set_errno(95)
- def cb():
- e = get_errno()
- set_errno(e - 6)
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid)
- f = callback(BFunc5, cb)
- f()
- assert get_errno() == 89
- f(); f()
- assert get_errno() == 77
-
-def test_cast_to_array():
- # not valid in C! extension to get a non-owning <cdata 'int[3]'>
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, 3)
- x = cast(BArray, 0)
- assert repr(x) == "<cdata 'int[3]' NULL>"
-
-def test_cast_invalid():
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [])
- p = cast(new_pointer_type(BStruct), 123456)
- s = p[0]
- py.test.raises(TypeError, cast, BStruct, s)
-
-def test_bug_float_convertion():
- BDouble = new_primitive_type("double")
- BDoubleP = new_pointer_type(BDouble)
- py.test.raises(TypeError, newp, BDoubleP, "foobar")
-
-def test_bug_delitem():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- x = newp(BCharP)
- with pytest.raises(TypeError):
- del x[0]
-
-def test_bug_delattr():
- BLong = new_primitive_type("long")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BLong, -1)])
- x = newp(new_pointer_type(BStruct))
- with pytest.raises(AttributeError):
- del x.a1
-
-def test_variable_length_struct():
- py.test.skip("later")
- BLong = new_primitive_type("long")
- BArray = new_array_type(new_pointer_type(BLong), None)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BArray, -1)])
- assert sizeof(BStruct) == size_of_long()
- assert alignof(BStruct) == alignof(BLong)
- #
- py.test.raises(TypeError, newp, BStructP, None)
- x = newp(BStructP, 5)
- assert sizeof(x) == 6 * size_of_long()
- x[4] = 123
- assert x[4] == 123
- with pytest.raises(IndexError):
- x[5]
- assert len(x.a2) == 5
- #
- py.test.raises(TypeError, newp, BStructP, [123])
- x = newp(BStructP, [123, 5])
- assert x.a1 == 123
- assert len(x.a2) == 5
- assert list(x.a2) == [0] * 5
- #
- x = newp(BStructP, {'a2': 5})
- assert x.a1 == 0
- assert len(x.a2) == 5
- assert list(x.a2) == [0] * 5
- #
- x = newp(BStructP, [123, (4, 5)])
- assert x.a1 == 123
- assert len(x.a2) == 2
- assert list(x.a2) == [4, 5]
- #
- x = newp(BStructP, {'a2': (4, 5)})
- assert x.a1 == 0
- assert len(x.a2) == 2
- assert list(x.a2) == [4, 5]
-
-def test_autocast_int():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BLongLong = new_primitive_type("long long")
- BULongLong = new_primitive_type("unsigned long long")
- BULongLongPtr = new_pointer_type(BULongLong)
- x = newp(BIntPtr, cast(BInt, 42))
- assert x[0] == 42
- x = newp(BIntPtr, cast(BLongLong, 42))
- assert x[0] == 42
- x = newp(BIntPtr, cast(BULongLong, 42))
- assert x[0] == 42
- x = newp(BULongLongPtr, cast(BInt, 42))
- assert x[0] == 42
- py.test.raises(OverflowError, newp, BULongLongPtr, cast(BInt, -42))
- x = cast(BInt, cast(BInt, 42))
- assert int(x) == 42
- x = cast(BInt, cast(BLongLong, 42))
- assert int(x) == 42
- x = cast(BInt, cast(BULongLong, 42))
- assert int(x) == 42
- x = cast(BULongLong, cast(BInt, 42))
- assert int(x) == 42
- x = cast(BULongLong, cast(BInt, -42))
- assert int(x) == 2 ** 64 - 42
- x = cast(BIntPtr, cast(BInt, 42))
- assert int(cast(BInt, x)) == 42
-
-def test_autocast_float():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("float")
- BFloatPtr = new_pointer_type(BFloat)
- x = newp(BFloatPtr, cast(BDouble, 12.5))
- assert x[0] == 12.5
- x = cast(BFloat, cast(BDouble, 12.5))
- assert float(x) == 12.5
-
-def test_longdouble():
- py_py = 'PY_DOT_PY' in globals()
- BInt = new_primitive_type("int")
- BLongDouble = new_primitive_type("long double")
- BLongDoublePtr = new_pointer_type(BLongDouble)
- BLongDoubleArray = new_array_type(BLongDoublePtr, None)
- a = newp(BLongDoubleArray, 1)
- x = a[0]
- if not py_py:
- assert repr(x).startswith("<cdata 'long double' 0.0")
- assert float(x) == 0.0
- assert int(x) == 0
- #
- b = newp(BLongDoubleArray, [1.23])
- x = b[0]
- if not py_py:
- assert repr(x).startswith("<cdata 'long double' 1.23")
- assert float(x) == 1.23
- assert int(x) == 1
- #
- BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble)
- f = cast(BFunc19, _testfunc(19))
- start = lstart = 1.5
- for i in range(107):
- start = 4 * start - start * start
- lstart = f(lstart, 1)
- lother = f(1.5, 107)
- if not py_py:
- assert float(lstart) == float(lother)
- assert repr(lstart) == repr(lother)
- if sizeof(BLongDouble) > sizeof(new_primitive_type("double")):
- assert float(lstart) != start
- assert repr(lstart).startswith("<cdata 'long double' ")
- #
- c = newp(BLongDoubleArray, [lstart])
- x = c[0]
- assert float(f(lstart, 107)) == float(f(x, 107))
-
-def test_get_array_of_length_zero():
- for length in [0, 5, 10]:
- BLong = new_primitive_type("long")
- BLongP = new_pointer_type(BLong)
- BArray0 = new_array_type(BLongP, length)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BArray0, -1)])
- p = newp(BStructPtr, None)
- if length == 0:
- assert repr(p.a1).startswith("<cdata 'long *' 0x")
- else:
- assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length)
-
-def test_nested_anonymous_struct():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- BInnerStruct = new_struct_type("struct foo")
- complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
- ('a2', BChar, -1)])
- complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
- ('a3', BChar, -1)])
- assert sizeof(BInnerStruct) == sizeof(BInt) * 2 # with alignment
- assert sizeof(BStruct) == sizeof(BInt) * 3 # 'a3' is placed after
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BInt
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BInt)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BChar
- assert d[2][1].offset == sizeof(BInt) * 2
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
-
-def test_nested_anonymous_struct_2():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BInnerUnion = new_union_type("union bar")
- complete_struct_or_union(BInnerUnion, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- complete_struct_or_union(BStruct, [('b1', BInt, -1),
- ('', BInnerUnion, -1),
- ('b2', BInt, -1)])
- assert sizeof(BInnerUnion) == sizeof(BInt)
- assert sizeof(BStruct) == sizeof(BInt) * 3
- fields = [(name, fld.offset, fld.flags) for (name, fld) in BStruct.fields]
- assert fields == [
- ('b1', 0 * sizeof(BInt), 0),
- ('a1', 1 * sizeof(BInt), 0),
- ('a2', 1 * sizeof(BInt), 1),
- ('b2', 2 * sizeof(BInt), 0),
- ]
-
-def test_sizeof_union():
- # a union has the largest alignment of its members, and a total size
- # that is the largest of its items *possibly further aligned* if
- # another smaller item has a larger alignment...
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- assert sizeof(BShort) == alignof(BShort) == 2
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BChar),
- ('a2', BChar),
- ('a3', BChar)])
- assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
- BUnion = new_union_type("union u")
- complete_struct_or_union(BUnion, [('s', BStruct),
- ('i', BShort)])
- assert sizeof(BUnion) == 4
- assert alignof(BUnion) == 2
-
-def test_unaligned_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('b', BInt, -1, 1)],
- None, 5, 1)
-
-def test_CData_CType():
- CData, CType = _get_types()
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- nullchr = cast(BChar, 0)
- chrref = newp(BCharP, None)
- assert isinstance(nullchr, CData)
- assert isinstance(chrref, CData)
- assert not isinstance(BChar, CData)
- assert not isinstance(nullchr, CType)
- assert not isinstance(chrref, CType)
- assert isinstance(BChar, CType)
-
-def test_no_cdata_float():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BUInt = new_primitive_type("unsigned int")
- BUIntP = new_pointer_type(BUInt)
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
- py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
-
-def test_bool():
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- assert int(cast(BBool, False)) == 0
- assert int(cast(BBool, True)) == 1
- assert bool(cast(BBool, False)) is False # since 1.7
- assert bool(cast(BBool, True)) is True
- assert int(cast(BBool, 3)) == 1
- assert int(cast(BBool, long(3))) == 1
- assert int(cast(BBool, long(10)**4000)) == 1
- assert int(cast(BBool, -0.1)) == 1
- assert int(cast(BBool, -0.0)) == 0
- assert int(cast(BBool, '\x00')) == 0
- assert int(cast(BBool, '\xff')) == 1
- assert newp(BBoolP, False)[0] == 0
- assert newp(BBoolP, True)[0] == 1
- assert newp(BBoolP, 0)[0] == 0
- assert newp(BBoolP, 1)[0] == 1
- py.test.raises(TypeError, newp, BBoolP, 1.0)
- py.test.raises(TypeError, newp, BBoolP, '\x00')
- py.test.raises(OverflowError, newp, BBoolP, 2)
- py.test.raises(OverflowError, newp, BBoolP, -1)
- BCharP = new_pointer_type(new_primitive_type("char"))
- p = newp(BCharP, b'\x01')
- q = cast(BBoolP, p)
- assert q[0] is True
- p = newp(BCharP, b'\x00')
- q = cast(BBoolP, p)
- assert q[0] is False
- py.test.raises(TypeError, string, cast(BBool, False))
- BDouble = new_primitive_type("double")
- assert int(cast(BBool, cast(BDouble, 0.1))) == 1
- assert int(cast(BBool, cast(BDouble, 0.0))) == 0
- BBoolA = new_array_type(BBoolP, None)
- p = newp(BBoolA, b'\x01\x00')
- assert p[0] is True
- assert p[1] is False
-
-def test_bool_forbidden_cases():
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- BBoolA = new_array_type(BBoolP, None)
- BCharP = new_pointer_type(new_primitive_type("char"))
- p = newp(BCharP, b'X')
- q = cast(BBoolP, p)
- with pytest.raises(ValueError):
- q[0]
- py.test.raises(TypeError, newp, BBoolP, b'\x00')
- assert newp(BBoolP, 0)[0] is False
- assert newp(BBoolP, 1)[0] is True
- py.test.raises(OverflowError, newp, BBoolP, 2)
- py.test.raises(OverflowError, newp, BBoolP, -1)
- py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02')
- py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2])
- py.test.raises(TypeError, string, newp(BBoolP, 1))
- py.test.raises(TypeError, string, newp(BBoolA, [1]))
-
-def test_typeoffsetof():
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BChar, -1),
- ('a3', BChar, -1)])
- py.test.raises(TypeError, typeoffsetof, BStructPtr, None)
- py.test.raises(TypeError, typeoffsetof, BStruct, None)
- assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0)
- assert typeoffsetof(BStruct, 'a1') == (BChar, 0)
- assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1)
- assert typeoffsetof(BStruct, 'a3') == (BChar, 2)
- assert typeoffsetof(BStructPtr, 'a2', 0) == (BChar, 1)
- assert typeoffsetof(BStruct, u+'a3') == (BChar, 2)
- py.test.raises(TypeError, typeoffsetof, BStructPtr, 'a2', 1)
- py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4')
- py.test.raises(KeyError, typeoffsetof, BStruct, 'a5')
- py.test.raises(TypeError, typeoffsetof, BStruct, 42)
- py.test.raises(TypeError, typeoffsetof, BChar, 'a1')
-
-def test_typeoffsetof_array():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- py.test.raises(TypeError, typeoffsetof, BArray, None)
- py.test.raises(TypeError, typeoffsetof, BArray, 'a1')
- assert typeoffsetof(BArray, 51) == (BInt, 51 * size_of_int())
- assert typeoffsetof(BIntP, 51) == (BInt, 51 * size_of_int())
- assert typeoffsetof(BArray, -51) == (BInt, -51 * size_of_int())
- MAX = sys.maxsize // size_of_int()
- assert typeoffsetof(BArray, MAX) == (BInt, MAX * size_of_int())
- assert typeoffsetof(BIntP, MAX) == (BInt, MAX * size_of_int())
- py.test.raises(OverflowError, typeoffsetof, BArray, MAX + 1)
-
-def test_typeoffsetof_no_bitfield():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 4)])
- py.test.raises(TypeError, typeoffsetof, BStruct, 'a1')
-
-def test_rawaddressof():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BChar, -1),
- ('a3', BChar, -1)])
- p = newp(BStructPtr)
- assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>"
- s = p[0]
- assert repr(s) == "<cdata 'struct foo' owning 3 bytes>"
- a = rawaddressof(BStructPtr, s, 0)
- assert repr(a).startswith("<cdata 'struct foo *' 0x")
- py.test.raises(TypeError, rawaddressof, BStruct, s, 0)
- b = rawaddressof(BCharP, s, 0)
- assert b == cast(BCharP, p)
- c = rawaddressof(BStructPtr, a, 0)
- assert c == a
- py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'), 0)
- #
- d = rawaddressof(BCharP, s, 1)
- assert d == cast(BCharP, p) + 1
- #
- e = cast(BCharP, 109238)
- f = rawaddressof(BCharP, e, 42)
- assert f == e + 42
- #
- BCharA = new_array_type(BCharP, None)
- e = newp(BCharA, 50)
- f = rawaddressof(BCharP, e, 42)
- assert f == e + 42
-
-def test_newp_signed_unsigned_char():
- BCharArray = new_array_type(
- new_pointer_type(new_primitive_type("char")), None)
- p = newp(BCharArray, b"foo")
- assert len(p) == 4
- assert list(p) == [b"f", b"o", b"o", b"\x00"]
- #
- BUCharArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- p = newp(BUCharArray, b"fo\xff")
- assert len(p) == 4
- assert list(p) == [ord("f"), ord("o"), 0xff, 0]
- #
- BSCharArray = new_array_type(
- new_pointer_type(new_primitive_type("signed char")), None)
- p = newp(BSCharArray, b"fo\xff")
- assert len(p) == 4
- assert list(p) == [ord("f"), ord("o"), -1, 0]
-
-def test_newp_from_bytearray_doesnt_work():
- BCharArray = new_array_type(
- new_pointer_type(new_primitive_type("char")), None)
- py.test.raises(TypeError, newp, BCharArray, bytearray(b"foo"))
- p = newp(BCharArray, 5)
- buffer(p)[:] = bytearray(b"foo.\x00")
- assert len(p) == 5
- assert list(p) == [b"f", b"o", b"o", b".", b"\x00"]
- p[1:3] = bytearray(b"XY")
- assert list(p) == [b"f", b"X", b"Y", b".", b"\x00"]
-
-def test_string_assignment_to_byte_array():
- BByteArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- p = newp(BByteArray, 5)
- p[0:3] = bytearray(b"XYZ")
- assert list(p) == [ord("X"), ord("Y"), ord("Z"), 0, 0]
-
-# XXX hack
-if sys.version_info >= (3,):
- try:
- import posix, io
- posix.fdopen = io.open
- except ImportError:
- pass # win32
-
-def test_FILE():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- BFILE = new_struct_type("struct _IO_FILE")
- BFILEP = new_pointer_type(BFILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP, BCharP), BInt, True)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- fscanf = ll.load_function(BFunc2, "fscanf")
- #
- import posix
- fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'rb', 256)
- fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1.write(b"X")
- res = fputs(b"hello world\n", fw1)
- assert res >= 0
- fw1.flush() # should not be needed
- #
- p = newp(new_array_type(BCharP, 100), None)
- res = fscanf(fr1, b"%s\n", p)
- assert res == 1
- assert string(p) == b"Xhello"
- fr1.close()
- fw1.close()
-
-def test_FILE_only_for_FILE_arg():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- B_NOT_FILE = new_struct_type("struct NOT_FILE")
- B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- #
- import posix
- fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'r')
- fw1 = posix.fdopen(fdw, 'w')
- #
- e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
- assert str(e.value).startswith(
- "initializer for ctype 'struct NOT_FILE *' must "
- "be a cdata pointer, not ")
-
-def test_FILE_object():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- BFILE = new_struct_type("FILE")
- BFILEP = new_pointer_type(BFILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP,), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- fileno = ll.load_function(BFunc2, "fileno")
- #
- import posix
- fdr, fdw = posix.pipe()
- fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1p = cast(BFILEP, fw1)
- fw1.write(b"X")
- fw1.flush()
- res = fputs(b"hello\n", fw1p)
- assert res >= 0
- res = fileno(fw1p)
- assert (res == fdw) == (sys.version_info < (3,))
- fw1.close()
- #
- data = posix.read(fdr, 256)
- assert data == b"Xhello\n"
- posix.close(fdr)
-
-def test_errno_saved():
- set_errno(42)
- # a random function that will reset errno to 0 (at least on non-windows)
- import os; os.stat('.')
- #
- res = get_errno()
- assert res == 42
-
-def test_GetLastError():
- if sys.platform != "win32":
- py.test.skip("GetLastError(): only for Windows")
- #
- lib = find_and_load_library('KERNEL32.DLL')
- BInt = new_primitive_type("int")
- BVoid = new_void_type()
- BFunc1 = new_function_type((BInt,), BVoid, False)
- BFunc2 = new_function_type((), BInt, False)
- SetLastError = lib.load_function(BFunc1, "SetLastError")
- GetLastError = lib.load_function(BFunc2, "GetLastError")
- #
- SetLastError(42)
- # a random function that will reset the real GetLastError() to 0
- import nt; nt.stat('.')
- #
- res = GetLastError()
- assert res == 42
- #
- SetLastError(2)
- code, message = getwinerror()
- assert code == 2
- assert message == "The system cannot find the file specified"
- #
- code, message = getwinerror(1155)
- assert code == 1155
- assert message == ("No application is associated with the "
- "specified file for this operation")
-
-def test_nonstandard_integer_types():
- for typename in ['int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
- 'uint32_t', 'int64_t', 'uint64_t', 'intptr_t',
- 'uintptr_t', 'ptrdiff_t', 'size_t', 'ssize_t',
- 'int_least8_t', 'uint_least8_t',
- 'int_least16_t', 'uint_least16_t',
- 'int_least32_t', 'uint_least32_t',
- 'int_least64_t', 'uint_least64_t',
- 'int_fast8_t', 'uint_fast8_t',
- 'int_fast16_t', 'uint_fast16_t',
- 'int_fast32_t', 'uint_fast32_t',
- 'int_fast64_t', 'uint_fast64_t',
- 'intmax_t', 'uintmax_t']:
- new_primitive_type(typename) # works
-
-def test_cannot_convert_unicode_to_charp():
- BCharP = new_pointer_type(new_primitive_type("char"))
- BCharArray = new_array_type(BCharP, None)
- py.test.raises(TypeError, newp, BCharArray, u+'foobar')
-
-def test_buffer_keepalive():
- BCharP = new_pointer_type(new_primitive_type("char"))
- BCharArray = new_array_type(BCharP, None)
- buflist = []
- for i in range(20):
- c = newp(BCharArray, str2bytes("hi there %d" % i))
- buflist.append(buffer(c))
- import gc; gc.collect()
- for i in range(20):
- buf = buflist[i]
- assert buf[:] == str2bytes("hi there %d\x00" % i)
-
-def test_slice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- assert len(c) == 5
- assert repr(c) == "<cdata 'int[]' owning 20 bytes>"
- d = c[1:4]
- assert len(d) == 3
- assert repr(d) == "<cdata 'int[]' sliced length 3>"
- d[0] = 123
- d[2] = 456
- assert c[1] == 123
- assert c[3] == 456
- assert d[2] == 456
- with pytest.raises(IndexError):
- d[3]
- with pytest.raises(IndexError):
- d[-1]
-
-def test_slice_ptr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- d = (c+1)[0:2]
- assert len(d) == 2
- assert repr(d) == "<cdata 'int[]' sliced length 2>"
- d[1] += 50
- assert c[2] == 50
-
-def test_slice_array_checkbounds():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- c[0:5]
- assert len(c[5:5]) == 0
- with pytest.raises(IndexError):
- c[-1:1]
- cp = c + 0
- cp[-1:1]
-
-def test_nonstandard_slice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- with pytest.raises(IndexError) as e:
- c[:5]
- assert str(e.value) == "slice start must be specified"
- with pytest.raises(IndexError) as e:
- c[4:]
- assert str(e.value) == "slice stop must be specified"
- with pytest.raises(IndexError) as e:
- c[1:2:3]
- assert str(e.value) == "slice with step not supported"
- with pytest.raises(IndexError) as e:
- c[1:2:1]
- assert str(e.value) == "slice with step not supported"
- with pytest.raises(IndexError) as e:
- c[4:2]
- assert str(e.value) == "slice start > stop"
- with pytest.raises(IndexError) as e:
- c[6:6]
- assert str(e.value) == "index too large (expected 6 <= 5)"
-
-def test_setslice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- c[1:3] = [100, 200]
- assert list(c) == [0, 100, 200, 0, 0]
- cp = c + 3
- cp[-1:1] = [300, 400]
- assert list(c) == [0, 100, 300, 400, 0]
- cp[-1:1] = iter([500, 600])
- assert list(c) == [0, 100, 500, 600, 0]
- with pytest.raises(ValueError):
- cp[-1:1] = [1000]
- assert list(c) == [0, 100, 1000, 600, 0]
- with pytest.raises(ValueError):
- cp[-1:1] = (700, 800, 900)
- assert list(c) == [0, 100, 700, 800, 0]
-
-def test_setslice_array():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- d = newp(BIntArray, [10, 20, 30])
- c[1:4] = d
- assert list(c) == [0, 10, 20, 30, 0]
- #
- BShortP = new_pointer_type(new_primitive_type("short"))
- BShortArray = new_array_type(BShortP, None)
- d = newp(BShortArray, [40, 50])
- c[1:3] = d
- assert list(c) == [0, 40, 50, 30, 0]
-
-def test_cdata_name_module_doc():
- p = new_primitive_type("signed char")
- x = cast(p, 17)
- assert x.__module__ == '_cffi_backend'
- assert x.__name__ == '<cdata>'
- assert hasattr(x, '__doc__')
-
-def test_different_types_of_ptr_equality():
- BVoidP = new_pointer_type(new_void_type())
- BIntP = new_pointer_type(new_primitive_type("int"))
- x = cast(BVoidP, 12345)
- assert x == cast(BIntP, 12345)
- assert x != cast(BIntP, 12344)
- assert hash(x) == hash(cast(BIntP, 12345))
-
-def test_new_handle():
- import _weakref
- BVoidP = new_pointer_type(new_void_type())
- BCharP = new_pointer_type(new_primitive_type("char"))
- class mylist(list):
- pass
- o = mylist([2, 3, 4])
- x = newp_handle(BVoidP, o)
- assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>"
- assert x
- assert from_handle(x) is o
- assert from_handle(cast(BCharP, x)) is o
- wr = _weakref.ref(o)
- del o
- import gc; gc.collect()
- assert wr() is not None
- assert from_handle(x) == list((2, 3, 4))
- assert from_handle(cast(BCharP, x)) == list((2, 3, 4))
- del x
- for i in range(3):
- if wr() is not None:
- import gc; gc.collect()
- assert wr() is None
- py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
-
-def test_new_handle_cycle():
- import _weakref
- BVoidP = new_pointer_type(new_void_type())
- class A(object):
- pass
- o = A()
- o.cycle = newp_handle(BVoidP, o)
- wr = _weakref.ref(o)
- del o
- for i in range(3):
- if wr() is not None:
- import gc; gc.collect()
- assert wr() is None
-
-def _test_bitfield_details(flag):
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BStruct = new_struct_type("struct foo1")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('b1', BInt, 9),
- ('b2', BUInt, 7),
- ('c', BChar, -1)], -1, -1, -1, flag)
- if not (flag & SF_MSVC_BITFIELDS): # gcc, any variant
- assert typeoffsetof(BStruct, 'c') == (BChar, 3)
- assert sizeof(BStruct) == 4
- else: # msvc
- assert typeoffsetof(BStruct, 'c') == (BChar, 8)
- assert sizeof(BStruct) == 12
- assert alignof(BStruct) == 4
- #
- p = newp(new_pointer_type(BStruct), None)
- p.a = b'A'
- p.b1 = -201
- p.b2 = 99
- p.c = b'\x9D'
- raw = buffer(p)[:]
- if sys.byteorder == 'little':
- if flag & SF_MSVC_BITFIELDS:
- assert raw == b'A\x00\x00\x007\xC7\x00\x00\x9D\x00\x00\x00'
- 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 & SF_MSVC_BITFIELDS:
- assert raw == b'A\x00\x00\x00\x00\x00\xC77\x9D\x00\x00\x00'
- 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")
- #
- BStruct = new_struct_type("struct foo2")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('', BShort, 9),
- ('c', BChar, -1)], -1, -1, -1, flag)
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- if flag & SF_MSVC_BITFIELDS:
- assert sizeof(BStruct) == 6
- assert alignof(BStruct) == 2
- 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")
- #
- BStruct = new_struct_type("struct foo2")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('', BInt, 0),
- ('', BInt, 0),
- ('c', BChar, -1)], -1, -1, -1, flag)
- if flag & SF_MSVC_BITFIELDS:
- assert typeoffsetof(BStruct, 'c') == (BChar, 1)
- assert sizeof(BStruct) == 2
- assert alignof(BStruct) == 1
- 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")
-
-
-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=SF_MSVC_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-
-def test_bitfield_as_arm_gcc():
- _test_bitfield_details(flag=SF_GCC_ARM_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-
-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():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- BStruct = new_struct_type("foo")
- py.test.raises(TypeError, complete_struct_or_union,
- BStruct, [('x', BArray),
- ('y', BInt)])
- #
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BInt),
- ('y', BArray)])
- assert sizeof(BStruct) == size_of_int()
- d = BStruct.fields
- assert len(d) == 2
- assert d[0][0] == 'x'
- assert d[0][1].type is BInt
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'y'
- assert d[1][1].type is BArray
- assert d[1][1].offset == size_of_int()
- assert d[1][1].bitshift == -2
- assert d[1][1].bitsize == -1
- #
- p = newp(new_pointer_type(BStruct))
- p.x = 42
- assert p.x == 42
- assert typeof(p.y) is BArray
- assert len(p.y) == 0
- assert p.y == cast(BIntP, p) + 1
- #
- p = newp(new_pointer_type(BStruct), [100])
- assert p.x == 100
- assert len(p.y) == 0
- #
- # Tests for
- # ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
- # ffi.new("struct_with_var_array *", [field.., array_size])
- plist = []
- for i in range(20):
- if i % 2 == 0:
- p = newp(new_pointer_type(BStruct), [100, [200, i, 400]])
- else:
- p = newp(new_pointer_type(BStruct), [100, 3])
- p.y[1] = i
- p.y[0] = 200
- assert p.y[2] == 0
- p.y[2] = 400
- assert len(p.y) == 3
- assert len(p[0].y) == 3
- assert len(buffer(p)) == sizeof(BInt) * 4
- assert sizeof(p[0]) == sizeof(BInt) * 4
- plist.append(p)
- for i in range(20):
- p = plist[i]
- assert p.x == 100
- assert p.y[0] == 200
- assert p.y[1] == i
- assert p.y[2] == 400
- assert list(p.y) == [200, i, 400]
- #
- # the following assignment works, as it normally would, for any array field
- p.y = [501, 601]
- assert list(p.y) == [501, 601, 400]
- p[0].y = [500, 600]
- assert list(p[0].y) == [500, 600, 400]
- assert repr(p) == "<cdata 'foo *' owning %d bytes>" % (
- sizeof(BStruct) + 3 * sizeof(BInt),)
- assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % (
- sizeof(BStruct) + 3 * sizeof(BInt),)
- assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt)
- #
- # from a non-owning pointer, we can't get the length
- q = cast(new_pointer_type(BStruct), p)
- assert q.y[0] == 500
- assert q[0].y[0] == 500
- py.test.raises(TypeError, len, q.y)
- py.test.raises(TypeError, len, q[0].y)
- assert typeof(q.y) is BIntP
- assert typeof(q[0].y) is BIntP
- assert sizeof(q[0]) == sizeof(BStruct)
- #
- # error cases
- with pytest.raises(IndexError):
- p.y[4]
- with pytest.raises(TypeError):
- p.y = cast(BIntP, 0)
- with pytest.raises(TypeError):
- p.y = 15
- with pytest.raises(TypeError):
- p.y = None
- #
- # accepting this may be specified by the C99 standard,
- # or a GCC strangeness...
- BStruct2 = new_struct_type("bar")
- complete_struct_or_union(BStruct2, [('f', BStruct),
- ('n', BInt)])
- p = newp(new_pointer_type(BStruct2), {'n': 42})
- assert p.n == 42
- #
- # more error cases
- py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None])
- BArray4 = new_array_type(BIntP, 4)
- BStruct4 = new_struct_type("test4")
- complete_struct_or_union(BStruct4, [('a', BArray4)]) # not varsized
- py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None])
- py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4])
- p = newp(new_pointer_type(BStruct4), [[10, 20, 30]])
- assert p.a[0] == 10
- assert p.a[1] == 20
- assert p.a[2] == 30
- assert p.a[3] == 0
- #
- # struct of struct of varsized array
- BStruct2 = new_struct_type("bar")
- complete_struct_or_union(BStruct2, [('head', BInt),
- ('tail', BStruct)])
- for i in range(2): # try to detect heap overwrites
- p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]])
- assert p.tail.y[49] == 49
-
-
-def test_struct_array_no_length_explicit_position():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items
- ('y', BInt, -1, 12)])
- p = newp(new_pointer_type(BStruct), [[10, 20], 30])
- assert p.x[0] == 10
- assert p.x[1] == 20
- assert p.x[2] == 0
- assert p.y == 30
- p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50})
- assert p.x[0] == 40
- assert p.x[1] == 0
- assert p.x[2] == 0
- assert p.y == 50
- p = newp(new_pointer_type(BStruct), {'y': 60})
- assert p.x[0] == 0
- assert p.x[1] == 0
- assert p.x[2] == 0
- assert p.y == 60
- #
- # This "should" work too, allocating a larger structure
- # (a bit strange in this case, but useful in general)
- plist = []
- for i in range(20):
- p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]])
- plist.append(p)
- for i in range(20):
- p = plist[i]
- assert p.x[0] == 10
- assert p.x[1] == 20
- assert p.x[2] == 30
- assert p.x[3] == 40 == p.y
- assert p.x[4] == 50
- assert p.x[5] == 60
- assert p.x[6] == 70
-
-def test_struct_array_not_aligned():
- # struct a { int x; char y; char z[]; };
- # ends up of size 8, but 'z' is at offset 5
- BChar = new_primitive_type("char")
- BInt = new_primitive_type("int")
- BCharP = new_pointer_type(BChar)
- BArray = new_array_type(BCharP, None)
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BInt),
- ('y', BChar),
- ('z', BArray)])
- assert sizeof(BStruct) == 2 * size_of_int()
- def offsetof(BType, fieldname):
- return typeoffsetof(BType, fieldname)[1]
- base = offsetof(BStruct, 'z')
- assert base == size_of_int() + 1
- #
- p = newp(new_pointer_type(BStruct), {'z': 3})
- assert sizeof(p[0]) == base + 3
- q = newp(new_pointer_type(BStruct), {'z': size_of_int()})
- assert sizeof(q) == size_of_ptr()
- assert sizeof(q[0]) == base + size_of_int()
- assert len(p.z) == 3
- assert len(p[0].z) == 3
- assert len(q.z) == size_of_int()
- assert len(q[0].z) == size_of_int()
-
-def test_ass_slice():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), None)
- p = newp(BArray, b"foobar")
- p[2:5] = [b"*", b"Z", b"T"]
- p[1:3] = b"XY"
- assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
- with pytest.raises(TypeError):
- p[1:5] = u+'XYZT'
- with pytest.raises(TypeError):
- p[1:5] = [1, 2, 3, 4]
- #
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- BUniChar = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BUniChar), None)
- p = newp(BArray, u+"foobar")
- p[2:5] = [u+"*", u+"Z", u+"T"]
- p[1:3] = u+"XY"
- assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
- with pytest.raises(TypeError):
- p[1:5] = b'XYZT'
- with pytest.raises(TypeError):
- p[1:5] = [1, 2, 3, 4]
-
-def test_void_p_arithmetic():
- BVoid = new_void_type()
- BInt = new_primitive_type("intptr_t")
- p = cast(new_pointer_type(BVoid), 100000)
- assert int(cast(BInt, p)) == 100000
- assert int(cast(BInt, p + 42)) == 100042
- assert int(cast(BInt, p - (-42))) == 100042
- assert (p + 42) - p == 42
- q = cast(new_pointer_type(new_primitive_type("char")), 100000)
- with pytest.raises(TypeError):
- p - q
- with pytest.raises(TypeError):
- q - p
- with pytest.raises(TypeError):
- p + cast(new_primitive_type('int'), 42)
- with pytest.raises(TypeError):
- p - cast(new_primitive_type('int'), 42)
-
-def test_sizeof_sliced_array():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), 10)
- p = newp(BArray, None)
- assert sizeof(p[2:9]) == 7 * sizeof(BInt)
-
-def test_packed():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- for extra_args in [(SF_PACKED,), (0, 1)]:
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BChar, -1),
- ('a3', BShort, -1)],
- None, -1, -1, *extra_args)
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BLong)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BShort
- assert d[2][1].offset == sizeof(BLong) + sizeof(BChar)
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
- assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort)
- assert alignof(BStruct) == 1
- #
- BStruct2 = new_struct_type("struct foo")
- complete_struct_or_union(BStruct2, [('b1', BChar, -1),
- ('b2', BLong, -1)],
- None, -1, -1, 0, 2)
- d = BStruct2.fields
- assert len(d) == 2
- assert d[0][0] == 'b1'
- assert d[0][1].type is BChar
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'b2'
- assert d[1][1].type is BLong
- assert d[1][1].offset == 2
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert sizeof(BStruct2) == 2 + sizeof(BLong)
- assert alignof(BStruct2) == 2
-
-def test_packed_with_bitfields():
- if sys.platform == "win32":
- py.test.skip("testing gcc behavior")
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- py.test.raises(NotImplementedError,
- complete_struct_or_union,
- BStruct, [('a1', BLong, 30),
- ('a2', BChar, 5)],
- None, -1, -1, SF_PACKED)
-
-def test_from_buffer():
- import array
- a = array.array('H', [10000, 20000, 30000])
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- c = from_buffer(BCharA, a)
- assert typeof(c) is BCharA
- assert len(c) == 6
- assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>"
- p = new_pointer_type(new_primitive_type("unsigned short"))
- cast(p, c)[1] += 500
- assert list(a) == [10000, 20500, 30000]
-
-def test_from_buffer_not_str_unicode():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p1 = from_buffer(BCharA, b"foo")
- assert p1 == from_buffer(BCharA, b"foo")
- import gc; gc.collect()
- assert p1 == from_buffer(BCharA, b"foo")
- py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
- try:
- from __builtin__ import buffer
- except ImportError:
- pass
- else:
- # Python 2 only
- contents = from_buffer(BCharA, buffer(b"foo"))
- assert len(contents) == len(p1)
- for i in range(len(contents)):
- assert contents[i] == p1[i]
- p4 = buffer(u+"foo")
- contents = from_buffer(BCharA, buffer(u+"foo"))
- assert len(contents) == len(p4)
- for i in range(len(contents)):
- assert contents[i] == p4[i]
- try:
- from __builtin__ import memoryview
- except ImportError:
- pass
- else:
- contents = from_buffer(BCharA, memoryview(b"foo"))
- assert len(contents) == len(p1)
- for i in range(len(contents)):
- assert contents[i] == p1[i]
-
-
-def test_from_buffer_bytearray():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- assert typeof(p) is BCharA
- assert len(p) == 3
- assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
- assert p[2] == b"z"
- p[2] = b"."
- assert a[2] == ord(".")
- a[2] = ord("?")
- assert p[2] == b"?"
-
-def test_from_buffer_more_cases():
- try:
- from _cffi_backend import _testbuff
- except ImportError:
- py.test.skip("not for pypy")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- #
- def check1(bufobj, expected):
- c = from_buffer(BCharA, bufobj)
- assert typeof(c) is BCharA
- if sys.version_info >= (3,):
- expected = [bytes(c, "ascii") for c in expected]
- assert list(c) == list(expected)
- #
- def check(methods, expected, expected_for_memoryview=None):
- if sys.version_info >= (3,):
- if methods <= 7:
- return
- if expected_for_memoryview is not None:
- expected = expected_for_memoryview
- class X(object):
- pass
- _testbuff(X, methods)
- bufobj = X()
- check1(bufobj, expected)
- try:
- from __builtin__ import buffer
- bufobjb = buffer(bufobj)
- except (TypeError, ImportError):
- pass
- else:
- check1(bufobjb, expected)
- try:
- bufobjm = memoryview(bufobj)
- except (TypeError, NameError):
- pass
- else:
- check1(bufobjm, expected_for_memoryview or expected)
- #
- check(1, "RDB")
- check(2, "WRB")
- check(4, "CHB")
- check(8, "GTB")
- check(16, "ROB")
- #
- check(1 | 2, "RDB")
- check(1 | 4, "RDB")
- check(2 | 4, "CHB")
- check(1 | 8, "RDB", "GTB")
- check(1 | 16, "RDB", "ROB")
- check(2 | 8, "WRB", "GTB")
- check(2 | 16, "WRB", "ROB")
- check(4 | 8, "CHB", "GTB")
- check(4 | 16, "CHB", "ROB")
-
-def test_from_buffer_require_writable():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p1 = from_buffer(BCharA, b"foo", False)
- assert p1 == from_buffer(BCharA, b"foo", False)
- py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
- ba = bytearray(b"foo")
- p1 = from_buffer(BCharA, ba, True)
- p1[0] = b"g"
- assert ba == b"goo"
-
-def test_from_buffer_types():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BIntA = new_array_type(BIntP, None)
- lst = [-12345678, 87654321, 489148]
- bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
- lst2 = lst + [42, -999999999]
- bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ')
- #
- p1 = from_buffer(BIntA, bytestring) # int[]
- assert typeof(p1) is BIntA
- assert len(p1) == 3
- assert p1[0] == lst[0]
- assert p1[1] == lst[1]
- assert p1[2] == lst[2]
- with pytest.raises(IndexError):
- p1[3]
- with pytest.raises(IndexError):
- p1[-1]
- #
- py.test.raises(TypeError, from_buffer, BInt, bytestring)
- #
- p2 = from_buffer(BIntP, bytestring) # int *
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- # note: on py.py ^^^, bytearray buffers are not emulated well enough
- assert typeof(p2) is BIntP
- assert p2[0] == lst[0]
- assert p2[1] == lst[1]
- assert p2[2] == lst[2]
- # hopefully does not crash, but doesn't raise an exception:
- p2[3]
- p2[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BIntP, b"")
- #
- BIntA2 = new_array_type(BIntP, 2)
- p2 = from_buffer(BIntA2, bytestring) # int[2]
- assert typeof(p2) is BIntA2
- assert len(p2) == 2
- assert p2[0] == lst[0]
- assert p2[1] == lst[1]
- with pytest.raises(IndexError):
- p2[2]
- with pytest.raises(IndexError):
- p2[-1]
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- #
- BIntA4 = new_array_type(BIntP, 4) # int[4]: too big
- py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
- #
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- BStructP = new_pointer_type(BStruct)
- BStructA = new_array_type(BStructP, None)
- p1 = from_buffer(BStructA, bytestring2) # struct[]
- assert len(p1) == 2
- assert typeof(p1) is BStructA
- assert p1[0].a1 == lst2[0]
- assert p1[0].a2 == lst2[1]
- assert p1[1].a1 == lst2[2]
- assert p1[1].a2 == lst2[3]
- with pytest.raises(IndexError):
- p1[2]
- with pytest.raises(IndexError):
- p1[-1]
- assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>"
- #
- p2 = from_buffer(BStructP, bytestring2) # 'struct *'
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- assert typeof(p2) is BStructP
- assert p2.a1 == lst2[0]
- assert p2.a2 == lst2[1]
- assert p2[0].a1 == lst2[0]
- assert p2[0].a2 == lst2[1]
- assert p2[1].a1 == lst2[2]
- assert p2[1].a2 == lst2[3]
- # does not crash:
- p2[2]
- p2[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BStructP, b"")
- from_buffer(BStructP, b"1234567")
- #
- release(p1)
- assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>"
- #
- BEmptyStruct = new_struct_type("empty")
- complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
- assert sizeof(BEmptyStruct) == 0
- BEmptyStructP = new_pointer_type(BEmptyStruct)
- BEmptyStructA = new_array_type(BEmptyStructP, None)
- py.test.raises(ZeroDivisionError, from_buffer, # empty[]
- BEmptyStructA, bytestring)
- #
- BEmptyStructA5 = new_array_type(BEmptyStructP, 5)
- p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5]
- assert typeof(p1) is BEmptyStructA5
- assert len(p1) == 5
- assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring)
- or 'PY_DOT_PY' in globals())
- #
- BVarStruct = new_struct_type("varfoo")
- BVarStructP = new_pointer_type(BVarStruct)
- complete_struct_or_union(BVarStruct, [('a1', BInt, -1),
- ('va', BIntA, -1)])
- with pytest.raises(TypeError):
- from_buffer(BVarStruct, bytestring)
- pv = from_buffer(BVarStructP, bytestring) # varfoo *
- assert pv.a1 == lst[0]
- assert pv.va[0] == lst[1]
- assert pv.va[1] == lst[2]
- assert sizeof(pv[0]) == 1 * size_of_int()
- with pytest.raises(TypeError):
- len(pv.va)
- # hopefully does not crash, but doesn't raise an exception:
- pv.va[2]
- pv.va[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BVarStructP, b"")
- assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>"
- assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
- #
- release(pv)
- assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>"
- assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
- #
- pv = from_buffer(BVarStructP, bytestring) # make a fresh one
- with pytest.raises(ValueError):
- release(pv[0])
-
-def test_issue483():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BIntA = new_array_type(BIntP, None)
- lst = list(range(25))
- bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
- p1 = from_buffer(BIntA, bytestring) # int[]
- assert len(buffer(p1)) == 25 * size_of_int()
- assert sizeof(p1) == 25 * size_of_int()
- #
- p2 = from_buffer(BIntP, bytestring)
- assert sizeof(p2) == size_of_ptr()
- assert len(buffer(p2)) == size_of_int() # first element only, by default
-
-def test_memmove():
- Short = new_primitive_type("short")
- ShortA = new_array_type(new_pointer_type(Short), None)
- Char = new_primitive_type("char")
- CharA = new_array_type(new_pointer_type(Char), None)
- p = newp(ShortA, [-1234, -2345, -3456, -4567, -5678])
- memmove(p, p + 1, 4)
- assert list(p) == [-2345, -3456, -3456, -4567, -5678]
- p[2] = 999
- memmove(p + 2, p, 6)
- assert list(p) == [-2345, -3456, -2345, -3456, 999]
- memmove(p + 4, newp(CharA, b"\x71\x72"), 2)
- if sys.byteorder == 'little':
- assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
- else:
- assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
-
-def test_memmove_buffer():
- import array
- Short = new_primitive_type("short")
- ShortA = new_array_type(new_pointer_type(Short), None)
- a = array.array('H', [10000, 20000, 30000])
- p = newp(ShortA, 5)
- memmove(p, a, 6)
- assert list(p) == [10000, 20000, 30000, 0, 0]
- memmove(p + 1, a, 6)
- assert list(p) == [10000, 10000, 20000, 30000, 0]
- b = array.array('h', [-1000, -2000, -3000])
- memmove(b, a, 4)
- assert b.tolist() == [10000, 20000, -3000]
- assert a.tolist() == [10000, 20000, 30000]
- p[0] = 999
- p[1] = 998
- p[2] = 997
- p[3] = 996
- p[4] = 995
- memmove(b, p, 2)
- assert b.tolist() == [999, 20000, -3000]
- memmove(b, p + 2, 4)
- assert b.tolist() == [997, 996, -3000]
- p[2] = -p[2]
- p[3] = -p[3]
- memmove(b, p + 2, 6)
- assert b.tolist() == [-997, -996, 995]
-
-def test_memmove_readonly_readwrite():
- SignedChar = new_primitive_type("signed char")
- SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
- p = newp(SignedCharA, 5)
- memmove(p, b"abcde", 3)
- assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
- memmove(p, bytearray(b"ABCDE"), 2)
- assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
- py.test.raises((TypeError, BufferError), memmove, b"abcde", p, 3)
- ba = bytearray(b"xxxxx")
- memmove(dest=ba, src=p, n=3)
- assert ba == bytearray(b"ABcxx")
- memmove(ba, b"EFGH", 4)
- assert ba == bytearray(b"EFGHx")
-
-def test_memmove_sign_check():
- SignedChar = new_primitive_type("signed char")
- SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
- p = newp(SignedCharA, 5)
- py.test.raises(ValueError, memmove, p, p + 1, -1) # not segfault
-
-def test_memmove_bad_cdata():
- BInt = new_primitive_type("int")
- p = cast(BInt, 42)
- py.test.raises(TypeError, memmove, p, bytearray(b'a'), 1)
- py.test.raises(TypeError, memmove, bytearray(b'a'), p, 1)
-
-def test_dereference_null_ptr():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- p = cast(BIntPtr, 0)
- with pytest.raises(RuntimeError):
- p[0]
- with pytest.raises(RuntimeError):
- p[0] = 42
- with pytest.raises(RuntimeError):
- p[42]
- with pytest.raises(RuntimeError):
- p[42] = -1
-
-def test_mixup():
- BStruct1 = new_struct_type("foo")
- BStruct2 = new_struct_type("foo") # <= same name as BStruct1
- BStruct3 = new_struct_type("bar")
- BStruct1Ptr = new_pointer_type(BStruct1)
- BStruct2Ptr = new_pointer_type(BStruct2)
- BStruct3Ptr = new_pointer_type(BStruct3)
- BStruct1PtrPtr = new_pointer_type(BStruct1Ptr)
- BStruct2PtrPtr = new_pointer_type(BStruct2Ptr)
- BStruct3PtrPtr = new_pointer_type(BStruct3Ptr)
- pp1 = newp(BStruct1PtrPtr)
- pp2 = newp(BStruct2PtrPtr)
- pp3 = newp(BStruct3PtrPtr)
- pp1[0] = pp1[0]
- with pytest.raises(TypeError) as e:
- pp3[0] = pp1[0]
- assert str(e.value).startswith("initializer for ctype 'bar *' must be a ")
- assert str(e.value).endswith(", not cdata 'foo *'")
- with pytest.raises(TypeError) as e:
- pp2[0] = pp1[0]
- assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to "
- "be 'foo *', but the types are different (check "
- "that you are not e.g. mixing up different ffi "
- "instances)")
-
-def test_stdcall_function_type():
- assert FFI_CDECL == FFI_DEFAULT_ABI
- try:
- stdcall = FFI_STDCALL
- except NameError:
- stdcall = FFI_DEFAULT_ABI
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False, stdcall)
- if stdcall != FFI_DEFAULT_ABI:
- assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>"
- else:
- assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
-
-def test_get_common_types():
- d = {}
- _get_common_types(d)
- assert d['bool'] == '_Bool'
-
-def test_unpack():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 10) # char[10]
- p = newp(BArray, b"abc\x00def")
- p0 = p
- assert unpack(p, 10) == b"abc\x00def\x00\x00\x00"
- assert unpack(p+1, 5) == b"bc\x00de"
-
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- BWChar = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10]
- p = newp(BArray, u"abc\x00def")
- assert unpack(p, 10) == u"abc\x00def\x00\x00\x00"
-
- for typename, samples in [
- ("uint8_t", [0, 2**8-1]),
- ("uint16_t", [0, 2**16-1]),
- ("uint32_t", [0, 2**32-1]),
- ("uint64_t", [0, 2**64-1]),
- ("int8_t", [-2**7, 2**7-1]),
- ("int16_t", [-2**15, 2**15-1]),
- ("int32_t", [-2**31, 2**31-1]),
- ("int64_t", [-2**63, 2**63-1]),
- ("_Bool", [False, True]),
- ("float", [0.0, 10.5]),
- ("double", [12.34, 56.78]),
- ]:
- BItem = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BItem), 10)
- p = newp(BArray, samples)
- result = unpack(p, len(samples))
- assert result == samples
- for i in range(len(samples)):
- assert result[i] == p[i] and type(result[i]) is type(p[i])
- assert (type(result[i]) is bool) == (type(samples[i]) is bool)
- #
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, unpack, p)
- py.test.raises(TypeError, unpack, b"foobar", 6)
- py.test.raises(TypeError, unpack, cast(BInt, 42), 1)
- #
- BPtr = new_pointer_type(BInt)
- random_ptr = cast(BPtr, -424344)
- other_ptr = cast(BPtr, 54321)
- BArray = new_array_type(new_pointer_type(BPtr), None)
- lst = unpack(newp(BArray, [random_ptr, other_ptr]), 2)
- assert lst == [random_ptr, other_ptr]
- #
- BFunc = new_function_type((BInt, BInt), BInt, False)
- BFuncPtr = new_pointer_type(BFunc)
- lst = unpack(newp(new_array_type(BFuncPtr, None), 2), 2)
- assert len(lst) == 2
- assert not lst[0] and not lst[1]
- assert typeof(lst[0]) is BFunc
- #
- BStruct = new_struct_type("foo")
- BStructPtr = new_pointer_type(BStruct)
- e = py.test.raises(ValueError, unpack, cast(BStructPtr, 42), 5)
- assert str(e.value) == "'foo *' points to items of unknown size"
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- array_of_structs = newp(new_array_type(BStructPtr, None), [[4,5], [6,7]])
- lst = unpack(array_of_structs, 2)
- assert typeof(lst[0]) is BStruct
- assert lst[0].a1 == 4 and lst[1].a2 == 7
- #
- py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 0)
- py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 10)
- #
- py.test.raises(ValueError, unpack, p0, -1)
- py.test.raises(ValueError, unpack, p, -1)
-
-def test_cdata_dir():
- BInt = new_primitive_type("int")
- p = cast(BInt, 42)
- check_dir(p, [])
- p = newp(new_array_type(new_pointer_type(BInt), None), 5)
- check_dir(p, [])
- BStruct = new_struct_type("foo")
- p = cast(new_pointer_type(BStruct), 0)
- check_dir(p, []) # opaque
- complete_struct_or_union(BStruct, [('a2', BInt, -1),
- ('a1', BInt, -1)])
- check_dir(p, ['a1', 'a2']) # always sorted
- p = newp(new_pointer_type(BStruct), None)
- check_dir(p, ['a1', 'a2'])
- check_dir(p[0], ['a1', 'a2'])
- pp = newp(new_pointer_type(new_pointer_type(BStruct)), p)
- check_dir(pp, [])
- check_dir(pp[0], ['a1', 'a2'])
- check_dir(pp[0][0], ['a1', 'a2'])
-
-def test_char_pointer_conversion():
- import warnings
- assert __version__.startswith("1."), (
- "the warning will be an error if we ever release cffi 2.x")
- BCharP = new_pointer_type(new_primitive_type("char"))
- BIntP = new_pointer_type(new_primitive_type("int"))
- BVoidP = new_pointer_type(new_void_type())
- BUCharP = new_pointer_type(new_primitive_type("unsigned char"))
- z1 = cast(BCharP, 0)
- z2 = cast(BIntP, 0)
- z3 = cast(BVoidP, 0)
- z4 = cast(BUCharP, 0)
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- newp(new_pointer_type(BIntP), z1) # warn
- assert len(w) == 1
- newp(new_pointer_type(BVoidP), z1) # fine
- assert len(w) == 1
- newp(new_pointer_type(BCharP), z2) # warn
- assert len(w) == 2
- newp(new_pointer_type(BVoidP), z2) # fine
- assert len(w) == 2
- newp(new_pointer_type(BCharP), z3) # fine
- assert len(w) == 2
- newp(new_pointer_type(BIntP), z3) # fine
- assert len(w) == 2
- newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here)
- assert len(w) == 2
- newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here)
- assert len(w) == 2
- newp(new_pointer_type(BUCharP), z3) # fine
- assert len(w) == 2
- # check that the warnings are associated with lines in this file
- assert w[1].lineno == w[0].lineno + 4
-
-def test_primitive_comparison():
- def assert_eq(a, b):
- assert (a == b) is True
- assert (b == a) is True
- assert (a != b) is False
- assert (b != a) is False
- assert (a < b) is False
- assert (a <= b) is True
- assert (a > b) is False
- assert (a >= b) is True
- assert (b < a) is False
- assert (b <= a) is True
- assert (b > a) is False
- assert (b >= a) is True
- assert hash(a) == hash(b)
- def assert_lt(a, b, check_hash=True):
- assert (a == b) is False
- assert (b == a) is False
- assert (a != b) is True
- assert (b != a) is True
- assert (a < b) is True
- assert (a <= b) is True
- assert (a > b) is False
- assert (a >= b) is False
- assert (b < a) is False
- assert (b <= a) is False
- assert (b > a) is True
- assert (b >= a) is True
- if check_hash:
- assert hash(a) != hash(b) # (or at least, it is unlikely)
- def assert_gt(a, b, check_hash=True):
- assert_lt(b, a, check_hash)
- def assert_ne(a, b):
- assert (a == b) is False
- assert (b == a) is False
- assert (a != b) is True
- assert (b != a) is True
- if strict_compare:
- with pytest.raises(TypeError): a < b
- with pytest.raises(TypeError): a <= b
- with pytest.raises(TypeError): a > b
- with pytest.raises(TypeError): a >= b
- with pytest.raises(TypeError): b < a
- with pytest.raises(TypeError): b <= a
- with pytest.raises(TypeError): b > a
- with pytest.raises(TypeError): b >= a
- elif a < b:
- assert_lt(a, b)
- else:
- assert_lt(b, a)
- assert_eq(5, 5)
- assert_lt(3, 5)
- assert_ne('5', 5)
- #
- t1 = new_primitive_type("char")
- t2 = new_primitive_type("int")
- t3 = new_primitive_type("unsigned char")
- t4 = new_primitive_type("unsigned int")
- t5 = new_primitive_type("float")
- t6 = new_primitive_type("double")
- assert_eq(cast(t1, 65), b'A')
- assert_lt(cast(t1, 64), b'\x99')
- assert_gt(cast(t1, 200), b'A')
- assert_ne(cast(t1, 65), 65)
- assert_eq(cast(t2, -25), -25)
- assert_lt(cast(t2, -25), -24)
- assert_gt(cast(t2, -25), -26)
- assert_eq(cast(t3, 65), 65)
- assert_ne(cast(t3, 65), b'A')
- assert_ne(cast(t3, 65), cast(t1, 65))
- assert_gt(cast(t4, -1), -1, check_hash=False)
- assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False)
- assert_gt(cast(t4, -1), 99999)
- assert_eq(cast(t4, -1), 256 ** size_of_int() - 1)
- assert_eq(cast(t5, 3.0), 3)
- assert_eq(cast(t5, 3.5), 3.5)
- assert_lt(cast(t5, 3.3), 3.3) # imperfect rounding
- assert_eq(cast(t6, 3.3), 3.3)
- assert_eq(cast(t5, 3.5), cast(t6, 3.5))
- assert_lt(cast(t5, 3.1), cast(t6, 3.1)) # imperfect rounding
- assert_eq(cast(t5, 7.0), cast(t3, 7))
- assert_lt(cast(t5, 3.1), 3.101)
- assert_gt(cast(t5, 3.1), 3)
-
-def test_explicit_release_new():
- # release() on a ffi.new() object has no effect on CPython, but
- # really releases memory on PyPy. We can't test that effect
- # though, because a released cdata is not marked.
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = newp(BIntP)
- p[0] = 42
- with pytest.raises(IndexError):
- p[1]
- release(p)
- # here, reading p[0] might give garbage or segfault...
- release(p) # no effect
- #
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('p', BIntP, -1)])
- pstruct = newp(BStructP)
- assert pstruct.p == cast(BIntP, 0)
- release(pstruct)
- # here, reading pstruct.p might give garbage or segfault...
- release(pstruct) # no effect
-
-def test_explicit_release_new_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- with newp(BIntP) as p:
- p[0] = 42
- assert p[0] == 42
- # here, reading p[0] might give garbage or segfault...
- release(p) # no effect
-
-def test_explicit_release_badtype():
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = cast(BIntP, 12345)
- py.test.raises(ValueError, release, p)
- py.test.raises(ValueError, release, p)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('p', BIntP, -1)])
- pstruct = newp(BStructP)
- py.test.raises(ValueError, release, pstruct[0])
-
-def test_explicit_release_badtype_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = cast(BIntP, 12345)
- with pytest.raises(ValueError):
- with p:
- pass
- with pytest.raises(ValueError):
- with p:
- pass
-
-def test_explicit_release_gc():
- BIntP = new_pointer_type(new_primitive_type("int"))
- seen = []
- intp1 = newp(BIntP, 12345)
- p1 = cast(BIntP, intp1)
- p = gcp(p1, seen.append)
- assert seen == []
- release(p)
- assert seen == [p1]
- assert p1[0] == 12345
- assert p[0] == 12345 # true so far, but might change to raise RuntimeError
- release(p) # no effect
-
-def test_explicit_release_gc_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- seen = []
- intp1 = newp(BIntP, 12345)
- p1 = cast(BIntP, intp1)
- p = gcp(p1, seen.append)
- with p:
- assert p[0] == 12345
- assert seen == []
- assert seen == [p1]
- assert p1[0] == 12345
- assert p[0] == 12345 # true so far, but might change to raise RuntimeError
- release(p) # no effect
-
-def test_explicit_release_from_buffer():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- assert p[2] == b"z"
- assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
- release(p)
- assert p[2] == b"z" # true so far, but might change to raise RuntimeError
- assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
- release(p) # no effect
-
-def test_explicit_release_from_buffer_contextmgr():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- with p:
- assert p[2] == b"z"
- assert p[2] == b"z" # true so far, but might change to raise RuntimeError
- assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
- release(p) # no effect
-
-def test_explicit_release_bytearray_on_cpython():
- if '__pypy__' in sys.builtin_module_names:
- py.test.skip("pypy's bytearray are never locked")
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- a += b't' * 10
- p = from_buffer(BCharA, a)
- with pytest.raises(BufferError):
- a += b'u' * 100
- release(p)
- a += b'v' * 100
- release(p) # no effect
- a += b'w' * 1000
- assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000)
-
-def test_int_doesnt_give_bool():
- BBool = new_primitive_type("_Bool")
- x = int(cast(BBool, 42))
- assert type(x) is int and x == 1
- x = long(cast(BBool, 42))
- assert type(x) is long and x == 1
- with pytest.raises(TypeError):
- float(cast(BBool, 42))
- with pytest.raises(TypeError):
- complex(cast(BBool, 42))
-
-def test_cannot_call_null_function_pointer():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- f = cast(BFunc, 0)
- with pytest.raises(RuntimeError):
- f(40, 2)
-
-def test_huge_structure():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), sys.maxsize)
- assert sizeof(BArray) == sys.maxsize
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BArray, -1)])
- assert sizeof(BStruct) == sys.maxsize
-
-def test_get_types():
- import _cffi_backend
- CData, CType = _get_types()
- assert CData is _cffi_backend._CDataBase
- assert CType is _cffi_backend.CType
-
-def test_type_available_with_correct_names():
- import _cffi_backend
- check_names = [
- 'CType',
- 'CField',
- 'CLibrary',
- '_CDataBase',
- 'FFI',
- 'Lib',
- 'buffer',
- ]
- if '__pypy__' in sys.builtin_module_names:
- check_names += [
- '__CData_iterator',
- '__FFIGlobSupport',
- '__FFIAllocator',
- '__FFIFunctionWrapper',
- ]
- else:
- check_names += [
- '__CDataOwn',
- '__CDataOwnGC',
- '__CDataFromBuf',
- '__CDataGCP',
- '__CData_iterator',
- '__FFIGlobSupport',
- ]
- for name in check_names:
- tp = getattr(_cffi_backend, name)
- assert isinstance(tp, type)
- assert (tp.__module__, tp.__name__) == ('_cffi_backend', name)
-
-def test_unaligned_types():
- BByteArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- pbuf = newp(BByteArray, 40)
- buf = buffer(pbuf)
- #
- for name in ['short', 'int', 'long', 'long long', 'float', 'double',
- 'float _Complex', 'double _Complex']:
- p = new_primitive_type(name)
- if name.endswith(' _Complex'):
- num = cast(p, 1.23 - 4.56j)
- else:
- num = cast(p, 0x0123456789abcdef)
- size = sizeof(p)
- buf[0:40] = b"\x00" * 40
- pbuf1 = cast(new_pointer_type(p), pbuf + 1)
- pbuf1[0] = num
- assert pbuf1[0] == num
- assert buf[0] == b'\x00'
- assert buf[1 + size] == b'\x00'
diff --git a/c/wchar_helper.h b/c/wchar_helper.h
deleted file mode 100644
index 8e6ea58..0000000
--- a/c/wchar_helper.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * wchar_t helpers
- */
-
-typedef uint16_t cffi_char16_t;
-typedef uint32_t cffi_char32_t;
-
-
-#if Py_UNICODE_SIZE == 2
-
-/* Before Python 2.7, PyUnicode_FromWideChar is not able to convert
- wchar_t values greater than 65535 into two-unicode-characters surrogates.
- But even the Python 2.7 version doesn't detect wchar_t values that are
- out of range(1114112), and just returns nonsense.
-
- From cffi 1.11 we can't use it anyway, because we need a version
- with char32_t input types.
-*/
-static PyObject *
-_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
-{
- PyObject *unicode;
- register Py_ssize_t i;
- Py_ssize_t alloc;
- const cffi_char32_t *orig_w;
-
- alloc = size;
- orig_w = w;
- for (i = size; i > 0; i--) {
- if (*w > 0xFFFF)
- alloc++;
- w++;
- }
- w = orig_w;
- unicode = PyUnicode_FromUnicode(NULL, alloc);
- if (!unicode)
- return NULL;
-
- /* Copy the wchar_t data into the new object */
- {
- register Py_UNICODE *u;
- u = PyUnicode_AS_UNICODE(unicode);
- for (i = size; i > 0; i--) {
- if (*w > 0xFFFF) {
- cffi_char32_t ordinal;
- if (*w > 0x10FFFF) {
- PyErr_Format(PyExc_ValueError,
- "char32_t out of range for "
- "conversion to unicode: 0x%x", (int)*w);
- Py_DECREF(unicode);
- return NULL;
- }
- ordinal = *w++;
- ordinal -= 0x10000;
- *u++ = 0xD800 | (ordinal >> 10);
- *u++ = 0xDC00 | (ordinal & 0x3FF);
- }
- else
- *u++ = *w++;
- }
- }
- return unicode;
-}
-
-static PyObject *
-_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
-{
- return PyUnicode_FromUnicode((const Py_UNICODE *)w, size);
-}
-
-#else /* Py_UNICODE_SIZE == 4 */
-
-static PyObject *
-_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
-{
- return PyUnicode_FromUnicode((const Py_UNICODE *)w, size);
-}
-
-static PyObject *
-_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
-{
- /* 'size' is the length of the 'w' array */
- PyObject *result = PyUnicode_FromUnicode(NULL, size);
-
- if (result != NULL) {
- Py_UNICODE *u_base = PyUnicode_AS_UNICODE(result);
- Py_UNICODE *u = u_base;
-
- if (size == 1) { /* performance only */
- *u = (cffi_char32_t)*w;
- }
- else {
- while (size > 0) {
- cffi_char32_t ch = *w++;
- size--;
- if (0xD800 <= ch && ch <= 0xDBFF && size > 0) {
- cffi_char32_t ch2 = *w;
- if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
- ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
- w++;
- size--;
- }
- }
- *u++ = ch;
- }
- if (PyUnicode_Resize(&result, u - u_base) < 0) {
- Py_DECREF(result);
- return NULL;
- }
- }
- }
- return result;
-}
-
-#endif
-
-
-#define IS_SURROGATE(u) (0xD800 <= (u)[0] && (u)[0] <= 0xDBFF && \
- 0xDC00 <= (u)[1] && (u)[1] <= 0xDFFF)
-#define AS_SURROGATE(u) (0x10000 + (((u)[0] - 0xD800) << 10) + \
- ((u)[1] - 0xDC00))
-
-static int
-_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result,
- char *err_got)
-{
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- if (PyUnicode_GET_SIZE(unicode) != 1) {
- sprintf(err_got, "unicode string of length %zd",
- PyUnicode_GET_SIZE(unicode));
- return -1;
- }
-#if Py_UNICODE_SIZE == 4
- if (((unsigned int)u[0]) > 0xFFFF)
- {
- sprintf(err_got, "larger-than-0xFFFF character");
- return -1;
- }
-#endif
- *result = (cffi_char16_t)u[0];
- return 0;
-}
-
-static int
-_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result,
- char *err_got)
-{
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- if (PyUnicode_GET_SIZE(unicode) == 1) {
- *result = (cffi_char32_t)u[0];
- return 0;
- }
-#if Py_UNICODE_SIZE == 2
- if (PyUnicode_GET_SIZE(unicode) == 2 && IS_SURROGATE(u)) {
- *result = AS_SURROGATE(u);
- return 0;
- }
-#endif
- sprintf(err_got, "unicode string of length %zd",
- PyUnicode_GET_SIZE(unicode));
- return -1;
-}
-
-static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode)
-{
- Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
- Py_ssize_t result = length;
-
-#if Py_UNICODE_SIZE == 4
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- Py_ssize_t i;
-
- for (i=0; i<length; i++) {
- if (u[i] > 0xFFFF)
- result++;
- }
-#endif
- return result;
-}
-
-static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode)
-{
- Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
- Py_ssize_t result = length;
-
-#if Py_UNICODE_SIZE == 2
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- Py_ssize_t i;
-
- for (i=0; i<length-1; i++) {
- if (IS_SURROGATE(u+i))
- result--;
- }
-#endif
- return result;
-}
-
-static int _my_PyUnicode_AsChar16(PyObject *unicode,
- cffi_char16_t *result,
- Py_ssize_t resultlen)
-{
- Py_ssize_t len = PyUnicode_GET_SIZE(unicode);
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- Py_ssize_t i;
- for (i=0; i<len; i++) {
-#if Py_UNICODE_SIZE == 2
- cffi_char16_t ordinal = u[i];
-#else
- cffi_char32_t ordinal = u[i];
- if (ordinal > 0xFFFF) {
- if (ordinal > 0x10FFFF) {
- PyErr_Format(PyExc_ValueError,
- "unicode character out of range for "
- "conversion to char16_t: 0x%x", (int)ordinal);
- return -1;
- }
- ordinal -= 0x10000;
- *result++ = 0xD800 | (ordinal >> 10);
- *result++ = 0xDC00 | (ordinal & 0x3FF);
- continue;
- }
-#endif
- *result++ = ordinal;
- }
- return 0;
-}
-
-static int _my_PyUnicode_AsChar32(PyObject *unicode,
- cffi_char32_t *result,
- Py_ssize_t resultlen)
-{
- Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
- Py_ssize_t i;
- for (i=0; i<resultlen; i++) {
- cffi_char32_t ordinal = *u;
-#if Py_UNICODE_SIZE == 2
- if (IS_SURROGATE(u)) {
- ordinal = AS_SURROGATE(u);
- u++;
- }
-#endif
- result[i] = ordinal;
- u++;
- }
- return 0;
-}
diff --git a/c/wchar_helper_3.h b/c/wchar_helper_3.h
deleted file mode 100644
index f15464e..0000000
--- a/c/wchar_helper_3.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * wchar_t helpers, version CPython >= 3.3.
- *
- * CPython 3.3 added support for sys.maxunicode == 0x10FFFF on all
- * platforms, even ones with wchar_t limited to 2 bytes. As such,
- * this code here works from the outside like wchar_helper.h in the
- * case Py_UNICODE_SIZE == 4, but the implementation is very different.
- */
-
-typedef uint16_t cffi_char16_t;
-typedef uint32_t cffi_char32_t;
-
-
-static PyObject *
-_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
-{
- return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, w, size);
-}
-
-static PyObject *
-_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
-{
- /* are there any surrogate pairs, and if so, how many? */
- Py_ssize_t i, count_surrogates = 0;
- for (i = 0; i < size - 1; i++) {
- if (0xD800 <= w[i] && w[i] <= 0xDBFF &&
- 0xDC00 <= w[i+1] && w[i+1] <= 0xDFFF)
- count_surrogates++;
- }
- if (count_surrogates == 0) {
- /* no, fast path */
- return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, w, size);
- }
- else
- {
- PyObject *result = PyUnicode_New(size - count_surrogates, 0x10FFFF);
- Py_UCS4 *data;
- assert(PyUnicode_KIND(result) == PyUnicode_4BYTE_KIND);
- data = PyUnicode_4BYTE_DATA(result);
-
- for (i = 0; i < size; i++)
- {
- cffi_char32_t ch = w[i];
- if (0xD800 <= ch && ch <= 0xDBFF && i < size - 1) {
- cffi_char32_t ch2 = w[i + 1];
- if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
- ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
- i++;
- }
- }
- *data++ = ch;
- }
- return result;
- }
-}
-
-static int
-_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result,
- char *err_got)
-{
- cffi_char32_t ch;
- if (PyUnicode_GET_LENGTH(unicode) != 1) {
- sprintf(err_got, "unicode string of length %zd",
- PyUnicode_GET_LENGTH(unicode));
- return -1;
- }
- ch = PyUnicode_READ_CHAR(unicode, 0);
-
- if (ch > 0xFFFF)
- {
- sprintf(err_got, "larger-than-0xFFFF character");
- return -1;
- }
- *result = (cffi_char16_t)ch;
- return 0;
-}
-
-static int
-_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result,
- char *err_got)
-{
- if (PyUnicode_GET_LENGTH(unicode) != 1) {
- sprintf(err_got, "unicode string of length %zd",
- PyUnicode_GET_LENGTH(unicode));
- return -1;
- }
- *result = PyUnicode_READ_CHAR(unicode, 0);
- return 0;
-}
-
-static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode)
-{
- Py_ssize_t length = PyUnicode_GET_LENGTH(unicode);
- Py_ssize_t result = length;
- unsigned int kind = PyUnicode_KIND(unicode);
-
- if (kind == PyUnicode_4BYTE_KIND)
- {
- Py_UCS4 *data = PyUnicode_4BYTE_DATA(unicode);
- Py_ssize_t i;
- for (i = 0; i < length; i++) {
- if (data[i] > 0xFFFF)
- result++;
- }
- }
- return result;
-}
-
-static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode)
-{
- return PyUnicode_GET_LENGTH(unicode);
-}
-
-static int _my_PyUnicode_AsChar16(PyObject *unicode,
- cffi_char16_t *result,
- Py_ssize_t resultlen)
-{
- Py_ssize_t len = PyUnicode_GET_LENGTH(unicode);
- unsigned int kind = PyUnicode_KIND(unicode);
- void *data = PyUnicode_DATA(unicode);
- Py_ssize_t i;
-
- for (i = 0; i < len; i++) {
- cffi_char32_t ordinal = PyUnicode_READ(kind, data, i);
- if (ordinal > 0xFFFF) {
- if (ordinal > 0x10FFFF) {
- PyErr_Format(PyExc_ValueError,
- "unicode character out of range for "
- "conversion to char16_t: 0x%x", (int)ordinal);
- return -1;
- }
- ordinal -= 0x10000;
- *result++ = 0xD800 | (ordinal >> 10);
- *result++ = 0xDC00 | (ordinal & 0x3FF);
- }
- else
- *result++ = ordinal;
- }
- return 0;
-}
-
-static int _my_PyUnicode_AsChar32(PyObject *unicode,
- cffi_char32_t *result,
- Py_ssize_t resultlen)
-{
- if (PyUnicode_AsUCS4(unicode, (Py_UCS4 *)result, resultlen, 0) == NULL)
- return -1;
- return 0;
-}