Re: unset does not act as expected on namerefs

2015-06-06 Thread Chet Ramey
On 6/2/15 11:37 AM, Greg Wooledge wrote:

> Ksh's nameref is completely different.  With one of ksh's two different
> kinds of functions, you actually CAN use ksh nameref to pass a value
> back to the caller without variable name collisions.

In my opinion, the most interesting thing about ksh93's namerefs is that
they change ksh to allow dynamic scoping and give funtions access to a
calling function's local variables.  ksh93 doesn't normally allow that,
and David Korn was very vocal about the superiority of ksh93's static
scoping.

-- 
``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: unset does not act as expected on namerefs

2015-06-06 Thread Chet Ramey
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 6/1/15 9:59 PM, Shawn Wilson wrote:
> Top posting as I'm kinda going out of band of the thread here;
> 
> Having read the discussion, I guess the issue I brought up really
> isn't a "bug" (though Greg's points probably should be considered
> bugs). I'll preface this by saying I'm not an expert in bash by any
> means. However, most languages have a garbage collection facility
> which cleans up anonymous refs with nothing pointing to it and most
> high level languages make it easier to make a soft or symbolic
> reference than making hard references. But also, when you
> 'undef'/delete()/whatever the variable or the pointer, handle both
> and avoid this issue. While I do like the idea of pointers for bash
> variables, I would much prefer being able to create references.
> Also, whatever happens, I think there should also be a way to test
> for variable type (either another test flag or something like perl's
> ref() ).

I think it's a case of mismatched expectations.  There are a couple of
ways to go with this, and I went with the way Korn specified `unset'.
I initially implemented namerefs in bash without any special changes to
unset, but ended up adding it for compatibility.

Bash's dynamic scoping also drove some of the decisions.  Just as you
can follow the call chain to get different instances of a variable
named `x', for example, you get the same kind of variable resolution
with namerefs when you use `soft' symbolic references rather than `hard'
pointer references.  You absolutely have to be careful when you do this;
this part of the shell is a sharp instrument.  It's like I told Greg:
dynamic scoping is fundamental to how bash works, and namerefs don't
change that.

