mirror of
https://github.com/espressif/mbedtls.git
synced 2026-10-24 09:33:44 +00:00
174 lines
6.3 KiB
Python
Executable File
174 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Script to check/fix header guards in C header files.
|
|
|
|
Usage: scripts/c_header_guards.py [--fix]
|
|
|
|
The script must be called from the TF-PSA-Crypto root folder.
|
|
|
|
If called without any additional parameter the script checks current guards
|
|
and in case of any mismatching with respect to the expected format it print
|
|
the errors that it found and it returns an error code.
|
|
If called with '--fix' input parameter, instead, it checks and modifies headers'
|
|
guards if needed.
|
|
|
|
The expected format for the headers' guards is as follows:
|
|
1. "<rel_path>_<filename>_H" for public headers;
|
|
2. "TF_PSA_CRYPTO_<rel_path>_<filename>_H" for private ones;
|
|
where:
|
|
- 'TF_PSA_CRYPTO_' is an hardcoded prefix;
|
|
- 'rel_path' is the path used in C files to include such header file.
|
|
"""
|
|
|
|
## Copyright The Mbed TLS Contributors
|
|
## SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
|
|
|
import sys
|
|
import os
|
|
import re
|
|
import argparse
|
|
from typing import List, Tuple, Match
|
|
|
|
import framework_scripts_path # pylint: disable=unused-import
|
|
from mbedtls_framework import build_tree
|
|
|
|
PREFIX = 'TF_PSA_CRYPTO_'
|
|
|
|
# Dictionary containing the folders where header files are to be fixed/checked:
|
|
# - key: path of header files to check;
|
|
# - value: path that must be trimmed from the key value in order to get the
|
|
# final guard.
|
|
FOLDERS_TO_CHECK = {
|
|
'drivers/builtin/include/mbedtls/': 'drivers/builtin/include/',
|
|
'drivers/builtin/include/mbedtls/private/': 'drivers/builtin/include/',
|
|
'drivers/builtin/src/': 'drivers/builtin/src/',
|
|
'drivers/everest/include/tf-psa-crypto/private/everest/':
|
|
'drivers/everest/include/tf-psa-crypto/private/everest/',
|
|
'drivers/p256-m/': 'drivers/p256-m/',
|
|
'drivers/p256-m/p256-m/': 'drivers/p256-m/',
|
|
'include/mbedtls/': 'include/',
|
|
'include/psa/': 'include/',
|
|
'include/tf-psa-crypto/': 'include/',
|
|
'core/': 'core/',
|
|
'dispatch/': 'dispatch/',
|
|
'extras/': 'extras/',
|
|
'platform/': 'platform/',
|
|
'utilities/': 'utilities/',
|
|
}
|
|
|
|
def generate_guard_name(file_path: str, trim_path: str) -> str:
|
|
"""Generate the new header guard."""
|
|
adjusted_name = file_path
|
|
# Trim prefix
|
|
if adjusted_name.startswith(trim_path):
|
|
adjusted_name = adjusted_name[len(trim_path):]
|
|
# Remove suffix
|
|
if adjusted_name.endswith('.h'):
|
|
adjusted_name = adjusted_name[:-2]
|
|
|
|
adjusted_name = re.sub(r'[^a-zA-Z0-9]', '_', adjusted_name).upper()
|
|
guard_elements = []
|
|
# Add prefix only to non public header files
|
|
if not file_path.startswith('include'):
|
|
guard_elements.append('TF_PSA_CRYPTO')
|
|
guard_elements.extend([adjusted_name, 'H'])
|
|
return '_'.join(guard_elements)
|
|
|
|
def find_line(lines: List[str], search_range, regex: str) -> Tuple[int, Match]:
|
|
"""Try to match the regex expression on the range of lines given in input.
|
|
The first successful match is returned; an exception is returned if no
|
|
match is found in all the given lines.
|
|
|
|
Input params:
|
|
lines: content of the file given as list of strings;
|
|
search_range: range() to use when going through the list of lines;
|
|
regex: the regex expression to be used for the match.
|
|
|
|
Returns: a tuple where
|
|
int: the first line where the match was successful;
|
|
Match: the Match object returned on the matching line.
|
|
"""
|
|
for i in search_range:
|
|
stripped = lines[i].strip()
|
|
match = re.match(regex, stripped)
|
|
if match is not None:
|
|
return i, match
|
|
|
|
raise ValueError(f'Error: {regex} line not found')
|
|
|
|
def process_header(file_path, trim_path, fix) -> None:
|
|
"""Check/fix header guard in a single file.
|
|
On failure an exception is thrown.
|
|
"""
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
lines = f.readlines()
|
|
|
|
correct_guard = generate_guard_name(file_path, trim_path)
|
|
|
|
ifndef_line, match = find_line(lines, range(0, len(lines)),
|
|
r'#ifndef\s+(\w+)\b')
|
|
expected_line = f'#ifndef {correct_guard}'
|
|
if expected_line not in lines[ifndef_line]:
|
|
if fix:
|
|
lines[ifndef_line] = expected_line
|
|
else:
|
|
raise ValueError(f'Invalid guard format:\n'
|
|
f' Expected:{expected_line}'
|
|
f' Found:{match.group(0)}')
|
|
|
|
define_line, match = find_line(lines, range(ifndef_line, len(lines)),
|
|
r'#define\s+(\w+)\b')
|
|
expected_line = f'#define {correct_guard}'
|
|
if expected_line not in lines[define_line]:
|
|
if fix:
|
|
lines[define_line] = expected_line
|
|
else:
|
|
raise ValueError(f'Invalid guard format:\n'
|
|
f' Expected:{expected_line}'
|
|
f' Found:{match.group(0)}')
|
|
|
|
define_line, match = find_line(lines, range(len(lines) - 1, -1, -1),
|
|
r'#endif\s*\/\*\s*([\w+.]+)\s*\*\/')
|
|
expected_line = f'#endif /* {correct_guard} */'
|
|
if expected_line not in lines[define_line]:
|
|
if fix:
|
|
lines[define_line] = expected_line
|
|
else:
|
|
raise ValueError(f'Invalid guard format:\n'
|
|
f' Expected:{expected_line}'
|
|
f' Found:{match.group(0)}')
|
|
|
|
# Write back to file
|
|
new_content = ''.join(lines)
|
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
f.write(new_content)
|
|
|
|
def main():
|
|
current_path = os.getcwd()
|
|
|
|
arg_parser = argparse.ArgumentParser()
|
|
arg_parser.add_argument('--fix', action='store_true',
|
|
help="Fix guards in header files. Default behavior is to check only.")
|
|
args = arg_parser.parse_args()
|
|
|
|
if not build_tree.looks_like_tf_psa_crypto_root(current_path):
|
|
print("Error: this script must be launched from TF-PSA-Crypto root")
|
|
sys.exit(1)
|
|
|
|
had_failure = False
|
|
for folder in FOLDERS_TO_CHECK:
|
|
files = [filename for filename in os.listdir(folder) if re.match(r'.*\.h$', filename)]
|
|
for file in files:
|
|
full_file_path = os.path.join(folder, file)
|
|
try:
|
|
process_header(full_file_path, FOLDERS_TO_CHECK[folder], args.fix)
|
|
except ValueError as e:
|
|
print(f"Error processing {full_file_path}: {e}")
|
|
had_failure = True
|
|
|
|
if had_failure:
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|