]> Savannah Git Hosting - gnulib.git/commitdiff
xstrtol: document and stray less from strtol
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 19 Jul 2024 00:28:36 +0000 (17:28 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 19 Jul 2024 00:30:02 +0000 (17:30 -0700)
This patch alters xstrtol behavior slightly, in areas are not
likely to affect any real callers, by making xstrtol behave more
like the system strtol.  In particular, it lets xstrtol support
bases other than those required by POSIX, if the underlying
implementation does; this removes the need for an ‘assert’.
It also uses ‘restrict’ like the underlying strtol does.
The patch also documents xstrtol in xstrtol.h.
Problems reported by AlejandroColomar in:
https://lists.gnu.org/r/bug-gnulib/2024-07/msg00159.html
* lib/xstrtol.c: Do not include stdio.h or assure.h.
(__xstrtol): Use same parameter names as POSIX, to make it
easier for outsiders to follow.  Assume C99 decls after statement.
Do not require the base to be 0, or 2-36, as the underlying
implementation is allowed to support other bases.
Do not assume isspace preserves errno.
* lib/xstrtol.h (_DECLARE_XSTRTOL): Declare pointers to be
‘restrict’, for compatibility with C.
* m4/xstrtol.m4 (gl_XSTRTOL): Require AC_C_RESTRICT.
* modules/xstrtol (Depends-on): Remove ‘assure’.

ChangeLog
lib/xstrtol.c
lib/xstrtol.h
m4/xstrtol.m4
modules/xstrtol

index 833ecd6d80deb5625f5e4fc2e5af1e63c22a9d67..172884639282760b0ac4619c0bd42c441c286521 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2024-07-18  Paul Eggert  <eggert@cs.ucla.edu>
+
+       xstrtol: document and stray less from strtol
+       This patch alters xstrtol behavior slightly, in areas are not
+       likely to affect any real callers, by making xstrtol behave more
+       like the system strtol.  In particular, it lets xstrtol support
+       bases other than those required by POSIX, if the underlying
+       implementation does; this removes the need for an ‘assert’.
+       It also uses ‘restrict’ like the underlying strtol does.
+       The patch also documents xstrtol in xstrtol.h.
+       Problems reported by AlejandroColomar in:
+       https://lists.gnu.org/r/bug-gnulib/2024-07/msg00159.html
+       * lib/xstrtol.c: Do not include stdio.h or assure.h.
+       (__xstrtol): Use same parameter names as POSIX, to make it
+       easier for outsiders to follow.  Assume C99 decls after statement.
+       Do not require the base to be 0, or 2-36, as the underlying
+       implementation is allowed to support other bases.
+       Do not assume isspace preserves errno.
+       * lib/xstrtol.h (_DECLARE_XSTRTOL): Declare pointers to be
+       ‘restrict’, for compatibility with C.
+       * m4/xstrtol.m4 (gl_XSTRTOL): Require AC_C_RESTRICT.
+       * modules/xstrtol (Depends-on): Remove ‘assure’.
+
 2024-07-18  Bruno Haible  <bruno@clisp.org>
 
        abort-debug: Don't assume that signal SIGABRT is unmasked and unhandled.
index 575c16d45f9057b424b3788da55c80ae7f83c5b5..c3145171f37587df53bf68dd9fd8f0f42f0cfefa 100644 (file)
 
 #include "xstrtol.h"
 
-/* Some pre-ANSI implementations (e.g. SunOS 4)
-   need stderr defined if assertion checking is enabled.  */
-#include <stdio.h>
-
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
@@ -45,7 +41,6 @@
 # include <inttypes.h>
 #endif
 
-#include "assure.h"
 #include "intprops.h"
 
 static strtol_error
@@ -72,26 +67,17 @@ bkm_scale_by_power (__strtol_t *x, int base, int power)
   return err;
 }
 
-/* FIXME: comment.  */
-
 strtol_error
