Hi,

Ted Unangst wrote on Tue, Jan 05, 2016 at 03:10:05PM -0500:
> Rafael Sadowski wrote:

>> $ mem=`sysctl -n hw.usermem`
>> $ echo $mem
>> 8302469120
>> $ expr $mem + 1
>> -287465471
>> 
>> OpenBSD's expr can only process values between -2147483648
>> and +2147483647.

According to

  http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
  12.1. Utility Argument Syntax, item 6.

that is sufficient to satisfy POSIX.  Then again,

  "Ranges greater than those listed here are allowed."

Extending the range to int64_t does seem useful.

> it would be simpler to fix the bug than to rewrite the whole program, no?

Indeed, i like Ted's patch much better.

The recursive decent parser written by John T. Conklin in 1994 is
much easier to read than the yacc(1)-based implementation written
by Jaromir Dolecek in 2000.  I hate automatic code generation in
general: obfuscation is a fertile group to breed bugs and to confuse
human developers.  I hate it even more when there isn't even a good
reason to use it.

OK schwarze@ for tedu@'s patch.
  Ingo


> Index: expr.c
> ===================================================================
> RCS file: /cvs/src/bin/expr/expr.c,v
> retrieving revision 1.23
> diff -u -p -r1.23 expr.c
> --- expr.c    29 Dec 2015 19:06:16 -0000      1.23
> +++ expr.c    5 Jan 2016 20:09:31 -0000
> @@ -16,10 +16,10 @@
>  #include <regex.h>
>  #include <err.h>
>  
> -struct val   *make_int(int);
> +struct val   *make_int(int64_t);
>  struct val   *make_str(char *);
>  void          free_value(struct val *);
> -int           is_integer(struct val *, int *);
> +int           is_integer(struct val *, int64_t *);
>  int           to_integer(struct val *);
>  void          to_string(struct val *);
>  int           is_zero_or_null(struct val *);
> @@ -46,7 +46,7 @@ struct val {
>  
>       union {
>               char           *s;
> -             int             i;
> +             int64_t         i;
>       } u;
>  };
>  
> @@ -55,7 +55,7 @@ struct val     *tokval;
>  char       **av;
>  
>  struct val *
> -make_int(int i)
> +make_int(int64_t i)
>  {
>       struct val     *vp;
>  
> @@ -94,11 +94,11 @@ free_value(struct val *vp)
>  
>  /* determine if vp is an integer; if so, return it's value in *r */
>  int
> -is_integer(struct val *vp, int *r)
> +is_integer(struct val *vp, int64_t *r)
>  {
>       char           *s;
>       int             neg;
> -     int             i;
> +     int64_t         i;
>  
>       if (vp->type == integer) {
>               *r = vp->u.i;
> @@ -138,7 +138,7 @@ is_integer(struct val *vp, int *r)
>  int
>  to_integer(struct val *vp)
>  {
> -     int             r;
> +     int64_t         r;
>  
>       if (vp->type == integer)
>               return 1;
> @@ -163,7 +163,7 @@ to_string(struct val *vp)
>       if (vp->type == string)
>               return;
>  
> -     if (asprintf(&tmp, "%d", vp->u.i) == -1)
> +     if (asprintf(&tmp, "%lld", vp->u.i) == -1)
>               err(3, NULL);
>  
>       vp->type = string;
> @@ -287,7 +287,7 @@ eval5(void)
>                               v = make_str(l->u.s + rm[1].rm_so);
>  
>                       } else {
> -                             v = make_int((int)(rm[0].rm_eo - rm[0].rm_so));
> +                             v = make_int(rm[0].rm_eo - rm[0].rm_so);
>                       }
>               } else {
>                       if (rp.re_nsub == 0) {
> @@ -381,7 +381,7 @@ eval2(void)
>  {
>       struct val     *l, *r;
>       enum token      op;
> -     int             v = 0, li, ri;
> +     int64_t         v = 0, li, ri;
>  
>       l = eval3();
>       while ((op = token) == EQ || op == NE || op == LT || op == GT ||
> @@ -518,7 +518,7 @@ main(int argc, char *argv[])
>       }
>  
>       if (vp->type == integer)
> -             printf("%d\n", vp->u.i);
> +             printf("%lld\n", vp->u.i);
>       else
>               printf("%s\n", vp->u.s);
>  
> 

Reply via email to