summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-12-10 10:38:56 +0000
committerJakub Jelinek <jakub@redhat.com>2006-12-10 10:38:56 +0000
commitb0ec19ce6e64c405fdd95c90a5d4212f86abea1f (patch)
tree9f52f1f004f36f9bd712fe2fb753736733f6324c
parent7f65f3e3920a0dd6bb6a8774f46063371be4d029 (diff)
Updated to fedora-glibc-20061210T1006
-rw-r--r--ChangeLog45
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in10
-rw-r--r--include/features.h2
-rw-r--r--malloc/memusage.c38
-rw-r--r--malloc/memusagestat.c4
-rw-r--r--misc/Makefile2
-rw-r--r--misc/getusershell.c12
-rw-r--r--misc/mntent_r.c12
-rw-r--r--misc/tst-mntent2.c41
-rw-r--r--nptl/ChangeLog14
-rw-r--r--nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h21
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h21
-rw-r--r--stdlib/Makefile3
-rw-r--r--stdlib/strtod_l.c36
-rw-r--r--stdlib/tst-atof1.c19
-rw-r--r--stdlib/tst-atof2.c55
18 files changed, 294 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index 80fa9c5050..0e8507a668 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2006-12-09 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #3632]
+ * include/features.h: Fix comment about default value for
+ _POSIX_C_SOURCE.
+
+ [BZ #3664]
+ * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix test to recognize
+ empty parsed strings.
+ * stdlib/Makefile (tests): Add tst-strtod2.
+ * stdlib/tst-strtod2.c: New file.
+
+ [BZ #3673]
+ * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix exp_limit
+ computation.
+ * stdlib/Makefile (tests): Add tst-atof2.
+ * stdlib/tst-atof2.c: New file.
+
+ [BZ #3674]
+ * stdlib/strtod_l.c (____STRTOF_INTERNAL): Adjust exponent value
+ correctly if removing trailing zero of hex-float.
+ * stdlib/Makefile (tests): Add tst-atof1.
+ * stdlib/tst-atof1.c: New file.
+
+2006-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ * misc/mntent_r.c (__hasmntopt): Check p[optlen] even when p == rest.
+ Start searching for next comma at p rather than rest.
+ * misc/Makefile (tests): Add tst-mntent2.
+ * misc/tst-mntent2.c: New test.
+
+ * misc/getusershell.c (initshells): Check for integer overflows.
+ Make strings buffer one bigger as fgets always succeeds when second
+ argument is 1. Don't use calloc for shells array. Disallow
+ / as shell.
+
+2006-12-08 Ulrich Drepper <drepper@redhat.com>
+
+ * malloc/memusage.c: Handle realloc with new size of zero and
+ non-NULL pointer correctly.
+ (me): Really write first record twice.
+ (struct entry): Make format bi-arch safe.
+ (dest): Write out more realloc statistics.
+ * malloc/memusagestat.c (struct entry): Make format bi-arch safe.
+
2006-12-05 Jakub Jelinek <jakub@redhat.com>
* nis/nis_subr.c (nis_getnames): Revert last change.
diff --git a/fedora/branch.mk b/fedora/branch.mk
index b61ceaaa5f..41c73b2907 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -3,5 +3,5 @@ glibc-branch := fedora
glibc-base := HEAD
DIST_BRANCH := devel
COLLECTION := dist-fc7
-fedora-sync-date := 2006-12-05 21:41 UTC
-fedora-sync-tag := fedora-glibc-20061205T2141
+fedora-sync-date := 2006-12-10 10:06 UTC
+fedora-sync-tag := fedora-glibc-20061210T1006
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index d1b7f560af..7d39fbcdf3 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 11
+%define glibcrelease 12
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define xenarches i686 athlon
%ifarch %{xenarches}
@@ -1544,8 +1544,14 @@ rm -f *.filelist*
%endif
%changelog
+* Sun Dec 10 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-12
+- fix hasmntopt (#218802)
+- fix setusershell and getusershell (#218782)
+- strtod fixes (BZ#3664, BZ#3673, BZ#3674)
+- fix memusage with realloc (x, 0)
+
* Tue Dec 5 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-11
-- allow suid apps to setenv NIS_PATH and incluence through that
+- allow suid apps to setenv NIS_PATH and influence through that
nis_list and nis_lookup (#209155)
- fix ttyname and ttyname_r with invalid file descriptor (#218276)
- cs_CZ LC_TIME fixes (#218438)
diff --git a/include/features.h b/include/features.h
index aeeb3a578a..4eb49a92b1 100644
--- a/include/features.h
+++ b/include/features.h
@@ -49,7 +49,7 @@
The `-ansi' switch to the GNU C compiler defines __STRICT_ANSI__.
If none of these are defined, the default is to have _SVID_SOURCE,
_BSD_SOURCE, and _POSIX_SOURCE set to one and _POSIX_C_SOURCE set to
- 199506L. If more than one of these are defined, they accumulate.
+ 200112L. If more than one of these are defined, they accumulate.
For example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE
together give you ISO C, 1003.1, and 1003.2, but nothing else.
diff --git a/malloc/memusage.c b/malloc/memusage.c
index bf2978ef02..d11e9e6ed5 100644
--- a/malloc/memusage.c
+++ b/malloc/memusage.c
@@ -80,6 +80,7 @@ static memusage_cntr_t large;
static memusage_cntr_t calls_total;
static memusage_cntr_t inplace;
static memusage_cntr_t decreasing;
+static memusage_cntr_t realloc_free;
static memusage_cntr_t inplace_mremap;
static memusage_cntr_t decreasing_mremap;
static memusage_size_t current_heap;
@@ -103,8 +104,8 @@ extern const char *__progname;
struct entry
{
- size_t heap;
- size_t stack;
+ uint64_t heap;
+ uint64_t stack;
uint32_t time_low;
uint32_t time_high;
};
@@ -267,6 +268,7 @@ me (void)
GETTIME (first.time_low, first.time_high);
/* Write it two times since we need the starting and end time. */
write (fd, &first, sizeof (first));
+ write (fd, &first, sizeof (first));
/* Determine the buffer size. We use the default if the
environment variable is not present. */
@@ -411,6 +413,23 @@ realloc (void *old, size_t len)
/* Keep track of total memory requirement. */
catomic_add (&grand_total, len - old_len);
}
+
+ if (len == 0 && old != NULL)
+ {
+ /* Special case. */
+ catomic_increment (&realloc_free);
+ /* Keep track of total memory freed using `free'. */
+ catomic_add (&total[idx_free], real->length);
+
+ /* Update the allocation data and write out the records if necessary. */
+ update_data (NULL, 0, old_len);
+
+ /* Do the real work. */
+ (*freep) (real);
+
+ return NULL;
+ }
+
/* Remember the size of the request. */
if (len < 65536)
catomic_increment (&histogram[len / 16]);
@@ -770,7 +789,12 @@ dest (void)
if (fd != -1)
{
/* Write the partially filled buffer. */
- write (fd, buffer, buffer_cnt * sizeof (struct entry));
+ if (buffer_cnt > buffer_size)
+ write (fd, buffer + buffer_size,
+ (buffer_cnt - buffer_size) * sizeof (struct entry));
+ else
+ write (fd, buffer, buffer_cnt * sizeof (struct entry));
+
/* Go back to the beginning of the file. We allocated two records
here when we opened the file. */
lseek (fd, 0, SEEK_SET);
@@ -794,7 +818,7 @@ dest (void)
\e[01;32mMemory usage summary:\e[0;0m heap total: %llu, heap peak: %lu, stack peak: %lu\n\
\e[04;34m total calls total memory failed calls\e[0m\n\
\e[00;34m malloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
-\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (in place: %ld, dec: %ld)\n\
+\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove:%ld, dec:%ld, free:%ld)\n\
\e[00;34m calloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
\e[00;34m free|\e[0m %10lu %12llu\n",
(unsigned long long int) grand_total, (unsigned long int) peak_heap,
@@ -807,7 +831,9 @@ dest (void)
(unsigned long long int) total[idx_realloc],
failed[idx_realloc] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_realloc],
- (unsigned long int) inplace, (unsigned long int) decreasing,
+ (unsigned long int) inplace,
+ (unsigned long int) decreasing,
+ (unsigned long int) realloc_free,
(unsigned long int) calls[idx_calloc],
(unsigned long long int) total[idx_calloc],
failed[idx_calloc] ? "\e[01;41m" : "",
@@ -820,7 +846,7 @@ dest (void)
\e[00;34mmmap(r)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
\e[00;34mmmap(w)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
\e[00;34mmmap(a)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
-\e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (in place: %ld, dec: %ld)\n\
+\e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove: %ld, dec:%ld)\n\
\e[00;34m munmap|\e[0m %10lu %12llu %s%12lu\e[00;00m\n",
(unsigned long int) calls[idx_mmap_r],
(unsigned long long int) total[idx_mmap_r],
diff --git a/malloc/memusagestat.c b/malloc/memusagestat.c
index d8fc71b729..93ac2cd744 100644
--- a/malloc/memusagestat.c
+++ b/malloc/memusagestat.c
@@ -81,8 +81,8 @@ static struct argp argp =
struct entry
{
- size_t heap;
- size_t stack;
+ uint64_t heap;
+ uint64_t stack;
uint32_t time_low;
uint32_t time_high;
};
diff --git a/misc/Makefile b/misc/Makefile
index f9ad0b76fc..9eac1b6275 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -78,7 +78,7 @@ endif
gpl2lgpl := error.c error.h
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
- tst-error1 tst-pselect tst-insremque
+ tst-error1 tst-pselect tst-insremque tst-mntent2
ifeq (no,$(cross-compiling))
tests: $(objpfx)tst-error1-mem
endif
diff --git a/misc/getusershell.c b/misc/getusershell.c
index 255b579b1a..636da322f9 100644
--- a/misc/getusershell.c
+++ b/misc/getusershell.c
@@ -98,7 +98,7 @@ initshells()
register char **sp, *cp;
register FILE *fp;
struct stat64 statb;
- int flen;
+ size_t flen;
free(shells);
shells = NULL;
@@ -114,9 +114,11 @@ initshells()
okshells[1] = _PATH_CSHELL;
return (char **) okshells;
}
- if ((strings = malloc((u_int)statb.st_size + 1)) == NULL)
+ if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3)
goto init_okshells;
- shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
+ if ((strings = malloc(statb.st_size + 2)) == NULL)
+ goto init_okshells;
+ shells = malloc(statb.st_size / 3 * sizeof (char *));
if (shells == NULL) {
free(strings);
strings = NULL;
@@ -124,11 +126,11 @@ initshells()
}
sp = shells;
cp = strings;
- flen = statb.st_size;
+ flen = statb.st_size + 2;
while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
while (*cp != '#' && *cp != '/' && *cp != '\0')
cp++;
- if (*cp == '#' || *cp == '\0')
+ if (*cp == '#' || *cp == '\0' || cp[1] == '\0')
continue;
*sp++ = cp;
while (!isspace(*cp) && *cp != '#' && *cp != '\0')
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
index 1476c86ee2..829750b395 100644
--- a/misc/mntent_r.c
+++ b/misc/mntent_r.c
@@ -1,5 +1,6 @@
/* Utilities for reading/writing fstab, mtab, etc.
- Copyright (C) 1995-2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2000, 2001, 2002, 2003, 2006
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -278,14 +279,11 @@ __hasmntopt (const struct mntent *mnt, const char *opt)
while ((p = strstr (rest, opt)) != NULL)
{
- if (p == rest
- || (p[-1] == ','
- && (p[optlen] == '\0' ||
- p[optlen] == '=' ||
- p[optlen] == ',')))
+ if ((p == rest || p[-1] == ',')
+ && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
return p;
- rest = strchr (rest, ',');
+ rest = strchr (p, ',');
if (rest == NULL)
break;
++rest;
diff --git a/misc/tst-mntent2.c b/misc/tst-mntent2.c
new file mode 100644
index 0000000000..6c25e0127c
--- /dev/null
+++ b/misc/tst-mntent2.c
@@ -0,0 +1,41 @@
+#include <mntent.h>
+#include <stdio.h>
+#include <string.h>
+
+
+int
+main (void)
+{
+ int result = 0;
+ struct mntent mef;
+
+ mef.mnt_fsname = strdupa ("/dev/sdf6");
+ mef.mnt_dir = strdupa ("/some dir");
+ mef.mnt_type = strdupa ("ext3");
+ mef.mnt_opts = strdupa ("opt1,opt2,noopt=6,rw,norw,brw");
+ mef.mnt_freq = 1;
+ mef.mnt_passno = 2;
+
+#define TEST(opt, found) \
+ if (!!hasmntopt (&mef, (opt)) != (found)) \
+ { \
+ printf ("Option %s was %sfound\n", (opt), (found) ? "not " : ""); \
+ result = 1; \
+ }
+
+ TEST ("opt1", 1)
+ TEST ("opt2", 1)
+ TEST ("noopt", 1)
+ TEST ("rw", 1)
+ TEST ("norw", 1)
+ TEST ("brw", 1)
+ TEST ("opt", 0)
+ TEST ("oopt", 0)
+ TEST ("w", 0)
+ TEST ("r", 0)
+ TEST ("br", 0)
+ TEST ("nor", 0)
+ TEST ("or", 0)
+
+ return result;
+}
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index ac3ddfff9b..a237c5e080 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,17 @@
+2006-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Handle
+ 6 argument cancellable syscalls.
+ (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define.
+ * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Handle
+ 6 argument cancellable syscalls.
+ (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define.
+
+2006-12-09 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/unix/sysv/linux/rtld-lowlevel.h
+ (__rtld_mrlock_initialize): Add missing closing parenthesis.
+
2006-10-30 Jakub Jelinek <jakub@redhat.com>
* sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use
diff --git a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
index bc7a6454ea..6b3d3682da 100644
--- a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
+++ b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
@@ -43,7 +43,7 @@ typedef int __rtld_mrlock_t;
#define _RTLD_MRLOCK_INITIALIZER 0
#define __rtld_mrlock_initialize(NAME) \
- (void) ((NAME) = 0
+ (void) ((NAME) = 0)
#define __rtld_mrlock_lock(lock) \
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
index 17ab562daa..6b0240243a 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
@@ -45,7 +45,13 @@ L(pseudo_cancel): \
bas %r14,0(%r1,%r13); \
lr %r0,%r2; \
LM_##args \
- DO_CALL(syscall_name, args); \
+ .if SYS_ify (syscall_name) < 256; \
+ svc SYS_ify (syscall_name); \
+ .else; \
+ lhi %r1,SYS_ify (syscall_name); \
+ svc 0; \
+ .endif; \
+ LR7_##args \
l %r1,2f-0b(%r13); \
lr %r12,%r2; \
lr %r2,%r0; \
@@ -89,6 +95,7 @@ L(pseudo_end):
#define STM_3 stm %r2,%r4,8(%r15);
#define STM_4 stm %r2,%r5,8(%r15);
#define STM_5 stm %r2,%r5,8(%r15);
+#define STM_6 stm %r2,%r7,8(%r15);
#define LM_0 /* Nothing */
#define LM_1 l %r2,8+96(%r15);
@@ -96,6 +103,18 @@ L(pseudo_end):
#define LM_3 lm %r2,%r4,8+96(%r15);
#define LM_4 lm %r2,%r5,8+96(%r15);
#define LM_5 lm %r2,%r5,8+96(%r15);
+#define LM_6 lm %r2,%r5,8+96(%r15); \
+ cfi_offset (%r7, -68); \
+ l %r7,96+96(%r15);
+
+#define LR7_0 /* Nothing */
+#define LR7_1 /* Nothing */
+#define LR7_2 /* Nothing */
+#define LR7_3 /* Nothing */
+#define LR7_4 /* Nothing */
+#define LR7_5 /* Nothing */
+#define LR7_6 l %r7,28+96(%r15); \
+ cfi_restore (%r7);
# ifndef __ASSEMBLER__
# define SINGLE_THREAD_P \
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
index 77ce742495..70d5a86429 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
@@ -42,7 +42,13 @@ L(pseudo_cancel): \
brasl %r14,CENABLE; \
lgr %r0,%r2; \
LM_##args \
- DO_CALL(syscall_name, args); \
+ .if SYS_ify (syscall_name) < 256; \
+ svc SYS_ify (syscall_name); \
+ .else; \
+ lghi %r1,SYS_ify (syscall_name); \
+ svc 0; \
+ .endif; \
+ LR7_##args \
lgr %r13,%r2; \
lgr %r2,%r0; \
brasl %r14,CDISABLE; \
@@ -85,6 +91,7 @@ L(pseudo_end):
#define STM_3 stmg %r2,%r4,16(%r15);
#define STM_4 stmg %r2,%r5,16(%r15);
#define STM_5 stmg %r2,%r5,16(%r15);
+#define STM_6 stmg %r2,%r7,16(%r15);
#define LM_0 /* Nothing */
#define LM_1 lg %r2,16+160(%r15);
@@ -92,6 +99,18 @@ L(pseudo_end):
#define LM_3 lmg %r2,%r4,16+160(%r15);
#define LM_4 lmg %r2,%r5,16+160(%r15);
#define LM_5 lmg %r2,%r5,16+160(%r15);
+#define LM_6 lmg %r2,%r5,16+160(%r15); \
+ cfi_offset (%r7, -104); \
+ lg %r7,160+160(%r15);
+
+#define LR7_0 /* Nothing */
+#define LR7_1 /* Nothing */
+#define LR7_2 /* Nothing */
+#define LR7_3 /* Nothing */
+#define LR7_4 /* Nothing */
+#define LR7_5 /* Nothing */
+#define LR7_6 lg %r7,56+160(%r15); \
+ cfi_restore (%r7);
# if defined IS_IN_libpthread || !defined NOT_IN_libc
# ifndef __ASSEMBLER__
diff --git a/stdlib/Makefile b/stdlib/Makefile
index a0ff427b7e..37400ec547 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -66,7 +66,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
test-canon test-canon2 tst-strtoll tst-environ \
tst-xpg-basename tst-random tst-random2 tst-bsearch \
tst-limits tst-rand48 bug-strtod tst-setcontext \
- test-a64l tst-qsort tst-system testmb2 bug-strtod2
+ test-a64l tst-qsort tst-system testmb2 bug-strtod2 \
+ tst-atof1 tst-atof2 tst-strtod2
include ../Makeconfig
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index e13f1086da..b926aeba56 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -662,20 +662,20 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
/* If no other digit but a '0' is found the result is 0.0.
Return current read pointer. */
- if ((c < L_('0') || c > L_('9'))
- && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
- || c > (CHAR_TYPE) TOLOWER (L_('f'))))
+ if (!((c >= L_('0') && c <= L_('9'))
+ || (base == 16 && ((CHAR_TYPE) TOLOWER (c) >= L_('a')
+ && (CHAR_TYPE) TOLOWER (c) <= L_('f')))
#ifdef USE_WIDE_CHAR
- && c != (wint_t) decimal
+ || c == (wint_t) decimal
#else
- && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+ || ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
if (decimal[cnt] != cp[cnt])
break;
- decimal[cnt] != '\0'; })
+ decimal[cnt] == '\0'; })
#endif
- && (base == 16 && (cp == start_of_digits
- || (CHAR_TYPE) TOLOWER (c) != L_('p')))
- && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
+ || (base == 16 && (cp != start_of_digits
+ && (CHAR_TYPE) TOLOWER (c) == L_('p')))
+ || (base != 16 && (CHAR_TYPE) TOLOWER (c) == L_('e'))))
{
#ifdef USE_WIDE_CHAR
tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
@@ -759,13 +759,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
}
}
- /* We have the number digits in the integer part. Whether these are all or
- any is really a fractional digit will be decided later. */
+ /* We have the number of digits in the integer part. Whether these
+ are all or any is really a fractional digit will be decided
+ later. */
int_no = dig_no;
lead_zero = int_no == 0 ? -1 : 0;
- /* Read the fractional digits. A special case are the 'american style'
- numbers like `16.' i.e. with decimal but without trailing digits. */
+ /* Read the fractional digits. A special case are the 'american
+ style' numbers like `16.' i.e. with decimal point but without
+ trailing digits. */
if (
#ifdef USE_WIDE_CHAR
c == (wint_t) decimal
@@ -815,15 +817,16 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
if (base == 16)
exp_limit = (exp_negative ?
-MIN_EXP + MANT_DIG + 4 * int_no :
- MAX_EXP - 4 * int_no + lead_zero);
+ MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
else
exp_limit = (exp_negative ?
-MIN_10_EXP + MANT_DIG + int_no :
- MAX_10_EXP - int_no + lead_zero);
+ MAX_10_EXP - int_no + lead_zero + 1);
do
{
exponent *= 10;
+ exponent += c - L_('0');
if (exponent > exp_limit)
/* The exponent is too large/small to represent a valid
@@ -853,7 +856,6 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
/* NOTREACHED */
}
- exponent += c - L_('0');
c = *++cp;
}
while (c >= L_('0') && c <= L_('9'));
@@ -888,7 +890,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
--expp;
--dig_no;
--int_no;
- ++exponent;
+ exponent += base == 16 ? 4 : 1;
}
while (dig_no > 0 && exponent < 0);
diff --git a/stdlib/tst-atof1.c b/stdlib/tst-atof1.c
new file mode 100644
index 0000000000..879d866558
--- /dev/null
+++ b/stdlib/tst-atof1.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+ char buf[100];
+ snprintf (buf, sizeof (buf), "%g", atof ("0x10p-1"));
+ if (strcmp (buf, "8") != 0)
+ {
+ printf ("got \"%s\", expected \"8\"\n", buf);
+ return 1;
+ }
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdlib/tst-atof2.c b/stdlib/tst-atof2.c
new file mode 100644
index 0000000000..74dac87b0d
--- /dev/null
+++ b/stdlib/tst-atof2.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static const struct
+{
+ const char *str;
+ const char *expected;
+} tests[] =
+ {
+ { "1e308", "1e+308" },
+ { "100000000e300", "1e+308" },
+ { "0x1p1023", "8.98847e+307" },
+ { "0x1000p1011", "8.98847e+307" },
+ { "0x1p1020", "1.12356e+307" },
+ { "0x0.00001p1040", "1.12356e+307" },
+ { "1e-307", "1e-307" },
+ { "0.000001e-301", "1e-307" },
+ { "0.0000001e-300", "1e-307" },
+ { "0.00000001e-299", "1e-307" },
+ { "1000000e-313", "1e-307" },
+ { "10000000e-314", "1e-307" },
+ { "100000000e-315", "1e-307" },
+ { "0x1p-1021", "4.45015e-308" },
+ { "0x1000p-1033", "4.45015e-308" },
+ { "0x10000p-1037", "4.45015e-308" },
+ { "0x0.001p-1009", "4.45015e-308" },
+ { "0x0.0001p-1005", "4.45015e-308" },
+ };
+#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ int status = 0;
+
+ for (int i = 0; i < NTESTS; ++i)
+ {
+ char buf[100];
+ snprintf (buf, sizeof (buf), "%g", atof (tests[i].str));
+ if (strcmp (buf, tests[i].expected) != 0)
+ {
+ printf ("%d: got \"%s\", expected \"%s\"\n",
+ i, buf, tests[i].expected);
+ status = 1;
+ }
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"