1# -*- coding: utf-8 -*- 2 3import os 4import sys 5from fnmatch import fnmatch 6from optparse import OptionParser 7 8HEADER_PATTERNS = ["*.hpp", "*.h"] 9INDENTED_INCLUDE_PREFIX = "#\tinclude " 10IFNDEF_PREFIX = "#ifndef " 11 12def getIncludeGuardName (headerFile): 13 return '_' + os.path.basename(headerFile).upper().replace('.', '_') 14 15def getRedundantIncludeGuardErrors (fileName): 16 f = open(fileName, 'rb') 17 errors = [] 18 19 lineNumber = 1 20 prevLine = None 21 for line in f: 22 if line.startswith(INDENTED_INCLUDE_PREFIX): 23 if prevLine is not None and prevLine.startswith(IFNDEF_PREFIX): 24 ifndefName = prevLine[len(IFNDEF_PREFIX):-1] # \note -1 to take out the newline. 25 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. 26 if getIncludeGuardName(includeName) != ifndefName: 27 errors.append("Invalid redundant include guard around line %d:" % lineNumber) 28 errors.append("guard is %s but included file is %s" % (ifndefName, includeName)) 29 30 prevLine = line 31 lineNumber += 1 32 33 f.close() 34 return errors 35 36def isHeader (filename): 37 for pattern in HEADER_PATTERNS: 38 if fnmatch(filename, pattern): 39 return True 40 return False 41 42def getFileList (path): 43 allFiles = [] 44 if os.path.isfile(path): 45 if isHeader(path): 46 allFiles.append(path) 47 else: 48 for root, dirs, files in os.walk(path): 49 for file in files: 50 if isHeader(file): 51 allFiles.append(os.path.join(root, file)) 52 return allFiles 53 54if __name__ == "__main__": 55 parser = OptionParser() 56 parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="only print files with errors") 57 58 (options, args) = parser.parse_args() 59 quiet = options.quiet 60 files = [] 61 invalidFiles = [] 62 63 for dir in args: 64 files += getFileList(os.path.normpath(dir)) 65 66 print "Checking..." 67 for file in files: 68 if not quiet: 69 print " %s" % file 70 71 errors = getRedundantIncludeGuardErrors(file) 72 if errors: 73 if quiet: 74 print " %s" % file 75 for err in errors: 76 print " %s" % err 77 invalidFiles.append(file) 78 79 print "" 80 if len(invalidFiles) > 0: 81 print "Found %d files with invalid redundant include guards:" % len(invalidFiles) 82 83 for file in invalidFiles: 84 print " %s" % file 85 86 sys.exit(-1) 87 else: 88 print "All files have valid redundant include guards." 89