diff --git a/poc b/poc
index d23c29d..4a91166 100755
--- a/poc
+++ b/poc
@@ -49,6 +49,18 @@ function is_true {
function miaou_debug {
is_true "${MIAOU_DEBUG}" && >&4 builtin echo -e "\e[90m <== DEBUG ==> \e[33m$*\e[0m" || true
}
+
+function on_return {
+ local regex='return ([0-9]+)'
+ if [[ "$BASH_COMMAND" =~ $regex ]] && [[ "${BASH_REMATCH[1]}" -gt 0 ]]; then
+ failure_code="${BASH_REMATCH[1]}"
+ failure_type="RETURN"
+ failure_payload="${FUNCNAME[0]}"
+ print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
+ miaou_debug ""
+ fi
+}
+
# overridden function which permits backtracing of the original `exit` statement
function exit {
error_source=("${BASH_SOURCE[@]}")
@@ -89,13 +101,22 @@ function print_miaou_error {
}
function on_error {
+ trap - RETURN
failure_code="${1:-200}"
>&4 printf '\r' # TODO: force carriage return explicitly, is it really useful?
if [[ $$ == "$BASHPID" ]]; then
- miaou_debug ""
- failure_type="COMMAND_ERROR"
- print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" '...'
+ if [[ ! -v failure_type ]]; then
+ failure_type="COMMAND_ERROR"
+ failure_payload="${BASH_COMMAND}"
+ print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
+ fi
+
+ if [[ -v failure_payload ]]; then
+ miaou_debug ""
+ else
+ miaou_debug ""
+ fi
error_source=("${BASH_SOURCE[@]}")
error_lineno=("${BASH_LINENO[@]}")
@@ -116,6 +137,7 @@ function on_error {
}
function on_pipe {
+ trap - RETURN
local tmp_error regex source lineno
error_source=("${BASH_SOURCE[@]}")
@@ -198,36 +220,51 @@ function dump_stacktrace {
}
function on_exit {
- local code
- code="${1:-0}"
+ trap - RETURN
+ local code="${1:-0}" last_error regex
mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
2>&3 >&3 dump_stderr
-
- if [[ $code -gt 0 && ${#tmp_error[@]} -gt 0 ]]; then
- local last_error regex
+ if [[ -v failure_type && "$failure_type" == 'RETURN' ]]; then
last_error="${tmp_error[-1]}"
- miaou_debug ""
- if [[ $code -eq 1 ]]; then
- regex='^(.*): line ([0-9]+): (.*): unbound variable$'
- if [[ "$last_error" =~ $regex ]]; then
- local source line payload
- source="${BASH_REMATCH[1]}"
- line="${BASH_REMATCH[2]}"
- payload="${BASH_REMATCH[3]}"
- miaou_debug ""
- failure_code=$code
- failure_type='UNBOUND_VARIABLE'
- failure_payload="${BASH_REMATCH[3]}"
- error_source=("${BASH_SOURCE[@]}")
- error_lineno=("${BASH_LINENO[@]}")
- error_funcname=("${FUNCNAME[@]}")
- unset 'error_source[0]' 'error_lineno[0]' 'error_funcname[0]'
- unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
- unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
- error_source=("$source" "${error_source[@]}")
- error_lineno=("$line" "${error_lineno[@]}")
- error_funcname=("${error_funcname[@]}" '')
+ regex='^(.*): line ([0-9]+): miaou_error: code=[0-9]+ type=RETURN'
+ if [[ "$last_error" =~ $regex ]]; then
+ miaou_debug ""
+ local source line
+ source="${BASH_REMATCH[1]}"
+ line="${BASH_REMATCH[2]}"
+ error_source=("$source" "${error_source[@]}")
+ error_lineno=("$line" "${error_lineno[@]}")
+ error_funcname=("$failure_payload" "${error_funcname[@]}")
+ else
+ miaou_debug ""
+ fi
+
+ else
+ if [[ $code -gt 0 && ${#tmp_error[@]} -gt 0 ]]; then
+ last_error="${tmp_error[-1]}"
+ miaou_debug ""
+ if [[ $code -eq 1 ]]; then
+ regex='^(.*): line ([0-9]+): (.*): unbound variable$'
+ if [[ "$last_error" =~ $regex ]]; then
+ local source line payload
+ source="${BASH_REMATCH[1]}"
+ line="${BASH_REMATCH[2]}"
+ payload="${BASH_REMATCH[3]}"
+ miaou_debug ""
+ failure_code=$code
+ failure_type='UNBOUND_VARIABLE'
+ failure_payload="${BASH_REMATCH[3]}"
+ error_source=("${BASH_SOURCE[@]}")
+ error_lineno=("${BASH_LINENO[@]}")
+ error_funcname=("${FUNCNAME[@]}")
+ unset 'error_source[0]' 'error_lineno[0]' 'error_funcname[0]'
+ unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
+ unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
+ error_source=("$source" "${error_source[@]}")
+ error_lineno=("$line" "${error_lineno[@]}")
+ error_funcname=("${error_funcname[@]}" '')
+ fi
fi
fi
miaou_debug ""
@@ -245,7 +282,7 @@ function on_exit {
set -euo pipefail
set -E # HALT on subshell error
-# set -T # DEBUG RETURN
+set -T # DEBUG RETURN
[[ $# -lt 1 ]] && >&2 echo 'ERROR: script expected!' && builtin exit 1
BASH_ARGV0="$1" && shift # to pretend script runs by itself
@@ -253,6 +290,7 @@ BASH_ARGV0="$1" && shift # to pretend script runs by itself
trap 'on_error $?' ERR
trap 'on_exit $?' EXIT
trap 'on_pipe' PIPE
+trap 'on_return' RETURN
if [[ -e /proc/$$/fd/3 ]]; then exec 4>&3 3>&-; else exec 4>/dev/tty; fi # swap fd 3 4 when fd 3 sent off
exec 3>/dev/stderr 2>"$MIAOU_BASH_ERROR"
diff --git a/test/stub/scenario.bash b/test/stub/scenario.bash
index a9fef6a..119c58c 100755
--- a/test/stub/scenario.bash
+++ b/test/stub/scenario.bash
@@ -33,11 +33,6 @@ function do_last_false {
! true
}
-function do_return {
- echo START
- return 99
-}
-
function do_command_not_found {
echo START
command_not_found A B C
@@ -50,6 +45,10 @@ function do_exit {
echo SHOULD NOT APPEAR
}
+function do_return {
+ should_return
+}
+
function do_unbound_associative {
declare -A associative
associative['A']='Abc'
@@ -115,6 +114,10 @@ function call_function_which_will_exit {
exit 99
}
+function call_function_which_will_return {
+ return 199
+}
+
function F2 {
echo "stdout A"
# echo toto >>/tmp/toto
@@ -155,6 +158,17 @@ function main {
>&2 echo some trace in stderr2
}
+function should_return {
+ echo A
+ if call_function_which_will_return; then
+ echo SUCCESS
+ else
+ echo FAILURE
+ fi
+ call_function_which_will_return
+ echo SHOULD NOT APPEAR
+}
+
function F3 {
echo F3
return 0