Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Kang-Che Sung
On Wednesday, September 7, 2022, Steffen Nurpmeso 
wrote:
> Kang-Che Sung wrote in
>  :
>  |On Wednesday, September 7, 2022, Steffen Nurpmeso 
>  |wrote:
>  ...
>  |>|> +  if(su_64( i > U32_MAX || ) i >= UZ_MAX / 2 ||
>  ...
>  |>|I have to admit that the amount of macro maze makes it really hard to
>  |>|read ;)
>  |>
>  |> Well it is easier than having lots of #ifdef #else #endif blocks
>  |> in my opinion.  On 32-bit the above would spit out a warning
>  |> (possibly, i have not really looked what compiler/linker flags
>  |> busybox uses) because i>U32_MAX can never be true.  I mean i could
>  ...
>  |Compiler will optimize out always-false expressions without giving any
>  |warning.
>
> Regarding the warning: not if you excess an integer limit.
> If you say if(0){} i go with you.
> Hm.  Well, actually it seems current compilers really do so in
> simplemost test files at least, like
>
>   int main(void){if(10>0xULL)return 1;return 0;}
>
> But already if it is a bit more complicated there is
>
>   int main(void){
> unsigned long long int i = 10;
> if(i>0xULL)return 1;
> return 0;}
>
>   t.c:3:6: warning: result of comparison 'unsigned long long' >
18446744073709551615 is always false [-Wtautological-type-limit-compare]
>   if(i>0xULL)return 1;
>  ~^~
>   1 warning generated.
>
> I can assure you that i am surprised, "in earlier times" you would
> have been thrown warnings at.  (gcc 12.2.0 is silent!!!)

Okay, I didn't notice there is such a warning in Clang, but I would prefer
writing this way:

if ( (sizeof(i) > 4 && i > U32_MAX) || i >= UZ_MAX / 2 ...
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Steffen Nurpmeso
Kang-Che Sung wrote in
 :
 |On Wednesday, September 7, 2022, Steffen Nurpmeso 
 |wrote:
 ...
 |>|> +  if(su_64( i > U32_MAX || ) i >= UZ_MAX / 2 ||
 ...
 |>|I have to admit that the amount of macro maze makes it really hard to
 |>|read ;)
 |>
 |> Well it is easier than having lots of #ifdef #else #endif blocks
 |> in my opinion.  On 32-bit the above would spit out a warning
 |> (possibly, i have not really looked what compiler/linker flags
 |> busybox uses) because i>U32_MAX can never be true.  I mean i could
 ...
 |Compiler will optimize out always-false expressions without giving any
 |warning.

Regarding the warning: not if you excess an integer limit.
If you say if(0){} i go with you.
Hm.  Well, actually it seems current compilers really do so in
simplemost test files at least, like

  int main(void){if(10>0xULL)return 1;return 0;}

But already if it is a bit more complicated there is

  int main(void){
unsigned long long int i = 10;
if(i>0xULL)return 1;
return 0;}

  t.c:3:6: warning: result of comparison 'unsigned long long' > 
18446744073709551615 is always false [-Wtautological-type-limit-compare]
  if(i>0xULL)return 1;
 ~^~
  1 warning generated.

I can assure you that i am surprised, "in earlier times" you would
have been thrown warnings at.  (gcc 12.2.0 is silent!!!)

 |It's common for C code to produce many expressions like this that evaluate
 |to constants (boolean or integer) at compile time as results of macro
 |expansion, so no warnings should be given.
 |
 |The expression with a macro like `su_64( i > U32_MAX || )` looks really
 |ugly to me. If what you are achieving is to remove statements that are
 |always false (under certain preprocessor condition), just let the compiler
 |do the job.

I do not think you are right here.
But sure, as the above is not critical at all, one could simply
use any other much, much lower limit, say, test the 32-bit
100.000.000 limit always, which makes the test expression much
easier.  However i have found a bug in that

  /* Done for empty expression */
  if((i = a_shexp__arith_ws_squeeze(self, exp_buf, exp_len, NIL)) == 0)
 goto jleave;
  ++i;

^ This could have overflowed before.  It must be leftover, as we
++i later on (again), which is (then) safe.  Ah, what a mess.

--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)
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Steffen Nurpmeso
Steffen Nurpmeso wrote in
 <20220906193906.l5sy8%stef...@sdaoden.eu>:
 ...
 ||Missing license statement here?
 ...
 ||Ah, here is the license. Please move it to line 2 ?
 ...

