#!/bin/bash
#
# RTAI immed/piped interrupt dispatching mode control.
#
# Copyright (c) 2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
#
# Usage:
#	mode-control
#	mode-control check
#		Check current overall dispatching mode.
#
#	mode-control immed|piped
#		Set new overall dispatching mode to specified value (i.e. copy
#		foo.immed to foo.c etc.). Will fail if there is at least one
#		file that is diffent to both is .piped AND .immed variant (i.e.
#		file dispatching mode is DIRTY, if at least one file is DIRTY,
#		the overall dispatching mode is DIRTY too).
#
#	mode-control -f|--force immed|piped
#		Set new overall dispatching mode to specified value, even if
#		overall dispatching mode is DIRTY. Warning! You might loose
#		source code changes if you do this!
#		
# File modes:
#	IMMED	source file foo.x is the same as foo.immed
#	PIPED	source file foo.x is the same as foo.piped
#	DIRTY	source file foo.x is neither the same as foo.piped
#		nor the same as foo.immed
#	
# Overall modes:
#	IMMED	all source files are the same as their .immed variant
#	PIPED	all source files are the same as their .piped variant
#	MIXED	some source files are the same as their .piped variant,
#		some equal their .immed variant but none are DIRTY
#	DIRTY	at least one source file is DIRTY
#
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, USA; either
# version 2 of the License, or (at your option) any later version.
#
# 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, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#

# source code files that are affected by dispatching mode (currently, only .c &
# .h files will work with the code below)
files='../arch/arm/hal/hal.c
    ../arch/i386/hal/hal.c 
    ../include/asm-arm/rtai_hal.h
    ../include/asm-i386/rtai_hal.h 
    ../sched/sched.c'

function get_current_mode() {
    echo "Current dispatching mode of files:"
    overall_mode=''
    for i in $files; do
	piped=${i/%.[ch]/.piped}
	immed=${i/%.[ch]/.immed}
	if cmp -s $i $piped; then
	    # active == piped
	    echo -e "  PIPED\t$i"
	    file_mode='PIPED'
	elif cmp -s $i $immed; then
	    # active == immed
	    echo -e "  IMMED\t$i"
	    file_mode='IMMED'
	else
	    # active != immed && active != piped
	    echo -e "  DIRTY\t$i"
	    file_mode='DIRTY'
	fi
	if [ -z "$overall_mode" ]; then
	    # overall mode was never set
	    overall_mode=$file_mode 
	else
	    # overall mode was set at least once
	    case $overall_mode in
	    IMMED|PIPED)
		# until now all other files had the same mode
		if [ "$file_mode" == 'DIRTY' ]; then
		    overall_mode='DIRTY'
		else
		    # file mode is PIPED|IMMED and different than overall mode
		    # -> either overall mode is not changed or becomes MIXED
		    [ "$overall_mode" != "$file_mode" ] && overall_mode='MIXED'
		fi
		;;
	    MIXED)
		# from MIXED we go only to DIRTY (if file is DIRTY)
		[ "$file_mode" == 'DIRTY' ] && overall_mode='DIRTY'
		;;
	    DIRTY)
		# once overall mode is dirty it stays there
		;;
	    esac
	fi
    done
    echo "=> Current overall dispatching mode: $overall_mode"
    case $overall_mode in
    IMMED|PIPED|MIXED)
	return 0;;		# allow mode to be changed
    *)
	if [ "$force" ]; then
	    echo ''
	    echo "** Overall dispatching mode is $overall_mode,"
	    echo "** but user has requested forced mode change!"
	    return 0		# force mode change
	else
	    return 1		# prevent mode change (changes might be lost)
	fi
	;;
    esac
}

function set_mode() {
    mode="$1"
    echo ''
    echo "Setting overall dispatching mode to: $(echo $mode | tr a-z A-Z)"
    for i in $files; do
	src=${i/%.[ch]/.$mode}
	printf "  %-36s -> %s\n" $src $i
	cp $src $i
    done
}

# check for force option
if [ "x$1" == 'x-f' -o "x$1" == 'x--force' ]; then
    force=1
    shift
else
    force=''
fi

case "$1" in
""|check)
    get_current_mode
    exit $?
    ;;
piped|immed)
    if get_current_mode; then
	set_mode "$1"
    else
	echo ''
	echo 'At least one file is dirty, i.e. not the same as either its .piped or'
	echo '.immed variant! (See output above for details.) The dispatching mode will'
	echo 'not be set as this might result in lost code changes. Please fix this'
	echo 'manually or force a mode set by specifying the -f|--force option.'
    fi
    ;;
*)
    echo ''
    echo "Unknown command '$1'" >&2
    exit 1
    ;;
esac
