]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/, tests/: addsl(): Add addsl(), a variadic macro
authorAlejandro Colomar <alx@kernel.org>
Sat, 6 Jan 2024 01:17:38 +0000 (02:17 +0100)
committerIker Pedrosa <ikerpedrosam@gmail.com>
Tue, 16 Jan 2024 15:58:18 +0000 (16:58 +0100)
Add a variadic macro addsl() that accepts an arbitrary number of
addends, instead of having specific versions like addsl2() or addsl3().

It is internally implemented by the addslN() function, which itself
calls addsl2().  addsl3() is now obsolete and thus removed.

Code should just call addsl().

Link: <https://github.com/shadow-maint/shadow/pull/882#discussion_r1437155212>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/adds.c
lib/adds.h
tests/unit/test_adds.c

index b5ea3bb6651ef0aa9f552ca29bd7984780256258..5d8c1537f201d0dbf0fb5942a1a99185865f00e8 100644 (file)
@@ -6,8 +6,10 @@
 
 #include "adds.h"
 
+#include <stddef.h>
+
 
 extern inline long addsl2(long a, long b);
-extern inline long addsl3(long a, long b, long c);
+extern inline long addslN(size_t n, long addend[n]);
 
 extern inline int cmpl(const void *p1, const void *p2);
index 107e64e24cde0e3ed2b377b2570312be589be53c..6544ce5fe540c17d5220a0225e724f6ab38456f9 100644 (file)
 
 #include <errno.h>
 #include <limits.h>
+#include <stddef.h>
 #include <stdlib.h>
 
 #include "sizeof.h"
 
 
+#define addsl(a, b, ...)                                                      \
+({                                                                            \
+       long  addend_[] = {a, b, __VA_ARGS__};                                \
+                                                                              \
+       addslN(NITEMS(addend_), addend_);                                     \
+})
+
+
 inline long addsl2(long a, long b);
-inline long addsl3(long a, long b, long c);
+inline long addslN(size_t n, long addend[n]);
 
 inline int cmpl(const void *p1, const void *p2);
 
@@ -37,21 +46,26 @@ addsl2(long a, long b)
 
 
 inline long
-addsl3(long a, long b, long c)
+addslN(size_t n, long addend[n])
 {
        int   e;
-       long  sum;
-       long  n[3] = {a, b, c};
+
+       if (n == 0) {
+               errno = EDOM;
+               return 0;
+       }
 
        e = errno;
-       qsort(n, NITEMS(n), sizeof(n[0]), cmpl);
+       while (n > 1) {
+               qsort(addend, n, sizeof(addend[0]), cmpl);
 
-       errno = 0;
-       sum = addsl(n[0], n[2]);
-       if (errno == EOVERFLOW)
-               return sum;
+               errno = 0;
+               addend[0] = addsl2(addend[0], addend[--n]);
+               if (errno == EOVERFLOW)
+                       return addend[0];
+       }
        errno = e;
-       return addsl(sum, n[1]);
+       return addend[0];
 }
 
 
index 72790a59307cda54240ee0a8e8f98634af48661a..fdc671f5c639a5fb7a46b6574a81c68c9ef9c752 100644 (file)
@@ -19,6 +19,7 @@ static void test_addsl_2_overflow(void **state);
 static void test_addsl_3_ok(void **state);
 static void test_addsl_3_underflow(void **state);
 static void test_addsl_3_overflow(void **state);
+static void test_addsl_5_ok(void **state);
 
 
 int
@@ -31,6 +32,7 @@ main(void)
         cmocka_unit_test(test_addsl_3_ok),
         cmocka_unit_test(test_addsl_3_underflow),
         cmocka_unit_test(test_addsl_3_overflow),
