From ab99f2fa7204469931c256898eb90c5820a45d96 Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Sun, 1 Oct 2023 03:07:26 -0400 Subject: [PATCH] Handle pcpp relative path quirk --- cxxheaderparser/preprocessor.py | 14 ++++++++++- tests/test_preprocessor.py | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/cxxheaderparser/preprocessor.py b/cxxheaderparser/preprocessor.py index 4b6aabe..33382dd 100644 --- a/cxxheaderparser/preprocessor.py +++ b/cxxheaderparser/preprocessor.py @@ -3,6 +3,7 @@ """ import io +import re import os from os.path import relpath import typing @@ -36,7 +37,6 @@ def _filter_self(fname: str, fp: typing.TextIO) -> str: # isn't what a typical user of cxxheaderparser would want, so we strip out # the line directives and any content that isn't in our original file - # pcpp always emits line directives that match whatever is passed in to it line_ending = f'{fname}"\n' new_output = io.StringIO() @@ -100,6 +100,18 @@ def _preprocess_file(filename: str, content: str) -> str: if retain_all_content: return fp.read() else: + # pcpp emits the #line directive using the filename you pass in + # but will rewrite it if it's on the include path it uses. This + # is copied from pcpp: + abssource = os.path.abspath(filename) + for rewrite in pp.rewrite_paths: + temp = re.sub(rewrite[0], rewrite[1], abssource) + if temp != abssource: + filename = temp + if os.sep != "/": + filename = filename.replace(os.sep, "/") + break + return _filter_self(filename, fp) return _preprocess_file diff --git a/tests/test_preprocessor.py b/tests/test_preprocessor.py index b0d87e9..df2e76f 100644 --- a/tests/test_preprocessor.py +++ b/tests/test_preprocessor.py @@ -1,3 +1,4 @@ +import os import pathlib from cxxheaderparser.options import ParserOptions @@ -66,6 +67,46 @@ def test_preprocessor_omit_content(tmp_path: pathlib.Path) -> None: ) +def test_preprocessor_omit_content2(tmp_path: pathlib.Path) -> None: + """ + Ensure that content in other headers is omitted while handling pcpp + relative path quirk + """ + h_content = '#include "t2.h"' "\n" "int x = X;\n" + h2_content = "#define X 2\n" "int omitted = 1;\n" + + tmp_path2 = tmp_path / "l1" + tmp_path2.mkdir() + + with open(tmp_path2 / "t1.h", "w") as fp: + fp.write(h_content) + + with open(tmp_path2 / "t2.h", "w") as fp: + fp.write(h2_content) + + options = ParserOptions( + preprocessor=make_pcpp_preprocessor(include_paths=[str(tmp_path)]) + ) + + # Weirdness happens here + os.chdir(tmp_path) + data = parse_file(tmp_path2 / "t1.h", options=options) + + assert data == ParsedData( + namespace=NamespaceScope( + variables=[ + Variable( + name=PQName(segments=[NameSpecifier(name="x")]), + type=Type( + typename=PQName(segments=[FundamentalSpecifier(name="int")]) + ), + value=Value(tokens=[Token(value="2")]), + ) + ] + ) + ) + + def test_preprocessor_encoding(tmp_path: pathlib.Path) -> None: """Ensure we can handle alternate encodings""" h_content = b"// \xa9 2023 someone\n" b'#include "t2.h"' b"\n" b"int x = X;\n"