From owner-freebsd-hackers@FreeBSD.ORG Fri Apr 4 19:06:33 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A3A7737B401 for ; Fri, 4 Apr 2003 19:06:33 -0800 (PST) Received: from snark.ratmir.ru (snark.ratmir.ru [213.24.248.177]) by mx1.FreeBSD.org (Postfix) with ESMTP id 65E0843FCB for ; Fri, 4 Apr 2003 19:06:32 -0800 (PST) (envelope-from freebsd@snark.ratmir.ru) Received: from snark.ratmir.ru (freebsd@localhost [127.0.0.1]) by snark.ratmir.ru (8.12.9/8.12.9) with ESMTP id h3536UDR005203 for ; Sat, 5 Apr 2003 07:06:30 +0400 (MSD) (envelope-from freebsd@snark.ratmir.ru) Received: (from freebsd@localhost) by snark.ratmir.ru (8.12.9/8.12.9/Submit) id h3536TjW005202 for freebsd-hackers@freebsd.org; Sat, 5 Apr 2003 07:06:29 +0400 (MSD) Date: Sat, 5 Apr 2003 07:06:29 +0400 From: Alex Semenyaka To: freebsd-hackers@freebsd.org Message-ID: <20030405030629.GA2669@snark.ratmir.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable User-Agent: Mutt/1.5.4i Subject: /bin/sh and BIG NUMBERS X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Apr 2003 03:06:33 -0000 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