From 19ff1036043ae40ff3d8a2e1a6a793219e1ec378 Mon Sep 17 00:00:00 2001
From: Armin Rigo <arigo@tunes.org>
Date: Tue, 26 May 2020 15:51:56 +0200
Subject: [PATCH] Issue #454
Try harder to avoid #line directives confuse the rest of pre-parsing
---
cffi/cparser.py | 37 ++++++++++++++++++++++++---
testing/cffi0/test_parsing.py | 48 ++++++++++++++++++++++++++++++++++-
2 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/cffi/cparser.py b/cffi/cparser.py
index d7069a73..d9784655 100644
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -29,6 +29,7 @@ _r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
r"\b((?:[^\n\\]|\\.)*?)$",
re.DOTALL | re.MULTILINE)
+_r_line_directive = re.compile(r"^[ \t]*#[ \t]*line\b.*$", re.MULTILINE)
_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
@@ -163,10 +164,37 @@ def _warn_for_non_extern_non_static_global_variable(decl):
"with C it should have a storage class specifier "
"(usually 'extern')" % (decl.name,))
+def _remove_line_directives(csource):
+ # _r_line_directive matches whole lines, without the final \n, if they
+ # start with '#line' with some spacing allowed. This function stores
+ # them away and replaces them with exactly the string '#line@N', where
+ # N is the index in the list 'line_directives'.
+ line_directives = []
+ def replace(m):
+ i = len(line_directives)
+ line_directives.append(m.group())
+ return '#line@%d' % i
+ csource = _r_line_directive.sub(replace, csource)
+ return csource, line_directives
+
+def _put_back_line_directives(csource, line_directives):
+ def replace(m):
+ s = m.group()
+ if not s.startswith('#line@'):
+ raise AssertionError("unexpected #line directive "
+ "(should have been processed and removed")
+ return line_directives[int(s[6:])]
+ return _r_line_directive.sub(replace, csource)
+
def _preprocess(csource):
+ # First, remove the lines of the form '#line N "filename"' because