Re: curiosity: 'typeset -xr' vs. 'export -r'

2022-12-13 Thread Lawrence Velázquez
On Mon, Dec 12, 2022, at 4:43 AM, L A Walsh wrote:
> On 2022/12/11 20:47, Lawrence Velázquez wrote:
>> This happens because "declare"/"typeset" creates local variables
>> within functions.  Using -g works around this...
>>
>>  $ Export() { declare -gx "$@"; }
>>  $ Export -r foo=1
>>  $ declare -p foo
>>  declare -rx foo="1"
>>
>> ...but now "Export" always creates global variables, rather than
>> scoping as "declare" and your alias-based version does.  On the
>> other hand, "export" also creates global variables, so in a sense
>> the workaround version is more consistent.
>>
>>  $ f() { export "$@"; }
>>  $ f var=1
>>  $ declare -p var
>>  declare -x var="1"
>>   
> 
> I see, but you still can't use "-r" w/export

Of course not.  I only meant to demonstrate that "export" always
creates global variables, so a function that utilizes "declare -gx"
actually behaves more like "export" then your alias does.


> though I think the -r flag would get dropped in any exported shell

The environment does not propagate the readonly attribute, no.


> though
> in that case, one might expect an error if one uses "typeset -xr"
> along the lines of "-r flag won't be exported".

The readonly attribute is still applied to the original shell
variable, so there's no reason to produce an error.


> Side curious: If one uses -g, does it cause the var to be defined
> in all intervening functions as well as the top(global)
> and current scope?

It defines a global variable, which is then visible to all functions.


-- 
vq



Re: curiosity: 'typeset -xr' vs. 'export -r'

2022-12-13 Thread Emanuele Torre
On Tue, Dec 13, 2022 at 03:07:16AM -0500, Lawrence Velázquez wrote:
> Of course not.  I only meant to demonstrate that "export" always
> creates global variables, so a function that utilizes "declare -gx"
> actually behaves more like "export" then your alias does.

This is a little inaccurate.

`export' doesn't always act on the *global* variable, but "declare -g"
does.

The differences are that:
 * `declare' (without -g), always acts on variables in the current
   dynamic scope, and will create a new variable in the current dynamic
   scope if no variable with the name it was looking for exists.

 * `export' and `readonly' act on the variable they can see, and set
   their "x"/"r" attribute; they will only create a new variable (in the
   global scope) if no variable with the name they were looking for
   exists in any dynamic scope. Just like simple "a=b" assignments.

What `declare -xr' does in a function:

  fun () {
  declare -xr a=2
  }

Is equivalent to:

  fun () {
  declare a=2 && # create a new "a" variable in the current scope
 # and set its value to 2
  export a&& # set its "x" attribute
  readonly a # set its "r" attribute

  # when this function returns, that variable will be deleted
  }

So, as we already know, a function that runs that runs only `declare'
commands (without -p, -f, or -g) is pretty much useless.

