X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com Message-ID: <52D02D96.9000000@gmx.de> Date: Fri, 10 Jan 2014 18:27:50 +0100 From: Juan Manuel Guerrero User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: _doprnt bug fix if mantissa fraction precision exceeds the default of 39 decimal digits. References: <52CB29B1 DOT 3010904 AT gmx DOT de> In-Reply-To: <52CB29B1.3010904@gmx.de> Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:2RI7mdWOfUZfdr77bGVVcTeWB/KTZbq0H0FY7ig3l81JCItfjcF gNWmHNKbHHX/OzOHht0sMO6hTKkDtFXSDcEOZyfglRE7OMoCbahCWGGiXDEdOM3lGJcVYtJ AiuTcvZ1+PQ8SZqW9qcGbBuhx0mPYR1AALHERj5yFBDVp9aDZGNBV3CMZV3j5W1CQqMb+Vy jTZpYPAp4+R4HbXE7Yrvw== Reply-To: djgpp-workers AT delorie DOT com Am 06.01.2014 23:09, schrieb Juan Manuel Guerrero: > Please look at the following code snippet: > > #include > > int main(void) > { > printf("%.60Le\n", 1.75L); > return 0; > } > > > It must produce the following output (linux): > 1.750000000000000000000000000000000000000000000000000000000000e+00 > but it produces the following output: > 1.750000000000000000000000000000000000000e+00000000000000000000000 [snip] OFYI, I committed the patch below to fix the bug reported concerning the field width specifier for the AEFG conversion specifiers. I added a check for this issue and fixed some signed-unsigned issues in other checks. Regards, Juan M. Guerrero # cvs ci -m"Fix some -Werror=sign-compare occurrences." djgpp/tests/libc/ansi/stdio/append.c # cvs ci -m"Fix some -Werror=sign-compare occurrences." djgpp/tests/libc/ansi/stdio/fseek.c # cvs ci -m"Fix some -Werror=sign-compare occurrences." djgpp/tests/libc/ansi/stdio/tscanf3.c # cvs ci -m"Fix some -Werror=sign-compare occurrences." djgpp/tests/libc/ansi/stdio/tsnprtf.c # cvs ci -m"Handle case when field width specifier for AEFG conversion specifiers exceeds max default precision of 39 decimal digits." djgpp/src/libc/ansi/stdio/doprnt.c # cvs ci -m"Check added to targets list." djgpp/tests/libc/ansi/stdio/makefile # cd djgpp/tests/libc/ansi/stdio # cvs ci -m"Check of field width specifier for AEFG conversion specifiers." djgpp/tests/libc/ansi/stdio/printf6.c # cd ~ 2014-01-06 Juan Manuel Guerrero * djgpp/src/libc/ansi/stdio/doprnt.c: Handle case when field width specifier for AEFG conversion specifiers exceeds max default precision of 39 decimal digits. * djgpp/tests/libc/ansi/stdio/makefile: Check added to targets list. * djgpp/tests/libc/ansi/stdio/printf6.c: Check of field width specifier for AEFG conversion specifiers. * djgpp/tests/libc/ansi/stdio/append.c: Fix some -Werror=sign-compare occurrences. * djgpp/tests/libc/ansi/stdio/fseek.c: Fix some -Werror=sign-compare occurrences. * djgpp/tests/libc/ansi/stdio/tscanf3.c: Fix some -Werror=sign-compare occurrences. * djgpp/tests/libc/ansi/stdio/tsnprtf.c: Fix some -Werror=sign-compare occurrences. diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/doprnt.c djgpp/src/libc/ansi/stdio/doprnt.c --- djgpp.orig/src/libc/ansi/stdio/doprnt.c 2014-01-09 22:00:02 +0100 +++ djgpp/src/libc/ansi/stdio/doprnt.c 2014-01-09 22:01:46 +0100 @@ -1,5 +1,6 @@ +/* Copyright (C) 2014 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2012 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ @@ -404,12 +405,13 @@ rflag: * cvt may have to round up past the "start" of the * buffer, i.e. ``intf("%.2f", (double)9.999);''; * if the first char isn't NUL, it did. */ *buf = '\0'; - size = doprnt_cvtl(_ldouble, prec, flags, &softsign, *fmt, buf, + size = doprnt_cvtl(_ldouble, prec + fpprec, flags, &softsign, *fmt, buf, buf + sizeof(buf)); + fpprec = 0; /* Floating point fraction precision already adjusted in doprnt_cvtl. */ /* * If the format specifier requested an explicit sign, * we print a negative sign even if no significant digits * will be shown, and we also print a sign for a NaN. In * other words, "%+f" might print -0.000000, +NaN and -NaN. diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/append.c djgpp/tests/libc/ansi/stdio/append.c --- djgpp.orig/tests/libc/ansi/stdio/append.c 2001-05-22 22:52:26 +0100 +++ djgpp/tests/libc/ansi/stdio/append.c 2014-01-09 22:01:46 +0100 @@ -8,11 +8,11 @@ int main(void) { FILE *f; int status = 0; /* Return value. */ struct stat s; - size_t len; + off_t len; f = fopen(FILE_NAME, "w"); fprintf(f, "hello, there\n"); fclose(f); stat(FILE_NAME, &s); diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/fseek.c djgpp/tests/libc/ansi/stdio/fseek.c --- djgpp.orig/tests/libc/ansi/stdio/fseek.c 1996-02-05 02:40:26 +0100 +++ djgpp/tests/libc/ansi/stdio/fseek.c 2014-01-09 22:01:46 +0100 @@ -65,11 +65,12 @@ int main (int argc, char *argv[]) char *source = (char *)malloc (strlen (*argv) + 3); if (source) { FILE *fp; - long flen, buflen; + long flen; + size_t buflen; char *buf1 = 0; char *buf2 = 0; char *buf3 = 0; long fpos1 = 0; int i; diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/makefile djgpp/tests/libc/ansi/stdio/makefile --- djgpp.orig/tests/libc/ansi/stdio/makefile 2012-12-24 19:04:10 +0100 +++ djgpp/tests/libc/ansi/stdio/makefile 2014-01-09 22:01:46 +0100 @@ -16,10 +16,11 @@ SRC += hello.c SRC += mktemp.c SRC += printf.c SRC += printf2.c SRC += printf3.c SRC += printf4.c +SRC += printf6.c SRC += sscanf.c SRC += sscanf2.c SRC += sscanf3.c SRC += tmpnam.c SRC += tremove.c diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/printf6.c djgpp/tests/libc/ansi/stdio/printf6.c --- djgpp.orig/tests/libc/ansi/stdio/printf6.c 1970-01-01 01:00:00 +0100 +++ djgpp/tests/libc/ansi/stdio/printf6.c 2014-01-09 22:01:46 +0100 @@ -0,0 +1,90 @@ +/* + * printf6.c + * Test cases for field width specifier for different floating point conversions. + */ + +#include +#include + +#define SIZE 128 + + +int +main(void) +{ + const char *should_be[] = { + /* Created with linux libc. */ + "0xe.10624dd2f1a9fbe000000000000000000000000000000000000000000000p-3", + "1.757999999999999999949693019196672594262054190039634704589844e+00", + "1.757999999999999999949693019196672594262054190039634704589844", + "1.757999999999999999949693019196672594262054190039634704589844", + "0xe.000000000000000000000000000000000000000000000000000000000000p-3", + "1.750000000000000000000000000000000000000000000000000000000000e+00", + "1.750000000000000000000000000000000000000000000000000000000000", + "1.75" + }; + char result[SIZE]; + int failures = 0; + + + snprintf(result, SIZE, "%.60La", 1.758L); + if (strcmp(result, should_be[0])) + { + printf("Check 0 \"%%.60La\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[0]); + failures++; + } + + snprintf(result, SIZE, "%.60Le", 1.758L); + if (strcmp(result, should_be[1])) + { + printf("Check 1 \"%%.60Le\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[1]); + failures++; + } + + snprintf(result, SIZE, "%.60Lf", 1.758L); + if (strcmp(result, should_be[2])) + { + printf("Check 2 \"%%.60Lf\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[2]); + failures++; + } + + snprintf(result, SIZE, "%.60Lg", 1.758L); + if (strcmp(result, should_be[3])) + { + printf("Check 3 \"%%.60Lg\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[3]); + failures++; + } + + snprintf(result, SIZE, "%.60La", 1.75L); + if (strcmp(result, should_be[4])) + { + printf("Check 4 \"%%.60La\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[4]); + failures++; + } + + snprintf(result, SIZE, "%.60Le", 1.75L); + if (strcmp(result, should_be[5])) + { + printf("Check 5 \"%%.60Le\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[5]); + failures++; + } + + snprintf(result, SIZE, "%.60Lf", 1.75L); + if (strcmp(result, should_be[6])) + { + printf("Check 6 \"%%.60Lf\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[6]); + failures++; + } + + snprintf(result, SIZE, "%.60Lg", 1.75L); + if (strcmp(result, should_be[7])) + { + printf("Check 7 \"%%.60Lg\":\nresult = '%s'\nshould be = '%s'\n", result, should_be[7]); + failures++; + } + + printf("%d checks failed.\n", failures); + + + return failures; +} diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/tscanf3.c djgpp/tests/libc/ansi/stdio/tscanf3.c --- djgpp.orig/tests/libc/ansi/stdio/tscanf3.c 2012-12-24 19:09:56 +0100 +++ djgpp/tests/libc/ansi/stdio/tscanf3.c 2014-01-09 22:01:46 +0100 @@ -32,11 +32,12 @@ int main(void) { 2012, "diciembre", 21, 1, 2, 3}, /* spanish */ { 2012, "Dezember", 21, 1, 2, 3}, /* german */ { 2012, "december", 21, 1, 2, 3} /* english */ }; char month[10]; - int year, day, hour, min, sec, i, status; + int year, day, hour, min, sec; + size_t i, status; for (status = i = 0; i < (sizeof buffer / sizeof buffer[0]);) { printf("This string will be scanned:\n%s\n\n", buffer[i]); diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/tsnprtf.c djgpp/tests/libc/ansi/stdio/tsnprtf.c --- djgpp.orig/tests/libc/ansi/stdio/tsnprtf.c 2002-06-08 15:54:30 +0100 +++ djgpp/tests/libc/ansi/stdio/tsnprtf.c 2014-01-09 22:01:46 +0100 @@ -10,11 +10,11 @@ int main (void) { char BIG[] = "Hello this is a too big string for the buffer"; char holder[24]; - int i, j; + size_t i, j; i = snprintf(holder, sizeof(holder), "%s\n", BIG); printf("%s\n", BIG); printf("%s\n", holder); /* @@ -25,11 +25,11 @@ main (void) */ if (i != strlen(BIG) + 1 /* nul */) { fprintf(stderr, "FAILED snprintf\n"); fprintf(stderr, - "sizeof (%lu), snprintf(%d), strlen(%lu)\n", + "sizeof (%lu), snprintf(%zd), strlen(%lu)\n", sizeof(holder), i, strlen(BIG)) ; exit(EXIT_FAILURE); } /* @@ -48,17 +48,17 @@ main (void) printf(line); j = printf(holder); if (i != j) { fprintf(stderr, "FAILED snprintf\n"); - fprintf(stderr, "snprintf (%d) != printf (%d)\n", i, j); + fprintf(stderr, "snprintf (%zd) != printf (%zd)\n", i, j); exit(EXIT_FAILURE); } } else { - printf("sscanf (%d)\n", i); + printf("sscanf (%zd)\n", i); printf("FAILED sscanf\n"); exit(EXIT_FAILURE); } } @@ -97,34 +97,34 @@ main (void) exit(EXIT_FAILURE); } /* Test padding a field to larger than buffer size. */ { - int s = sizeof(holder) * 16; + size_t s = sizeof(holder) * 16; - i = snprintf(holder, sizeof(holder), "%*s", s, BIG); + i = snprintf(holder, sizeof(holder), "%*s", (int)s, BIG); if ((i != s) || ((strlen(holder) + 1) != sizeof(holder))) { fprintf(stderr, - "FAILED with padding larger than buffer: %d output, " + "FAILED with padding larger than buffer: %zd output, " "%lu written to buffer\n", i, strlen(holder)); exit(EXIT_FAILURE); } } /* Test precision to larger than buffer size. */ { - int s = sizeof(holder) * 4; + size_t s = sizeof(holder) * 4; - i = snprintf(holder, sizeof(holder), "%*.*e", s, s, 1e0); + i = snprintf(holder, sizeof(holder), "%*.*e", (int)s, (int)s, 1e0); if ((i <= s) || ((strlen(holder) + 1) != sizeof(holder))) { fprintf(stderr, - "FAILED with precision larger than buffer: %d output, " + "FAILED with precision larger than buffer: %zd output, " "%lu written to buffer\n", i, strlen(holder)); exit(EXIT_FAILURE); } }