Reactos
1'''
2PROJECT: ReactOS code linter
3LICENSE: MIT (https://spdx.org/licenses/MIT)
4PURPOSE: Verifies that there are no headers included where packing is modified
5COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
6'''
7from pathlib import Path
8import re
9
10DEFAULT_SUFFIXES = [
11 '.cpp', '.cxx', '.cc', '.c', '.idl',
12 '.hpp', '.h', '.inc'
13]
14
15START_HEADERS = [
16 'pshpack1.h',
17 'pshpack2.h',
18 'pshpack4.h',
19 'pshpack8.h',
20]
21
22END_HEADERS = [
23 'poppack.h',
24]
25
26
27def print_error(file, line, text):
28 print(f'{file}({line}): ERROR: {text}')
29
30def print_warning(file, line, text):
31 print(f'{file}({line}): WARNING: {text}')
32
33
34def check_file(filename):
35 cur_packing = []
36 with open (filename, 'rb') as input_file:
37 for line_nr, line in enumerate(input_file):
38 res = re.search(rb'#[\s]*include[\s]+[<"]([^[">]+)[">]', line)
39 if res:
40 header = res.group(1).decode('utf-8')
41 line_nr += 1 # Line numbers start at 1
42 if header in START_HEADERS:
43 if cur_packing:
44 print_warning(filename, line_nr, f'Overrides packing from {cur_packing[-1][0]} to {header}')
45 cur_packing.append([header, line_nr])
46 elif header in END_HEADERS:
47 if cur_packing:
48 cur_packing.pop()
49 else:
50 print_error(filename, line_nr, f'Unexpected "{header}"')
51 elif cur_packing:
52 err = f'Include "{header}" while struct packing is modified ({cur_packing[-1][0]})'
53 print_error(filename, line_nr, err)
54 if cur_packing:
55 print_error(filename, cur_packing[-1][1], 'Struct packing not restored!')
56
57
58def check_packing(path, include_suffixes):
59 global EXCLUDE_SUFFIXES
60 for item in path.iterdir():
61 if item.is_dir() and item.name[0] != '.':
62 check_packing(item, include_suffixes)
63 continue
64 suffix = item.suffix
65 if suffix in include_suffixes:
66 check_file(item)
67
68
69if __name__ == '__main__':
70 # Skip filename and 'sdk/tools'
71 use_path = Path(__file__).parents[2]
72 check_packing(use_path, DEFAULT_SUFFIXES)