[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