[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Passing variables by reference conflicts with local
From: |
Dennis Williamson |
Subject: |
Re: Passing variables by reference conflicts with local |
Date: |
Sat, 1 May 2010 20:12:02 -0500 |
In Bash 3.2.0(1)-release, "local" displays local variables that do and
do not have values. In Bash 4.0.33(1)-release and 4.1.0(1)-release
only those with values are printed. Oops.
f () { local var1 var2=abc var3=; local; }; f
Bash 3:
var1=
var2=abc
var3=
Bash 4:
var2=abc
var3=
So it looks like the only way is to use "local var=" instead of "local var".
I can understand the desire to have blackbox_var_sane "$3" called near
the eval, but it seems to me to make sense to have it fail early
rather than waste "# Lots of complicated library code here" first.
This also applies to the placement in the public function.
You might consider sanitizing using something like this: [[ $1 =~
[_[:alpha:]][_[:alnum:]]* ]] then you won't have to worry that you're
forgetting something.
On Sat, May 1, 2010 at 5:19 PM, Freddy Vulto <fvulto@gmail.com> wrote:
> 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, 2010/05/01
- Re: Passing variables by reference conflicts with local,
Dennis Williamson <=
- 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