Add wasm tacle-bench targets

This commit is contained in:
2026-06-12 20:06:22 +02:00
parent 30daa8a00c
commit 08c2e9c13d
1122 changed files with 520422 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*
Include section
*/
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
#include "ammunition_string.h"
/*
Standard library functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
char
ammunition_isdigit(unsigned char c) {
if ((c >= '0') & (c <= '9'))
return 1;
else
return 0;
}
int
ammunition_isspace(int c) {
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
}
void *
ammunition_memcpy(void *dest, const void *src, size_t size) {
size_t i;
__pragma_loopbound(2, 6);
for (i = 0; i < size; i++)
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
return dest;
}
void *
ammunition_memset(void *s, int c, size_t n) {
size_t i;
__pragma_loopbound(0, 4);
for (i = 0; i < n; i++)
((unsigned char *) s)[i] = (unsigned char) c;
return s;
}
int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
const unsigned char *p1 = (const unsigned char *) mem1,
*p2 = (const unsigned char *) mem2;
__pragma_loopbound(0, 4);
while (size--)
if (*p1 != *p2)
return (*p1 - *p2);
else
p1++, p2++;
return 0;
}
/* The following function is an analog of standard C function
`memmove'. The function returns the first operand. */
void *
ammunition_memmove(void *s1, const void *s2, size_t n) {
int i;
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
return (void *) ammunition_memcpy(s1, s2, n);
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
__pragma_loopbound(0, 4);
for (i = 0; (size_t) i < n; i++)
((char *) s1)[i] = ((char *) s2)[i];
} else {
__pragma_loopbound(0, 4);
for (i = n - 1; i >= 0; i--)
((char *) s1)[i] = ((char *) s2)[i];
}
return s1;
}
int
ammunition_strcmp(const char *str1, const char *str2) {
__pragma_loopbound(1, 11);
while (*str1 && (*str1 == *str2))
str1++, str2++;
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
}
int
ammunition_atoi(const char *str) {
int result = 0;
int sign = (str[0] == '-' ? -1 : 1);
int readingPos = 0;
if (str[0] == '-' || str[0] == '+')
readingPos++;
__pragma_loopbound(1, 7);
do {
result *= 10;
result += str[readingPos++] - 48;
} while (str[readingPos] != 0);
return sign * result;
}
int
ammunition_sprintf_d(char *s, int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
if (number < 0) {
writePos++;
s[0] = '-';
}
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] =
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits + (number < 0 ? 1 : 0);
}
int
ammunition_sprintf_u(char *s, unsigned int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
unsigned long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] = 48 + (copyOfNumber % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits;
}

View File

@ -0,0 +1,36 @@
#ifndef AMMUNITION_LIMITS_H
#define AMMUNITION_LIMITS_H
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
#ifndef SCHAR_MAX
#define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
#define SCHAR_MIN (-128)
#endif
#ifndef USHRT_MAX
#define USHRT_MAX 65535
#endif
#ifndef SHRT_MAX
#define SHRT_MAX 32767
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
#ifndef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#endif
#endif /* #ifndef AMMUNITION_LIMITS_H */

View File

@ -0,0 +1,9 @@
#ifndef AMMUNITION_STDIO_H
#define AMMUNITION_STDIO_H
int ammunition_sprintf_d(char *s, int number);
int ammunition_sprintf_u(char *s, unsigned int number);
#endif

View File

@ -0,0 +1,7 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
int ammunition_atoi(const char *str);
#endif

View File

@ -0,0 +1,17 @@
#ifndef AMMUNITION_STRING_H
#define AMMUNITION_STRING_H
typedef unsigned int size_t;
/*
Forward declaration of functions
*/
void *ammunition_memcpy(void *, const void *, size_t);
void *ammunition_memset(void *, int, size_t);
int ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
void *ammunition_memmove(void *s1, const void *s2, size_t n);
int ammunition_strcmp(const char *str1, const char *str2);
#endif /* AMMUNITION_STRING_H */

View File

