Re: sourcing script file from inside a function doesn't work anymore
Hi all, Chet, I compiled a 4.3.11 from scratch. Then I applied your fix and compiled again. I executed my test program I attached in my bug report and it works like a charm and like bash 4.2. Now I'm going to try with several scripts I wrote which were affected by this bug... Thank you all for your time Best regards Jean-Philippe Le 12/05/2014 17:31, Chet Ramey a écrit : On 5/12/14, 9:33 AM, Geir Hauge wrote: 2014-05-12 14:11 GMT+02:00 Greg Wooledge : On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote: Now, I source it from inside a function: I obtain following error message: bash: declare: tmp: not found I think this problem raises in the particular case of involving array variables definitions inside sourced bash script file... cat << "EOF" > "${file_to_be_sourced}" declare -a tmp='([0]="1" [1]="2")' EOF The problem is that you are using "declare" within the file-to-be-sourced. When you source the file inside a function, Bash runs the declare command within the context of the function, where declare has the same meaning as "local". Thus, it makes the variable local to the function. There really is a bug here, a weird one. Using a simplified script, we see that this works as expected: Yep. Thanks for the report. The issue is that the `placeholder' attribute doesn't get unset when the argument is quoted -- it takes a different code path than when it's unquoted. I've attached a patch for people to experiment with. Chet
Re: sourcing script file from inside a function doesn't work anymore
On 5/12/14, 9:33 AM, Geir Hauge wrote: > 2014-05-12 14:11 GMT+02:00 Greg Wooledge : > >> On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote: >>> Now, I source it from inside a function: I obtain following error >> message: >>> bash: declare: tmp: not found >>> I think this problem raises in the particular case of involving array >>> variables definitions inside sourced bash script file... >> >>> cat << "EOF" > "${file_to_be_sourced}" >>> declare -a tmp='([0]="1" [1]="2")' >>> EOF >> >> The problem is that you are using "declare" within the file-to-be-sourced. >> When you source the file inside a function, Bash runs the declare command >> within the context of the function, where declare has the same meaning as >> "local". Thus, it makes the variable local to the function. > > > There really is a bug here, a weird one. Using a simplified script, we > see that this works as expected: Yep. Thanks for the report. The issue is that the `placeholder' attribute doesn't get unset when the argument is quoted -- it takes a different code path than when it's unquoted. I've attached a patch for people to experiment with. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ *** ../bash-4.3-patched/arrayfunc.c 2014-03-28 10:54:21.0 -0400 --- arrayfunc.c 2014-05-12 11:19:00.0 -0400 *** *** 180,183 --- 180,184 FREE (newval); + VUNSETATTR (entry, att_invisible); /* no longer invisible */ return (entry); }
Re: sourcing script file from inside a function doesn't work anymore
On Mon, May 12, 2014 at 03:33:34PM +0200, Geir Hauge wrote: > Oddly, the quotes seem to matter; changing array='(x)' to array=(x) > makes it work... > > $ f() { source <(printf "declare -a array=(x); declare -p array\n"); }; f > declare -a array='([0]="x")' OK, this also happens on my system. In fact this is the first time I've ever seen array='(...)' instead of array=(...) and I had no idea the quoted version works outside of a function. It seems like an incredibly strange syntax; without the explicit "declare -a" it would be initializing a string variable. But this doesn't change the fact that the original poster is making a local variable inside the function, which won't be visible outside it.
Re: sourcing script file from inside a function doesn't work anymore
2014-05-12 14:11 GMT+02:00 Greg Wooledge : > On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote: > > Now, I source it from inside a function: I obtain following error > message: > > bash: declare: tmp: not found > > I think this problem raises in the particular case of involving array > > variables definitions inside sourced bash script file... > > > cat << "EOF" > "${file_to_be_sourced}" > > declare -a tmp='([0]="1" [1]="2")' > > EOF > > The problem is that you are using "declare" within the file-to-be-sourced. > When you source the file inside a function, Bash runs the declare command > within the context of the function, where declare has the same meaning as > "local". Thus, it makes the variable local to the function. There really is a bug here, a weird one. Using a simplified script, we see that this works as expected: $ source <(printf "declare -a array='(x)'; declare -p array\n") declare -a array='([0]="x")' Wrapping it in a function should yield the same output, but doesn't: $ f() { source <(printf "declare -a array='(x)'; declare -p array\n"); }; f bash: declare: array: not found And while declare -p array fails to "find" the array, declare -p (without a name) does list it: $ f() { source <(printf "declare -a array='(x)'; declare -p array; declare -p | grep array= \n"); }; f bash: declare: array: not found declare -a array='([0]="x")' Oddly, the quotes seem to matter; changing array='(x)' to array=(x) makes it work... $ f() { source <(printf "declare -a array=(x); declare -p array\n"); }; f declare -a array='([0]="x")' -- Geir Hauge
Re: sourcing script file from inside a function doesn't work anymore
On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote: > Now, I source it from inside a function: I obtain following error message: > bash: declare: tmp: not found > I think this problem raises in the particular case of involving array > variables definitions inside sourced bash script file... > cat << "EOF" > "${file_to_be_sourced}" > declare -a tmp='([0]="1" [1]="2")' > EOF The problem is that you are using "declare" within the file-to-be-sourced. When you source the file inside a function, Bash runs the declare command within the context of the function, where declare has the same meaning as "local". Thus, it makes the variable local to the function. If you only put tmp=(...) in the file, it works as you expect. Which is fine as long as you're only using normal arrays, and not associative arrays. If you want to declare associative arrays in this way, you'll need to add the -g option to declare, which is available in bash 4.2 and later. This makes the variable global instead of local. There is unfortunately no middle ground between local and variable if you must use "declare" (i.e. there is no way to mimic tmp=(foo bar) to use default scoping with an associative array because you can't skip the declare -A step on those), nor is there a way to mimic declare -g -A in bash 4.0 or 4.1. The only other option is to issue the declare -A outside of the function (either in global scope, or in the outermost function where the variable needs to be available), and then use tmp=(...) (without a declare) in the file-to-be-sourced.
sourcing script file from inside a function doesn't work anymore
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../. -I.././include -I.././lib -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wall uname output: Linux thioroup8-laptop 3.13.0-26-generic #48-Ubuntu SMP Wed May 7 23:31:02 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 4.3 Patch Level: 11 Release Status: release Description: I write a bash script file containing variables definitions. From another bash script file, I source it from outside any function: in this case all is working fine as expected. Now, I source it from inside a function: I obtain following error message: bash: declare: tmp: not found I think this problem raises in the particular case of involving array variables definitions inside sourced bash script file... Repeat-By: You can execute the script below: #!/bin/bash generate_file_to_be_sourced() { local file_to_be_sourced file_to_be_sourced="$(mktemp)" cat << "EOF" > "${file_to_be_sourced}" declare -a tmp='([0]="1" [1]="2")' EOF echo "${file_to_be_sourced}" } foo() { source "${g_file_to_be_sourced}" if declare -p tmp &> /dev/null && [ "${#tmp[@]}" = "2" ] then echo "test #2: OK" else echo "test #2: NOK" fi unset tmp } echo "bash version: ${BASH_VERSION}" echo declare -r g_file_to_be_sourced="$(generate_file_to_be_sourced)" echo "content of file to be sourced:" cat "${g_file_to_be_sourced}" echo source "${g_file_to_be_sourced}" if declare -p tmp &> /dev/null && [ "${#tmp[@]}" = "2" ] then echo "test #1: OK" else echo "test #1: NOK" fi unset tmp foo rm "${g_file_to_be_sourced}" If you need further informations, don't hesitate to ask me... Best regards Jean-Philippe