[pypy-commit] cffi cffi-1.0: Add to the recompiler the value of the elements that "belong" to an

arigo noreply at buildbot.pypy.org
Fri Apr 24 17:48:42 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1806:4adfe9dbfcbf
Date: 2015-04-24 17:49 +0200
http://bitbucket.org/cffi/cffi/changeset/4adfe9dbfcbf/

Log:	Add to the recompiler the value of the elements that "belong" to an
	enum (even though they don't really belong there in the C sense)

diff --git a/_cffi1/lib_obj.c b/_cffi1/lib_obj.c
--- a/_cffi1/lib_obj.c
+++ b/_cffi1/lib_obj.c
@@ -165,23 +165,11 @@
         break;
 
     case _CFFI_OP_CONSTANT_INT:
+    case _CFFI_OP_ENUM:
     {
         /* a constant integer whose value, in an "unsigned long long",
            is obtained by calling the function at g->address */
-        unsigned long long value;
-        int neg = ((int(*)(unsigned long long*))g->address)(&value);
-        if (!neg) {
-            if (value <= (unsigned long long)LONG_MAX)
-                x = PyInt_FromLong((long)value);
-            else
-                x = PyLong_FromUnsignedLongLong(value);
-        }
-        else {
-            if ((long long)value >= (long long)LONG_MIN)
-                x = PyInt_FromLong((long)value);
-            else
-                x = PyLong_FromLongLong((long long)value);
-        }
+        x = realize_global_int(g);
         break;
     }
 
diff --git a/_cffi1/parse_c_type.h b/_cffi1/parse_c_type.h
--- a/_cffi1/parse_c_type.h
+++ b/_cffi1/parse_c_type.h
@@ -92,6 +92,7 @@
     const char *name;
     int type_index;          // -> _cffi_types, on a OP_ENUM
     int type_prim;           // _CFFI_PRIM_xxx
+    const char *enumerators; // comma-delimited string
 };
 
 struct _cffi_typename_s {
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -214,6 +214,25 @@
     return x;
 }
 
+static PyObject *realize_global_int(const struct _cffi_global_s *g)
+{
+    PyObject *x;
+    unsigned long long value;
+    int neg = ((int(*)(unsigned long long*))g->address)(&value);
+    if (!neg) {
+        if (value <= (unsigned long long)LONG_MAX)
+            x = PyInt_FromLong((long)value);
+        else
+            x = PyLong_FromUnsignedLongLong(value);
+    }
+    else {
+        if ((long long)value >= (long long)LONG_MIN)
+            x = PyInt_FromLong((long)value);
+        else
+            x = PyLong_FromLongLong((long long)value);
+    }
+    return x;
+}
 
 static PyObject *
 _realize_c_type_or_func(builder_c_t *builder,
@@ -378,7 +397,51 @@
             if (basetd == NULL)
                 return NULL;
 
-            PyObject *args = Py_BuildValue("(s()()O)", e->name, basetd);
+            PyObject *enumerators = NULL, *enumvalues = NULL, *tmp;
+            Py_ssize_t i, j, n = 0;
+            const char *p;
+            const struct _cffi_global_s *g;
+            int gindex;
+
+            if (*e->enumerators != '\0') {
+                n++;
+                for (p = e->enumerators; *p != '\0'; p++)
+                    n += (*p == ',');
+            }
+            enumerators = PyTuple_New(n);
+            if (enumerators == NULL)
+                return NULL;
+
+            enumvalues = PyTuple_New(n);
+            if (enumvalues == NULL) {
+                Py_DECREF(enumerators);
+                return NULL;
+            }
+
+            p = e->enumerators;
+            for (i = 0; i < n; i++) {
+                j = 0;
+                while (p[j] != ',' && p[j] != '\0')
+                    j++;
+                tmp = PyString_FromStringAndSize(p, j);
+                PyTuple_SET_ITEM(enumerators, i, tmp);
+
+                gindex = search_in_globals(&builder->ctx, p, j);
+                g = &builder->ctx.globals[gindex];
+                assert(gindex >= 0 && g->type_op == op);
+
+                tmp = realize_global_int(g);
+                PyTuple_SET_ITEM(enumvalues, i, tmp);
+
+                p += j + 1;
+            }
+
+            PyObject *args = NULL;
+            if (!PyErr_Occurred())
+                args = Py_BuildValue("(sOOO)", e->name, enumerators,
+                                     enumvalues, basetd);
+            Py_DECREF(enumerators);
+            Py_DECREF(enumvalues);
             if (args == NULL)
                 return NULL;
 
diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -620,10 +620,12 @@
             size = "sizeof(%s)" % cname
             signed = "((%s)-1) <= 0" % cname
             prim = "_cffi_prim_int(%s, %s)" % (size, signed)
+            allenums = ",".join(tp.enumerators)
         else:
             size = xxxx
         self._lsts["enum"].append(
-            '  { "%s", %d, %s },' % (tp.name, type_index, prim))
+            '  { "%s", %d, %s,\n    "%s" },' % (tp.name, type_index,
+                                                prim, allenums))
 
     def _generate_cpy_enum_ctx(self, tp, name):
         if tp.has_c_name():
diff --git a/_cffi1/test_verify1.py b/_cffi1/test_verify1.py
--- a/_cffi1/test_verify1.py
+++ b/_cffi1/test_verify1.py
@@ -688,6 +688,9 @@
     # try again
     ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
     assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
+    #
+    assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
+    assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
 
 def test_full_enum():
     ffi = FFI()
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -703,6 +703,9 @@
     # try again
     ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
     assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
+    #
+    assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
+    assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
 
 def test_full_enum():
     ffi = FFI()


More information about the pypy-commit mailing list