@ -0,0 +1,105 @@
/*
FILE NAME: arithm.h
TITLE: Include file of package for arbitrary precision integer
arithmetic
DESCRIPTION: This header file contains ANSI C prototype definitions of
the package functions and definitions of external
variable of the package and C++ classes for arbitrary
precision integer arithmetic.
*/
#ifndef __ARITHMETIC__
#define __ARITHMETIC__
#include "ammunition_limits.h"
/* This page contains definitions of variables and macros common for
all package functions. */
/* The value of macro is suggested to be maximum length of integer operands
The length of use integers should be not greater than this value. */
#define MAX_INTEGER_OPERAND_SIZE 128
/* The following macro value is sign of integer number (0 or 1) given
as macro parameter. */
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
extern int ammunition_overflow_bit;
void ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_add_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_subtract_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_subtract_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_multiply_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_multiply_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_divide_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_divide_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_remainder(int size, const void *op1,
const void *op2, void *result);
void ammunition_unsigned_integer_shift_right(int size, const void *operand,
int bits, void *result);
void ammunition_integer_shift_right(int size, const void *operand, int bits,
void *result);
void ammunition_integer_shift_left(int size, const void *operand, int bits,
void *result);
void ammunition_unsigned_integer_shift_left(int size, const void *operand,
int bits, void *result);
void ammunition_integer_or(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
void *result);
void ammunition_integer_and(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
void *result);
void ammunition_integer_not(int size, const void *operand, void *result);
void ammunition_unsigned_integer_not(int size, const void *operand,
void *result);
int ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_eq_integer(int size, const void *op1, const void *op2);
int ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_ne_integer(int size, const void *op1, const void *op2);
int ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_gt_integer(int size, const void *op1, const void *op2);
int ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_lt_integer(int size, const void *op1, const void *op2);
int ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_ge_integer(int size, const void *op1, const void *op2);
int ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_le_integer(int size, const void *op1, const void *op2);
void ammunition_change_unsigned_integer_size(int operand_size,
const void *operand,
int result_size, void *result);
void ammunition_change_integer_size(int operand_size, const void *operand,
int result_size, void *result);
char *ammunition_unsigned_integer_to_string(int size, const void *operand,
char *result);
char *ammunition_integer_to_string(int size, const void *operand, char *result);
char *ammunition_unsigned_integer_from_string(int size, const char *operand,
void *result);
char *ammunition_integer_from_string(int size, const char *operand,
void *result);
char ammunition_isdigit(unsigned char c);
int ammunition_isspace(int c);
#endif /* #ifndef __ARITHMETIC__ */

View File

