blob: a18605a82b41de547889f91f34f9c31183f9f723 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001#!/usr/bin/env python3
2#
3# SPDX-License-Identifier: BSD-3-Clause
4# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
5# SPDX-FileCopyrightText: Copyright Arm Limited and Contributors.
6#
7
8from argparse import ArgumentParser
9import codecs
10import os
11import re
12import sys
13import logging
14from os import access, R_OK
15from os.path import isfile
16
17INCLUDE_RE = re.compile(r"^\s*#\s*include\s\s*(?P<path>[\"<].+[\">])")
18
19# exit program with rc
20def print_error_and_exit(total_errors):
21 if total_errors:
22 print("total: " + str(total_errors) + " errors")
23 sys.exit(1)
24 else:
25 sys.exit(0)
26
27def include_paths(lines):
28 """List all include paths in a file. Ignore starting `+` in diff mode."""
29 pattern = INCLUDE_RE
30 matches = (pattern.match(line) for line in lines)
31 return [m.group("path") for m in matches if m]
32
33# check if 'file' is a regular file and it is readable
34def file_readable(file):
35 if not isfile(file):
36 print(file + ": WARNING: File not found")
37 return 0
38
39 if not access(file, R_OK):
40 print(file + ": WARNING: File not readable")
41 return 0
42
43 return 1
44
45def file_include_list(path):
46 """Return a list of all include paths in a file or None on failure."""
47 try:
48 with codecs.open(path, encoding="utf-8") as f:
49 return include_paths(f)
50 except Exception:
51 logging.exception(path + ": ERROR while parsing.")
52 return ([])
53
54def check_includes(file):
55 """Checks whether the order of includes in the file specified in the path
56 is correct or not."""
57 print("Checking file: " + file)
58 if not file_readable(file):
59 return 0
60
61 inc_list = file_include_list(file)
62
63 # If there are less than 2 includes there's no need to check.
64 if len(inc_list) < 2:
65 return 0
66
67 # remove leading and trailing <, >
68 inc_list = [x[1:-1] for x in inc_list]
69
70 if sorted(inc_list) != inc_list:
71 print(file + ": ERROR: includes not in order. Include order should be " +
72 ', '.join(sorted(inc_list)))
73 return 1
74 else:
75 return 0
76
77if __name__ == "__main__":
78 ap = ArgumentParser(description='Check #include orders')
79 ap.add_argument('files', nargs='*', help='Check files.')
80 args = ap.parse_args()
81
82 total_errors = 0
83 for file in args.files:
84 total_errors += check_includes(file)
85
86 print_error_and_exit(total_errors)