#!/bin/bash
# cgreen-debug
#
# Script to start cgreen-runner under gdb, load a library and break
# on a named test.
#

# If you are viewing 'cgreen-debug' this *is* that script and you'll
# find the logic at the end of this file. To update it, edit
# `cgreen-debug.argbash` instead.

# But if you are looking at 'cgreen-debug.argbash' then this is
# actually a template for argbash (https://argbash.io) which generates
# argument parsing capable bash scripts from a template just like
# this.

# To generate a new 'cgreen-debug' use
#
#     'argbash cgreen-debug.argbash -o cgreen-debug'
#
# if you have argbash installed, or go to https://argbash.io and paste
# this file into the online version.

# ARG_HELP([Start cgreen-runner under GDB (or other debugger) and break at a specific test])
# ARG_OPTIONAL_SINGLE([debugger],[d],[The debugger to use],[cgdb])
# ARG_POSITIONAL_SINGLE([library],[Dynamically loadable library with Cgreen tests],[])
# ARG_POSITIONAL_SINGLE([testname],[The test to debug, in Cgreen notation ('<Context>:<test>')],[])
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.9.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
# Generated online by https://argbash.io/generate


die()
{
    local _ret="${2:-1}"
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    echo "$1" >&2
    exit "${_ret}"
}


begins_with_short_option()
{
    local first_option all_short_options='hd'
    first_option="${1:0:1}"
    test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

# THE DEFAULTS INITIALIZATION - POSITIONALS
_positionals=()
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_debugger="cgdb"


print_help()
{
    printf '%s\n' "Start cgreen-runner under GDB (or other debugger) and break at a specific test"
    printf 'Usage: %s [-h|--help] [-d|--debugger <arg>] <library> <testname>\n' "$0"
    printf '\t%s\n' "<library>: Dynamically loadable library with Cgreen tests"
    printf '\t%s\n' "<testname>: The test to debug, in Cgreen notation ('<Context>:<test>')"
    printf '\t%s\n' "-h, --help: Prints help"
    printf '\t%s\n' "-d, --debugger: The debugger to use (default: 'cgdb')"
}


parse_commandline()
{
    _positionals_count=0
    while test $# -gt 0
    do
        _key="$1"
        case "$_key" in
            -h|--help)
                print_help
                exit 0
                ;;
            -h*)
                print_help
                exit 0
                ;;
            -d|--debugger)
                test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
                _arg_debugger="$2"
                shift
                ;;
            --debugger=*)
                _arg_debugger="${_key##--debugger=}"
                ;;
            -d*)
                _arg_debugger="${_key##-d}"
                ;;
            *)
                _last_positional="$1"
                _positionals+=("$_last_positional")
                _positionals_count=$((_positionals_count + 1))
                ;;
        esac
        shift
    done
}


handle_passed_args_count()
{
    local _required_args_string="'library' and 'testname'"
    test "${_positionals_count}" -ge 2 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require exactly 2 (namely: $_required_args_string), but got only ${_positionals_count}." 1
    test "${_positionals_count}" -le 2 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect exactly 2 (namely: $_required_args_string), but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
}


assign_positional_args()
{
    local _positional_name _shift_for=$1
    _positional_names="_arg_library _arg_testname "

    shift "$_shift_for"
    for _positional_name in ${_positional_names}
    do
        test $# -gt 0 || break
        eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
        shift
    done
}

parse_commandline "$@"
handle_passed_args_count
assign_positional_args 1 "${_positionals[@]}"

# OTHER STUFF GENERATED BY Argbash

### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash

if [ "$_arg_debugger" == "" ]; then
    if command -v cgdb > /dev/null 2>&1 ; then
        debugger=cgdb
    else
        debugger=gdb
    fi
else
    if command -v $_arg_debugger > /dev/null 2>&1 ; then
        debugger=$_arg_debugger
    else
        echo "No such debugger: $_arg_debugger"
        exit 1
    fi
fi

# Figure out where to place breakpoint by replacing ':' with '__'
bp=${_arg_testname//:/__}

if [ "$debugger" == "lldb" ] ; then
    echo break set -n $bp > .cgreen-debug-commands
    echo run $_arg_library $_arg_testname >> .cgreen-debug-commands
    $debugger cgreen-runner --source .cgreen-debug-commands
else
    echo break $bp > .cgreen-debug-commands
    echo run $_arg_library $_arg_testname >> .cgreen-debug-commands
    $debugger -ex "set breakpoint pending on" cgreen-runner --command=.cgreen-debug-commands
fi

#rm .cgreen-debug-commands

# ] <-- needed because of Argbash
