]> Savannah Git Hosting - gnulib.git/commitdiff
strtol, strtoll, strtoul, strtoull: Make ISO C 23 compliant.
authorBruno Haible <bruno@clisp.org>
Thu, 16 Mar 2023 15:02:02 +0000 (16:02 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 16 Mar 2023 15:02:02 +0000 (16:02 +0100)
* lib/strtol.c (INTERNAL (strtol)): Treat 'b' and base 2 like 'x' and
base 16. Based on glibc commit 64924422a99690d147a166b4de3103f3bf3eaf6c
by Joseph Myers.
* m4/strtol.m4 (gl_FUNC_STRTOL): Test also whether parsing binary
integers works. Update cross-compilation guesses.
* m4/strtoll.m4 (gl_FUNC_STRTOLL): Likewise.
* m4/strtoul.m4 (gl_FUNC_STRTOUL): Likewise.
* m4/strtoull.m4 (gl_FUNC_STRTOULL): Likewise.
* tests/test-strtol.c (main): Add tests of parsing binary integers.
* tests/test-strtoll.c (main): Likewise.
* tests/test-strtoul.c (main): Likewise.
* tests/test-strtoull.c (main): Likewise.
* doc/posix-functions/strtol.texi: Mention the problem with parsing
binary integers.
* doc/posix-functions/strtoll.texi: Likewise.
* doc/posix-functions/strtoul.texi: Likewise.
* doc/posix-functions/strtoull.texi: Likewise.

14 files changed:
ChangeLog
doc/posix-functions/strtol.texi
doc/posix-functions/strtoll.texi
doc/posix-functions/strtoul.texi
doc/posix-functions/strtoull.texi
lib/strtol.c
m4/strtol.m4
m4/strtoll.m4
m4/strtoul.m4
m4/strtoull.m4
tests/test-strtol.c
tests/test-strtoll.c
tests/test-strtoul.c
tests/test-strtoull.c

index 454b61bb6764cd3f004f512644929a5aa18b698c..40f92591133833413e29f2604d2bd547558eb762 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2023-03-16  Bruno Haible  <bruno@clisp.org>
+
+       strtol, strtoll, strtoul, strtoull: Make ISO C 23 compliant.
+       * lib/strtol.c (INTERNAL (strtol)): Treat 'b' and base 2 like 'x' and
+       base 16. Based on glibc commit 64924422a99690d147a166b4de3103f3bf3eaf6c
+       by Joseph Myers.
+       * m4/strtol.m4 (gl_FUNC_STRTOL): Test also whether parsing binary
+       integers works. Update cross-compilation guesses.
+       * m4/strtoll.m4 (gl_FUNC_STRTOLL): Likewise.
+       * m4/strtoul.m4 (gl_FUNC_STRTOUL): Likewise.
+       * m4/strtoull.m4 (gl_FUNC_STRTOULL): Likewise.
+       * tests/test-strtol.c (main): Add tests of parsing binary integers.
+       * tests/test-strtoll.c (main): Likewise.
+       * tests/test-strtoul.c (main): Likewise.
+       * tests/test-strtoull.c (main): Likewise.
+       * doc/posix-functions/strtol.texi: Mention the problem with parsing
+       binary integers.
+       * doc/posix-functions/strtoll.texi: Likewise.
+       * doc/posix-functions/strtoul.texi: Likewise.
+       * doc/posix-functions/strtoull.texi: Likewise.
+
 2023-03-16  Bruno Haible  <bruno@clisp.org>
 
        timegm: Document under ISO C and POSIX substitutes.
index 5ebcb284d496c6894a046ab9d32ec7532d72e6c8..061deea1b390870c96ebe3fe3486159d71c5ef9f 100644 (file)
@@ -14,6 +14,9 @@ This function is missing on some old platforms.
 This function does not parse the leading @samp{0} when the input string is
 @code{"0x"} and the base is 16 or 0 on some platforms:
 Minix 3.3, mingw, MSVC 14.
+@item
+This function does not parse binary integers (with a @samp{0b} or @samp{0B}
+prefix) when the base is 2 or 0 on many platforms.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index b507fc33c60c4b31c9da8ffec53a89c1dd877534..42f73d344959c78ff2f3d919b316dc338616aa16 100644 (file)
@@ -15,6 +15,9 @@ HP-UX 11.11, MSVC 9.
 This function does not parse the leading @samp{0} when the input string is
 @code{"0x"} and the base is 16 or 0 on some platforms:
 Minix 3.3, mingw, MSVC 14.
+@item
+This function does not parse binary integers (with a @samp{0b} or @samp{0B}
+prefix) when the base is 2 or 0 on many platforms.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 3b1fa7fb5eab77b15d28917cdbac84a8f0985485..c3a97ee39a1bbc857b48e54ca383c3650db7325c 100644 (file)
@@ -14,6 +14,9 @@ This function is missing on some old platforms.
 This function does not parse the leading @samp{0} when the input string is
 @code{"0x"} and the base is 16 or 0 on some platforms:
 Minix 3.3, mingw, MSVC 14.
+@item
+This function does not parse binary integers (with a @samp{0b} or @samp{0B}
+prefix) when the base is 2 or 0 on many platforms.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 68ede343e1732230370c617834e6d9bc69666a78..ba976a77e6c133023d8b292fbbaeb609b182f31b 100644 (file)
@@ -15,6 +15,9 @@ HP-UX 11.11, MSVC 9.
 This function does not parse the leading @samp{0} when the input string is
 @code{"0x"} and the base is 16 or 0 on some platforms:
 Minix 3.3, mingw, MSVC 14.
+@item
+This function does not parse binary integers (with a @samp{0b} or @samp{0B}
+prefix) when the base is 2 or 0 on many platforms.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index d11269b2622bc0c137dcd39ea87c19f45ebd3923..b93483dca49739fadff78ae7ccc61cda0b80adcd 100644 (file)
@@ -288,6 +288,11 @@ INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
           s += 2;
           base = 16;
         }
