#!/bin/sh
#
# NetHack configuration utility. Version 1.0.1
#
# Author: J. Ali Harlow, ali@avrc.city.ac.uk
#
# Copyright (c) 1999-2000, J. Ali Harlow.
#	Free for use with NetHack or any derivatives covered by its license.
#
# Note:	This is an early release of my configuration utility for NetHack
#	for use with RPMs only. It is far too unstable for general use
#	yet, although you are welcome to try. Please don't distribute
#	it outside of the source RPM however. A more stable version will
#	be released in due course. It only understands v3.2 style
#	disabled defns; the 3.3 style, which avoids nested comments and
#	is therefore ANSI compatible, is not supported.
#
# Usage: config <template> <toplevel>
#		[-D|-U]<SWITCH> ... <toplevel>
#

WS="[ 	]"
# find_line		Find the line to act on
# Usage:	find_line <context> <regexp> <filename>
find_line()
{
    awk "\
      BEGIN {found=best=dist=0} \
      /$1/ {found=NR;} \
      /$2/ {if (found){if (!best || dist>(NR-found)){best=NR;dist=NR-found}}} \
      END {if (best)print best}" $3
}
initialise()
{
    echo "" > /tmp/$1.$$
}
# Comment out (if existing line has a comment) or undef any existing defns.
# If context supplied (with undefine -C <context> <symbol>) then only
# the first defn. after the first occurance of <context> in the file will
# be commented out. Note: The line which contains <context> is the first
# line searched.
undefine()
{
    context=""
    if [ "$1" = "-C" ]; then
    	context="$2"
	shift;shift
    fi
    case $label in
    *_c|*_h)
	if [ -z "$context" ]; then
	    echo config: Disabling all definitions for $1
	    echo "s:^#${WS}*define $1${WS}.*/\*:/* &:" >> /tmp/$label.$$
	    echo "s:^#${WS}*define $1${WS}.*$:#undef $1:" >> /tmp/$label.$$
	else
	    line=`find_line "$context" "^(\/\*)?${WS}*#${WS}*define $1${WS}*" \
	      $filename`
	    if [ -n "$line" ]; then
		echo config: Disabling definition for $1 on line $line
		echo "$line s:^#${WS}*define $1${WS}.*/\*:/* &:" >> /tmp/$label.$$
		echo "$line s:^#${WS}*define $1${WS}.*$:#undef $1:" >> /tmp/$label.$$
	    else
		echo Warning: no existing definition to disable in $label
	    fi
	fi
	;;
    *akefile|*akefile.*)
	if [ -z "$context" ]; then
	    echo config: Disabling all definitions for $1
	    echo "s:^${WS}*$1${WS}*=:# &:" >> /tmp/$label.$$
	else
	    line=`find_line "$context" "^${WS}*#?${WS}*$1${WS}*=" \
	      $filename`
	    if [ -n "$line" ]; then
		echo config: Disabling definition for $1 on line $line
		echo "$line s:^${WS}*$1${WS}*=:# &:" >> /tmp/$label.$$
	    else
		echo Warning: no existing definition to disable in $label
	    fi
	fi
	;;
    esac
}
# Enable any existing defns. of $1 for $2 (otherwise no action)
# If no second argument:
#    If context supplied (with define -C <context> <symbol>) then
#    the closest defn. after an occurance of <context> in the file will
#    be enabled (first defn. in a tie-break situation). Note: The line
#    which contains <context> is the first line searched.
#    If no context supplied then the first defn. in the file will be enabled.
define()
{
    context=""
    if [ "$1" = "-C" ]; then
    	context="$2"
	shift;shift
    fi
    case $label in
    *_c|*_h)
	if [ $# -eq 2 ]; then
	    echo config: Enabling all definitions of $1 for $2
	    echo "s:^/\*${WS}*\(#${WS}*define $1${WS}*$2\):\1:" >> /tmp/$label.$$
	    echo "s:^#undef $1${WS}*$:#define $1 $2:" >> /tmp/$label.$$
	else
	    if [ -z "$context" ]; then
		line=`egrep -n "^(/\*)?${WS}*#${WS}*define $1${WS}*" $filename | awk -F: 'NR==1 { print $1; }'`
	    else
		line=`find_line "$context" "^(\/\*)?${WS}*#${WS}*define $1${WS}*" \
		  $filename`
	    fi
	    if [ -n "$line" ]; then
		echo config: Enabling definition for $1 on line $line
		echo "$line s:^/\*${WS}*\(#${WS}*define $1${WS}*\):\1:" >> /tmp/$label.$$
	    else
		echo Warning: no existing definition to enable in $label
		echo + egrep -n "^(/\*)?${WS}*#${WS}*define $1${WS}*" $filename
		egrep -n "^(/\*)?${WS}*#${WS}*define $1${WS}*" $filename
		if [ -n "$context" ]; then
		    echo + awk "/$context/ {print NR \":\" \$0}" $filename
		    awk "/$context/ {print NR \":\" \$0}" $filename
		fi
	    fi
	fi
	;;
    *akefile|*akefile.*)
	if [ $# -eq 2 ]; then
	    echo config: Enabling all definitions of $1 for $2
	    echo "s:^${WS}*#${WS}*\($1${WS}*=${WS}*$2\)$:\1:" >> /tmp/$label.$$
	else
	    if [ -z "$context" ]; then
		line=`egrep -n "^${WS}*#?${WS}*$1${WS}*=" $filename | awk -F: 'NR==1 { print $1; }'`
	    else
		line=`find_line "$context" "^${WS}*#?${WS}*$1${WS}*=" $filename`
	    fi
	    if [ -n "$line" ]; then
		echo config: Enabling definition for $1 on line $line
		echo "$line s:^${WS}*#${WS}*\($1${WS}*=\):\1:" >> /tmp/$label.$$
	    else
		echo Warning: no existing definition to enable in $label
		echo + egrep -n \""^${WS}*#?${WS}*$1${WS}*="\" $filename
		egrep -n "^${WS}*#?${WS}*$1${WS}*=" $filename
	    fi
	fi
	;;
    esac
}
# Change any _enabled_ existing defns. for $1 to $2
redefine()
{
    case $label in
    *_c|*_h)
	echo "s:^\(#${WS}*define $1${WS}${WS}*\).*/\*:\1$2 /*:" >> /tmp/$label.$$
	echo t >> /tmp/$label.$$
	echo "s:^\(#${WS}*define $1${WS}${WS}*\).*$:\1$2:" >> /tmp/$label.$$
	;;
    *akefile|*akefile.*)
	echo "s:^${WS}*\($1${WS}*=${WS}*\).*$:\1$2:" >> /tmp/$label.$$
	;;
    esac
}
# Remove any disabled defns. for $1
sanitize()
{
    case $label in
    *_c|*_h)
	echo "/^\/\*${WS}*#${WS}*define${WS}*$1${WS}*/ d" >> /tmp/$label.$$
	echo "/^${WS}*#${WS}*undef${WS}*$1${WS}*/ d" >> /tmp/$label.$$
	;;
    *akefile|*akefile.*)
	echo "/^${WS}*#${WS}*$1${WS}*=${WS}*/ d" >> /tmp/$label.$$
	;;
    esac
}
BEGIN()
{
    :
}
END()
{
    sed -f /tmp/$label.$$ < $filename > /tmp/$label.new.$$
    cmp -s /tmp/$label.new.$$ $filename || cat /tmp/$label.new.$$ > $filename
    #rm -f /tmp/$label.$$ /tmp/$label.new.$$
}
configure()
{
    label=$1
    filename=$2
    initialise $label
}
usage()
{
	echo "Usage: config <template> <toplevel>" >&2
	echo "              [-D|-U]<SWITCH> ... <toplevel>" >&2
	exit 1
}
if [ $# -lt 2 ]; then usage; fi
toplevel=`echo "$*" | sed 's/.* //'`
switch_mode=0
finished=0
while [ $# -gt 1 -a $finished -eq 0 ]; do
	case $1 in
	-D*)
		if [ $switch_mode -eq 0 ]; then
			switch_mode=1
			configure config_h $toplevel/include/config.h
			BEGIN
		fi
		switch=`echo $1 | sed 's/-D//'`
		define $switch
		shift
		;;
	-U*)
		if [ $switch_mode -eq 0 ]; then
			switch_mode=1
			configure config_h $toplevel/include/config.h
			BEGIN
		fi
		switch=`echo $1 | sed 's/-U//'`
		undefine $switch
		shift
		;;
	*)	finished=1
		;;
	esac
done
if [ $switch_mode -eq 0 ]; then
	if [ $# -ne 2 ]; then usage; fi
	template=$1
	if [ -r ${template}.configure ]; then
		. ${template}.configure
	else
		echo "Unknown template $template" >&2
		exit 1
	fi
else
	if [ $# -ne 1 ]; then usage; fi
	END
fi
exit 0