(Bash-4.3 has a way to test whether or not a variable is a nameref:
`test -R'.)

There's no need to flame anyone about this.  It's fair to discuss the
rationale for design decisions.

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/
-BEGIN PGP SIGNATURE-
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iEYEARECAAYFAlVzIgoACgkQu1hp8GTqdKufHQCeL4Z0v8l9Au7hWJbr/lnT3NxI
SOsAn1gDxHDXkshb8mfRaANy8dFyhOlh
=bZx+
-END PGP SIGNATURE-



Re: unset does not act as expected on namerefs

2015-06-06 Thread Dan Douglas
On Tue, Jun 2, 2015 at 7:31 AM, Greg Wooledge  wrote:
> There's declare -i, but no sane person USES that, so we can ignore it.

While in bash `-i` likely either has no effect or slows things down
very slightly, in ksh93 and probably zsh it's a huge performance win
because it prevents integers and floats from being automatically
coerced to and from a string on every operation. It also guarantees
(after the attribute is set) that the value will never be anything
other than the right type unless the attribute is explicitly removed.
It's perfectly sane to use it for values that are always guaranteed
correct by construction or by validation. (Use the `integer' and
`float' aliases in ksh, which are preset to use the largest currently
available type).

So long as you always remember to initialize the variable you can't
really go wrong with it.



Re: unset does not act as expected on namerefs

2015-06-02 Thread Shawn Wilson
On +2015/06/02 08:31:57, Greg Wooledge wrote:

> 
> > Also, whatever happens, I think there should also be a way to test
> > for variable type (either another test flag or something like perl's
> > ref() ).
> 
> Bash is not a strongly typed language.  You've got strings, and indexed
> arrays, and associative arrays.  That's all.  (There's declare -i, but
> no sane person USES that, so we can ignore it.)
> 
> You might be trying to do things that Bash is simply not designed to do.
> It's a shell.

I would argue that a nameref is a variable type.


pgpmvsk0XMiMp.pgp
Description: PGP signature


Re: unset does not act as expected on namerefs

2015-06-02 Thread Greg Wooledge
On Tue, Jun 02, 2015 at 11:16:27AM -0400, Shawn Wilson wrote:
> I would argue that a nameref is a variable type.

I suppose you're right, insofar as it has its own special rules that
you have to know about.

A lot of people wanted declare -n to be more than it is.  It's really
just syntactic sugar that doesn't actually let you do anything you
couldn't do already (with printf -v for assignment, and ${!foo} or eval
for reference).  So, like declare -i, it's something you can completely
disregard if you're writing new scripts, and not maintaining other
people's scripts.

Ksh's nameref is completely different.  With one of ksh's two different
kinds of functions, you actually CAN use ksh nameref to pass a value
back to the caller without variable name collisions.

$ bash -c 'f() { local x=from_f; g x; }; g() { declare -n x="$1"; echo "$x"; }; 
f'
bash: warning: x: circular name reference

$ ksh -c 'f() { typeset x=from_f; g x; }; g() { typeset -n x="$1"; echo "$x"; 
}; f'
ksh: typeset: x: invalid self reference

$ ksh -c 'function f { typeset x=from_f; g x; }; function g { typeset -n 
x="$1"; echo "$x"; }; f'
from_f



Re: unset does not act as expected on namerefs

2015-06-02 Thread Greg Wooledge
On Mon, Jun 01, 2015 at 09:59:51PM -0400, Shawn Wilson wrote:
> I'll preface this by saying I'm not an expert in bash by any
> means. However, most languages have a garbage collection facility

C does not.  Bash (all shells, really) is very strongly influenced by C.

> and most
> high level languages make it easier to make a soft or symbolic
> reference than making hard references.

Bash is not a high-level language.

> Also, whatever happens, I think there should also be a way to test
> for variable type (either another test flag or something like perl's
> ref() ).

Bash is not a strongly typed language.  You've got strings, and indexed
arrays, and associative arrays.  That's all.  (There's declare -i, but
no sane person USES that, so we can ignore it.)

You might be trying to do things that Bash is simply not designed to do.
It's a shell.



Re: unset does not act as expected on namerefs

2015-06-01 Thread Shawn Wilson
Top posting as I'm kinda going out of band of the thread here;

Having read the discussion, I guess the issue I brought up really
isn't a "bug" (though Greg's points probably should be considered
bugs). I'll preface this by saying I'm not an expert in bash by any
means. However, most languages have a garbage collection facility
which cleans up anonymous refs with nothing pointing to it and most
high level languages make it easier to make a soft or symbolic
reference than making hard references. But also, when you
'undef'/delete()/whatever the variable or the pointer, handle both
and avoid this issue. While I do like the idea of pointers for bash
variables, I would much prefer being able to create references.
Also, whatever happens, I think there should also be a way to test
for variable type (either another test flag or something like perl's
ref() ).

Feel free to flame me and say 'go away' if I'm off the mark with how
this should be handled :)
-BEGIN PGP PUBLIC KEY BLOCK-
Version: GnuPG v1

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
BM11LSajiKSbeGELAuG

Re: unset does not act as expected on namerefs

2015-05-29 Thread Chet Ramey
On 5/27/15 8:25 AM, Greg Wooledge wrote:

>  1) It doesn't cross scopes.  It's not like Tcl's upvar at all.  It
> only refers to a variable in the same scope (which, following the
> standard bash rules, means it'll recursively search upward until
> it finds a matching variable by name).  

This isn't about namerefs; namerefs don't change bash's scoping rules.


>  2) It allows arbitrary code execution, just like eval:
> 
> imadev:~$ f() { declare -n foo="$1"; echo "$foo"; }
> imadev:~$ f 'x[i=0$(date >&2)]'
> Wed May 27 08:07:35 EDT 2015

So, given the nameref assignment, these two things are equivalent:

echo "${x[i=0$(date >&2)]"
echo "$foo"

You might have a beef with the subscript in an array reference undergoing
the usual set of word expansions, but this isn't anything nameref-
specific.

> Here's another surprise, that I didn't know until now.  Given the above,
> if we follow it up with another declaration of foo, it "hides" the
> nameref.   But the nameref declaration is still there, lurking, waiting.
> 
> imadev:~$ declare -A foo
> imadev:~$ foo["jug"]="brown"
> imadev:~$ declare -p foo somevariable
> declare -A foo='([jug]="brown" )'
> bash: declare: somevariable: not found
> imadev:~$ unset foo
> imadev:~$ declare -p foo somevariable
> declare -n foo="somevariable"
> bash: declare: somevariable: not found

Thanks, this is an actual problem.  The 'declare -A foo' doesn't look up
foo for assignment, it looks up foo as if it were being referenced as $foo.
I'll see what I need to do to fix it.

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: unset does not act as expected on namerefs

2015-05-27 Thread Chet Ramey
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 5/26/15 5:02 PM, Shawn Wilson wrote:
> On +2015/05/26 18:05:18, Geir Hauge wrote:
>> On Tue, May 26, 2015 at 11:00:45AM -0500, Eduardo A. Bustamante López wr
ote:
>>> # Here we 'unset ref', which actually unsets 'var'. Then, we assign 'va
r' to
>>> # 'ref', but since 'ref' is still a nameref, it instead assigns 'var' t
o 'var'.
>>> dualbus@hp:~$ unset ref; ref=var; echo "$ref"; declare -p ref
>>> var
>>> declare -n ref="var"
>>> dualbus@hp:~$ declare -p var
>>> declare -- var="var"
>>
>> Ah, that explains it! Mystery solved, and no longer surprising behavior.
>>
> 
> If there's no good reason to keep this as is (some use case where
> this might be wanted and breaking backward compatibility - I can't
> see anyone actually *wanting* it this way) shouldn't it be changed?
> A behavior can be documented and still be bad.

What behavior do you want? That namerefs should act transparently (that
is, use the nameref variable's non-null value as the variable name to
operate on) in all contexts *except* unset?

- -- 
``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/
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iEYEARECAAYFAlVl1JQACgkQu1hp8GTqdKudNQCeJn533z6DE//zfQLMVFctElOg
DXkAniyUQHTEfGXcYJTqWHBJDgTOW4pG
=Jrw3
-END PGP SIGNATURE-



Re: unset does not act as expected on namerefs

2015-05-27 Thread Chet Ramey
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 5/26/15 10:31 AM, Shawn Wilson wrote:
> swilson@swlap1:~/temp$ bash --version
> GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> swilson@swlap1:~/temp$ cat t.txt 
> $ome text !n a file|
> swilson@swlap1:~/temp$ unset t
> swilson@swlap1:~/temp$ t=$(< ./t.txt)
> swilson@swlap1:~/temp$ echo "$t"
> bash: $ome text !n a file|: invalid variable name for name reference

This is pretty obviously not the entire story, since you've never assigned
`t' the nameref attribute.  If you run `declare -n t' after the unset,
you'll see that error, but your transcript doesn't show you doing that.

If you can show me a complete transcript I can tell you what's happening.
It may be that you've discovered a bug, but it's hard to say.

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/
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iEYEARECAAYFAlVl0ygACgkQu1hp8GTqdKspagCfXwqF2uqmwtMhs2vKHevGSJu2
1EAAn01FXqjv+RpKlilPQn7TxJRg1dMt
=PQ5D
-END PGP SIGNATURE-



Re: unset does not act as expected on namerefs

2015-05-27 Thread Greg Wooledge
On Tue, May 26, 2015 at 05:02:43PM -0400, Shawn Wilson wrote:
> If there's no good reason to keep this as is (some use case where
> this might be wanted and breaking backward compatibility - I can't
> see anyone actually *wanting* it this way) shouldn't it be changed?
> A behavior can be documented and still be bad.

