[pypy-commit] creflect default: pointer types

arigo noreply at buildbot.pypy.org
Wed Dec 3 15:19:52 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r140:dc4373af8fab
Date: 2014-12-03 15:20 +0100
http://bitbucket.org/cffi/creflect/changeset/dc4373af8fab/

Log:	pointer types

diff --git a/zeffir/builder.c b/zeffir/builder.c
--- a/zeffir/builder.c
+++ b/zeffir/builder.c
@@ -10,30 +10,63 @@
     PyObject *types_dict;
 } zeffir_builder_t;
 
-static CTypeDescrObject *get_cached_type(_crx_builder_t *cb, const char *name,
-                                         int accept_flags)
+static PyObject *combine_type_name(_crx_builder_t *cb, CTypeDescrObject *ct,
+                                   const char *extra_text)
+{
+    /* Build a PyString with the name given by combining 'ct' and 'extra_text'.
+       'ct' can be NULL.  If an error occurs (or has already occurred),
+       returns NULL. */
+    size_t base_name_len, extra_name_len;
+    PyObject *result;
+    char *p;
+
+    if (PyErr_Occurred())
+        return NULL;
+
+    base_name_len = (ct != NULL ? strlen(ct->ct_name) : 0);
+    extra_name_len = strlen(extra_text);
+    result = PyString_FromStringAndSize(NULL, base_name_len + extra_name_len);
+    if (result == NULL)
+        return NULL;
+
+    p = PyString_AS_STRING(result);
+    if (ct != NULL) {
+        memcpy(p, ct->ct_name, ct->ct_name_position);
+        p += ct->ct_name_position;
+    }
+    memcpy(p, extra_text, extra_name_len);
+    if (ct != NULL) {
+        p += extra_name_len;
+        memcpy(p, ct->ct_name + ct->ct_name_position,
+               base_name_len - ct->ct_name_position);
+    }
+    return result;
+}
+
+static CTypeDescrObject *get_cached_type(_crx_builder_t *cb, PyObject *name_obj)
+{
+    /* Look up the type called 'name_obj' and check that it's a type with the
+       right flags.  Returns either the type or NULL, without changing
+       the reference counts.  Never raises an exception.
+    */
+    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
+    PyObject *x;
+
+    assert(name_obj != NULL);
+    x = PyDict_GetItem(types_dict, name_obj);
+    if (x == NULL || !CTypeDescr_Check(x))
+        return NULL;
+    else
+        return (CTypeDescrObject *)x;
+}
+
+static void put_cached_type(_crx_builder_t *cb, PyObject *name_obj,
+                            CTypeDescrObject *ct)
 {
     PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
-    PyObject *x = PyDict_GetItemString(types_dict, name);
-    CTypeDescrObject *ct;
-
-    if (x == NULL || !CTypeDescr_Check(x))
-        return NULL;
-    ct = (CTypeDescrObject *)x;
-    if ((ct->ct_flags & accept_flags) == 0)
-        return NULL;
-    return ct;
-}
-
-static _crx_type_t *put_cached_type(_crx_builder_t *cb, const char *name,
-                                    CTypeDescrObject *ct)
-{
-    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
-    int err = PyDict_SetItemString(types_dict, name, (PyObject *)ct);
-    Py_DECREF(ct);
-    if (err < 0)
-        return NULL;
-    return ct;    /* still a reference in the dict */
+    PyDict_SetItem(types_dict, name_obj, (PyObject *)ct);
+    Py_DECREF(ct);   /* still a reference in the dict,
+                        unless PyDict_SetItem failed */
 }
 
 static _crx_type_t *zef_get_void_type(_crx_builder_t *cb)
