| # -*- coding: utf-8 -*- |
| |
| #------------------------------------------------------------------------- |
| # drawElements Quality Program utilities |
| # -------------------------------------- |
| # |
| # Copyright 2019 The Khronos Group Inc. |
| # Copyright 2015 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| #------------------------------------------------------------------------- |
| |
| import sys |
| from functools import partial |
| from argparse import ArgumentParser |
| from common import getChangedFiles, getAllProjectFiles, isTextFile |
| |
| EXCLUSION_LIST = [ |
| "/doc/testspecs/VK/apitests.adoc", |
| "/targets/default/FindWayland.cmake", |
| ] |
| |
| def checkEnds(line, ends): |
| return any(line.endswith(end) for end in ends) |
| |
| def hexDumpFromFile(filename, position, size): |
| print("Invalid symbol(s) at offset %x (%i), byte number: %i" % (position, position, size)) |
| columnWidth = 32 |
| size += position % columnWidth |
| position = columnWidth * int(position / columnWidth) |
| size = columnWidth * int((size + columnWidth - 1) / columnWidth) |
| |
| f = open(filename, 'rb') |
| f.seek(position) |
| |
| out1 = "" |
| out2 = "" |
| numBytes = 0 |
| while numBytes < size: |
| if numBytes % columnWidth == 0: |
| if len(out1) != 0: |
| print(out1 + " " + out2) |
| out1 = "" |
| out2 = "" |
| out1 += "%0.8X: " % + (position + numBytes) |
| |
| byte = f.read(1) |
| if (byte == None): |
| break; |
| |
| if (sys.version_info < (3, 0)): |
| byte = int(ord(byte[0])) |
| else: |
| byte = int(byte[0]) |
| |
| numBytes += 1 |
| |
| out1 += "%0.2X " % byte |
| if (byte >= 32 and byte <=127): |
| out2 += chr(byte) |
| else: |
| out2 += '.' |
| |
| if len(out1) != 0: |
| print(out1 + " " + out2) |
| |
| f.close() |
| |
| def SearchInvalidSymbols (filename): |
| start = None |
| end = None |
| with open(filename, 'rb') as file: |
| for byte in iter(partial(file.read, 1), b''): |
| if (sys.version_info < (3, 0)): |
| byte = int(ord(byte[0])) |
| else: |
| byte = int(byte[0]) |
| if (byte > 0x7F): |
| if start == None: |
| start = file.tell() |
| else: |
| if start != None: |
| end = file.tell() |
| if end != None: |
| hexDumpFromFile(filename, start, end - start) |
| start = None |
| end = None |
| if start != None: |
| file.seek(0, 2) # Seek to end of file |
| end = file.tell() |
| hexDumpFromFile(filename, start, end - start) |
| |
| def checkFileEncoding (filename): |
| generalEncoding = "ascii" |
| file = None |
| error = False |
| try: |
| if (sys.version_info < (3, 0)): |
| file = open(filename, 'rt') |
| for line in file: |
| line.decode(generalEncoding) |
| else: |
| file = open(filename, 'rt', encoding=generalEncoding) |
| for bytes in iter(partial(file.read, 1024 * 1024), ''): |
| pass |
| except UnicodeDecodeError as e: |
| if not checkEnds(filename.replace("\\", "/"), EXCLUSION_LIST): |
| error = True |
| print("") |
| print("Unicode error in file: %s (%s)" % (filename, e)) |
| SearchInvalidSymbols(filename) |
| finally: |
| if file != None: |
| file.close() |
| |
| return not error |
| |
| def checkEncoding (files): |
| error = False |
| for file in files: |
| if isTextFile(file): |
| if not checkFileEncoding(file): |
| error = True |
| |
| return not error |
| |
| if __name__ == "__main__": |
| parser = ArgumentParser() |
| parser.add_argument("-e", "--only-errors", action="store_true", dest="onlyErrors", default=False, help="Print only on error") |
| parser.add_argument("-i", "--only-changed", action="store_true", dest="useGitIndex", default=False, help="Check only modified files. Uses git.") |
| |
| args = parser.parse_args() |
| |
| if args.useGitIndex: |
| files = getChangedFiles() |
| else: |
| files = getAllProjectFiles() |
| |
| error = not checkEncoding(files) |
| |
| if error: |
| print("One or more checks failed") |
| sys.exit(1) |
| if not args.onlyErrors: |
| print("All checks passed") |