Author: Armin Rigo <[email protected]>
Branch:
Changeset: r77400:b24ae16f9d02
Date: 2015-05-19 19:43 +0200
http://bitbucket.org/pypy/pypy/changeset/b24ae16f9d02/
Log: hg merge cffi-1.0
diff too long, truncating to 2000 out of 24656 lines
diff --git a/lib_pypy/_gdbm_build.py b/lib_pypy/_gdbm_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_gdbm_build.py
@@ -0,0 +1,65 @@
+import cffi, os, sys
+
+ffi = cffi.FFI()
+ffi.cdef('''
+#define GDBM_READER ...
+#define GDBM_WRITER ...
+#define GDBM_WRCREAT ...
+#define GDBM_NEWDB ...
+#define GDBM_FAST ...
+#define GDBM_SYNC ...
+#define GDBM_NOLOCK ...
+#define GDBM_REPLACE ...
+
+void* gdbm_open(char *, int, int, int, void (*)());
+void gdbm_close(void*);
+
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+datum gdbm_fetch(void*, datum);
+datum pygdbm_fetch(void*, char*, int);
+int gdbm_delete(void*, datum);
+int gdbm_store(void*, datum, datum, int);
+int gdbm_exists(void*, datum);
+int pygdbm_exists(void*, char*, int);
+
+int gdbm_reorganize(void*);
+
+datum gdbm_firstkey(void*);
+datum gdbm_nextkey(void*, datum);
+void gdbm_sync(void*);
+
+char* gdbm_strerror(int);
+int gdbm_errno;
+
+void free(void*);
+''')
+
+
+kwds = {}
+if sys.platform.startswith('freebsd'):
+ _localbase = os.environ.get('LOCALBASE', '/usr/local')
+ kwds['include_dirs'] = [os.path.join(_localbase, 'include')]
+ kwds['library_dirs'] = [os.path.join(_localbase, 'lib')]
+
+ffi.set_source("_gdbm_cffi", '''
+#include <stdlib.h>
+#include "gdbm.h"
+
+static datum pygdbm_fetch(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_fetch(gdbm_file, key);
+}
+
+static int pygdbm_exists(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_exists(gdbm_file, key);
+}
+''', libraries=['gdbm'], **kwds)
+
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/lib_pypy/cffi.egg-info b/lib_pypy/cffi.egg-info
deleted file mode 100644
--- a/lib_pypy/cffi.egg-info
+++ /dev/null
@@ -1,10 +0,0 @@
-Metadata-Version: 1.0
-Name: cffi
-Version: 0.9.2
-Summary: Foreign Function Interface for Python calling C code.
-Home-page: http://cffi.readthedocs.org
-Author: Armin Rigo, Maciej Fijalkowski
-Author-email: [email protected]
-License: MIT
-Description: UNKNOWN
-Platform: UNKNOWN
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -0,0 +1,31 @@
+Metadata-Version: 1.1
+Name: cffi
+Version: 1.0.0
+Summary: Foreign Function Interface for Python calling C code.
+Home-page: http://cffi.readthedocs.org
+Author: Armin Rigo, Maciej Fijalkowski
+Author-email: [email protected]
+License: MIT
+Description:
+ CFFI
+ ====
+
+ Foreign Function Interface for Python calling C code.
+ Please see the `Documentation <http://cffi.readthedocs.org/>`_.
+
+ Contact
+ -------
+
+ `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
+
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
diff --git a/lib_pypy/cffi.egg-info/SOURCES.txt
b/lib_pypy/cffi.egg-info/SOURCES.txt
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/SOURCES.txt
@@ -0,0 +1,143 @@
+AUTHORS
+LICENSE
+MANIFEST.in
+setup.py
+setup_base.py
+c/_cffi_backend.c
+c/cdlopen.c
+c/cffi1_module.c
+c/cgc.c
+c/cglob.c
+c/ffi_obj.c
+c/file_emulator.h
+c/lib_obj.c
+c/malloc_closure.h
+c/minibuffer.h
+c/misc_thread.h
+c/misc_win32.h
+c/parse_c_type.c
+c/realize_c_type.c
+c/test_c.py
+c/wchar_helper.h
+c/libffi_msvc/ffi.c
+c/libffi_msvc/ffi.h
+c/libffi_msvc/ffi_common.h
+c/libffi_msvc/fficonfig.h
+c/libffi_msvc/ffitarget.h
+c/libffi_msvc/prep_cif.c
+c/libffi_msvc/types.c
+c/libffi_msvc/win32.c
+c/libffi_msvc/win64.asm
+c/libffi_msvc/win64.obj
+cffi/__init__.py
+cffi/_cffi_include.h
+cffi/api.py
+cffi/backend_ctypes.py
+cffi/cffi_opcode.py
+cffi/commontypes.py
+cffi/cparser.py
+cffi/ffiplatform.py
+cffi/gc_weakref.py
+cffi/lock.py
+cffi/model.py
+cffi/parse_c_type.h
+cffi/recompiler.py
+cffi/setuptools_ext.py
+cffi/vengine_cpy.py
+cffi/vengine_gen.py
+cffi/verifier.py
+cffi.egg-info/PKG-INFO
+cffi.egg-info/SOURCES.txt
+cffi.egg-info/dependency_links.txt
+cffi.egg-info/entry_points.txt
+cffi.egg-info/not-zip-safe
+cffi.egg-info/requires.txt
+cffi.egg-info/top_level.txt
+demo/_curses.py
+demo/_curses_build.py
+demo/_curses_setup.py
+demo/api.py
+demo/bsdopendirtype.py
+demo/bsdopendirtype_build.py
+demo/bsdopendirtype_setup.py
+demo/btrfs-snap.py
+demo/cffi-cocoa.py
+demo/fastcsv.py
+demo/gmp.py
+demo/manual.c
+demo/manual2.py
+demo/pwuid.py
+demo/py.cleanup
+demo/pyobj.py
+demo/readdir.py
+demo/readdir2.py
+demo/readdir2_build.py
+demo/readdir2_setup.py
+demo/readdir_build.py
+demo/readdir_ctypes.py
+demo/readdir_setup.py
+demo/recopendirtype.py
+demo/recopendirtype_build.py
+demo/setup.py
+demo/setup_manual.py
+demo/winclipboard.py
+demo/xclient.py
+doc/Makefile
+doc/make.bat
+doc/misc/design.rst
+doc/misc/grant-cffi-1.0.rst
+doc/misc/parse_c_type.rst
+doc/source/cdef.rst
+doc/source/conf.py
+doc/source/index.rst
+doc/source/installation.rst
+doc/source/overview.rst
+doc/source/using.rst
+testing/__init__.py
+testing/support.py
+testing/udir.py
+testing/cffi0/__init__.py
+testing/cffi0/backend_tests.py
+testing/cffi0/callback_in_thread.py
+testing/cffi0/test_cdata.py
+testing/cffi0/test_ctypes.py
+testing/cffi0/test_ffi_backend.py
+testing/cffi0/test_function.py
+testing/cffi0/test_model.py
+testing/cffi0/test_ownlib.py
+testing/cffi0/test_parsing.py
+testing/cffi0/test_platform.py
+testing/cffi0/test_unicode_literals.py
+testing/cffi0/test_verify.py
+testing/cffi0/test_verify2.py
+testing/cffi0/test_version.py
+testing/cffi0/test_vgen.py
+testing/cffi0/test_vgen2.py
+testing/cffi0/test_zdistutils.py
+testing/cffi0/test_zintegration.py
+testing/cffi0/snippets/distutils_module/setup.py
+testing/cffi0/snippets/distutils_module/snip_basic_verify.py
+testing/cffi0/snippets/distutils_package_1/setup.py
+testing/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py
+testing/cffi0/snippets/distutils_package_2/setup.py
+testing/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py
+testing/cffi0/snippets/infrastructure/setup.py
+testing/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py
+testing/cffi0/snippets/setuptools_module/setup.py
+testing/cffi0/snippets/setuptools_module/snip_setuptools_verify.py
+testing/cffi0/snippets/setuptools_package_1/setup.py
+testing/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
+testing/cffi0/snippets/setuptools_package_2/setup.py
+testing/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
+testing/cffi1/__init__.py
+testing/cffi1/test_cffi_binary.py
+testing/cffi1/test_dlopen.py
+testing/cffi1/test_dlopen_unicode_literals.py
+testing/cffi1/test_ffi_obj.py
+testing/cffi1/test_new_ffi_1.py
+testing/cffi1/test_parse_c_type.py
+testing/cffi1/test_re_python.py
+testing/cffi1/test_realize_c_type.py
+testing/cffi1/test_recompiler.py
+testing/cffi1/test_unicode_literals.py
+testing/cffi1/test_verify1.py
\ No newline at end of file
diff --git a/lib_pypy/cffi.egg-info/dependency_links.txt
b/lib_pypy/cffi.egg-info/dependency_links.txt
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/dependency_links.txt
@@ -0,0 +1,1 @@
+
diff --git a/lib_pypy/cffi.egg-info/entry_points.txt
b/lib_pypy/cffi.egg-info/entry_points.txt
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[distutils.setup_keywords]
+cffi_modules = cffi.setuptools_ext:cffi_modules
+
diff --git a/lib_pypy/cffi.egg-info/not-zip-safe
b/lib_pypy/cffi.egg-info/not-zip-safe
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/not-zip-safe
@@ -0,0 +1,1 @@
+
diff --git a/lib_pypy/cffi.egg-info/requires.txt
b/lib_pypy/cffi.egg-info/requires.txt
new file mode 100644
diff --git a/lib_pypy/cffi.egg-info/top_level.txt
b/lib_pypy/cffi.egg-info/top_level.txt
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi.egg-info/top_level.txt
@@ -0,0 +1,2 @@
+_cffi_backend
+cffi
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "0.9.2"
-__version_info__ = (0, 9, 2)
+__version__ = "1.0.0"
+__version_info__ = (1, 0, 0)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -0,0 +1,209 @@
+#include <Python.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stddef.h>
+#include "parse_c_type.h"
+
+/* 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)
+# include <alloca.h>
+# endif
+#endif
+
+
+/********** CPython-specific section **********/
+#ifndef PYPY_VERSION
+
+
+#if PY_MAJOR_VERSION >= 3
+# define PyInt_FromLong PyLong_FromLong
+#endif
+
+#define _cffi_from_c_double PyFloat_FromDouble
+#define _cffi_from_c_float PyFloat_FromDouble
+#define _cffi_from_c_long PyInt_FromLong
+#define _cffi_from_c_ulong PyLong_FromUnsignedLong
+#define _cffi_from_c_longlong PyLong_FromLongLong
+#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
+
+#define _cffi_to_c_double PyFloat_AsDouble
+#define _cffi_to_c_float PyFloat_AsDouble
+
+#define _cffi_from_c_int(x, type) \
+ (((type)-1) > 0 ? /* unsigned */ \
+ (sizeof(type) < sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ sizeof(type) == sizeof(long) ? \
+ PyLong_FromUnsignedLong((unsigned long)x) : \
+ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
+ (sizeof(type) <= sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ PyLong_FromLongLong((long long)x)))
+
+#define _cffi_to_c_int(o, type) \
+ (sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
+ : (type)_cffi_to_c_i8(o)) : \
+ sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
+ : (type)_cffi_to_c_i16(o)) : \
+ sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
+ : (type)_cffi_to_c_i32(o)) : \
+ sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
+ : (type)_cffi_to_c_i64(o)) : \
+ (Py_FatalError("unsupported size for type " #type), (type)0))
+
+#define _cffi_to_c_i8 \
+ ((int(*)(PyObject *))_cffi_exports[1])
+#define _cffi_to_c_u8 \
+ ((int(*)(PyObject *))_cffi_exports[2])
+#define _cffi_to_c_i16 \
+ ((int(*)(PyObject *))_cffi_exports[3])
+#define _cffi_to_c_u16 \
+ ((int(*)(PyObject *))_cffi_exports[4])
+#define _cffi_to_c_i32 \
+ ((int(*)(PyObject *))_cffi_exports[5])
+#define _cffi_to_c_u32 \
+ ((unsigned int(*)(PyObject *))_cffi_exports[6])
+#define _cffi_to_c_i64 \
+ ((long long(*)(PyObject *))_cffi_exports[7])
+#define _cffi_to_c_u64 \
+ ((unsigned long long(*)(PyObject *))_cffi_exports[8])
+#define _cffi_to_c_char \
+ ((int(*)(PyObject *))_cffi_exports[9])
+#define _cffi_from_c_pointer \
+ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
+#define _cffi_to_c_pointer \
+ ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
+#define _cffi_get_struct_layout \
+ not used any more
+#define _cffi_restore_errno \
+ ((void(*)(void))_cffi_exports[13])
+#define _cffi_save_errno \
+ ((void(*)(void))_cffi_exports[14])
+#define _cffi_from_c_char \
+ ((PyObject *(*)(char))_cffi_exports[15])
+#define _cffi_from_c_deref \
+ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
+#define _cffi_to_c \
+ ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
+#define _cffi_from_c_struct \
+ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
+#define _cffi_to_c_wchar_t \
+ ((wchar_t(*)(PyObject *))_cffi_exports[19])
+#define _cffi_from_c_wchar_t \
+ ((PyObject *(*)(wchar_t))_cffi_exports[20])
+#define _cffi_to_c_long_double \
+ ((long double(*)(PyObject *))_cffi_exports[21])
+#define _cffi_to_c__Bool \
+ ((_Bool(*)(PyObject *))_cffi_exports[22])
+#define _cffi_prepare_pointer_call_argument \
+ ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
+#define _cffi_convert_array_from_object \
+ ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
+#define _CFFI_NUM_EXPORTS 25
+
+typedef struct _ctypedescr CTypeDescrObject;
+
+static void *_cffi_exports[_CFFI_NUM_EXPORTS];
+
+#define _cffi_type(index) ( \
+ assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
+ (CTypeDescrObject *)_cffi_types[index])
+
+static PyObject *_cffi_init(const char *module_name, Py_ssize_t version,
+ const struct _cffi_type_context_s *ctx)
+{
+ PyObject *module, *o_arg, *new_module;
+ void *raw[] = {
+ (void *)module_name,
+ (void *)version,
+ (void *)_cffi_exports,
+ (void *)ctx,
+ };
+
+ module = PyImport_ImportModule("_cffi_backend");
+ if (module == NULL)
+ goto failure;
+
+ o_arg = PyLong_FromVoidPtr((void *)raw);
+ if (o_arg == NULL)
+ goto failure;
+
+ new_module = PyObject_CallMethod(
+ module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg);
+
+ Py_DECREF(o_arg);
+ Py_DECREF(module);
+ return new_module;
+
+ failure:
+ Py_XDECREF(module);
+ return NULL;
+}
+
+#endif
+/********** end CPython-specific section **********/
+
+
+#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
+
+#define _cffi_prim_int(size, sign) \
+ ((size) == sizeof(int) ? ((sign) ? _CFFI_PRIM_INT : _CFFI_PRIM_UINT) :
\
+ (size) == sizeof(long)? ((sign) ? _CFFI_PRIM_LONG : _CFFI_PRIM_ULONG) :
\
+ (size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) :
\
+ (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) :
\
+ (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) :
\
+ (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) :
\
+ 0)
+
+#define _cffi_check_int(got, got_nonpos, expected) \
+ ((got_nonpos) == (expected <= 0) && \
+ (got) == (unsigned long long)expected)
+
+#ifdef __GNUC__
+# define _CFFI_UNUSED_FN __attribute__((unused))
+#else
+# define _CFFI_UNUSED_FN /* nothing */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -70,6 +70,7 @@
self._function_caches = []
self._libraries = []
self._cdefsources = []
+ self._included_ffis = []
self._windows_unicode = None
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
@@ -418,12 +419,17 @@
variables, which must anyway be accessed directly from the
lib object returned by the original FFI instance.
"""
+ if not isinstance(ffi_to_include, FFI):
+ raise TypeError("ffi.include() expects an argument that is also of"
+ " type cffi.FFI, not %r" % (
+ type(ffi_to_include).__name__,))
with ffi_to_include._lock:
with self._lock:
self._parser.include(ffi_to_include._parser)
self._cdefsources.append('[')
self._cdefsources.extend(ffi_to_include._cdefsources)
self._cdefsources.append(']')
+ self._included_ffis.append(ffi_to_include)
def new_handle(self, x):
return self._backend.newp_handle(self.BVoidP, x)
@@ -469,6 +475,74 @@
('_UNICODE', '1')]
kwds['define_macros'] = defmacros
+ def set_source(self, module_name, source, source_extension='.c', **kwds):
+ if hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() cannot be called several times "
+ "per ffi object")
+ if not isinstance(module_name, basestring):
+ raise TypeError("'module_name' must be a string")
+ self._assigned_source = (str(module_name), source,
+ source_extension, kwds)
+
+ def distutils_extension(self, tmpdir='build', verbose=True):
+ from distutils.dir_util import mkpath
+ from .recompiler import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored
+ return self.verifier.get_extension()
+ raise ValueError("set_source() must be called before"
+ " distutils_extension()")
+ module_name, source, source_extension, kwds = self._assigned_source
+ if source is None:
+ raise TypeError("distutils_extension() is only for C extension "
+ "modules, not for dlopen()-style pure Python "
+ "modules")
+ mkpath(tmpdir)
+ ext, updated = recompile(self, module_name,
+ source, tmpdir=tmpdir,
+ source_extension=source_extension,
+ call_c_compiler=False, **kwds)
+ if verbose:
+ if updated:
+ sys.stderr.write("regenerated: %r\n" % (ext.sources[0],))
+ else:
+ sys.stderr.write("not modified: %r\n" % (ext.sources[0],))
+ return ext
+
+ def emit_c_code(self, filename):
+ from .recompiler import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() must be called before
emit_c_code()")
+ module_name, source, source_extension, kwds = self._assigned_source
+ if source is None:
+ raise TypeError("emit_c_code() is only for C extension modules, "
+ "not for dlopen()-style pure Python modules")
+ recompile(self, module_name, source,
+ c_file=filename, call_c_compiler=False, **kwds)
+
+ def emit_python_code(self, filename):
+ from .recompiler import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() must be called before
emit_c_code()")
+ module_name, source, source_extension, kwds = self._assigned_source
+ if source is not None:
+ raise TypeError("emit_python_code() is only for dlopen()-style "
+ "pure Python modules, not for C extension modules")
+ recompile(self, module_name, source,
+ c_file=filename, call_c_compiler=False, **kwds)
+
+ def compile(self, tmpdir='.'):
+ from .recompiler import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() must be called before compile()")
+ module_name, source, source_extension, kwds = self._assigned_source
+ return recompile(self, module_name, source, tmpdir=tmpdir,
+ source_extension=source_extension, **kwds)
+
def _load_backend_lib(backend, name, flags):
if name is None:
@@ -532,6 +606,11 @@
if name in library.__dict__:
return
#
+ key = 'constant ' + name
+ if key in ffi._parser._declarations:
+ raise NotImplementedError("fetching a non-integer constant "
+ "after dlopen()")
+ #
raise AttributeError(name)
#
def make_accessor(name):
diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/cffi_opcode.py
@@ -0,0 +1,171 @@
+
+class CffiOp(object):
+ def __init__(self, op, arg):
+ self.op = op
+ self.arg = arg
+
+ def as_c_expr(self):
+ if self.op is None:
+ assert isinstance(self.arg, str)
+ return '(_cffi_opcode_t)(%s)' % (self.arg,)
+ classname = CLASS_NAME[self.op]
+ return '_CFFI_OP(_CFFI_OP_%s, %d)' % (classname, self.arg)
+
+ def as_python_bytes(self):
+ if self.op is None:
+ if self.arg.isdigit():
+ value = int(self.arg) # non-negative: '-' not in self.arg
+ if value >= 2**31:
+ raise OverflowError("cannot emit %r: limited to 2**31-1"
+ % (self.arg,))
+ return format_four_bytes(value)
+ from .ffiplatform import VerificationError
+ raise VerificationError("cannot emit to Python: %r" % (self.arg,))
+ return format_four_bytes((self.arg << 8) | self.op)
+
+ def __str__(self):
+ classname = CLASS_NAME.get(self.op, self.op)
+ return '(%s %s)' % (classname, self.arg)
+
+def format_four_bytes(num):
+ return '\\x%02X\\x%02X\\x%02X\\x%02X' % (
+ (num >> 24) & 0xFF,
+ (num >> 16) & 0xFF,
+ (num >> 8) & 0xFF,
+ (num ) & 0xFF)
+
+OP_PRIMITIVE = 1
+OP_POINTER = 3
+OP_ARRAY = 5
+OP_OPEN_ARRAY = 7
+OP_STRUCT_UNION = 9
+OP_ENUM = 11
+OP_FUNCTION = 13
+OP_FUNCTION_END = 15
+OP_NOOP = 17
+OP_BITFIELD = 19
+OP_TYPENAME = 21
+OP_CPYTHON_BLTN_V = 23 # varargs
+OP_CPYTHON_BLTN_N = 25 # noargs
+OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg)
+OP_CONSTANT = 29
+OP_CONSTANT_INT = 31
+OP_GLOBAL_VAR = 33
+OP_DLOPEN_FUNC = 35
+
+PRIM_VOID = 0
+PRIM_BOOL = 1
+PRIM_CHAR = 2
+PRIM_SCHAR = 3
+PRIM_UCHAR = 4
+PRIM_SHORT = 5
+PRIM_USHORT = 6
+PRIM_INT = 7
+PRIM_UINT = 8
+PRIM_LONG = 9
+PRIM_ULONG = 10
+PRIM_LONGLONG = 11
+PRIM_ULONGLONG = 12
+PRIM_FLOAT = 13
+PRIM_DOUBLE = 14
+PRIM_LONGDOUBLE = 15
+
+PRIM_WCHAR = 16
+PRIM_INT8 = 17
+PRIM_UINT8 = 18
+PRIM_INT16 = 19
+PRIM_UINT16 = 20
+PRIM_INT32 = 21
+PRIM_UINT32 = 22
+PRIM_INT64 = 23
+PRIM_UINT64 = 24
+PRIM_INTPTR = 25
+PRIM_UINTPTR = 26
+PRIM_PTRDIFF = 27
+PRIM_SIZE = 28
+PRIM_SSIZE = 29
+PRIM_INT_LEAST8 = 30
+PRIM_UINT_LEAST8 = 31
+PRIM_INT_LEAST16 = 32
+PRIM_UINT_LEAST16 = 33
+PRIM_INT_LEAST32 = 34
+PRIM_UINT_LEAST32 = 35
+PRIM_INT_LEAST64 = 36
+PRIM_UINT_LEAST64 = 37
+PRIM_INT_FAST8 = 38
+PRIM_UINT_FAST8 = 39
+PRIM_INT_FAST16 = 40
+PRIM_UINT_FAST16 = 41
+PRIM_INT_FAST32 = 42
+PRIM_UINT_FAST32 = 43
+PRIM_INT_FAST64 = 44
+PRIM_UINT_FAST64 = 45
+PRIM_INTMAX = 46
+PRIM_UINTMAX = 47
+
+_NUM_PRIM = 48
+
+PRIMITIVE_TO_INDEX = {
+ 'char': PRIM_CHAR,
+ 'short': PRIM_SHORT,
+ 'int': PRIM_INT,
+ 'long': PRIM_LONG,
+ 'long long': PRIM_LONGLONG,
+ 'signed char': PRIM_SCHAR,
+ 'unsigned char': PRIM_UCHAR,
+ 'unsigned short': PRIM_USHORT,
+ 'unsigned int': PRIM_UINT,
+ 'unsigned long': PRIM_ULONG,
+ 'unsigned long long': PRIM_ULONGLONG,
+ 'float': PRIM_FLOAT,
+ 'double': PRIM_DOUBLE,
+ 'long double': PRIM_LONGDOUBLE,
+ '_Bool': PRIM_BOOL,
+ 'wchar_t': PRIM_WCHAR,
+ 'int8_t': PRIM_INT8,
+ 'uint8_t': PRIM_UINT8,
+ 'int16_t': PRIM_INT16,
+ 'uint16_t': PRIM_UINT16,
+ 'int32_t': PRIM_INT32,
+ 'uint32_t': PRIM_UINT32,
+ 'int64_t': PRIM_INT64,
+ 'uint64_t': PRIM_UINT64,
+ 'intptr_t': PRIM_INTPTR,
+ 'uintptr_t': PRIM_UINTPTR,
+ 'ptrdiff_t': PRIM_PTRDIFF,
+ 'size_t': PRIM_SIZE,
+ 'ssize_t': PRIM_SSIZE,
+ 'int_least8_t': PRIM_INT_LEAST8,
+ 'uint_least8_t': PRIM_UINT_LEAST8,
+ 'int_least16_t': PRIM_INT_LEAST16,
+ 'uint_least16_t': PRIM_UINT_LEAST16,
+ 'int_least32_t': PRIM_INT_LEAST32,
+ 'uint_least32_t': PRIM_UINT_LEAST32,
+ 'int_least64_t': PRIM_INT_LEAST64,
+ 'uint_least64_t': PRIM_UINT_LEAST64,
+ 'int_fast8_t': PRIM_INT_FAST8,
+ 'uint_fast8_t': PRIM_UINT_FAST8,
+ 'int_fast16_t': PRIM_INT_FAST16,
+ 'uint_fast16_t': PRIM_UINT_FAST16,
+ 'int_fast32_t': PRIM_INT_FAST32,
+ 'uint_fast32_t': PRIM_UINT_FAST32,
+ 'int_fast64_t': PRIM_INT_FAST64,
+ 'uint_fast64_t': PRIM_UINT_FAST64,
+ 'intmax_t': PRIM_INTMAX,
+ 'uintmax_t': PRIM_UINTMAX,
+ }
+
+F_UNION = 0x01
+F_CHECK_FIELDS = 0x02
+F_PACKED = 0x04
+F_EXTERNAL = 0x08
+F_OPAQUE = 0x10
+
+G_FLAGS = dict([('_CFFI_' + _key, globals()[_key])
+ for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED',
+ 'F_EXTERNAL', 'F_OPAQUE']])
+
+CLASS_NAME = {}
+for _name, _value in list(globals().items()):
+ if _name.startswith('OP_') and isinstance(_value, int):
+ CLASS_NAME[_value] = _name[3:]
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -23,7 +23,7 @@
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
_r_words = re.compile(r"\w+|\S")
_parser_cache = None
-_r_int_literal = re.compile(r"^0?x?[0-9a-f]+u?l?$", re.IGNORECASE)
+_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE)
def _get_parser():
global _parser_cache
@@ -95,6 +95,7 @@
def __init__(self):
self._declarations = {}
+ self._included_declarations = set()
self._anonymous_counter = 0
self._structnode2type = weakref.WeakKeyDictionary()
self._override = False
@@ -214,22 +215,26 @@
"multiple declarations of constant: %s" % (key,))
self._int_constants[key] = val
+ def _add_integer_constant(self, name, int_str):
+ int_str = int_str.lower().rstrip("ul")
+ neg = int_str.startswith('-')
+ if neg:
+ int_str = int_str[1:]
+ # "010" is not valid oct in py3
+ if (int_str.startswith("0") and int_str != '0'
+ and not int_str.startswith("0x")):
+ int_str = "0o" + int_str[1:]
+ pyvalue = int(int_str, 0)
+ if neg:
+ pyvalue = -pyvalue
+ self._add_constants(name, pyvalue)
+ self._declare('macro ' + name, pyvalue)
+
def _process_macros(self, macros):
for key, value in macros.items():
value = value.strip()
- match = _r_int_literal.search(value)
- if match is not None:
- int_str = match.group(0).lower().rstrip("ul")
-
- # "010" is not valid oct in py3
- if (int_str.startswith("0") and
- int_str != "0" and
- not int_str.startswith("0x")):
- int_str = "0o" + int_str[1:]
-
- pyvalue = int(int_str, 0)
- self._add_constants(key, pyvalue)
- self._declare('macro ' + key, pyvalue)
+ if _r_int_literal.match(value):
+ self._add_integer_constant(key, value)
elif value == '...':
self._declare('macro ' + key, value)
else:
@@ -251,22 +256,35 @@
self._declare('function ' + decl.name, tp)
else:
if isinstance(node, pycparser.c_ast.Struct):
- # XXX do we need self._declare in any of those?
- if node.decls is not None:
- self._get_struct_union_enum_type('struct', node)
+ self._get_struct_union_enum_type('struct', node)
elif isinstance(node, pycparser.c_ast.Union):
- if node.decls is not None:
- self._get_struct_union_enum_type('union', node)
+ self._get_struct_union_enum_type('union', node)
elif isinstance(node, pycparser.c_ast.Enum):
- if node.values is not None:
- self._get_struct_union_enum_type('enum', node)
+ self._get_struct_union_enum_type('enum', node)
elif not decl.name:
raise api.CDefError("construct does not declare any variable",
decl)
#
if decl.name:
tp = self._get_type(node, partial_length_ok=True)
- if self._is_constant_globalvar(node):
+ if tp.is_raw_function:
+ tp = self._get_type_pointer(tp)
+ self._declare('function ' + decl.name, tp)
+ elif (isinstance(tp, model.PrimitiveType) and
+ tp.is_integer_type() and
+ hasattr(decl, 'init') and
+ hasattr(decl.init, 'value') and
+ _r_int_literal.match(decl.init.value)):
+ self._add_integer_constant(decl.name, decl.init.value)
+ elif (isinstance(tp, model.PrimitiveType) and
+ tp.is_integer_type() and
+ isinstance(decl.init, pycparser.c_ast.UnaryOp) and
+ decl.init.op == '-' and
+ hasattr(decl.init.expr, 'value') and
+ _r_int_literal.match(decl.init.expr.value)):
+ self._add_integer_constant(decl.name,
+ '-' + decl.init.expr.value)
+ elif self._is_constant_globalvar(node):
self._declare('constant ' + decl.name, tp)
else:
self._declare('variable ' + decl.name, tp)
@@ -279,7 +297,7 @@
raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
return self._get_type(exprnode.type)
- def _declare(self, name, obj):
+ def _declare(self, name, obj, included=False):
if name in self._declarations:
if self._declarations[name] is obj:
return
@@ -289,10 +307,16 @@
"try cdef(xx, override=True))" % (name,))
assert '__dotdotdot__' not in name.split()
self._declarations[name] = obj
+ if included:
+ self._included_declarations.add(obj)
- def _get_type_pointer(self, type, const=False):
+ def _get_type_pointer(self, type, const=False, declname=None):
if isinstance(type, model.RawFunctionType):
return type.as_function_pointer()
+ if (isinstance(type, model.StructOrUnionOrEnum) and
+ type.name.startswith('$') and type.name[1:].isdigit() and
+ type.forcename is None and declname is not None):
+ return model.NamedPointerType(type, declname)
if const:
return model.ConstPointerType(type)
return model.PointerType(type)
@@ -319,7 +343,8 @@
# pointer type
const = (isinstance(typenode.type, pycparser.c_ast.TypeDecl)
and 'const' in typenode.type.quals)
- return self._get_type_pointer(self._get_type(typenode.type), const)
+ return self._get_type_pointer(self._get_type(typenode.type), const,
+ declname=name)
#
if isinstance(typenode, pycparser.c_ast.TypeDecl):
type = typenode.type
@@ -602,7 +627,9 @@
def include(self, other):
for name, tp in other._declarations.items():
kind = name.split(' ', 1)[0]
- if kind in ('typedef', 'struct', 'union', 'enum'):
- self._declare(name, tp)
+ if kind in ('struct', 'union', 'enum', 'anonymous'):
+ self._declare(name, tp, included=True)
+ elif kind == 'typedef':
+ self._declare(name, tp, included=True)
for k, v in other._int_constants.items():
self._add_constants(k, v)
diff --git a/lib_pypy/cffi/ffiplatform.py b/lib_pypy/cffi/ffiplatform.py
--- a/lib_pypy/cffi/ffiplatform.py
+++ b/lib_pypy/cffi/ffiplatform.py
@@ -1,4 +1,4 @@
-import os
+import sys, os
class VerificationError(Exception):
@@ -14,7 +14,17 @@
LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs',
'extra_objects', 'depends']
+def _hack_at_distutils():
+ # Windows-only workaround for some configurations: see
+ # https://bugs.python.org/issue23246 (Python 2.7.9)
+ if sys.platform == "win32":
+ try:
+ import setuptools # for side-effects, patches distutils
+ except ImportError:
+ pass
+
def get_extension(srcfilename, modname, sources=(), **kwds):
+ _hack_at_distutils() # *before* the following import
from distutils.core import Extension
allsources = [srcfilename]
allsources.extend(sources)
@@ -37,6 +47,7 @@
def _build(tmpdir, ext):
# XXX compact but horrible :-(
+ _hack_at_distutils()
from distutils.core import Distribution
import distutils.errors
#
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -31,6 +31,9 @@
def has_c_name(self):
return '$' not in self._get_c_name()
+
+ def sizeof_enabled(self):
+ return False
def get_cached_btype(self, ffi, finishlist, can_delay=False):
try:
@@ -102,8 +105,26 @@
'uint32_t': 'i',
'int64_t': 'i',
'uint64_t': 'i',
+ 'int_least8_t': 'i',
+ 'uint_least8_t': 'i',
+ 'int_least16_t': 'i',
+ 'uint_least16_t': 'i',
+ 'int_least32_t': 'i',
+ 'uint_least32_t': 'i',
+ 'int_least64_t': 'i',
+ 'uint_least64_t': 'i',
+ 'int_fast8_t': 'i',
+ 'uint_fast8_t': 'i',
+ 'int_fast16_t': 'i',
+ 'uint_fast16_t': 'i',
+ 'int_fast32_t': 'i',
+ 'uint_fast32_t': 'i',
+ 'int_fast64_t': 'i',
+ 'uint_fast64_t': 'i',
'intptr_t': 'i',
'uintptr_t': 'i',
+ 'intmax_t': 'i',
+ 'uintmax_t': 'i',
'ptrdiff_t': 'i',
'size_t': 'i',
'ssize_t': 'i',
@@ -121,6 +142,9 @@
def is_float_type(self):
return self.ALL_PRIMITIVE_TYPES[self.name] == 'f'
+ def sizeof_enabled(self):
+ return True
+
def build_backend_type(self, ffi, finishlist):
return global_cache(self, ffi, 'new_primitive_type', self.name)
@@ -161,6 +185,9 @@
class FunctionPtrType(BaseFunctionType):
_base_pattern = '(*&)(%s)'
+ def sizeof_enabled(self):
+ return True
+
def build_backend_type(self, ffi, finishlist):
result = self.result.get_cached_btype(ffi, finishlist)
args = []
@@ -169,6 +196,9 @@
return global_cache(self, ffi, 'new_function_type',
tuple(args), result, self.ellipsis)
+ def as_raw_function(self):
+ return RawFunctionType(self.args, self.result, self.ellipsis)
+
class PointerType(BaseType):
_attrs_ = ('totype',)
@@ -183,6 +213,9 @@
extra = self._base_pattern
self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra)
+ def sizeof_enabled(self):
+ return True
+
def build_backend_type(self, ffi, finishlist):
BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True)
return global_cache(self, ffi, 'new_pointer_type', BItem)
@@ -219,10 +252,13 @@
elif length == '...':
brackets = '&[/*...*/]'
else:
- brackets = '&[%d]' % length
+ brackets = '&[%s]' % length
self.c_name_with_marker = (
self.item.c_name_with_marker.replace('&', brackets))
+ def sizeof_enabled(self):
+ return self.item.sizeof_enabled() and self.length is not None
+
def resolve_length(self, newlength):
return ArrayType(self.item, newlength)
@@ -268,6 +304,14 @@
self.fldbitsize = fldbitsize
self.build_c_name_with_marker()
+ def has_anonymous_struct_fields(self):
+ if self.fldtypes is None:
+ return False
+ for name, type in zip(self.fldnames, self.fldtypes):
+ if name == '' and isinstance(type, StructOrUnion):
+ return True
+ return False
+
def enumfields(self):
for name, type, bitsize in zip(self.fldnames, self.fldtypes,
self.fldbitsize):
@@ -368,6 +412,9 @@
from . import ffiplatform
raise ffiplatform.VerificationMissing(self._get_c_name())
+ def sizeof_enabled(self):
+ return self.fldtypes is not None
+
def build_backend_type(self, ffi, finishlist):
self.check_not_partial()
finishlist.append(self)
@@ -396,6 +443,9 @@
self.baseinttype = baseinttype
self.build_c_name_with_marker()
+ def sizeof_enabled(self):
+ return True # not strictly true, but external enums are obscure
+
def force_the_name(self, forcename):
StructOrUnionOrEnum.force_the_name(self, forcename)
if self.forcename is None:
@@ -451,11 +501,12 @@
structname = '$%s' % name
tp = StructType(structname, None, None, None)
tp.force_the_name(name)
+ tp.origin = "unknown_type"
return tp
def unknown_ptr_type(name, structname=None):
if structname is None:
- structname = '*$%s' % name
+ structname = '$$%s' % name
tp = StructType(structname, None, None, None)
return NamedPointerType(tp, name)
diff --git a/lib_pypy/cffi/parse_c_type.h b/lib_pypy/cffi/parse_c_type.h
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/parse_c_type.h
@@ -0,0 +1,161 @@
+
+/* See doc/parse_c_type.rst in the source of CFFI for more information */
+
+typedef void *_cffi_opcode_t;
+
+#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg))
<< 8))
+#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode)
+#define _CFFI_GETARG(cffi_opcode) (((uintptr_t)cffi_opcode) >> 8)
+
+#define _CFFI_OP_PRIMITIVE 1
+#define _CFFI_OP_POINTER 3
+#define _CFFI_OP_ARRAY 5
+#define _CFFI_OP_OPEN_ARRAY 7
+#define _CFFI_OP_STRUCT_UNION 9
+#define _CFFI_OP_ENUM 11
+#define _CFFI_OP_FUNCTION 13
+#define _CFFI_OP_FUNCTION_END 15
+#define _CFFI_OP_NOOP 17
+#define _CFFI_OP_BITFIELD 19
+#define _CFFI_OP_TYPENAME 21
+#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs
+#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs
+#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg)
+#define _CFFI_OP_CONSTANT 29
+#define _CFFI_OP_CONSTANT_INT 31
+#define _CFFI_OP_GLOBAL_VAR 33
+#define _CFFI_OP_DLOPEN_FUNC 35
+
+#define _CFFI_PRIM_VOID 0
+#define _CFFI_PRIM_BOOL 1
+#define _CFFI_PRIM_CHAR 2
+#define _CFFI_PRIM_SCHAR 3
+#define _CFFI_PRIM_UCHAR 4
+#define _CFFI_PRIM_SHORT 5
+#define _CFFI_PRIM_USHORT 6
+#define _CFFI_PRIM_INT 7
+#define _CFFI_PRIM_UINT 8
+#define _CFFI_PRIM_LONG 9
+#define _CFFI_PRIM_ULONG 10
+#define _CFFI_PRIM_LONGLONG 11
+#define _CFFI_PRIM_ULONGLONG 12
+#define _CFFI_PRIM_FLOAT 13
+#define _CFFI_PRIM_DOUBLE 14
+#define _CFFI_PRIM_LONGDOUBLE 15
+
+#define _CFFI_PRIM_WCHAR 16
+#define _CFFI_PRIM_INT8 17
+#define _CFFI_PRIM_UINT8 18
+#define _CFFI_PRIM_INT16 19
+#define _CFFI_PRIM_UINT16 20
+#define _CFFI_PRIM_INT32 21
+#define _CFFI_PRIM_UINT32 22
+#define _CFFI_PRIM_INT64 23
+#define _CFFI_PRIM_UINT64 24
+#define _CFFI_PRIM_INTPTR 25
+#define _CFFI_PRIM_UINTPTR 26
+#define _CFFI_PRIM_PTRDIFF 27
+#define _CFFI_PRIM_SIZE 28
+#define _CFFI_PRIM_SSIZE 29
+#define _CFFI_PRIM_INT_LEAST8 30
+#define _CFFI_PRIM_UINT_LEAST8 31
+#define _CFFI_PRIM_INT_LEAST16 32
+#define _CFFI_PRIM_UINT_LEAST16 33
+#define _CFFI_PRIM_INT_LEAST32 34
+#define _CFFI_PRIM_UINT_LEAST32 35
+#define _CFFI_PRIM_INT_LEAST64 36
+#define _CFFI_PRIM_UINT_LEAST64 37
+#define _CFFI_PRIM_INT_FAST8 38
+#define _CFFI_PRIM_UINT_FAST8 39
+#define _CFFI_PRIM_INT_FAST16 40
+#define _CFFI_PRIM_UINT_FAST16 41
+#define _CFFI_PRIM_INT_FAST32 42
+#define _CFFI_PRIM_UINT_FAST32 43
+#define _CFFI_PRIM_INT_FAST64 44
+#define _CFFI_PRIM_UINT_FAST64 45
+#define _CFFI_PRIM_INTMAX 46
+#define _CFFI_PRIM_UINTMAX 47
+
+#define _CFFI__NUM_PRIM 48
+
+
+struct _cffi_global_s {
+ const char *name;
+ void *address;
+ _cffi_opcode_t type_op;
+ size_t size; // 0 if unknown
+};
+
+struct _cffi_getconst_s {
+ unsigned long long value;
+ const struct _cffi_type_context_s *ctx;
+ int gindex;
+};
+
+struct _cffi_struct_union_s {
+ const char *name;
+ int type_index; // -> _cffi_types, on a OP_STRUCT_UNION
+ int flags; // _CFFI_F_* flags below
+ size_t size;
+ int alignment;
+ int first_field_index; // -> _cffi_fields array
+ int num_fields;
+};
+#define _CFFI_F_UNION 0x01 // is a union, not a struct
+#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the
+ // "standard layout" or if some are
missing
+#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed
struct
+#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include()
+#define _CFFI_F_OPAQUE 0x10 // opaque
+
+struct _cffi_field_s {
+ const char *name;
+ size_t field_offset;
+ size_t field_size;
+ _cffi_opcode_t field_type_op;
+};
+
+struct _cffi_enum_s {
+ const char *name;
+ int type_index; // -> _cffi_types, on a OP_ENUM
+ int type_prim; // _CFFI_PRIM_xxx
+ const char *enumerators; // comma-delimited string
+};
+
+struct _cffi_typename_s {
+ const char *name;
+ int type_index; /* if opaque, points to a possibly artificial
+ OP_STRUCT which is itself opaque */
+};
+
+struct _cffi_type_context_s {
+ _cffi_opcode_t *types;
+ const struct _cffi_global_s *globals;
+ const struct _cffi_field_s *fields;
+ const struct _cffi_struct_union_s *struct_unions;
+ const struct _cffi_enum_s *enums;
+ const struct _cffi_typename_s *typenames;
+ int num_globals;
+ int num_struct_unions;
+ int num_enums;
+ int num_typenames;
+ const char *const *includes;
+ int num_types;
+ int flags; /* future extension */
+};
+
+struct _cffi_parse_info_s {
+ const struct _cffi_type_context_s *ctx;
+ _cffi_opcode_t *output;
+ unsigned int output_size;
+ size_t error_location;
+ const char *error_message;
+};
+
+#ifdef _CFFI_INTERNAL
+static int parse_c_type(struct _cffi_parse_info_s *info, const char *input);
+static int search_in_globals(const struct _cffi_type_context_s *ctx,
+ const char *search, size_t search_len);
+static int search_in_struct_unions(const struct _cffi_type_context_s *ctx,
+ const char *search, size_t search_len);
+#endif
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/recompiler.py
@@ -0,0 +1,1180 @@
+import os, sys, io
+from . import ffiplatform, model
+from .cffi_opcode import *
+
+VERSION = "0x2601"
+
+try:
+ int_type = (int, long)
+except NameError: # Python 3
+ int_type = int
+
+
+class GlobalExpr:
+ def __init__(self, name, address, type_op, size=0, check_value=None):
+ self.name = name
+ self.address = address
+ self.type_op = type_op
+ self.size = size
+ self.check_value = check_value
+
+ def as_c_expr(self):
+ return ' { "%s", (void *)%s, %s, %s },' % (
+ self.name, self.address, self.type_op.as_c_expr(), self.size)
+
+ def as_python_expr(self):
+ if not isinstance(self.check_value, int_type):
+ raise ffiplatform.VerificationError(
+ "ffi.dlopen() will not be able to figure out the value of "
+ "constant %r (only integer constants are supported, and only "
+ "if their value are specified in the cdef)" % (self.name,))
+ return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name,
+ self.check_value)
+
+class FieldExpr:
+ def __init__(self, name, field_offset, field_size, fbitsize,
field_type_op):
+ self.name = name
+ self.field_offset = field_offset
+ self.field_size = field_size
+ self.fbitsize = fbitsize
+ self.field_type_op = field_type_op
+
+ def as_c_expr(self):
+ spaces = " " * len(self.name)
+ return (' { "%s", %s,\n' % (self.name, self.field_offset) +
+ ' %s %s,\n' % (spaces, self.field_size) +
+ ' %s %s },' % (spaces, self.field_type_op.as_c_expr()))
+
+ def as_python_expr(self):
+ raise NotImplementedError
+
+ def as_field_python_expr(self):
+ if self.field_type_op.op == OP_NOOP:
+ size_expr = ''
+ elif self.field_type_op.op == OP_BITFIELD:
+ size_expr = format_four_bytes(self.fbitsize)
+ else:
+ raise NotImplementedError
+ return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(),
+ size_expr,
+ self.name)
+
+class StructUnionExpr:
+ def __init__(self, name, type_index, flags, size, alignment, comment,
+ first_field_index, c_fields):
+ self.name = name
+ self.type_index = type_index
+ self.flags = flags
+ self.size = size
+ self.alignment = alignment
+ self.comment = comment
+ self.first_field_index = first_field_index
+ self.c_fields = c_fields
+
+ def as_c_expr(self):
+ return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags)
+ + '\n %s, %s, ' % (self.size, self.alignment)
+ + '%d, %d ' % (self.first_field_index, len(self.c_fields))
+ + ('/* %s */ ' % self.comment if self.comment else '')
+ + '},')
+
+ def as_python_expr(self):
+ flags = eval(self.flags, G_FLAGS)
+ fields_expr = [c_field.as_field_python_expr()
+ for c_field in self.c_fields]
+ return "(b'%s%s%s',%s)" % (
+ format_four_bytes(self.type_index),
+ format_four_bytes(flags),
+ self.name,
+ ','.join(fields_expr))
+
+class EnumExpr:
+ def __init__(self, name, type_index, size, signed, allenums):
+ self.name = name
+ self.type_index = type_index
+ self.size = size
+ self.signed = signed
+ self.allenums = allenums
+
+ def as_c_expr(self):
+ return (' { "%s", %d, _cffi_prim_int(%s, %s),\n'
+ ' "%s" },' % (self.name, self.type_index,
+ self.size, self.signed, self.allenums))
+
+ def as_python_expr(self):
+ prim_index = {
+ (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8,
+ (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16,
+ (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32,
+ (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64,
+ }[self.size, self.signed]
+ return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index),
+ format_four_bytes(prim_index),
+ self.name, self.allenums)
+
+class TypenameExpr:
+ def __init__(self, name, type_index):
+ self.name = name
+ self.type_index = type_index
+
+ def as_c_expr(self):
+ return ' { "%s", %d },' % (self.name, self.type_index)
+
+ def as_python_expr(self):
+ return "b'%s%s'" % (format_four_bytes(self.type_index), self.name)
+
+
+# ____________________________________________________________
+
+
+class Recompiler:
+
+ def __init__(self, ffi, module_name, target_is_python=False):
+ self.ffi = ffi
+ self.module_name = module_name
+ self.target_is_python = target_is_python
+
+ def collect_type_table(self):
+ self._typesdict = {}
+ self._generate("collecttype")
+ #
+ all_decls = sorted(self._typesdict, key=str)
+ #
+ # prepare all FUNCTION bytecode sequences first
+ self.cffi_types = []
+ for tp in all_decls:
+ if tp.is_raw_function:
+ assert self._typesdict[tp] is None
+ self._typesdict[tp] = len(self.cffi_types)
+ self.cffi_types.append(tp) # placeholder
+ for tp1 in tp.args:
+ assert isinstance(tp1, (model.VoidType,
+ model.PrimitiveType,
+ model.PointerType,
+ model.StructOrUnionOrEnum,
+ model.FunctionPtrType))
+ if self._typesdict[tp1] is None:
+ self._typesdict[tp1] = len(self.cffi_types)
+ self.cffi_types.append(tp1) # placeholder
+ self.cffi_types.append('END') # placeholder
+ #
+ # prepare all OTHER bytecode sequences
+ for tp in all_decls:
+ if not tp.is_raw_function and self._typesdict[tp] is None:
+ self._typesdict[tp] = len(self.cffi_types)
+ self.cffi_types.append(tp) # placeholder
+ if tp.is_array_type and tp.length is not None:
+ self.cffi_types.append('LEN') # placeholder
+ assert None not in self._typesdict.values()
+ #
+ # collect all structs and unions and enums
+ self._struct_unions = {}
+ self._enums = {}
+ for tp in all_decls:
+ if isinstance(tp, model.StructOrUnion):
+ self._struct_unions[tp] = None
+ elif isinstance(tp, model.EnumType):
+ self._enums[tp] = None
+ for i, tp in enumerate(sorted(self._struct_unions,
+ key=lambda tp: tp.name)):
+ self._struct_unions[tp] = i
+ for i, tp in enumerate(sorted(self._enums,
+ key=lambda tp: tp.name)):
+ self._enums[tp] = i
+ #
+ # emit all bytecode sequences now
+ for tp in all_decls:
+ method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__)
+ method(tp, self._typesdict[tp])
+ #
+ # consistency check
+ for op in self.cffi_types:
+ assert isinstance(op, CffiOp)
+ self.cffi_types = tuple(self.cffi_types) # don't change any more
+
+ def _do_collect_type(self, tp):
+ if not isinstance(tp, model.BaseTypeByIdentity):
+ if isinstance(tp, tuple):
+ for x in tp:
+ self._do_collect_type(x)
+ return
+ if tp not in self._typesdict:
+ self._typesdict[tp] = None
+ if isinstance(tp, model.FunctionPtrType):
+ self._do_collect_type(tp.as_raw_function())
+ elif isinstance(tp, model.StructOrUnion):
+ if tp.fldtypes is not None and (
+ tp not in self.ffi._parser._included_declarations):
+ for name1, tp1, _ in tp.enumfields():
+ self._do_collect_type(self._field_type(tp, name1, tp1))
+ else:
+ for _, x in tp._get_items():
+ self._do_collect_type(x)
+
+ def _get_declarations(self):
+ return sorted(self.ffi._parser._declarations.items())
+
+ def _generate(self, step_name):
+ for name, tp in self._get_declarations():
+ kind, realname = name.split(' ', 1)
+ try:
+ method = getattr(self, '_generate_cpy_%s_%s' % (kind,
+ step_name))
+ except AttributeError:
+ raise ffiplatform.VerificationError(
+ "not implemented in recompile(): %r" % name)
+ try:
+ method(tp, realname)
+ except Exception as e:
+ model.attach_exception_info(e, name)
+ raise
+
+ # ----------
+
+ ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"]
+
+ def collect_step_tables(self):
+ # collect the declarations for '_cffi_globals', '_cffi_typenames', etc.
+ self._lsts = {}
+ for step_name in self.ALL_STEPS:
+ self._lsts[step_name] = []
+ self._seen_struct_unions = set()
+ self._generate("ctx")
+ self._add_missing_struct_unions()
+ #
+ for step_name in self.ALL_STEPS:
+ lst = self._lsts[step_name]
+ if step_name != "field":
+ lst.sort(key=lambda entry: entry.name)
+ self._lsts[step_name] = tuple(lst) # don't change any more
+ #
+ # check for a possible internal inconsistency: _cffi_struct_unions
+ # should have been generated with exactly self._struct_unions
+ lst = self._lsts["struct_union"]
+ for tp, i in self._struct_unions.items():
+ assert i < len(lst)
+ assert lst[i].name == tp.name
+ assert len(lst) == len(self._struct_unions)
+ # same with enums
+ lst = self._lsts["enum"]
+ for tp, i in self._enums.items():
+ assert i < len(lst)
+ assert lst[i].name == tp.name
+ assert len(lst) == len(self._enums)
+
+ # ----------
+
+ def _prnt(self, what=''):
+ self._f.write(what + '\n')
+
+ def write_source_to_f(self, f, preamble):
+ if self.target_is_python:
+ assert preamble is None
+ self.write_py_source_to_f(f)
+ else:
+ assert preamble is not None
+ self.write_c_source_to_f(f, preamble)
+
+ def _rel_readlines(self, filename):
+ g = open(os.path.join(os.path.dirname(__file__), filename), 'r')
+ lines = g.readlines()
+ g.close()
+ return lines
+
+ def write_c_source_to_f(self, f, preamble):
+ self._f = f
+ prnt = self._prnt
+ #
+ # first the '#include' (actually done by inlining the file's content)
+ lines = self._rel_readlines('_cffi_include.h')
+ i = lines.index('#include "parse_c_type.h"\n')
+ lines[i:i+1] = self._rel_readlines('parse_c_type.h')
+ prnt(''.join(lines))
+ #
+ # then paste the C source given by the user, verbatim.
+ prnt('/************************************************************/')
+ prnt()
+ prnt(preamble)
+ prnt()
+ prnt('/************************************************************/')
+ prnt()
+ #
+ # the declaration of '_cffi_types'
+ prnt('static void *_cffi_types[] = {')
+ typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
+ for i, op in enumerate(self.cffi_types):
+ comment = ''
+ if i in typeindex2type:
+ comment = ' // ' + typeindex2type[i]._get_c_name()
+ prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment))
+ if not self.cffi_types:
+ prnt(' 0')
+ prnt('};')
+ prnt()
+ #
+ # call generate_cpy_xxx_decl(), for every xxx found from
+ # ffi._parser._declarations. This generates all the functions.
+ self._seen_constants = set()
+ self._generate("decl")
+ #
+ # the declaration of '_cffi_globals' and '_cffi_typenames'
+ nums = {}
+ for step_name in self.ALL_STEPS:
+ lst = self._lsts[step_name]
+ nums[step_name] = len(lst)
+ if nums[step_name] > 0:
+ prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % (
+ step_name, step_name))
+ for entry in lst:
+ prnt(entry.as_c_expr())
+ prnt('};')
+ prnt()
+ #
+ # the declaration of '_cffi_includes'
+ if self.ffi._included_ffis:
+ prnt('static const char * const _cffi_includes[] = {')
+ for ffi_to_include in self.ffi._included_ffis:
+ try:
+ included_module_name, included_source = (
+ ffi_to_include._assigned_source[:2])
+ except AttributeError:
+ raise ffiplatform.VerificationError(
+ "ffi object %r includes %r, but the latter has not "
+ "been prepared with set_source()" % (
+ self.ffi, ffi_to_include,))
+ if included_source is None:
+ raise ffiplatform.VerificationError(
+ "not implemented yet: ffi.include() of a Python-based "
+ "ffi inside a C-based ffi")
+ prnt(' "%s",' % (included_module_name,))
+ prnt(' NULL')
+ prnt('};')
+ prnt()
+ #
+ # the declaration of '_cffi_type_context'
+ prnt('static const struct _cffi_type_context_s _cffi_type_context = {')
+ prnt(' _cffi_types,')
+ for step_name in self.ALL_STEPS:
+ if nums[step_name] > 0:
+ prnt(' _cffi_%ss,' % step_name)
+ else:
+ prnt(' NULL, /* no %ss */' % step_name)
+ for step_name in self.ALL_STEPS:
+ if step_name != "field":
+ prnt(' %d, /* num_%ss */' % (nums[step_name], step_name))
+ if self.ffi._included_ffis:
+ prnt(' _cffi_includes,')
+ else:
+ prnt(' NULL, /* no includes */')
+ prnt(' %d, /* num_types */' % (len(self.cffi_types),))
+ prnt(' 0, /* flags */')
+ prnt('};')
+ prnt()
+ #
+ # the init function
+ base_module_name = self.module_name.split('.')[-1]
+ prnt('#ifdef PYPY_VERSION')
+ prnt('PyMODINIT_FUNC')
+ prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
+ prnt('{')
+ prnt(' p[0] = (const void *)%s;' % VERSION)
+ prnt(' p[1] = &_cffi_type_context;')
+ prnt('}')
+ # on Windows, distutils insists on putting init_cffi_xyz in
+ # 'export_symbols', so instead of fighting it, just give up and
+ # give it one
+ prnt('# ifdef _MSC_VER')
+ prnt(' PyMODINIT_FUNC')
+ prnt('# if PY_MAJOR_VERSION >= 3')
+ prnt(' PyInit_%s(void) { return -1; }' % (base_module_name,))
+ prnt('# else')
+ prnt(' init%s(void) { }' % (base_module_name,))
+ prnt('# endif')
+ prnt('# endif')
+ prnt('#elif PY_MAJOR_VERSION >= 3')
+ prnt('PyMODINIT_FUNC')
+ prnt('PyInit_%s(void)' % (base_module_name,))
+ prnt('{')
+ prnt(' return _cffi_init("%s", %s, &_cffi_type_context);' % (
+ self.module_name, VERSION))
+ prnt('}')
+ prnt('#else')
+ prnt('PyMODINIT_FUNC')
+ prnt('init%s(void)' % (base_module_name,))
+ prnt('{')
+ prnt(' _cffi_init("%s", %s, &_cffi_type_context);' % (
+ self.module_name, VERSION))
+ prnt('}')
+ prnt('#endif')
+
+ def _to_py(self, x):
+ if isinstance(x, str):
+ return "b'%s'" % (x,)
+ if isinstance(x, (list, tuple)):
+ rep = [self._to_py(item) for item in x]
+ if len(rep) == 1:
+ rep.append('')
+ return "(%s)" % (','.join(rep),)
+ return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp.
+
+ def write_py_source_to_f(self, f):
+ self._f = f
+ prnt = self._prnt
+ #
+ # header
+ prnt("# auto-generated file")
+ prnt("import _cffi_backend")
+ #
+ # the 'import' of the included ffis
+ num_includes = len(self.ffi._included_ffis or ())
+ for i in range(num_includes):
+ ffi_to_include = self.ffi._included_ffis[i]
+ try:
+ included_module_name, included_source = (
+ ffi_to_include._assigned_source[:2])
+ except AttributeError:
+ raise ffiplatform.VerificationError(
+ "ffi object %r includes %r, but the latter has not "
+ "been prepared with set_source()" % (
+ self.ffi, ffi_to_include,))
+ if included_source is not None:
+ raise ffiplatform.VerificationError(
+ "not implemented yet: ffi.include() of a C-based "
+ "ffi inside a Python-based ffi")
+ prnt('from %s import ffi as _ffi%d' % (included_module_name, i))
+ prnt()
+ prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,))
+ prnt(" _version = %s," % (VERSION,))
+ #
+ # the '_types' keyword argument
+ self.cffi_types = tuple(self.cffi_types) # don't change any more
+ types_lst = [op.as_python_bytes() for op in self.cffi_types]
+ prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),))
+ typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
+ #
+ # the keyword arguments from ALL_STEPS
+ for step_name in self.ALL_STEPS:
+ lst = self._lsts[step_name]
+ if len(lst) > 0 and step_name != "field":
+ prnt(' _%ss = %s,' % (step_name, self._to_py(lst)))
+ #
+ # the '_includes' keyword argument
+ if num_includes > 0:
+ prnt(' _includes = (%s,),' % (
+ ', '.join(['_ffi%d' % i for i in range(num_includes)]),))
+ #
+ # the footer
+ prnt(')')
+
+ # ----------
+
+ def _gettypenum(self, type):
+ # a KeyError here is a bug. please report it! :-)
+ return self._typesdict[type]
+
+ def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
+ extraarg = ''
+ if isinstance(tp, model.PrimitiveType):
+ if tp.is_integer_type() and tp.name != '_Bool':
+ converter = '_cffi_to_c_int'
+ extraarg = ', %s' % tp.name
+ else:
+ converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
+ tp.name.replace(' ', '_'))
+ errvalue = '-1'
+ #
+ elif isinstance(tp, model.PointerType):
+ self._convert_funcarg_to_c_ptr_or_array(tp, fromvar,
+ tovar, errcode)
+ return
+ #
+ elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
+ # a struct (not a struct pointer) as a function argument
+ self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
+ % (tovar, self._gettypenum(tp), fromvar))
+ self._prnt(' %s;' % errcode)
+ return
+ #
+ elif isinstance(tp, model.FunctionPtrType):
+ converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
+ extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
+ errvalue = 'NULL'
+ #
+ else:
+ raise NotImplementedError(tp)
+ #
+ self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
+ self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
+ tovar, tp.get_c_name(''), errvalue))
+ self._prnt(' %s;' % errcode)
+
+ def _extra_local_variables(self, tp, localvars):
+ if isinstance(tp, model.PointerType):
+ localvars.add('Py_ssize_t datasize')
+
+ def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
+ self._prnt(' datasize = _cffi_prepare_pointer_call_argument(')
+ self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % (
+ self._gettypenum(tp), fromvar, tovar))
+ self._prnt(' if (datasize != 0) {')
+ self._prnt(' if (datasize < 0)')
+ self._prnt(' %s;' % errcode)
+ self._prnt(' %s = (%s)alloca((size_t)datasize);' % (
+ tovar, tp.get_c_name('')))
+ self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
+ self._prnt(' if (_cffi_convert_array_from_object('
+ '(char *)%s, _cffi_type(%d), %s) < 0)' % (
+ tovar, self._gettypenum(tp), fromvar))
+ self._prnt(' %s;' % errcode)
+ self._prnt(' }')
+
+ def _convert_expr_from_c(self, tp, var, context):
+ if isinstance(tp, model.PrimitiveType):
+ if tp.is_integer_type():
+ return '_cffi_from_c_int(%s, %s)' % (var, tp.name)
+ elif tp.name != 'long double':
+ return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var)
+ else:
+ return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, (model.PointerType, model.FunctionPtrType)):
+ return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, model.ArrayType):
+ return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
+ var, self._gettypenum(model.PointerType(tp.item)))
+ elif isinstance(tp, model.StructType):
+ if tp.fldnames is None:
+ raise TypeError("'%s' is used as %s, but is opaque" % (
+ tp._get_c_name(), context))
+ return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, model.EnumType):
+ return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ else:
+ raise NotImplementedError(tp)
+
+ # ----------
+ # typedefs
+
+ def _generate_cpy_typedef_collecttype(self, tp, name):
+ self._do_collect_type(tp)
+
+ def _generate_cpy_typedef_decl(self, tp, name):
+ pass
+
+ def _typedef_ctx(self, tp, name):
+ type_index = self._typesdict[tp]
+ self._lsts["typename"].append(TypenameExpr(name, type_index))
+
+ def _generate_cpy_typedef_ctx(self, tp, name):
+ self._typedef_ctx(tp, name)
+ if getattr(tp, "origin", None) == "unknown_type":
+ self._struct_ctx(tp, tp.name, approxname=None)
+ elif isinstance(tp, model.NamedPointerType):
+ self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name,
+ named_ptr=tp)
+
+ # ----------
+ # function declarations
+
+ def _generate_cpy_function_collecttype(self, tp, name):
+ self._do_collect_type(tp.as_raw_function())
+ if tp.ellipsis:
+ self._do_collect_type(tp)
+
+ def _generate_cpy_function_decl(self, tp, name):
+ assert isinstance(tp, model.FunctionPtrType)
+ if tp.ellipsis:
+ # cannot support vararg functions better than this: check for its
+ # exact type (including the fixed arguments), and build it as a
+ # constant function pointer (no CPython wrapper)
+ self._generate_cpy_constant_decl(tp, name)
+ return
+ prnt = self._prnt
+ numargs = len(tp.args)
+ if numargs == 0:
+ argname = 'noarg'
+ elif numargs == 1:
+ argname = 'arg0'
+ else:
+ argname = 'args'
+ #
+ prnt('#ifndef PYPY_VERSION') # ------------------------------
+ #
+ prnt('static PyObject *')
+ prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
+ prnt('{')
+ #
+ context = 'argument of %s' % name
+ for i, type in enumerate(tp.args):
+ arg = type.get_c_name(' x%d' % i, context)
+ prnt(' %s;' % arg)
+ #
+ localvars = set()
+ for type in tp.args:
+ self._extra_local_variables(type, localvars)
+ for decl in localvars:
+ prnt(' %s;' % (decl,))
+ #
+ if not isinstance(tp.result, model.VoidType):
+ result_code = 'result = '
+ context = 'result of %s' % name
+ result_decl = ' %s;' % tp.result.get_c_name(' result', context)
+ prnt(result_decl)
+ else:
+ result_decl = None
+ result_code = ''
+ #
+ if len(tp.args) > 1:
+ rng = range(len(tp.args))
+ for i in rng:
+ prnt(' PyObject *arg%d;' % i)
+ prnt()
+ prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
+ 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng])))
+ prnt(' return NULL;')
+ prnt()
+ #
+ for i, type in enumerate(tp.args):
+ self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
+ 'return NULL')
+ prnt()
+ #
+ prnt(' Py_BEGIN_ALLOW_THREADS')
+ prnt(' _cffi_restore_errno();')
+ call_arguments = ['x%d' % i for i in range(len(tp.args))]
+ call_arguments = ', '.join(call_arguments)
+ prnt(' { %s%s(%s); }' % (result_code, name, call_arguments))
+ prnt(' _cffi_save_errno();')
+ prnt(' Py_END_ALLOW_THREADS')
+ prnt()
+ #
+ prnt(' (void)self; /* unused */')
+ if numargs == 0:
+ prnt(' (void)noarg; /* unused */')
+ if result_code:
+ prnt(' return %s;' %
+ self._convert_expr_from_c(tp.result, 'result', 'result type'))
+ else:
+ prnt(' Py_INCREF(Py_None);')
+ prnt(' return Py_None;')
+ prnt('}')
+ #
+ prnt('#else') # ------------------------------
+ #
+ # the PyPy version: need to replace struct/union arguments with
+ # pointers, and if the result is a struct/union, insert a first
+ # arg that is a pointer to the result.
+ arguments = []
+ call_arguments = []
+ context = 'argument of %s' % name
+ for i, type in enumerate(tp.args):
+ indirection = ''
+ if isinstance(type, model.StructOrUnion):
+ indirection = '*'
+ arg = type.get_c_name(' %sx%d' % (indirection, i), context)
+ arguments.append(arg)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit