Updated to fedora-glibc-20061210T1006
authorjakub <jakub>
Sun, 10 Dec 2006 10:38:51 +0000 (10:38 +0000)
committerjakub <jakub>
Sun, 10 Dec 2006 10:38:51 +0000 (10:38 +0000)
18 files changed:
ChangeLog
fedora/branch.mk
fedora/glibc.spec.in
include/features.h
malloc/memusage.c
malloc/memusagestat.c
misc/Makefile
misc/getusershell.c
misc/mntent_r.c
misc/tst-mntent2.c [new file with mode: 0644]
nptl/ChangeLog
nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
stdlib/Makefile
stdlib/strtod_l.c
stdlib/tst-atof1.c [new file with mode: 0644]
stdlib/tst-atof2.c [new file with mode: 0644]

index 80fa9c5..0e8507a 100644 (file)
--- 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.
index b61ceaa..41c73b2 100644 (file)
@@ -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
index d1b7f56..7d39fbc 100644 (file)
@@ -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)
index aeeb3a5..4eb49a9 100644 (file)
@@ -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.
 
index bf2978e..d11e9e6 100644 (file)
@@ -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],
index d8fc71b..93ac2cd 100644 (file)
@@ -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;
 };
index f9ad0b7..9eac1b6 100644 (file)
@@ -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
index 255b579..636da32 100644 (file)
@@ -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')
index 1476c86..829750b 100644 (file)
@@ -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 (file)
index 0000000..6c25e01
--- /dev/null
@@ -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;
+}
index ac3ddff..a237c5e 100644 (file)
@@ -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
index bc7a645..6b3d368 100644 (file)
@@ -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) \
index 17ab562..6b02402 100644 (file)
@@ -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 \
index 77ce742..70d5a86 100644 (file)
@@ -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__
index a0ff427..37400ec 100644 (file)
@@ -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
 
index e13f108..b926aeb 100644 (file)
@@ -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 (file)
index 0000000..879d866
--- /dev/null
@@ -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 (file)
index 0000000..74dac87
--- /dev/null
@@ -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"