@ -0,0 +1,305 @@
/*
FILE NAME: bits.c
TITLE: Package for work with bits
DESCRIPTION: This file implements functions of the package for work
with bit strings. A bit is given by address (start address) of
byte from which counting bits starts and its displacement which
is any non negative number of bit from the start address. The
most significant bit of the start address byte has number 0.
The bit string is given by its first bit and its length in
bits.
*/
#include "bits.h"
/* This function determines that given bit string contains only zero
bits. The function retruns TRUE if all bits of given bit string
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
non-negative and can be greater than CHAR_BIT. */
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length) {
const unsigned char *current_byte = (unsigned const char *) start_byte;
if (bit_length <= 0)
return 1 /* TRUE */;
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_length < CHAR_BIT - bit_displacement)
return (((*current_byte << bit_displacement) &
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
UCHAR_MAX) == 0;
else if (bit_displacement != 0) {
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
return 0 /* FALSE */;
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 7);
while (bit_length >= CHAR_BIT) {
if (*current_byte != 0)
return 0 /* FALSE */;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
return 0 /* FALSE */;
return 1 /* TRUE */;
}
/* This function sets up new value of all bits of given bit string.
This function is analog of standard C function `memset'. Value of
`bit_displacement' must be non-negative and can be greater than
CHAR_BIT. */
void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length) {
unsigned char *current_byte = (unsigned char *) start_byte;
unsigned char filling_byte;
int mask;
if (bit_length <= 0)
return;
bit = bit != 0; /* 1 or 0 */
filling_byte = (bit ? UCHAR_MAX : 0);
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_displacement != 0) {
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
if (bit_length < CHAR_BIT - bit_displacement)
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 8);
while (bit_length >= CHAR_BIT) {
*current_byte = filling_byte;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0)
*current_byte =
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. This
function is analog of standard C function `memcpy'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte =
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
(from_bit_displacement != 0 &&
bit_length > (CHAR_BIT - from_bit_displacement)
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
: 0));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte = (*current_to_byte &
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
(byte >> to_bit_displacement);
if (to_bit_displacement != 0)
current_to_byte[1] =
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
(byte << (CHAR_BIT - to_bit_displacement));
bit_length -= CHAR_BIT;
current_from_byte++;
current_to_byte++;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
*current_to_byte =
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
bit_length -= CHAR_BIT - to_bit_displacement;
if (bit_length > 0)
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
((byte << (CHAR_BIT - to_bit_displacement)) &
(UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. Copying
starts with the last bits of the bit strings. This function is
used by function `bit_string_move'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
to_bit_displacement += bit_length - 1;
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
to_bit_displacement %= CHAR_BIT; /* last bit */
from_bit_displacement += bit_length - 1;
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
from_bit_displacement %= CHAR_BIT; /* last bit */
__pragma_loopbound(0, 7);
while (1) {
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
((from_bit_displacement != CHAR_BIT - 1 &&
bit_length > from_bit_displacement + 1
? current_from_byte[-1] << (from_bit_displacement + 1)
: 0) &
UCHAR_MAX));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte =
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
(byte << (CHAR_BIT - 1 - to_bit_displacement));
if (to_bit_displacement != CHAR_BIT - 1)
current_to_byte[-1] =
(current_to_byte[-1] &
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
(byte >> (to_bit_displacement + 1));
bit_length -= CHAR_BIT;
current_from_byte--;
current_to_byte--;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
*current_to_byte = (*current_to_byte & mask) |
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
bit_length -= to_bit_displacement + 1;
if (bit_length > 0)
current_to_byte[-1] =
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
(byte >> (to_bit_displacement + 1) &
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string with the aid
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
function is analog of standard C function `memmove'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string can
be overlapped. */
void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
if (current_from_byte > current_to_byte ||
(current_from_byte == current_to_byte &&
from_bit_displacement > to_bit_displacement))
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte, from_bit_displacement,
bit_length);
else
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte,
from_bit_displacement, bit_length);
}
/* This function compares bit strings. This function is analog of
standard C function `memcmp'. The function returns 0 if the bit
strings are equal, 1 if the first bit string is greater than the
second, -1 if the first bit string is less than the first. Values
of `bit_displacement1' and `bit_displacement2' must be non-negative
and can be greater than CHAR_BIT. */
int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length) {
const unsigned char *current_byte1 = (unsigned const char *) str1;
const unsigned char *current_byte2 = (unsigned const char *) str2;
int byte1;
int byte2;
int mask;
if (bit_length <= 0)
return 0;
current_byte1 += bit_displacement1 / CHAR_BIT;
bit_displacement1 %= CHAR_BIT;
current_byte2 += bit_displacement2 / CHAR_BIT;
bit_displacement2 %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
(bit_displacement1 != 0
/* Shift is correct when to_bit_displacement == 0
because its value is less than word bit size. */
&& bit_length > CHAR_BIT - bit_displacement1
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
: 0));
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
(bit_displacement2 != 0 &&
bit_length > CHAR_BIT - bit_displacement2
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
: 0));
if (bit_length <= CHAR_BIT)
break;
if (byte1 > byte2)
return 1;
else if (byte1 < byte2)
return -1;
bit_length -= CHAR_BIT;
current_byte2++;
current_byte1++;
}
/* Shift is correct when to_bit_displacement == 0 because its value
is less than word bit size. */
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
if ((byte1 & mask) > (byte2 & mask))
return 1;
else if ((byte1 & mask) < (byte2 & mask))
return -1;
else
return 0;
}

View File

@ -0,0 +1,58 @@
/*
FILE NAME: bits.h
TITLE: Include file of package for work with bits
DESCRIPTION:
This is header file contains macros and the ANSI C prototype
definitions for the package for work with bits and bit strings
and C++ class for work with bits and bit strings. A bit is
given by address (start address) of byte from which counting
bits starts and its displacement which is any non negative
number of bit from the start address. The most significant bit
of the start address byte has number 0. The bit string is
given by its first bit and its length in bits.
*/
#ifndef __BITS__
#define __BITS__
#include "ammunition_limits.h"
/* This macro value returns bit vlaue (0 or 1) with given bit
displacement (0, 1, ...). The macro has side effects! Value of
`bit_displacement' must be nonegative and can be greater than
CHAR_BIT. */
#define BIT(start_byte, bit_displacement) \
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
1)
/* This macro value sets up new value (must be `0' or `1') of a given
bit (bit displacement starts with 0). The macro has side effects!
Value of `bit_displacement' must be nonegative and can be greater
than CHAR_BIT. */
#define SET_BIT(start_byte, bit_displacement, bit) \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
int ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length);
void ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length);
void ammunition_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length);
void ammunition_bit_string_move(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length);
int ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length);
#endif /* #ifndef __BITS__ */

View File