Btw i have no problem with relicensing this to Public Domain, or
even simply removing the (ISC) license, shall it be integrated
into math.c.  It is more or less licensed only because of the
disclaimer.

--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)
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Kang-Che Sung
On Wednesday, September 7, 2022, Steffen Nurpmeso 
wrote:
>  |> +  /* Overflow check: since arithmetic expressions are rarely \
>  |> long enough
>  |> +   * to come near this limit, xxx laxe & fuzzy, not exact; max \
>  |> U32_MAX! */
>  |> +  if(su_64( i > U32_MAX || ) i >= UZ_MAX / 2 ||
>  |
>  |I have to admit that the amount of macro maze makes it really hard to
>  |read ;)
>
> Well it is easier than having lots of #ifdef #else #endif blocks
> in my opinion.  On 32-bit the above would spit out a warning
> (possibly, i have not really looked what compiler/linker flags
> busybox uses) because i>U32_MAX can never be true.  I mean i could
> say i>=U32_MAX-1 or what, sure.  The above is "laxe and fuzzy"
> anyhow.  :-)

Compiler will optimize out always-false expressions without giving any
warning.
It's common for C code to produce many expressions like this that evaluate
to constants (boolean or integer) at compile time as results of macro
expansion, so no warnings should be given.

The expression with a macro like `su_64( i > U32_MAX || )` looks really
ugly to me. If what you are achieving is to remove statements that are
always false (under certain preprocessor condition), just let the compiler
do the job.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Steffen Nurpmeso
Hello.

Bernhard Reutner-Fischer wrote in
 <20220906183821.1f82672d@nbbrfq>:
 |On Wed, 31 Aug 2022 01:43:26 +0200
 |Steffen Nurpmeso  wrote:
 |
 |> The former implementation was not correct regarding whiteouts in
 |> ?: conditional branches.  The new one also parses a bit better, in
 |> effect on equal level than bash with its recursive descendent parser.
 |
 |Please provide bloat-o-meter output.
 |i.e.
 |make baseline
 |# apply patch
 |make bloatcheck

That made me find docs/keep_data_small.txt.
With my own busybox .config (very much) against the same with also
CONFIG_FEATURE_SH_MATH_ERROR_TRACK=y, eh.. i get

  /usr/bin/env: ‘python’: No such file or directory
  make: *** [/x/src/busybox.git/Makefile.custom:112: bloatcheck] Error 127

There is only python3 here.  I get

  #?0|kent:busybox.git$ make bloatcheck
  function old new   delta
  static.a_shexp__arith_eval -1891   +1891
  a_shexp__arith_op_apply-1532   +1532
  a_shexp__arith_val_eval- 272+272
  arith 14 264+250
  a_shexp_arith_op_toks  - 199+199
  strto_arith_t  - 156+156
  static.a_shexp__arith_ws_squeeze   - 147+147
  .rodata   104665  104750 +85
  a_shexp__arith_op_apply_colons -  75 +75
  ash_arith126 123  -3
  op_tokens141   --141
  arith_lookup_val 193   --193
  arith_apply 1044   -   -1044
  evaluate_string 1146   -   -1146
  --
  (add/remove: 7/4 grow/shrink: 2/1 up/down: 4607/-2527)   Total: 2080 bytes
 textdata bss dec hex filename
  1926334   32428   29370 1988132  1e5624 busybox_old
  1928414   32428   29370 1990212  1e5e44 busybox_unstripped

 |> diff --git a/shell/math.c b/shell/math.c
 |> index 76d22c9bd5..8ba0d2f7fb 100644
 |> --- a/shell/math.c
 |> +++ b/shell/math.c
 |
 |> +#define su_ienc_s64(X,Y,Z) (sprintf(X, ARITH_FMT, Y), X)
 |> +#define n_var_vlook(X,Y) (*self->sac_cookie->lookupvar)(X)
 |> +#define n_var_vset(X,Y,Z) (*self->sac_cookie->setvar)(X, (char*)(Y))
 |> +#define su_idec_cp(A,B,C,D,E) a_idec_x(A, B, E)
 |
 |Can you drop the unused parameters?

