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>