@@ -54,26 +87,33 @@
 static _crx_type_t *zef_get_signed_type(_crx_builder_t *cb, size_t sz,
                                         const char *name)
 {
-    CTypeDescrObject *td = get_cached_type(cb, name, CT_PRIMITIVE_SIGNED);
-    if (td != NULL && td->ct_size == sz)
-        return td;
+    PyObject *name_obj;
+    CTypeDescrObject *ct;
 
-    size_t name_length = strlen(name);
-
-    td = ctypedescr_new(name_length + 1);
-    if (td == NULL)
+    name_obj = combine_type_name(cb, NULL, name);
+    if (name_obj == NULL)
         return NULL;
 
-    memcpy(td->ct_name, name, name_length + 1);
-    td->ct_name_position = name_length;
-    td->ct_size = sz;
-    //td->ct_length = ptypes->align;
-    //td->ct_extra = ffitype;
-    td->ct_flags = CT_PRIMITIVE_SIGNED;
-    if (td->ct_size <= sizeof(long))
-        td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
+    ct = get_cached_type(cb, name_obj);
+    if (ct && (ct->ct_flags & CT_PRIMITIVE_SIGNED) && ct->ct_size == sz)
+        goto done;
 
-    return put_cached_type(cb, name, td);
+    ct = ctypedescr_new(name_obj, PyString_GET_SIZE(name_obj));
+    if (ct == NULL)
+        goto done;
+
+    ct->ct_size = sz;
+    //ct->ct_length = ptypes->align;
+    //ct->ct_extra = ffitype;
+    ct->ct_flags = CT_PRIMITIVE_SIGNED;
+    if (ct->ct_size <= sizeof(long))
+        ct->ct_flags |= CT_PRIMITIVE_FITS_LONG;
+
+    put_cached_type(cb, name_obj, ct);
+
+ done:
+    Py_DECREF(name_obj);
+    return ct;
 }
 
 static _crx_type_t *zef_get_unsigned_type(_crx_builder_t *cb, size_t sz,
@@ -106,7 +146,41 @@
 static _crx_type_t *zef_get_pointer_type(_crx_builder_t *cb,
                                          _crx_type_t *totype, int toquals)
 {
-    abort();
+    const char *extra;
+    PyObject *name_obj;
+    CTypeDescrObject *ct;
+
+    if (totype->ct_flags & CT_ARRAY)
+        extra = "(*)";
+    else
+        extra = " *";
+
+    name_obj = combine_type_name(cb, totype, extra);
+    if (name_obj == NULL)
+        return NULL;
+
+    ct = get_cached_type(cb, name_obj);
+    if (ct && (ct->ct_flags & CT_POINTER))
+        goto done;
+
+    ct = ctypedescr_new(name_obj, totype->ct_name_position + 2);
+    if (ct == NULL)
+        goto done;
+
+    ct->ct_size = sizeof(void *);
+    ct->ct_flags = CT_POINTER;
+    if (totype->ct_flags & CT_VOID)
+        ct->ct_flags |= CT_IS_VOID_PTR;
+    if ((totype->ct_flags & CT_VOID) ||
+        ((totype->ct_flags & CT_PRIMITIVE_CHAR) &&
+         totype->ct_size == sizeof(char)))
+        ct->ct_flags |= CT_CAST_ANYTHING;   /* 'void *' or 'char *' only */
+
+    put_cached_type(cb, name_obj, ct);
+
+ done:
+    Py_DECREF(name_obj);
+    return ct;
 }
 
 static _crx_type_t *zef_get_array_type(_crx_builder_t *cb, _crx_type_t *t,
diff --git a/zeffir/ctype.c b/zeffir/ctype.c
--- a/zeffir/ctype.c
+++ b/zeffir/ctype.c
@@ -45,7 +45,7 @@
     Py_ssize_t ct_length;   /* length of arrays, or -1 if unknown */
     int ct_flags;           /* CT_xxx flags */
 
-    int ct_name_position;   /* index in ct_name of where to put a var name */
+    size_t ct_name_position;/* index in ct_name of where to put a var name */
     char ct_name[1];        /* string, e.g. "int *" for pointers to ints */
 };
 
@@ -64,11 +64,12 @@
 
 /************************************************************/
 
-static CTypeDescrObject *ctypedescr_new(size_t name_size)
+static CTypeDescrObject *ctypedescr_new(PyObject *name_obj,
+                                        size_t name_position)
 {
     CTypeDescrObject *ct = PyObject_GC_NewVar(CTypeDescrObject,
                                               &CTypeDescr_Type,
-                                              name_size);
+                                              PyString_GET_SIZE(name_obj) + 1);
     if (ct == NULL)
         return NULL;
 
@@ -77,6 +78,9 @@
     ct->ct_weakreflist = NULL;
     ct->ct_size = -1;
     ct->ct_length = -1;
+    ct->ct_name_position = name_position;
+    memcpy(ct->ct_name, PyString_AS_STRING(name_obj),
+           PyString_GET_SIZE(name_obj) + 1);
     PyObject_GC_Track(ct);
     return ct;
 }
diff --git a/zeffir/test/test_ctype.py b/zeffir/test/test_ctype.py
--- a/zeffir/test/test_ctype.py
+++ b/zeffir/test/test_ctype.py
@@ -1,8 +1,18 @@
 import support
 
 
-def test_typeof():
+def test_typeof_primitive():
     ffi = support.new_ffi()
-    assert repr(ffi.typeof("int")) == "<ctype 'int'>"
-    assert repr(ffi.typeof("long int")) == "<ctype 'long'>"
-    #assert repr(ffi.typeof("int*")) == "<ctype 'int *'>"
+    ct_int = ffi.typeof("int")
+    assert repr(ct_int) == "<ctype 'int'>"
+    #
+    ct_long = ffi.typeof("long int")
+    assert repr(ct_long) == "<ctype 'long'>"
+    #
+    assert ffi.types == {'int': ct_int,
+                         'long': ct_long,
+                         'long int': ct_long}
+
+def test_typeof_pointer():
+    ffi = support.new_ffi()
+    assert repr(ffi.typeof("int*")) == "<ctype 'int *'>"


More information about the pypy-commit mailing list