Well if you busyboxify shexp-arith.h then yes.

 |> +static inline uint32_t a_idec_x(void *resp, char const *cbuf,
 |> +   char const **endptr_or_nil){
 |> +   uint32_t rv;
 |> +   arith_t res;
 |> +   char const *eptr;
 |> +
 |> +   if(endptr_or_nil == NULL)
 |> +   endptr_or_nil = 
 |
 |Space after if please.

Below.

  ...
 |> +++ b/shell/shexp-arith.h
 |> @@ -0,0 +1,1292 @@
 |> +/*@ S-nail - a mail user agent derived from Berkeley Mail.
 |
 |Missing license statement here?

That is not always in line 2 for busybox, too.

  ...
 |> + *@ - a_SHEXP_ARITH_COMPAT_SHIMS: for inclusion in other code bases, \
 ...
 |these defines

Yes?

 ...
 |Ah, here is the license. Please move it to line 2 ?
 ...

 |What's NYD2_IN supposed to accomplish? Delete.

So what is this now?  I said shexp-arith.h is taken as-is from my
mailer for which i wrote it.  It could remain so, hooked in via
compatibility shims, or the code may be moved entirely to
busybox's math.c, with syntax adjustments just as you desire.
In this case i would expect the above bloatcheck to become
less of a headache.  A bit at least.
NYD is part of my infrastructure that is used in shexp-arith.h.

 |> +  /* Overflow check: since arithmetic expressions are rarely \
 |> long enough
 |> +   * to come near this limit, xxx laxe & fuzzy, not exact; max \
 |> U32_MAX! */
 |> +  if(su_64( i > U32_MAX || ) i >= UZ_MAX / 2 ||
 |
 |I have to admit that the amount of macro maze makes it really hard to
 |read ;)

Well it is easier than having lots of #ifdef #else #endif blocks
in my opinion.  On 32-bit the above would spit out a warning
(possibly, i have not really looked what compiler/linker flags
busybox uses) because i>U32_MAX can never be true.  I mean i could
say i>=U32_MAX-1 or what, sure.  The above is "laxe and fuzzy"
anyhow.  :-)
Btw if you start reading after the /* -- >8 -- 8< -- */ scissor
line it is quite in a flow.  (I usually do not use preprocessor
macro in files, the support uses quite a lot, though.)

I mean, i have a little infrastructure, which is used here.
The pure part of it, and i am hoping the mailer part of it, to
which shexp-arith.h belongs, in a distant future, too, can be
compiled with a C++ compiler also.

Regarding overall syntax: is there a formatter 

Re: [PATCH v4] shell: exchange Dijkstra $(( )) evaluator..

2022-09-06 Thread Bernhard Reutner-Fischer
Hi Steffen,

On Wed, 31 Aug 2022 01:43:26 +0200
Steffen Nurpmeso  wrote:

> The former implementation was not correct regarding whiteouts in
> ?: conditional branches.  The new one also parses a bit better, in
> effect on equal level than bash with its recursive descendent parser.

Please provide bloat-o-meter output.
i.e.
make baseline
# apply patch
make bloatcheck

> diff --git a/shell/math.c b/shell/math.c
> index 76d22c9bd5..8ba0d2f7fb 100644
> --- a/shell/math.c
> +++ b/shell/math.c

> +#define su_ienc_s64(X,Y,Z) (sprintf(X, ARITH_FMT, Y), X)
> +#define n_var_vlook(X,Y) (*self->sac_cookie->lookupvar)(X)
> +#define n_var_vset(X,Y,Z) (*self->sac_cookie->setvar)(X, (char*)(Y))
> +#define su_idec_cp(A,B,C,D,E) a_idec_x(A, B, E)

Can you drop the unused parameters?

> +
> +static inline uint32_t a_idec_x(void *resp, char const *cbuf,
> + char const **endptr_or_nil){
> + uint32_t rv;
> + arith_t res;
> + char const *eptr;
> +
> + if(endptr_or_nil == NULL)
> + endptr_or_nil = 

Space after if please.

> diff --git a/shell/shexp-arith.h b/shell/shexp-arith.h
> new file mode 100644
> index 00..5f3655b456
> --- /dev/null
> +++ b/shell/shexp-arith.h
> @@ -0,0 +1,1292 @@
> +/*@ S-nail - a mail user agent derived from Berkeley Mail.

Missing license statement here?

> + *@ Signed 64-bit sh(1)ell-style $(( ARITH ))metic expression evaluator.
> + *@ POW2 bases are parsed as unsigned, operation overflow -> limit 
> constant(s),
> + *@ saturated mode is not supported, division by zero is handled via error.
> + *@ The expression length limit is ~100.000.000 on 32-bit, U32_MAX otherwise.
> + *@ After reading on Dijkstra's two stack algorithm, as well as bash:expr.c.
> + *@ Most heavily inspired by busybox -- conclusion: the Dijkstra algorithm
> + *@ scales very badly to ternary as are used to implement conditionals and
> + *@ their ignored sub-expressions.
> + *@
> + *@ #define's:
> + *@ - a_SHEXP_ARITH_COMPAT_SHIMS: for inclusion in other code bases, setting
> + *@   this defines most necessary compat macros.

these defines

> + *@   We still need s64, u64, S64_MIN, savestr(CP) <> strdup(3) that does not
> + *@   return NIL (only with _ERROR_TRACK).  Plus stdint.h, ctype.h, string.h.
> + *@   We need su_idec_cp(), su_ienc_s64(), n_var_vlook() and n_var_vset().
> + *@   We need su_IDEC_STATE_EMASK (= 1) and su_IDEC_STATE_CONSUMED (= 2), 
> e.g.:
> + *@ errno = 0;
> + *@ res = strto_arith_t(cbuf, (char**)endptr_or_nil);
> + *@ rv = 0;
> + *@ if(errno == 0){
> + *@   if(**endptr_or_nil == '\0')
> + *@ rv = su_IDEC_STATE_CONSUMED;
> + *@ }else{
> + *@   rv = su_IDEC_STATE_EMASK;
> + *@   res = 0;
> + *@ }
> + *@ *S(s64*,resp) = res;
> + *@ - a_SHEXP_ARITH_COOKIE: adds struct a_shexp_arith_ctx:sac_cookie, and
> + *@   a cookie arg to a_shexp_arith_eval().
> + *@ - a_SHEXP_ARITH_ERROR_TRACK: add "char **error_track_or_nil" to
> + *@   a_shexp_arith_eval(), and according error stack handling, so that users
> + *@   can be given hint where an error occurred.  ("Three stack algorithm.")
> + *
> + * Copyright (c) 2022 Steffen Nurpmeso .
> + * SPDX-License-Identifier: ISC
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */

Ah, here is the license. Please move it to line 2 ?

> +static void
> +a_shexp__arith_eval(struct a_shexp_arith_ctx *self,
> +  char const *exp_buf, uz exp_len){
> +   char *ep, *varp, *cp, c;
> +   u16 lop;
> +   struct a_shexp_arith_stack *sasp;
> +   void *mem_p;
> +   NYD2_IN;

What's NYD2_IN supposed to accomplish? Delete.

> +
> +   a_SHEXP_ARITH_L((" > _arith_eval %zu <%.*s>\n",
> +  exp_len, S(int,exp_len != UZ_MAX ? exp_len : su_cs_len(exp_buf)),
> +  exp_buf));
> +
> +   mem_p = NIL;
> +   sasp = self->sac_stack;
> +
> +   /* Create a single continuous allocation for anything */
> +   /* C99 */{
> +  union {void *v; char *c;} p;
> +  uz i, j, a;
> +
> +  /* Done for empty expression */
> +  if((i = a_shexp__arith_ws_squeeze(self, exp_buf, exp_len, NIL)) == 0)
> + goto jleave;
> +  ++i;
> +
> +  /* Overflow check: since arithmetic expressions are rarely long enough
> +   * to come near this limit, xxx laxe & fuzzy, not exact; max U32_MAX! 
> */
> +