#!/bin/bash # APSK Bash Debugging Library # # by Apollia - http://apollia.com/ # # # 2020-09-11 01:32:46. A library of Bash functions useful for debugging, # such as backtrace, forthtrace, announcing entrances to and exits from # a function, and printing strings or arrays with the source location # automatically displayed above what you printed. # # With most of the functions that are intended for developer use, you can # control whether they get run or not by providing a tag argument, and/or # by changing the config vars and arrays listed below. # # Also, you can make it so debug functions only get run if they're called # from a particular function or set of functions that you're curious about. # # However, tag includes or excludes take precedence over function includes # or excludes. # # # This app's Git repo: # # https://apollia.org/gitlist/APSK-Bash-Debugging-Tools.git # # # 2020-12-08 01:01:57. # # List of all functions especially intended for developer use: # # decho # # ardecho # hashdecho # # echoar # echohash # # backtrace (or bt) # forthtrace (or ft) # # Decho____Now_In_This_Function # Decho____Back_In_This_Function # Decho____Now_Exiting_This_Function # # APSK_Debug____Print_All_Unique_Tags_Used # # techo (or tagged_echo) # # teval (or tagged_eval) # dexit # # # Doesn't have tag feature or source location header: # # APSK_Debug____PrintArr # APSK_Debug____PrintHash # # # See the rest of this source code for more details. #------------------------------------------------------------------------------------------------------------------- # # 2020-09-08 02:31:24. Copy-and-pasteable, developer-settable config vars # and arrays. # # But you shouldn't edit them here - you should copy and paste # the below into your own program and edit them there. # #------------------------------------------------------------------------------------- # # *(*)* # # 03:45:38 09/11/2020. APSK Bash Debugging Library config: # # APSK_DEBUG_MODE=true APSK_Debug____should_print_Now_in_Function_headers=true APSK_Debug____should_print_Back_in_Function_headers=true APSK_Debug____should_print_Now_Exiting_This_Function_footers=true APSK_Debug____should_allow_decho=true # 2020-09-08 17:20:24. Doesn't affect printing of function headers # or footers. APSK_Debug____should_allow_dexit=true APSK_Debug____should_allow_ardecho=true APSK_Debug____should_allow_echoar=true APSK_Debug____should_allow_hashdecho=true APSK_Debug____should_allow_echohash=true APSK_Debug____should_allow_backtrace=true # 2020-09-09 23:19:15. Only affects bt() and backtrace(). APSK_Debug____should_allow_forthtrace=true # 2020-09-10 08:39:29. Only affects ft() and forthtrace(). APSK_Debug____should_allow_tagged_echo=true # 2020-11-01 10:32:29. Only affects techo() and tagged_echo(). APSK_Debug____should_allow_tagged_eval=true # 2020-10-17 00:20:16. Only affects teval() and tagged_eval(). APSK_Debug____should_allow_printing_of_unique_tags=true # 2020-09-08 22:16:25. Only affects APSK_Debug____Print_All_Unique_Tags_Used(). # 2020-09-06 23:03:50. If anything is in these Include arrays, #debug mode gets aborted for anything not in these arrays: APSK_Debug____Functions_to_Include=( ) APSK_Debug____Tags_to_Include=( ) # 2020-09-06 23:08:44. If these Exclude arrays are used instead, # debug mode is allowed to continue for everything except the # excluded items: APSK_Debug____Tags_to_Exclude=( ) APSK_Debug____Functions_to_Exclude=( ) # 2020-09-07 23:21:55. Used to determine whether # Decho____Now_In_This_Function should be allowed to run: APSK_Debug____Function_Headers_to_Include=( ) APSK_Debug____Function_Headers_to_Exclude=( ) # 2020-09-27 14:51:21. Used to determine whether # Decho____Back_In_This_Function should be allowed to run. APSK_Debug____Back_In_Function_Headers_to_Include=( ) APSK_Debug____Back_In_Function_Headers_to_Exclude=( ) # 2020-09-07 23:22:42. Used to determine whether #Decho____Now_Exiting_This_Function should be allowed to run. APSK_Debug____Function_Footers_to_Include=( ) APSK_Debug____Function_Footers_to_Exclude=( ) # # # 2020-09-08 02:32:28. # # End of APSK Bash Debugging Library config - # # Copy-and-pasteable, developer-settable config vars # and arrays. # # You shouldn't edit them here - you should copy and paste # them into your own program and edit them there. # # #------------------------------------------------------------------------------------------------------------------- # 2020-09-08 02:31:06. Not developer-settable, used by APSK Bash Debugging Library: APSK_Debug____All_Unique_Tags_Used=() #------------------------------------------------------------------------------------------------------------------- # # *(*)* # # 2020-09-08 22:29:37. Functions especially intended for the developer. # # # 2020-09-08 17:50:35. Most of these functions accept a tag argument, # to make it easier to control whether it gets run or displayed or not. # # #-------------------------------------------------- # # 2020-09-08 17:49:13. 2020-09-09 04:13:39. 2020-12-04 18:26:37. # # 7 general printing functions: # # # decho: Debug echo, with source location header # # ardecho: Debug-echo an array, with source location header # # hashdecho: Debug-echo a hash (an associative array), with source location header # # # APSK_Debug____PrintArr: Echo an array without echoing a header, nor other frills. # Doesn't accept tags. # # APSK_Debug____PrintHash: Echo a hash (an associative array) without echoing a header. # Keys and values are labeled and enclosed in single quotes. Doesn't accept tags. # # # echoar: Like APSK_Debug____PrintArr, but accepts a tag, # and has an easier to type name. # # echohash: Like APSK_Debug____PrintHash, but accepts a tag, # and has an easier to type name. ############ # Function decho() { # 2020-09-08 17:50:12. Debug echo, with a source location header. # 2020-09-12 02:22:23. 5 inrvars in all, 3 here: local tag local stuff_to_echo local result_code # 2020-09-12 00:08:44. Unlimited inpvars (input vars), 0 outvars. # # If there's more than 1 inpvar, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. local args=("$@") APSK_Debug____Process_Decho_Args args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 # 2020-09-12 02:37:01. The last 2 inrvars (inner, non-input-arg local vars): local retval local Source_Location #@@@@ APSK_Debug____Get_Location_in_Source_File Source_Location="$retval" #@@@@ echo " -------------------- decho from $Source_Location" [ ! -z "$tag" ] && echo " Tag: $tag" echo " %%%%% $stuff_to_echo ^^^^^" #!!!! return "$?" } #readonly -f decho # End of # Function ############ ############ # Function ardecho() { # 2020-09-08 17:49:52. Debug-echo an array, with a source location header. # 2020-09-08 17:43:03. 3 inpvars, 0 outvars: local tag="$3" #2020-09-26 12:34:12. 3 inrvars, 1 here: local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local thisarray="$1" # local thisarray=("${!1}") local message="$2" # 2020-09-08 17:43:34. Last 2 inrvars: local Source_Location local retval #@@@@ APSK_Debug____Get_Location_in_Source_File Source_Location="$retval" #@@@@ echo " @@@@@@@@@@@@@@@@@@@@ ardecho from $Source_Location" [ ! -z "$tag" ] && echo " Tag: $tag" echo " Array: $1" [ ! -z "$message" ] && echo " Debug message: $message" echo " %%%%% " APSK_Debug____PrintArr "$thisarray" echo " ^^^^^^^^^^^^^^^^^^^^" } #readonly -f ardecho # End of # Function ############ ############ # Function hashdecho() { # 2020-09-08 17:49:52. 2020-12-04 17:18:35. # # Debug-echo a hash (an associative array), with a source location header. # 2020-09-08 17:43:03. 3 inpvars, 0 outvars: local tag="$3" #2020-09-26 12:34:12. 3 inrvars, 1 here: local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local thisarray="$1" # local thisarray=("${!1}") local message="$2" # 2020-09-08 17:43:34. Last 2 inrvars: local Source_Location local retval #@@@@ APSK_Debug____Get_Location_in_Source_File Source_Location="$retval" #@@@@ echo " %%%%%%%%%%%%%%%%%%%% hashdecho from $Source_Location" [ ! -z "$tag" ] && echo " Tag: $tag" echo " Hash: $1" [ ! -z "$message" ] && echo " Debug message: $message" echo " %%%%%" APSK_Debug____PrintHash "$thisarray" echo " ^^^^^^^^^^^^^^^^^^^^" } #readonly -f hashdecho # End of # Function ############ ############ # Function echoar() { # 2020-09-11 02:35:36. Prints an array, but without frills # such as a source location header. # # Accepts a tag. # 2020-09-11 02:45:29. Example call of this function: # # echoar My_Array[@] # # # Or, to run it silently: # # result=$(echoar My_Array[@] ) # 2020-09-11 02:36:26. 2 inpvars, 0 outvars, 1 inrvar: local tag="$2" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local thisarray="$1" APSK_Debug____PrintArr "$thisarray" } #readonly -f echoar # End of # Function ############ ############ # Function echohash() { # 2020-09-11 02:35:36. 2020-12-04 18:29:38. # # Prints a hash (an associative array) without a source location header. # Keys and values are labeled and enclosed in single quotes. # # Accepts a tag. # 2020-09-11 02:45:29. 2020-12-04 18:30:41. # # Example call of this function: # # echohash My_Hash # # # Or, to run it silently: # # result=$(echohash My_Hash ) # 2020-09-11 02:36:26. 2 inpvars, 0 outvars, 1 inrvar: local tag="$2" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local thisarray="$1" APSK_Debug____PrintHash "$thisarray" } #readonly -f echohash # End of # Function ############ ############ # Function APSK_Debug____PrintArr() { # 2020-09-06 21:17:39. Example call of this function: # # APSK_Debug____PrintArr My_Array[@] # # # Or, to run it silently: # # result=$(APSK_Debug____PrintArr My_Array[@] ) # 2020-09-08 17:32:49. 1 inpvar, 0 outvars, 0 inrvars: local thisarray=("${!1}") printf '"%s"\n\n' "${thisarray[@]}" } #readonly -f APSK_Debug____PrintArr # End of # Function ############ # 2020-12-04 17:21:37. This showed me how to deal with hashes (associative arrays): # #https://stackoverflow.com/questions/4069188/how-to-pass-an-associative-array-as-argument-to-a-function-in-bash/32536571#32536571 ############ # Function APSK_Debug____PrintHash() { # 2020-09-06 21:17:39. 2020-12-04 17:20:31. # # Example call of this function: # # APSK_Debug____PrintHash My_Hash # # # Or, to run it silently: # # result=$(APSK_Debug____PrintHash My_Hash ) #echo "now in APSK_Debug____PrintHash" #2020-12-04 17:36:28. 1 inpvar, 0 outvars: local hash_definition=$( declare -p "$1" ) #echo; echo; echo "hash_definition: $hash_definition" # 2020-12-04 17:37:07. 3 inrvars: local hash local command_line local key command_line="declare -A hash=${hash_definition#*=}" #echo "command_line: $command_line" eval "$command_line" for key in "${!hash[@]}" do echo echo echo "Key '$key' value: \"${hash[$key]}\"" done } #readonly -f APSK_Debug____PrintHash # End of # Function ############ # # # 2020-09-08 18:17:22. 2020-12-04 18:26:56. # # End of 7 general printing functions for the developer. # # #-------------------------------------------------- # # *(*)* # # 2020-09-09 04:18:51. 3 function-announcement functions for the developer: # # # Decho____Now_In_This_Function # Decho____Back_In_This_Function # Decho____Now_Exiting_This_Function ############ # Function Decho____Now_In_This_Function() { # 2020-09-12 02:23:30. 4 inrvars total, 3 here: local tag local stuff_to_echo local result_code # 2020-09-12 00:31:26. Unlimited inpvars (input vars), 0 outvars. # # If there's more than 1 inpvar, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. local args=("$@") APSK_Debug____Process_Decho_Args args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 # 2020-09-12 02:36:22. The last inrvar: local Function_Name Function_Name="${FUNCNAME[1]}" echo " ----------------------------------------------------------------------" echo echo "Now in $Function_Name()" [ ! -z "$tag" ] && echo " Tag: $tag" if [ ! -z "$stuff_to_echo" ] then echo " Debug message: $stuff_to_echo" fi echo echo #!!!! return 0 } #readonly -f Decho____Now_In_This_Function # End of # Function ############ ############ # Function Decho____Back_In_This_Function() { # 2020-09-12 02:24:23. 4 inrvars total, 3 here: local tag local stuff_to_echo local result_code # 2020-09-12 00:32:26. Unlimited inpvars (input vars), 0 outvars. # # If there's more than 1 inpvar, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. local args=("$@") APSK_Debug____Process_Decho_Args args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 # 2020-09-12 02:36:12. The last inrvar: local Function_Name Function_Name="${FUNCNAME[1]}" echo -n " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Back in $Function_Name()" [ ! -z "$tag" ] && echo " Tag: $tag" if [ ! -z "$stuff_to_echo" ] then echo " Debug message: $stuff_to_echo" fi echo echo #!!!! return 0 } #readonly -f Decho____Back_In_This_Function # End of # Function ############ ############ # Function Decho____Now_Exiting_This_Function() { # 2020-09-11 02:12:56. Optionally, this can print # a custom message, and/or announce the return code # the function is about to return. # # Announces the function which the caller of Decho____Now_Exiting_This_Function # is about to return to. # 2020-09-12 02:25:20. 6 inrvars total, 4 here: local tag local stuff_to_echo local return_code local result_code # 2020-09-12 00:35:42. Unlimited inpvars (input vars), 0 outvars. # # 2020-09-12 00:35:37. The 1st arg is always assumed to be # $return_code, which will be printed and also returned. # # (However, this function can't stop its parent function from continuing # after this is run, so you'll have to stop the parent function yourself by # always putting a return or exit command after the # Decho____Now_Exiting_This_Function command.) # # If there are more than 2 inpvars, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. local args=("$@") APSK_Debug____Process_Args_for_Decho_Function_Footer args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 # 2020-09-12 02:35:59. The last 2 inrvars: local Function_Name local Parent_Function_Name Function_Name="${FUNCNAME[1]}" Parent_Function_Name="${FUNCNAME[2]}" echo " ---------- Now exiting this function: $Function_Name()" [ ! -z "$tag" ] && echo " Tag: $tag" if [ ! -z "$stuff_to_echo" ] then echo " Debug message: %%%%% $stuff_to_echo ^^^^^ Still exiting this function: $Function_Name()" fi echo if [ ! -z "$return_code" ] then echo "Returning $return_code to:" else echo "Returning to:" fi echo " $Parent_Function_Name()" echo echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" #!!!! [ ! -z "$return_code" ] && return "$return_code" #!!!! return 0 } #readonly -f Decho____Now_Exiting_This_Function # End of # Function ############ # # # 2020-09-09 04:21:02. # # End of 3 function-announcement functions for the developer. # # #-------------------------------------------------- # # *(*)* # # 2020-09-10 03:08:45. 5 more functions for the developer: # # # APSK_Debug____Print_All_Unique_Tags_Used: # # Lets you know what debug tags your program used so far. # # # backtrace # bt # forthtrace # ft ############ # Function APSK_Debug____Print_All_Unique_Tags_Used() { # 2020-09-08 18:21:28. 1 inpvar, 0 outvars, 1 inrvar. local tag="$1" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 echo; echo; echo; echo "---------"; echo "APSK Debug: now printing all unique tags used:" echo APSK_Debug____PrintArr APSK_Debug____All_Unique_Tags_Used[@] echo echo "^^^^^" echo } #readonly -f APSK_Debug____Print_All_Unique_Tags_Used # End of # Function ############ ############ # Function techo() { tagged_echo "$@" } #readonly -f techo # End of # Function ############ ############ # Function tagged_echo() { # 2020-11-01 11:07:03. Like decho() minus most of the clutter # (such as a source location header) surrounding what you echo. # # However, if you provide more than one $stuff_to_echo arg, # newlines are inserted between them. # 2020-09-12 02:22:23. 4 inrvars in all, 3 here: local tag local stuff_to_echo local result_code # 2020-09-12 00:08:44. Unlimited inpvars (input vars), 0 outvars. # # If there's more than 1 inpvar, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. local args=("$@") APSK_Debug____Process_Decho_Args args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 echo "$stuff_to_echo" } #readonly -f tagged_echo # End of # Function ############ ############ # Function teval() { tagged_eval "$@" } #readonly -f teval # End of # Function ############ ############ # Function tagged_eval() { local tag="$2" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local command_line="$1" eval "$command_line" } #readonly -f tagged_eval # End of # Function ############ ############ # Function dexit() { # 2020-09-11 02:12:56. 2020-10-30 11:35:00. # # Announces the location at which the entire program is being exited. # # Optionally, this can print a custom message. # 2020-10-30 11:37:25. 8 inrvars total, 5 here: local tag local stuff_to_echo local return_code local exit_code local result_code # 2020-09-12 00:35:42. Unlimited inpvars (input vars), 0 outvars. # # 2020-10-30 11:36:51. The 1st arg is always assumed to be # $return_code, which will be used as $exit_code. # # If there are more than 2 inpvars, the last one will be assumed to be a tag. # # Everything else is assumed to be stuff to echo. # 2020-10-30 12:25:46. 1 more inrvar: local args=("$@") APSK_Debug____Process_Args_for_Decho_Function_Footer args[@] #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 # 2020-09-12 02:37:01. The last 2 inrvars (inner, non-input-arg local vars): local retval local Source_Location #@@@@ exit_code="$return_code" [ -z "$exit_code" ] && exit_code=255 APSK_Debug____Get_Location_in_Source_File Source_Location="$retval" #@@@@ msg=" !!!!!!!!!!!!!!!!!!!! dexit from $Source_Location Exit code: $exit_code" [ ! -z "$tag" ] && msg+=" Tag: $tag" [ ! -z "$stuff_to_echo" ] && msg+=" %%%%% $stuff_to_echo ^^^^^ End of dexit from $Source_Location Exit code: $exit_code " echo "$msg" #!!!! exit "$exit_code" } #readonly -f dexit # End of # Function ############ ############ # Function backtrace() { local tag="$4" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local quantity_to_breve_at_start="$1" local quantity_to_breve_at_end="$2" local max_unbreved_entries="$3" backtrace_or_forthtrace "Back" "$quantity_to_breve_at_start" "$quantity_to_breve_at_end" "$max_unbreved_entries" } #readonly -f backtrace # End of # Function ############ ############ # Function bt() { local tag="$4" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local quantity_to_breve_at_start="$1" local quantity_to_breve_at_end="$2" local max_unbreved_entries="$3" backtrace_or_forthtrace "Back" "$quantity_to_breve_at_start" "$quantity_to_breve_at_end" "$max_unbreved_entries" } #readonly -f bt # End of # Function ############ ############ # Function forthtrace() { local tag="$4" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local quantity_to_breve_at_start="$1" local quantity_to_breve_at_end="$2" local max_unbreved_entries="$3" backtrace_or_forthtrace "Forth" "$quantity_to_breve_at_start" "$quantity_to_breve_at_end" "$max_unbreved_entries" } #readonly -f forthtrace # End of # Function ############ ############ # Function ft() { local tag="$4" local result_code #!!!! APSK_Debug____If_Necessary__Quit_This_Debug_Func "$tag"; result_code="$?"; [ "$result_code" = 0 ] && return 1 local quantity_to_breve_at_start="$1" local quantity_to_breve_at_end="$2" local max_unbreved_entries="$3" backtrace_or_forthtrace "Forth" "$quantity_to_breve_at_start" "$quantity_to_breve_at_end" "$max_unbreved_entries" } #readonly -f ft # End of # Function ############ # # # 2020-09-08 22:06:34. # # # End of functions especially intended for use by the developer. # # #------------------------------------------------------------------------------------------------------------------- # # # 2020-09-08 18:18:26. The rest of these functions are used internally. # # 2020-09-09 05:42:01. But the developer can use them if per wants. # # https://stallman.org/articles/genderless-pronouns.html ############ # Function APSK_Debug____Process_Decho_Args() { # 2020-09-11 23:51:46. Used by 3 functions: # # decho # Decho____Now_In_This_Function # Decho____Back_In_This_Function # # # 2020-09-12 00:29:38. But not Decho____Now_Exiting_This_Function(), # since it was too different from the others. # 2020-09-09 22:00:32. 2020-09-12 00:03:21. # # If there's more than one arg, the last arg s assumed to be a tag, # which will be placed in $tag. # # All other args get added to $stuff_to_echo. # 2020-09-11 23:50:58. 1 inpvar: local args=("${!1}") # 2020-09-11 23:51:13. 2 outvars: tag="" stuff_to_echo="" # 2020-09-11 23:51:27. 2 inrvars: local count_of_args local inc count_of_args="${#args[@]}" #ardecho args[@] if [[ "$count_of_args" -lt 2 ]] then tag="" else tag="${args[@]: -1}" fi if [[ "$count_of_args" = 1 ]] then [ ! -z "${args[0]}" ] && stuff_to_echo+="${args[0]}" #!!!! return 0 fi inc=0 for arg in "${args[@]}" do let "inc++" [[ "$inc" -eq "count_of_args" ]] && break [[ "$inc" -gt 1 ]] && stuff_to_echo+=" " stuff_to_echo+="$arg" done } #readonly -f APSK_Debug____Process_Decho_Args # End of # Function ############ ############ # Function APSK_Debug____Process_Args_for_Decho_Function_Footer() { # 2020-09-12 00:23:26. 2020-10-30 11:33:00. # # Used by 2 functions: # # Decho____Now_Exiting_This_Function # dexit # 2020-09-09 22:00:32. 2020-09-12 00:03:21. # 2020-09-12 00:24:41. # # The 1st arg is always used as $return_code. # # If there are more than 2 args, the last arg is assumed to be a tag, # which will be placed in $tag. # # All other args get added to $stuff_to_echo. # 2020-09-11 23:50:58. 1 inpvar: local args=("${!1}") # 2020-09-11 23:51:13. 3 outvars: tag="" stuff_to_echo="" return_code="" # 2020-09-11 23:51:27. 2 inrvars: local count_of_args local inc count_of_args="${#args[@]}" if [[ "$count_of_args" -lt 3 ]] then tag="" else tag="${args[@]: -1}" fi return_code="${args[0]}" if [[ "$count_of_args" = 1 ]] then #!!!! return 0 fi if [[ "$count_of_args" = 2 ]] then return_code="${args[0]}" [ ! -z "${args[1]}" ] && stuff_to_echo+="${args[1]}" #!!!! return 0 fi inc=0 for arg in "${args[@]}" do let "inc++" case "$inc" in 0|1) #>>>> continue ;; "$count_of_args") break; ;; esac # [[ "$inc" -eq "count_of_args" ]] && break [[ "$inc" -gt 2 ]] && stuff_to_echo+=" " stuff_to_echo+="$arg" done } #readonly -f APSK_Debug____Process_Args_for_Decho_Function_Footer # End of # Function ############ ############ # Function APSK_Debug____For_Trace____Get_Details_about_Function_Call() { local arrin="$1" local parent_arrin="$2" Function_Name="${FUNCNAME[$arrin]}" Line_Number="${BASH_LINENO[$arrin]}" Func_Fillepath="${BASH_SOURCE[$arrin]}" Func_Filename=$(basename "$Func_Fillepath") Func_Follpath=$(dirname "$Func_Fillepath") Func_Follpath=$(realpath "$Func_Follpath") # APSK_Debug____Path_to_Htap "$Func_Follpath" # func_foll_htap="$retval" Parent_Function="${FUNCNAME[$parent_arrin]}" Parent_Fillepath="${BASH_SOURCE[$parent_arrin]}" Parent_Filename=$(basename "$Parent_Fillepath") Parent_Follpath=$(dirname "$Parent_Fillepath") Parent_Follpath=$(realpath "$Parent_Follpath") APSK_Debug____Path_to_Htap "$Parent_Follpath" parent_foll_htap="$retval" } #readonly -f APSK_Debug____For_Trace____Get_Details_about_Function_Call # End of # Function ############ ############ # Function backtrace_or_forthtrace() { # 2020-09-10 04:37:05. Used by both bt()/backtrace() and ft()/forthtrace(). # # Displays a list of the functions called before this function was called. # # Backtrace: most recent -> least recent. # Forthtrace: least recent -> most recent. # # 2020-09-11 02:21:48. Tries to exclude itself from the list. # 2020-09-10 08:29:15. 4 inpvars, 0 outvars: local back_or_forth="$1" local quantity_to_breve_at_start="$2" local quantity_to_breve_at_end="$3" local max_unbreved_entries="$4" #[ "$max_unbreved_entries" = 0 ] && max_unbreved_entries="" [ "$quantity_to_breve_at_start" = 0 ] && quantity_to_breve_at_start="" [ "$quantity_to_breve_at_end" = 0 ] && quantity_to_breve_at_end="" # 2020-09-10 19:57:23. 27 inrvars in all - 4 below and 23 later: local Function_Which_Called_bt_or_ft local count_of_funcs local count_of_funcs_minus_1 local Header_Text #@@@@ [ -z "$back_or_forth" ] && back_or_forth="Back" Function_Which_Called_bt_or_ft="${FUNCNAME[1]}" count_of_funcs="${#FUNCNAME[@]}" count_of_funcs_minus_1="$count_of_funcs" let "count_of_funcs_minus_1--" #@@@@ # echo "Function_Which_Called_bt_or_ft: $Function_Which_Called_bt_or_ft" #APSK_Debug____PrintArr FUNCNAME[@] # echo # APSK_Debug____PrintArr BASH_LINENO[@] # echo # APSK_Debug____PrintArr BASH_SOURCE[@] # echo "count of funcs: $count_of_funcs" # echo "quantity_to_breve_at_start: $quantity_to_breve_at_start" echo echo echo "========================================" echo Header_Text="${back_or_forth}trace" [ ! -z "$max_unbreved_entries" ] && Header_Text+=", printing max $max_unbreved_entries unabreved function" [[ "$max_unbreved_entries" -gt 1 ]] && Header_Text+="s" [ ! -z "$quantity_to_breve_at_start" ] && Header_Text+=", abreving first $quantity_to_breve_at_start function" [[ "$quantity_to_breve_at_start" -gt 1 ]] && Header_Text+="s" [ ! -z "$quantity_to_breve_at_end" ] && Header_Text+=", abreving last $quantity_to_breve_at_end" Header_Text+=":" echo "$Header_Text" echo # 2020-09-10 08:52:25. 4 more inrvars, with 19 more remaining: local arrin local parent_arrin local origin_arrin local breve_at_end_arrin if [ "$back_or_forth" = "Back" ] then breve_at_end_arrin=$(( count_of_funcs - quantity_to_breve_at_end )) let "breve_at_end_arrin--" # 2020-09-10 02:46:38. Backtrace starts near the beginning # of the FUNCNAME array, forthtrace starts near the end. case "$Function_Which_Called_bt_or_ft" in "backtrace"|"bt") arrin=2 parent_arrin=3 ;; *) arrin=0 parent_arrin=1 ;; esac else # 2020-09-10 01:35:07. Forth. arrin="$count_of_funcs" case "$Function_Which_Called_bt_or_ft" in "forthtrace"|"ft") let "arrin--" origin_arrin=2 # let "arrin--" # let "arrin--" # echo "arrin now: $arrin" ;; *) let "arrin--" origin_arrin=1 ;; esac breve_at_end_arrin=$(( origin_arrin + quantity_to_breve_at_end )) #let "breve_at_end_arrin++" parent_arrin="$arrin" let "parent_arrin++" fi # 2020-09-10 08:53:47. 8 more inrvars, with 11 remaining. local count_of_entries local count_of_entries_printed local keep_going local Origin local should_print_long_entry local entry local abreved_entry local entries #@@@@ count_of_entries=0 count_of_entries_printed=0 keep_going=true Origin="" should_print_long_entry=true #@@@@ # 2020-09-10 08:56:02. The last 11 inrvar declarations. local Function_Name local Line_Number local Func_Fillepath local Func_Filename local Func_Follpath local func_foll_htap local Parent_Function local Parent_Fillepath local Parent_Filename local Parent_Follpath local parent_foll_htap while [ "$keep_going" = true ] do should_print_long_entry=true APSK_Debug____For_Trace____Get_Details_about_Function_Call "$arrin" "$parent_arrin" entry="$Parent_Function() -> $Function_Name() <- Line $Line_Number of $Parent_Filename" abreved_entry="$Parent_Function() -> $Function_Name() <- Line $Line_Number <- $Parent_Filename" #abreved_entry="$Parent_Function() -> $Function_Name()" #abreved_entry="$entry" if [ "$count_of_entries" -gt 0 ] then entry=" ------- $entry" fi if [ "$back_or_forth" = "Back" ] then if [ -z "$Origin" ] then Origin="$Parent_Function() -> $Function_Name() <- Line $Line_Number of $Parent_Filename" echo "$Origin" echo echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " else # 2020-09-10 05:13:42. Origin has already been printed for backtrace. if [ ! -z "$max_unbreved_entries" ] then [[ "$count_of_entries_printed" -ge "$max_unbreved_entries" ]] && should_print_long_entry=false fi if [ "$should_print_long_entry" = true ] then if [ ! -z "$quantity_to_breve_at_start" ] then [[ "$count_of_entries" -lt "$quantity_to_breve_at_start" ]] && should_print_long_entry=false fi fi if [ "$should_print_long_entry" = true ] then if [ ! -z "$quantity_to_breve_at_end" ] then [[ "$arrin" -ge "$breve_at_end_arrin" ]] && should_print_long_entry=false fi fi if [ "$should_print_long_entry" = true ] then echo "$entry" let "count_of_entries_printed++" else # 2020-09-11 02:25:13. If the long entry doesn't get printed, # the indented, just slightly abreved entry is printed instead. echo " --- $abreved_entry" fi let "count_of_entries++" fi let "arrin++" let "parent_arrin++" [ "$arrin" -eq "$count_of_funcs_minus_1" ] && { keep_going=false; continue; } else # 2020-09-10 02:10:04. Forth if [ "$arrin" -eq "$origin_arrin" ] then Origin="$Parent_Function() -> $Function_Name() <- Line $Line_Number of $Parent_Filename" echo "$Origin" echo echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" echo echo echo "$entries" keep_going=false #>>>> continue else if [ "$arrin" -gt 1 ] then if [ ! -z "$max_unbreved_entries" ] then [[ "$count_of_entries_printed" -ge "$max_unbreved_entries" ]] && should_print_long_entry=false fi if [ "$should_print_long_entry" = true ] then if [ ! -z "$quantity_to_breve_at_start" ] then [[ "$count_of_entries" -lt "$quantity_to_breve_at_start" ]] && should_print_long_entry=false fi fi if [ "$should_print_long_entry" = true ] then if [ ! -z "$quantity_to_breve_at_end" ] then [[ "$arrin" -le "$breve_at_end_arrin" ]] && should_print_long_entry=false fi fi if [ "$should_print_long_entry" = true ] then entries+=" $entry" let "count_of_entries_printed++" else entries+=" --- $abreved_entry" fi let "count_of_entries++" fi fi let "arrin--" let "parent_arrin--" [[ "$parent_arrin" -eq 0 ]] && parent_arrin=1 fi done echo echo echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" echo # echo "End of ${back_or_forth}trace:" echo "End of $Header_Text" echo echo "$Origin" echo echo "========================================" } #readonly -f backtrace_or_forthtrace # End of # Function ############ ############ # Function APSK_Debug____Get_Location_in_Source_File() { # 2020-09-08 17:39:19. 0 inpvars # # 1 outvar: $retval # # 7 inrvars: local Function_Name local Line_Number local Source_Fillepath local Source_Filename local Source_Follpath local foll_htap local location #@@@ Function_Name="${FUNCNAME[2]}" Line_Number="${BASH_LINENO[1]}" Source_Fillepath="${BASH_SOURCE[2]}" Source_Filename=$(basename "$Source_Fillepath") Source_Follpath=$(dirname "$Source_Fillepath") Source_Follpath=$(realpath "$Source_Follpath") #@@@@ APSK_Debug____Path_to_Htap "$Source_Follpath" foll_htap="$retval" location="$Function_Name() -> Line $Line_Number <- $Source_Filename $foll_htap" retval="$location" #!!!! return 0 } #readonly -f APSK_Debug____Get_Location_in_Source_File # End of # Function ############ ############ # Function APSK_Debug____Path_to_Htap() { # 2020-09-08 22:10:55. 1 inpvar: local path="$1" # 2020-09-08 22:11:21. 1 outvar: retval="" # 2020-09-08 22:11:31. 2 inrvars: local htap local Array____htap IFS=/ read -a Array____htap <<< "$path" htap=$(printf '%s\n' "${Array____htap[@]}" | tac | tr '\n' '\\') retval="$htap" #!!!! return 0 } #readonly -f APSK_Debug____Path_to_Htap # End of # Function ############ ############ # Function APSK_Debug____Check_Array_for_String() { # 2020-09-06 22:57:39. Example call of this function: # # APSK_Debug____Check_Array_for_String "string" My_Array[@] # 2020-09-06 23:09:28. # # Return codes: # # 0: string found # 1: string not found # 2020-09-06 22:57:43. 2 inpvars, 0 outvars: local string="$1" local thisarray=("${!2}") # 2020-09-07 01:43:28. 1 inrvar: local item #!!!! [ ${#thisarray[@]} -eq 0 ] && return 1 #inc=0 for item in "${thisarray[@]}" do #echo "inc: $inc" #echo "string: $string" #echo "item: $item" #let "inc++" if [ "$string" = "$item" ] then #echo "String=item!" #!!!! return 0 fi done #!!!! return 1 } #readonly -f APSK_Debug____Check_Array_for_String # End of # Function ############ ############ # Function APSK_Debug____See_if_New_Array_Item_is_Unique() { # 2020-09-07 02:21:56. # # Return codes: # # 0: unique # 1: not unique # 2020-09-09 06:07:38. 2 inpvars, 0 outvars: local item="$1" local thisarray=("${!2}") # 2020-09-09 06:07:53. 1 inrvar: local old_item #!!!! [ ${#thisarray[@]} -eq 0 ] && return 0 for old_item in "${thisarray[@]}" do if [ "$old_item" = "$item" ] then #!!!! return 1 fi done #!!!! return 0 } #readonly -f APSK_Debug____See_if_New_Array_Item_is_Unique # End of # Function ############ ############ # Function APSK_Debug____Note_Unique_Tag() { # 2020-09-09 07:10:21. # # Return codes: # # 0 = noted a tag # 1 = didn't note a tag # 2020-09-09 07:09:41. 1 inpvar, 0 outvars: local tag="$1" #local thisarray=("${!2}") # 2020-09-09 07:10:04. 1 inrvar: local result_code #!!!! #[ -z "$tag" ] && return 1 APSK_Debug____See_if_New_Array_Item_is_Unique "$tag" APSK_Debug____All_Unique_Tags_Used[@] result_code="$?" if [ "$result_code" = 0 ] then APSK_Debug____All_Unique_Tags_Used+=( "$tag" ) #!!!! return 0 fi #!!!! return 1 } #readonly -f APSK_Debug____Note_Unique_Tag # End of # Function ############ ############ # Function APSK_Debug____If_Necessary__Quit_This_Debug_Func() { # 2020-09-08 22:13:38. 2020-09-11 02:32:35. 2020-10-30 12:17:43. 2020-12-04 19:14:43. # # This function gets run at the beginning of most # developer-useable debug functions, including: # # decho # # ardecho # hashdecho # # echoar # echohash # # APSK_Debug____Print_All_Unique_Tags_Used # # Decho____Now_In_This_Function # Decho____Back_In_This_Function # Decho____Now_Exiting_This_Function # # backtrace # bt # # forthtrace # ft # # tagged_echo (long name for techo) # # tagged_eval (long name for teval) # dexit # 2020-09-07 01:49:56. # # Return codes: # # 0: should quit this debug function # 1: shouldn't quit #!!!! [ "$APSK_DEBUG_MODE" != true ] && return 0 # 2020-09-07 02:02:02. 1 inpvar, 0 outvars: local tag="$1" APSK_Debug____Note_Unique_Tag "$tag" # 2020-09-07 01:48:48. 3 inrvars: local Function_Name local Debug_Function_Name local result_code #@@@@ local Function_Name="${FUNCNAME[2]}" local Debug_Function_Name="${FUNCNAME[1]}" #@@@@ #echo "Debug_Function_Name: $Debug_Function_Name" case "$Debug_Function_Name" in "decho") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "decho" "$tag" "$Function_Name" result_code="$?" ;; #---- "ardecho") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "ardecho" "$tag" "$Function_Name" result_code="$?" ;; #---- "hashdecho") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "hashdecho" "$tag" "$Function_Name" result_code="$?" ;; #---- "echoar") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "echoar" "$tag" "$Function_Name" result_code="$?" ;; #---- "echohash") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "echohash" "$tag" "$Function_Name" result_code="$?" ;; #---- "APSK_Debug____Print_All_Unique_Tags_Used") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "APSK_Debug____Print_All_Unique_Tags_Used" "$tag" "$Function_Name" result_code="$?" ;; #---- "Decho____Now_In_This_Function") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "Decho____Now_In_This_Function" "$tag" "$Function_Name" result_code="$?" ;; #---- "Decho____Back_In_This_Function") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "Decho____Back_In_This_Function" "$tag" "$Function_Name" result_code="$?" ;; #---- "Decho____Now_Exiting_This_Function") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "Decho____Now_Exiting_This_Function" "$tag" "$Function_Name" result_code="$?" ;; #---- "bt"|"backtrace") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "bt" "$tag" "$Function_Name" result_code="$?" ;; #---- "ft"|"forthtrace") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "ft" "$tag" "$Function_Name" result_code="$?" ;; #---- "techo"|"tagged_echo") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "techo" "$tag" "$Function_Name" result_code="$?" ;; #---- "teval"|"tagged_eval") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "teval" "$tag" "$Function_Name" result_code="$?" ;; #---- "dexit") APSK_Debug____Check_if_This_Debug_Function_is_Allowed "dexit" "$tag" "$Function_Name" result_code="$?" ;; #---- *) APSK_Debug____Console_and_Copyable_Dialog_Box____Error_Message " APSK Debug: Aborting because the function APSK_Debug____If_Necessary__Quit_This_Debug_Func() was called by a function not recognized as an APSK debug function! The unrecognized function was: $Debug_Function_Name()" "Unusual APSK Debug Error" #!!!! exit 199 esac #!!!! [ "$result_code" = 0 ] && return 1 #!!!! return 0 } #readonly -f APSK_Debug____If_Necessary__Quit_This_Debug_Func # End of # Function ############ ############ # Function APSK_Debug____Check_if_This_Debug_Function_is_Allowed() { # 2020-09-11 02:55:50. Return codes: # # 0 - this debug function is allowed # 1 - this debug function isn't allowed # 2020-09-08 18:36:08. 3 inpvars, 0 outvars: local Debug_Function_Name="$1" local tag="$2" local Function_Name="$3" # 2020-09-08 18:36:18. 3 inrvars: local tag_result_code local function_result_code local dechoer_result_code case "$Debug_Function_Name" in #---- "decho") #!!!! [ "$APSK_Debug____should_allow_decho" != true ] && return 1 ;; #---- "ardecho") #!!!! [ "$APSK_Debug____should_allow_ardecho" != true ] && return 1 ;; #---- "hashdecho") #!!!! [ "$APSK_Debug____should_allow_hashdecho" != true ] && return 1 ;; #---- "echoar") #!!!! [ "$APSK_Debug____should_allow_echoar" != true ] && return 1 ;; #---- "echohash") #!!!! [ "$APSK_Debug____should_allow_echohash" != true ] && return 1 ;; #---- "APSK_Debug____Print_All_Unique_Tags_Used") #!!!! [ "$APSK_Debug____should_allow_printing_of_unique_tags" != true ] && return 1 ;; #---- "Decho____Now_In_This_Function") #!!!! [ "$APSK_Debug____should_print_Now_in_Function_headers" != true ] && return 1 ;; #---- "Decho____Back_In_This_Function") #!!!! [ "$APSK_Debug____should_print_Back_in_Function_headers" != true ] && return 1 ;; #---- "Decho____Now_Exiting_This_Function") #!!!! [ "$APSK_Debug____should_print_Now_Exiting_This_Function_footers" != true ] && return 1 ;; #---- "bt"|"backtrace") #!!!! [ "$APSK_Debug____should_allow_backtrace" != true ] && return 1 ;; #---- "ft"|"forthtrace") #!!!! [ "$APSK_Debug____should_allow_forthtrace" != true ] && return 1 ;; #---- "techo"|"tagged_echo") #!!!! [ "$APSK_Debug____should_allow_tagged_echo" != true ] && return 1 ;; #---- "teval"|"tagged_eval") #!!!! [ "$APSK_Debug____should_allow_tagged_eval" != true ] && return 1 ;; #---- "dexit") #!!!! [ "$APSK_Debug____should_allow_dexit" != true ] && return 1 ;; esac # 2020-09-27 14:53:30. Tags have precedence over everything else. APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Tag "$tag" tag_result_code="$?" #!!!! [ "$tag_result_code" != 2 ] && return "$tag_result_code" # 2020-09-08 18:40:24. 2020-09-11 02:59:37. # # If a tag is definitely included, or or definitely excluded, or # if there's a tag-include list and this tag was left out of it, # we return early without doing function checks. # # But if a tag doesn't fall into any of those categories - # whether the function it's attached to gets run or not # depends on the function includes/excludes or lack thereof. # 2020-09-27 14:54:26. Next, if this is a debug function which dechoes # function headers or footers, we check if it's allowed or not. # # 2020-09-27 15:41:03. These header/footer includes/excludes have precedence # over the function includes/excludes. case "$Debug_Function_Name" in "Decho____Now_In_This_Function"|"Decho____Back_In_This_Function"|"Decho____Now_Exiting_This_Function") APSK_Debug____Check_if_Debug_Should_Proceed_For_Dechoer_of_Function_Header_or_Footer "$Debug_Function_Name" "$Function_Name" dechoer_result_code="$?" #!!!! [ "$dechoer_result_code" != 2 ] && return "$dechoer_result_code" ;; esac # 2020-09-08 01:32:00. Next, checking the function arrays. APSK_Debug____Check_if_Debug_Should_Proceed_Within_This_Function "$Function_Name" function_result_code="$?" #!!!! [ "$function_result_code" -lt 2 ] && return 0 # 2020-09-11 03:00:00. If the function wasn't excluded, # or was in the function-include list, or if there's no # function-include list (in which case being left out of the # include list has no effect) - this debug function is allowed. # 2020-09-08 01:56:12. In any other cases, it's a no. #!!!! return 1 } #readonly -f APSK_Debug____Check_if_This_Debug_Function_is_Allowed # End of # Function ############ ############ # Function APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Tag() { # 2020-09-08 02:56:28. Return codes: # # 0 - calling function should return 1, to immediately proceed # # 1 - calling function should return 0, to immediately skip this tag # # 2 - calling function shouldn't return yet, and should do other checks # to figure out whether to proceed # 2020-09-11 03:04:10. 1 inpvar, 0 outvars: local tag="$1" # 2020-09-11 03:04:20. 1 inrvar: local tag_result_code # 2020-09-08 01:53:07. First, checking the Tags arrays. #echo "Checking tags arrays" APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$tag" APSK_Debug____Tags_to_Include[@] APSK_Debug____Tags_to_Exclude[@] tag_result_code="$?" # 2020-09-08 00:02:43. # # Return codes for tag check above: # # 0 - probably should proceed - # neither included nor excluded # # 1 - definitely should proceed - # definitely included # # 2 - definitely shouldn't proceed - # definitely not included # # 3 - definitely shouldn't proceed - # definitely excluded #echo "tag: '$tag' tag_result_code: $tag_result_code" #!!!! [ "$tag_result_code" = 1 ] && return 0 # 2020-09-08 01:25:55. 1 = a definite yes for the tag, in which # case, it's a definite yes overall without even checking anything else. #!!!! [ "$tag_result_code" = 2 ] && return 1 # 2020-09-08 02:03:45. 2 = definitely not included, which # means there are include tags, which means anything not # included should be skipped. #!!!! [ "$tag_result_code" = 3 ] && return 1 # 2020-09-08 02:08:42. 3 = definitely excluded. # 2020-09-11 03:05:57. If none of the above applies, other # checks need to be done. #!!!! return 2 } #readonly -f APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Tag # End of # Function ############ ############ # Function APSK_Debug____Check_if_Debug_Should_Proceed_For_Dechoer_of_Function_Header_or_Footer() { # 2020-09-08 02:56:28. 2020-09-27 15:03:18. # # Return codes: # # 0 - calling function should return 1, to immediately proceed # # 1 - calling function should return 0, to immediately skip this header or footer # # 2 - calling function shouldn't return yet, and should do other checks # to figure out whether to proceed # 2020-09-27 16:16:09. 2 inpvars, 0 outvars: local Debug_Function_Name="$1" local Function_Name="$2" # 2020-09-27 16:16:13. 4 inrvars: local dechoer_result_code local array_prefix local array_name____includes local array_name____excludes case "$Debug_Function_Name" in #---- "Decho____Now_In_This_Function") array_prefix="APSK_Debug____Function_Headers" # APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$Function_Name" APSK_Debug____Function_Headers_to_Include[@] APSK_Debug____Function_Headers_to_Exclude[@] result_code="$?" ;; #---- "Decho____Back_In_This_Function") array_prefix="APSK_Debug____Back_In_Function_Headers" # APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$Function_Name" APSK_Debug____Back_In_Function_Headers_to_Include[@] APSK_Debug____Back_In_Function_Headers_to_Exclude[@] result_code="$?" ;; #---- "Decho____Now_Exiting_This_Function") array_prefix="APSK_Debug____Function_Footers" #APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$Function_Name" APSK_Debug____Back_In_Function_Headers_to_Include[@] APSK_Debug____Back_In_Function_Headers_to_Exclude[@] result_code="$?" ;; esac array_name____includes="${array_prefix}_to_Include[@]" array_name____excludes="${array_prefix}_to_Exclude[@]" #echo "array_name____includes: $array_name____includes" #echo "array_name____excludes: $array_name____excludes" APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$Function_Name" "$array_name____includes" "$array_name____excludes" dechoer_result_code="$?" #echo; echo "$Debug_Function_Name $Function_Name dechoer_result_code: $dechoer_result_code" # 2020-09-08 00:02:43. 2020-09-27 15:43:22. # # Return codes for the check above: # # 0 - probably should proceed - # neither included nor excluded # # 1 - definitely should proceed - # definitely included # # 2 - definitely shouldn't proceed - # definitely not included # # 3 - definitely shouldn't proceed - # definitely excluded #!!!! [ "$dechoer_result_code" = 1 ] && return 0 # 2020-09-08 01:25:55. 2020-09-27 15:46:16. # # 1 = a definite yes for this dechoer, in which # case, it's a definite yes overall without even checking anything else. #!!!! [ "$dechoer_result_code" = 2 ] && return 1 # 2020-09-08 02:03:45. 2020-09-27 15:46:21. # # 2 = definitely not included, which # means there are included dechoers, which means anything not # included should be skipped. #!!!! [ "$dechoer_result_code" = 3 ] && return 1 # 2020-09-08 02:08:42. 3 = definitely excluded. # 2020-09-11 03:05:57. If none of the above applies, other # checks need to be done. #!!!! return 2 } #readonly -f APSK_Debug____Check_if_Debug_Should_Proceed_For_Dechoer_of_Function_Header_or_Footer # End of # Function ############ ############ # Function APSK_Debug____Check_if_Debug_Should_Proceed_Within_This_Function() { # 2020-09-11 03:06:23. 1 inpvar, 0 outvars: local Function_Name="$1" # 2020-09-11 03:06:34. 1 inrvar: local result_code APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category "$Function_Name" APSK_Debug____Functions_to_Include[@] APSK_Debug____Functions_to_Exclude[@] result_code="$?" #!!!! return "$result_code" } #readonly -f APSK_Debug____Check_if_Debug_Should_Proceed_Within_This_Function # End of # Function ############ ############ # Function APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category() { # 2020-09-08 00:02:43. # # Return codes: # # 0 - probably should proceed - # neither included nor excluded # # 1 - definitely should proceed - # definitely included # # 2 - definitely shouldn't proceed - # definitely not included # # 3 - definitely shouldn't proceed - # definitely excluded # 2020-09-11 03:08:01. 3 inpvars, 0 outvars: local string="$1" local array_of_includes=("${!2}") local array_of_excludes=("${!3}") # 2020-09-11 03:08:27. 1 inrvar: local result_code # echo; echo # echo "string: $string 2: $2 3: $3" # echo "includes array count: ${#array_of_includes[@]}" # echo "excludes array count: ${#array_of_excludes[@]}" # echo; echo # 2020-09-07 23:57:50. If there are no includes or excludes, anything goes. if [ ${#array_of_includes[@]} -eq 0 ] then if [ ${#array_of_excludes[@]} -eq 0 ] then #!!!! return 0 fi fi if [ ${#array_of_includes[@]} -eq 0 ] then # 2020-09-07 01:58:37. No strings to include, so we check for strings to exclude. APSK_Debug____Check_Array_for_String "$string" array_of_excludes[@] result_code="$?" #!!!! [ "$result_code" = 0 ] && return 3 # 2020-09-07 01:58:47. Should quit if a string to exclude is found. #!!!! return 0 else # 2020-09-07 01:58:52. There are strings to include, so we ignore anything not included. APSK_Debug____Check_Array_for_String "$string" array_of_includes[@] result_code="$?" #!!!! [ "$result_code" = 0 ] && return 1 # 2020-09-07 01:59:08. Shouldn't quit if a string to include is found. #!!!! return 2 fi } #readonly -f APSK_Debug____Check_if_Debug_Should_Proceed_For_This_Category # End of # Function ############ ################################### # # 2020-12-04 18:41:34. # # Stuff originally from APSK Simple Dialog Displayer: # # ############ # Function APSK_Debug____Wrap_Text() { local -r message="$1" local -r columns="$2" #---- local wrapped_message ############################## wrapped_message=$(echo "$message" | fold --width $columns --spaces) retval="$wrapped_message" } #readonly -f APSK_Debug____Wrap_Text # End of # Function ############ ############ # Function APSK_Debug____Console____Error_Message() { local -r error_message="$1" local -r should_omit_heading="$2" ############################## if [ ! -z "$should_omit_heading" ] then retval="$error_message" >&2 echo "$error_message" #!!!! return 0 fi #~ retval="$Script_Title error: #~ #~ $error_message" retval="$error_message" >&2 echo "$retval" #!!!! return 0 } #readonly -f APSK_Debug____Console____Error_Message # End of # Function ############ ############ # Function APSK_Debug____Dialog_Box____Copyable_Message() { #!!!! [ "$APSK____should_display_GUI_dialog_boxes" = false ] && return 0 #---- local -r message="$1" local -r title="$2" local width="$3" local height="$4" #@@@@ [ -z "$width" ] && width=-1 [ -z "$height" ] && height=-1 ############################## echo "$message" | Xdialog --title "$title" --textbox - "$height" "$width" case "$?" in 0) #echo "OK" ;; 255) #echo "Box closed" ;; esac #!!!! return 0 } #readonly -f APSK_Debug____Dialog_Box____Copyable_Message # End of # Function ############ ############ # Function APSK_Debug____Dialog_Box____Copyable_Error_Message() { #!!!! [ "$APSK____should_display_GUI_dialog_boxes" = false ] && return 0 local -r error_message="$1" local -r title="$2" local width="$3" local height="$4" if [ -z "$title" ] then error_title="" fi ############################## APSK_Debug____Dialog_Box____Copyable_Message "$error_message" "$error_title" "$width" "$height" } #readonly -f APSK_Debug____Dialog_Box____Copyable_Error_Message # End of # Function ############ ############ # Function APSK_Debug____Console_and_Copyable_Dialog_Box____Error_Message() { local -r error_message="$1" local error_title="$2" local -r width="$3" local -r height="$4" ############################## APSK_Debug____Console____Error_Message "$error_message" #echo; echo; echo "APSK____should_display_GUI_dialog_boxes: $APSK____should_display_GUI_dialog_boxes" #!!!! [ "$APSK____should_display_GUI_dialog_boxes" = false ] && return 0 APSK_Debug____Wrap_Text "$error_message" 80 APSK_Debug____Dialog_Box____Copyable_Error_Message "$retval" "$error_title" "$height" "$width" #!!!! return 0 } #readonly -f APSK_Debug____Console_and_Copyable_Dialog_Box____Error_Message # End of # Function ############