#!/bin/sh
########################################################################################
#                                                                                      #
#                                   install-MacsBug                                    #
#                                                                                      #
#        Installer Script to Install MacsBug in a place other than it's default        #
#                                                                                      #
#                           NOT FOR RELEASE OUTSIDE OF APPLE                           #
#                                                                                      #
#                                     Ira L. Ruben                                     #
#                      Copyright Apple Computer, Inc. 2000-2001                        #
#                                                                                      #
########################################################################################

# install-Macsbug [where] [--gdbinit=pathname] [--v[erbose]] [--f[orce]] [--help]

# The MacsBug support directory is normally installed in /usr/libexec/gdb/plugins/.
# This is installed when the system is installed to ensure it's tied to the proper
# version of gdb which is tightly coupled with the MacaBug plugin code.

# There are two key files in the MacsBug folder:

#   gdbinit-MacsBug
#   MacsBug

# The gdbinit-MacsBug file is a gdb script which, among other things, does a
# load-plugin gdb command to load the MacsBug plugin file.  The load-plugin requires
# a full pathname to the MacsBug plugin.  So it is preset to load from the MacsBug
# directory.  The user's .gdbinit script should then do a SOURCE command to load
# the gdbinit-MacsBug script, again from the default directory.

# The user's .gdbinit script can be explicitly edited by the user or this installer
# script can be used to do it.

# It is also possible that there may be intermediate releases of the MacsBug plugins
# which are compatible with the user's system.  Intermediate releases are not expected
# to be placed in /usr/libexec/gdb/plugins/MacsBug.  So this intaller script can also
# be used to install a newer MacsBug directory in a directory of the user's choosing.

# This installer script does 3 things:

#  1. Optionally edit the user's .gdbinit script (if --gdbinit is specified) to create
#     or modify a SOURCE command that loads the gdbinit-MacsBug from a copy of the
#     MacsBug directory or the system-installed MacsBug directory.

#  2. Optionally copies an entire MacsBug directory to a chosen directory ("where").
#     The source MacsBug directory is the directory containing this installer script.

#  3. Modifies the copied gdbinit-MacsBug load-plugin command to load the MacsBugplugin
#     from the copied folder.

# The parameters to this script have the following meaning:

#  where        	A pathname specifying a directory which is created containing
#			the contents of the MacsBug directory.  It doesn't have to be
#			called "MacsBug" and it need not be a "visible" directory, i.e.,
#			you could name it with a leading '.'.

#			Default is to not copy the MacsBug directory and set the --gdbinit
#			specified script to use the MacsBug script defined in the folder
#			containing this installer script.

#			Note, specify a full pathname since this is needed for the 
#			load-plugin command.

#  --gdbinit=pathname	Optionally specifies the location of the user's .gdbinit file.
#			For use in all gdb invocations this should be ~/.gdbinit.  If
#			this parameter is not specified the user's .gdbinit script will
#			not be modified.

#			Note, if the .gdbinit script is modified, the original version
#			of the script is renamed with "-bkup" added to the filename.

#  --force		This script checks that the "where" is not in the same place from
#			which this script is running.  If is is, that implies the
#			source and destination directories are the same.  In addition
#			a check is done to see if the "where" has already been
#			installed for MacsBug.  In either of these cases no further
#			action is taken the and script terminates.  Specifying
#			--force overrides these tests and "forces" the installation.

#  --verbose		Script confirms what it is doing.

#####################################################################################

declare -i status

usage="${0##*/}"' [where] [--gdbinit=pathname] [--v[erbose]] [--f[orce]] [--help]'

#debug='echo '
force=0
verbose=0

usage='usage: '"${0##*/}"' [where] [--gdbinit=pathname] [--v[erbose]] [--f[orce]]'
macsbug_script="gdbinit-MacsBug"