+      else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B'))
+        {
+          s += 2;
+          base = 2;
+        }
       else if (base == 0)
         base = 8;
     }
@@ -378,11 +383,14 @@ INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
 noconv:
   /* We must handle a special case here: the base is 0 or 16 and the
      first two characters are '0' and 'x', but the rest are no
-     hexadecimal digits.  This is no error case.  We return 0 and
-     ENDPTR points to the 'x'.  */
+     hexadecimal digits.  Likewise when the base is 0 or 2 and the
+     first two characters are '0' and 'b', but the rest are no binary
+     digits.  This is no error case.  We return 0 and ENDPTR points to
+     the 'x' or 'b'.  */
   if (endptr != NULL)
     {
-      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+      if (save - nptr >= 2
+          && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B'))
           && save[-2] == L_('0'))
         *endptr = (STRING_TYPE *) &save[-1];
       else
index 7e3b0d0044ea851d738a8fbd129686b4487065c9..5cdd86adc72525208e8b744423db5fde0b56932c 100644 (file)
@@ -1,4 +1,4 @@
-# strtol.m4 serial 7
+# strtol.m4 serial 8
 dnl Copyright (C) 2002-2003, 2006, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,15 +24,26 @@ AC_DEFUN([gl_FUNC_STRTOL],
                 if (term != input + 1)
                   result |= 1;
               }
+              /* This test fails on pre-C23 platforms.  */
+              {
+                const char input[] = "0b1";
+                (void) strtol (input, &term, 2);
+                if (term != input + 3)
+                  result |= 2;
+              }
               return result;
             ]])
          ],
          [gl_cv_func_strtol_works=yes],
          [gl_cv_func_strtol_works=no],
          [case "$host_os" in
-                    # Guess no on native Windows.
-            mingw*) gl_cv_func_strtol_works="guessing no" ;;
-            *)      gl_cv_func_strtol_works="$gl_cross_guess_normal" ;;
+                                # Guess no on native Windows.
+            mingw*)             gl_cv_func_strtol_works="guessing no" ;;
+                                # Guess no on glibc systems.
+            *-gnu* | gnu*)      gl_cv_func_strtol_works="guessing no" ;;
+                                # Guess no on musl systems.
+            *-musl* | midipix*) gl_cv_func_strtol_works="guessing no" ;;
+            *)                  gl_cv_func_strtol_works="$gl_cross_guess_normal" ;;
           esac
          ])
     ])
