2021-06-10 20:05:25 +00:00
|
|
|
'''
|
|
|
|
PROJECT: ReactOS code linter
|
|
|
|
LICENSE: MIT (https://spdx.org/licenses/MIT)
|
2022-11-02 23:13:48 +00:00
|
|
|
PURPOSE: Verifies that there are no headers included where packing is modified
|
2021-06-10 20:05:25 +00:00
|
|
|
COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
|
|
|
|
'''
|
|
|
|
from pathlib import Path
|
|
|
|
import re
|
|
|
|
|
|
|
|
DEFAULT_SUFFIXES = [
|
2022-11-02 23:13:48 +00:00
|
|
|
'.cpp', '.cxx', '.cc', '.c', '.idl',
|
2021-06-10 20:05:25 +00:00
|
|
|
'.hpp', '.h', '.inc'
|
|
|
|
]
|
|
|
|
|
|
|
|
START_HEADERS = [
|
|
|
|
'pshpack1.h',
|
|
|
|
'pshpack2.h',
|
|
|
|
'pshpack4.h',
|
|
|
|
'pshpack8.h',
|
|
|
|
]
|
|
|
|
|
|
|
|
END_HEADERS = [
|
|
|
|
'poppack.h',
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
def print_error(file, line, text):
|
|
|
|
print(f'{file}({line}): ERROR: {text}')
|
|
|
|
|
|
|
|
def print_warning(file, line, text):
|
|
|
|
print(f'{file}({line}): WARNING: {text}')
|
|
|
|
|
|
|
|
|
|
|
|
def check_file(filename):
|
|
|
|
cur_packing = []
|
|
|
|
with open (filename, 'rb') as input_file:
|
|
|
|
for line_nr, line in enumerate(input_file):
|
|
|
|
res = re.search(rb'#[\s]*include[\s]+[<"]([^[">]+)[">]', line)
|
|
|
|
if res:
|
|
|
|
header = res.group(1).decode('utf-8')
|
|
|
|
line_nr += 1 # Line numbers start at 1
|
|
|
|
if header in START_HEADERS:
|
|
|
|
if cur_packing:
|
|
|
|
print_warning(filename, line_nr, f'Overrides packing from {cur_packing[-1][0]} to {header}')
|
|
|
|
cur_packing.append([header, line_nr])
|
|
|
|
elif header in END_HEADERS:
|
|
|
|
if cur_packing:
|
|
|
|
cur_packing.pop()
|
|
|
|
else:
|
|
|
|
print_error(filename, line_nr, f'Unexpected "{header}"')
|
|
|
|
elif cur_packing:
|
|
|
|
err = f'Include "{header}" while struct packing is modified ({cur_packing[-1][0]})'
|
|
|
|
print_error(filename, line_nr, err)
|
|
|
|
if cur_packing:
|
|
|
|
print_error(filename, cur_packing[-1][1], 'Struct packing not restored!')
|
|
|
|
|
|
|
|
|
|
|
|
def check_packing(path, include_suffixes):
|
|
|
|
global EXCLUDE_SUFFIXES
|
|
|
|
for item in path.iterdir():
|
|
|
|
if item.is_dir() and item.name[0] != '.':
|
|
|
|
check_packing(item, include_suffixes)
|
|
|
|
continue
|
|
|
|
suffix = item.suffix
|
|
|
|
if suffix in include_suffixes:
|
|
|
|
check_file(item)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
# Skip filename and 'sdk/tools'
|
|
|
|
use_path = Path(__file__).parents[2]
|
|
|
|
check_packing(use_path, DEFAULT_SUFFIXES)
|