#!/bin/sh
# $Id: ncu-symbols,v 1.47 2015/07/11 13:11:31 tom Exp $
# -----------------------------------------------------------------------------
# Copyright 2014,2015 by Thomas E. Dickey
#
#                         All Rights Reserved
#
# 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, 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 LISTED COPYRIGHT HOLDER(S) 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.
# -----------------------------------------------------------------------------
# extract symbols from a given patch-date for ncurses

failed() {
	echo "$*" 1>&2
	exit 1
}

get_symbols() {
	clean-ncurses
	RCS-toggle >/dev/null
	if test $DATE -le 20061217
	then
		case "$*" in
		*enable-widec*)
			export LIBS=-lncursesw
			;;
		*)
			export LIBS=-lncurses
			;;
		esac
	fi
	CFG_OPTS="\
		--with-termlib \
		--with-trace \
		--disable-leaks \
		--disable-root-environ \
		--without-ada \
		--enable-rpath"
	test $DATE -lt 20130309 && CFG_OPTS="$CFG_OPTS --without-cxx-binding"

	MAP_OPTS="-v"
	FIX_WEAK=
	if test $DATE -ge 20100529
	then
		case "$*" in
		*enable-weak-symbols*enable-widec* |\
		*enable-widec*enable-weak-symbols*)
			FIX_WEAK=tw
			;;
		*enable-weak-symbols*)
			FIX_WEAK=t
			;;
		esac
		if test -n "$FIX_WEAK"
		then
			echo "** fixup weak-symbols($FIX_WEAK)"
			MAP_OPTS="$MAP_OPTS -t"
		fi
	fi

	echo "** BUILD $* $CFG_OPTS" | sed -e 's/[[:space:]][[:space:]]*/ /g'
	if cfg-shared $* $CFG_OPTS
	then
		make sources
		case "$*" in
		*enable-widec*)
			;;
		*)
			if test $DATE -lt 20100328
			then
				MYFILE=include/curses.h
				echo "** workaround for ifdef in $MYFILE"
				sed -i.bak -e 's,\(_XOPEN_SOURCE_EXTENDED\),OOPS\1,' $MYFILE
				diff -u $MYFILE.bak $MYFILE
				rm -f $MYFILE.bak
			fi
			;;
		esac

		if test $DATE -le 20110000 && test $DATE -ge 20081102
		then
			MYFILE=ncurses/curses.priv.h
			echo "** workaround for ifdef in $MYFILE"
			sed -i.bak -e "/FIXME-THREADS/d" $MYFILE
			sed -i -e '/_nc_use_pthreads/a\
#else /* FIXME-THREADS */\
	int		nested_tracef; /* FIXME-THREADS */\
	int		use_pthreads /* FIXME-THREADS */;
' $MYFILE
			diff -u $MYFILE.bak $MYFILE
			rm -f $MYFILE.bak
		fi

		shlib make
		RC=$?
		echo "DONE $RC"
		if test $RC != 0
		then
			RCS-toggle >/dev/null
			exit 1
		fi

		echo "MAPSYMS $MAP_OPTS"
		ncu-mapsyms $MAP_OPTS # -m

		for CMP in package/$DATE-*.map package/$DATE-*.sym
		do
			case $CMP in
			package/$DATE-[0-9]*)
				continue
				;;
			esac

			REF=$CMP-ref

			if test ! -f $REF
			then
				cp -vp $CMP $REF
			elif cmp -s $CMP $REF
			then
				echo "** map-file unchanged: $CMP"
			else
				echo "** map-file changed: $CMP"
				case $CMP in 
				*.map)
					TST=`compare-mapsyms -s $REF $CMP`
					case "$TST" in
					*\(*)
						echo $TST
						;;
					*)
						echo "?? map-file comments: $CMP"
						diff -u $REF $CMP
						;;
					esac
					;;
				*.sym)
					diff -u $REF $CMP |diffstat
					;;
				esac
				cp -vp $CMP $REF
			fi
		done 
	fi
	unset LIBS
	RCS-toggle >/dev/null
}

