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>