+        cmocka_unit_test(test_addsl_5_ok),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);
@@ -40,41 +42,41 @@ main(void)
 static void
 test_addsl_2_ok(void **state)
 {
-       assert_true(addsl2(1, 3)                == 1 + 3);
-       assert_true(addsl2(-4321, 7)            == -4321 + 7);
-       assert_true(addsl2(1, 1)                == 1 + 1);
-       assert_true(addsl2(-1, -2)              == -1 - 2);
-       assert_true(addsl2(LONG_MAX, -1)        == LONG_MAX - 1);
-       assert_true(addsl2(LONG_MIN, 1)         == LONG_MIN + 1);
-       assert_true(addsl2(LONG_MIN, LONG_MAX)  == LONG_MIN + LONG_MAX);
-       assert_true(addsl2(0, 0)                == 0);
+       assert_true(addsl(1, 3)                 == 1 + 3);
+       assert_true(addsl(-4321, 7)             == -4321 + 7);
+       assert_true(addsl(1, 1)                 == 1 + 1);
+       assert_true(addsl(-1, -2)               == -1 - 2);
+       assert_true(addsl(LONG_MAX, -1)         == LONG_MAX - 1);
+       assert_true(addsl(LONG_MIN, 1)          == LONG_MIN + 1);
+       assert_true(addsl(LONG_MIN, LONG_MAX)   == LONG_MIN + LONG_MAX);
+       assert_true(addsl(0, 0)                 == 0);
 }
 
 
 static void
 test_addsl_2_underflow(void **state)
 {
-       assert_true(addsl2(LONG_MIN, -1)        == LONG_MIN);
-       assert_true(addsl2(LONG_MIN + 3, -7)    == LONG_MIN);
-       assert_true(addsl2(LONG_MIN, LONG_MIN)  == LONG_MIN);
+       assert_true(addsl(LONG_MIN, -1)         == LONG_MIN);
+       assert_true(addsl(LONG_MIN + 3, -7)     == LONG_MIN);
+       assert_true(addsl(LONG_MIN, LONG_MIN)   == LONG_MIN);
 }
 
 
 static void
 test_addsl_2_overflow(void **state)
 {
-       assert_true(addsl2(LONG_MAX, 1)         == LONG_MAX);
-       assert_true(addsl2(LONG_MAX - 3, 7)     == LONG_MAX);
-       assert_true(addsl2(LONG_MAX, LONG_MAX)  == LONG_MAX);
+       assert_true(addsl(LONG_MAX, 1)          == LONG_MAX);
+       assert_true(addsl(LONG_MAX - 3, 7)      == LONG_MAX);
+       assert_true(addsl(LONG_MAX, LONG_MAX)   == LONG_MAX);
 }
 
 
 static void
 test_addsl_3_ok(void **state)
 {
-       assert_true(addsl3(1, 2, 3)             == 1 + 2 + 3);
-       assert_true(addsl3(LONG_MIN, -3, 4)     == LONG_MIN + 4 - 3);
-       assert_true(addsl3(LONG_MAX, LONG_MAX, LONG_MIN)
+       assert_true(addsl(1, 2, 3)              == 1 + 2 + 3);
+       assert_true(addsl(LONG_MIN, -3, 4)      == LONG_MIN + 4 - 3);
+       assert_true(addsl(LONG_MAX, LONG_MAX, LONG_MIN)
                                                == LONG_MAX + LONG_MIN + LONG_MAX);
 }
 
@@ -82,15 +84,22 @@ test_addsl_3_ok(void **state)
 static void
 test_addsl_3_underflow(void **state)
 {
-       assert_true(addsl3(LONG_MIN, 2, -3)     == LONG_MIN);
-       assert_true(addsl3(LONG_MIN, -1, 0)     == LONG_MIN);
+       assert_true(addsl(LONG_MIN, 2, -3)      == LONG_MIN);
+       assert_true(addsl(LONG_MIN, -1, 0)      == LONG_MIN);
 }
 
 
 static void
 test_addsl_3_overflow(void **state)
 {
-       assert_true(addsl3(LONG_MAX, -1, 2)     == LONG_MAX);
-       assert_true(addsl3(LONG_MAX, +1, 0)     == LONG_MAX);
-       assert_true(addsl3(LONG_MAX, LONG_MAX, 0)== LONG_MAX);
+       assert_true(addsl(LONG_MAX, -1, 2)      == LONG_MAX);
+       assert_true(addsl(LONG_MAX, +1, 0)      == LONG_MAX);
+       assert_true(addsl(LONG_MAX, LONG_MAX, 0)== LONG_MAX);
+}
+
+
+static void
+test_addsl_5_ok(void **state)
+{
+       assert_true(addsl(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN, 44) == 42);
 }