#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);
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];
}
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
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);
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);
}
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);
}