-__xstrtol (const char *s, char **ptr, int strtol_base,
-           __strtol_t *val, const char *valid_suffixes)
+__xstrtol (char const *nptr, char **endptr, int base,
+           __strtol_t *val, char const *valid_suffixes)
 {
   char *t_ptr;
-  char **p;
-  __strtol_t tmp;
-  strtol_error err = LONGINT_OK;
-
-  assure (0 == strtol_base || (2 <= strtol_base && strtol_base <= 36));
-
-  p = (ptr ? ptr : &t_ptr);
-
-  errno = 0;
+  char **p = endptr ? endptr : &t_ptr;
+  *p = (char *) nptr;
 
   if (! TYPE_SIGNED (__strtol_t))
     {
-      const char *q = s;
+      char const *q = nptr;
       unsigned char ch = *q;
       while (isspace (ch))
         ch = *++q;
@@ -99,16 +85,17 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
         return LONGINT_INVALID;
     }
 
-  tmp = __strtol (s, p, strtol_base);
+  errno = 0;
+  __strtol_t tmp = __strtol (nptr, p, base);
+  strtol_error err = LONGINT_OK;
 
-  if (*p == s)
+  if (*p == nptr)
     {
       /* If there is no number but there is a valid suffix, assume the
          number is 1.  The string is invalid otherwise.  */
-      if (valid_suffixes && **p && strchr (valid_suffixes, **p))
-        tmp = 1;
-      else
+      if (! (valid_suffixes && *nptr && strchr (valid_suffixes, *nptr)))
         return LONGINT_INVALID;
+      tmp = 1;
     }
   else if (errno != 0)
     {
@@ -128,7 +115,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
 
   if (**p != '\0')
     {
-      int base = 1024;
+      int xbase = 1024;
       int suffixes = 1;
       strtol_error overflow;
 
@@ -160,7 +147,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
 
               case 'B':
               case 'D': /* 'D' is obsolescent */
-                base = 1000;
+                xbase = 1000;
                 suffixes++;
                 break;
               }
@@ -184,39 +171,39 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
           break;
 
         case 'E': /* exa or exbi */
-          overflow = bkm_scale_by_power (&tmp, base, 6);
+          overflow = bkm_scale_by_power (&tmp, xbase, 6);
           break;
 
         case 'G': /* giga or gibi */
         case 'g': /* 'g' is undocumented; for compatibility only */
-          overflow = bkm_scale_by_power (&tmp, base, 3);
+          overflow = bkm_scale_by_power (&tmp, xbase, 3);
           break;
 
         case 'k': /* kilo */
         case 'K': /* kibi */
-          overflow = bkm_scale_by_power (&tmp, base, 1);
+          overflow = bkm_scale_by_power (&tmp, xbase, 1);
           break;
 
         case 'M': /* mega or mebi */
         case 'm': /* 'm' is undocumented; for compatibility only */
-          overflow = bkm_scale_by_power (&tmp, base, 2);
+          overflow = bkm_scale_by_power (&tmp, xbase, 2);
           break;
 
         case 'P': /* peta or pebi */
-          overflow = bkm_scale_by_power (&tmp, base, 5);
+          overflow = bkm_scale_by_power (&tmp, xbase, 5);
           break;
 
         case 'Q': /* quetta or 2**100 */
-          overflow = bkm_scale_by_power (&tmp, base, 10);
+          overflow = bkm_scale_by_power (&tmp, xbase, 10);
           break;
 
         case 'R': /* ronna or 2**90 */
-          overflow = bkm_scale_by_power (&tmp, base, 9);
+          overflow = bkm_scale_by_power (&tmp, xbase, 9);
           break;
 
         case 'T': /* tera or tebi */
         case 't': /* 't' is undocumented; for compatibility only */
-          overflow = bkm_scale_by_power (&tmp, base, 4);
+          overflow = bkm_scale_by_power (&tmp, xbase, 4);
           break;
 
         case 'w':
@@ -224,11 +211,11 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
           break;
 
         case 'Y': /* yotta or 2**80 */
-          overflow = bkm_scale_by_power (&tmp, base, 8);
+          overflow = bkm_scale_by_power (&tmp, xbase, 8);
           break;
 
         case 'Z': /* zetta or 2**70 */
-          overflow = bkm_scale_by_power (&tmp, base, 7);
+          overflow = bkm_scale_by_power (&tmp, xbase, 7);
           break;
 
         default:
index 280c1f3a43fbcbe86e6408408382c5ab4bc3e9ed..cedff6393ef52ac29965d249b23ad570b88be5be 100644 (file)
@@ -44,8 +44,23 @@ enum strtol_error
 typedef enum strtol_error strtol_error;
 #endif
 
+/* Act like the system's strtol (NPTR, ENDPTR, BASE) except:
+   - The TYPE of the result might be something other than long int.
+   - Return strtol_error, and store any result through an additional
+     TYPE *VAL pointer instead of returning the result.
+   - If TYPE is unsigned, reject leading '-'.
+   - Accept an additional char const *VALID_SUFFIXES pointer to a
+     possibly-empty string containing allowed numeric suffixes,
+     which multiply the value.  These include SI suffixes like 'k' and 'M';
+     these normally stand for powers of 1024, but if VALID_SUFFIXES also
+     includes '0' they can be followed by "B" to stand for the usual
+     SI powers of 1000 (or by "iB" to stand for powers of 1024 as before).
+     Other supported suffixes include 'K' for 1024 or 1000, 'b' for 512,
+     'c' for 1, and 'w' for 2.  */
+
 #define _DECLARE_XSTRTOL(name, type) \
-  strtol_error name (const char *, char **, int, type *, const char *);
+  strtol_error name (char const *restrict, char **restrict, int, \
+                     type *restrict, char const *restrict);
 _DECLARE_XSTRTOL (xstrtol, long int)
 _DECLARE_XSTRTOL (xstrtoul, unsigned long int)
 _DECLARE_XSTRTOL (xstrtoll, long long int)
index 20f1de1498e88a65848bfb2af919c5bb4b0f564f..dd6dd17adac5ecd1a08045d6766c7b49c30996fa 100644 (file)
@@ -1,5 +1,5 @@
 # xstrtol.m4
-# serial 11
+# serial 12
 dnl Copyright (C) 2002-2007, 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,5 +7,6 @@ dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_XSTRTOL],
 [
+  AC_REQUIRE([AC_C_RESTRICT])
   :
 ])
index c9712dee0c7f1ee7a563528db04823d0c1557895..ef49dfc357b1f215d1985dfdd0ad2917ac51e126 100644 (file)
@@ -8,7 +8,6 @@ lib/xstrtoul.c
 m4/xstrtol.m4
 
 Depends-on:
-assure
 intprops
 stdckdint
 stdint