aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--Makefile3
-rw-r--r--close_range.c19
-rw-r--r--get_stack_limit.c26
-rw-r--r--get_stack_space.c5
-rw-r--r--libsimple.h1
-rw-r--r--libsimple/definitions.h110
-rw-r--r--libsimple/random.h103
-rw-r--r--libsimple/stack.h50
-rw-r--r--libsimple/time.h39
-rw-r--r--man3/libsimple_close_range.35
-rw-r--r--random_bits.c6
-rw-r--r--random_bytes.c41
13 files changed, 371 insertions, 39 deletions
diff --git a/LICENSE b/LICENSE
index b29e37d..99eb019 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
ISC License
-© 2017, 2018, 2021, 2022, 2023, 2024 Mattias Andrée <maandree@kth.se>
+© 2017, 2018, 2021, 2022, 2023, 2024, 2025 Mattias Andrée <m@maandree.se>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/Makefile b/Makefile
index 4c2f411..c85db9d 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ include mk/$(OS).mk
LIB_MAJOR = 1
-LIB_MINOR = 7
+LIB_MINOR = 8
LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
LIB_NAME = simple
@@ -941,6 +941,7 @@ OBJ =\
qsort_ushortp.o\
qsort_ushortp_nul.o\
random_bits.o\
+ random_bytes.o\
random_float.o\
random_signed.o\
random_unsigned.o\
diff --git a/close_range.c b/close_range.c
index 540eba0..096aa56 100644
--- a/close_range.c
+++ b/close_range.c
@@ -73,7 +73,8 @@ libsimple_close_range(unsigned int first, unsigned int last, unsigned int *next)
{
int saved_errno;
- *next = first;
+ if (next)
+ *next = first;
if (first > last) {
errno = EINVAL;
@@ -103,10 +104,12 @@ libsimple_close_range(unsigned int first, unsigned int last, unsigned int *next)
qsort(fds, n, sizeof(*fds), uintpcmp);
for (i = 0; i < n; i++) {
if (close((int)fds[i]) && errno != EBADF) {
- if (i + 1 < n)
- *next = fds[i + 1];
- else
- *next = fds[i] + (fds[i] < LIBSIMPLE_CLOSE_RANGE_MAX);
+ if (next) {
+ if (i + 1 < n)
+ *next = fds[i + 1];
+ else
+ *next = fds[i] + (fds[i] < LIBSIMPLE_CLOSE_RANGE_MAX);
+ }
free(fds);
return -1;
}
@@ -118,13 +121,15 @@ libsimple_close_range(unsigned int first, unsigned int last, unsigned int *next)
fallback:
do {
if (close((int)first) && errno != EBADF) {
- *next = first + (first < LIBSIMPLE_CLOSE_RANGE_MAX);
+ if (next)
+ *next = first + (first < LIBSIMPLE_CLOSE_RANGE_MAX);
return -1;
}
} while (first++ < last);
out:
- *next = last + (last < LIBSIMPLE_CLOSE_RANGE_MAX);
+ if (next)
+ *next = last + (last < LIBSIMPLE_CLOSE_RANGE_MAX);
errno = saved_errno;
return 0;
}
diff --git a/get_stack_limit.c b/get_stack_limit.c
index 363147a..cb19f2d 100644
--- a/get_stack_limit.c
+++ b/get_stack_limit.c
@@ -12,7 +12,7 @@ libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard)
size_t off = 0;
size_t lineoff, linelen;
- fd = open("/proc/self/limits", O_RDONLY);
+ fd = open("/proc/thread-self/limits", O_RDONLY);
if (fd < 0)
return -1;
@@ -41,22 +41,30 @@ libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard)
if (!strcmp(line, "Max stack size "))
goto line_found;
}
-
}
-
+
line_found:
close(fd);
line = &line[sizeof("Max stack size ") - 1U];
- while (*line == ' ')
+ while (*line == ' ' || *line == '\t')
line++;
- if (soft)
- *soft = (size_t)strtoull(line, NULL, 10);
+ if (soft) {
+ *soft = SIZE_MAX;
+ if (isdigit(*line))
+ *soft = (size_t)strtoull(line, NULL, 10);
+ }
- while (*line == ' ')
+ while (*line != ' ' && *line != '\t' && *line && *line != '\n')
line++;
- if (hard)
- *hard = (size_t)strtoull(line, NULL, 10);
+
+ while (*line == ' ' || *line == '\t')
+ line++;
+ if (hard) {
+ *hard = SIZE_MAX;
+ if (isdigit(*line))
+ *hard = (size_t)strtoull(line, NULL, 10);
+ }
return 0;
}
diff --git a/get_stack_space.c b/get_stack_space.c
index 7f1fdd3..bb0d92b 100644
--- a/get_stack_space.c
+++ b/get_stack_space.c
@@ -12,7 +12,7 @@ libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high)
size_t off = 0;
size_t lineoff, linelen;
- fd = open("/proc/self/maps", O_RDONLY);
+ fd = open("/proc/thread-self/maps", O_RDONLY);
if (fd < 0)
return -1;
@@ -41,9 +41,8 @@ libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high)
if (!strcmp(&line[linelen - (sizeof(" [stack]\n") - 1U)], " [stack]\n"))
goto line_found;
}
-
}
-
+
line_found:
close(fd);
diff --git a/libsimple.h b/libsimple.h
index ba01ab5..6d1867e 100644
--- a/libsimple.h
+++ b/libsimple.h
@@ -211,6 +211,7 @@ libsimple_close(int *fdp__)
* @throws Any error for close(3) except EBADF
*
* @since 1.6
+ * @since 1.8 `next` can be `NULL`
*/
int libsimple_close_range(unsigned int first, unsigned int last, unsigned int *next);
#define LIBSIMPLE_CLOSE_RANGE_MAX (~0U)
diff --git a/libsimple/definitions.h b/libsimple/definitions.h
index 6fbc17f..b0f816b 100644
--- a/libsimple/definitions.h
+++ b/libsimple/definitions.h
@@ -218,13 +218,117 @@
*
* This macro does not support the wide-character strings
*
- * @param STR:const char [] The string, must be a literal
- * @return :size_t The value of `strlen(STR)` as a constant expression
+ * @param STR:string literal The string (must be a literal)
+ * @return :size_t The value of `strlen(STR)` as a constant expression
*
* @since 1.0
*/
#ifndef STRLEN
-# define STRLEN(STR) (sizeof(STR) - 1)
+# define STRLEN(STR) (sizeof(STR) - 1U)
+#endif
+
+
+/**
+ * Get the length of a string, stored in as a
+ * character array, that might not be NUL-termianted
+ *
+ * Note that since arrays are passed as pointers
+ * in function arguments, function parameters
+ * declared as arrays are actually pointers and
+ * cannot be used with this macro
+ *
+ * Using this macro when `S` is a pointer,
+ * will cause the returned length to be truncated
+ * to at most `sizeof(void *)`
+ *
+ * @param S:char[] The string to get the legnth of
+ * @return The length of `S`
+ *
+ * @since 1.8
+ */
+#ifndef BUFSTRLEN
+# define BUFSTRLEN(S) (strnlen((S), sizeof(S))) /* TODO man */
+#endif
+
+
+/**
+ * This macro doesn't really do anything, but
+ * it can be used to mark that a poorly named
+ * constant is the length of a string including
+ * the NUL byte
+ *
+ * @param X:size_t Any value
+ * @return :size_t `X` as is
+ *
+ * @since 1.8
+ */
+#ifndef ISSTRSIZE
+# define ISSTRSIZE(X) (X) /* TODO man */
+#endif
+
+
+/**
+ * Macro that can be used to mark that a value
+ * is the length of a string excluding the NUL
+ * byte, but adds one to convert it to the
+ * length of the string inlcuding the NUL byte
+ *
+ * @param X:size_t String length excluding NUL byte
+ * @return :size_t String length including NUL byte
+ *
+ * @since 1.8
+ */
+#ifndef TOSTRSIZE
+# define TOSTRSIZE(X) ((X) + 1U) /* TODO man */
+#endif
+
+
+/**
+ * This macro doesn't really do anything, but
+ * it can be used to mark that a poorly named
+ * constant is the length of a string excluding
+ * the NUL byte
+ *
+ * @param X:size_t Any value
+ * @return :size_t `X` as is
+ *
+ * @since 1.8
+ */
+#ifndef ISSTRLEN
+# define ISSTRLEN(X) (X) /* TODO man */
+#endif
+
+
+/**
+ * Macro that can be used to mark that a value
+ * is the length of a string including the NUL
+ * byte, but substracts one to convert it to the
+ * length of the string exlcuding the NUL byte
+ *
+ * @param X:size_t String length including NUL byte
+ * @return :size_t String length excluding NUL byte
+ *
+ * @since 1.8
+ */
+#ifndef TOSTRLEN
+# define TOSTRLEN(X) ((X) - 1U) /* TODO man */
+#endif
+
+
+/**
+ * Limit a value to an inclusive range
+ *
+ * @param MINIMUM The minimum allowed value
+ * @param X The value to limit
+ * @param MAXIMUM The maximum allowed value
+ * @return `X` except no less than `MINIMUM` and no greater than `MAXIMUM`
+ *
+ * `MAXIMUM` must be at least `MINIMUM`
+ *
+ * @since 1.8
+ */
+#ifndef LIMITRANGE
+# define LIMITRANGE(MINIMUM, X, MAXIMUM) (MIN(MAX((MINIMUM), (X)), (MAXIMUM))) /* TODO man */
#endif
diff --git a/libsimple/random.h b/libsimple/random.h
index 29e3bbf..d3cc008 100644
--- a/libsimple/random.h
+++ b/libsimple/random.h
@@ -9,8 +9,7 @@
* @since 1.6
*/
LIBSIMPLE_GCC_ONLY__(__attribute__((__warn_unused_result__)))
-unsigned int libsimple_generate_seed(void); /* TODO add man page */
-
+unsigned int libsimple_generate_seed(void); /* TODO man */
/**
* Wrapper for srand(3) that creates a pseudo-random
@@ -20,14 +19,102 @@ unsigned int libsimple_generate_seed(void); /* TODO add man page */
* @since 1.6
*/
inline void
-libsimple_srand(void) /* TODO add man page */
+libsimple_srand(void) /* TODO man */
{
srand(libsimple_generate_seed());
}
+/**
+ * Generate a set of uniformly random bits
+ *
+ * @param bits The number of bits to generate
+ * @param unused This parameter is unused, but is provided so that
+ * the function has a prototype that is compatible
+ * with alternative functions that need an extra
+ * argument to make it reenterent
+ * @return An integer with it's lowest `bits` bits independently
+ * randomly set, each bit has a 50 % chance of being
+ * cleared and 50 a % chance of being set, any excess
+ * bit will be cleared
+ *
+ * @since 1.6
+ */
+uintmax_t libsimple_random_bits(size_t bits, void *unused); /* TODO man */
-/* TODO doc, man (since 1.6) (libsimple_random_float requires -lm) */
-uintmax_t libsimple_random_bits(size_t bits, void *unused);
-uintmax_t libsimple_random_unsigned(uintmax_t (*rng)(size_t bits, void *user), void *user, uintmax_t min, uintmax_t max);
-intmax_t libsimple_random_signed(uintmax_t (*rng)(size_t bits, void *user), void *user, intmax_t min, intmax_t max);
-long double libsimple_random_float(uintmax_t (*rng)(size_t bits, void *user), void *user, long double min, long double postmax);
+/**
+ * Generate a uniformally random, unsigned integer with [`min`, `max`]
+ *
+ * @param rng Random bit generating function, `libsimple_random_bits`
+ * can be used, if any other function is used, it must
+ * have the same specification: the first argument is
+ * the number of bits to generate, the second argument
+ * will be `user` and is either unused or defined by the
+ * function, and the returned value shall have it's `bits`
+ * lowest bits randomly set and all other bits cleared
+ * @param user Pass into `*rng` as it's second argument
+ * @param min The lower, inclusive, boundary for the random value
+ * @param max The upper, inclusive, boundary for the random value
+ * @return A uniformally random, unsigned integer within [`min`, `max`]
+ *
+ * @since 1.6
+ */
+uintmax_t libsimple_random_unsigned(uintmax_t (*rng)(size_t bits, void *user), void *user, uintmax_t min, uintmax_t max); /* TODO man */
+
+/**
+ * Generate a uniformally random, signed integer with [`min`, `max`]
+ *
+ * @param rng Random bit generating function, `libsimple_random_bits`
+ * can be used, if any other function is used, it must
+ * have the same specification: the first argument is
+ * the number of bits to generate, the second argument
+ * will be `user` and is either unused or defined by the
+ * function, and the returned value shall have it's `bits`
+ * lowest bits randomly set and all other bits cleared
+ * @param user Pass into `*rng` as it's second argument
+ * @param min The lower, inclusive, boundary for the random value
+ * @param max The upper, inclusive, boundary for the random value
+ * @return A uniformally random, signed integer within [`min`, `max`]
+ *
+ * @since 1.6
+ */
+intmax_t libsimple_random_signed(uintmax_t (*rng)(size_t bits, void *user), void *user, intmax_t min, intmax_t max); /* TODO man */
+
+/**
+ * Generate a uniformally random, real number with [`min`, `postmax`)
+ *
+ * @param rng Random bit generating function, `libsimple_random_bits`
+ * can be used, if any other function is used, it must
+ * have the same specification: the first argument is
+ * the number of bits to generate, the second argument
+ * will be `user` and is either unused or defined by the
+ * function, and the returned value shall have it's `bits`
+ * lowest bits randomly set and all other bits cleared
+ * @param user Pass into `*rng` as it's second argument
+ * @param min The lower, inclusive, boundary for the random value
+ * @param max The upper, exclusive, boundary for the random value
+ * @return A uniformally random, real number within [`min`, `postmax`)
+ *
+ * @linkwith -lm
+ *
+ * @since 1.6
+ */
+long double libsimple_random_float(uintmax_t (*rng)(size_t bits, void *user), void *user, long double min, long double postmax); /* TODO man */
+
+/**
+ * Generate a set uniformally random bytes
+ *
+ * @param rng Random bit generating function, `libsimple_random_bits`
+ * can be used, if any other function is used, it must
+ * have the same specification: the first argument is
+ * the number of bits to generate, the second argument
+ * will be `user` and is either unused or defined by the
+ * function, and the returned value shall have it's `bits`
+ * lowest bits randomly set and all other bits cleared
+ * @param user Pass into `*rng` as it's second argument
+ * @param buffer Output buffer for the random bytes
+ * @param bytes The number of bytes to generate
+ * @return The end of `buffer`
+ *
+ * @since 1.7
+ */
+void *libsimple_random_bytes(uintmax_t (*rng)(size_t bits, void *user), void *user, void *buffer, size_t bytes); /* TODO man */
diff --git a/libsimple/stack.h b/libsimple/stack.h
index a7b1294..bb082f6 100644
--- a/libsimple/stack.h
+++ b/libsimple/stack.h
@@ -1,11 +1,53 @@
/* See LICENSE file for copyright and license details. */
-int libsimple_get_stack_space(uintptr_t *restrict, uintptr_t *restrict); /* TODO man, doc (since 1.7) */
-int libsimple_get_stack_limit(size_t *restrict, size_t *restrict); /* TODO man, doc (since 1.7) */
-int libsimple_get_stack_direction(void); /* TODO man, doc (since 1.7) */
+/**
+ * Get area of the the thread's stack space
+ *
+ * @param low Output parameter for the address of the beginning of the stack space
+ * @param high Output parameter for the address immediately after the last byte in the stack space
+ * @return 0 on success, -1 on failure
+ *
+ * @since 1.7
+ */
+LIBSIMPLE_GCC_ONLY__(__attribute__((__nonnull__)))
+int libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high); /* TODO man */
-int libsimple_needstack(size_t); /* TODO man, doc (since 1.7) */
+/**
+ * Get the stack size limit for the thread
+ *
+ * @param soft Output parameter for the soft limit, or `NULL`
+ * @param hard Output parameter for the hard limit, or `NULL`
+ * @return 0 on success, -1 on failure
+ *
+ * @since 1.7
+ */
+int libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard); /* TODO man */
+
+/**
+ * Get the direction the stack grows in
+ *
+ * @return +1 if the stack grows upwards (higher addresses),
+ * -1 if the stack grows downwards (lower addresses),
+ * 0 on failure
+ *
+ * @throws ENOTSUP Unable to determine stack growth direction
+ *
+ * @since 1.7
+ */
+int libsimple_get_stack_direction(void); /* TODO man */
+
+/**
+ * Check if the some amount of memory can be allowed on the stack
+ *
+ * @param n The amount of memory
+ * @return 1 if `n` bytes can be allocated,
+ * 0 if `n` bytes may or may not be allocated,
+ * -1 on failure
+ *
+ * @since 1.7
+ */
+int libsimple_needstack(size_t n); /* TODO man */
#ifndef needstack
# define needstack libsimple_needstack
#endif
diff --git a/libsimple/time.h b/libsimple/time.h
index b873635..5317cfc 100644
--- a/libsimple/time.h
+++ b/libsimple/time.h
@@ -1,6 +1,45 @@
/* See LICENSE file for copyright and license details. */
+/* TODO man, doc (since 1.8) */
+#define LIBSIMPLE_NANOSECONDS_PER_NANOSECOND UINT64_C(1)
+#define LIBSIMPLE_NANOSECONDS_PER_MICROSECOND UINT64_C(1000)
+#define LIBSIMPLE_NANOSECONDS_PER_MILLISECOND (LIBSIMPLE_NANOSECONDS_PER_MICROSECOND * UINT64_C(1000))
+#define LIBSIMPLE_NANOSECONDS_PER_SECOND (LIBSIMPLE_NANOSECONDS_PER_MILLISECOND * UINT64_C(1000))
+#define LIBSIMPLE_NANOSECONDS_PER_MINUTE (LIBSIMPLE_NANOSECONDS_PER_SECOND * UINT64_C(60))
+#define LIBSIMPLE_NANOSECONDS_PER_HOUR (LIBSIMPLE_NANOSECONDS_PER_MINUTE * UINT64_C(60))
+#define LIBSIMPLE_NANOSECONDS_PER_DAY (LIBSIMPLE_NANOSECONDS_PER_HOUR * UINT64_C(24))
+#define LIBSIMPLE_NANOSECONDS_PER_WEEK (LIBSIMPLE_NANOSECONDS_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_MICROSECONDS_PER_MICROSECOND UINT64_C(1)
+#define LIBSIMPLE_MICROSECONDS_PER_MILLISECOND UINT64_C(1000)
+#define LIBSIMPLE_MICROSECONDS_PER_SECOND (LIBSIMPLE_MICROSECONDS_PER_MICROSECOND * UINT64_C(1000))
+#define LIBSIMPLE_MICROSECONDS_PER_MINUTE (LIBSIMPLE_MICROSECONDS_PER_SECOND * UINT64_C(60))
+#define LIBSIMPLE_MICROSECONDS_PER_HOUR (LIBSIMPLE_MICROSECONDS_PER_MINUTE * UINT64_C(60))
+#define LIBSIMPLE_MICROSECONDS_PER_DAY (LIBSIMPLE_MICROSECOND_PER_HOUR * UINT64_C(24))
+#define LIBSIMPLE_MICROSECONDS_PER_WEEK (LIBSIMPLE_MICROSECOND_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_MILLISECONDS_PER_MILLISECONDS UINT64_C(1)
+#define LIBSIMPLE_MILLISECONDS_PER_SECOND UINT64_C(1000)
+#define LIBSIMPLE_MILLISECONDS_PER_MINUTE (LIBSIMPLE_MILLISECONDS_PER_SECOND * UINT64_C(60))
+#define LIBSIMPLE_MILLISECONDS_PER_HOUR (LIBSIMPLE_MILLISECONDS_PER_MINUTE * UINT64_C(60))
+#define LIBSIMPLE_MILLISECONDS_PER_DAY (LIBSIMPLE_MILLISECONDS_PER_HOUR * UINT64_C(24))
+#define LIBSIMPLE_MILLISECONDS_PER_WEEK (LIBSIMPLE_MILLISECONDS_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_SECONDS_PER_SECOND UINT64_C(1)
+#define LIBSIMPLE_SECONDS_PER_MINUTE UINT64_C(60)
+#define LIBSIMPLE_SECONDS_PER_HOUR (LIBSIMPLE_SECONDS_PER_MINUTE * UINT64_C(60))
+#define LIBSIMPLE_SECONDS_PER_DAY (LIBSIMPLE_SECONDS_PER_HOUR * UINT64_C(24))
+#define LIBSIMPLE_SECONDS_PER_WEEK (LIBSIMPLE_SECONDS_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_MINUTES_PER_MINUTE UINT64_C(1)
+#define LIBSIMPLE_MINUTES_PER_HOUR UINT64_C(60)
+#define LIBSIMPLE_MINUTES_PER_DAY (LIBSIMPLE_MINUTES_PER_HOUR * UINT64_C(24))
+#define LIBSIMPLE_MINUTES_PER_WEEK (LIBSIMPLE_MINUTES_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_HOURS_PER_HOUR UINT64_C(1)
+#define LIBSIMPLE_HOURS_PER_DAY UINT64_C(24)
+#define LIBSIMPLE_HOURS_PER_WEEK (LIBSIMPLE_HOURS_PER_DAY * UINT64_C(7))
+#define LIBSIMPLE_DAYS_PER_DAY UINT64_C(1)
+#define LIBSIMPLE_DAYS_PER_WEEK UINT64_C(7)
+#define LIBSIMPLE_WEEKS_PER_WEEK UINT64_C(1)
+
+
/**
* Calculates the sum of two `struct timespec`s
*
diff --git a/man3/libsimple_close_range.3 b/man3/libsimple_close_range.3
index 76094d0..a1b172c 100644
--- a/man3/libsimple_close_range.3
+++ b/man3/libsimple_close_range.3
@@ -69,7 +69,10 @@ None.
libsimple 1.6
.SH BUGS
-None.
+.I next
+could not be
+.I NULL
+before version 1.8 of libsimple.
.SH SEE ALSO
.BR close_range (2),
diff --git a/random_bits.c b/random_bits.c
index 528b09e..a6d95a2 100644
--- a/random_bits.c
+++ b/random_bits.c
@@ -14,8 +14,10 @@ libsimple_random_bits(size_t bits, void *unused)
bits -= 8;
}
- ret <<= bits;
- ret |= (uintmax_t)(rand() & ((1 << bits) - 1));
+ if (bits) {
+ ret <<= bits;
+ ret |= (uintmax_t)(rand() & ((1 << bits) - 1));
+ }
(void) unused;
return ret;
diff --git a/random_bytes.c b/random_bytes.c
new file mode 100644
index 0000000..723fc63
--- /dev/null
+++ b/random_bytes.c
@@ -0,0 +1,41 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+void *
+libsimple_random_bytes(uintmax_t (*rng)(size_t bits, void *user), void *user, void *buffer, size_t bytes)
+{
+ char *buf = buffer;
+ uintmax_t rnd;
+
+ while (bytes >= sizeof(uintmax_t)) {
+ rnd = (*rng)(sizeof(uintmax_t) * 8U, user);
+ memcpy(buf, &rnd, sizeof(uintmax_t));
+ bytes -= sizeof(uintmax_t);
+ buf = &buf[sizeof(uintmax_t)];
+ }
+
+ if (bytes) {
+ rnd = (*rng)(bytes * 8U, user);
+ while (bytes) {
+ *buf++ = (char)(rnd & 255U);
+ bytes--;
+ rnd >>= 8;
+ }
+ }
+
+ return buf;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void)
+{
+ return 0;
+}
+
+#endif