From 68306c4c6db7d65c96cd0ae329542c70c5cb0754 Mon Sep 17 00:00:00 2001 From: Tyler Akins Date: Fri, 12 May 2023 08:17:57 -0500 Subject: [PATCH] More Bash 4.x compatibility issues found and fixed --- mo | 30 ++++++++++++++++-------------- tests/assoc-array | 4 ++-- tests/function-args-read | 16 +++++++++++++++- tests/help | 2 +- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/mo b/mo index e10df27..e56ee0e 100755 --- a/mo +++ b/mo @@ -1061,7 +1061,7 @@ mo::evaluate() { ;; *) - moStack=("${moStack[@]}" "$1" "$2") + moStack=(${moStack[@]+"${moStack[@]}"} "$1" "$2") ;; esac @@ -1077,7 +1077,7 @@ mo::evaluate() { else #: Concatenate mo::debug "Concatenating ${#moStack[@]} stack items" - mo::evaluateListOfSingles moResult "${moStack[@]}" + mo::evaluateListOfSingles moResult ${moStack[@]+"${moStack[@]}"} fi local "$moTarget" && mo::indirect "$moTarget" "$moResult" @@ -1310,10 +1310,12 @@ mo::evaluateFunction() { if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then mo::debug "Function arguments are allowed" - for moTemp in "${moArgs[@]}"; do - mo::escape moTemp "$moTemp" - moFunctionCall="$moFunctionCall $moTemp" - done + if [[ ${#moArgs[@]} -gt 0 ]]; then + for moTemp in "${moArgs[@]}"; do + mo::escape moTemp "$moTemp" + moFunctionCall="$moFunctionCall $moTemp" + done + fi fi mo::debug "Calling function: $moFunctionCall" @@ -1321,7 +1323,7 @@ mo::evaluateFunction() { #: Call the function in a subshell for safety. Employ the trick to preserve #: whitespace at the end of the output. moContent=$( - export MO_FUNCTION_ARGS=("${moArgs[@]}") + export MO_FUNCTION_ARGS=(${moArgs[@]+"${moArgs[@]}"}) echo -n "$moContent" | eval "$moFunctionCall ; moFunctionResult=\$? ; echo -n '.' ; exit \"\$moFunctionResult\"" ) || { moFunctionResult=$? @@ -1767,7 +1769,7 @@ mo::tokenizeTagContents() { "$moTerminator"*) mo::debug "Found terminator" - local "$1" && mo::indirectArray "$1" "$moTokenCount" "${moResult[@]}" + local "$1" && mo::indirectArray "$1" "$moTokenCount" ${moResult[@]+"${moResult[@]}"} return ;; @@ -1775,7 +1777,7 @@ mo::tokenizeTagContents() { #: Do not tokenize the open paren - treat this as RPL MO_UNPARSED=${MO_UNPARSED:1} mo::tokenizeTagContents moTemp ')' - moResult=("${moResult[@]}" "${moTemp[@]:1}" PAREN "${moTemp[0]}") + moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]:1}" PAREN "${moTemp[0]}") MO_UNPARSED=${MO_UNPARSED:1} ;; @@ -1783,7 +1785,7 @@ mo::tokenizeTagContents() { #: Do not tokenize the open brace - treat this as RPL MO_UNPARSED=${MO_UNPARSED:1} mo::tokenizeTagContents moTemp '}' - moResult=("${moResult[@]}" "${moTemp[@]:1}" BRACE "${moTemp[0]}") + moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]:1}" BRACE "${moTemp[0]}") MO_UNPARSED=${MO_UNPARSED:1} ;; @@ -1793,17 +1795,17 @@ mo::tokenizeTagContents() { "'"*) mo::tokenizeTagContentsSingleQuote moTemp - moResult=("${moResult[@]}" "${moTemp[@]}") + moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}") ;; '"'*) mo::tokenizeTagContentsDoubleQuote moTemp - moResult=("${moResult[@]}" "${moTemp[@]}") + moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}") ;; *) mo::tokenizeTagContentsName moTemp - moResult=("${moResult[@]}" "${moTemp[@]}") + moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}") ;; esac @@ -1947,7 +1949,7 @@ mo::tokenizeTagContentsSingleQuote() { # Save the original command's path for usage later MO_ORIGINAL_COMMAND="$(cd "${BASH_SOURCE[0]%/*}" || exit 1; pwd)/${BASH_SOURCE[0]##*/}" -MO_VERSION="3.0.1" +MO_VERSION="3.0.2" # If sourced, load all functions. # If executed, perform the actions as expected. diff --git a/tests/assoc-array b/tests/assoc-array index cf73494..338ef0b 100755 --- a/tests/assoc-array +++ b/tests/assoc-array @@ -3,7 +3,8 @@ cd "${0%/*}" || exit 1 . ../run-tests declare -A repo -repo[resque]="Resque" +# The order of the array elements can be shuffled depending on the version of +# Bash. Keeping this to a minimal set and alphabetized seems to help. repo[hub]="Hub" repo[rip]="Rip" export repo @@ -18,7 +19,6 @@ expected() { cat <hub - Hub rip - Rip - resque - Resque EOF } diff --git a/tests/function-args-read b/tests/function-args-read index e75080f..cb256ca 100755 --- a/tests/function-args-read +++ b/tests/function-args-read @@ -6,7 +6,21 @@ testArgs() { local args # shellcheck disable=SC2031 args=$(declare -p MO_FUNCTION_ARGS) - echo -n "${args#*=}" + + # The output from declare -p could look like these + # declare -a MO_FUNCTION_ARGS=([0]="one") + # declare -ax MO_FUNCTION_ARGS='([0]="one")' + # Trim leading declare statement and variable name + args="${args#*=}" + + # If there are any quotes, remove them. The function arguments will always + # be an array. + if [[ "${args:0:1}" == "'" ]]; then + args=${args#\'} + args=${args%\'} + fi + + echo -n "$args" } template() { cat <