#
# Parse the parameters: [where] [--gdbinit=pathname] [--v[erbose]] [--f[orce]]
#
for arg; do
    case $next_arg in
    	-gdbinit | --gdbinit)
   	    gdbinit="$arg"
    	    next_arg=
    	    ;;
   	*)
    	    case $arg in
	     	-help | --help)
	     	    echo
		    echo "$usage"
		    echo
		    echo "where               Pathname specifying a directory which is created containing"
		    echo "                    the contents of the MacsBug directory.  It doesn't have to"
		    echo "                    be called \"MacsBug\" and it need not be a \"visible\""
		    echo "                    directory, i.e., you could name it with a leading '.'."
		    echo
		    echo "                    Default is to not copy the MacsBug directory and set the"
		    echo "                    --gdbinit specified script to use the MacsBug script"
		    echo "                    defined in the folder containing this installer script."
		    echo
		    echo "--gdbinit=pathname  Optionally specifies the location of the your .gdbinit"
		    echo "                    file.  For use in all gdb invocations this should be"
		    echo "                    ~/.gdbinit.  If this parameter is not specified your"
		    echo "                    .gdbinit script will not be modified."
		    echo
		    echo "                    Note, if the .gdbinit script is modified, the original"
		    echo "                    version of the script is renamed with \"-bkup\" added to"
		    echo "                    the filename."
		    echo
		    echo "--force             This script checks that the \"where\" is not in the same"
		    echo "                    place from which this script is running.  If it is,"
		    echo "                    that implies the source and destination directories are"
		    echo "                    the same.  In addition a check is done to see if the"
		    echo "                    \"where\" has already been installed for MacsBug.  In either"
		    echo "                    of these cases no further action is taken the and script"
		    echo "                    terminates.  Specifying --force overrides these tests and"
		    echo "                    \"forces\" the installation."
		    echo
		    echo "--verbose           Script confirms what it is doing."
		    echo
		    exit 0
		    ;;
	     	-f | --f)
	     	    force=1
		    ;;
	     	-force | --force)
	     	    force=1
		    ;;
	     	-v | --v)
	     	    verbose=1
		    ;;
	     	-verbose | --verbose)
	     	    verbose=1
		    ;;
	    	-gdbinit=* | --gdbinit=*)
	    	    gdbinit=`echo $arg | sed -e 's/-*gdbinit=//'`
		    ;;
	    	-*)
	    	    if [ "$next_arg" != "" ]; then
		    	echo Usage: "$usage"
		   	echo "Unknown option $arg"
		    	exit 1
	    	    fi
		    next_arg=$arg
		    ;;
	    	--*)
	    	    if [ "$next_arg" != "" ]; then
		    	echo Usage: "$usage"
		   	echo "Unknown option $arg"
		    	exit 1
	    	    fi
		    next_arg=$arg
		    ;;
	    	*)
	    	    where=$arg
	    	    ;;
   	    esac
    esac
done

if [ "$next_arg" != "" ]; then
    echo Usage: "$usage"
    echo "Unknown option $next_arg"
    exit 1
fi

#
# Set "where" default if not specified.  It's the same directory containing this script.
#

#if [ "$where" = "" ]; then
#    where="${0%/*}/"
#fi
where=${where:-"${0%/*}/"}

if [ "${where##/*}" != "" ]; then
    echo "Warning, destination folder ($where) not specified as a full pathname"
fi

if [ "$debug" != "" ]; then
    echo
    echo 'where   =' "$where"
    echo 'gdbinit =' "$gdbinit"
    echo 'force   =' "$force"
    echo 'verbose =' "$verbose"
    echo
fi

#
# If gdbinit was specified then edit the users .gdbinit script (or whatever was
# specified) to add a SOURCE command to load the MacsBug gdbinit-MacsBug script
# from the "where" directory.  If the the gdbinit script already has a SOURCE
# command to gdbinit-MacsBug then just edit that.  Either way the user's original
# gdbinit script is renamed with to its original name with the suffix "-bkup"
# added.  We try to do this as safely as we can.
#
# Note that this step is skipped if the user's .gdbinit script already has a
# source command to the desired gdbinit-MacsBug.
#

changed_gdbinit=0

if [ "$gdbinit" != "" ]; then
    if [ -e "$gdbinit" ]; then
    	if [ ! -f "$gdbinit" ]; then
	    echo "$gdbinit is not an regular file"
	    exit 1
	fi
	
    	if [ "`grep \"$where/$macsbug_script\" $gdbinit`" = "" ]; then
	    cat "$gdbinit" | \
	    sed -e 's,\(^[^#]*[ ]*source[ ]*\)\([.]\{0\,1\}\).*'"$macsbug_script"'\(.*\)$,\1'"$where/$macsbug_script"'\3,' >"$gdbinit"-new
	
	    #
	    # If the above line didn't edit an existing SOURCE command so we assume we need to
	    # create the command...
	    #
	    if ! `grep "^[^#]*$where/$macsbug_script" "$gdbinit"-new >/dev/null`; then
		echo 					>>"$gdbinit"-new
		echo '#' 				>>"$gdbinit"-new
		echo '# Add MacsBug commands...' 	>>"$gdbinit"-new
		echo '#' 				>>"$gdbinit"-new
		echo "source $where/$macsbug_script" 	>>"$gdbinit"-new
	    fi
	    
	    #
	    # Rename "old" gdbinit script as with a -bkup suffix.  We may have to undo this if
	    # we later discover something is wrong with the "where" directory when that is
	    # specified.  We're only doing this before that check because at a minimum this
	    # script can be used just to edit the user's gdbinit script to source the MacsBug
	    # script from it's system-installed (default) location.
	    #
	    
	    changed_gdbinit=1
	    mv "$gdbinit" "$gdbinit"-bkup
	    status=$?
	    if [ $status -eq 0 ]; then
		mv "$gdbinit"-new "$gdbinit"
		status=$?
	    fi
	    if [ $status -ne 0 ]; then
		# If the above failed it should have reported an error of its own
		echo "### MacsBug installation not completed ###"
		exit 1
	    fi
	    if [ $verbose ]; then
		echo "### $gdbinit updated to load $where/$macsbug_script"
	    fi
	fi
    else
	echo '#' 			     >>"$gdbinit"
	echo '# MacsBug commands...'         >>"$gdbinit"
	echo '#' 			     >>"$gdbinit"
	echo "source $where/$macsbug_script" >>"$gdbinit"
    fi