index ede630c6061a3fc43ecb19a5977a585e15089b85..ec09609cd42591c45dfd258d1bc570470093c925 100644 (file)
@@ -1,4 +1,4 @@
-# strtoll.m4 serial 9
+# strtoll.m4 serial 10
 dnl Copyright (C) 2002, 2004, 2006, 2008-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,15 +24,26 @@ AC_DEFUN([gl_FUNC_STRTOLL],
                 if (term != input + 1)
                   result |= 1;
               }
+              /* This test fails on pre-C23 platforms.  */
+              {
+                const char input[] = "0b1";
+                (void) strtoll (input, &term, 2);
+                if (term != input + 3)
+                  result |= 2;
+              }
               return result;
             ]])
          ],
          [gl_cv_func_strtoll_works=yes],
          [gl_cv_func_strtoll_works=no],
          [case "$host_os" in
-                    # Guess no on native Windows.
-            mingw*) gl_cv_func_strtoll_works="guessing no" ;;
-            *)      gl_cv_func_strtoll_works="$gl_cross_guess_normal" ;;
+                                # Guess no on native Windows.
+            mingw*)             gl_cv_func_strtoll_works="guessing no" ;;
+                                # Guess no on glibc systems.
+            *-gnu* | gnu*)      gl_cv_func_strtoll_works="guessing no" ;;
+                                # Guess no on musl systems.
+            *-musl* | midipix*) gl_cv_func_strtoll_works="guessing no" ;;
+            *)                  gl_cv_func_strtoll_works="$gl_cross_guess_normal" ;;
           esac
          ])
     ])
index 30a83d7e19055b12ae033ff9d0e8e20d869f025f..9baa9729e6ec7a292d942d1416171bf64ce09618 100644 (file)
@@ -1,4 +1,4 @@
-# strtoul.m4 serial 6
+# strtoul.m4 serial 7
 dnl Copyright (C) 2002, 2006, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,15 +24,26 @@ AC_DEFUN([gl_FUNC_STRTOUL],
                 if (term != input + 1)
                   result |= 1;
               }
+              /* This test fails on pre-C23 platforms.  */
+              {
+                const char input[] = "0b1";
+                (void) strtoul (input, &term, 2);
+                if (term != input + 3)
+                  result |= 2;
+              }
               return result;
             ]])
          ],
          [gl_cv_func_strtoul_works=yes],
          [gl_cv_func_strtoul_works=no],
          [case "$host_os" in
-                    # Guess no on native Windows.
-            mingw*) gl_cv_func_strtoul_works="guessing no" ;;
-            *)      gl_cv_func_strtoul_works="$gl_cross_guess_normal" ;;
+                                # Guess no on native Windows.
+            mingw*)             gl_cv_func_strtoul_works="guessing no" ;;
+                                # Guess no on glibc systems.
+            *-gnu* | gnu*)      gl_cv_func_strtoul_works="guessing no" ;;
+                                # Guess no on musl systems.
+            *-musl* | midipix*) gl_cv_func_strtoul_works="guessing no" ;;
+            *)                  gl_cv_func_strtoul_works="$gl_cross_guess_normal" ;;
           esac
          ])
     ])
index a9b0ddf9f26306c3b11cf0b6cdb5965dcab8deac..4f895c76af8045a44b2086a0d87ec341ae54a8d0 100644 (file)
@@ -1,4 +1,4 @@
-# strtoull.m4 serial 9
+# strtoull.m4 serial 10
 dnl Copyright (C) 2002, 2004, 2006, 2008-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,15 +24,26 @@ AC_DEFUN([gl_FUNC_STRTOULL],
                 if (term != input + 1)
                   result |= 1;
               }
