#!/bin/bash

#
# NetLabel Tools code syntax checking tool
#
# Copyright (c) 2015 Red Hat <pmoore@redhat.com>
# Author: Paul Moore <pmoore@redhat.com>
#

#
# This program is free software: you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

CHK_C_LIST="include/*.h \
	    libnetlabel/*.c libnetlabel/*.h \
	    netlabelctl/*.c netlabelctl/*.h"
CHK_C_EXCLUDE=""

####
# functions

#
# Dependency verification
#
# Arguments:
#     1    Dependency to check for
#
function verify_deps() {
	[[ -z "$1" ]] && return
	if ! which "$1" >& /dev/null; then
		echo "error: install \"$1\" and include it in your \$PATH"
		exit 1
	fi
}

#
# Print out script usage details
#
function usage() {
cat << EOF
usage: check-syntax [-h]

netlabel tools code syntax checking tool
optional arguments:
  -h             show this help message and exit
  -f             fix the file formatting
EOF
}

#
# Generate a properly formatted C source/header file
#
# Arguments:
#     1    Source file
#
function tool_c_style() {
	astyle --options=none --lineend=linux --mode=c \
		--style=linux \
		--indent=force-tab=8 \
		--indent-preprocessor \
		--indent-col1-comments \
		--min-conditional-indent=0 \
		--max-instatement-indent=80 \
		--pad-oper \
		--align-pointer=name \
		--align-reference=name \
		--max-code-length=80 \
		--break-after-logical < "$1"
}

#
# Check the formatting on a C source/header file
#
# Arguments:
#     1    File to check
#
function tool_c_style_check() {
	[[ -z "$1" || ! -r "$1" ]] && return

	tool_c_style "$1" | diff -pu --label="$1.orig" "$1" --label="$1" -
}

#
# Fix the formatting on a C source/header file
#
# Arguments:
#     1    File to fix
#
function tool_c_style_fix() {
	[[ -z "$1" || ! -r "$1" ]] && return

	tmp="$(mktemp --tmpdir=$(dirname "$1"))"
	tool_c_style "$1" > "$tmp"
	mv "$tmp" "$1"
}

#
# Perform all known syntax checks for the configured C sources/headers
#
function check_c() {
	for i in $CHK_C_LIST; do
		echo "$CHK_C_EXCLUDE" | grep -q "$i" && continue
		echo "Differences for $i"
		tool_c_style_check "$i"
	done
}

#
# Perform all known syntax fixess for the configured C sources/headers
#
function fix_c() {
	for i in $CHK_C_LIST; do
		echo "$CHK_C_EXCLUDE" | grep -q "$i" && continue
		echo "Fixing $i"
		tool_c_style_fix "$i"
	done
}

####
# main

verify_deps astyle

opt_fix=0

while getopts "fh" opt; do
	case $opt in
	f)
		opt_fix=1
		;;
	h|*)
		usage
		exit 1
		;;
	esac
done

# display the results
echo "=============== $(date) ==============="
echo "Code Syntax Check Results (\"check-syntax $*\")"
if [[ $opt_fix -eq 1 ]]; then
	fix_c
else
	check_c
fi
echo "============================================================"

# exit
exit 0
