diff --git a/scripts/cleanup-includes.py b/scripts/cleanup-includes.py new file mode 100755 index 0000000000000000000000000000000000000000..640458e9f314c43c0980fe61737e4ebd78c736fc --- /dev/null +++ b/scripts/cleanup-includes.py @@ -0,0 +1,98 @@ +#!/usr/bin/python -Es +# vim: et:sw=4:ts=4:sts=4 +# +# Check #includes in source files and: +# - fix includes to be relative to src/ +# - check if <config.h> is the first include in all .c sources +# + +import os +import re +import sys + +class SourceProcessor(object): + def __init__(self): + self._log_prefix = None + + def process(self, filename, code): + raise NotImplemented() + + def log(self, message): + print >>sys.stderr, "[%s] %s" % (self._log_prefix, message) + +class FixIncludePaths(SourceProcessor): + def __init__(self, src_root, search_paths): + self._log_prefix = "include-paths" + self._src_root = src_root + self._search_paths = search_paths + + def _fix_include(self, filename, include): + current_path = os.path.split(filename)[0] + for search_path in [current_path] + self._search_paths: + new_include = os.path.join(search_path, include) + if os.path.exists(new_include): + new_include = os.path.relpath(new_include, self._src_root) + return new_include + return include + + def process(self, filename, code): + def callback(match): + (prefix, path, suffix) = match.groups() + fixed_path = self._fix_include(filename, path) + return "%s%s%s" % (prefix, fixed_path, suffix) + + fixed_code = re.sub(r'(#\s*include\s+")([^"]+)(")', callback, code) + if code != fixed_code: + self.log("fixed %s" % filename) + + return fixed_code + +class TestConfigH(SourceProcessor): + def __init__(self): + self._log_prefix = "config.h" + + def _check_code(self, code): + first_include = re.search('#\s*include\s+(".+"|<.+>)', code) + return first_include is not None and first_include.group(1) == "<config.h>" + + def process(self, filename, code): + if not re.search(r'\.h$', filename) and not self._check_code(code): + self.log("config.h is not first include in %s" % filename) + return code + +# ---------------------------------------------------------------------------- + +from subprocess import Popen, PIPE + +def run(command): + p = Popen(command, stdout=PIPE, stderr=PIPE) + (out, errout) = p.communicate() + if p.returncode != 0: + raise Exception("Command %s failed.", command) + return out + +# ---------------------------------------------------------------------------- + +git_root = run(["git", "rev-parse", "--show-toplevel"]).strip() +os.chdir(git_root) + +command = ["git", "ls-files", "src/*.h", "src/*.c", "src/*.y"] +filenames = run(command).splitlines() + +pipeline = [ + FixIncludePaths("src", ["src", "src/libknot"]), + TestConfigH(), +] + +for filename in filenames: + code = open(filename, "r").read() + modified = False + + for processor in pipeline: + new_code = processor.process(filename, code) + if new_code != code: + modified = True + code = new_code + + if modified: + open(filename, "w").write(code)