1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------- 4# drawElements Quality Program utilities 5# -------------------------------------- 6# 7# Copyright 2015 The Android Open Source Project 8# 9# Licensed under the Apache License, Version 2.0 (the "License"); 10# you may not use this file except in compliance with the License. 11# You may obtain a copy of the License at 12# 13# http://www.apache.org/licenses/LICENSE-2.0 14# 15# Unless required by applicable law or agreed to in writing, software 16# distributed under the License is distributed on an "AS IS" BASIS, 17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18# See the License for the specific language governing permissions and 19# limitations under the License. 20# 21#------------------------------------------------------------------------- 22 23import os 24import sys 25from fnmatch import fnmatch 26from optparse import OptionParser 27 28HEADER_PATTERNS = ["*.hpp", "*.h"] 29CHECK_END_COMMENT = True 30 31def getIncludeGuardName (headerFile): 32 return '_' + os.path.basename(headerFile).upper().replace('.', '_') 33 34def hasValidIncludeGuard (headerFile): 35 includeGuard = getIncludeGuardName(headerFile) 36 f = open(headerFile, 'rb') 37 isHpp = headerFile[-4:] == ".hpp" 38 39 line0 = f.readline().strip() 40 line1 = f.readline().strip() 41 42 if line0 != ("#ifndef %s" % includeGuard): 43 return False 44 if line1 != ("#define %s" % includeGuard): 45 return False 46 47 if CHECK_END_COMMENT: 48 lastLine = "" 49 expectedComment = ("#endif // %s" if isHpp else "#endif /* %s */") % includeGuard 50 for line in f: 51 lastLine = line.strip() 52 53 if lastLine != expectedComment: 54# print "'%s' != '%s'" % (lastLine, expectedComment) 55 return False 56 57 f.close() 58 return True 59 60def fixIncludeGuard (headerFile): 61 f = open(headerFile, 'rb') 62 lines = [] 63 isHpp = headerFile[-4:] == ".hpp" 64 includeGuard = getIncludeGuardName(headerFile) 65 66 for line in f: 67 lines.append(line) 68 f.close() 69 70 # Replace include guards 71 lines[0] = "#ifndef %s\n" % includeGuard 72 lines[1] = "#define %s\n" % includeGuard 73 74 if CHECK_END_COMMENT: 75 lines[len(lines)-1] = ("#endif // %s\n" if isHpp else "#endif /* %s */\n") % includeGuard 76 77 f = open(headerFile, 'wb') 78 for line in lines: 79 f.write(line) 80 f.close() 81 82def isHeader (filename): 83 for pattern in HEADER_PATTERNS: 84 if fnmatch(filename, pattern): 85 return True 86 return False 87 88def getHeaderFileList (path): 89 headers = [] 90 if os.path.isfile(path): 91 if isHeader(path): 92 headers.append(path) 93 else: 94 for root, dirs, files in os.walk(path): 95 for file in files: 96 if isHeader(file): 97 headers.append(os.path.join(root, file)) 98 return headers 99 100def checkIncludeGuards (files): 101 error = False 102 for file in files: 103 if isHeader(file): 104 if not hasValidIncludeGuard(file): 105 error = True 106 print "File %s contains invalid include guards" % file 107 return not error 108 109if __name__ == "__main__": 110 parser = OptionParser() 111 parser.add_option("-x", "--fix", action="store_true", dest="fix", default=False, help="attempt to fix include guards (use with caution)") 112 113 (options, args) = parser.parse_args() 114 fix = options.fix 115 headers = [] 116 invalidHeaders = [] 117 118 for dir in args: 119 headers += getHeaderFileList(os.path.normpath(dir)) 120 121 print "Checking..." 122 for header in headers: 123 print " %s" % header 124 if not hasValidIncludeGuard(header): 125 invalidHeaders.append(header) 126 127 print "" 128 if len(invalidHeaders) > 0: 129 print "Found %d files with invalid include guards:" % len(invalidHeaders) 130 131 for header in invalidHeaders: 132 print " %s" % header 133 134 if not fix: 135 sys.exit(-1) 136 else: 137 print "All headers have valid include guards." 138 139 if fix: 140 print "" 141 for header in invalidHeaders: 142 fixIncludeGuard(header) 143 print "Fixed %s" % header 144