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); > >