]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/atoi/: a2i(): Re-implement with a statement expression
authorAlejandro Colomar <alx@kernel.org>
Thu, 16 Oct 2025 23:36:03 +0000 (01:36 +0200)
committerSerge Hallyn <serge@hallyn.com>
Fri, 28 Nov 2025 02:23:43 +0000 (20:23 -0600)
Synopsis
int a2i(typename T, T *restrict n, QChar *s,
        QChar **_Nullable restrict endp, int base,
        T min, T max);

Description
This macro converts the initial portion of the string pointed to
by 's' to an integer of base 'base', ensure that the number is
in the range [min, max], and store it in *n.

It is similar to NetBSD's strtoi(3) and strtou(3), which
themselves are similar to strtol(3) and strtoul(3).

Arguments
T
The integer type used for the number.
n
A pointer to an integer.  The parsed number will be
stored there.
s
See strtol(3).
endp
See strtol(3).  A difference with strtol(3) is that this
macro is const-correct.  If 's' has type 'const char *',
then 'endp' must have type 'const char **', whereas if
's' has type 'char *', 'endp' must have type 'char **'.
base
See strtol(3).
min
max
See strtoi(3) and strtou(3).

An important difference with NetBSD's strtou(3) is that
a2i() (with an unsigned type T) doesn't intepret any
negative numbers as if they were large positive numbers.
a2i() respects the limits [min, max] as one would
intuitively expect.

Return value
On success, 0 is returned.
On error, -1 is returned and errno is set to indicate the error.

Errors
See strtoi(3) and strtou(3).

Examples
if (a2i(pid_t, &pid, s, &s, 10, 1, _Maxof(pid_t)) == -1)
goto err;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/atoi/a2i/a2i.h
lib/atoi/a2i/a2s_c.c [deleted file]
lib/atoi/a2i/a2s_c.h [deleted file]
lib/atoi/a2i/a2s_nc.c [deleted file]
lib/atoi/a2i/a2s_nc.h [deleted file]
lib/atoi/a2i/a2u_c.c [deleted file]
lib/atoi/a2i/a2u_c.h [deleted file]
lib/atoi/a2i/a2u_nc.c [deleted file]
lib/atoi/a2i/a2u_nc.h [deleted file]

index c20a0f414764002c44146944437fe9492e3688cb..3533648b6b1e217a2ee2af0e21ae181c46b4e1c3 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
+// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
 // SPDX-License-Identifier: BSD-3-Clause
 
 
@@ -8,55 +8,38 @@
 
 #include "config.h"
 
-#include "atoi/a2i/a2s_c.h"
-#include "atoi/a2i/a2s_nc.h"
-#include "atoi/a2i/a2u_c.h"
-#include "atoi/a2i/a2u_nc.h"
-
-
-/*
- * See the manual of these macros in liba2i's documentation:
- * <http://www.alejandro-colomar.es/share/dist/liba2i/git/HEAD/liba2i-HEAD.pdf>
- */
-
-
-#define a2i(TYPE, n, s, ...)                                                  \
-(                                                                             \
-       _Generic((void (*)(TYPE, typeof(s))) 0,                               \
-               void (*)(short,              const char *):  a2sh_c,          \
-               void (*)(short,              const void *):  a2sh_c,          \
-               void (*)(short,              char *):        a2sh_nc,         \
-               void (*)(short,              void *):        a2sh_nc,         \
-               void (*)(int,                const char *):  a2si_c,          \
-               void (*)(int,                const void *):  a2si_c,          \
-               void (*)(int,                char *):        a2si_nc,         \
-               void (*)(int,                void *):        a2si_nc,         \
-               void (*)(long,               const char *):  a2sl_c,          \
-               void (*)(long,               const void *):  a2sl_c,          \
-               void (*)(long,               char *):        a2sl_nc,         \
-               void (*)(long,               void *):        a2sl_nc,         \
-               void (*)(long long,          const char *):  a2sll_c,         \
-               void (*)(long long,          const void *):  a2sll_c,         \
-               void (*)(long long,          char *):        a2sll_nc,        \
-               void (*)(long long,          void *):        a2sll_nc,        \
-               void (*)(unsigned short,     const char *):  a2uh_c,          \
-               void (*)(unsigned short,     const void *):  a2uh_c,          \
-               void (*)(unsigned short,     char *):        a2uh_nc,         \
-               void (*)(unsigned short,     void *):        a2uh_nc,         \
-               void (*)(unsigned int,       const char *):  a2ui_c,          \
-               void (*)(unsigned int,       const void *):  a2ui_c,          \
-               void (*)(unsigned int,       char *):        a2ui_nc,         \
-               void (*)(unsigned int,       void *):        a2ui_nc,         \
-               void (*)(unsigned long,      const char *):  a2ul_c,          \
-               void (*)(unsigned long,      const void *):  a2ul_c,          \
-               void (*)(unsigned long,      char *):        a2ul_nc,         \
-               void (*)(unsigned long,      void *):        a2ul_nc,         \
-               void (*)(unsigned long long, const char *):  a2ull_c,         \
-               void (*)(unsigned long long, const void *):  a2ull_c,         \
-               void (*)(unsigned long long, char *):        a2ull_nc,        \
-               void (*)(unsigned long long, void *):        a2ull_nc         \
-       )(n, s, __VA_ARGS__)                                                  \
-)
+#include <errno.h>
+
+#include "atoi/strtoi/strtoi.h"
+#include "atoi/strtoi/strtou_noneg.h"
+#include "typetraits.h"
+
+
+// a2i - alpha to integer
+#define a2i(T, n, s, endp, base, min, max)                            \
+({                                                                    \
+       T            *n_ = n;                                         \
+       QChar_of(s)  **endp_ = endp;                                  \
+       T            min_ = min;                                      \
+       T            max_ = max;                                      \
+                                                                      \
+       int  status;                                                  \
+                                                                      \
+       *n_ = _Generic((T){},                                         \
+               short:              strtoi_,                          \
+               int:                strtoi_,                          \
+               long:               strtoi_,                          \
+               long long:          strtoi_,                          \
+               unsigned short:     strtou_noneg,                     \
+               unsigned int:       strtou_noneg,                     \
+               unsigned long:      strtou_noneg,                     \
+               unsigned long long: strtou_noneg                      \
+       )(s, (char **) endp_, base, min_, max_, &status);             \
+                                                                      \
+       if (status != 0)                                              \
+               errno = status;                                       \
+       -!!status;                                                    \
+})
 
 
 #endif  // include guard
