#!/bin/sh
# $Id: tdindent,v 1.51 2026/04/17 23:47:43 tom Exp $
#****************************************************************************
#* Copyright (c) 2010-2025,2026 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'
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
}

# ncurses internals
/EMPTY_MODULE(/s/)$/);/
s,\(MODULEID(\),//\1,
/MODULE_ID(/s/)$/);/
/\<METHOD\>[[:space:]]*(/{
	s%,[[:space:]]*%, %g
	s,\<\(METHOD\)(\([^)]*\)),\1/*\$\2\$*/,
}
s,\<\(NCURSES_SP_NAME\)(\([^)]*\)),\1$\2$,

# ncurses headers
s,\(\<FORM_EXPORT_VAR\>.*;\),//\1,
s,\(\<MENU_EXPORT_VAR\>.*;\),//\1,
s,\(\<NCURSES_EXPORT_VAR\>.*;\),//\1,
s,\(\<PANEL_EXPORT_VAR\>.*;\),//\1,

# from tin-indent
s,\(\<MARK_END_OF_PROLOG\>\),\1;,
s,\(\<YY_RULE_SETUP\>\),\1;,
s,\(\<YY_BREAK\>\),\1;,
EOF

cat >"$MY_TMP"/postpro <<'EOF'
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

# ncurses internals
/EMPTY_MODULE(/s/);$/)/
s,//\(MODULEID(\),\1,
/MODULE_ID(/s/);$/)/
/\<METHOD\>/{
	s,[[:space:]]*/\*[[:space:]]*\$,(,
	s,\$[[:space:]]*\*/[[:space:]]*,),
}
s,\(\<NCURSES_SP_NAME\)\$\([^\$]*\)\$,\1(\2),

# ncurses headers
s,//\(\<FORM_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<MENU_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<NCURSES_EXPORT_VAR\>[ ]*\),\1,
s,//\(\<PANEL_EXPORT_VAR\>[ ]*\),\1,

# from tin-indent
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 (such as -v) 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[123]        debug with levels 1-3.
		  -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[123])
		OPTS="$OPTS $name"
		;;
	-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" || exit

		# 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" || exit
		else
			cd "$MY_PWD" || exit
			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
