summaryrefslogtreecommitdiff
path: root/cffi/cparser.py
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-11-12 16:39:37 +0100
committerArmin Rigo <arigo@tunes.org>2015-11-12 16:39:37 +0100
commit1218c24b71551b43531f825577b0b04eca1c64e9 (patch)
tree8b7a6c96898cf6528c8b5ae84552e98335eca6ac /cffi/cparser.py
parentffce6a08afb9ec3a899eddcbc06c5c8a796c1fe8 (diff)
downloadcffi-1218c24b71551b43531f825577b0b04eca1c64e9.tar.gz
Parsing CFFI_CALL_PYTHON in the cdef
Diffstat (limited to 'cffi/cparser.py')
-rw-r--r--cffi/cparser.py29
1 files changed, 25 insertions, 4 deletions
diff --git a/cffi/cparser.py b/cffi/cparser.py
index 9be70c6..b2290f1 100644
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -29,6 +29,7 @@ _r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE)
_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
_r_cdecl = re.compile(r"\b__cdecl\b")
+_r_cffi_call_python = re.compile(r"\bCFFI_CALL_PYTHON\b")
_r_star_const_space = re.compile( # matches "* const "
r"[*]\s*((const|volatile|restrict)\b\s*)+")
@@ -101,8 +102,13 @@ def _preprocess(csource):
csource = _r_stdcall2.sub(' volatile volatile const(', csource)
csource = _r_stdcall1.sub(' volatile volatile const ', csource)
csource = _r_cdecl.sub(' ', csource)
+ #
+ # Replace "CFFI_CALL_PYTHON" with "void CFFI_CALL_PYTHON;"
+ csource = _r_cffi_call_python.sub('void CFFI_CALL_PYTHON;', csource)
+ #
# Replace "[...]" with "[__dotdotdotarray__]"
csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
+ #
# Replace "...}" with "__dotdotdotNUM__}". This construction should
# occur only at the end of enums; at the end of structs we have "...;}"
# and at the end of vararg functions "...);". Also replace "=...[,}]"
@@ -255,7 +261,9 @@ class Parser(object):
break
#
try:
+ self._found_cffi_call_python = False
for decl in iterator:
+ old_cffi_call_python = self._found_cffi_call_python
if isinstance(decl, pycparser.c_ast.Decl):
self._parse_decl(decl)
elif isinstance(decl, pycparser.c_ast.Typedef):
@@ -278,6 +286,8 @@ class Parser(object):
self._declare('typedef ' + decl.name, realtype, quals=quals)
else:
raise api.CDefError("unrecognized construct", decl)
+ if old_cffi_call_python and self._found_cffi_call_python:
+ raise api.CDefError("CFFI_CALL_PYTHON misplaced")
except api.FFIError as e:
msg = self._convert_pycparser_error(e, csource)
if msg:
@@ -324,13 +334,20 @@ class Parser(object):
' #define %s %s'
% (key, key, key, value))
+ def _declare_function(self, tp, quals, decl):
+ tp = self._get_type_pointer(tp, quals)
+ if self._found_cffi_call_python:
+ self._declare('call_python ' + decl.name, tp)
+ self._found_cffi_call_python = False
+ else:
+ self._declare('function ' + decl.name, tp)
+
def _parse_decl(self, decl):
node = decl.type
if isinstance(node, pycparser.c_ast.FuncDecl):
tp, quals = self._get_type_and_quals(node, name=decl.name)
assert isinstance(tp, model.RawFunctionType)
- tp = self._get_type_pointer(tp, quals)
- self._declare('function ' + decl.name, tp)
+ self._declare_function(tp, quals, decl)
else:
if isinstance(node, pycparser.c_ast.Struct):
self._get_struct_union_enum_type('struct', node)
@@ -346,8 +363,7 @@ class Parser(object):
tp, quals = self._get_type_and_quals(node,
partial_length_ok=True)
if tp.is_raw_function:
- tp = self._get_type_pointer(tp, quals)
- self._declare('function ' + decl.name, tp)
+ self._declare_function(tp, quals, decl)
elif (tp.is_integer_type() and
hasattr(decl, 'init') and
hasattr(decl.init, 'value') and
@@ -360,6 +376,11 @@ class Parser(object):
_r_int_literal.match(decl.init.expr.value)):
self._add_integer_constant(decl.name,
'-' + decl.init.expr.value)
+ elif tp is model.void_type and decl.name == 'CFFI_CALL_PYTHON':
+ # hack: "CFFI_CALL_PYTHON" in the C source is replaced
+ # with "void CFFI_CALL_PYTHON;", which when parsed arrives
+ # at this point and sets this flag:
+ self._found_cffi_call_python = True
elif (quals & model.Q_CONST) and not tp.is_array_type:
self._declare('constant ' + decl.name, tp, quals=quals)
else: