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