#!/usr/bin/bash
#   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007  Rocky Bernstein 
#   rockyb@users.sourceforge.net
#
#   Bash 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; either version 2, or (at your option) any later
#   version.
#
#   Bash 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 Bash; see the file COPYING.  If not, write to the Free Software
#   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
#

# The alternate way to invoke debugger, "bash --debugger", has some
# advantages: it sets $0 correctly and doesn't show this script in
# the call trace. However the bash has been a bit inflexible and
# quirky so sadly this script seems to be needed more than it would
# normally.

typeset _Dbg_ver=\
'$Id: bashdb.in,v 1.20 2007/10/14 03:53:24 rockyb Exp $'

_Dbg_usage_long() {
  printf "_Dbg_usage:
    ${_Dbg_pname} [OPTIONS] <script_file>

Runs script_file under a debugger.

options: 
    -B | --basename  basename only on source listings. 
                     (Needed in regression tests)
    -h | --help      print this help
    -n | --nx |--no-init   
                     Don't run initialization files
    -c cmd | --command cmd
                     Run this passed command as a script
    -q | --quiet     Quiet. Do not print introductory and quiet messages.
    -L libdir | --library libdir
                     set directory location of library helper file: $_Dbg_main
                     The default directory is: $_Dbg_libdir
    -T tmpdir | --tempdir
                     set directory location for temporary files: $_Dbg_tmpdir
    -t tty | --tty tty | --terminal tty
                     set debugger terminal
    -x cmdfile | --cmdfile cmdfiles
                     execute debugger commands from cmdfile
    -X | --trace
                     set line tracing
    -V | --version   show version number and no-warranty and exit.

Long options may be abbreviated, e.g. --lib is okay for --library.
" 1>&2
}

_Dbg_usage_short() {
  printf "_Dbg_usage:
    ${_Dbg_pname} [OPTIONS] <script_file>

Runs script_file under a debugger.

options: 
    -B           basename only on source listings. (Needed in regression tests)
    -h           print this help
    -n           Don't run initialization files
    -c command   Run this passed command as a script
    -q           Quiet. Do not print introductory and quiet messages.
    -L libdir    set directory location of library helper file: $_Dbg_main
                 the default directory is: $_Dbg_libdir
    -T tmpdir    set directory location for temporary files: $_Dbg_tmpdir
    -t tty       set debugger terminal
    -x cmdfile   execute debugger commands from cmdfile
    -X           set line tracing
    -Y           set line tracing with variable expansion
    -V           show version number and no-warranty and exit.
" 1>&2
}

# This routine gets called via the -c or --command option and its sole
# purpose is to capture the command string such as via "x $*" or 
# in a traceback ("where").
bashdb_eval() {
  eval $*  # Type: "x $*" to see what's being run.
}

declare -a _Dbg_script_args="$@"

# Equivalent to basename $0; the short program name
typeset _Dbg_pname=${0##*/}  

# Show basename only in location listing. This is needed in regression tests
typeset -i _Dbg_basename_only=${BASHDB_BASENAME_ONLY:-0}

typeset    _Dbg_main=dbg-main.inc
prefix=/usr  # cygwin gets PKGDATADIR wrong
typeset    _Dbg_libdir=/usr/share/bashdb
typeset    _Dbg_bindir=$(dirname $0)
typeset    _Dbg_tmpdir=/tmp
typeset -i _Dbg_opt_linetrace=0
typeset    _Dbg_cmd='' # If command string given on command line, this is it.

# What to set for location of helper routines? 
if [[ ! -e $_Dbg_libdir/$_Dbg_main ]] ; then
  # Use bindir/../share as fallback
    _Dbg_libdir=
    if [[ -d $_Dbg_bindir/../share/bashdb ]] ; then
      _Dbg_libdir=$_Dbg_bindir/../share/bashdb
    fi
fi

# Process using short or long options, depending on the availability
# of getopt
TEMP=`getopt -o testing t 2>/dev/null`
if [ 1 = 1 ] && [ 0 = $? ] ; then
  # Process using long options
  # Note that we use `"$@"' to let each command-line parameter expand to a 
  # separate word. The quotes around `$@' are essential!
  # We need TEMP as the `eval set --' would nuke the return value of getopt.
  TEMP=`getopt -o Bc:hL:nqt:T::x:XYV \
--long basename,command:,debugger,help,library:,no-init,quiet,tempdir:,terminal:,trace,tty,version \
     -n 'bashdb' -- "$@"`

  if [ $? != 0 ] ; then 
    echo "Use --help for option help. Terminating..." >&2 ; 
    exit 1 ; 
  fi
  
  # Note the quotes around `$TEMP': they are essential!
  eval set -- "$TEMP"
  
  while true ; do
    case $1 in
      -B|--basename) _Dbg_basename_only=1 ;;
      -c|--command) _Dbg_cmd="$2"; shift ;;
      --debugger) ;;  # This option is for compatibility with bash --debugger
      -h|--help) _Dbg_usage_long; exit 100 ;;
      -L|--library) _Dbg_libdir=$2; shift ;;
      -n|--nx|--no-init) _Dbg_no_init=1 ;;
      -q|--quiet) _Dbg_quiet=1 ;;
      -T|--tempdir) _Dbg_tmpdir=$2; shift ;;
      -t|--terminal|--tty) 
	if ! $(touch $2 >/dev/null 2>/dev/null); then 
	  echo "${_Dbg_pname}: Can't access $2 for writing."
	elif [[ ! -w $2 ]] ; then
	  echo "${_Dbg_pname}: terminal $2 needs to be writable."
	else
	  _Dbg_tty=$2 ;
	fi
	shift
	;;
      -x) BASHDB_INPUT="$BASHDB_INPUT $2"; shift ;;  
      -X|--trace) _Dbg_opt_linetrace=1 ;;  
      # -Y|--vtrace) _Dbg_opt_linetrace=1 ; _Dbg_opt_linetrace_expand=1 ;;  
      -V|--version) show_version=1 ;;
      --) shift ; break ;;
      *) 
	echo "Use --help for option help. Terminating..."
	exit 2 ;;
    esac
    shift
  done
