Rafael Sadowski wrote: > Hi, > > last days I worked on the netbeans port and try to fix the heapsize > problem. My patch always crashed and I realized this effect: > > $ mem=`sysctl -n hw.usermem` > $ echo $mem > 8302469120 > $ expr $mem + 1 > -287465471 > > OpenBSD's expr can only process values between -2147483648 and > +2147483647. It only handle/convert simple int. I looked at the other > BSDs and found NetBSD's expr. > > "The reimplement expr using lexical parser generated by yacc > highlights: > - use 64 bit arithmetic, so expr is able to process integer values from > (2**63) to (2**63 - 1) > - checks for integer over- & underflows added > - error messages improved, more error checking added" > - http://cvsweb.netbsd.org/bsdweb.cgi/src/bin/expr/expr.y?only_with_tag=MAIN > > This patch contains NetBSD reimplemented expr with following changes:
it would be simpler to fix the bug than to rewrite the whole program, no? 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);