# -*- coding: utf-8 -*- import os import sys from fnmatch import fnmatch from optparse import OptionParser HEADER_PATTERNS = ["*.hpp", "*.h"] INDENTED_INCLUDE_PREFIX = "#\tinclude " IFNDEF_PREFIX = "#ifndef " def getIncludeGuardName (headerFile): return '_' + os.path.basename(headerFile).upper().replace('.', '_') def getRedundantIncludeGuardErrors (fileName): f = open(fileName, 'rb') errors = [] lineNumber = 1 prevLine = None for line in f: if line.startswith(INDENTED_INCLUDE_PREFIX): if prevLine is not None and prevLine.startswith(IFNDEF_PREFIX): ifndefName = prevLine[len(IFNDEF_PREFIX):-1] # \note -1 to take out the newline. includeName = line[len(INDENTED_INCLUDE_PREFIX)+1:-2] # \note +1 to take out the beginning quote, -2 to take out the newline and the ending quote. if getIncludeGuardName(includeName) != ifndefName: errors.append("Invalid redundant include guard around line %d:" % lineNumber) errors.append("guard is %s but included file is %s" % (ifndefName, includeName)) prevLine = line lineNumber += 1 f.close() return errors def isHeader (filename): for pattern in HEADER_PATTERNS: if fnmatch(filename, pattern): return True return False def getFileList (path): allFiles = [] if os.path.isfile(path): if isHeader(path): allFiles.append(path) else: for root, dirs, files in os.walk(path): for file in files: if isHeader(file): allFiles.append(os.path.join(root, file)) return allFiles if __name__ == "__main__": parser = OptionParser() parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="only print files with errors") (options, args) = parser.parse_args() quiet = options.quiet files = [] invalidFiles = [] for dir in args: files += getFileList(os.path.normpath(dir)) print "Checking..." for file in files: if not quiet: print " %s" % file errors = getRedundantIncludeGuardErrors(file) if errors: if quiet: print " %s" % file for err in errors: print " %s" % err invalidFiles.append(file) print "" if len(invalidFiles) > 0: print "Found %d files with invalid redundant include guards:" % len(invalidFiles) for file in invalidFiles: print " %s" % file sys.exit(-1) else: print "All files have valid redundant include guards."