[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