Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Apr 2003 07:06:29 +0400
From:      Alex Semenyaka <alexs@ratmir.ru>
To:        freebsd-hackers@freebsd.org
Subject:   /bin/sh and BIG NUMBERS
Message-ID:  <20030405030629.GA2669@snark.ratmir.ru>

next in thread | raw e-mail | index | archive | help
I found that /bin/sh cannot handle numbers those do not fit to integer type.
That is not too bad. Too bad that it just silently warps them in arithmetic=
al
operations:

alexs@snark> /bin/sh -c 'echo $((10000000000-1))'
2147483646

That was not a problem 5 years ago... But now we have a lot of 64-bits valu=
es.
So those old scripts which perfectly worked for a long time now can give wr=
ong
results, and you will not be able even to notice it, there is no any diagno=
stics
or such. The simplest way to fix it is to switch internal /bin/sh arithmeti=
cs
=66rom 32 to 64-bits (you know, approach "640K ought to be enough for anybo=
dy").
I've did the patch for this (below), please, look at it. Any comments or
suggestions?

diff -u -U1 -r ../sh.old/arith.h ./arith.h
--- ../sh.old/arith.h	Fri Jul 19 08:38:51 2002
+++ ./arith.h	Sat Apr  5 06:26:48 2003
@@ -36,3 +36,3 @@
=20
-int arith(char *);
+long long arith(char *);
 int expcmd(int , char **);
diff -u -U1 -r ../sh.old/arith.y ./arith.y
--- ../sh.old/arith.y	Fri Jul 19 08:38:51 2002
+++ ./arith.y	Sat Apr  5 06:23:58 2003
@@ -1 +1,7 @@
+%{
+#define YYSTYPE long long
+
+static long long arith_res;
+%}
+
 %token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
@@ -16,3 +22,4 @@
 exp:	expr =3D {
-			return ($1);
+			arith_res =3D $1;
+			return (0);
 		}
@@ -110,7 +117,5 @@
=20
-int
+long long
 arith(char *s)
 {
-	long result;
-
 	arith_buf =3D arith_startbuf =3D s;
@@ -118,3 +123,3 @@
 	INTOFF;
-	result =3D yyparse();
+	yyparse();
 	arith_lex_reset();	/* reprime lex */
@@ -122,3 +127,3 @@
=20
-	return (result);
+	return (arith_res);
 }
@@ -144,3 +149,3 @@
 	char **ap;
-	long i;
+	long long i;
=20
@@ -169,3 +174,3 @@
=20
-	out1fmt("%ld\n", i);
+	out1fmt("%qd\n", i);
 	return (! i);
diff -u -U1 -r ../sh.old/arith_lex.l ./arith_lex.l
--- ../sh.old/arith_lex.l	Fri Jul 19 08:38:51 2002
+++ ./arith_lex.l	Sat Apr  5 06:24:30 2003
@@ -48,3 +48,3 @@
=20
-extern int yylval;
+extern long long yylval;
 extern char *arith_buf, *arith_startbuf;
@@ -58,3 +58,3 @@
 [ \t\n]	{ ; }
-[0-9]+	{ yylval =3D atol(yytext); return(ARITH_NUM); }
+[0-9]+	{ yylval =3D strtoll(yytext, NULL, 10); return(ARITH_NUM); }
 "("	{ return(ARITH_LPAREN); }
diff -u -U1 -r ../sh.old/expand.c ./expand.c
--- ../sh.old/expand.c	Fri Jan 17 14:37:03 2003
+++ ./expand.c	Sat Apr  5 06:35:15 2003
@@ -368,3 +368,3 @@
 	char *p, *start;
-	int result;
+	long long result;
 	int begoff;
@@ -384,6 +384,6 @@
 	 */
-#if INT_MAX / 1000000000 >=3D 10 || INT_MIN / 1000000000 <=3D -10
-#error "integers with more than 10 digits are not supported"
-#endif
-	CHECKSTRSPACE(12 - 2, expdest);
+//#if INT_MAX / 1000000000 >=3D 10 || INT_MIN / 1000000000 <=3D -10
+//#error "integers with more than 10 digits are not supported"
+//#endif
+	CHECKSTRSPACE(21 - 2, expdest);
 	USTPUTC('\0', expdest);
@@ -409,3 +409,3 @@
 	result =3D arith(p+2);
-	fmtstr(p, 12, "%d", result);
+	fmtstr(p, 21, "%qd", result);
 	while (*p++)


/Alexs



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030405030629.GA2669>