# some of the _nc_XXX symbols drop/add when doing sp-funcs, so we build and
# merge the lists of symbols.
get_normal() {
	get_symbols $* --with-ticlib --with-broken_linker
	get_symbols $* --enable-termcap --enable-getcap --enable-getcap-cache
	test $DATE -ge 20060805 && get_symbols $* --with-ticlib --with-hashed-db --enable-wgetch-events
	if test $DATE -ge 20090214
	then
		get_symbols --enable-sp-funcs $*
		get_symbols --enable-sp-funcs --with-broken_linker --with-hashed-db $*
		get_symbols --enable-reentrant --enable-sp-funcs $*
		test $DATE -ge 20091107 && get_symbols $* --enable-interop
	elif test $DATE -ge 20070310
	then
		get_symbols --enable-reentrant $*
	fi
}

get_thread() {
	if test $DATE -ge 20100529
	then
		get_normal --with-pthread --enable-weak-symbols $*
	else
		get_normal --with-pthread $*
	fi
}

zap_tree() {
	clean-ncurses

	if test -f MANIFEST
	then
		fgrep -v terminfo.src MANIFEST | \
		fgrep -v .map | \
		fgrep -v .sym | \
		fgrep -v config. | \
		xargs rm -f {} \;
	fi
	rcsget -d -q -r$1 || exit
	test -f MANIFEST  || exit
	test -f configure || autoconf-213
}

get_date() {
	test -f dist.mk || failed "cannot find dist.mk"
	DATE=`fgrep NCURSES_PATCH dist.mk | sed -e 's/^.*=[[:space:]]*//'`
	test -n "$DATE" || failed "no NCURSE_PATH date found"
}

build_tree() {
	clean-ncurses

	get_date
	rm -f package/$DATE-*.map* package/$DATE-*.sym*

	if test -f MANIFEST
	then
		get_normal
		get_normal --enable-widec
		if expr $DATE \>= 20080329
		then
			get_thread
			get_thread --enable-widec
		fi
	fi
}

save_symbols() {
	echo "** save_symbols for $DATE"
	for SAVE in package/$DATE-*.map
	do
		sed -i s/$PATCHED/current/ $SAVE
	done

	for SAVE in package/$DATE-*.map package/$DATE-*.sym
	do
		test -f "$SAVE" || continue
		cp -vp $SAVE package/SAVE/
		mv -vf $SAVE package/`basename $SAVE|sed -e s/^$DATE-//`
	done
}

usage() {
	cat >&2 <<EOF
Usage: $0 [-a] [label]

Options:
  -a	process all releases to rebuild .map/.sym files
EOF
	exit 1
}

OPT_A=no

set -- `getopt 'ah' $*`
if [ $? != 0 ]
then
	eval $0 -h
	exit 1
fi

while [ $# != 0 ]
do
	opt=$1
	shift
	case $opt in
	-a)
		OPT_A=yes;;
	-h)
		usage;;
	--)
		break;;
	esac
done


if test $# = 1
then
	rm -vf package/[1-9]*-*.sym package/[1-9]*-*.map
	zap_tree $1
	build_tree
elif test $# != 0
then
	usage
elif test $OPT_A = yes
then
	rm -f package/*.sym package/*.map
	rm -rf package/SAVE
	mkdir -p package/SAVE

	CURRENT=`rlog dist.mk | \
		sed \
			-e '1,/^symbolic names:$/d' \
			-e '/^keyword substitution/,999999d' \
			-e 's/^	//' \
			-e 's/:.*//' \
			-e '/^[^v]/d' | \
		sort -r 2>/dev/null | \
		head -n 1`
	PATCHED=`echo "$CURRENT" | sed -e 's/^.*_//'`
	echo "** Current $CURRENT"
	echo "** Patched $PATCHED"

	# A specific date is used in 5.3 for a case which gives a build-failure
	# for the combination of options used in this script.
	#
	# The dated tag for 5.9 is the last version before changing the default
	# ABI for the 6.0 release.
	for TAG in \
		v5_0 \
		v5_1 \
		v5_2 \
		v5_3_20021019 \
		v5_4 \
		v5_5 \
		v5_6 \
		v5_7 \
		v5_8 \
		v5_9 \
		v5_9_20150530 \
		$CURRENT
	do
		zap_tree $TAG
		build_tree
		save_symbols
	done
	ncu-mapsyms -sv
	save_symbols
	ncu-mapsyms -pv
	save_symbols
else
	build_tree
fi