@ -0,0 +1,164 @@
/*
Include section
*/
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
#include "ammunition_string.h"
/*
Standard library functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline char
ammunition_isdigit(unsigned char c) {
if ((c >= '0') & (c <= '9'))
return 1;
else
return 0;
}
__attribute__((always_inline)) static inline int
ammunition_isspace(int c) {
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
}
__attribute__((always_inline)) static inline void *
ammunition_memcpy(void *dest, const void *src, size_t size) {
size_t i;
__pragma_loopbound(2, 6);
for (i = 0; i < size; i++)
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
return dest;
}
__attribute__((always_inline)) static inline void *
ammunition_memset(void *s, int c, size_t n) {
size_t i;
__pragma_loopbound(0, 4);
for (i = 0; i < n; i++)
((unsigned char *) s)[i] = (unsigned char) c;
return s;
}
__attribute__((always_inline)) static inline int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
const unsigned char *p1 = (const unsigned char *) mem1,
*p2 = (const unsigned char *) mem2;
__pragma_loopbound(0, 4);
while (size--)
if (*p1 != *p2)
return (*p1 - *p2);
else
p1++, p2++;
return 0;
}
/* The following function is an analog of standard C function
`memmove'. The function returns the first operand. */
__attribute__((always_inline)) static inline void *
ammunition_memmove(void *s1, const void *s2, size_t n) {
int i;
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
return (void *) ammunition_memcpy(s1, s2, n);
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
__pragma_loopbound(0, 4);
for (i = 0; (size_t) i < n; i++)
((char *) s1)[i] = ((char *) s2)[i];
} else {
__pragma_loopbound(0, 4);
for (i = n - 1; i >= 0; i--)
((char *) s1)[i] = ((char *) s2)[i];
}
return s1;
}
__attribute__((always_inline)) static inline int
ammunition_strcmp(const char *str1, const char *str2) {
__pragma_loopbound(1, 11);
while (*str1 && (*str1 == *str2))
str1++, str2++;
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
}
__attribute__((always_inline)) static inline int
ammunition_atoi(const char *str) {
int result = 0;
int sign = (str[0] == '-' ? -1 : 1);
int readingPos = 0;
if (str[0] == '-' || str[0] == '+')
readingPos++;
__pragma_loopbound(1, 7);
do {
result *= 10;
result += str[readingPos++] - 48;
} while (str[readingPos] != 0);
return sign * result;
}
__attribute__((always_inline)) static inline int
ammunition_sprintf_d(char *s, int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
if (number < 0) {
writePos++;
s[0] = '-';
}
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] =
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits + (number < 0 ? 1 : 0);
}
__attribute__((always_inline)) static inline int
ammunition_sprintf_u(char *s, unsigned int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
unsigned long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] = 48 + (copyOfNumber % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits;
}

View File

@ -0,0 +1,36 @@
#ifndef AMMUNITION_LIMITS_H
#define AMMUNITION_LIMITS_H
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
#ifndef SCHAR_MAX
#define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
#define SCHAR_MIN (-128)
#endif
#ifndef USHRT_MAX
#define USHRT_MAX 65535
#endif
#ifndef SHRT_MAX
#define SHRT_MAX 32767
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
#ifndef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#endif
#endif /* #ifndef AMMUNITION_LIMITS_H */

View File

@ -0,0 +1,11 @@
#ifndef AMMUNITION_STDIO_H
#define AMMUNITION_STDIO_H
__attribute__((always_inline)) static inline int
ammunition_sprintf_d(char *s, int number);
__attribute__((always_inline)) static inline int
ammunition_sprintf_u(char *s, unsigned int number);
#endif

View File

@ -0,0 +1,8 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
__attribute__((always_inline)) static inline int
ammunition_atoi(const char *str);
#endif

View File

@ -0,0 +1,22 @@
#ifndef AMMUNITION_STRING_H
#define AMMUNITION_STRING_H
typedef unsigned int size_t;
/*
Forward declaration of functions
*/
__attribute__((always_inline)) static inline void *
ammunition_memcpy(void *, const void *, size_t);
__attribute__((always_inline)) static inline void *
ammunition_memset(void *, int, size_t);
__attribute__((always_inline)) static inline int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
__attribute__((always_inline)) static inline void *
ammunition_memmove(void *s1, const void *s2, size_t n);
__attribute__((always_inline)) static inline int
ammunition_strcmp(const char *str1, const char *str2);
#endif /* AMMUNITION_STRING_H */

View File

