| # -*- 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." |