[pypy-commit] cffi cffi-1.0: in-progress
arigo
noreply at buildbot.pypy.org
Tue Apr 14 15:35:24 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1699:943c257b5873
Date: 2015-04-14 15:35 +0200
http://bitbucket.org/cffi/cffi/changeset/943c257b5873/
Log: in-progress
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3338,7 +3338,7 @@
/************************************************************/
-static PyObject *b_new_primitive_type(PyObject *self, PyObject *args)
+static CTypeDescrObject *new_primitive_type(const char *name)
{
#define ENUM_PRIMITIVE_TYPES \
EPTYPE(c, char, CT_PRIMITIVE_CHAR) \
@@ -3403,7 +3403,6 @@
#undef EPTYPE
CTypeDescrObject *td;
- const char *name;
static const struct descr_s { const char *name; int size, align, flags; }
types[] = {
#define EPTYPE(code, typename, flags) \
@@ -3422,9 +3421,6 @@
int name_size;
ffi_type *ffitype;
- if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name))
- return NULL;
-
for (ptypes=types; ; ptypes++) {
if (ptypes->name == NULL) {
#ifndef HAVE_WCHAR_H
@@ -3487,7 +3483,7 @@
td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
}
td->ct_name_position = strlen(td->ct_name);
- return (PyObject *)td;
+ return td;
bad_ffi_type:
PyErr_Format(PyExc_NotImplementedError,
@@ -3497,15 +3493,19 @@
return NULL;
}
-static PyObject *b_new_pointer_type(PyObject *self, PyObject *args)
-{
- CTypeDescrObject *td, *ctitem;
+static PyObject *b_new_primitive_type(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name))
+ return NULL;
+ return (PyObject *)new_primitive_type(name);
+}
+
+static CTypeDescrObject *new_pointer_type(CTypeDescrObject *ctitem)
+{
+ CTypeDescrObject *td;
const char *extra;
- if (!PyArg_ParseTuple(args, "O!:new_pointer_type",
- &CTypeDescr_Type, &ctitem))
- return NULL;
-
if (ctitem->ct_flags & CT_ARRAY)
extra = "(*)"; /* obscure case: see test_array_add */
else
@@ -3525,7 +3525,16 @@
((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
ctitem->ct_size == sizeof(char)))
td->ct_flags |= CT_CAST_ANYTHING; /* 'void *' or 'char *' only */
- return (PyObject *)td;
+ return td;
+}
+
+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 (PyObject *)new_pointer_type(ctitem);
}
static PyObject *b_new_array_type(PyObject *self, PyObject *args)
@@ -3594,7 +3603,7 @@
return (PyObject *)td;
}
-static PyObject *b_new_void_type(PyObject *self, PyObject *args)
+static CTypeDescrObject *new_void_type(void)
{
int name_size = strlen("void") + 1;
CTypeDescrObject *td = ctypedescr_new(name_size);
@@ -3605,7 +3614,12 @@
td->ct_size = -1;
td->ct_flags = CT_VOID | CT_IS_OPAQUE;
td->ct_name_position = strlen("void");
- return (PyObject *)td;
+ return td;
+}
+
+static PyObject *b_new_void_type(PyObject *self, PyObject *args)
+{
+ return (PyObject *)new_void_type();
}
static PyObject *_b_struct_or_union_type(const char *name, int flag)
@@ -5683,8 +5697,10 @@
}
#endif
+#include "../new/cffi1_module.c"
+
static void *cffi_exports[] = {
- 0,
+ (void *)26,
_cffi_to_c_i8,
_cffi_to_c_u8,
_cffi_to_c_i16,
@@ -5714,6 +5730,7 @@
_cffi_to_c__Bool,
_prepare_pointer_call_argument,
convert_array_from_object,
+ _cffi_init_module,
};
/************************************************************/
diff --git a/new/_cffi_include.h b/new/_cffi_include.h
new file mode 100644
--- /dev/null
+++ b/new/_cffi_include.h
@@ -0,0 +1,191 @@
+#include <Python.h>
+#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
+
+#if PY_MAJOR_VERSION < 3
+# undef PyCapsule_CheckExact
+# undef PyCapsule_GetPointer
+# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
+# define PyCapsule_GetPointer(capsule, name) \
+ (PyCObject_AsVoidPtr(capsule))
+#endif
+
+#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_const(x) \
+ (((x) > 0) ? \
+ ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \
+ PyInt_FromLong((long)(x)) : \
+ PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \
+ ((long long)(x) >= (long long)LONG_MIN) ? \
+ PyInt_FromLong((long)(x)) : \
+ PyLong_FromLongLong((long long)(x)))
+
+#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 \
+ ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12])
+#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_init_module \
+ ((int(*)(char *, const struct _cffi_type_context_s *))_cffi_exports[25])
+#define _CFFI_NUM_EXPORTS 26
+
+typedef struct _ctypedescr CTypeDescrObject;
+
+static void *_cffi_exports[_CFFI_NUM_EXPORTS];
+
+
+static int _cffi_init(void)
+{
+ PyObject *module, *c_api_object = NULL;
+ void *src;
+
+ module = PyImport_ImportModule("_cffi_backend");
+ if (module == NULL)
+ goto failure;
+
+ c_api_object = PyObject_GetAttrString(module, "_C_API");
+ if (c_api_object == NULL)
+ goto failure;
+ if (!PyCapsule_CheckExact(c_api_object)) {
+ PyErr_SetNone(PyExc_ImportError);
+ goto failure;
+ }
+ src = PyCapsule_GetPointer(c_api_object, "cffi");
+ if ((uintptr_t)(((void **)src)[0]) < _CFFI_NUM_EXPORTS) {
+ PyErr_SetString(PyExc_ImportError,
+ "the _cffi_backend module is an outdated version");
+ goto failure;
+ }
+ memcpy(_cffi_exports, src, _CFFI_NUM_EXPORTS * sizeof(void *));
+
+ Py_DECREF(module);
+ Py_DECREF(c_api_object);
+ return 0;
+
+ failure:
+ Py_XDECREF(module);
+ Py_XDECREF(c_api_object);
+ return -1;
+}
diff --git a/new/cffi1_module.c b/new/cffi1_module.c
new file mode 100644
--- /dev/null
+++ b/new/cffi1_module.c
@@ -0,0 +1,52 @@
+#include "parse_c_type.c"
+#include "realize_c_type.c"
+
+typedef struct FFIObject_s FFIObject;
+typedef struct LibObject_s LibObject;
+
+static PyTypeObject FFI_Type; /* forward */
+static PyTypeObject Lib_Type; /* forward */
+
+static PyObject *FFIError;
+
+#include "ffi_obj.c"
+//#include "lib_obj.c"
+
+
+static int init_ffi_lib(void)
+{
+ static int ffi_lib_ok = 0;
+ if (ffi_lib_ok)
+ return 0;
+
+ if (!PyType_Ready(&FFI_Type) < 0)
+ return -1;
+ if (!PyType_Ready(&Lib_Type) < 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;
+
+ ffi_lib_ok = 1;
+ return 0;
+}
+
+static int _cffi_init_module(char *module_name,
+ const struct _cffi_type_context_s *ctx)
+{
+ if (init_ffi_lib() < 0)
+ return -1;
+
+ PyObject *m = Py_InitModule(module_name, NULL);
+ if (m == NULL)
+ return -1;
+
+ FFIObject *ffi = ffi_internal_new(ctx);
+ if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/new/ffi_obj.c b/new/ffi_obj.c
new file mode 100644
--- /dev/null
+++ b/new/ffi_obj.c
@@ -0,0 +1,603 @@
+
+/* 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 */
+
+struct FFIObject_s {
+ PyObject_HEAD
+ PyObject *types_dict;
+ PyObject *gc_wrefs;
+ struct _cffi_parse_info_s info;
+ _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT];
+};
+
+static FFIObject *ffi_internal_new(const struct _cffi_type_context_s *ctx)
+{
+ PyObject *dict = PyDict_New();
+ if (dict == NULL)
+ return NULL;
+
+ FFIObject *ffi = PyObject_GC_New(FFIObject, &FFI_Type);
+ if (ffi == NULL) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ ffi->types_dict = dict;
+ ffi->gc_wrefs = NULL;
+ ffi->info.ctx = ctx;
+ ffi->info.output = ffi->internal_output;
+ ffi->info.output_size = FFI_COMPLEXITY_OUTPUT;
+
+ PyObject_GC_Track(ffi);
+ return ffi;
+}
+
+static void ffi_dealloc(FFIObject *ffi)
+{
+ PyObject_GC_UnTrack(ffi);
+ Py_DECREF(ffi->types_dict);
+ Py_XDECREF(ffi->gc_wrefs);
+ PyObject_GC_Del(ffi);
+}
+
+static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg)
+{
+ Py_VISIT(ffi->types_dict);
+ 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 */
+ /* XXX LATER */
+ PyErr_SetString(PyExc_NotImplementedError, "FFI()");
+ return NULL;
+}
+
+#define ACCEPT_STRING 1
+#define ACCEPT_CTYPE 2
+#define ACCEPT_CDATA 4
+#define ACCEPT_ALL (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA)
+
+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 *x = PyDict_GetItem(ffi->types_dict, arg);
+ if (x != NULL && CTypeDescr_Check(x))
+ return (CTypeDescrObject *)x;
+
+ char *input_text = PyText_AS_UTF8(arg);
+ int index = parse_c_type(&ffi->info, input_text);
+ if (index < 0) {
+ size_t num_spaces = ffi->info.error_location;
+ char spaces[num_spaces + 1];
+ memset(spaces, ' ', num_spaces);
+ spaces[num_spaces] = '\0';
+ PyErr_Format(FFIError, "%s\n%s\n%s^", ffi->info.error_message,
+ input_text, spaces);
+ return NULL;
+ }
+ CTypeDescrObject *ct = realize_c_type(ffi->info.ctx,
+ ffi->info.output, index);
+ if (ct == NULL)
+ return NULL;
+ x = PyDict_GetItemString(ffi->types_dict, ct->ct_name);
+ if (x != NULL) {
+ Py_INCREF(x);
+ Py_DECREF(ct);
+ ct = (CTypeDescrObject *)x;
+ }
+ PyDict_SetItemString(ffi->types_dict, ct->ct_name, (PyObject *)ct);
+ PyDict_SetItem(ffi->types_dict, arg, (PyObject *)ct);
+ return ct;
+ }
+ else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) {
+ return (CTypeDescrObject *)arg;
+ }
+ else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) {
+ return ((CDataObject *)arg)->c_type;
+ }
+ 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;
+ }
+}
+
+static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg)
+{
+ CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
+ if (ct == NULL)
+ return NULL;
+
+ if (ct->ct_size < 0) {
+ PyErr_Format(FFIError, "don't know the size of ctype '%s'",
+ ct->ct_name);
+ return NULL;
+ }
+ return PyInt_FromSsize_t(ct->ct_size);
+}
+
+#if 0
+static PyObject *ffi_typeof(ZefFFIObject *self, PyObject *arg)
+{
+ PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA);
+ if (x != NULL) {
+ Py_INCREF(x);
+ }
+ else if (PyCFunction_Check(arg)) {
+ PyErr_SetString(PyExc_TypeError, "typeof(lib.func) not supported: the "
+ "exact type of functions is unknown (declare that "
+ "function as a function pointer instead)");
+ }
+ return x;
+}
+
+static PyObject *ffi_new(ZefFFIObject *self, PyObject *args)
+{
+ CTypeDescrObject *ct, *ctitem;
+ CDataObject *cd;
+ PyObject *arg, *init = Py_None;
+ Py_ssize_t dataoffset, datasize, explicitlength;
+ if (!PyArg_ParseTuple(args, "O|O:new", &arg, &init))
+ return NULL;
+
+ ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
+ if (ct == NULL)
+ return NULL;
+
+ explicitlength = -1;
+ if (ct->ct_flags & (CT_POINTER | CT_STRUCT | CT_UNION)) {
+ dataoffset = offsetof(CDataObject_own_nolength, alignment);
+ ctitem = (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct;
+ 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_WITH_VAR_ARRAY) && 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(&init);
+ if (explicitlength < 0)
+ return NULL;
+ ctitem = ct->ct_itemdescr;
+ dataoffset = offsetof(CDataObject_own_length, alignment);
+ datasize = 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 if (ct->ct_flags & CT_PRIMITIVE_ANY) {
+ cd = _new_casted_primitive(ct);
+ datasize = ct->ct_size;
+ goto initialize_casted_primitive;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "cannot create cdata '%s' objects", ct->ct_name);
+ return NULL;
+ }
+
+ cd = allocate_owning_object(dataoffset + datasize, ct);
+ if (cd == NULL)
+ return NULL;
+
+ cd->c_data = ((char *)cd) + dataoffset;
+ if (explicitlength >= 0)
+ ((CDataObject_own_length*)cd)->length = explicitlength;
+
+ initialize_casted_primitive:
+ memset(cd->c_data, 0, datasize);
+ 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 *ffi_cast(ZefFFIObject *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);
+}
+
+static PyObject *ffi_string(ZefFFIObject *self, PyObject *args)
+{
+ CDataObject *cd;
+ Py_ssize_t maxlen = -1;
+ if (!PyArg_ParseTuple(args, "O!|n:string",
+ &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)) {
+ 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_flags & CT_IS_ENUM) {
+ abort();
+ //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);
+ }
+ PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument",
+ cd->c_type->ct_name);
+ return NULL;
+}
+
+static CFieldObject *_ffi_field(CTypeDescrObject *ct, const char *fieldname)
+{
+ CFieldObject *cf;
+ if (ct->ct_stuff == NULL) {
+ PyErr_Format(PyExc_TypeError, "'%s' is incomplete", ct->ct_name);
+ return NULL;
+ }
+ cf = (CFieldObject *)PyDict_GetItemString(ct->ct_stuff, fieldname);
+ if (cf == NULL) {
+ PyErr_Format(PyExc_KeyError, "'%s' has got no field '%s'",
+ ct->ct_name, fieldname);
+ return NULL;
+ }
+ if (cf->cf_bitshift >= 0) {
+ PyErr_SetString(PyExc_TypeError, "not supported for bitfields");
+ return NULL;
+ }
+ return cf;
+}
+
+static PyObject *ffi_offsetof(ZefFFIObject *self, PyObject *args)
+{
+ PyObject *arg;
+ char *fieldname;
+ CTypeDescrObject *ct;
+ CFieldObject *cf;
+
+ if (!PyArg_ParseTuple(args, "Os:offsetof", &arg, &fieldname))
+ return NULL;
+
+ ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
+ if (ct == NULL)
+ return NULL;
+
+ if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a struct or union ctype, got '%s'",
+ ct->ct_name);
+ return NULL;
+ }
+ cf = _ffi_field(ct, fieldname);
+ if (cf == NULL)
+ return NULL;
+ return PyInt_FromSsize_t(cf->cf_offset);
+}
+
+static PyObject *ffi_addressof(ZefFFIObject *self, PyObject *args)
+{
+ PyObject *obj;
+ char *fieldname = NULL;
+
+ if (!PyArg_ParseTuple(args, "O|z:addressof", &obj, &fieldname))
+ return NULL;
+
+ if (CData_Check(obj)) {
+ CDataObject *cd = (CDataObject *)obj;
+ CTypeDescrObject *ct;
+ Py_ssize_t offset;
+
+ ct = cd->c_type;
+ if (fieldname != NULL && ct->ct_flags & CT_POINTER)
+ ct = ct->ct_itemdescr;
+
+ if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a struct or union cdata, got '%s'",
+ ct->ct_name);
+ return NULL;
+ }
+
+ if (fieldname == NULL) {
+ offset = 0;
+ }
+ else {
+ CFieldObject *cf = _ffi_field(ct, fieldname);
+ if (cf == NULL)
+ return NULL;
+ offset = cf->cf_offset;
+ ct = cf->cf_type;
+ }
+ ct = fetch_pointer_type(self->types_dict, ct);
+ if (ct == NULL)
+ return NULL;
+ return new_simple_cdata(cd->c_data + offset, ct);
+ }
+ else if (ZefLib_Check(obj)) {
+ PyObject *attr, *name;
+ char *reason;
+
+ if (fieldname == NULL) {
+ PyErr_SetString(PyExc_TypeError, "addressof(Lib, fieldname) "
+ "cannot be used with only one argument");
+ return NULL;
+ }
+ name = PyString_FromString(fieldname);
+ if (name == NULL)
+ return NULL;
+ attr = lib_findattr((ZefLibObject *)obj, name, ZefError);
+ Py_DECREF(name);
+ if (attr == NULL)
+ return NULL;
+
+ if (ZefGlobSupport_Check(attr)) {
+ return addressof_global_var((ZefGlobSupportObject *)attr);
+ }
+
+ if (PyCFunction_Check(attr))
+ reason = "declare that function as a function pointer instead";
+ else
+ reason = "numeric constants don't have addresses";
+
+ PyErr_Format(PyExc_TypeError,
+ "cannot take the address of '%s' (%s)",
+ fieldname, reason);
+ return NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "addressof() first argument must be "
+ "a cdata struct or union, a pointer to one, or a Lib "
+ "object");
+ return NULL;
+ }
+}
+
+static PyObject *ffi_getctype(ZefFFIObject *self, PyObject *args)
+{
+ PyObject *cdecl, *res;
+ char *p, *replace_with = "";
+ int add_paren, add_space;
+ CTypeDescrObject *ct;
+ size_t replace_with_len;
+
+ if (!PyArg_ParseTuple(args, "O|s:getctype", &cdecl, &replace_with))
+ return NULL;
+
+ ct = _ffi_type(self, cdecl, 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 | CT_FUNCTION)) != 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 = PyString_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] = ')';
+ return res;
+}
+
+static PyObject *ffi_new_handle(ZefFFIObject *self, PyObject *arg)
+{
+ CTypeDescrObject *ct = ZefNULL->c_type; // <ctype 'void *'>
+ CDataObject *cd;
+
+ cd = (CDataObject *)PyObject_GC_New(CDataObject, &CDataOwningGC_Type);
+ if (cd == NULL)
+ return NULL;
+ Py_INCREF(ct);
+ cd->c_type = ct;
+ Py_INCREF(arg);
+ cd->c_data = ((char *)arg) - 42;
+ cd->c_weakreflist = NULL;
+ PyObject_GC_Track(cd);
+ return (PyObject *)cd;
+}
+
+static PyObject *ffi_from_handle(PyObject *self, PyObject *arg)
+{
+ CTypeDescrObject *ct;
+ char *raw;
+ PyObject *x;
+ if (!CData_Check(arg)) {
+ PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
+ return NULL;
+ }
+ ct = ((CDataObject *)arg)->c_type;
+ raw = ((CDataObject *)arg)->c_data;
+ if (!(ct->ct_flags & CT_CAST_ANYTHING)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a 'cdata' object with a 'void *' out of "
+ "new_handle(), got '%s'", ct->ct_name);
+ return NULL;
+ }
+ if (!raw) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot use from_handle() on NULL pointer");
+ return NULL;
+ }
+ x = (PyObject *)(raw + 42);
+ Py_INCREF(x);
+ return x;
+}
+
+static PyObject *ffi_gc(ZefFFIObject *self, PyObject *args)
+{
+ CDataObject *cd;
+ PyObject *destructor;
+
+ if (!PyArg_ParseTuple(args, "O!O:gc", &CData_Type, &cd, &destructor))
+ return NULL;
+
+ return gc_weakrefs_build(self, cd, destructor);
+}
+#endif
+
+static PyMethodDef ffi_methods[] = {
+#if 0
+ {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS},
+ {"cast", (PyCFunction)ffi_cast, METH_VARARGS},
+ {"close_library", ffi_close_library, METH_VARARGS | METH_STATIC},
+ {"from_handle", (PyCFunction)ffi_from_handle,METH_O},
+ {"gc", (PyCFunction)ffi_gc, METH_VARARGS},
+ {"getctype", (PyCFunction)ffi_getctype, METH_VARARGS},
+ {"load_library", (PyCFunction)ffi_load_library,METH_VARARGS|METH_KEYWORDS},
+ {"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS},
+ {"new", (PyCFunction)ffi_new, METH_VARARGS},
+ {"new_handle", (PyCFunction)ffi_new_handle,METH_O},
+#endif
+ {"sizeof", (PyCFunction)ffi_sizeof, METH_O},
+#if 0
+ {"string", (PyCFunction)ffi_string, METH_VARARGS},
+ {"typeof", (PyCFunction)ffi_typeof, METH_O},
+#endif
+ {NULL}
+};
+
+static PyTypeObject FFI_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "cffi.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, /* 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 */
+ 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 */
+ ffiobj_new, /* tp_new */
+ PyObject_GC_Del, /* tp_free */
+};
diff --git a/new/lib_obj.c b/new/lib_obj.c
new file mode 100644
--- /dev/null
+++ b/new/lib_obj.c
@@ -0,0 +1,197 @@
+
+/* A Lib object is what is returned by any of:
+
+ - the "lib" attribute of a C extension module originally created by
+ recompile()
+
+ - ffi.dlopen()
+
+ - ffi.verify()
+
+ A Lib object is special in the sense that it has a custom
+ __getattr__ which returns C globals, functions and constants. It
+ raises AttributeError for anything else, like '__class__'.
+
+ A Lib object has internally a reference back to the FFI object,
+ which holds the _cffi_type_context_s used to create lazily the
+ objects returned by __getattr__. For a dlopen()ed Lib object, all
+ the 'address' fields in _cffi_global_s are NULL, and instead
+ dlsym() is used lazily on the l_dl_lib.
+*/
+
+struct LibObject_s {
+ PyObject_HEAD
+ PyObject *l_dict; /* content, built lazily */
+ struct FFIObject_s *l_ffi; /* ffi object */
+ void *l_dl_lib; /* the result of 'dlopen()', or NULL */
+};
+
+#define ZefLib_Check(ob) ((Py_TYPE(ob) == &ZefLib_Type))
+
+static void lib_dealloc(ZefLibObject *lib)
+{
+ (void)lib_close(lib);
+ PyObject_Del(lib);
+}
+
+static PyObject *lib_repr(ZefLibObject *lib)
+{
+ return PyText_FromFormat("<zeffir.Lib object for '%.200s'%s>",
+ lib->l_libname,
+ lib->l_dl_lib == NULL ? " (closed)" : "");
+}
+
+static PyObject *lib_findattr(ZefLibObject *lib, PyObject *name, PyObject *exc)
+{
+ /* does not return a new reference! */
+
+ if (lib->l_dict == NULL) {
+ PyErr_Format(ZefError, "lib '%.200s' was closed", lib->l_libname);
+ return NULL;
+ }
+
+ PyObject *x = PyDict_GetItem(lib->l_dict, name);
+ if (x == NULL) {
+ PyErr_Format(exc,
+ "lib '%.200s' has no function,"
+ " global variable or constant '%.200s'",
+ lib->l_libname,
+ PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
+ return NULL;
+ }
+ return x;
+}
+
+static PyObject *lib_getattr(ZefLibObject *lib, PyObject *name)
+{
+ PyObject *x = lib_findattr(lib, name, PyExc_AttributeError);
+ if (x == NULL)
+ return NULL;
+
+ if (ZefGlobSupport_Check(x)) {
+ return read_global_var((ZefGlobSupportObject *)x);
+ }
+ Py_INCREF(x);
+ return x;
+}
+
+static int lib_setattr(ZefLibObject *lib, PyObject *name, PyObject *val)
+{
+ PyObject *x = lib_findattr(lib, name, PyExc_AttributeError);
+ if (x == NULL)
+ return -1;
+
+ if (val == NULL) {
+ PyErr_SetString(PyExc_AttributeError,
+ "cannot delete attributes from Lib object");
+ return -1;
+ }
+
+ if (ZefGlobSupport_Check(x)) {
+ return write_global_var((ZefGlobSupportObject *)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 *lib, PyObject *noarg)
+{
+ return PyDict_Keys(((ZefLibObject *)lib)->l_dict);
+}
+
+static PyMethodDef lib_methods[] = {
+ {"__dir__", lib_dir, METH_NOARGS},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyTypeObject ZefLib_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "zeffir.Lib",
+ sizeof(ZefLibObject),
+ 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, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* 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(ZefLibObject, l_dict), /* tp_dictoffset */
+};
+
+static void lib_dlerror(ZefLibObject *lib)
+{
+ char *error = dlerror();
+ if (error == NULL)
+ error = "(no error reported)";
+ PyErr_Format(PyExc_OSError, "%s: %s", lib->l_libname, error);
+}
+
+static ZefLibObject *lib_create(PyObject *path)
+{
+ ZefLibObject *lib;
+
+ lib = PyObject_New(ZefLibObject, &ZefLib_Type);
+ if (lib == NULL)
+ return NULL;
+
+ lib->l_dl_lib = NULL;
+ lib->l_libname = PyString_AsString(path);
+ Py_INCREF(path);
+ lib->l_libname_obj = path;
+ lib->l_dict = PyDict_New();
+ if (lib->l_dict == NULL) {
+ Py_DECREF(lib);
+ return NULL;
+ }
+
+ lib->l_dl_lib = dlopen(lib->l_libname, RTLD_LAZY);
+ if (lib->l_dl_lib == NULL) {
+ lib_dlerror(lib);
+ Py_DECREF(lib);
+ return NULL;
+ }
+ return lib;
+}
+
+static int lib_close(ZefLibObject *lib)
+{
+ void *dl_lib;
+ Py_CLEAR(lib->l_dict);
+
+ dl_lib = lib->l_dl_lib;
+ if (dl_lib != NULL) {
+ lib->l_dl_lib = NULL;
+ if (dlclose(dl_lib) != 0) {
+ lib_dlerror(lib);
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/new/manual.c b/new/manual.c
new file mode 100644
--- /dev/null
+++ b/new/manual.c
@@ -0,0 +1,109 @@
+#include "_cffi_include.h"
+
+
+int foo42(int a, int *b)
+{
+ return a - *b;
+}
+
+int foo64(int a)
+{
+ return ~a;
+}
+
+/************************************************************/
+
+static void *_cffi_types[] = {
+ _CFFI_OP(_CFFI_OP_FUNCTION, 1),
+ _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT),
+ _CFFI_OP(_CFFI_OP_POINTER, 1),
+ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0),
+ _CFFI_OP(_CFFI_OP_FUNCTION, 1),
+ _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT),
+ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0),
+};
+
+static PyObject *
+_cffi_f_foo42(PyObject *self, PyObject *args)
+{
+ int x0;
+ int * x1;
+ Py_ssize_t datasize;
+ int result;
+ PyObject *arg0;
+ PyObject *arg1;
+
+ if (!PyArg_ParseTuple(args, "OO:foo42", &arg0, &arg1))
+ return NULL;
+
+ x0 = _cffi_to_c_int(arg0, int);
+ if (x0 == (int)-1 && PyErr_Occurred())
+ return NULL;
+
+ datasize = _cffi_prepare_pointer_call_argument(
+ _cffi_types[1], arg1, (char **)&x1);
+ if (datasize != 0) {
+ if (datasize < 0)
+ return NULL;
+ x1 = alloca(datasize);
+ memset((void *)x1, 0, datasize);
+ if (_cffi_convert_array_from_object((char *)x1, _cffi_types[1], arg1) < 0)
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ _cffi_restore_errno();
+ { result = foo42(x0, x1); }
+ _cffi_save_errno();
+ Py_END_ALLOW_THREADS
+
+ return _cffi_from_c_int(result, int);
+}
+
+static PyObject *
+_cffi_f_foo64(PyObject *self, PyObject *arg0)
+{
+ int x0;
+ int result;
+
+ x0 = _cffi_to_c_int(arg0, int);
+ if (x0 == (int)-1 && PyErr_Occurred())
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ _cffi_restore_errno();
+ { result = foo64(x0); }
+ _cffi_save_errno();
+ Py_END_ALLOW_THREADS
+
+ return _cffi_from_c_int(result, int);
+}
+
+static const struct _cffi_global_s _cffi_globals[] = {
+ { "foo42", &_cffi_f_foo42, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN, 0) },
+ { "foo64", &_cffi_f_foo64, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN, 4) },
+};
+
+static const struct _cffi_type_context_s _cffi_type_context = {
+ _cffi_types,
+ _cffi_globals,
+ NULL, /* no constants */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 1, /* num_globals */
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+PyMODINIT_FUNC
+initmanual(void)
+{
+ if (_cffi_init() < 0)
+ return;
+
+ _cffi_init_module("manual", &_cffi_type_context);
+}
diff --git a/new/parse_c_type.c b/new/parse_c_type.c
--- a/new/parse_c_type.c
+++ b/new/parse_c_type.c
@@ -41,9 +41,9 @@
typedef struct {
struct _cffi_parse_info_s *info;
- const char *p;
+ const char *input, *p;
+ size_t size; // the next token is at 'p' and of length 'size'
enum token_e kind;
- size_t size;
_cffi_opcode_t *output;
size_t output_index;
} token_t;
@@ -177,7 +177,7 @@
{
if (tok->kind != TOK_ERROR) {
tok->kind = TOK_ERROR;
- tok->info->error_location = tok->p;
+ tok->info->error_location = tok->p - tok->input;
tok->info->error_message = msg;
}
return -1;
@@ -349,7 +349,7 @@
return _CFFI_GETARG(result);
}
-static int search_struct_union(struct _cffi_type_context_s *ctx,
+static int search_struct_union(const struct _cffi_type_context_s *ctx,
const char *search, size_t search_len)
{
int left = 0, right = ctx->num_structs_unions;
@@ -368,7 +368,7 @@
return -1;
}
-static int search_typename(struct _cffi_type_context_s *ctx,
+static int search_typename(const struct _cffi_type_context_s *ctx,
const char *search, size_t search_len)
{
int left = 0, right = ctx->num_typenames;
@@ -554,6 +554,7 @@
token.info = info;
token.kind = TOK_START;
+ token.input = input;
token.p = input;
token.size = 0;
token.output = info->output;
diff --git a/new/parse_c_type.h b/new/parse_c_type.h
--- a/new/parse_c_type.h
+++ b/new/parse_c_type.h
@@ -95,10 +95,10 @@
};
struct _cffi_parse_info_s {
- struct _cffi_type_context_s *ctx;
+ const struct _cffi_type_context_s *ctx;
_cffi_opcode_t *output;
int output_size;
- const char *error_location;
+ size_t error_location;
const char *error_message;
};
diff --git a/new/realize_c_type.c b/new/realize_c_type.c
--- a/new/realize_c_type.c
+++ b/new/realize_c_type.c
@@ -1,22 +1,19 @@
-#include <Python.h>
-#include "parse_c_type.h"
+static CTypeDescrObject *all_primitives[_CFFI__NUM_PRIM];
-static PyObject *all_primitives[_CFFI__NUM_PRIM];
-
-PyObject *build_primitive_type(int num)
+CTypeDescrObject *build_primitive_type(int num)
{
- PyObject *x;
+ CTypeDescrObject *x;
switch (num) {
case _CFFI_PRIM_VOID:
- x = PyString_FromString("VOID");
+ x = new_void_type();
break;
case _CFFI_PRIM_INT:
- x = PyString_FromString("INT");
+ x = new_primitive_type("int");
break;
default:
@@ -29,15 +26,21 @@
}
-PyObject *realize_c_type(struct _cffi_type_context_s *ctx,
- _cffi_opcode_t opcodes[], int index)
+/* Interpret an opcodes[] array. If opcodes == ctx->types, store all
+ the intermediate types back in the opcodes[]. Returns a new
+ reference.
+*/
+CTypeDescrObject *realize_c_type(const struct _cffi_type_context_s *ctx,
+ _cffi_opcode_t opcodes[], int index)
{
- PyObject *x, *y;
+ CTypeDescrObject *ct;
+ CTypeDescrObject *x, *y;
_cffi_opcode_t op = opcodes[index];
+
if ((((uintptr_t)op) & 1) == 0) {
- x = (PyObject *)op;
- Py_INCREF(x);
- return x;
+ ct = (CTypeDescrObject *)op;
+ Py_INCREF(ct);
+ return ct;
}
switch (_CFFI_GETOP(op)) {
@@ -53,7 +56,7 @@
y = realize_c_type(ctx, opcodes, _CFFI_GETARG(op));
if (y == NULL)
return NULL;
- x = Py_BuildValue("sO", "pointer", y);
+ x = new_pointer_type(y);
Py_DECREF(y);
break;
@@ -62,44 +65,10 @@
return NULL;
}
- if (opcodes == ctx->types) {
+ if (x != NULL && opcodes == ctx->types) {
+ assert((((uintptr_t)x) & 1) == 0);
Py_INCREF(x);
opcodes[index] = x;
}
return x;
};
-
-
-static PyObject *b_test(PyObject *self, PyObject *args)
-{
- char *s;
- if (!PyArg_ParseTuple(args, "s", &s))
- return NULL;
-
- _cffi_opcode_t opcodes[100];
- struct _cffi_type_context_s global_ctx = { NULL };
- struct _cffi_parse_info_s parse_info = {
- .ctx = &global_ctx,
- .output = opcodes,
- .output_size = 100,
- };
- int res = parse_c_type(&parse_info, s);
- if (res < 0) {
- PyErr_SetString(PyExc_ValueError, parse_info.error_message);
- return NULL;
- }
-
- return realize_c_type(&global_ctx, opcodes, res);
-}
-
-static PyMethodDef MyMethods[] = {
- {"test", b_test, METH_VARARGS},
- {NULL, NULL} /* Sentinel */
-};
-
-PyMODINIT_FUNC
-initrealize_c_type(void)
-{
- PyObject *m = Py_InitModule("realize_c_type", MyMethods);
- (void)m;
-}
diff --git a/new/setup_manual.py b/new/setup_manual.py
new file mode 100644
--- /dev/null
+++ b/new/setup_manual.py
@@ -0,0 +1,5 @@
+from distutils.core import setup
+from distutils.extension import Extension
+setup(name='manual',
+ ext_modules=[Extension(name='manual',
+ sources=['manual.c'])])
diff --git a/new/test_parse_c_type.py b/new/test_parse_c_type.py
--- a/new/test_parse_c_type.py
+++ b/new/test_parse_c_type.py
@@ -49,11 +49,10 @@
info.output_size = len(out)
for j in range(len(out)):
out[j] = ffi.cast("void *", -424242)
- c_input = ffi.new("char[]", input)
- res = lib.parse_c_type(info, c_input)
+ res = lib.parse_c_type(info, input)
if res < 0:
raise ParseError(ffi.string(info.error_message),
- info.error_location - c_input)
+ info.error_location)
assert 0 <= res < len(out)
result = []
for j in range(len(out)):
More information about the pypy-commit
mailing list