@ -0,0 +1,139 @@
/*
FILE NAME: arithm.h
TITLE: Include file of package for arbitrary precision integer
arithmetic
DESCRIPTION: This header file contains ANSI C prototype definitions of
the package functions and definitions of external
variable of the package and C++ classes for arbitrary
precision integer arithmetic.
*/
#ifndef __ARITHMETIC__
#define __ARITHMETIC__
#include "ammunition_limits.h"
/* This page contains definitions of variables and macros common for
all package functions. */
/* The value of macro is suggested to be maximum length of integer operands
The length of use integers should be not greater than this value. */
#define MAX_INTEGER_OPERAND_SIZE 128
/* The following macro value is sign of integer number (0 or 1) given
as macro parameter. */
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
extern int ammunition_overflow_bit;
__attribute__((always_inline)) static inline void
ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_add_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_subtract_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_subtract_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_multiply_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_multiply_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_divide_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_divide_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_remainder(int size, const void *op1,
const void *op2, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_shift_right(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_shift_right(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_shift_left(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_shift_left(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_or(int size, const void *op1, const void *op2, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_and(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_not(int size, const void *operand, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_not(int size, const void *operand, void *result);
__attribute__((always_inline)) static inline int
ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_eq_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ne_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_gt_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_lt_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ge_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_le_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline void
ammunition_change_unsigned_integer_size(int operand_size, const void *operand,
int result_size, void *result);
__attribute__((always_inline)) static inline void
ammunition_change_integer_size(int operand_size, const void *operand,
int result_size, void *result);
__attribute__((always_inline)) static inline char *
ammunition_unsigned_integer_to_string(int size, const void *operand,
char *result);
__attribute__((always_inline)) static inline char *
ammunition_integer_to_string(int size, const void *operand, char *result);
__attribute__((always_inline)) static inline char *
ammunition_unsigned_integer_from_string(int size, const char *operand,
void *result);
__attribute__((always_inline)) static inline char *
ammunition_integer_from_string(int size, const char *operand, void *result);
__attribute__((always_inline)) static inline char
ammunition_isdigit(unsigned char c);
__attribute__((always_inline)) static inline int ammunition_isspace(int c);
#endif /* #ifndef __ARITHMETIC__ */

View File

@ -0,0 +1,305 @@
/*
FILE NAME: bits.c
TITLE: Package for work with bits
DESCRIPTION: This file implements functions of the package for work
with bit strings. A bit is given by address (start address) of
byte from which counting bits starts and its displacement which
is any non negative number of bit from the start address. The
most significant bit of the start address byte has number 0.
The bit string is given by its first bit and its length in
bits.
*/
#include "bits.h"
/* This function determines that given bit string contains only zero
bits. The function retruns TRUE if all bits of given bit string
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
non-negative and can be greater than CHAR_BIT. */
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length) {
const unsigned char *current_byte = (unsigned const char *) start_byte;
if (bit_length <= 0)
return 1 /* TRUE */;
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_length < CHAR_BIT - bit_displacement)
return (((*current_byte << bit_displacement) &
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
UCHAR_MAX) == 0;
else if (bit_displacement != 0) {
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
return 0 /* FALSE */;
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 7);
while (bit_length >= CHAR_BIT) {
if (*current_byte != 0)
return 0 /* FALSE */;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
return 0 /* FALSE */;
return 1 /* TRUE */;
}
/* This function sets up new value of all bits of given bit string.
This function is analog of standard C function `memset'. Value of
`bit_displacement' must be non-negative and can be greater than
CHAR_BIT. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length) {
unsigned char *current_byte = (unsigned char *) start_byte;
unsigned char filling_byte;
int mask;
if (bit_length <= 0)
return;
bit = bit != 0; /* 1 or 0 */
filling_byte = (bit ? UCHAR_MAX : 0);
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_displacement != 0) {
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
if (bit_length < CHAR_BIT - bit_displacement)
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 8);
while (bit_length >= CHAR_BIT) {
*current_byte = filling_byte;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0)
*current_byte =
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. This
function is analog of standard C function `memcpy'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte =
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
(from_bit_displacement != 0 &&
bit_length > (CHAR_BIT - from_bit_displacement)
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
: 0));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte = (*current_to_byte &
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
(byte >> to_bit_displacement);
if (to_bit_displacement != 0)
current_to_byte[1] =
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
(byte << (CHAR_BIT - to_bit_displacement));
bit_length -= CHAR_BIT;
current_from_byte++;
current_to_byte++;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
*current_to_byte =
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
bit_length -= CHAR_BIT - to_bit_displacement;
if (bit_length > 0)
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
((byte << (CHAR_BIT - to_bit_displacement)) &
(UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. Copying
starts with the last bits of the bit strings. This function is
used by function `bit_string_move'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
__attribute__((always_inline)) static inline void
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
to_bit_displacement += bit_length - 1;
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
to_bit_displacement %= CHAR_BIT; /* last bit */
from_bit_displacement += bit_length - 1;
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
from_bit_displacement %= CHAR_BIT; /* last bit */
__pragma_loopbound(0, 7);
while (1) {
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
((from_bit_displacement != CHAR_BIT - 1 &&
bit_length > from_bit_displacement + 1
? current_from_byte[-1] << (from_bit_displacement + 1)
: 0) &
UCHAR_MAX));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte =
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
(byte << (CHAR_BIT - 1 - to_bit_displacement));
if (to_bit_displacement != CHAR_BIT - 1)
current_to_byte[-1] =
(current_to_byte[-1] &
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
(byte >> (to_bit_displacement + 1));
bit_length -= CHAR_BIT;
current_from_byte--;
current_to_byte--;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
*current_to_byte = (*current_to_byte & mask) |
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
bit_length -= to_bit_displacement + 1;
if (bit_length > 0)
current_to_byte[-1] =
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
(byte >> (to_bit_displacement + 1) &
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string with the aid
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
function is analog of standard C function `memmove'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string can
be overlapped. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
if (current_from_byte > current_to_byte ||
(current_from_byte == current_to_byte &&
from_bit_displacement > to_bit_displacement))
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte, from_bit_displacement,
bit_length);
else
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte,
from_bit_displacement, bit_length);
}
/* This function compares bit strings. This function is analog of
standard C function `memcmp'. The function returns 0 if the bit
strings are equal, 1 if the first bit string is greater than the
second, -1 if the first bit string is less than the first. Values
of `bit_displacement1' and `bit_displacement2' must be non-negative
and can be greater than CHAR_BIT. */
__attribute__((always_inline)) static inline int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length) {
const unsigned char *current_byte1 = (unsigned const char *) str1;
const unsigned char *current_byte2 = (unsigned const char *) str2;
int byte1;
int byte2;
int mask;
if (bit_length <= 0)
return 0;
current_byte1 += bit_displacement1 / CHAR_BIT;
bit_displacement1 %= CHAR_BIT;
current_byte2 += bit_displacement2 / CHAR_BIT;
bit_displacement2 %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
(bit_displacement1 != 0
/* Shift is correct when to_bit_displacement == 0
because its value is less than word bit size. */
&& bit_length > CHAR_BIT - bit_displacement1
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
: 0));
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
(bit_displacement2 != 0 &&
bit_length > CHAR_BIT - bit_displacement2
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
: 0));
if (bit_length <= CHAR_BIT)
break;
if (byte1 > byte2)
return 1;
else if (byte1 < byte2)
return -1;
bit_length -= CHAR_BIT;
current_byte2++;
current_byte1++;
}
/* Shift is correct when to_bit_displacement == 0 because its value
is less than word bit size. */
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
if ((byte1 & mask) > (byte2 & mask))
return 1;
else if ((byte1 & mask) < (byte2 & mask))
return -1;
else
return 0;
}

View File

@ -0,0 +1,61 @@
/*
FILE NAME: bits.h
TITLE: Include file of package for work with bits
DESCRIPTION:
This is header file contains macros and the ANSI C prototype
definitions for the package for work with bits and bit strings
and C++ class for work with bits and bit strings. A bit is
given by address (start address) of byte from which counting
bits starts and its displacement which is any non negative
number of bit from the start address. The most significant bit
of the start address byte has number 0. The bit string is
given by its first bit and its length in bits.
*/
#ifndef __BITS__
#define __BITS__
#include "ammunition_limits.h"
/* This macro value returns bit vlaue (0 or 1) with given bit
displacement (0, 1, ...). The macro has side effects! Value of
`bit_displacement' must be nonegative and can be greater than
CHAR_BIT. */
#define BIT(start_byte, bit_displacement) \
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
1)
/* This macro value sets up new value (must be `0' or `1') of a given
bit (bit displacement starts with 0). The macro has side effects!
Value of `bit_displacement' must be nonegative and can be greater
than CHAR_BIT. */
#define SET_BIT(start_byte, bit_displacement, bit) \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
__attribute__((always_inline)) static inline int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length);
__attribute__((always_inline)) static inline int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length);
#endif /* #ifndef __BITS__ */