need ability to tell if array is associative or not - bug?

2014-08-29 Thread Jason Vas Dias
Good day list -

There seems to be no way of testing if an array variable is associative or not ,
yet attempting to make associative assigments to a normal array results in a
syntax error .

I have something like:

declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
function f()
{  declare -n an_array=$1;
   local type=$2;
   case $type in
 $TYPE_ASSOC)
  an_array['some_value']=1;


}



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Greg Wooledge
On Fri, Aug 29, 2014 at 03:07:40PM +0100, Jason Vas Dias wrote:
> There seems to be no way of testing if an array variable is associative or not

$ unset a b; declare -A a; a[1]=foo; b=(an array); declare -p a b
declare -A a='([1]="foo" )'
declare -a b='([0]="an" [1]="array")'



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Jason Vas Dias
Sorry, mailer sent previous mail before I was ready. Reposting.

Good day list -

There seems to be no way of testing if an array variable is associative or not ,

I have something like:

declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
function f()
{  declare -n an_array=$1;
   local type=$2;
   case $type in
 $TYPE_ASSOC)
  an_array['some_value']=1;
  ;;
 $TYPE_ARRAY)
  an_array[0]=1;
   esac
   }

Now, if I call :
   declare -a my_array();  f my_array $TYPE_ASSOC;
I'll end up with no 'some_value' subscript in array.

It would be great if bash could provide some '-A'  conditional
expression operator
to test if a variable is an associative array or not .
Or perhaps 'declare -A identifier' could return non-zero if
'identifier' was not previously defined as an associative array, as
declare -F does for functions ?
Or is there some way to test if a variable is an associative array or not?

Thanks & Regards,
Jason


On 8/29/14, Jason Vas Dias  wrote:
> Good day list -
>
> There seems to be no way of testing if an array variable is associative or
> not ,
> yet attempting to make associative assigments to a normal array results in
> a
> syntax error .
>
> I have something like:
>
> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
> function f()
> {  declare -n an_array=$1;
>local type=$2;
>case $type in
>  $TYPE_ASSOC)
>   an_array['some_value']=1;
>
>
> }
>



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Chet Ramey
On 8/29/14, 10:21 AM, Jason Vas Dias wrote:
> Sorry, mailer sent previous mail before I was ready. Reposting.
> 
> Good day list -
> 
> There seems to be no way of testing if an array variable is associative or 
> not ,
> 
> I have something like:
> 
> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
> function f()
> {  declare -n an_array=$1;
>local type=$2;
>case $type in
>  $TYPE_ASSOC)
>   an_array['some_value']=1;
>   ;;
>  $TYPE_ARRAY)
>   an_array[0]=1;
>esac
>}
> 
> Now, if I call :
>declare -a my_array();  f my_array $TYPE_ASSOC;

Syntax errors aside, isn't this pretty clearly a programming error?  I
mean, you've passed the wrong type.

