Re: Some incorrect behaviour for BASH arrays

2023-08-31 Thread Victor Pasko
Thanks for prompt response. But see my comments below.

Well, instead of the following line

RESULT=''

done

declare -p RESULT

without initialization, because otherwise I got the following error "-bash:
declare: RESULT=: not found".

And after deleting/commenting the following fragment in badrev

#if [ $i -ge $QSTRING ] ; then
#echo "XXX-break i=$i result=$RESULT size=${#RESULT}"
#break
#fi

and correcting end echo-line to

echo " result=${RESULT[0]} size=${#RESULT[0]}"

i can see strange output for badrev:
declare -a RESULT=([0]="987654321" [1]="B" [2]="1" [3]="2" [4]="3" [5]="\\"
[6]="-" [7]="4" [8]="5" [9]="6" [10]="7" [11]="\\" [12]="-" [13]="8")
result=9 size=1
Still incorrect output and size:( How to get correct output? ${RESULT[0]}
???

result=${RESULT[0]} size=${#RESULT[0]} ### does not work :(

BTW, in the presented link to the manual with  *6.7 Arrays*
there is no explanation for *declare -p *:(

Still unclear output for badsed

BAD variants of sed
string=Bb12345678 QSTRING=10
declare -a RESULT=([0]="bB123\\-4567\\-8" [1]="8" [2]="7" [3]="6" [4]="5"
[5]="4" [6]="3" [7]="2" [8]="1" [9]="6" [10]="7" [11]="\\" [12]="-"
[13]="8")
DEBUG i-symbol=B
DEBUG i-symbol=b
DEBUG i-symbol=1
DEBUG i-symbol=2
DEBUG i-symbol=3
DEBUG i-symbol=4
DEBUG i-symbol=5
DEBUG i-symbol=6
DEBUG i-symbol=7
DEBUG i-symbol=8
result=B size=1


On Thu, Aug 31, 2023 at 4:49 AM Lawrence Velázquez  wrote:

> On Wed, Aug 30, 2023, at 2:12 PM, Victor Pasko wrote:
> > Attached please find bug.bash to reproduce incorrect BASH behaviour for
> > BASH arrays
> > and look at ways to run it
>
> Your tests are flawed.  The lines you use to inspect RESULT...
>
> > badsed() { # just array indexes are used for RESULT
> >   ...
> >   echo -n "   result=$RESULT size=${#RESULT}"
> >   echo " ${RESULT:0:$k}"
> > }
> >
> > ...
> >
> > badrev() {
> > ...
> > if [ $i -ge $QSTRING ] ; then
> > echo "XXX-break i=$i result=$RESULT size=${#RESULT}"
> > break # XXX
> > fi
> >   done
> >   echo "  result=$RESULT size=${#RESULT}"
> > }
>
> ...are actually only inspecting element 0 of RESULT.  As per the
> manual, "[r]eferencing an array variable without a subscript is
> equivalent to referencing with a subscript of 0" [*].
>
> Try using ''declare -p RESULT'' instead.
>
> [*] https://www.gnu.org/software/bash/manual/html_node/Arrays.html
>
> --
> vq
>


-- 

-- PSK


Re: Some incorrect behaviour for BASH arrays

2023-08-31 Thread Kerin Millar
On Thu, 31 Aug 2023 19:39:09 +0700
Victor Pasko  wrote:

> Thanks for prompt response. But see my comments below.
> 
> Well, instead of the following line
> 
> RESULT=''
> 
> done
> 
> declare -p RESULT
> 
> without initialization, because otherwise I got the following error "-bash:
> declare: RESULT=: not found".

declare -p RESULT='' translates as declare -p RESULT=, which instructs bash to 
attempt to dump the contents of a variable named RESULT=. There is no variable 
named RESULT=, so it prints an error to that effect. Put another way, you're 
not supposed to be using declare -p as a substitute for assignment syntax. 
While declare can also be used to set variables, that's not what the -p option 
is for.

> 
> And after deleting/commenting the following fragment in badrev
> 
> #if [ $i -ge $QSTRING ] ; then
> #echo "XXX-break i=$i result=$RESULT size=${#RESULT}"
> #break
> #fi
> 
> and correcting end echo-line to
> 
> echo " result=${RESULT[0]} size=${#RESULT[0]}"

${RESULT[0]} will expand as the first element of the array. ${#RESULT[0]} will 
expand as the length of the first element of the array (not the length of the 
array itself).

> 
> i can see strange output for badrev:
> declare -a RESULT=([0]="987654321" [1]="B" [2]="1" [3]="2" [4]="3" [5]="\\"
> [6]="-" [7]="4" [8]="5" [9]="6" [10]="7" [11]="\\" [12]="-" [13]="8")
> result=9 size=1
> Still incorrect output and size:( How to get correct output? ${RESULT[0]}
> ???

What would be correct to you?

> 
> result=${RESULT[0]} size=${#RESULT[0]} ### does not work :(

What would it be doing for you to be satisfied that it works?

Your script contains no explanation as to what it is intended to do. Comments 
to the effect of "not working" do not help to discern your intent.

> 
> BTW, in the presented link to the manual with  *6.7 Arrays*
> there is no explanation for *declare -p *:(

It's a builtin command, so it's listed within the SHELL BUILTIN COMMANDS 
section. Also, you may use the help builtin to display some (less detailed) 
documentation.

$ help declare | grep -- -p
  -pdisplay the attributes and value of each NAME

-- 
Kerin Millar



Re: Some incorrect behaviour for BASH arrays

2023-08-31 Thread Kerin Millar
On Thu, 31 Aug 2023 01:12:48 +0700
Victor Pasko  wrote:

> Hi,
> 
> On my Win-7 64-bit using Cygwin
> 
> 
> *% bash --version*GNU bash, version 5.2.15(3)-release (x86_64-pc-cygwin)
> Copyright (C) 2022 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later  >
> 
> This is free software; you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.
> 
> 
> *% echo LANG=$LANG; echo LC_ALL=$LC_ALL*LANG=
> LC_ALL=
> 
> Attached please find bug.bash to reproduce incorrect BASH behaviour for
> BASH arrays
> and look at ways to run it

This script is a mess because its functions begin by defining RESULT as an 
ordinary, non-array variable (if not yet declared).

$ RESULT='string'
$ declare -p RESULT # not yet an array variable
declare -- RESULT='string'

It then proceeds to operate on the variable in such a way that it will be 
transformed to an array.

$ RESULT[1]='second element'
$ declare -p RESULT
declare -a RESULT=([0]="string" [1]="second element")

Now, would RESULT='' empty this array? No, it would not.

$ RESULT='' # no different from RESULT[0]=''
$ declare -p RESULT
declare -a RESULT=([0]="" [1]="second element")

A correct way to initialise an empty array variable is RESULT=().

$ RESULT=()
$ declare -p RESULT # now an empty array
declare -a RESULT=()

You might also consider using the "local" builtin to declare the variable with 
a function-local scope.

$ f() { local RESULT=(); RESULT+=("append me"); declare -p RESULT; }; unset -v 
RESULT; f; declare -p RESULT
declare -a RESULT=([0]="append me")
bash: declare: RESULT: not found

Note that the second declare command correctly raises an error because RESULT 
is not visible in its scope. Used judiciously, local can help to avoid the 
writing of needless bugs.

-- 
Kerin Millar



RFC: changing printf(1) behavior on %b

2023-08-31 Thread Eric Blake
In today's Austin Group call, we discussed the fact that printf(1) has
mandated behavior for %b (escape sequence processing similar to XSI
echo) that will eventually conflict with C2x's desire to introduce %b
to printf(3) (to produce 0b000... binary literals).

For POSIX Issue 8, we plan to mark the current semantics of %b in
printf(1) as obsolescent (it would continue to work, because Issue 8
targets C17 where there is no conflict with C2x), but with a Future
Directions note that for Issue 9, we could remove %b entirely, or
(more likely) make %b output binary literals just like C.  But that
raises the question of whether the escape-sequence processing
semantics of %b should still remain available under the standard,
under some other spelling, since relying on XSI echo is still not
portable.

One of the observations made in the meeting was that currently, both
the POSIX spec for printf(1) as seen at [1], and the POSIX and C
standard (including the upcoming C2x standard) for printf(3) as seen
at [3] state that both the ' and # flag modifiers are currently
undefined when applied to %s.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
"The format operand shall be used as the format string described in
XBD File Format Notation[2] with the following exceptions:..."

[2] 
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html#tag_05
"The flag characters and their meanings are: ...
# The value shall be converted to an alternative form. For c, d, i, u,
  and s conversion specifiers, the behavior is undefined.
[and no mention of ']"

[3] https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
"The flag characters and their meanings are:
' [CX] [Option Start] (The .) The integer portion of the
  result of a decimal conversion ( %i, %d, %u, %f, %F, %g, or %G )
  shall be formatted with thousands' grouping characters. For other
  conversions the behavior is undefined. The non-monetary grouping
  character is used. [Option End]
...
# Specifies that the value is to be converted to an alternative
  form. For o conversion, it shall increase the precision, if and only
  if necessary, to force the first digit of the result to be a zero
  (if the value and precision are both 0, a single 0 is printed). For
  x or X conversion specifiers, a non-zero result shall have 0x (or
  0X) prefixed to it. For a, A, e, E, f, F, g, and G conversion
  specifiers, the result shall always contain a radix character, even
  if no digits follow the radix character. Without this flag, a radix
  character appears in the result of these conversions only if a digit
  follows it. For g and G conversion specifiers, trailing zeros shall
  not be removed from the result as they normally are. For other
  conversion specifiers, the behavior is undefined."

Thus, it appears that both %#s and %'s are available for use for
future standardization.  Typing-wise, %#s as a synonym for %b is
probably going to be easier (less shell escaping needed).  Is there
any interest in a patch to coreutils or bash that would add such a
synonym, to make it easier to leave that functionality in place for
POSIX Issue 9 even when %b is repurposed to align with C2x?

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org




Re: Some incorrect behaviour for BASH arrays

2023-08-31 Thread Greg Wooledge
On Thu, Aug 31, 2023 at 04:13:09PM +0100, Kerin Millar wrote:
> This script is a mess because its functions begin by defining RESULT as an 
> ordinary, non-array variable (if not yet declared).
> 
> $ RESULT='string'
> $ declare -p RESULT # not yet an array variable
> declare -- RESULT='string'
> 
> It then proceeds to operate on the variable in such a way that it will be 
> transformed to an array.
> 
> $ RESULT[1]='second element'
> $ declare -p RESULT
> declare -a RESULT=([0]="string" [1]="second element")
> 
> Now, would RESULT='' empty this array? No, it would not.
> 
> $ RESULT='' # no different from RESULT[0]=''
> $ declare -p RESULT
> declare -a RESULT=([0]="" [1]="second element")
> 
> A correct way to initialise an empty array variable is RESULT=().
> 
> $ RESULT=()
> $ declare -p RESULT # now an empty array
> declare -a RESULT=()
> 
> You might also consider using the "local" builtin to declare the variable 
> with a function-local scope.

All of this is excellent advice.  If you'd like a tutorial that explains
more about bash arrays, I recommend:

https://mywiki.wooledge.org/BashFAQ/005



Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Chet Ramey

On 8/31/23 11:35 AM, Eric Blake wrote:

In today's Austin Group call, we discussed the fact that printf(1) has
mandated behavior for %b (escape sequence processing similar to XSI
echo) that will eventually conflict with C2x's desire to introduce %b
to printf(3) (to produce 0b000... binary literals).

For POSIX Issue 8, we plan to mark the current semantics of %b in
printf(1) as obsolescent (it would continue to work, because Issue 8
targets C17 where there is no conflict with C2x), but with a Future
Directions note that for Issue 9, we could remove %b entirely, or
(more likely) make %b output binary literals just like C.


I doubt I'd ever remove %b, even in posix mode -- it's already been there
for 25 years.


But that
raises the question of whether the escape-sequence processing
semantics of %b should still remain available under the standard,
under some other spelling, since relying on XSI echo is still not
portable.

One of the observations made in the meeting was that currently, both
the POSIX spec for printf(1) as seen at [1], and the POSIX and C
standard (including the upcoming C2x standard) for printf(3) as seen
at [3] state that both the ' and # flag modifiers are currently
undefined when applied to %s.


Neither one is a very good choice, but `#' is the better one. It at least
has a passing resemblence to the desired functionality.

Why not standardize another character, like %B? I suppose I'll have to look
at the etherpad for the discussion. I think that came up on the mailing
list, but I can't remember the details.


Is there
any interest in a patch to coreutils or bash that would add such a
synonym, to make it easier to leave that functionality in place for
POSIX Issue 9 even when %b is repurposed to align with C2x?


It's maybe a two or three line change at most.

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




Re: bug#65659: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Paul Eggert

On 2023-08-31 08:35, Eric Blake wrote:

Typing-wise, %#s as a synonym for %b is
probably going to be easier (less shell escaping needed).  Is there
any interest in a patch to coreutils or bash that would add such a
synonym, to make it easier to leave that functionality in place for
POSIX Issue 9 even when %b is repurposed to align with C2x?


Sounds good to me for coreutils.



Re: bug attached

2023-08-31 Thread queency3 jones
i don't think that main is significant when it declared in "Bash" but even
though,
if you change the function main , to function ain  the $aa should be local
, but it ain't !!


On Wed, Aug 30, 2023 at 5:59 PM Andreas Kusalananda Kähäri <
andreas.kah...@abc.se> wrote:

> On Wed, Aug 30, 2023 at 03:40:21PM +0300, queency3 jones wrote:
> >
>
> > From: queen...@gmail.com
> > To: bug-bash@gnu.org
> > Subject: 2 same var name in different function causing mix
> >
> > Configuration Information [Automatically generated, do not change]:
> > Machine: x86_64
> > OS: linux-gnu
> > Compiler: gcc
> > Compilation CFLAGS: -g -O2
> -fdebug-prefix-map=/build/bash-2bxm7h/bash-5.0=. -fstack-protector-strong
> -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security
> > uname output: Linux debian 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2
> (2023-08-08) x86_64 GNU/Linux
> > Machine Type: x86_64-pc-linux-gnu
> >
> > Bash Version: 5.0
> > Patch Level: 3
> > Release Status: release
> >
> > Description:
> >
> > function sub { aa=8;return_value=$aa; }
> > function sub { aa=8; }
> >
> > function main { aa=3;sub;aa=$(($aa+1));printf "$aa\n"; }
> >
> >
> > calling main will print 9 instead of 4
> >
> >
>
> Not a bug.
>
> The code outputs "9" because the scope of the variable "aa" is global
> (once it has been created in "main").  The second function "sub" will
> therefore modify the value of the variable "aa" in the global scope.
> The change in the variabel's value will be visible in "main" after the
> call to "sub".
>
> To make the variable local to the "sub" function, use the "local"
> keyword:
>
> function sub { local aa=8; }
>
> This will create a local variable "aa" in the function "sub" that will
> not be visible outside of the function.  In particular, it will not
> overwrite the global variable "aa" in "main" and the value of "aa" in
> "main" will remain unchanged (until you increment it from "3" to "4").
>
> On an unrelated note, you sohuld be printing the value using a static
> formatting string, like so:
>
> printf '%s\n' "$aa"
>
> This avoids interpreting the value of the variable as a printf formatting
> string.
>
> --
> Andreas (Kusalananda) Kähäri
> SciLifeLab, NBIS, ICM
> Uppsala University, Sweden
>
> .
>


Re: bug attached

2023-08-31 Thread Chet Ramey

On 8/31/23 3:38 PM, queency3 jones wrote:

i don't think that main is significant when it declared in "Bash" but even
though,
if you change the function main , to function ain  the $aa should be local
, but it ain't !!


Why? Are you saying that all variable assignments in functions should act
as if the variable is local?

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




Re: bug attached

2023-08-31 Thread Greg Wooledge
On Thu, Aug 31, 2023 at 10:38:55PM +0300, queency3 jones wrote:
> > > function sub { aa=8;return_value=$aa; }
> > > function sub { aa=8; }
> > >
> > > function main { aa=3;sub;aa=$(($aa+1));printf "$aa\n"; }

> i don't think that main is significant when it declared in "Bash" but even
> though,
> if you change the function main , to function ain  the $aa should be local
> , but it ain't !!

Bash uses dynamic variable scope.  If a function needs to retrieve
the value from a variable, it looks at its own local variables first,
then at its caller's local variables, then it's caller's caller's
variables, and so on up the stack.

Since main calls sub, "aa=8" in sub look for a local variable in sub.
There isn't one, so it looks for a local variable in main.  And if
there isn't one in main, then it looks in main's caller, which happens
to be the global scope.

If you add "local aa" inside main, this doesn't change anything inside
main or sub.  sub will find the local variable aa inside main, and it
will change that one, instead of the global one.  The difference here
is that the modified aa is no longer visible at the global scope.  It
"disappears" when main is finished.

If you add "local aa" inside sub, this *does* change the result.  Now,
aa=8 is executed upon the copy of aa that's local to sub, rather than
the one that's local to main.  So, main's copy remains set to 3.

If you want *every* copy of aa to be treated as a local variable within
its own function, you must declare it as local inside every function
where it's used.  That's the way bash works: every variable is non-local
by default.



Re: bug attached

2023-08-31 Thread Andreas Kusalananda Kähäri
On Thu, Aug 31, 2023 at 10:38:55PM +0300, queency3 jones wrote:
> i don't think that main is significant when it declared in "Bash" but even
> though,
> if you change the function main , to function ain  the $aa should be local
> , but it ain't !!

Function names being "main" or "ain" is irrelevant (the shell does
not give significance to their name).  The scope of the variable "aa"
is global in all functions in your example.  If you want a variable
to be local to a function, you need to declare it as such.  Note that
declaring a variable as local in your "main" function will give it a
scope that stretches into the called "sub" function.  If you want the
changes that "sub" makes to the variable be local to that function, then
you need to declare it as local in "sub", like I showed.

Quoting the manual:

Variables local to the function may be declared with the local
builtin command (local variables).  Ordinarily, variables and
their values are shared between the function and its caller.
If a variable is declared local, the variable's visible scope
is restricted to that function and its children (including the
functions it calls).



> 
> 
> On Wed, Aug 30, 2023 at 5:59 PM Andreas Kusalananda Kähäri <
> andreas.kah...@abc.se> wrote:
> 
> > On Wed, Aug 30, 2023 at 03:40:21PM +0300, queency3 jones wrote:
> > >
> >
> > > From: queen...@gmail.com
> > > To: bug-bash@gnu.org
> > > Subject: 2 same var name in different function causing mix
> > >
> > > Configuration Information [Automatically generated, do not change]:
> > > Machine: x86_64
> > > OS: linux-gnu
> > > Compiler: gcc
> > > Compilation CFLAGS: -g -O2
> > -fdebug-prefix-map=/build/bash-2bxm7h/bash-5.0=. -fstack-protector-strong
> > -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security
> > > uname output: Linux debian 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2
> > (2023-08-08) x86_64 GNU/Linux
> > > Machine Type: x86_64-pc-linux-gnu
> > >
> > > Bash Version: 5.0
> > > Patch Level: 3
> > > Release Status: release
> > >
> > > Description:
> > >
> > > function sub { aa=8;return_value=$aa; }
> > > function sub { aa=8; }
> > >
> > > function main { aa=3;sub;aa=$(($aa+1));printf "$aa\n"; }
> > >
> > >
> > > calling main will print 9 instead of 4
> > >
> > >
> >
> > Not a bug.
> >
> > The code outputs "9" because the scope of the variable "aa" is global
> > (once it has been created in "main").  The second function "sub" will
> > therefore modify the value of the variable "aa" in the global scope.
> > The change in the variabel's value will be visible in "main" after the
> > call to "sub".
> >
> > To make the variable local to the "sub" function, use the "local"
> > keyword:
> >
> > function sub { local aa=8; }
> >
> > This will create a local variable "aa" in the function "sub" that will
> > not be visible outside of the function.  In particular, it will not
> > overwrite the global variable "aa" in "main" and the value of "aa" in
> > "main" will remain unchanged (until you increment it from "3" to "4").
> >
> > On an unrelated note, you sohuld be printing the value using a static
> > formatting string, like so:
> >
> > printf '%s\n' "$aa"
> >
> > This avoids interpreting the value of the variable as a printf formatting
> > string.
> >
> > --
> > Andreas (Kusalananda) Kähäri
> > SciLifeLab, NBIS, ICM
> > Uppsala University, Sweden
> >
> > .
> >

-- 
Andreas (Kusalananda) Kähäri
SciLifeLab, NBIS, ICM
Uppsala University, Sweden

.



Re: bug attached

2023-08-31 Thread queency3 jones
yes ! the local declaration solved my problem.
tnx very much .

On Thu, Aug 31, 2023 at 10:51 PM Andreas Kusalananda Kähäri <
andreas.kah...@abc.se> wrote:

> On Thu, Aug 31, 2023 at 10:38:55PM +0300, queency3 jones wrote:
> > i don't think that main is significant when it declared in "Bash" but
> even
> > though,
> > if you change the function main , to function ain  the $aa should be
> local
> > , but it ain't !!
>
> Function names being "main" or "ain" is irrelevant (the shell does
> not give significance to their name).  The scope of the variable "aa"
> is global in all functions in your example.  If you want a variable
> to be local to a function, you need to declare it as such.  Note that
> declaring a variable as local in your "main" function will give it a
> scope that stretches into the called "sub" function.  If you want the
> changes that "sub" makes to the variable be local to that function, then
> you need to declare it as local in "sub", like I showed.
>
> Quoting the manual:
>
> Variables local to the function may be declared with the local
> builtin command (local variables).  Ordinarily, variables and
> their values are shared between the function and its caller.
> If a variable is declared local, the variable's visible scope
> is restricted to that function and its children (including the
> functions it calls).
>
>
>
> >
> >
> > On Wed, Aug 30, 2023 at 5:59 PM Andreas Kusalananda Kähäri <
> > andreas.kah...@abc.se> wrote:
> >
> > > On Wed, Aug 30, 2023 at 03:40:21PM +0300, queency3 jones wrote:
> > > >
> > >
> > > > From: queen...@gmail.com
> > > > To: bug-bash@gnu.org
> > > > Subject: 2 same var name in different function causing mix
> > > >
> > > > Configuration Information [Automatically generated, do not change]:
> > > > Machine: x86_64
> > > > OS: linux-gnu
> > > > Compiler: gcc
> > > > Compilation CFLAGS: -g -O2
> > > -fdebug-prefix-map=/build/bash-2bxm7h/bash-5.0=.
> -fstack-protector-strong
> > > -Wformat -Werror=format-security -Wall -Wno-parentheses
> -Wno-format-security
> > > > uname output: Linux debian 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2
> > > (2023-08-08) x86_64 GNU/Linux
> > > > Machine Type: x86_64-pc-linux-gnu
> > > >
> > > > Bash Version: 5.0
> > > > Patch Level: 3
> > > > Release Status: release
> > > >
> > > > Description:
> > > >
> > > > function sub { aa=8;return_value=$aa; }
> > > > function sub { aa=8; }
> > > >
> > > > function main { aa=3;sub;aa=$(($aa+1));printf "$aa\n"; }
> > > >
> > > >
> > > > calling main will print 9 instead of 4
> > > >
> > > >
> > >
> > > Not a bug.
> > >
> > > The code outputs "9" because the scope of the variable "aa" is global
> > > (once it has been created in "main").  The second function "sub" will
> > > therefore modify the value of the variable "aa" in the global scope.
> > > The change in the variabel's value will be visible in "main" after the
> > > call to "sub".
> > >
> > > To make the variable local to the "sub" function, use the "local"
> > > keyword:
> > >
> > > function sub { local aa=8; }
> > >
> > > This will create a local variable "aa" in the function "sub" that will
> > > not be visible outside of the function.  In particular, it will not
> > > overwrite the global variable "aa" in "main" and the value of "aa" in
> > > "main" will remain unchanged (until you increment it from "3" to "4").
> > >
> > > On an unrelated note, you sohuld be printing the value using a static
> > > formatting string, like so:
> > >
> > > printf '%s\n' "$aa"
> > >
> > > This avoids interpreting the value of the variable as a printf
> formatting
> > > string.
> > >
> > > --
> > > Andreas (Kusalananda) Kähäri
> > > SciLifeLab, NBIS, ICM
> > > Uppsala University, Sweden
> > >
> > > .
> > >
>
> --
> Andreas (Kusalananda) Kähäri
> SciLifeLab, NBIS, ICM
> Uppsala University, Sweden
>
> .
>


Re: bug#65659: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Eric Blake
On Thu, Aug 31, 2023 at 03:10:58PM -0400, Chet Ramey wrote:
> On 8/31/23 11:35 AM, Eric Blake wrote:
> > In today's Austin Group call, we discussed the fact that printf(1) has
> > mandated behavior for %b (escape sequence processing similar to XSI
> > echo) that will eventually conflict with C2x's desire to introduce %b
> > to printf(3) (to produce 0b000... binary literals).
> > 
> > For POSIX Issue 8, we plan to mark the current semantics of %b in
> > printf(1) as obsolescent (it would continue to work, because Issue 8
> > targets C17 where there is no conflict with C2x), but with a Future
> > Directions note that for Issue 9, we could remove %b entirely, or
> > (more likely) make %b output binary literals just like C.
> 
> I doubt I'd ever remove %b, even in posix mode -- it's already been there
> for 25 years.

But the longer that printf(3) supports "%b" to output binary values,
the more surprised new shell coders will be that printf(1) %b does not
behave the same.  What's more, other languages have already started
using %b for binary output (python, for example), so it is definitely
gaining in mindshare.

That said, I also agree with your desire to keep the functionality in
place.  The current POSIX says that %b was added so that on a non-XSI
system, you could do:

my_echo() {
  printf %b\\n "$*"
}

and then call my_echo everywhere that a script used to depend on XSI
echo (perhaps by 'alias echo=my_echo' with aliases enabled), for a
much quicker portability hack than a tedious search-and-replace of
every echo call that requires manual inspection of its arguments for
translation of any XSI escape sequences into printf format
specifications.  In particular, code like [var='...\c'; echo "$var"]
cannot be changed to use printf by a mere s/echo/printf %s\\n/.  Thus,
when printf was invented and standardized for the shell, the solution
at the time was to create [printf %b\\n "$var"] as a drop-in
replacement for XSI [echo "$var"], even for platforms without XSI
echo.

Nowadays, I personally have not seen very many scripts like this in
the wild (for example, autoconf scripts prefer to directly use printf,
rather than trying to shoe-horn behavior into echo).  But assuming
such legacy scripts still exist, it is still much easier to rewrite
just the my_echo wrapper to now use %#s\\n instead of %b\\n, than it
would be to find every callsite of my_echo.

Bash already has shopt -s xpg_echo; I could easily see this being a
case where you toggle between the old or new behavior of %b (while
keeping %#s always at the old behavior) by either this or some other
shopt in bash, so that newer script writers that want binary output
for %b can do so with one setting, while scripts that must continue to
run under old semantics can likewise do so.

> 
> > But that
> > raises the question of whether the escape-sequence processing
> > semantics of %b should still remain available under the standard,
> > under some other spelling, since relying on XSI echo is still not
> > portable.
> > 
> > One of the observations made in the meeting was that currently, both
> > the POSIX spec for printf(1) as seen at [1], and the POSIX and C
> > standard (including the upcoming C2x standard) for printf(3) as seen
> > at [3] state that both the ' and # flag modifiers are currently
> > undefined when applied to %s.
> 
> Neither one is a very good choice, but `#' is the better one. It at least
> has a passing resemblence to the desired functionality.

Indeed, that's what the Austin Group settled on today after I first
wrote my initial email, and what I wrote up in a patch to GNU
Coreutils (https://debbugs.gnu.org/65659)

> 
> Why not standardize another character, like %B? I suppose I'll have to look
> at the etherpad for the discussion. I think that came up on the mailing
> list, but I can't remember the details.

Yes, https://austingroupbugs.net/view.php?id=1771 has a good
discussion of the various ideas.

%B is out for the same reason as %b: although the current C2x draft
wording says that % is reserved for implementation use, other
than [AEFGX] which already have a history of use by C (as it was, when
C99 added %A, that caused problems for some folks), it goes on to
_highly_ encourage any implementation that adds %b for "0b0" binary
output also add %B for "0B0" binary output (to match the x/X
dichotomy).  Burning %B to retain the old behavior while repurposing
%b to output lower-case binary values is thus a non-starter, while
burning %#s (which C says is undefined) felt nicer.

The Austin Group also felt that standardizing bash's behavior of %q/%Q
for outputting quoted text, while too late for Issue 8, has a good
chance of success, even though C says %q is reserved for
standardization by C. Our reasoning there is that lots of libc over
the years have used %qi as a synonym for %lli, and C would be foolish
to burn %q for anything that does not match those semantics at the C
language level; which means it will likely never be claimed by C and
thus 

Re: bug#65659: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Emanuele Torre
On Thu, Aug 31, 2023 at 03:02:22PM -0500, Eric Blake wrote:
> On Thu, Aug 31, 2023 at 03:10:58PM -0400, Chet Ramey wrote:
> > Why not standardize another character, like %B? I suppose I'll have to look
> > at the etherpad for the discussion. I think that came up on the mailing
> > list, but I can't remember the details.
> 
> Yes, https://austingroupbugs.net/view.php?id=1771 has a good
> discussion of the various ideas.
> 
> %B is out for the same reason as %b: although the current C2x draft
> wording says that % is reserved for implementation use, other
> than [AEFGX] which already have a history of use by C (as it was, when
> C99 added %A, that caused problems for some folks), it goes on to
> _highly_ encourage any implementation that adds %b for "0b0" binary
> output also add %B for "0B0" binary output (to match the x/X
> dichotomy).  Burning %B to retain the old behavior while repurposing
> %b to output lower-case binary values is thus a non-starter, while
> burning %#s (which C says is undefined) felt nicer.

Also note that, in ksh93, %B is already used for something else.
It interprets its argument as a variable name, and dereferences it:
`printf %B PWD' is similar to `printf %s "$PWD"' (assuming PWD is a
string variable).

o/
 emanuele6



Re: [PATCH] printf: add %#s alias to %b

2023-08-31 Thread Eric Blake
On Thu, Aug 31, 2023 at 04:01:17PM -0500, Rob Landley wrote:
> On 8/31/23 13:31, Eric Blake wrote:
> > POSIX Issue 8 will be obsoleting %b (escape sequence interpolation) so
> > that future Issue 9 can change to having %b (binary literal output)
> > that aligns with C2x.
> 
> I.E. you sent an RFC to that effect to the posix list earlier today, and so 
> far
> the only reply on the posix list was the bash maintainer, who said "I doubt 
> I'd
> ever remove %b, even in posix mode -- it's already been there for 25 years."

The RFC to the POSIX list was started earlier than today
(https://austingroupbugs.net/view.php?id=1771 was filed on Aug 7, not
by me; and by Aug 8 we had already identified the future conflict with
C2x %b).  But you are right that today was the first time I widened
the audience by mailing coreutils and bash (rather than just the few
developers that follow the POSIX mailing list).  There are also plans
to ask the same question of other shell developers (dash, BSD,
busybox, ...); but I figured I'd start with the people and code I know
best.

It's not hard to see why POSIX is choosing to have Issue 8 obsoleting
(not removing) %b's old semantics; in the short term, nothing about %b
changes, so your dusty-deck shell scripts will continue to work as
they have before; but you now have enough time to update your scripts.
The question is whether Issue 9 (several years down the road) will be
able to repurpose %b to mean binary literal output (only possible if
all shell authors agree that C2X compatibility is worth it), or must
instead just undocument %b altogether (shells can always provide
extensions that POSIX doesn't document - and the obvious extensions in
that case would be a shell's choice of %b with the old semantics or %b
to do binary literals).

But if POSIX _is_ able to repurpose %b (because enough shell authors
agree that binary output is more useful these days than XSI echo
compatibility), the followon question is whether there should be a
portable way to access the old functionality.  Since %#s is currently
unspecified, we are trying to guage feedback of how many
implementations are willing to add that alias now, which in turn will
affect whether Issue 9 can mandate that behavior (because everyone
liked it) or must continue to leave it undefined.

But nothing is stopping coreutils from adding %#s as an extension now,
regardless of what input other shell authors provide to the ongoing
POSIX discussion.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org




Inner Command Groups fail in Bash 5.2

2023-08-31 Thread Dima Korobskiy

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin20.6.0
Compiler: clang
Compilation CFLAGS: -DSSH_SOURCE_BASHRC
uname output: Darwin San-Francisco-iMac.local 20.6.0 Darwin Kernel 
Version 20.6.0: Thu Jul  6 22:12:47 PDT 2023; 
root:xnu-7195.141.49.702.12~1/RELEASE_X86_$

Machine Type: x86_64-apple-darwin20.6.0

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

Description:
    One of my Bash scripts started to fail all of a sudden and I 
was able to narrow down this problem to Bash upgrade itself (via 
Homebrew on a Mac): from 5.1.16 to 5.2.15.
It looks to me pretty serious: a lot of scripts might be potentially 
affected.


Repeat-By:

# Bash 5.1.16: success
# Bash 5.2.15: syntax error near unexpected token `}'
var2=$(time { echo foo; echo bar; })
echo -e "\nvar2=\`$var2\`"

# Bash 5.1.16: success
# Bash 5.2.15: syntax error near unexpected token `echo'
var3=$(time (echo foo; echo bar))
echo -e "\nvar3=\`$var3\`"

Fix:
   The scripts have to change to work around this problem: to 
refactor out an inner command group. It might or might not be feasible. 
For example, the fix for the script above:


time var4=$(echo foo; echo bar)
echo -e "\nvar4=\`$var4\`"

--
🇺🇸 Dima Korobskiy 🇺🇦




Inner Command Lists fail in Bash 5.2.15

2023-08-31 Thread dkroot2
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin20.6.0
Compiler: clang
Compilation CFLAGS: -DSSH_SOURCE_BASHRC
uname output: Darwin San-Francisco-iMac.local 20.6.0 Darwin Kernel Version 
20.6.0: Thu Jul  6 22:12:47 PDT 2023; 
root:xnu-7195.141.49.702.12~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin20.6.0

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

Description:
I've run into a regression in one of my scripts after upgrading Bash 
from 5.1.16 to 5.2.15 via HomeBrew on a Mac.
I was able to narrow it down to the Bash upgrade itself. The problem seems to 
be a pretty serious one that can affect a lot of scripts.

Repeat-By:

# Bash 5.1.16: success
# Bash 5.2.15: syntax error near unexpected token `}'
var2=$(time { echo foo; echo bar; })
echo -e "\nvar2=\`$var2\`"

# Bash 5.1.16: success
# Bash 5.2.15: syntax error near unexpected token `)'
var3=$(time (echo foo; echo bar))
echo -e "\nvar3=\`$var3\`"

Fix:
[Description of how to fix the problem.  If you don't know a
fix for the problem, don't include this section.]



riscv32, qemu-user: semi-functional, what goes wrong?

2023-08-31 Thread Andreas K. Huettel
Dear all, 

I'm trying to get qemu usermode emulation of riscv32 working.
I managed to cross-build a linux system, and have it mostly rebuild itself
(including gcc 3-phase bootstrap), however, something is broken in bash.

Which may very well be a qemu usermode emulation bug, as I'm told bash works
fine in a riscv32 system emulation.

Below is the output of the bash testsuite. Any advice on where to 
start looking for problems would be appreciated. 

Best, Andreas


>>> Test phase: app-shells/bash-5.2_p15-r6
make -j1   check
make[1]: Entering directory 
'/var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/builtins'
make[1]: 'pipesize.h' is up to date.
make[1]: Leaving directory 
'/var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/builtins'

  ***
  * *
  * GNU bash, version 5.2.15(1)-release (riscv32-unknown-linux-gnu)
  * *
  ***

declare -r SHELLOPTS="braceexpand:hashall:interactive-comments"
Testing /var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/bash
version: 5.2.15(1)-release
versinfo: 5 2 15 1 release riscv32-unknown-linux-gnu
HOSTTYPE = riscv32
OSTYPE = linux-gnu
MACHTYPE = riscv32-unknown-linux-gnu
Any output from any test, unless otherwise noted, indicates a possible anomaly
run-alias
run-appendop
run-arith
run-arith-for
run-array
warning: all of these tests will fail if arrays have not
warning: been compiled into the shell
warning: the BASH_ARGC and BASH_ARGV tests will fail if debugging support
warning: has not been compiled into the shell
run-array2
warning: all of these tests will fail if arrays have not
warning: been compiled into the shell
run-assoc
warning: all of these tests will fail if arrays have not
warning: been compiled into the shell
run-attr
run-braces
run-builtins
warning: some of these tests may fail if process substitution has not
warning: been compiled into the shell or if the OS does not provide
warning: /dev/fd.
88,89c88,89
< /var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/bash
< /var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/bash
---
> specialname
> -specialname
run-case
run-casemod
run-complete
run-comsub
run-comsub-eof
run-comsub-posix
run-cond
warning: all of these tests will fail if the conditional command has not
warning: been compiled into the shell
warning: some of these tests will fail if extended pattern matching has not
warning: been compiled into the shell
run-coproc
run-cprint
run-dbg-support
run-dbg-support2
run-dirstack
run-dollars
run-dynvar
run-errors
run-execscript
warning: the text of a system error message may vary between systems and
warning: produce diff output.
warning: UNIX versions number signals differently.
warning: If output differing only in line numbers is produced, please
warning: do not consider this a test failure.
warning: if the text of the error messages concerning `notthere' or
warning: `/tmp/bash-notthere' not being found or `/' being a directory
warning: produce diff output, please do not consider this a test failure
warning: if diff output differing only in the location of the bash
warning: binary appears, please do not consider this a test failure
24d23
< trap -- 'echo USR1' SIGUSR1
25a25
> trap -- 'echo USR1' SIGUSR1
30d29
< trap -- 'echo USR1' SIGUSR1
31a31
> trap -- 'echo USR1' SIGUSR1
47c47
< this is /var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/bash
---
> this is ohio-state
run-exp-tests
run-exportfunc
run-extglob
run-extglob2
run-extglob3
run-func
warning: if you have exported functions defined in your environment,
warning: they may show up as diff output.
warning: if so, please do not consider this a test failure
run-getopts
run-glob-test
2,3d1
< glob2.sub: warning: you do not have the zh_HK.big5hkscs locale installed;
< glob2.sub: warning: that will cause some of these tests to fail.
9d6
< ./glob2.sub: line 44: warning: setlocale: LC_ALL: cannot change locale 
(zh_HK.big5hkscs): No such file or directory
11c8
< argv[1] = 
---
> argv[1] = 
14,15c11,12
< argv[1] = 
< 000 141 316 261 142
---
> argv[1] = 
> 000 141 243 134 142
18,19d14
< ./glob2.sub: line 65: warning: setlocale: LC_ALL: cannot change locale 
(zh_HK.big5hkscs)
< /var/tmp/portage/app-shells/bash-5.2_p15-r6/work/bash-5.2/bash: warning: 
setlocale: LC_ALL: cannot change locale (zh_HK.big5hkscs)
run-globstar
run-heredoc
warning: UNIX versions number signals and schedule processes differently.
warning: If output differing only in line numbers is produced, please
warning: do not consider this a test failure.
129c129
< /bin/grep: *.c: No such file or directory
---
> grep: *.c: No such file or directory
run-herestr
run-histexpand
warning: all of these tests will fail if history has not been compiled
warning: into the shell
run-history
warning: all of t

Re: Inner Command Lists fail in Bash 5.2.15

2023-08-31 Thread Kerin Millar
On Thu, 31 Aug 2023 12:05:21 -0400 (EDT)
dkro...@gmail.com wrote:

> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: darwin20.6.0
> Compiler: clang
> Compilation CFLAGS: -DSSH_SOURCE_BASHRC
> uname output: Darwin San-Francisco-iMac.local 20.6.0 Darwin Kernel Version 
> 20.6.0: Thu Jul  6 22:12:47 PDT 2023; 
> root:xnu-7195.141.49.702.12~1/RELEASE_X86_64 x86_64
> Machine Type: x86_64-apple-darwin20.6.0
> 
> Bash Version: 5.2
> Patch Level: 15
> Release Status: release
> 
> Description:
>   I've run into a regression in one of my scripts after upgrading Bash 
> from 5.1.16 to 5.2.15 via HomeBrew on a Mac.
> I was able to narrow it down to the Bash upgrade itself. The problem seems to 
> be a pretty serious one that can affect a lot of scripts.
> 
> Repeat-By:
> 
> # Bash 5.1.16: success
> # Bash 5.2.15: syntax error near unexpected token `}'
> var2=$(time { echo foo; echo bar; })

This looks like a casualty of the changes made for 5.2 that have it validate 
syntax recursively. The error message suggests that "time" is not considered to 
be a keyword there, even though it is. In any case, here is a temporary 
workaround for this regression.

$ declare -- BASH_VERSION="5.2.15(1)-release"
$ var2=$(:; time { echo foo; echo bar; })

real0m0.000s
user0m0.000s
sys 0m0.000s

-- 
Kerin Millar



Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Phi Debian
On Thu, Aug 31, 2023 at 9:11 PM Chet Ramey  wrote:

>
> I doubt I'd ever remove %b, even in posix mode -- it's already been there
> for 25 years.
>
>
> Neither one is a very good choice, but `#' is the better one. It at least
> has a passing resemblence to the desired functionality.
>
> Why not standardize another character, like %B? I suppose I'll have to look
> at the etherpad for the discussion. I think that came up on the mailing
> list, but I can't remember the details.
>
>
Glad I red this thread before replying to the other one dealing with the
same issue.

I once worked on an issue on ksh93 regarding printf discrepency vs libc
printf, and got replied that "ksh is not C". I Think we got to admit that
shell's printf have departed from libc since long and now if a feature in
libc appears and collide with printf(1) then we got to get yet another %
exception char. In bash docco I see %b %q and %(datefmt...), so for a new
feature we should get something that we think libc as little chance to
target.

My vote is for posix_printf %B mapping to libc_printf %b, with the idea
that libc has little chance to have %B meaning UPPERCASE BINARY :-),  as %x
%X do.

And yet one more line in the docco explaining this divergence.


Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Phi Debian
Well after reading yet another thread regarding libc_printf() I got to
admit that even %B is crossed out, (Yet already choosen by ksh93)

The other thread also speak about libc_printf() documentting %# as
undefined for things other than  a, A, e, E, f, F, g, and G, yet the same
thread also talk about a A comming late (citing C99) in the dance, meaning
what is undefined today become defined tomorow, so %#b is no safer.

My guess is that printf(1) is now doomed to follow its route, keep its old
format exception, and then may be implement something like c_printf like
printf but the format string follow libc semantic, or may be a -C option to
printf(1)...

Well in all case %b can not change semantic in the bash script, since it is
there for so long, even if it depart from python, perl, libc, it is
unfortunate but that's the way it is, nobody want a semantic change, and on
next routers update, see the all internet falling appart :-)


Re: give_terminal_to() / maybe_give_terminal_to() race

2023-08-31 Thread Earl Chew

On 2023-08-30 07:39, Chet Ramey wrote:

OK, so there is a potential race condition here. What do you suggest the
right approach might be? It seems to me we can do one of two things:
rearrange and extend the PGRP_PIPE code to make sure the child process
doesn't proceed until the parent sets the terminal process group; or
change stop_pipeline() (and audit its callers, of course) so it does not
set the terminal process group.


I experimented a bit, and gave the matter some thought. The controlling
terminal must be reconfigured before the parent gets to wait() for the
job, and before the child gets to exec() the program (or their
equivalents). This means that there must be some synchronisation
to ensure that these conditions are true.

Either the parent must yield the controlling terminal, or the child
must acquire the controlling terminal, and the other must block
until the outcome has been achieved.

Since PGRP_PIPE supports the parent providing a synchronisation signal,
it aligns with the parent yielding the controlling terminal. Presently,
there is no mechanism for the child to trigger a synchronisation
with the parent. For this reason, I think the first option you list
is a more straightforward fit for the implementation.

Should I go ahead and propose a patch?

Earl



Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Stephane Chazelas
2023-08-31 10:35:59 -0500, Eric Blake via austin-group-l at The Open Group:
> In today's Austin Group call, we discussed the fact that printf(1) has
> mandated behavior for %b (escape sequence processing similar to XSI
> echo) that will eventually conflict with C2x's desire to introduce %b
> to printf(3) (to produce 0b000... binary literals).
[...]

Is C2x's %b already set in stone?

ksh93's printf (and I'd  expect ast's standalone printf) has
%[,[,]d to output a number in an
arbitrary base which IMO seems like a better approach than
introducing a new specifier for every base.

$ printf '%..2d\n' 63
11
$ printf '0b%.8.2d\n' 63
0b0011
$ printf '%#.8.2d\n' 63
2#0011

The one thing it can't do though is left-space-padding of 0b.

printf %b is used in countless scripts especially the more
correct/portable ones that use it to work around the portability
fiasco that is echo's escape sequence expansion. I can't imagine
it going away. Hard to imagine the C folks overlooked it, I'd
expect printf %b to be known by any shell scripter.

-- 
Stephane



Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Oğuz
On Fri, Sep 1, 2023 at 7:41 AM Phi Debian  wrote:
> My vote is for posix_printf %B mapping to libc_printf %b

In the shell we already have bc for base conversion. Does POSIX really
have to support C2x %b in the first place?



Re: RFC: changing printf(1) behavior on %b

2023-08-31 Thread Stephane Chazelas
2023-09-01 07:13:36 +0100, Stephane Chazelas via austin-group-l at The Open 
Group:
> 2023-08-31 10:35:59 -0500, Eric Blake via austin-group-l at The Open Group:
> > In today's Austin Group call, we discussed the fact that printf(1) has
> > mandated behavior for %b (escape sequence processing similar to XSI
> > echo) that will eventually conflict with C2x's desire to introduce %b
> > to printf(3) (to produce 0b000... binary literals).
> [...]
> 
> Is C2x's %b already set in stone?
> 
> ksh93's printf (and I'd  expect ast's standalone printf) has
> %[,[,]d to output a number in an
> arbitrary base which IMO seems like a better approach than
> introducing a new specifier for every base.
[...]

For completeness, several shells also support expanding integers
in arbitrary bases.

Like ksh's

typeset -i2 binary=123

already there in ksh85, possibly earlier, also available in
pdksh and derivatives and zsh.

Originally with the base number not specified the output base
was derived from the first assignment like typeset -i var;
var='2#111' would get you a $var that expands in binary. Looks
like that was discontinued in ksh93, but it's still there in
mksh or zsh.

And there's also:

$ echo $(( [#2] 16 )) $(( [##2] 16 ))
2#1 1

In zsh (note that you don't get 0b1 upon $(( [#2] 16 ))
after set -o cbases).

If bash added:

printf -v var %..2 16

à la ksh93, that would bridge that gap.

How to output/expand numbers in bases other thn 8, 10, 16 is a
recurring question for bash, with people generally surprised
that it can *input* numbers in any base, but not *output* in any
base.

See
https://unix.stackexchange.com/questions/415077/how-to-add-two-hexadecimal-numbers-in-a-bash-script/415107#415107
https://unix.stackexchange.com/questions/616215/bash-arithmetic-outputs-result-in-decimal
https://unix.stackexchange.com/questions/749988/arbitrary-base-conversion-from-base-10-using-only-builtins-in-bash
to list only a few.

-- 
Stephane