• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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