[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Passing variables by reference conflicts with local
From: |
Freddy Vulto |
Subject: |
Re: Passing variables by reference conflicts with local |
Date: |
Sun, 2 May 2010 00:19:25 +0200 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
Here's another revised version.
It seems like a lot of bookkeeping (I wish we could transfer to bash?),
but I don't see another way if you want to pass "variables by reference"
in a bash library and prevent both yourself and public users from being
bitten by a conflict with a local variable - other than obfuscating your
library local variables.
I hope we can get it right, so it can be used with a revised version of
the `_get_cword' function of the bash-completion package (= blackbox).
There are still some questions:
I have to give local variables a value (append an equal sign) in order
to get them listed with 'local' in "blackbox()". Is there a bash
builtin which lists all defined local variable names, even those not
having a value yet?
I also want to let 'blackbox' return array variables, which doesn't seem
to be possible with the 'printf/read' workarounds, so I have to use
'eval' and still need to sanitize the array variable names. What's
considered good sanitizing: I'm now checkin for $' \n\t;:$' in
"_blackbox_var_sane()"?
Other changes are:
Called private function _after_ collission test.
Output error messages to stderr and return non-zero value.
Added check to enforce private function "_blackbox()" is ALWAYS called
via public "blackbox()".
I thought about whether private function "_blackbox()" should also have
a check for having local conflicts, but I figured this should be covered
by blackbox unit tests :-)
Added an input parameter and return value for the sake of completeness.
Here's the code:
# Output error of variable by reference conflicting with local
# Params: $1 Variable name causing conflict
# $2 Function in which conflict occurs
_blackbox_var_conflict() {
echo "ERROR: variable name conflicts with local variable:"\
"'$1', in function: $2()" 1>&2
}
# Check whether private function is being called by public interface
# Params: $1 Function name of public interface
# Return: False (1) if error
_blackbox_called_by() {
if [[ ${FUNCNAME[2]} != $1 ]]; then
echo "ERROR: ${FUNCNAME[1]}() MUST be called by $1()" 1>&2
return 1
fi
}
# Check whether variable is sane to be used as eval assignment
# Param: $1 Variable name
# Return: False (1) if not sane
_blackbox_var_sane() {
if [[ ! $1 || ${1//[$' \n\t;:$']} != $1 ]]; then
echo "ERROR: invalid identifier: '$1'"\
"passed to function: ${FUNCNAME[1]}()" 1>&2
return 1
fi
}
# Private library function. Do not call directly. See blackbox()
_blackbox() {
_blackbox_called_by blackbox || return 1
local a b c d e f g h i j arr=( foo "bar cee" )
# ...
# Lots of complicated library code here
# ...
[[ $2 ]] && printf -v $2 %s b # Return value
_blackbox_var_sane "$3" && # Return array value
eval $3=\( \"\${arr[@]}\" \) || return 1
return 0 # Return exit status
}
# Param: $1 input argument
# Param: $2 variable name to return value to
# Param: $3 variable name to return array value to
# Public library function
blackbox() {
# NOTE: Give all locals a value so they're listed with 'local'
local __2= __3= __x= __v= IFS=$'\n'
# Check arguments conflicting with locals
for __v in $(local); do
case ${__v%=*} in $2|$3)
_blackbox_var_conflict ${__v%=*} $FUNCNAME; return 1;;
esac
done
_blackbox "$1" __2 __3 # Call private function
__x=$? # Catch exit status
[[ $2 ]] && printf -v $2 %s "$__2" # Return value
_blackbox_var_sane "$3" && # Return array value
eval $3=\( \"\${__3[@]}\" \) || return 1
return $__x # Return exit status
}
blackbox i a b; printf $'%s\n' $a "${b[@]}" # Outputs vars all right
blackbox i __2 __3 # Outputs error
d='ls /;true'; blackbox i "$d" "$d" # No oops
_blackbox a # Force public access
Freddy Vulto
http://fvue.nl/wiki/Bash:_passing_variables_by_reference
- Re: Passing variables by reference conflicts with local, Freddy Vulto, 2010/05/01
- Re: Passing variables by reference conflicts with local, Dennis Williamson, 2010/05/01
- Re: Passing variables by reference conflicts with local, Pierre Gaston, 2010/05/01
- Re: Passing variables by reference conflicts with local, Freddy Vulto, 2010/05/01
- Re: Passing variables by reference conflicts with local, Dennis Williamson, 2010/05/01
- Re: Passing variables by reference conflicts with local,
Freddy Vulto <=
- Re: Passing variables by reference conflicts with local, Dennis Williamson, 2010/05/01
- Re: Passing variables by reference conflicts with local, Freddy Vulto, 2010/05/02
- Re: Passing variables by reference conflicts with local, Dennis Williamson, 2010/05/02
- Re: Passing variables by reference conflicts with local, Freddy Vulto, 2010/05/03
- Re: Passing variables by reference conflicts with local, Freddy Vulto, 2010/05/04
- Re: Passing variables by reference conflicts with local, Chet Ramey, 2010/05/05
- Re: Passing variables by reference conflicts with local, Chet Ramey, 2010/05/04
- Re: Passing variables by reference conflicts with local, Chet Ramey, 2010/05/02
- Re: Passing variables by reference conflicts with local, Matthew Woehlke, 2010/05/03
Re: Passing variables by reference conflicts with local, Greg Wooledge, 2010/05/03