+              /* This test fails on pre-C23 platforms.  */
+              {
+                const char input[] = "0b1";
+                (void) strtoull (input, &term, 2);
+                if (term != input + 3)
+                  result |= 2;
+              }
               return result;
             ]])
          ],
          [gl_cv_func_strtoull_works=yes],
          [gl_cv_func_strtoull_works=no],
          [case "$host_os" in
-                    # Guess no on native Windows.
-            mingw*) gl_cv_func_strtoull_works="guessing no" ;;
-            *)      gl_cv_func_strtoull_works="$gl_cross_guess_normal" ;;
+                                # Guess no on native Windows.
+            mingw*)             gl_cv_func_strtoull_works="guessing no" ;;
+                                # Guess no on glibc systems.
+            *-gnu* | gnu*)      gl_cv_func_strtoull_works="guessing no" ;;
+                                # Guess no on musl systems.
+            *-musl* | midipix*) gl_cv_func_strtoull_works="guessing no" ;;
+            *)                  gl_cv_func_strtoull_works="$gl_cross_guess_normal" ;;
           esac
          ])
     ])
index ba8a54de4deeeaccf9422b3f779cc5abdea09e23..065b442ba5c172bbdd879261fe05d007b32f164b 100644 (file)
@@ -239,5 +239,67 @@ main (void)
     ASSERT (errno == 0);
   }
 
+  /* Binary integer syntax.  */
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 10);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 2);
+    ASSERT (result == 58L);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 0);
+    ASSERT (result == 58L);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 10);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 2);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 0);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+
   return 0;
 }
index ecedbe64607c7b364d765176770022b8362ef921..24cb4eb1e1be9bc9cf2cdfb1c4452a39f61545ef 100644 (file)
@@ -239,5 +239,67 @@ main (void)
     ASSERT (errno == 0);
   }
 
+  /* Binary integer syntax.  */
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 10);
+    ASSERT (result == 0LL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 2);
+    ASSERT (result == 58LL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 0);
+    ASSERT (result == 58LL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 10);
+    ASSERT (result == 0LL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 2);
+    ASSERT (result == 0LL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    long long result;
+    errno = 0;
+    result = strtoll (input, &ptr, 0);
+    ASSERT (result == 0LL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+
   return 0;
 }
index 7e8e5f78c61113b28a608d016e899cd65971667e..434cea49ed589c62d4519d7ef682bb78421dc7c4 100644 (file)
@@ -238,5 +238,67 @@ main (void)
     ASSERT (errno == 0);
   }
 
+  /* Binary integer syntax.  */
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 10);
+    ASSERT (result == 0UL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 2);
+    ASSERT (result == 58UL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 0);
+    ASSERT (result == 58UL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 10);
+    ASSERT (result == 0UL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 2);
+    ASSERT (result == 0UL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long result;
+    errno = 0;
+    result = strtoul (input, &ptr, 0);
+    ASSERT (result == 0UL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+
   return 0;
 }
index dd6ec2ad192977ed35757e82e77502e08eb33bc3..7b0027f621a83571456455591352982c0ca751e5 100644 (file)
@@ -238,5 +238,67 @@ main (void)
     ASSERT (errno == 0);
   }
 
+  /* Binary integer syntax.  */
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 10);
+    ASSERT (result == 0ULL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 2);
+    ASSERT (result == 58ULL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b111010";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 0);
+    ASSERT (result == 58ULL);
+    ASSERT (ptr == input + 8);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 10);
+    ASSERT (result == 0ULL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 2);
+    ASSERT (result == 0ULL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0b";
+    char *ptr;
+    unsigned long long result;
+    errno = 0;
+    result = strtoull (input, &ptr, 0);
+    ASSERT (result == 0ULL);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+
   return 0;
 }