1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------- 4# drawElements Quality Program utilities 5# -------------------------------------- 6# 7# Copyright 2019 The Khronos Group Inc. 8# Copyright 2015 The Android Open Source Project 9# 10# Licensed under the Apache License, Version 2.0 (the "License"); 11# you may not use this file except in compliance with the License. 12# You may obtain a copy of the License at 13# 14# http://www.apache.org/licenses/LICENSE-2.0 15# 16# Unless required by applicable law or agreed to in writing, software 17# distributed under the License is distributed on an "AS IS" BASIS, 18# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19# See the License for the specific language governing permissions and 20# limitations under the License. 21# 22#------------------------------------------------------------------------- 23 24import sys 25from functools import partial 26from argparse import ArgumentParser 27from common import getChangedFiles, getAllProjectFiles, isTextFile 28 29EXCLUSION_LIST = [ 30 "/doc/testspecs/VK/apitests.adoc", 31 "/targets/default/FindWayland.cmake", 32 "/scripts/src_util/clang-format", 33] 34 35def checkEnds(line, ends): 36 return any(line.endswith(end) for end in ends) 37 38def hexDumpFromFile(filename, position, size): 39 print("Invalid symbol(s) at offset %x (%i), byte number: %i" % (position, position, size)) 40 columnWidth = 32 41 size += position % columnWidth 42 position = columnWidth * int(position / columnWidth) 43 size = columnWidth * int((size + columnWidth - 1) / columnWidth) 44 45 f = open(filename, 'rb') 46 f.seek(position) 47 48 out1 = "" 49 out2 = "" 50 numBytes = 0 51 while numBytes < size: 52 if numBytes % columnWidth == 0: 53 if len(out1) != 0: 54 print(out1 + " " + out2) 55 out1 = "" 56 out2 = "" 57 out1 += "%0.8X: " % + (position + numBytes) 58 59 byte = f.read(1) 60 if (byte == None): 61 break; 62 63 if (sys.version_info < (3, 0)): 64 byte = int(ord(byte[0])) 65 else: 66 byte = int(byte[0]) 67 68 numBytes += 1 69 70 out1 += "%0.2X " % byte 71 if (byte >= 32 and byte <=127): 72 out2 += chr(byte) 73 else: 74 out2 += '.' 75 76 if len(out1) != 0: 77 print(out1 + " " + out2) 78 79 f.close() 80 81def SearchInvalidSymbols (filename): 82 start = None 83 end = None 84 with open(filename, 'rb') as file: 85 for byte in iter(partial(file.read, 1), b''): 86 if (sys.version_info < (3, 0)): 87 byte = int(ord(byte[0])) 88 else: 89 byte = int(byte[0]) 90 if (byte > 0x7F): 91 if start == None: 92 start = file.tell() 93 else: 94 if start != None: 95 end = file.tell() 96 if end != None: 97 hexDumpFromFile(filename, start, end - start) 98 start = None 99 end = None 100 if start != None: 101 file.seek(0, 2) # Seek to end of file 102 end = file.tell() 103 hexDumpFromFile(filename, start, end - start) 104 105def checkFileEncoding (filename): 106 generalEncoding = "ascii" 107 file = None 108 error = False 109 try: 110 if (sys.version_info < (3, 0)): 111 file = open(filename, 'rt') 112 for line in file: 113 line.decode(generalEncoding) 114 else: 115 file = open(filename, 'rt', encoding=generalEncoding) 116 for bytes in iter(partial(file.read, 1024 * 1024), ''): 117 pass 118 except UnicodeDecodeError as e: 119 if not checkEnds(filename.replace("\\", "/"), EXCLUSION_LIST): 120 error = True 121 print("") 122 print("Unicode error in file: %s (%s)" % (filename, e)) 123 SearchInvalidSymbols(filename) 124 finally: 125 if file != None: 126 file.close() 127 128 return not error 129 130def checkEncoding (files): 131 error = False 132 for file in files: 133 if isTextFile(file): 134 if not checkFileEncoding(file): 135 error = True 136 137 return not error 138 139if __name__ == "__main__": 140 parser = ArgumentParser() 141 parser.add_argument("-e", "--only-errors", action="store_true", dest="onlyErrors", default=False, help="Print only on error") 142 parser.add_argument("-i", "--only-changed", action="store_true", dest="useGitIndex", default=False, help="Check only modified files. Uses git.") 143 144 args = parser.parse_args() 145 146 if args.useGitIndex: 147 files = getChangedFiles() 148 else: 149 files = getAllProjectFiles() 150 151 error = not checkEncoding(files) 152 153 if error: 154 print("One or more checks failed") 155 sys.exit(1) 156 if not args.onlyErrors: 157 print("All checks passed") 158