fi

#
# If the place we want the MacsBug folder is where we're getting this script from
# then we assume we have already previously run this script and there is nothing
# to do.  However we support a -force option to override this test. 
#
if [ $force -eq 0 ] && [ "$where" = "${0%/*}/" ]; then
    if [ $verbose != 0 ]; then
    	echo "### MacsBug and destination directory are the same so no need to create it"
	echo
	echo "### MacsBug installation completed"
	echo
    fi
    exit 0
fi

#
# If "where" exists we only accept it if it's a directory and we added our files to
# it previously (but we only look for MacsBug).  In addition we assume there is
# nothing to install if the key files in the directory containing this script are
# not newer than the ones in the "where" directory.  In other words we already
# installed into "where" so why do it again?  However, like the above, we have the
# -force option to force the reinstallation.
#
# If "where" doesn't exist then we need to create create it.
#
if [ -e "$where" ]; then
    if [ -d "$where" ]; then
    	if [ ! -e "$where/MacsBug" ]; then
	    if [ $changed_gdbinit != 0 ]; then
	    	mv "$gdbinit"-bkup "$gdbinit"
	    fi
    	    echo "### $where already exists and it looks like it's not previously used for Macsbug"
    	    exit 1
    	fi
    	if [ $force -eq 0 ] && \
	     [ ! "${0%/*}/MacsBug -nt "$where/MacsBug" ] && \
	     [ ! "${0%/*}/$macsbug_script -nt "$where/$macsbug_script" ]; then
	    if [ $verbose != 0 ]; then
	    	echo "### It looks like the current MacsBug stuff is already installed in $where"
		echo
		echo "### MacsBug installation not completed"
		echo
	    fi
    	    exit 0
    	fi
    else
    	echo "### $where already exists as a file"
    	exit 1
    fi
else
    ${debug}mkdir -p "$where"
    if [ $? -ne 0 ]; then
    	echo "### MacsBug installation not completed ###"
    	exit 1
    fi
fi

#
# Copy the MacsBug directory to the "where" directory.  We can tell (or we assume) the
# directory this script is running in is the source MacsBug directory.
#
${debug}cp -p "${0%/*}/README.txt"      "$where"
status=$?
${debug}cp -p "${0%/*}/gdbinit-MacsBug" "$where"
status=$?+$status
${debug}cp -p "${0%/*}/MacsBug" 	"$where"
status=$?+$status
${debug}cp -p "${0%/*}/install-MacsBug" "$where"
status=$?+$status
if [ $status -ne 0 ]; then
    # If the above failed it should have reported an error of its own
    echo "### MacsBug installation not completed ###"
    exit 1
fi

#
# Change the load-plugin command in the "gdbinit-MacsBug" gdb script to load the
# plugin (MacsBug) from the "where" directory.  Note that the load-plugin command
# is rather brain dead (right at home with the rest of the gdb command language)
# in that it needs a full pathname and no '~'s.  This is why we require that the
# call to this script specify a full pathname for "where" (if specified at all).
# We do, however, allow '~' there since we are careful not to quote the "where"
# value until after we assigned it to $where.  Bash has its quirks too!
#
if [ "$debug" != "" ]; then
    echo "cat ${0%/*}/$macsbug_script | sed -e 's,\(load-plugin[ \t]*\)\(.*$\),\1\'\"$where\"'/MacsBug,'> $where/$macsbug_script"
else
    cat "${0%/*}/$macsbug_script" | \
    sed -e 's,\(load-plugin[ ]*\)\(.*$\),\1'"$where"'/MacsBug,' > "$where/$macsbug_script"
fi

if [ $verbose != 0 ]; then
    echo
    echo "### MacsBug installation completed"
    echo
fi

exit 0
