#!/bin/bash
set -eu
trap _exit_trap EXIT
trap _err_trap ERR
_showed_traceback=f
function _exit_trap
{
local _ec="$?"
if [[ $_ec != 0 && "${_showed_traceback}" != t ]]; then
traceback 1
fi
}
function _err_trap
{
local _ec="$?"
local _cmd="${BASH_COMMAND:-unknown}"
traceback 1
_showed_traceback=t
echo "The command ${_cmd} exited with exit code ${_ec}." 1>&2
}
function traceback
{
local -i start=$(( ${1:-0} + 1 )) # hide this function from backtrace
local -i end=${#BASH_SOURCE[@]}
local -i i=0
local -i j=0
echo "Traceback (most recent call last):" 1>&2
for ((i=start; i < end; i++)); do
j=$(( i - 1 ))
local fname="${FUNCNAME[$i]}"
local file="${BASH_SOURCE[$i]}"
local line="${BASH_LINENO[$j]}"
if [ $i -eq $start ] ; then printf " ⦿-"; fi 1>&2
printf "file: ${file}, line: ${line}, in ${fname}\n" 1>&2
printf "%-${j}s" "" 1>&2 ;
if [ $i -lt $(( end-1 )) ]; then
printf " %s" "\\_"
else
printf "\n" ; fi
done
}
function alpha
{
beta
}
function beta
{
gamma
}
function gamma
{
delta
}
function delta
{
epsilon
}
function epsilon
{
no_such_function
}
alpha