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

Reply via email to