Re: local -r issue in conjunction with trap

2022-07-16 Thread Robert Elz
Date:Fri, 15 Jul 2022 16:13:40 + (UTC)
From:Robert Stoll 
Message-ID:  <1549965963.26496.1657901620717.javamail.zim...@tegonal.com>

  | Unfortunately I have never built bash on my own and it would probably
  | take me too much time to do it.

It probably wouldn't, fetch the tarball, unpack it, ./configure && make
and you're done (after a short wait).

But that's only useful if a newer version fixes some problem, or if you
want to make changes of your own - the latter can certainly take time.

  | Thus, I am writing to this e-mail in the hope that someone more
  | experienced can try to reproduce it with the latest version.

There is no need, what you're seeing isn't a bug.  readonly variables
cannot be made local, the bash man page even says so ...

  The return status is 0 unless local
  is used outside a function, an invalid name is supplied, or name
  is a readonly variable.

The "readonly in a function can be made local in another function" thing
most likely is a bug - but (as I have said before, and will keep on saying)
bash's view of what a local variable should be is simply weird.   It isn't
true lexical scoping, like Korn was (IMO, inadvisedly) trying to achieve
in ksh, and it isn't simple and sane like other shells, just a mess.

One last comment - you probably shouldn't be using read only variables
at all, they're a rather special use case, and attempting to make a local
read only variable is weird in itself, but with the same name as some other
read only variable, is simply perverse.   Read only vars are best left for
applications which need something they can depend on not being able to be
changed (by anything - which is why making one local is not supposed to work)
in which case they tend to have names you're not likely to trip over by
accident when making a local var in a function.

kre





Gettings LINES and COLUMNS from stderr instead of /dev/tty

2022-07-16 Thread Martin Schulte
Hello,

I'm just wondering that bash (reproduced with 5.2-rc1 under Debian 11) seems to 
determine LINES and COLUMNS from stderr.

For example, this will lead to strange results when starting the script

#!/bin/bash

shopt -s checkwinsize
trap 'echo $LINES $COLUMNS' SIGWINCH
while true; do sleep 0.1; done

with standard error redirected to a file (or - even more strange ;-) - another 
terminal).

A quick POC shows that replacing
  tty = input_tty ();
with
  tty = open( "/dev/tty", O_RDONLY );
in get_new_windows_size in lib/sh/winsize.c gives the "expected" result.

In case there is some reason not to use /dev/tty, wouldn't it then be better to 
ask stdin instead of stderr? The script will most probably be interested in the 
size of device it is writing to, not the one it is logging to.

Best regards

Martin



Arithmetic expression: interest in unsigned right shift?

2022-07-16 Thread Steffen Nurpmeso
Hello.

I realized there is no unsigned right shift in bash arithmetic
expression, and thought maybe there is interest.
This is a not even compile-tested diff against 5.1.16.
(Using same tab/space as in surroundings.)

A nice Sunday i wish everyone.