diff --git a/lib/atoi/a2i/a2s_c.c b/lib/atoi/a2i/a2s_c.c
deleted file mode 100644 (file)
index e5cea7d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#include "config.h"
-
-#include "atoi/a2i/a2s_c.h"
-
-
-extern inline int a2sh_c(short *restrict n, const char *s,
-    const char **restrict endp, int base, short min, short max);
-extern inline int a2si_c(int *restrict n, const char *s,
-    const char **restrict endp, int base, int min, int max);
-extern inline int a2sl_c(long *restrict n, const char *s,
-    const char **restrict endp, int base, long min, long max);
-extern inline int a2sll_c(long long *restrict n, const char *s,
-    const char **restrict endp, int base, long long min, long long max);
diff --git a/lib/atoi/a2i/a2s_c.h b/lib/atoi/a2i/a2s_c.h
deleted file mode 100644 (file)
index 375478b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
-#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
-
-
-#include "config.h"
-
-#include <errno.h>
-#include <inttypes.h>
-
-#include "atoi/a2i/a2s_nc.h"
-#include "attr.h"
-
-
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sh_c(short *restrict n, const char *s,
-    const char **restrict endp, int base, short min, short max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2si_c(int *restrict n, const char *s,
-    const char **restrict endp, int base, int min, int max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sl_c(long *restrict n, const char *s,
-    const char **restrict endp, int base, long min, long max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sll_c(long long *restrict n, const char *s,
-    const char **restrict endp, int base, long long min, long long max);
-
-
-inline int
-a2sh_c(short *restrict n, const char *s,
-    const char **restrict endp, int base, short min, short max)
-{
-       return a2sh_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2si_c(int *restrict n, const char *s,
-    const char **restrict endp, int base, int min, int max)
-{
-       return a2si_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2sl_c(long *restrict n, const char *s,
-    const char **restrict endp, int base, long min, long max)
-{
-       return a2sl_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2sll_c(long long *restrict n, const char *s,
-    const char **restrict endp, int base, long long min, long long max)
-{
-       return a2sll_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-#endif  // include guard
diff --git a/lib/atoi/a2i/a2s_nc.c b/lib/atoi/a2i/a2s_nc.c
deleted file mode 100644 (file)
index 381d906..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#include "config.h"
-
-#include "atoi/a2i/a2s_nc.h"
-
-
-extern inline int a2sh_nc(short *restrict n, char *s,
-    char **restrict endp, int base, short min, short max);
-extern inline int a2si_nc(int *restrict n, char *s,
-    char **restrict endp, int base, int min, int max);
-extern inline int a2sl_nc(long *restrict n, char *s,
-    char **restrict endp, int base, long min, long max);
-extern inline int a2sll_nc(long long *restrict n, char *s,
-    char **restrict endp, int base, long long min, long long max);
diff --git a/lib/atoi/a2i/a2s_nc.h b/lib/atoi/a2i/a2s_nc.h
deleted file mode 100644 (file)
index 31bb911..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
-#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
-
-
-#include "config.h"
-
-#include <errno.h>
-
-#include "atoi/strtoi/strtoi.h"
-#include "attr.h"
-
-
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sh_nc(short *restrict n, char *s,
-    char **restrict endp, int base, short min, short max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2si_nc(int *restrict n, char *s,
-    char **restrict endp, int base, int min, int max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sl_nc(long *restrict n, char *s,
-    char **restrict endp, int base, long min, long max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2sll_nc(long long *restrict n, char *s,
-    char **restrict endp, int base, long long min, long long max);
-
-
-inline int
-a2sh_nc(short *restrict n, char *s,
-    char **restrict endp, int base, short min, short max)
-{
-       int  status;
-
-       *n = strtoi_(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2si_nc(int *restrict n, char *s,
-    char **restrict endp, int base, int min, int max)
-{
-       int  status;
-
-       *n = strtoi_(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2sl_nc(long *restrict n, char *s,
-    char **restrict endp, int base, long min, long max)
-{
-       int  status;
-
-       *n = strtoi_(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2sll_nc(long long *restrict n, char *s,
-    char **restrict endp, int base, long long min, long long max)
-{
-       int  status;
-
-       *n = strtoi_(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-#endif  // include guard
diff --git a/lib/atoi/a2i/a2u_c.c b/lib/atoi/a2i/a2u_c.c
deleted file mode 100644 (file)
index e7c9cbf..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#include "config.h"
-
-#include "atoi/a2i/a2u_c.h"
-
-
-extern inline int a2uh_c(unsigned short *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned short min,
-    unsigned short max);
-extern inline int a2ui_c(unsigned int *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned int min, unsigned int max);
-extern inline int a2ul_c(unsigned long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long min, unsigned long max);
-extern inline int a2ull_c(unsigned long long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long long min,
-    unsigned long long max);
diff --git a/lib/atoi/a2i/a2u_c.h b/lib/atoi/a2i/a2u_c.h
deleted file mode 100644 (file)
index 544846c..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
-#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
-
-
-#include "config.h"
-
-#include "atoi/a2i/a2u_nc.h"
-#include "attr.h"
-
-
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2uh_c(unsigned short *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned short min,
-    unsigned short max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ui_c(unsigned int *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned int min, unsigned int max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ul_c(unsigned long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long min, unsigned long max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ull_c(unsigned long long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long long min,
-    unsigned long long max);
-
-
-inline int
-a2uh_c(unsigned short *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned short min,
-    unsigned short max)
-{
-       return a2uh_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2ui_c(unsigned int *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned int min, unsigned int max)
-{
-       return a2ui_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2ul_c(unsigned long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long min, unsigned long max)
-{
-       return a2ul_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-inline int
-a2ull_c(unsigned long long *restrict n, const char *s,
-    const char **restrict endp, int base, unsigned long long min,
-    unsigned long long max)
-{
-       return a2ull_nc(n, (char *) s, (char **) endp, base, min, max);
-}
-
-
-#endif  // include guard
diff --git a/lib/atoi/a2i/a2u_nc.c b/lib/atoi/a2i/a2u_nc.c
deleted file mode 100644 (file)
index 10eb0d2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#include "config.h"
-
-#include "atoi/a2i/a2u_nc.h"
-
-
-extern inline int a2uh_nc(unsigned short *restrict n, char *s,
-    char **restrict endp, int base, unsigned short min, unsigned short max);
-extern inline int a2ui_nc(unsigned int *restrict n, char *s,
-    char **restrict endp, int base, unsigned int min, unsigned int max);
-extern inline int a2ul_nc(unsigned long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long min, unsigned long max);
-extern inline int a2ull_nc(unsigned long long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long long min,
-    unsigned long long max);
diff --git a/lib/atoi/a2i/a2u_nc.h b/lib/atoi/a2i/a2u_nc.h
deleted file mode 100644 (file)
index 93409c1..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
-// SPDX-License-Identifier: BSD-3-Clause
-
-
-#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
-#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
-
-
-#include "config.h"
-
-#include <errno.h>
-
-#include "atoi/strtoi/strtou_noneg.h"
-#include "attr.h"
-
-
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2uh_nc(unsigned short *restrict n, char *s,
-    char **restrict endp, int base, unsigned short min, unsigned short max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ui_nc(unsigned int *restrict n, char *s,
-    char **restrict endp, int base, unsigned int min, unsigned int max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ul_nc(unsigned long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long min, unsigned long max);
-ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
-inline int a2ull_nc(unsigned long long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long long min,
-    unsigned long long max);
-
-
-inline int
-a2uh_nc(unsigned short *restrict n, char *s,
-    char **restrict endp, int base, unsigned short min,
-    unsigned short max)
-{
-       int  status;
-
-       *n = strtou_noneg(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2ui_nc(unsigned int *restrict n, char *s,
-    char **restrict endp, int base, unsigned int min, unsigned int max)
-{
-       int  status;
-
-       *n = strtou_noneg(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2ul_nc(unsigned long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long min, unsigned long max)
-{
-       int  status;
-
-       *n = strtou_noneg(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-inline int
-a2ull_nc(unsigned long long *restrict n, char *s,
-    char **restrict endp, int base, unsigned long long min,
-    unsigned long long max)
-{
-       int  status;
-
-       *n = strtou_noneg(s, endp, base, min, max, &status);
-       if (status != 0) {
-               errno = status;
-               return -1;
-       }
-       return 0;
-}
-
-
-#endif  // include guard