diff --git a/chc/cmdline/ParseManager.py b/chc/cmdline/ParseManager.py index 8472c50..913a93c 100644 --- a/chc/cmdline/ParseManager.py +++ b/chc/cmdline/ParseManager.py @@ -33,6 +33,8 @@ import shlex import shutil +from pathlib import Path + import xml.etree.ElementTree as ET from typing import Any, Dict, List, Optional, Tuple @@ -77,6 +79,7 @@ def __init__( verbose: bool = True, keepUnused: bool = False, tgtplatform: str = "-m64", + preprocessed_path: str = "", ) -> None: """Initialize paths to code, results, and parser executable. @@ -109,6 +112,7 @@ def __init__( + ". Target platform is set to -m64" ) self._tgtplatform = "-m64" + self._preprocessed_path = preprocessed_path self.config = Config() @property @@ -221,6 +225,35 @@ def save_semantics(self) -> None: ) os.chdir(cwd) + def lookup_preprocess_file( + self, + cfilename: str, + copyfiles: bool = True + ) -> Optional[str]: + """Lookup the specified c file in the preprocessed_path directory.""" + if not self._preprocessed_path: + return None + ifilename = cfilename[:-1] + "i" + path = Path(self._preprocessed_path) / ifilename + path = path.resolve() + if not path.is_file(): + return None + if copyfiles: + tgtcfilename = os.path.join( + self.savedsourcepath, self.normalize_filename(cfilename) + ) + tgtifilename = os.path.join( + self.savedsourcepath, self.normalize_filename(ifilename) + ) + tgtcdir = os.path.dirname(tgtcfilename) + if not os.path.isdir(tgtcdir): + os.makedirs(tgtcdir) + os.chdir(self.projectpath) + if os.path.normpath(cfilename) != os.path.normpath(tgtcfilename): + shutil.copy(cfilename, tgtcfilename) + shutil.copy(ifilename, tgtifilename) + return str(path) + def preprocess_file_with_cc( self, cfilename: str, @@ -240,6 +273,9 @@ def preprocess_file_with_cc( copies the original source file and the generated .i file to the tgtpath/sourcefiles directory. """ + saved_ifilename = self.lookup_preprocess_file(cfilename, copyfiles) + if saved_ifilename: + return saved_ifilename chklogger.logger.info("Preprocess file with cc: %s", cfilename) cwd = os.getcwd() @@ -348,6 +384,10 @@ def preprocess( ecommand = command[:] cfilename: str = os.path.join(ccommand["directory"], ccommand["file"]) if cfilename.endswith(".c"): + saved_ifilename = self.lookup_preprocess_file(cfilename, copyfiles) + if saved_ifilename: + return (cfilename, saved_ifilename) + ifilename = cfilename[:-1] + "i" try: outputflagindex = command.index("-o") diff --git a/chc/cmdline/c_file/cfileutil.py b/chc/cmdline/c_file/cfileutil.py index 0075824..52231ba 100644 --- a/chc/cmdline/c_file/cfileutil.py +++ b/chc/cmdline/c_file/cfileutil.py @@ -124,6 +124,7 @@ def cfile_parse_file(args: argparse.Namespace) -> NoReturn: loglevel: str = args.loglevel logfilename: Optional[str] = args.logfilename logfilemode: str = args.logfilemode + preprocessed_path: str = args.preprocessed_path try: UF.check_parser() @@ -159,7 +160,8 @@ def cfile_parse_file(args: argparse.Namespace) -> NoReturn: chklogger.logger.info("Target path: %s", targetpath) parsemanager = ParseManager( - projectpath, projectname, targetpath, keep_system_includes=keep_system_includes) + projectpath, projectname, targetpath, keep_system_includes=keep_system_includes, + preprocessed_path=preprocessed_path) parsemanager.remove_semantics() parsemanager.initialize_paths() diff --git a/chc/cmdline/c_project/cprojectutil.py b/chc/cmdline/c_project/cprojectutil.py index b268c25..df08da2 100644 --- a/chc/cmdline/c_project/cprojectutil.py +++ b/chc/cmdline/c_project/cprojectutil.py @@ -121,6 +121,7 @@ def cproject_parse_project(args: argparse.Namespace) -> NoReturn: loglevel: str = args.loglevel logfilename: Optional[str] = args.logfilename logfilemode: str = args.logfilemode + preprocessed_path: str = args.preprocessed_path try: UF.check_parser() @@ -168,7 +169,8 @@ def cproject_parse_project(args: argparse.Namespace) -> NoReturn: projectpath, projectname, targetpath, - keep_system_includes=keep_system_includes) + keep_system_includes=keep_system_includes, + preprocessed_path=preprocessed_path) parsemanager.remove_semantics() parsemanager.initialize_paths() exitcode = parsemanager.parse_with_ccommands(compilecommands, copyfiles=True) diff --git a/chc/cmdline/chkc b/chc/cmdline/chkc index 5848e0c..7024a5c 100755 --- a/chc/cmdline/chkc +++ b/chc/cmdline/chkc @@ -663,6 +663,9 @@ def parse() -> argparse.Namespace: "--keep-system-includes", action="store_true", help="do not filter out functions from files with absolute file names") + cfileparse.add_argument( + "--preprocessed-path", + help="directory that contains preprocessed source files") cfileparse.add_argument( "--loglevel", "-log", choices=UL.LogLevel.options(), @@ -1491,6 +1494,9 @@ def parse() -> argparse.Namespace: "--keep-system-includes", action="store_true", help="don't filter out functions from files with absolute filenames") + cprojectparse.add_argument( + "--preprocessed-path", + help="directory that contains preprocessed source files") cprojectparse.add_argument( "--loglevel", "-log", choices=UL.LogLevel.options(),