blob: 6b5a8a3a0a3fd68691d50c2076e69488213916b8 [file] [log] [blame] [edit]
#!/usr/bin/env python3
#
# Copyright (c) 2025, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# This script updates the header guards in .hpp and .h files within the `src`
# `include/openthread`, and `tests` directories. It ensures that header
# guards follow a consistent naming convention based on the file path.
import os
#----------------------------------------------------------------------------------------------
# Helper functions
def get_header_file_list(path):
"""Get a sorted list of full file names (with path) in a given `path` folder having either `.h` or `.hpp` extension"""
return sorted([
"{}/{}".format(dir_path, file_name)[2:]
for dir_path, dir_names, file_names in os.walk('./' + path)
for file_name in file_names
if file_name.endswith('.hpp') or file_name.endswith('.h')
])
def read_txt_file(file_name):
"""Read the content of a text file with name `file_name` and return content as a list of lines"""
with open(file_name, 'r') as file:
lines = file.readlines()
return lines
def write_txt_file(file_name, lines):
"""Write a text file with name `file_name` with the content given as a list of `lines`"""
with open(file_name, 'w') as file:
file.writelines(lines)
def update_header_guard_in(file_name, replace_str, new_str):
"""Update header guard in a given file.
Args:
file_name (str): The name of the file to update.
replace_str (str): The prefix string to replace in the file path to generate header guard name
new_str (str): The new string to use as a prefix for the header guard.
"""
STATE_SEARCH = 1
STATE_MATCH_START = 2
STATE_DONE = 3
# Strip and replace the `replace_str` with `new_str`.
# Then replace '/','.', or `-` with '_', then format.
guard_name = file_name.replace(replace_str, new_str, 1)
guard_name = guard_name.replace('/', '_').replace('-', '_').replace('.', '_').upper() + '_'
lines = read_txt_file(file_name)
new_lines = []
state = STATE_SEARCH
for line in lines[:-1]:
if state == STATE_SEARCH:
if line.startswith('#ifndef '):
state = STATE_MATCH_START
line = '#ifndef ' + guard_name + '\n'
new_lines.append(line)
elif state == STATE_MATCH_START:
if not line.startswith('#define'):
raise RuntimeError('missing header guard #define in: {}'.format(file_name))
line = '#define ' + guard_name + '\n'
new_lines.append(line)
state = STATE_DONE
else:
new_lines.append(line)
if state != STATE_DONE:
raise RuntimeError('missing header guard #ifndef in: {}'.format(file_name))
if not lines[-1].startswith('#endif'):
raise RuntimeError('missing header guard #endif in: {}'.format(file_name))
new_lines.append('#endif // ' + guard_name + '\n')
if new_lines != lines:
write_txt_file(file_name, new_lines)
print("- Updated {} ({})".format(file_name, guard_name))
#----------------------------------------------------------------------------------------------
# Check and update header guards in various folders
folders = [('src', 'OT'), ('include/openthread', 'OPENTHREAD'), ('tests', 'OT')]
for folder in folders:
path = folder[0]
guard_prefix = folder[1]
header_file_list = get_header_file_list(path)
print('Updating header guards in ./{}/'.format(path))
for file_name in header_file_list:
update_header_guard_in(file_name, path, guard_prefix)