Examples:

  bash-5.1$ # the `export' and `readonly' in "fun2" will act on the "a"
  bash-5.1$ # variable in the dynamic scope of the "fun1" function
  bash-5.1$ declare -p a
  bash: declare: a: not found
  bash-5.1$ fun1 () { local a=hi; fun2; declare -p a ;}
  bash-5.1$ fun2 () { export a; readonly a;}
  bash-5.1$ a=hello; declare -p a; fun1; declare -p a
  declare -- a="hello"
  declare -rx a="hi"
  declare -- a="hello"

  bash-5.1$ setexportreadonly () { export -- "$1" && readonly -- "$1" ;}
  bash-5.1$ x=hi
  bash-5.1$ declare -p x
  bash-5.1$ setexportreadonly x
  bash-5.1$ declare -p x
  declare -rx x="hi"

  bash-5.1$ # `declare -g' will bypass all the dynamic scopes, and will
  bash-5.1$ # act on the global variable.
  bash-5.1$ declare -p g
  bash: declare: g: not found
  bash-5.1$ fun1 () { local g=hi; fun2; declare -p g ;}
  bash-5.1$ fun2 () { declare -grx g=hey ;}
  bash-5.1$ g=hello; declare -p g; fun1; declare -p g
  declare -- g="hello" # "g" in the global scope before calling fun2
  declare -- g="hi"# "g" in the dynamic scope of fun1 after calling fun2
  declare -rx g="hey"  # "g" in the global scope after calling fun2

  bash-5.1$ # `export', `readonly', and assignments in functions create
  bash-5.1$ # a new global variable if there are no visible variables
  bash-5.1$ # with the given name.
  bash-5.1$ declare -p v{1..5}
  bash: declare: v1: not found
  bash: declare: v2: not found
  bash: declare: v3: not found
  bash: declare: v4: not found
  bash: declare: v5: not found
  bash: declare: v6: not found
  bash-5.1$ fun1 () { local v4; fun2 "$1" ;}
  bash-5.1$ fun2 () { local v5; fun3 "$1" ;}
  bash-5.1$ fun3 () { local v6; eval " $1" ;}
  bash-5.1$ fun1 'v1=x'; fun1 'export v2=y'; fun1 'readonly v3=z'
  bash-5.1$ fun1 'v4=x'; fun1 'export v5=y'; fun1 'readonly v6=z'
  bash-5.1$ declare -p v{1..5}
  declare -- v1="x"
  declare -x v2="y"
  declare -r v3="z"
  bash: declare: v4: not found
  bash: declare: v5: not found
  bash: declare: v6: not found

 emanuele6



bash crashes if TERM is unset and the Delete key is pressed twice

2022-12-13 Thread Emanuele Torre
This happens since 88d69b4fa224d93ef1d26b80229668397bb6496b .

If bash is started with the TERM variable unset or empty, it will
segfault and crash if you press the Delete key twice (it only happens
for the first prompt, and if you don't press anything before the two
Delete key presses).

I was able to reproduce this in the linux virtual console, urxvt, and
xterm, both running tmux and not running tmux.

Reproduce with either of these commands:

* env -i /path/to/bash-devel/bash --norc --noprofile
* TERM= /path/to/bash-devel/bash --norc --noprofile

If it is not reproducible with your terminal emulator, try:

* xterm -e env -i /path/to/bash-devel/bash --norc --noprofile
* xterm -e env 'TERM=' /path/to/bash-devel/bash --norc --noprofile

 emanuele6



Nested expansion in heredoc fails

2022-12-13 Thread Norbert Lange
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -fstack-protector-strong -Wformat
-Werror=format-security -Wall
uname output: Linux lano-work 6.0.0-5-amd64 #1 SMP PREEMPT_DYNAMIC
Debian 6.0.10-2 (2022-12-01) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.2
Patch Level: 2
Release Status: release

Description:
Parameter expansion within heredocs fails.

The code below works with other shells aswell as bash 5.1

Repeat-By:
BUILDDIR=/builds/test
cat << EOC
Dir: ${BUILDDIR#$(pwd)/}
EOC



Re: curiosity: 'typeset -xr' vs. 'export -r'

2022-12-13 Thread Lawrence Velázquez
On Tue, Dec 13, 2022, at 6:38 AM, Emanuele Torre wrote:
> On Tue, Dec 13, 2022 at 03:07:16AM -0500, Lawrence Velázquez wrote:
>> Of course not.  I only meant to demonstrate that "export" always
>> creates global variables, so a function that utilizes "declare -gx"
>> actually behaves more like "export" then your alias does.
>
> This is a little inaccurate.
>
> `export' doesn't always act on the *global* variable, but "declare -g"
> does.
>
> The differences are that:
>  * `declare' (without -g), always acts on variables in the current
>dynamic scope, and will create a new variable in the current dynamic
>scope if no variable with the name it was looking for exists.
>
>  * `export' and `readonly' act on the variable they can see, and set
>their "x"/"r" attribute; they will only create a new variable (in the
>global scope) if no variable with the name they were looking for
>exists in any dynamic scope. Just like simple "a=b" assignments.

You're right, thanks for clarifying.  I was thinking exclusively
about the behavior when creating variables.

-- 
vq