diff -Napru bash-5.1.orig/expr.c bash-5.1/expr.c
--- bash-5.1.orig/expr.c2022-07-16 19:35:21.900221532 +0200
+++ bash-5.1/expr.c 2022-07-16 19:37:23.243552559 +0200
@@ -32,7 +32,7 @@
"**"[(exponentiation)]
"*", "/", "%"
"+", "-"
-   "<<", ">>"
+   "<<", ">>", ">>>"
"<=", ">=", "<", ">"
"==", "!="
"&"
@@ -41,7 +41,7 @@
"&&"
"||"
"expr ? expr : expr"
-   "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
+   "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=","^=","|="
,   [comma]
 
  (Note that most of these operators have special meaning to bash, and an
@@ -112,13 +112,14 @@
 #define LOR8   /* "||" Logical OR */
 #define LSH9   /* "<<" Left SHift */
 #define RSH10  /* ">>" Right SHift */
-#define OP_ASSIGN 11   /* op= expassign as in Posix.2 */
-#define COND   12  /* exp1 ? exp2 : exp3 */
-#define POWER  13  /* exp1**exp2 */
-#define PREINC 14  /* ++var */
-#define PREDEC 15  /* --var */
-#define POSTINC16  /* var++ */
-#define POSTDEC17  /* var-- */
+#define URSH   11  /* ">>>" Unsigned right SHift */
+#define OP_ASSIGN 12   /* op= expassign as in Posix.2 */
+#define COND   13  /* exp1 ? exp2 : exp3 */
+#define POWER  14  /* exp1**exp2 */
+#define PREINC 15  /* ++var */
+#define PREDEC 16  /* --var */
+#define POSTINC17  /* var++ */
+#define POSTDEC18  /* var-- */
 #define EQ '='
 #define GT '>'
 #define LT '<'
@@ -578,6 +579,9 @@ expassign ()
case RSH:
  lvalue >>= value;
  break;
+   case URSH:
+ lvalue = (uintmax_t)lvalue >> value;
+ break;
case BAND:
  lvalue &= value;
  break;
@@ -837,7 +841,7 @@ expshift ()
 
   val1 = exp3 ();
 
-  while ((curtok == LSH) || (curtok == RSH))
+  while ((curtok == LSH) || (curtok == RSH) || (curtok == URSH))
 {
   int op = curtok;
 
@@ -846,8 +850,10 @@ expshift ()
 
   if (op == LSH)
val1 = val1 << val2;
-  else
+  else if (op == RSH)
val1 = val1 >> val2;
+  else
+   val1 = (uintmax_t)val1 >> val2;
   lasttok = NUM;
 }
 
@@ -1251,6 +1257,7 @@ _is_multiop (c)
 case LOR:
 case LSH:
 case RSH:
+case URSH:
 case OP_ASSIGN:
 case COND:
 case POWER:
@@ -1424,7 +1431,19 @@ readtok ()
}
   else if ((c == GT) && (c1 == GT))
{
- if (*cp == '=')
+ if (*cp == GT)
+   {
+ cp++;
+ if (*cp == '=')
+   {
+ assigntok = URSH; /* a >>>= b */
+ c = OP_ASSIGN;
+ cp++;
+   }
+ else
+   c = URSH;
+   }
+ else if (*cp == '=')
{
  assigntok = RSH;  /* a >>= b */
  c = OP_ASSIGN;

--steffen
|
|Der Kragenbaer,The moon bear,
|der holt sich munter   he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)



Re: Arithmetic expression: interest in unsigned right shift?

2022-07-16 Thread Dale R. Worley
Steffen Nurpmeso  writes:
> I realized there is no unsigned right shift in bash arithmetic
> expression, and thought maybe there is interest.

This would be difficult to define cleanly.

Currently, arithmetic values are considered to be signed, and >>
operates on them as such.  So

$ echo $(( 1 >> 1 ))
0
$ echo $(( 2 >> 1 ))
1
$ echo $(( 3 >> 1 ))
1
$ echo $(( (-1) >> 1 ))
-1
$ echo $(( (-2) >> 1 ))
-1
$ echo $(( (-3) >> 1 ))
-2
$ echo $(( (-4) >> 1 ))
-2
$

For positive values, unsigned right shift would be the same as >>.  But
for negative numbers, the value has to be cast into an unsigned value,
which is then right-shifted (equivalently, divided by a power of 2), and
the resulting value then has to be cast back into a signed value.

But that will depend on (reveal) the word length of Bash arithmetic
computation:  (-1) >>> 1 will be equal to 2#0..., which prints
as a positive number.  In contrast the current Bash arithmetic model is
"word-length agnostic as long as you don't overflow", it acts as if the
values are mathematical integers.

Dale



Re: Gettings LINES and COLUMNS from stderr instead of /dev/tty

2022-07-16 Thread Dale R. Worley
Martin Schulte  writes:
> I'm just wondering that bash (reproduced with 5.2-rc1 under Debian 11)
> seems to determine LINES and COLUMNS from stderr.

It's not clear to me that the manual page says where the LINES and
COLUMNS values are obtained from.

Dale



Re: local -r issue in conjunction with trap

2022-07-16 Thread Dale R. Worley
Robert Stoll  writes:
> test1 # works as exit happens outside of test1
> test2 # fails with ./src/test.sh: line 6: local: readonlyVar: readonly 
> variable

Beware that you haven't specified what you mean by "works" and "fails".
I assume from the context that "fails" means "produces an error
message", but it's much hard to guess what "works" means.  In general,
when reporting a problem, always explicitly answer "What do I expect to
happen?" and "What happens?".

Dale



Re: Arithmetic expression: interest in unsigned right shift?

2022-07-16 Thread Martin D Kealey
Hi Steffen, thanks for that.

It will be especially useful for defining ((  MAXINT = ~0 >>> 1 )).

This reminds me of some other operations I've been meaning to implement,
including true modulus +% (where the sign of the result always matches the
divisor) with the corresponding flooring division +/, binary ?: (rather
than ternary), non-modulus shifts (so that 1>>32 is 0 on both 32- and
64-bit platforms).

It should be noted that non-parameterized functions already exist, though
they're awkward to use:

f='x*x+y*y'  # reusable function
$(( x=4, y=3, f )) # 25
$(( x=10, y=2, f )) # 104

The key to parameterized functions is some form of expression-local
variables to hold the arguments and other intermediate calculations, and a
sane syntax for defining them.


More ambitiously, I'd like parameterized numeric functions, bigints,
floating point, and overflow trapping.

I'm wondering how best to introduce floating point. It seems like there are
three feasible approaches:

 (1) use the existing syntax and operators with automatic detection based
on whether the arguments are non-integers. (Although this is what C does, I
wouldn't recommend it, because it can result in surprises like 1.5+3/2 →
2.5 where 3/2 is evaluated to 1 before 1+1.5 gets handled as FP. It also
means guesswork to pick the appropriate precision  for division.)

(2) Some sort of marker for the entire expression; for $((…)) it could be
useful  to allow the expression to be prefaced by a printf format
specifier, from which the type of operation can be inferred (including as
signed/unsigned, fixing the unsigned right shift btw). Then you get to write

 $(( %#x 27 )) # 0x1b
 $(( %.4f 20/3 )) # 6.6667

For the statement form it's still necessary to specify how assignment to a
string variable should work, so I would use the same there for consistency.

 (( %u maxint=~0>>1 ))  # correct unsigned operation

(3) Extend the existing operators where floating point gives the correct
integer result with integer arguments, but define new ones where they
differ, especially division // (which is why I wouldn't use // for flooring
division). This just leaves open the question of how integer overflow
should be handled.


Complex numbers and Unicode variable names would be nice too, so that I
could write (( y = R*sin(θ) )) or even (( c = ε ** ( a * √-1 * π ) )), but
that's much further away.

On Sun, 17 Jul 2022, 03:44 Steffen Nurpmeso,  wrote:

> Hello.
>
> I realized there is no unsigned right shift in bash arithmetic
> expression, and thought maybe there is interest.
> This is a not even compile-tested diff against 5.1.16.
> (Using same tab/space as in surroundings.)
>
> A nice Sunday i wish everyone.
>
> diff -Napru bash-5.1.orig/expr.c bash-5.1/expr.c
> --- bash-5.1.orig/expr.c2022-07-16 19:35:21.900221532 +0200
> +++ bash-5.1/expr.c 2022-07-16 19:37:23.243552559 +0200
> @@ -32,7 +32,7 @@
> "**"[(exponentiation)]
> "*", "/", "%"
> "+", "-"
> -   "<<", ">>"
> +   "<<", ">>", ">>>"
> "<=", ">=", "<", ">"
> "==", "!="
> "&"
> @@ -41,7 +41,7 @@
> "&&"
> "||"
> "expr ? expr : expr"
> -   "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
> +   "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=",
> "&=","^=","|="
> ,   [comma]
>
>   (Note that most of these operators have special meaning to bash, and an
> @@ -112,13 +112,14 @@
>  #define LOR8   /* "||" Logical OR */
>  #define LSH9   /* "<<" Left SHift */
>  #define RSH10  /* ">>" Right SHift */
> -#define OP_ASSIGN 11   /* op= expassign as in Posix.2 */
> -#define COND   12  /* exp1 ? exp2 : exp3 */
> -#define POWER  13  /* exp1**exp2 */
> -#define PREINC 14  /* ++var */
> -#define PREDEC 15  /* --var */
> -#define POSTINC16  /* var++ */
> -#define POSTDEC17  /* var-- */
> +#define URSH   11  /* ">>>" Unsigned right SHift */
> +#define OP_ASSIGN 12   /* op= expassign as in Posix.2 */
> +#define COND   13  /* exp1 ? exp2 : exp3 */
> +#define POWER  14  /* exp1**exp2 */
> +#define PREINC 15  /* ++var */
> +#define PREDEC 16  /* --var */
> +#define POSTINC17  /* var++ */
> +#define POSTDEC18  /* var-- */
>  #define EQ '='
>  #define GT '>'
>  #define LT '<'
> @@ -578,6 +579,9 @@ expassign ()
> case RSH:
>   lvalue >>= value;
>   break;
> +   case URSH:
> + lvalue = (uintmax_t)lvalue >> value;
> + break;
> case BAND:
>   lvalue &= value;
>   break;
> @@ -837,7 +841,7 @@ expshift ()
>
>val1 = exp3 ();
>
> -  while ((curtok == LSH) || (curtok == RSH))
> +  while ((curtok == LSH) || (curtok == RSH) || (curtok == URSH))
>  {
>int op = curtok;
>
> @@ -846,8 +850,10 @@ expshift ()
>
>if (op == LSH)
> val1 = va

Re: Arithmetic expression: interest in unsigned right shift?

2022-07-16 Thread Martin D Kealey
Printf %u already reveals  the word size, as do most kinds of overflow -
albeit messily, like $((3**40))

At least by explicitly exposing the word size in a controlled manner, we
can write code that avoids unintended overflow.

-Martin

On Sun, 17 Jul 2022, 11:54 Dale R. Worley,  wrote:

> Steffen Nurpmeso  writes:
> > I realized there is no unsigned right shift in bash arithmetic
> > expression, and thought maybe there is interest.
>
> This would be difficult to define cleanly.
>
> Currently, arithmetic values are considered to be signed, and >>
> operates on them as such.  So
>
> $ echo $(( 1 >> 1 ))
> 0
> $ echo $(( 2 >> 1 ))
> 1
> $ echo $(( 3 >> 1 ))
> 1
> $ echo $(( (-1) >> 1 ))
> -1
> $ echo $(( (-2) >> 1 ))
> -1
> $ echo $(( (-3) >> 1 ))
> -2
> $ echo $(( (-4) >> 1 ))
> -2
> $
>
> For positive values, unsigned right shift would be the same as >>.  But
> for negative numbers, the value has to be cast into an unsigned value,
> which is then right-shifted (equivalently, divided by a power of 2), and
> the resulting value then has to be cast back into a signed value.
>
> But that will depend on (reveal) the word length of Bash arithmetic
> computation:  (-1) >>> 1 will be equal to 2#0..., which prints
> as a positive number.  In contrast the current Bash arithmetic model is
> "word-length agnostic as long as you don't overflow", it acts as if the
> values are mathematical integers.
>
> Dale
>
>