xref: /aosp_15_r20/external/deqp/scripts/src_util/check_encoding.py (revision 35238bce31c2a825756842865a792f8cf7f89930)
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