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) 73