diff --git a/lib/adds.c b/lib/adds.c index b5ea3bb6..5d8c1537 100644 --- a/lib/adds.c +++ b/lib/adds.c @@ -6,8 +6,10 @@ #include "adds.h" +#include + 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); diff --git a/lib/adds.h b/lib/adds.h index 107e64e2..6544ce5f 100644 --- a/lib/adds.h +++ b/lib/adds.h @@ -10,13 +10,22 @@ #include #include +#include #include #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]; } diff --git a/tests/unit/test_adds.c b/tests/unit/test_adds.c index 72790a59..fdc671f5 100644 --- a/tests/unit/test_adds.c +++ b/tests/unit/test_adds.c @@ -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); }