diff --git a/.uncrustify.cfg b/.uncrustify.cfg new file mode 100644 index 0000000000..ac9173e18d --- /dev/null +++ b/.uncrustify.cfg @@ -0,0 +1,254 @@ +# Configuration options for Uncrustify specifying the Mbed TLS code style. +# +# Note: The code style represented by this file has not yet been introduced +# to Mbed TLS. +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Line length options + +# Wrap lines at 100 characters +code_width = 100 + +# Allow splitting long for statements between the condition statements +ls_for_split_full = true + +# Allow splitting function calls between arguments +ls_func_split_full = true + +input_tab_size = 4 + +# Spaces-only indentation +indent_with_tabs = 0 + +indent_columns = 4 + +# Indent 'case' 1 level from 'switch' +indent_switch_case = indent_columns + +# Line-up strings broken by '\' +indent_align_string = true + +# Braces on the same line (Egyptian-style braces) +nl_enum_brace = remove +nl_union_brace = remove +nl_struct_brace = remove +nl_do_brace = remove +nl_if_brace = remove +nl_for_brace = remove +nl_else_brace = remove +nl_while_brace = remove +nl_switch_brace = remove + +# Braces on same line as keywords that follow them - 'else' and the 'while' in 'do {} while ()'; +nl_brace_else = remove +nl_brace_while = remove +# Space before else on the same line +sp_brace_else = add +# If else is on the same line as '{', force exactly 1 space between them +sp_else_brace = force + +# Functions are the exception and have braces on the next line +nl_fcall_brace = add +nl_fdef_brace = add + +# Force exactly one space between ')' and '{' in statements +sp_sparen_brace = force + +# At least 1 space around assignment +sp_assign = add + +# Remove spaces around the preprocessor '##' token-concatenate +sp_pp_concat = ignore + +# At least 1 space around '||' and '&&' +sp_bool = add + +# But no space after the '!' operator +sp_not = remove + +# No space after the bitwise-not '~' operator +sp_inv = remove + +# No space after the addressof '&' operator +sp_addr = remove + +# No space around the member '.' and '->' operators +sp_member = remove + +# No space after the dereference '*' operator +sp_deref = remove + +# No space after a unary negation '-' +sp_sign = remove + +# No space between the '++'/'--' operator and its operand +sp_incdec = remove + +# At least 1 space around comparison operators +sp_compare = add + +# Remove spaces inside all kinds of parentheses: + +# Remove spaces inside parentheses +sp_inside_paren = remove + +# No spaces inside statement parentheses +sp_inside_sparen = remove + +# No spaces inside cast parentheses '( char )x' -> '(char)x' +sp_inside_paren_cast = remove + +# No spaces inside function parentheses +sp_inside_fparen = remove +# (The case where the function has no parameters/arguments) +sp_inside_fparens = remove + +# No spaces inside the first parentheses in a function type +sp_inside_tparen = remove + +# (Uncrustify >= 0.74.0) No spaces inside parens in for statements +sp_inside_for = remove + +# Remove spaces between nested parentheses '( (' -> '((' +sp_paren_paren = remove +# (Uncrustify >= 0.74.0) +sp_sparen_paren = remove + +# Remove spaces between ')' and adjacent '(' +sp_cparen_oparen = remove + +# (Uncrustify >= 0.73.0) space between 'do' and '{' +sp_do_brace_open = force + +# (Uncrustify >= 0.73.0) space between '}' and 'while' +sp_brace_close_while = force + +# At least 1 space before a '*' pointer star +sp_before_ptr_star = add + +# Remove spaces between pointer stars +sp_between_ptr_star = remove + +# No space after a pointer star +sp_after_ptr_star = remove + +# But allow a space in the case of e.g. char * const x; +sp_after_ptr_star_qualifier = ignore + +# Remove space after star in a function return type +sp_after_ptr_star_func = remove + +# At least 1 space after a type in variable definition etc +sp_after_type = add + +# Force exactly 1 space between a statement keyword (e.g. 'if') and an opening parenthesis +sp_before_sparen = force + +# Remove a space before a ';' +sp_before_semi = remove +# (Uncrustify >= 0.73.0) Remove space before a semi in a non-empty for +sp_before_semi_for = remove +# (Uncrustify >= 0.73.0) Remove space in empty first statement of a for +sp_before_semi_for_empty = remove +# (Uncrustify >= 0.74.0) Remove space in empty middle statement of a for +sp_between_semi_for_empty = remove + +# Add a space after a ';' (unless a comment follows) +sp_after_semi = add +# (Uncrustify >= 0.73.0) Add a space after a semi in non-empty for statements +sp_after_semi_for = add +# (Uncrustify >= 0.73.0) No space after final semi in empty for statements +sp_after_semi_for_empty = remove + +# Remove spaces on the inside of square brackets '[]' +sp_inside_square = remove + +# Must have at least 1 space after a comma +sp_after_comma = add + +# Must not have a space before a comma +sp_before_comma = remove + +# No space before the ':' in a case statement +sp_before_case_colon = remove + +# No space after a cast - '(char) x' -> '(char)x' +sp_after_cast = remove + +# No space between 'sizeof' and '(' +sp_sizeof_paren = remove + +# At least 1 space inside '{ }' +sp_inside_braces = add + +# At least 1 space inside '{ }' in an enum +sp_inside_braces_enum = add + +# At least 1 space inside '{ }' in a struct +sp_inside_braces_struct = add + +# At least 1 space between a function return type and the function name +sp_type_func = add + +# No space between a function name and its arguments/parameters +sp_func_proto_paren = remove +sp_func_def_paren = remove +sp_func_call_paren = remove + +# No space between '__attribute__' and '(' +sp_attribute_paren = remove + +# No space between 'defined' and '(' in preprocessor conditions +sp_defined_paren = remove + +# At least 1 space between a macro's name and its definition +sp_macro = add +sp_macro_func = add + +# Force exactly 1 space between a '}' and the name of a typedef if on the same line +sp_brace_typedef = force + +# At least 1 space before a '\' line continuation +sp_before_nl_cont = add + +# At least 1 space around '?' and ':' in ternary statements +sp_cond_colon = add +sp_cond_question = add + +# Space between #else/#endif and comment afterwards +sp_endif_cmt = add + +# Remove newlines at the start of a file +nl_start_of_file = remove + +# At least 1 newline at the end of a file +nl_end_of_file = add +nl_end_of_file_min = 1 + +# Add braces in single-line statements +mod_full_brace_do = add +mod_full_brace_for = add +mod_full_brace_if = add +mod_full_brace_while = add + +# Remove parentheses from return statements +mod_paren_on_return = remove + +# Disable removal of leading spaces in a multi-line comment if the first and +# last lines are the same length +cmt_multi_check_last = false diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 04e43e39d7..dfb4c5f6ea 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -23,6 +23,7 @@ #ifndef MBEDTLS_CHECK_CONFIG_H #define MBEDTLS_CHECK_CONFIG_H +/* *INDENT-OFF* */ /* * We assume CHAR_BIT is 8 in many places. In practice, this is true on our * target platforms, so not an issue, but let's just be extra sure. @@ -1099,4 +1100,5 @@ */ typedef int mbedtls_iso_c_forbids_empty_translation_units; +/* *INDENT-ON* */ #endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c index 13037190dd..f40874e1c0 100644 --- a/programs/psa/key_ladder_demo.c +++ b/programs/psa/key_ladder_demo.c @@ -713,4 +713,6 @@ usage_failure: usage( ); return( EXIT_FAILURE ); } -#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C && MBEDTLS_AES_C && MBEDTLS_CCM_C && MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */ +#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C && + MBEDTLS_AES_C && MBEDTLS_CCM_C && + MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */ diff --git a/scripts/code_style.py b/scripts/code_style.py new file mode 100755 index 0000000000..68cd556200 --- /dev/null +++ b/scripts/code_style.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +"""Check or fix the code style by running Uncrustify. + +Note: The code style enforced by this script is not yet introduced to +Mbed TLS. At present this script will only be used to prepare for a future +change of code style. +""" +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import argparse +import io +import os +import subprocess +import sys +from typing import List + +UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1" +CONFIG_FILE = ".uncrustify.cfg" +UNCRUSTIFY_EXE = "uncrustify" +UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE] +STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') +STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + +def print_err(*args): + print("Error: ", *args, file=STDERR_UTF8) + +def get_src_files() -> List[str]: + """ + Use git ls-files to get a list of the source files + """ + git_ls_files_cmd = ["git", "ls-files", + "*.[hc]", + "tests/suites/*.function", + "scripts/data_files/*.fmt"] + + result = subprocess.run(git_ls_files_cmd, stdout=subprocess.PIPE, \ + stderr=STDERR_UTF8, check=False) + + if result.returncode != 0: + print_err("git ls-files returned: " + str(result.returncode)) + return [] + else: + src_files = str(result.stdout, "utf-8").split() + # Don't correct style for files in 3rdparty/ + src_files = list(filter( \ + lambda filename: not filename.startswith("3rdparty/"), \ + src_files)) + return src_files + +def get_uncrustify_version() -> str: + """ + Get the version string from Uncrustify + """ + result = subprocess.run([UNCRUSTIFY_EXE, "--version"], \ + stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) + if result.returncode != 0: + print_err("Could not get Uncrustify version:", str(result.stderr, "utf-8")) + return "" + else: + return str(result.stdout, "utf-8") + +def check_style_is_correct(src_file_list: List[str]) -> bool: + """ + Check the code style and output a diff for each file whose style is + incorrect. + """ + style_correct = True + for src_file in src_file_list: + uncrustify_cmd = [UNCRUSTIFY_EXE] + UNCRUSTIFY_ARGS + [src_file] + subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \ + stderr=subprocess.PIPE, check=False) + + # Uncrustify makes changes to the code and places the result in a new + # file with the extension ".uncrustify". To get the changes (if any) + # simply diff the 2 files. + diff_cmd = ["diff", "-u", src_file, src_file + ".uncrustify"] + result = subprocess.run(diff_cmd, stdout=subprocess.PIPE, \ + stderr=STDERR_UTF8, check=False) + if len(result.stdout) > 0: + print(src_file + " - Incorrect code style.", file=STDOUT_UTF8) + print("File changed - diff:", file=STDOUT_UTF8) + print(str(result.stdout, "utf-8"), file=STDOUT_UTF8) + style_correct = False + else: + print(src_file + " - OK.", file=STDOUT_UTF8) + + # Tidy up artifact + os.remove(src_file + ".uncrustify") + + return style_correct + +def fix_style_single_pass(src_file_list: List[str]) -> None: + """ + Run Uncrustify once over the source files. + """ + code_change_args = UNCRUSTIFY_ARGS + ["--no-backup"] + for src_file in src_file_list: + uncrustify_cmd = [UNCRUSTIFY_EXE] + code_change_args + [src_file] + subprocess.run(uncrustify_cmd, check=False, stdout=STDOUT_UTF8, \ + stderr=STDERR_UTF8) + +def fix_style(src_file_list: List[str]) -> int: + """ + Fix the code style. This takes 2 passes of Uncrustify. + """ + fix_style_single_pass(src_file_list) + fix_style_single_pass(src_file_list) + + # Guard against future changes that cause the codebase to require + # more passes. + if not check_style_is_correct(src_file_list): + print("Code style still incorrect after second run of Uncrustify.") + return 1 + else: + return 0 + +def main() -> int: + """ + Main with command line arguments. + """ + uncrustify_version = get_uncrustify_version().strip() + if UNCRUSTIFY_SUPPORTED_VERSION not in uncrustify_version: + print("Warning: Using unsupported Uncrustify version '" \ + + uncrustify_version + "' (Note: The only supported version" \ + "is " + UNCRUSTIFY_SUPPORTED_VERSION + ")", file=STDOUT_UTF8) + + src_files = get_src_files() + + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--fix', action='store_true', \ + help='modify source files to fix the code style') + + args = parser.parse_args() + + if args.fix: + # Fix mode + return fix_style(src_files) + else: + # Check mode + if check_style_is_correct(src_files): + return 0 + else: + return 1 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index cadedb1bd1..deb525785e 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -3662,6 +3662,26 @@ support_test_psa_compliance () { [ "$ver_major" -eq 3 ] && [ "$ver_minor" -ge 10 ] } +component_test_corrected_code_style () { + ./scripts/code_style.py --fix + + msg "build: make, default config (out-of-box), corrected code style" + make + + msg "test: main suites make, default config (out-of-box), corrected code style" + make test + + # Clean up code-style corrections + git checkout -- . +} + +support_test_corrected_code_style() { + case $(uncrustify --version) in + *0.75.1*) true;; + *) false;; + esac +} + component_check_python_files () { msg "Lint: Python scripts" tests/scripts/check-python-files.sh