Re: 4.4 change in behavior from 4.3: how to catch unset when using ${#length}

2016-10-28 Thread Chet Ramey
On 10/28/16 3:43 PM, L. A. Walsh wrote:

> 
>Please, I'm not running in posix mode, so how would their rules
> apply?  

Because you're using `bash', not `walsh'?

Bash is a posix shell. Would the bash documentation convince you? You
could go read that instead.

> Just because posix defines something a certain way
> doesn't mean it should apply in a non-posix mode shell.

Come on, don't be willfully obtuse.  You know better than this.  Posix mode
doesn't mean "turning it off does everything the way Linda wants."

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Is this the expected behaviour for nameref in Bash 4.4 now?

2016-10-28 Thread Jack Kuan
thank you for the insight, it's very helpful!

On Oct 28, 2016 10:01 AM, "Chet Ramey"  wrote:

On 10/20/16 2:45 PM, kjk...@gmail.com wrote:
> set -x
>
> var_123=123
> f() {
> while (( $# )); do
> shift
> local var=var_123
> local -n var=$var; : status is $?
> local -p
> : var is $var
> done
> }
>
> f one two
>
>
> Running above script gives the follow output:
>
> + var_123=123
> + f one two
> + ((  2  ))
> + shift
> + local var=var_123
> + local -n var=var_123

`var' is a local nameref with value var_123

> + : status is 0
> + local -p
> var=var_123
> + : var is 123

Since var is a nameref, it expands to $var_123, which is 123

> + ((  1  ))
> + shift
> + local var=var_123

var doesn't get unset; it's still a nameref with value var_123.  Setting
the local attribute on an existing local variable doesn't unset any of
the variable's attributes.  You have to actually unset the variable to
do that.

> + local -n var=123
> ./x.sh: line 10: local: `123': invalid variable name for name reference

So now you try to assign `123' as the value of a nameref.  That would
cause subsequent attempts to assign to var to attempt to create and
assign to a variable named `123', which is invalid.  Bash-4.3 didn't
have enough error checking and would create variables with invalid names
in situations like this.

> + : status is 1
> + local -p
> var=var_123

This is probably where the confusion comes.  `local -p' doesn't print other
variable attributes.  If you had used `declare -p | grep var=' between the
two calls to `local' you would have seen that `var' had the nameref
attribute.

> + : var is 123
> + ((  0  ))

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~
chet/


Re: 4.4 change in behavior from 4.3: how to catch unset when using ${#length}

2016-10-28 Thread L. A. Walsh



Chet Ramey wrote:

On 10/24/16 7:32 PM, L. A. Walsh wrote:

  

   I don't understand the ambiguity.  If param= "#obj[@]", then it
is clear to me that the user wants the length of an array named "obj".



Stop there.  In something like ${#obj[@]}, `param' is `obj[@]'.  The
`${#param}' is a clearly-defined word expansion, separate from the
`[:]-' forms:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

That's what we're talking about here.
  


   Please, I'm not running in posix mode, so how would their rules
apply?  Just because pi=3 under Indiana state rules some number of years
ago, doesn't mean it is.  Just because posix defines something a certain way
doesn't mean it should apply in a non-posix mode shell.





Re: Race in bash-4.3 'typeset'?

2016-10-28 Thread Martijn Dekker
Op 28-10-16 om 15:00 schreef Chet Ramey:
> On 10/25/16 12:40 AM, Martijn Dekker wrote:
>> Try simply testing the exit status of 'typeset -p' or 'declare -p'. If
>> the variable is not declared, it exits unsuccessfully.
>>
>> if typeset -p "$var" >/dev/null 2>&1 && [[ ! -v $var ]]
>> then ...
>>
>> As far as I can tell, this is not documented in 'help' or in the info
>> page, by the way. Perhaps it should be.
> 
> It's documented.  The man page, for instance, says:
> 
> "The return value is 0 unless ... one of the names is not a valid shell
> variable name"
> 
> which handles both the "not correctly formed" and "not found" cases.

To me that seems like a far-fetched interpretation. The way I read it,
if a variable is not declared, that does not imply its name is not
valid. An invalid name would mean it is impossible to declare it. I
think adding ", the variable is not declared" would prevent
misunderstandings.

- M.




Re: Is this the expected behaviour for nameref in Bash 4.4 now?

2016-10-28 Thread Chet Ramey
On 10/20/16 2:45 PM, kjk...@gmail.com wrote:
> set -x
> 
> var_123=123
> f() {
> while (( $# )); do
> shift
> local var=var_123
> local -n var=$var; : status is $?
> local -p
> : var is $var
> done
> }
> 
> f one two
> 
> 
> Running above script gives the follow output:
> 
> + var_123=123
> + f one two
> + ((  2  ))
> + shift
> + local var=var_123
> + local -n var=var_123

`var' is a local nameref with value var_123

> + : status is 0
> + local -p
> var=var_123
> + : var is 123

Since var is a nameref, it expands to $var_123, which is 123

> + ((  1  ))
> + shift
> + local var=var_123

var doesn't get unset; it's still a nameref with value var_123.  Setting
the local attribute on an existing local variable doesn't unset any of
the variable's attributes.  You have to actually unset the variable to
do that.

> + local -n var=123
> ./x.sh: line 10: local: `123': invalid variable name for name reference

So now you try to assign `123' as the value of a nameref.  That would
cause subsequent attempts to assign to var to attempt to create and
assign to a variable named `123', which is invalid.  Bash-4.3 didn't
have enough error checking and would create variables with invalid names
in situations like this.

> + : status is 1
> + local -p
> var=var_123

This is probably where the confusion comes.  `local -p' doesn't print other
variable attributes.  If you had used `declare -p | grep var=' between the
two calls to `local' you would have seen that `var' had the nameref
attribute.

> + : var is 123
> + ((  0  ))

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Race in bash-4.3 'typeset'?

2016-10-28 Thread Chet Ramey
On 10/25/16 12:19 PM, Stuart Shelton wrote:

> Thanks for the suggestion!
> 
> However, it doesn’t appear to be able to detect local variables (is this 
> intentional or a bug?):

It's a bug; fixed in bash-4.4.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Is this the expected behaviour for nameref in Bash 4.4 now?

2016-10-28 Thread Chet Ramey
On 10/20/16 7:44 PM, Jack Kuan wrote:
> Thanks for replying.
> 
> I was expecting that in the second iteration of the loop, the
> local var=var_123  command would make var a normal variable again with
> value "var_123"

This is the bad assumption.  You didn't unset `var' before doing this, so
it retains its local attribute and its nameref attribute.  Trying to make
a local variable from an already-local variable is a no-op.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Race in bash-4.3 'typeset'?

2016-10-28 Thread Chet Ramey
On 10/25/16 12:40 AM, Martijn Dekker wrote:
> Op 25-10-16 om 00:42 schreef Stuart Shelton:
>> Failing this, is there any alternative to ‘typeset’ to list a
>> variable declared as local to a function but which has not yet been
>> assigned a value?
> 
> Try simply testing the exit status of 'typeset -p' or 'declare -p'. If
> the variable is not declared, it exits unsuccessfully.
> 
> if typeset -p "$var" >/dev/null 2>&1 && [[ ! -v $var ]]
> then ...
> 
> As far as I can tell, this is not documented in 'help' or in the info
> page, by the way. Perhaps it should be.

It's documented.  The man page, for instance, says:

"The return value is 0 unless ... one of the names is not a valid shell
variable name"

which handles both the "not correctly formed" and "not found" cases.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Race in bash-4.3 'typeset'?

2016-10-28 Thread Chet Ramey
On 10/25/16 4:09 PM, Stuart Shelton wrote:

> The cases appear, purely by inspection, to be:
> 
> Not declared: trivially, `typeset -p` doesn’t include the value;
> Declared (even as local) but unassigned: `typeset -p` includes "declare -- 
> varname";
> Declared and assigned: `typeset -p` includes "declare -- varname=‘value’”
> 
> … although how much of this is by design and how much by chance I’m not sure 
> ;)

It's all by design.  The idea is that you can use `typeset -p' to save and
restore the variable state.  It's imperfect, I'm sure, and there are
probably missing edge cases, but that's the idea.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: 4.4 change in behavior from 4.3: how to catch unset when using ${#length}

2016-10-28 Thread Chet Ramey
On 10/24/16 7:32 PM, L. A. Walsh wrote:

>I don't understand the ambiguity.  If param= "#obj[@]", then it
> is clear to me that the user wants the length of an array named "obj".

Stop there.  In something like ${#obj[@]}, `param' is `obj[@]'.  The
`${#param}' is a clearly-defined word expansion, separate from the
`[:]-' forms:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

That's what we're talking about here.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/