[pypy-commit] cffi default: Merged in mozbugbox/cffi/define-integer-constant (pull request #31)
arigo
noreply at buildbot.pypy.org
Fri Apr 4 16:52:48 CEST 2014
Author: Armin Rigo <armin.rigo at gmail.com>
Branch:
Changeset: r1495:6f31a53a6275
Date: 2014-04-04 16:52 +0200
http://bitbucket.org/cffi/cffi/changeset/6f31a53a6275/
Log: Merged in mozbugbox/cffi/define-integer-constant (pull request #31)
Handle "#define DOT 0x1FF" like defines
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -443,6 +443,10 @@
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
if enumname not in library.__dict__:
library.__dict__[enumname] = enumval
+ for key, val in ffi._parser._int_constants.items():
+ if key not in library.__dict__:
+ library.__dict__[key] = val
+
copied_enums.append(True)
if name in library.__dict__:
return
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -24,6 +24,7 @@
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
_r_words = re.compile(r"\w+|\S")
_parser_cache = None
+_r_int_literal = re.compile(r"^0?x?[0-9a-f]+u?l?$", re.IGNORECASE)
def _get_parser():
global _parser_cache
@@ -170,12 +171,7 @@
def _internal_parse(self, csource):
ast, macros, csource = self._parse(csource)
# add the macros
- for key, value in macros.items():
- value = value.strip()
- if value != '...':
- raise api.CDefError('only supports the syntax "#define '
- '%s ..." for now (literally)' % key)
- self._declare('macro ' + key, value)
+ self._process_macros(macros)
# find the first "__dotdotdot__" and use that as a separator
# between the repeated typedefs and the real csource
iterator = iter(ast.ext)
@@ -211,6 +207,34 @@
e.args = (e.args[0] + "\n *** Err: %s" % msg,)
raise
+ def _add_constants(self, key, val):
+ if key in self._int_constants:
+ raise api.FFIError(
+ "multiple declarations of constant: %s" % (key,))
+ self._int_constants[key] = val
+
+ def _process_macros(self, macros):
+ for key, value in macros.items():
+ value = value.strip()
+ match = _r_int_literal.search(value)
+ if match is not None:
+ int_str = match.group(0).lower().rstrip("ul")
+
+ # "010" is not valid oct in py3
+ if (int_str.startswith("0") and
+ int_str != "0" and
+ not int_str.startswith("0x")):
+ int_str = "0o" + int_str[1:]
+
+ pyvalue = int(int_str, 0)
+ self._add_constants(key, pyvalue)
+ elif value == '...':
+ self._declare('macro ' + key, value)
+ else:
+ raise api.CDefError('only supports the syntax "#define '
+ '%s ..." (literally) or "#define '
+ '%s 0x1FF" for now' % (key, key))
+
def _parse_decl(self, decl):
node = decl.type
if isinstance(node, pycparser.c_ast.FuncDecl):
@@ -542,11 +566,7 @@
if enum.value is not None:
nextenumvalue = self._parse_constant(enum.value)
enumvalues.append(nextenumvalue)
- if enum.name in self._int_constants:
- raise api.FFIError(
- "multiple declarations of constant %s" % (enum.name,))
-
- self._int_constants[enum.name] = nextenumvalue
+ self._add_constants(enum.name, nextenumvalue)
nextenumvalue += 1
enumvalues = tuple(enumvalues)
tp = model.EnumType(explicit_name, enumerators, enumvalues)
@@ -561,8 +581,4 @@
if kind in ('typedef', 'struct', 'union', 'enum'):
self._declare(name, tp)
for k, v in other._int_constants.items():
- if k not in self._int_constants:
- self._int_constants[k] = v
- else:
- raise api.FFIError(
- "multiple declarations of constant %s" % (k,))
+ self._add_constants(k, v)
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1581,3 +1581,25 @@
assert s[0].a == b'X'
assert s[1].b == -4892220
assert s[1].a == b'Y'
+
+ def test_define_integer_constant(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ #define DOT_0 0
+ #define DOT 100
+ #define DOT_OCT 0100l
+ #define DOT_HEX 0x100u
+ #define DOT_HEX2 0X10
+ #define DOT_UL 1000UL
+ enum foo {AA, BB=DOT, CC};
+ """)
+ lib = ffi.dlopen(None)
+ assert ffi.string(ffi.cast("enum foo", 100)) == "BB"
+ assert lib.DOT_0 == 0
+ assert lib.DOT == 100
+ assert lib.DOT_OCT == 0o100
+ assert lib.DOT_HEX == 0x100
+ assert lib.DOT_HEX2 == 0x10
+ assert lib.DOT_UL == 1000
+
+
More information about the pypy-commit
mailing list