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>
87 lines
1.5 KiB
C
87 lines
1.5 KiB
C
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
|
#ifndef SHADOW_INCLUDE_LIB_ADDS_H_
|
|
#define SHADOW_INCLUDE_LIB_ADDS_H_
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#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 addslN(size_t n, long addend[n]);
|
|
|
|
inline int cmpl(const void *p1, const void *p2);
|
|
|
|
|
|
inline long
|
|
addsl2(long a, long b)
|
|
{
|
|
if (a > 0 && b > LONG_MAX - a) {
|
|
errno = EOVERFLOW;
|
|
return LONG_MAX;
|
|
}
|
|
if (a < 0 && b < LONG_MIN - a) {
|
|
errno = EOVERFLOW;
|
|
return LONG_MIN;
|
|
}
|
|
return a + b;
|
|
}
|
|
|
|
|
|
inline long
|
|
addslN(size_t n, long addend[n])
|
|
{
|
|
int e;
|
|
|
|
if (n == 0) {
|
|
errno = EDOM;
|
|
return 0;
|
|
}
|
|
|
|
e = errno;
|
|
while (n > 1) {
|
|
qsort(addend, n, sizeof(addend[0]), cmpl);
|
|
|
|
errno = 0;
|
|
addend[0] = addsl2(addend[0], addend[--n]);
|
|
if (errno == EOVERFLOW)
|
|
return addend[0];
|
|
}
|
|
errno = e;
|
|
return addend[0];
|
|
}
|
|
|
|
|
|
inline int
|
|
cmpl(const void *p1, const void *p2)
|
|
{
|
|
const long *l1 = p1;
|
|
const long *l2 = p2;
|
|
|
|
if (*l1 < *l2)
|
|
return -1;
|
|
if (*l1 > *l2)
|
|
return +1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
#endif // include guard
|