#!/usr/bin/env bash set -e function help() { cat < This script is a wrapper for cppcheck that enables it to analyse the files that are the target for the build, it is used in place of a selected compiler and the make process will run it on every file that needs to be built. All the arguments passed to the original compiler are forwarded to it without modification, furthermore, they are used to improve the cppcheck analysis. Options: --compiler= Use this compiler for the build --cppcheck-cmd= Command line for the cppcheck analysis. --cppcheck-html Prepare for cppcheck HTML output --cppcheck-plat= Path to the cppcheck platform folder --ignore-path= This script won't run cppcheck on the files having this path, the compiler will run anyway on them. This argument can be specified multiple times. -h, --help Print this help EOF } CC_FILE="" COMPILER="" CPPCHECK_HTML="n" CPPCHECK_PLAT_PATH="" CPPCHECK_TOOL="" CPPCHECK_TOOL_ARGS="" FORWARD_FLAGS="" IGNORE_PATH="n" IGNORE_PATH_LIST="" JDB_FILE="" OBJTREE_PATH="" # Variable used for arg parsing forward_to_cc="n" sm_tool_args="n" obj_arg_content="n" for OPTION in "$@" do if [ "${forward_to_cc}" = "y" ]; then if [[ ${OPTION} == *.c ]] then CC_FILE="${OPTION}" elif [ "${OPTION}" = "-o" ] then # After -o there is the path to the obj file, flag it obj_arg_content="y" elif [ "${obj_arg_content}" = "y" ] then # This must be the path to the obj file, turn off flag and save path OBJTREE_PATH="$(dirname "${OPTION}")" obj_arg_content="n" fi # Forward any argument to the compiler FORWARD_FLAGS="${FORWARD_FLAGS} ${OPTION}" continue fi case ${OPTION} in -h|--help) help exit 0 ;; --compiler=*) COMPILER="${OPTION#*=}" sm_tool_args="n" ;; --cppcheck-cmd=*) CPPCHECK_TOOL="${OPTION#*=}" sm_tool_args="y" ;; --cppcheck-html) CPPCHECK_HTML="y" sm_tool_args="n" ;; --cppcheck-plat=*) CPPCHECK_PLAT_PATH="${OPTION#*=}" sm_tool_args="n" ;; --ignore-path=*) IGNORE_PATH_LIST="${IGNORE_PATH_LIST} ${OPTION#*=}" sm_tool_args="n" ;; --) forward_to_cc="y" sm_tool_args="n" ;; *) if [ "${sm_tool_args}" = "y" ]; then CPPCHECK_TOOL_ARGS="${CPPCHECK_TOOL_ARGS} ${OPTION}" else echo "Invalid option ${OPTION}" exit 1 fi ;; esac done if [ "${COMPILER}" = "" ] then echo "--compiler arg is mandatory." exit 1 fi function create_jcd() { local line="${1}" local arg_num=0 local same_line=0 { echo "[" echo " {" echo " \"arguments\": [" for arg in ${line}; do # This code prevents to put comma in the last element of the list or # on sequential lines that are going to be merged if [ "${arg_num}" -ne 0 ] && [ "${same_line}" -eq 0 ] then echo "," fi if [ "${same_line}" -ne 0 ] then echo -n "${arg}\"" same_line=0 elif [ "${arg}" = "-iquote" ] || [ "${arg}" = "-I" ] then # cppcheck doesn't understand -iquote, substitute with -I echo -n " \"-I" same_line=1 else echo -n " \"${arg}\"" fi arg_num=$(( arg_num + 1 )) done echo "" echo " ]," echo " \"directory\": \"$(pwd -P)\"," echo " \"file\": \"${CC_FILE}\"" echo " }" echo "]" } > "${JDB_FILE}" } # Execute compiler with forwarded flags # Shellcheck complains about missing quotes on FORWARD_FLAGS, but they can't be # used here # shellcheck disable=SC2086 ${COMPILER} ${FORWARD_FLAGS} if [ -n "${CC_FILE}" ]; then for path in ${IGNORE_PATH_LIST} do if [[ ${CC_FILE} == *${path}* ]] then IGNORE_PATH="y" echo "${0}: ${CC_FILE} ignored by --ignore-path matching *${path}*" fi done if [ "${IGNORE_PATH}" = "n" ] then JDB_FILE="${OBJTREE_PATH}/$(basename "${CC_FILE}".json)" # Prepare the Json Compilation Database for the file create_jcd "${COMPILER} ${FORWARD_FLAGS}" out_file="${OBJTREE_PATH}/$(basename "${CC_FILE%.c}".cppcheck.txt)" # Select the right target platform, ARCH is generated from Xen Makefile case ${ARCH} in arm64) # arm64 has efi code compiled with -fshort-wchar platform="${CPPCHECK_PLAT_PATH}/arm64-wchar_t2.xml" ;; arm32) # arm32 has no efi code platform="${CPPCHECK_PLAT_PATH}/arm32-wchar_t4.xml" ;; x86_64) # x86_64 has efi code compiled with -fshort-wchar platform="${CPPCHECK_PLAT_PATH}/x86_64-wchar_t2.xml" ;; *) echo "ARCH: ${ARCH} not expected!" exit 1 ;; esac if [ ! -f "${platform}" ] then echo "${platform} not found!" exit 1 fi # Shellcheck complains about missing quotes on CPPCHECK_TOOL_ARGS, but # they can't be used here # shellcheck disable=SC2086 ${CPPCHECK_TOOL} ${CPPCHECK_TOOL_ARGS} \ --project="${JDB_FILE}" \ --output-file="${out_file}" \ --platform="${platform}" if [ "${CPPCHECK_HTML}" = "y" ] then # Shellcheck complains about missing quotes on CPPCHECK_TOOL_ARGS, # but they can't be used here # shellcheck disable=SC2086 ${CPPCHECK_TOOL} ${CPPCHECK_TOOL_ARGS} \ --project="${JDB_FILE}" \ --output-file="${out_file%.txt}.xml" \ --platform="${platform}" \ -q \ --xml fi fi fi