#!/bin/sh
# $Id: tdindent,v 1.46 2020/12/11 23:51:43 tom Exp $
#****************************************************************************
#* Copyright (c) 2010-2019,2020 Thomas E. Dickey                            *
#*                                                                          *
#* Permission is hereby granted, free of charge, to any person obtaining a  *
#* copy of this software and associated documentation files (the            *
#* "Software"), to deal in the Software without restriction, including      *
#* without limitation the rights to use, copy, modify, merge, publish,      *
#* distribute, distribute with modifications, sublicense, and/or sell       *
#* copies of the Software, and to permit persons to whom the Software is    *
#* furnished to do so, subject to the following conditions:                 *
#*                                                                          *
#* The above copyright notice and this permission notice shall be included  *
#* in all copies or substantial portions of the Software.                   *
#*                                                                          *
#* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
#* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
#* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
#* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
#* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
#* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
#* THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
#*                                                                          *
#* Except as contained in this notice, the name(s) of the above copyright   *
#* holders shall not be used in advertising or otherwise to promote the     *
#* sale, use or other dealings in this Software without prior written       *
#* authorization.                                                           *
#****************************************************************************/
# this was ncu-indent, before integrating with cindent package in 2010.

: ${INDENT_PROG:=indent}
: ${INDENT_DATA:=.}

NOOP=no
OPTS="-npro"
USED=no
TEST_D=no
TEST_N=no

PROFILE=
unset INDENT_PROFILE

MY_PWD=`pwd`
MY_TMP=`mktemp -d 2>/dev/null`
[ -d "$MY_TMP" ] || mkdir ${TMPDIR:=/tmp}/indent$$
mkdir $MY_TMP/scripts
trap "cd $MY_PWD; rm -rf $MY_TMP" EXIT INT QUIT TERM HUP

cat >$MY_TMP/prepro <<'EOF'
/EMPTY_MODULE(/s/)$/);/
s,\(MODULEID(\),//\1,
/MODULE_ID(/s/)$/);/
s,[[:space:]]*\<GCC_UNUSED[[:space:]]*\([;]\),\1//GCC_UNUSED,
s,[[:space:]]*\<_X_NORETURN\(.*\);,;//_X_NORETURN\1,
s,[[:space:]]*\<_X_UNUSED\(.*\);,;//_X_UNUSED\1,
s,[[:space:]]*\<GCC_NORETURN\(.*\);,;//GCC_NORETURN\1,
s,[[:space:]]*\<GCC_PRINTFLIKE(\(.*\);,;//GCC_PRINTFLIKE(\1,
s,[[:space:]]*\<GCC_SCANFLIKE(\(.*\);,;//GCC_SCANFLIKE(\1,
:gcc2
/\/\/GCC_.*\/\/GCC_/ {
	s,\(//GCC_[UNPS][^/][^/]*\)//\(GCC_[UNPS].*\),\1 \2,
	b gcc2
}
s,\(\<FORM_EXPORT_VAR\>.*;\),//\1,
s,\(\<MENU_EXPORT_VAR\>.*;\),//\1,
s,\(\<NCURSES_EXPORT_VAR\>.*;\),//\1,
s,\(\<PANEL_EXPORT_VAR\>.*;\),//\1,
s,\(\<MARK_END_OF_PROLOG\>\),\1;,
s,\(\<YY_RULE_SETUP\>\),\1;,
s,\(\<YY_BREAK\>\),\1;,
EOF

cat >$MY_TMP/postpro <<'EOF'
/EMPTY_MODULE(/s/);$/)/
s,//\(MODULEID(\),\1,
/MODULE_ID(/s/);$/)/
s,[[:space:]]*\([;]\)[[:space:]]*//GCC_UNUSED\(.*\), GCC_UNUSED\1\2,
s,;[[:space:]]*//_X_NORETURN\(.*\);, _X_NORETURN\1;,
s,;[[:space:]]*//_X_UNUSED\(.*\);, _X_UNUSED\1;,
s,;[[:space:]]*//GCC_NORETURN\(.*\);, GCC_NORETURN\1;,
s,;[[:space:]]*//GCC_PRINTFLIKE(\(.*\);, GCC_PRINTFLIKE(\1;,
s,;[[:space:]]*//GCC_SCANFLIKE(\(.*\);, GCC_SCANFLIKE(\1;,
s,;[[:space:]]*//\(_X_.*\), \1;,
s,;[[:space:]]*//\(GCC_.*\), \1;,
s,\(\<GCC_[^[:space:]][^[:space:]]*\)[[:space:]][[:space:]]*\(\<GCC_[^[:space:]]\),\1 \2,g
s,//\(\<FORM_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<MENU_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<NCURSES_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<PANEL_EXPORT_VAR\>[ ]*\),\1,
s,\(\<MARK_END_OF_PROLOG\>\);,\1,
s,\(\<YY_RULE_SETUP\>\);,\1,
s,\(\<YY_BREAK\>\);,\1,
EOF

while [ $# != 0 ]
do
	OPT2=
	name="$1"
	shift

	case $name in
	-n|-vn|-nv)
		NOOP=yes
		OPTS="$OPTS -v"
		;;
	-s)
		OPTS="$OPTS -nut"
		;;
	-h|-help|--help)
		cat <<-EOF
		This is a wrapper for the $INDENT_PROG program, which adds options.
		Unrecognized options are passed to $INDENT_PROG, which does not use
		getopt.

		The wrapper pre/post-filters the source to provide for macros which
		would confuse $INDENT_PROG.

		Options:
		  -h             help (shows this message)
		  -n             no-op (perform indent and show difference without saving)
		  --profile file get settings (look in current, home or $INDENT_DATA)
		  -s             convert tabs to spaces in the updated file
		  -D             test: show differences from pre-filtering
		  -N             test: suppress indent, to test pre/post-filtering
