# -*-shell-script-*-

###
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright 2002 Mike Hearn (mike@theoretic.com)
#
###



###
# Failsafing routines. You can use this code in the following way:
# 
# failsafe "create and populate file" &lt;&lt;EOF
#     do a task;
#     run another command;
#     cleanup;
# EOF
#
# If any of the commands in the failsafe block return an exit code != 0,
# the block will terminate, and the failsafe handler will be called.
# if $failsafe_fail_handler is null, the program will show an error then
# terminate. By setting this variable, you can override that behaviour.
# Your own handler can call failsafe_fail() to perform the usual behaviour,
# and can pass the --no-exit switch to print the error but continue.
#
# If you want to insulate a command from the failsafing, write
# { command; true }
# to ensure it always returns an exit code of 0

function set_failsafe_line() {
  __failsafe_line="$1"
  __failsafe_str="$2"
  __failed=1
  return 1;
}

function failsafe_ok() {
    return $__failed
}

function failsafe_fail() {
    (
        echo
	red; out "$intl_FAIL $intl_FAILSAFE" "$sectionName";
	cyan; echo "${__failsafe_line}: $__failsafe_str";
	normal;
    ) >/dev/stderr
   
    if [[ $1 != "--no-exit" ]]; then
	exit 1
    fi
}

function failsafe() {
    sectionName="$1"
    # slurp stdin
    while read; do
	if [[ "$stdin" == "" ]]; then stdin="$REPLY"; else
	    stdin="$stdin
$REPLY";
	fi
    done
    
    # escape the commands for set_failsafe_str
    #a="$stdin"
    #a=$( echo "$a" | sed 's/"/\\\\"/g; s/;$//' | sed "s/'/\\\\\'/g" )
    ## process each line to failsafe it
    #b=$( echo "$stdin" | sed 's/;$//' | awk '{ print "{ " $0 " || set_failsafe_line" }'  )

    block=$( (( i = 0 )); echo "$stdin" | while read line; do
	(( i++ ))

	if [[ "$line" != "" ]]; then
	    # escape it
	    escaped=$( echo "$line" | sed 's/"/\\"/g; s/;$//; s/(/\\(/g; s/)/\\)/g' | sed "s/'/\\'/g" ) 
	    # ensure we're not a block begin/end keyword
	    if [[ `echo "$line" | sed -n '/^if/p; /then$/p; /else$/p; /fi$/p; /^while/p; /do$/p; /done$/p'` == "" ]]; then
		# wrap it
		wrapped=$( echo "$line" | sed 's/;$//' | awk '{ print "{ " $0 " || set_failsafe_line" }'  )
		echo "failsafe_ok && $wrapped $i \"${escaped}\"; }"
	    else
		# otherwise don't trap for this line
		echo "$line"
	    fi
	fi

    done; )

    echo
    echo "$block"
    echo
    
    if ! eval "$block"; then
	if [[ "$failsafe_fail_handler" == "" ]]; then
	    failsafe_fail
	else
	    eval "$failsafe_fail_handler"
	fi
    fi
    # else we succeeded
}