else 
  # Process using short options
  while getopts :Bc:hL:nqt:T:x:XYV opt; do
    case $opt in
      B) _Dbg_basename_only=1 ;;
      c) _Dbg_cmd="$OPTARG" ;;
      h) _Dbg_usage_short; exit 100 ;;
      n) _Dbg_no_init=1 ;;
      q) _Dbg_quiet=1 ;;
      L) _Dbg_libdir=$OPTARG ;;
      T) _Dbg_tmpdir=$OPTARG ;;
      t) 
	if ! $(touch $OPTARG >/dev/null 2>/dev/null); then 
	  echo "${_Dbg_pname}: Can't access $OPTARG for writing."
	elif [[ ! -w $OPTARG ]] ; then
	  echo "${_Dbg_pname}: terminal $OPTARG needs to be writable."
	else
	  _Dbg_tty=$OPTARG
	fi
	;;
      V) show_version=1 ;;
      x) BASHDB_INPUT="$BASHDB_INPUT $OPTARG" ;;  
      X) _Dbg_opt_linetrace=1 ;;  
      # Y) _Dbg_opt_linetrace=1 ; _Dbg_opt_linetrace_expand=1 ;;  
      *) 
	if ((_Dbg_basename_only == 1)) ; then
	  echo "${_Dbg_pname}: unrecognized option -- $OPTARG"
	else
	  echo "$0: unrecognized option -- $OPTARG"
	fi
	echo "Use --help for option help. Terminating..."
	exit 2 
	;;
    esac
  done
  shift $(($OPTIND - 1))
fi

[[ $# == 0 && -z $show_version && -z $_Dbg_cmd ]] && {
  echo "${_Dbg_pname}: Need to give a script name to debug."
  exit 1
}

if [[ ! -d $_Dbg_libdir ]] && [[ ! -d $_Dbg_libdir ]] ; then 
  echo "${_Dbg_pname}: Can't read debugger library directory '${_Dbg_libdir}'."
  echo "${_Dbg_pname}: Perhaps bashdb is installed wrong (if its installed)." >&2
  echo "${_Dbg_pname}: Try running bashdb using -L (with a different directory)." >&2
  echo "${_Dbg_pname}: Run bashdb --help for a list and explanation of options." >&2
  exit 1
fi

_source_file=$1
shift

if [[ ! -d $_Dbg_tmpdir ]] && [[ ! -w $_Dbg_tmpdir ]] ; then
  echo "${_Dbg_pname}: cannot write to temp directory $_Dbg_tmpdir." >&2
  echo "${_Dbg_pname}: Use -T try directory location." >&2
  exit 1
fi

[[ -r $_Dbg_libdir/$_Dbg_main ]] || {
  echo "${_Dbg_pname}: cannot read debugger file $_Dbg_libdir/$_Dbg_main." >&2
  echo "${_Dbg_pname}: Perhaps bashdb is installed incorrectly." >&2
  exit 1
}

# Note that this is called via bashdb rather than "bash --debugger"
_Dbg_script=1

. ${_Dbg_libdir}/dbg-pre.inc

if [[ -z $_Dbg_quiet ]] ; then 
  echo "Bourne-Again Shell Debugger, release $_Dbg_release"
  cat <<EOF
Copyright 2002, 2003, 2004, 2006, 2007 Rocky Bernstein
This is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.

EOF
fi

if (( show_version == 1 )) ; then 
cat <<EOF
There is absolutely no warranty for BASHDB.  Type "show warranty" for details.
EOF
  exit 1
fi

if [[ ! -r "$_source_file" ]] && [[ -z $_Dbg_cmd ]] ; then
  echo "${_Dbg_pname}: cannot read program to debug: $_source_file." >&2
  exit 1
else
  typeset -r _Dbg_source_file=$(_Dbg_expand_filename $_source_file)
fi

. $_Dbg_libdir/dbg-main.inc
if (( $_Dbg_opt_linetrace )) ; then 
  # No stepping.
  _Dbg_write_journal_eval "_Dbg_steps=-1" 
  BASHDB_QUIT_ON_QUIT=1
else 
  # Set to skip over the next 4 statements
  _Dbg_write_journal_eval "_Dbg_steps=5" 
fi
set -o functrace
if [[ -z $_Dbg_cmd ]] ; then 
  if (( $_Dbg_opt_linetrace )) ; then 
    (( _Dbg_opt_linetrace_expand )) && _Dbg_linetrace_expand=1
    _Dbg_linetrace=1
  fi
  . $_source_file
else 
  bashdb_eval "$_Dbg_cmd"
fi


# end of bashdb

#;;; Local Variables: ***
#;;; mode:shell-script ***
#;;; eval: (sh-set-shell "bash") ***
#;;; End: ***