EOF
		exit
		;;
	-version|--version)
		cat <<-EOF
		This is a wrapper for `$INDENT_PROG -version`
EOF
		;;
	-profile|--profile)
		if [ $# = 0 ]
		then
			echo "?? missing parameter for $name"
			$0 -h
			exit 1
		fi
		if [ -f "$1" ]
		then
			PROFILE="$1"
		elif [ -f "$HOME/$1" ]
		then
			PROFILE="$HOME/$1"
		elif [ -f "$INDENT_DATA/$1" ]
		then
			PROFILE="$INDENT_DATA/$1"
		else
			echo "?? cannot find profile $1"
			$0 -h
			exit 1
		fi
		shift
		case `$INDENT_PROG -version 2>/dev/null` in
		*.*-2[0-9][0-9][0-9][0-9][0-9][0-9][0-9])	# cindent uses yyyymmdd
			myprof=`basename "$PROFILE"`
			cat "$PROFILE" >$MY_TMP/scripts/$myprof
			PROFILE=./scripts/$myprof
			OPTS="--profile $PROFILE"
			;;
		*)
			OPTS=`sed \
				-e '/\/\*.*\*\//d' \
				-e '/\/\*/,/\*\//d' \
				-e 's/[ 	]*\([0-9]\)/\1/g' $PROFILE | tr '\n' ' '`
			OPTS="-npro $OPTS"
			;;
		esac
		[ "$NOOP" = yes ] && OPTS="$OPTS -v"
		;;
	-D)
		TEST_D=yes
		;;
	-N)
		TEST_N=yes
		NOOP=yes
		;;
	-*)
		OPTS="$OPTS $name"
		;;
	*.[ch]|*.hh|*.cc|*.cpp|*.[yl])
		case $name in
		*.[yl])
			OPT2="-ly"
			;;
		esac
		USED=yes

		leaf=`basename "$name"`
		save="$MY_TMP/${leaf}".orig
		test="$MY_TMP/${leaf}"
		rm -f "$save" "$test"

		# (pre-filter) temporarily comment-out macros which confuse indent
		cp "$name" "$save"
		sed -f $MY_TMP/prepro "$save" >"$test"

		# work in the temp-directory to leave its pathname out of diffs
		cd $MY_TMP

		# show the result of pre-filtering for the -D option
		if [ $TEST_D = yes ]; then
			echo ".. pre-filtering"
			diff -u "$leaf".orig "$leaf"
		fi

		# if the -N option is given, simply echo the command rather than
		# performing it.
		if [ $TEST_N = yes ]; then
			echo "$INDENT_PROG $OPTS $OPT2 $leaf"
		else
			$INDENT_PROG $OPTS $OPT2 "$leaf" 2>&1 | \
				sed	-E \
					-e "s/^(${INDENT_PROG##*/}|indent): //"
		fi

		# (post-filter) restore the file.  There is an extra chunk used to
		# handle multiple GCC_xxx's on the same line.
		sed -f $MY_TMP/postpro "$leaf" >"$leaf".new
		rm -f "${leaf}"
		rm -f "${leaf}~"
		mv "$leaf".new "$leaf"

		if [ $NOOP = yes ]; then
			if ( cmp -s "$save" "$test" ) ; then
				echo "** no change: $name"
			else
				diff -u "$leaf".orig "$leaf"
			fi
			cd "$MY_PWD"
		else
			cd "$MY_PWD"
			if ( cmp -s "$save" "$test" ) ; then
				echo "** unchanged $name"
			else
				echo "** updated $name"
				chmod u+w "$name"
				cat "$test" >"$name"
				chmod u-w "$name"
			fi
		fi
		;;
	*)
		USED=yes
		echo "** ignored:   $name"
		;;
	esac
done
if [ $USED = no ]
then
	echo "?? no filenames given"
	$0 -h
	exit 1
fi
# vi:ts=4 sw=4