I can maybe see the value in being able to write code that is able to
catch these kinds of errors without parsing the output of `declare', but
it's a big stretch to call this a bug.

> I'll end up with no 'some_value' subscript in array.
> 
> It would be great if bash could provide some '-A'  conditional
> expression operator
> to test if a variable is an associative array or not .
> Or perhaps 'declare -A identifier' could return non-zero if
> 'identifier' was not previously defined as an associative array, as
> declare -F does for functions ?

It already does that when you attempt to convert an indexed array to an
associative array, and prints an error message to drive the point home.
The problem with doing it in the general case is that the semantics of
converting a scalar to an associative array are already well-defined.

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/



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Jason Vas Dias
Actually, this appears to be a bit more involved.
What I was actually trying to work out was
the bash error that occurs with :

$( function f()
{
local an_array=$1;
local value='1.0';
local v=value;
local ev='['"'"'value'"'"']='"'""${!v}""'";
eval ${an_array}='('"$ev"')';
}
  declare -a my_array;
  set -x; f my_array;
)
+ f my_array
+ local an_array=my_array
+ local value=1.0
+ local v=value
+ local 'ev=['\''value'\'']='\''1.0'\'''
+ eval 'my_array=(['\''value'\'']='\''1.0'\'')'
++ my_array=(['value']='1.0')
bash: 1.0: syntax error: invalid arithmetic operator (error token is ".0")

This error does not happen if the array was originally declared associative:

$ ( function f()  {   local an_array=$1; local value='1.0';
 local v=value; local ev='['"'"'value'"'"']='"'""${!v}""'";
eval ${an_array}='('"$ev"')'; };
declare -A my_array; set -x; f my_array )
+ f my_array
+ local an_array=my_array
+ local value=1.0
+ local v=value
+ local 'ev=['\''value'\'']='\''1.0'\'''
+ eval 'my_array=(['\''value'\'']='\''1.0'\'')'
++ my_array=(['value']='1.0')

Nor does the error happen if indirect expansion is not used:

$ ( function f()  {   local an_array=$1; local value='1.0';
 local v=$value;
 local ev='['"'"'value'"'"']='"'""$v""'";
 eval ${an_array}='('"$ev"')'; }; declare -A my_array; set -x; f my_array )
+ f my_array
+ local an_array=my_array
+ local value=1.0
+ local v=1.0
+ local 'ev=['\''value'\'']='\''1.0'\'''
+ eval 'my_array=(['\''value'\'']='\''1.0'\'')'
++ my_array=(['value']='1.0')
$

So I was wondering if there is any way to determine if an array was originally
declared associative or not.

But it appears that there is a bash bug here that is triggered only if the
array was originally declared not associative and an indirect expansion
is involved in setting an array member.

The end result expression being evaluated:
++ my_array=(['value']='1.0')
should never involve an arithmetic expression,
and should be valid regardless if the array is
associative or not .

Any ideas what might be going on here ?

Thanks in advance,
Jason

On 8/29/14, Jason Vas Dias  wrote:
> Sorry, mailer sent previous mail before I was ready. Reposting.
>
> Good day list -
>
> There seems to be no way of testing if an array variable is associative or
> not ,
>
> I have something like:
>
> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
> function f()
> {  declare -n an_array=$1;
>local type=$2;
>case $type in
>  $TYPE_ASSOC)
>   an_array['some_value']=1;
>   ;;
>  $TYPE_ARRAY)
>   an_array[0]=1;
>esac
>}
>
> Now, if I call :
>declare -a my_array();  f my_array $TYPE_ASSOC;
> I'll end up with no 'some_value' subscript in array.
>
> It would be great if bash could provide some '-A'  conditional
> expression operator
> to test if a variable is an associative array or not .
> Or perhaps 'declare -A identifier' could return non-zero if
> 'identifier' was not previously defined as an associative array, as
> declare -F does for functions ?
> Or is there some way to test if a variable is an associative array or not?
>
> Thanks & Regards,
> Jason
>
>
> On 8/29/14, Jason Vas Dias  wrote:
>> Good day list -
>>
>> There seems to be no way of testing if an array variable is associative
>> or
>> not ,
>> yet attempting to make associative assigments to a normal array results
>> in
>> a
>> syntax error .
>>
>> I have something like:
>>
>> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
>> function f()
>> {  declare -n an_array=$1;
>>local type=$2;
>>case $type in
>>  $TYPE_ASSOC)
>>   an_array['some_value']=1;
>>
>>
>> }
>>
>



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Greg Wooledge
On Fri, Aug 29, 2014 at 04:45:30PM +0100, Jason Vas Dias wrote:
> local value='1.0';

> The end result expression being evaluated:
> ++ my_array=(['value']='1.0')
> should never involve an arithmetic expression,
> and should be valid regardless if the array is
> associative or not .

Your index is "value".  In a non-associative array, the index is
evaluated in a math context.  In a math context, a thing that CAN be
treated as a variable name IS treated as a variable name, and this
treatment is recursive.

So you are using an index of 1.0, and this causes the error message.



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Jason Vas Dias
Sorry - forget the bit about indirect expansion - the error only
occurs if the array is originally declared not associative :

$ ( function f()  {   local an_array=$1; local value='1.0';
local ev='['"'"'value'"'"']='"'""$value""'"; eval
${an_array}='('"$ev"')'; }; declare -a my_array; set -x; f my_array )
+ f my_array
+ local an_array=my_array
+ local value=1.0
+ local 'ev=['\''value'\'']='\''1.0'\'''
+ eval 'my_array=(['\''value'\'']='\''1.0'\'')'
++ my_array=(['value']='1.0')
bash: 1.0: syntax error: invalid arithmetic operator (error token is ".0")

$ ( function f()  {   local an_array=$1; local value='1.0';
local ev='['"'"'value'"'"']='"'""$value""'"; eval
${an_array}='('"$ev"')'; }; declare -A my_array; set -x; f my_array )
+ f my_array
+ local an_array=my_array
+ local value=1.0
+ local 'ev=['\''value'\'']='\''1.0'\'''
+ eval 'my_array=(['\''value'\'']='\''1.0'\'')'
++ my_array=(['value']='1.0')
$
(no error) .

And just evaluating :
$ ( declare -a my_array; my_array=(['value']='1.0') )
gives no error either, but there is no 'value' subscript.



On 8/29/14, Jason Vas Dias  wrote:
> Actually, this appears to be a bit more involved.
> What I was actually trying to work out was
> the bash error that occurs with :
>
> $( function f()
> {
> local an_array=$1;
> local value='1.0';
> local v=value;
> local ev='['"'"'value'"'"']='"'""${!v}""'";
> eval ${an_array}='('"$ev"')';
> }
>   declare -a my_array;
>   set -x; f my_array;
> )
> + f my_array
> + local an_array=my_array
> + local value=1.0
> + local v=value
> + local 'ev=['\''value'\'']='\''1.0'\'''
> + eval 'my_array=(['\''value'\'']='\''1.0'\'')'
> ++ my_array=(['value']='1.0')
> bash: 1.0: syntax error: invalid arithmetic operator (error token is ".0")
>
> This error does not happen if the array was originally declared
> associative:
>
> $ ( function f()  {   local an_array=$1; local value='1.0';
>  local v=value; local ev='['"'"'value'"'"']='"'""${!v}""'";
> eval ${an_array}='('"$ev"')'; };
> declare -A my_array; set -x; f my_array )
> + f my_array
> + local an_array=my_array
> + local value=1.0
> + local v=value
> + local 'ev=['\''value'\'']='\''1.0'\'''
> + eval 'my_array=(['\''value'\'']='\''1.0'\'')'
> ++ my_array=(['value']='1.0')
>
> Nor does the error happen if indirect expansion is not used:
>
> $ ( function f()  {   local an_array=$1; local value='1.0';
>  local v=$value;
>  local ev='['"'"'value'"'"']='"'""$v""'";
>  eval ${an_array}='('"$ev"')'; }; declare -A my_array; set -x; f
> my_array )
> + f my_array
> + local an_array=my_array
> + local value=1.0
> + local v=1.0
> + local 'ev=['\''value'\'']='\''1.0'\'''
> + eval 'my_array=(['\''value'\'']='\''1.0'\'')'
> ++ my_array=(['value']='1.0')
> $
>
> So I was wondering if there is any way to determine if an array was
> originally
> declared associative or not.
>
> But it appears that there is a bash bug here that is triggered only if the
> array was originally declared not associative and an indirect expansion
> is involved in setting an array member.
>
> The end result expression being evaluated:
> ++ my_array=(['value']='1.0')
> should never involve an arithmetic expression,
> and should be valid regardless if the array is
> associative or not .
>
> Any ideas what might be going on here ?
>
> Thanks in advance,
> Jason
>
> On 8/29/14, Jason Vas Dias  wrote:
>> Sorry, mailer sent previous mail before I was ready. Reposting.
>>
>> Good day list -
>>
>> There seems to be no way of testing if an array variable is associative
>> or
>> not ,
>>
>> I have something like:
>>
>> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
>> function f()
>> {  declare -n an_array=$1;
>>local type=$2;
>>case $type in
>>  $TYPE_ASSOC)
>>   an_array['some_value']=1;
>>   ;;
>>  $TYPE_ARRAY)
>>   an_array[0]=1;
>>esac
>>}
>>
>> Now, if I call :
>>declare -a my_array();  f my_array $TYPE_ASSOC;
>> I'll end up with no 'some_value' subscript in array.
>>
>> It would be great if bash could provide some '-A'  conditional
>> expression operator
>> to test if a variable is an associative array or not .
>> Or perhaps 'declare -A identifier' could return non-zero if
>> 'identifier' was not previously defined as an associative array, as
>> declare -F does for functions ?
>> Or is there some way to test if a variable is an associative array or
>> not?
>>
>> Thanks & Regards,
>> Jason
>>
>>
>> On 8/29/14, Jason Vas Dias  wrote:
>>> Good day list -
>>>
>>> There seems to be no way of testing if an array variable is associative
>>> or
>>> not ,
>>> yet attempting to make associative assigments to a normal array results
>>> in
>>> a
>>> syntax error .
>>>
>>> I have something like:
>>>
>>> declare -xr TYPE_ARRAY=0 TYPE_ASSOC=1
>>> function f()
>>> {  declare -n an_array=$1;
>>>local type=$2;
>>>case $type in
>>>  $TYPE_ASSOC)
>>> 

Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Chet Ramey
On 8/29/14, 11:45 AM, Jason Vas Dias wrote:

> Nor does the error happen if indirect expansion is not used:

Just to head off a potential question.  This is not the same as the first
example, since my_array is declared as an associative array.

> $ ( function f()  {   local an_array=$1; local value='1.0';
>  local v=$value;
>  local ev='['"'"'value'"'"']='"'""$v""'";
>  eval ${an_array}='('"$ev"')'; }; declare -A my_array; set -x; f my_array 
> )
^^^
|||
> + f my_array
> + local an_array=my_array
> + local value=1.0
> + local v=1.0
> + local 'ev=['\''value'\'']='\''1.0'\'''
> + eval 'my_array=(['\''value'\'']='\''1.0'\'')'
> ++ my_array=(['value']='1.0')
> $

-- 
``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/



Re: need ability to tell if array is associative or not - bug?

2014-08-29 Thread Greg Wooledge
On Fri, Aug 29, 2014 at 05:19:03PM +0100, Jason Vas Dias wrote:
> Aha! Yes, that was it . Thank you!
> I wouldn't have expected expansion to occur for a name in single quotes.
> 
> I still think it would be nice to have the ability to tell if an array has 
> been
> declared associative or not.  What about a 'test -A my_array' operator ?

$ unset a b; declare -A a; a[1]=foo; b=(an array); declare -p a b
declare -A a='([1]="foo" )'
declare -a b='([0]="an" [1]="array")'

If you want to mangle that into a test, it would be something like:

if [[ $(declare -p a) = declare\ -A* ]]; then

I still don't understand what your function is trying to DO, though.
Whatever it is, it looks extremely awkward and painful.

My advice to anyone who is trying to pass the name of an array as an
argument to a function in Bash is usually "Stop!  Use a real programming
language instead."  Even declare -n didn't give us the ability to do
this safely.

If you insist on doing this, you need to check all the user input before
handing it to eval.



Re: minor: "read line" may read several lines if stdin is a tty

2014-08-29 Thread Stephane Chazelas
2014-08-27 15:35:06 -0400, Chet Ramey:
> On 8/27/14, 3:20 PM, Stephane Chazelas wrote:
> 
> > However, one could imagine using bash's read to get data off a
> > tty device not in canonical mode (a serial device used as just a
> > serial device), or any other non-terminal character device for
> > that matter (a "strace bash -c 'read < /dev/urandom'" reveals
> > there's an issue there as well), and that would be more of a
> > problem.
> > 
> > Again, not a big one (hence the [minor] tag) but still a
> > non-POSIX conformance and bash seems to be the only shell with
> > the problem (though ksh93 has its own bugs as usual).
> 
> Well, again you have to rely on the system telling you what's happening.
> Bash tests whether a file descriptor is seekable using, logically
> enough, lseek.  If it doesn't return -1/ESPIPE, bash assumes the fd is
> seekable.  If it does, bash does unbuffered reads.
[...]

OK, sorry, I hadn't realised /dev/random was seekable (though
the seek is a no-op) on Linux.

> (If isatty() returns true, bash does assume that read(2) will return
> newline-delimited records.)
[...]

That assumption is only valid (to some extent, because of lnext)
if the terminal is in icanon mode though.

Cheers,
Stephane



nameref bug?

2014-08-29 Thread lolilolicon
The following is my test scripts and their output.
They are very similar, and I do not think they should result in
different output.
The output I expected from all of them is:

v1
v2

But as you can see, only 1 in the following 4 cases does it meet my
expectation. In the other 3 cases, the nameref attribute of the variable
'ref' is lost unexpectedly.

=== script ===
#!/bin/bash
declare -a arr=('dict[k1]' 'dict[k2]')
declare -A dict='([k1]=v1 [k2]=v2)'
func() {
  local -i i
  for ((i=0; i<${#arr[@]}; ++i)); do
local -n ref
ref=${arr[i]}
echo $ref
  done
}
func

--- output ---
v1
v2


=== script ===
#!/bin/bash
declare -a arr=('dict[k1]' 'dict[k2]')
declare -A dict='([k1]=v1 [k2]=v2)'
func() {
  local -i i
  local -n ref
  for ((i=0; i<${#arr[@]}; ++i)); do
ref=${arr[i]}
echo $ref
  done
}
func

--- output ---
v1
dict[k2]


=== script ===
#!/bin/bash
declare -a arr=('dict[k1]' 'dict[k2]')
declare -A dict='([k1]=v1 [k2]=v2)'
declare -i i
for ((i=0; i<${#arr[@]}; ++i)); do
  declare -n ref
  ref=${arr[i]}
  echo $ref
done

--- output ---
v1
dict[k2]


=== script ===
#!/bin/bash
declare -a arr=('dict[k1]' 'dict[k2]')
declare -A dict='([k1]=v1 [k2]=v2)'
declare -i i
declare -n ref
for ((i=0; i<${#arr[@]}; ++i)); do
  ref=${arr[i]}
  echo $ref
done

--- output ---
v1
dict[k2]



Re: nameref bug?

2014-08-29 Thread lolilolicon
On Sat, Aug 30, 2014 at 11:19 AM, lolilolicon  wrote:
> The following is my test scripts and their output.
> They are very similar, and I do not think they should result in
> different output.
> The output I expected from all of them is:
>
> v1
> v2
>
> But as you can see, only 1 in the following 4 cases does it meet my
> expectation. In the other 3 cases, the nameref attribute of the variable
> 'ref' is lost unexpectedly.

It seems to be a namespace / scope problem.

Another test script reveals that without assigning ref explicitly, such
as using the "for ... in" construct, it behaves as expected.

=== script ===
#!/bin/bash
declare -a arr=('dict[k1]' 'dict[k2]')
declare -A dict='([k1]=v1 [k2]=v2)'
declare -n ref
for ref in "${arr[@]}"; do
  echo $ref
done

ref=${arr[0]}
echo $ref
ref=${arr[1]}
echo $ref

--- output ---
v1
v2
dict[k1]
dict[k2]

As you see, once ref is assigned explicitly, or indeed, is assigned for
a second time, its nameref attribute is lost.



Re: nameref bug?

2014-08-29 Thread lolilolicon
On Sat, Aug 30, 2014 at 11:39 AM, lolilolicon  wrote:
>
> As you see, once ref is assigned explicitly, or indeed, is assigned for
> a second time, its nameref attribute is lost.

OK, here is the minimum script that demonstrates the bug:

=== script ===
#!/bin/bash
declare var="hello world"
declare -n ref
ref=var
echo $ref
ref=var
echo $ref

--- output ---
hello world
var


The equivalent "1 out of 4" script that works correctly:

#!/bin/bash
declare var="hello world"
func() {
  local -n ref
  ref=var
  echo $ref
  local -n ref  # the workaround
  ref=var
  echo $ref
}
func



Re: nameref bug?

2014-08-29 Thread lolilolicon
On Sat, Aug 30, 2014 at 11:51 AM, lolilolicon  wrote:
> On Sat, Aug 30, 2014 at 11:39 AM, lolilolicon  wrote:
>>
>> As you see, once ref is assigned explicitly, or indeed, is assigned for
>> a second time, its nameref attribute is lost.
>
> OK, here is the minimum script that demonstrates the bug:
>
> === script ===
> #!/bin/bash
> declare var="hello world"
> declare -n ref
> ref=var
> echo $ref
> ref=var
> echo $ref
>
> --- output ---
> hello world
> var
>
>
> The equivalent "1 out of 4" script that works correctly:
>
> #!/bin/bash
> declare var="hello world"
> func() {
>   local -n ref
>   ref=var
>   echo $ref
>   local -n ref  # the workaround
>   ref=var
>   echo $ref
> }
> func

Ah, LOL I think I need some sleep. This is not a bug. Sorry for all the noise.