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] 33 34def checkEnds(line, ends): 35 return any(line.endswith(end) for end in ends) 36 37def hexDumpFromFile(filename, position, size): 38 print("Invalid symbol(s) at offset %x (%i), byte number: %i" % (position, position, size)) 39 columnWidth = 32 40 size += position % columnWidth 41 position = columnWidth * int(position / columnWidth) 42 size = columnWidth * int((size + columnWidth - 1) / columnWidth) 43 44 f = open(filename, 'rb') 45 f.seek(position) 46 47 out1 = "" 48 out2 = "" 49 numBytes = 0 50 while numBytes < size: 51 if numBytes % columnWidth == 0: 52 if len(out1) != 0: 53 print(out1 + " " + out2) 54 out1 = "" 55 out2 = "" 56 out1 += "%0.8X: " % + (position + numBytes) 57 58 byte = f.read(1) 59 if (byte == None): 60 break; 61 62 if (sys.version_info < (3, 0)): 63 byte = int(ord(byte[0])) 64 else: 65 byte = int(byte[0]) 66 67 numBytes += 1 68 69 out1 += "%0.2X " % byte 70 if (byte >= 32 and byte <=127): 71 out2 += chr(byte) 72 else: 73 out2 += '.' 74 75 if len(out1) != 0: 76 print(out1 + " " + out2) 77 78 f.close() 79 80def SearchInvalidSymbols (filename): 81 start = None 82 end = None 83 with open(filename, 'rb') as file: 84 for byte in iter(partial(file.read, 1), b''): 85 if (sys.version_info < (3, 0)): 86 byte = int(ord(byte[0])) 87 else: 88 byte = int(byte[0]) 89 if (byte > 0x7F): 90 if start == None: 91 start = file.tell() 92 else: 93 if start != None: 94 end = file.tell() 95 if end != None: 96 hexDumpFromFile(filename, start, end - start) 97 start = None 98 end = None 99 if start != None: 100 file.seek(0, 2) # Seek to end of file 101 end = file.tell() 102 hexDumpFromFile(filename, start, end - start) 103 104def checkFileEncoding (filename): 105 generalEncoding = "ascii" 106 file = None 107 error = False 108 try: 109 if (sys.version_info < (3, 0)): 110 file = open(filename, 'rt') 111 for line in file: 112 line.decode(generalEncoding) 113 else: 114 file = open(filename, 'rt', encoding=generalEncoding) 115 for bytes in iter(partial(file.read, 1024 * 1024), ''): 116 pass 117 except UnicodeDecodeError as e: 118 if not checkEnds(filename.replace("\\", "/"), EXCLUSION_LIST): 119 error = True 120 print("") 121 print("Unicode error in file: %s (%s)" % (filename, e)) 122 SearchInvalidSymbols(filename) 123 finally: 124 if file != None: 125 file.close() 126 127 return not error 128 129def checkEncoding (files): 130 error = False 131 for file in files: 132 if isTextFile(file): 133 if not checkFileEncoding(file): 134 error = True 135 136 return not error 137 138if __name__ == "__main__": 139 parser = ArgumentParser() 140 parser.add_argument("-e", "--only-errors", action="store_true", dest="onlyErrors", default=False, help="Print only on error") 141 parser.add_argument("-i", "--only-changed", action="store_true", dest="useGitIndex", default=False, help="Check only modified files. Uses git.") 142 143 args = parser.parse_args() 144 145 if args.useGitIndex: 146 files = getChangedFiles() 147 else: 148 files = getAllProjectFiles() 149 150 error = not checkEncoding(files) 151 152 if error: 153 print("One or more checks failed") 154 sys.exit(1) 155 if not args.onlyErrors: 156 print("All checks passed") 157