Well, there are multiple aspects to this issue.

The first is that "declare -n" is very new (only since bash 4.2), so
most script writers either aren't aware of it yet, or haven't had
much chance to use it.  It's hard to have a good understanding of
how to use something properly without some experience.

The second is that bash's "declare -n" is, in its current implementation,
not robust enough for general use.  It has two major issues, which I've
documented on my wiki, which I'll summarize here:

 1) It doesn't cross scopes.  It's not like Tcl's upvar at all.  It
only refers to a variable in the same scope (which, following the
standard bash rules, means it'll recursively search upward until
it finds a matching variable by name).  What this means is that
while you might EXPECT this to work:

f() {
declare -n foo="$1"
foo=set_by_f
}

It won't work in the general case.  Demonstration:

imadev:~$ f() { declare -n foo="$1"; }
imadev:~$ g() { declare -n foo="$1"; f foo; }
imadev:~$ foo=bar
imadev:~$ g foo
bash: warning: foo: circular name reference

So, you can't use it to pass variable names from a caller to
a function.  You STILL have namespace collisions.

 2) It allows arbitrary code execution, just like eval:

imadev:~$ f() { declare -n foo="$1"; echo "$foo"; }
imadev:~$ f 'x[i=0$(date >&2)]'
Wed May 27 08:07:35 EDT 2015


Though, one might argue that this is more of an issue with bash's
indexed arrays than with eval or declare -n.  Even printf -v isn't
safe against this.

(See also http://mywiki.wooledge.org/BashFAQ/048)

The third aspect to consider about "unset nameref" is whether the script
writer's intent was to unset the nameref itself, or the variable pointed
to by the nameref.

foo=bar
unset foo

Given those two lines of code, with no context, we might expect that
the word "bar" is no longer held in memory anywhere (or is held in a
chunk of memory that's free to be overwritten at any time).  If foo
is a regular variable, this is the case.  If foo is a nameref to
another variable, then it's STILL true:

imadev:~$ declare -n foo=somevariable
imadev:~$ foo=bar
imadev:~$ unset foo
imadev:~$ declare -p foo somevariable
declare -n foo="somevariable"
bash: declare: somevariable: not found

This leaves the nameref intact, so you can assign a new "somevariable"
through it.  Wiping and re-assigning the pointed-to variable might be
what someone wants.

Here's another surprise, that I didn't know until now.  Given the above,
if we follow it up with another declaration of foo, it "hides" the
nameref.   But the nameref declaration is still there, lurking, waiting.

imadev:~$ declare -A foo
imadev:~$ foo["jug"]="brown"
imadev:~$ declare -p foo somevariable
declare -A foo='([jug]="brown" )'
bash: declare: somevariable: not found
imadev:~$ unset foo
imadev:~$ declare -p foo somevariable
declare -n foo="somevariable"
bash: declare: somevariable: not found

Is that what Chet intended?  I have no idea.  (I was actually expecting
"declare -A foo" to create an associative array named somevariable,
with foo still pointing to it.)



Re: unset does not act as expected on namerefs

2015-05-26 Thread Shawn Wilson
On +2015/05/26 18:05:18, Geir Hauge wrote:
> On Tue, May 26, 2015 at 11:00:45AM -0500, Eduardo A. Bustamante López wrote:
> > # Here we 'unset ref', which actually unsets 'var'. Then, we assign 'var' to
> > # 'ref', but since 'ref' is still a nameref, it instead assigns 'var' to 
> > 'var'.
> > dualbus@hp:~$ unset ref; ref=var; echo "$ref"; declare -p ref
> > var
> > declare -n ref="var"
> > dualbus@hp:~$ declare -p var
> > declare -- var="var"
> 
> Ah, that explains it! Mystery solved, and no longer surprising behavior.
> 

If there's no good reason to keep this as is (some use case where
this might be wanted and breaking backward compatibility - I can't
see anyone actually *wanting* it this way) shouldn't it be changed?
A behavior can be documented and still be bad.


pgpOwZAk14bLp.pgp
Description: PGP signature


Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:00:45AM -0500, Eduardo A. Bustamante López wrote:
> # Here we 'unset ref', which actually unsets 'var'. Then, we assign 'var' to
> # 'ref', but since 'ref' is still a nameref, it instead assigns 'var' to 
> 'var'.
> dualbus@hp:~$ unset ref; ref=var; echo "$ref"; declare -p ref
> var
> declare -n ref="var"
> dualbus@hp:~$ declare -p var
> declare -- var="var"

Ah, that explains it! Mystery solved, and no longer surprising behavior.

-- 
Geir Hauge



Re: unset does not act as expected on namerefs

2015-05-26 Thread Eduardo A . Bustamante López
On Tue, May 26, 2015 at 05:47:30PM +0200, Geir Hauge wrote:
[...]
> The surprising part is that it keeps the -n flag, but partially loses
> the nameref ability:
> 
> $ var=foo; declare -n ref
> $ ref=var
> $ printf '%s - ' "$ref"; declare -p ref
> foo - declare -n ref="var"
> $ unset ref
> $ ref=var
> $ printf '%s - ' "$ref"; declare -p ref
> var - declare -n ref="var"
> $ ref=baz
> baz - declare -n ref="var"

I'm not so sure about that. Let's see it, step by step:

# Here, we setup the whole thing, and everything works as expected. 'ref'
points to 'var', and the value printed is that of 'var'.
dualbus@hp:~$ var=foo; declare -n ref=var; echo "$ref"; declare -p ref
foo
declare -n ref="var"

# Here we 'unset ref', which actually unsets 'var'. Then, we assign 'var' to
# 'ref', but since 'ref' is still a nameref, it instead assigns 'var' to 'var'.
dualbus@hp:~$ unset ref; ref=var; echo "$ref"; declare -p ref
var
declare -n ref="var"
dualbus@hp:~$ declare -p var
declare -- var="var"

# Here you assign 'baz' to 'var', through 'ref'. It works as documented.
dualbus@hp:~$ ref=baz; echo "$ref"; declare -p ref var
baz
declare -n ref="var"
declare -- var="baz"

-- 
Eduardo Bustamante
https://dualbus.me/



Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:24:57AM -0400, Shawn Wilson wrote:
> On +2015/05/26 11:04:38, Greg Wooledge wrote:
> > On Tue, May 26, 2015 at 10:31:34AM -0400, Shawn Wilson wrote:
> > > swilson@swlap1:~/temp$ bash --version
> > > GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> > > swilson@swlap1:~/temp$ cat t.txt 
> > > $ome text !n a file|
> > > swilson@swlap1:~/temp$ unset t
> > > swilson@swlap1:~/temp$ t=$(< ./t.txt)
> > > swilson@swlap1:~/temp$ echo "$t"
> > > bash: $ome text !n a file|: invalid variable name for name reference
> > > swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo "$t"
> > > bash: $ome text !n a file|: invalid variable name for name reference
> > 
> > As surprising as that is, have a look at "help unset":
> > 
> 
> So current behavior should stand? I would think that unset (with no
> options) should DWIM. This behavior also seemed to surprise most on
> #bash IRC. This is not a bug for lack of documentation or not
> understanding the results after looking at the doc, but a "wow, this
> is surprising - maybe this could behave in a manner so it's not so
> surprising".

The surprising part is that it keeps the -n flag, but partially loses
the nameref ability:

$ var=foo; declare -n ref
$ ref=var
$ printf '%s - ' "$ref"; declare -p ref
foo - declare -n ref="var"
$ unset ref
$ ref=var
$ printf '%s - ' "$ref"; declare -p ref
var - declare -n ref="var"
$ ref=baz
baz - declare -n ref="var"

-- 
Geir Hauge



Re: unset does not act as expected on namerefs

2015-05-26 Thread Shawn Wilson
On +2015/05/26 11:04:38, Greg Wooledge wrote:
> On Tue, May 26, 2015 at 10:31:34AM -0400, Shawn Wilson wrote:
> > swilson@swlap1:~/temp$ bash --version
> > GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> > swilson@swlap1:~/temp$ cat t.txt 
> > $ome text !n a file|
> > swilson@swlap1:~/temp$ unset t
> > swilson@swlap1:~/temp$ t=$(< ./t.txt)
> > swilson@swlap1:~/temp$ echo "$t"
> > bash: $ome text !n a file|: invalid variable name for name reference
> > swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo "$t"
> > bash: $ome text !n a file|: invalid variable name for name reference
> 
> As surprising as that is, have a look at "help unset":
> 

So current behavior should stand? I would think that unset (with no
options) should DWIM. This behavior also seemed to surprise most on
#bash IRC. This is not a bug for lack of documentation or not
understanding the results after looking at the doc, but a "wow, this
is surprising - maybe this could behave in a manner so it's not so
surprising".

> unset: unset [-f] [-v] [-n] [name ...]
> Unset values and attributes of shell variables and functions.
> 
> For each NAME, remove the corresponding variable or function.
> 
> Options:
>   -ftreat each NAME as a shell function
>   -vtreat each NAME as a shell variable
>   -ntreat each NAME as a name reference and unset the variable 
> itself
> rather than the variable it references


pgpTDG5rNHwS4.pgp
Description: PGP signature


Re: unset does not act as expected on namerefs

2015-05-26 Thread Greg Wooledge
On Tue, May 26, 2015 at 10:31:34AM -0400, Shawn Wilson wrote:
> swilson@swlap1:~/temp$ bash --version
> GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> swilson@swlap1:~/temp$ cat t.txt 
> $ome text !n a file|
> swilson@swlap1:~/temp$ unset t
> swilson@swlap1:~/temp$ t=$(< ./t.txt)
> swilson@swlap1:~/temp$ echo "$t"
> bash: $ome text !n a file|: invalid variable name for name reference
> swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo "$t"
> bash: $ome text !n a file|: invalid variable name for name reference

As surprising as that is, have a look at "help unset":

unset: unset [-f] [-v] [-n] [name ...]
Unset values and attributes of shell variables and functions.

For each NAME, remove the corresponding variable or function.

Options:
  -ftreat each NAME as a shell function
  -vtreat each NAME as a shell variable
  -ntreat each NAME as a name reference and unset the variable 
itself
rather than the variable it references



unset does not act as expected on namerefs

2015-05-26 Thread Shawn Wilson
swilson@swlap1:~/temp$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
swilson@swlap1:~/temp$ cat t.txt 
$ome text !n a file|
swilson@swlap1:~/temp$ unset t
swilson@swlap1:~/temp$ t=$(< ./t.txt)
swilson@swlap1:~/temp$ echo "$t"
bash: $ome text !n a file|: invalid variable name for name reference
swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo "$t"
bash: $ome text !n a file|: invalid variable name for name reference



pgpk4Cwu_mrnZ.pgp
Description: PGP signature