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

View File

@ -0,0 +1,28 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(ammunition)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/ammunition.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/ammunition.c"
"generated/modified_sources/default/ammunition_libc.c"
"generated/modified_sources/default/arithm.c"
"generated/modified_sources/default/bits.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,66 @@
File: ammunition.c
Original provenience: DINO programming language
2016-03-03:
- Add generic TACLeBench header
- Prefix global functions with benchmark name
- Introduce volatile result variable for return statements
- Split code into ammunition_init and ammunition_main
- Fix compiler warnings "array subscript is of type 'char'":
char => unsigned char
- Fix compiler warnings "'&&' within '||'":
Place additional parentheses
- Remove usages and comments related to the macros
HAVE_MEMMOVE, NDEBUG, HAVE_MEMCMP
- Remove comment related to unused NO_TEMPLATE macro
2016-05-02:
- Change C++ style comments to ISO C90 compliant comments
- Avoid mixing declarations and code: move declaration of variable writePos in
functions ammunition_sprintf_d and ammunition_sprintf_u
- Change datatype in function ammunition_bits_test of iteration variables i and
j from int to unsigned int to avoid comparison between signed and unsigned
integer expressions
- Add forward declarations to ammunition.c
- Introduce variable ammunition_result
- Parantheses around comparison in functions ammunition_isdigit and
ammunition_isspace
- Remove usage of limits.h, move definitions of limits into separate file
ammunition_limits.h
- Remove unconditional assignments of variable result to zero after each test in
functions ammunition_bits_test and ammunition_arithm_test
- Remove unused functions unsigned_integer_maximum, integer_minimum,
integer_maximum, integer_remainder
- Remove unused declaration of function default_arithmetic_overflow_reaction
- Remove unused variables zero_constant_itself, zero_constant
- Remove unused declarations of functions set_unsigned_integer_overflow_reaction
and set_integer_overflow_reaction
- Remove block #ifndef MAX_INTEGER_OPERAND_SIZE, set definition of
MAX_INTEGER_OPERAND_SIZE to 128, since this is default
2016-05-10:
- Integrate new version of arithm library from ammunition repository from
dino repository on github (commit: db9cfab042c332abb234ec8d72750103010981c1),
which hanles arithmetic shifts by negative numbers. This change now makes all
test cases in ammunition.c pass. Update headers unsigned int bits => int bits
- Remove assert statements
- Fix memcmp implementation: dereferencing pointer was missing
- Add loop-bound annotation to memcmp
- Fix strcmp implementation
- Integrate working versions of memcpy and memset from pm benchmark
- Update signature of ammunition_memcpy to original version:
void *memcpy(void *dest, const void *src, size_t n);
- Move functions from libc into separate file, introduce header files
ammunition_limits.h, ammunition_stdio.h, ammunition_stdlib.h,
ammunition_string.h
- Fix overflow in sprintf_d: change datatype of variable 'copyOfNumber' from int
to long, since the negative value of INT_MIN is undefined
2016-05-17:
- Remove all static declarations of global functions
- Rename variables 'digit_number' to digit_num to keep lines below 80 characters
- Rename op1_digit_number to op1_digit_number and op1_digit_num in function
'ammunition_multiply_unsigned_integer_without_overflow_reaction'
- Rename variable 'scaled_op1_digit_number' in function
'ammunition_divide_unsigned_integer_without_overflow_reaction'
- Apply code formatting with astyle
2017-08-18:
- Add explicit casts to silence g++ warnings.

View File

@ -0,0 +1,86 @@
This directory AMMUNITION contains reusable packages on C/C++:
`allocate', `vlobject', `objstack', `hashtab', `commline', `ticker',
`position', `errors', `bits', `arithm', `IEEE':
o allocate
Allocating and freeing memory with automatic fixing some
allocation errors.
o vlobject
Work with variable length objects (VLO). Any number of bytes
may be added to and removed from the end of VLO. If it is
needed the memory allocated for storing variable length object
may be expanded possibly with changing the object place. But
between any additions of the bytes (or tailoring) the object
place is not changed. To decrease number of changes of the
object place the memory being allocated for the object is
longer than the current object length.
o objstack
Work with stacks of objects (OS). Work with the object on the
stack top is analogous to one with a variable length object.
One motivation for the package is the problem of growing char
strings in symbol tables. Memory for OS is allocated by
segments. A segment may contain more one objects. The most
recently allocated segment contains object on the top of OS.
If there is not sufficient free memory for the top object than
new segment is created and the top object is transferred into
the new segment, i.e. there is not any memory reallocation.
Therefore the top object may change its address. But other
objects never change address.
o hashtab
Work with hash tables. The package permits to work
simultaneously with several expandable hash tables. Besides
insertion and search of elements the elements from the hash
tables can be also removed. The table element can be only a
pointer. The size of hash tables is not fixed. The hash
table will be automatically expanded when its occupancy will
became big.
o position
Work with source code positions. The package serves to
support information about source positions of compiled files
taking all included files into account.
o errors
Output of compiler messages. The package serves output
one-pass or multi-pass compiler messages of various modes
(errors, warnings, fatal, system errors and appended messages)
in Unix style or for traditional listing. The package also
permits adequate error reporting for included files.
o commline
Work with command line. The package implements features
analogous to ones of public domain function `getopt'. The
goal of the package creation is to use more readable language
of command line description and to use command line
description as help output of program.
o ticker
Simultaneous work with several tickers (timers).
o bits
Work with bit strings (copying, moving, setting, testing,
comparison).
o arithm
Implementing host machine-independently arbitrary precision
integer numbers arithmetic. The implementation of the package
functions are not sufficiently efficient in order to use for
run-time. The package functions are oriented to implement
constant-folding in compilers, cross-compilers.
o IEEE
Implementing host machine-independently IEEE floating point
arithmetic. The implementation of the package functions are
not sufficiently efficient in order to use for run-time. The
package functions are oriented to implement constant-folding
in compilers, cross-compilers.
There are files with corresponding names and extensions `.h'
(interface file for C/C++), `.c' (implementation file on C), and
`.cpp' (implementation file on C++).
To install AMMUNITION see file INSTALL in the current directory.
There are also shell scripts for testing the package with
corresponding names and extension `.tst'. Documentation of the
reusable packages is in files `ammunition.txt', `ammunition.dvi',
`ammunition.ps', `ammunition.info*', `ammunition*.html',
`ammunition*.rtf' for C and `ammunition++.txt', `ammunition++.dvi',
`ammunition++.ps', `ammunition++.info*', `ammunition++*.html',
`ammunition++*.rtf'.
Please send bug reports and comments to vmakarov@fnmail.com
Vladimir Makarov

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
/*
Include section
*/
#include "ammunition_string.h"
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
/*
Standard library functions
*/
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 min 2 max 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 min 0 max 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 min 0 max 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 min 0 max 4" )
for ( i = 0; ( size_t ) i < n; i++ )
( ( char * ) s1 ) [ i ] = ( ( char * ) s2 ) [ i ];
} else {
_Pragma( "loopbound min 0 max 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 min 1 max 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 min 1 max 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 min 1 max 10" )
do {
digits++;
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
writePos = digits;
if ( number < 0 ) {
writePos++;
s[ 0 ] = '-';
}
s[ writePos ] = 0;
copyOfNumber = number;
_Pragma( "loopbound min 1 max 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 min 1 max 10" )
do {
digits++;
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
writePos = digits;
s[ writePos ] = 0;
copyOfNumber = number;
_Pragma( "loopbound min 1 max 10" )
do {
s[ --writePos ] = 48 + ( copyOfNumber % 10 );
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
return digits;
}

View File

@ -0,0 +1,35 @@
#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,8 @@
#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,6 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
int ammunition_atoi ( const char *str );
#endif

View File

@ -0,0 +1,18 @@
#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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/*
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;
extern void ammunition_add_unsigned_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_add_integer ( int size, const void *op1, const void *op2,
void *result );
extern void ammunition_subtract_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_subtract_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_multiply_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_multiply_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_divide_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_divide_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_unsigned_integer_remainder ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_shift_right ( int size,
const void *operand,
int bits, void *result );
extern void ammunition_integer_shift_right ( int size, const void *operand,
int bits, void *result );
extern void ammunition_integer_shift_left ( int size, const void *operand,
int bits, void *result );
extern void ammunition_unsigned_integer_shift_left ( int size,
const void *operand,
int bits, void *result );
extern void ammunition_integer_or ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_or ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_integer_and ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_and ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_integer_not ( int size, const void *operand,
void *result );
extern void ammunition_unsigned_integer_not ( int size, const void *operand,
void *result );
extern int ammunition_eq_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_eq_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_ne_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_ne_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_gt_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_gt_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_lt_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_lt_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_ge_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_ge_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_le_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_le_integer ( int size, const void *op1, const void *op2 );
extern void ammunition_change_unsigned_integer_size
( int operand_size, const void *operand, int result_size, void *result );
extern void ammunition_change_integer_size ( int operand_size,
const void *operand,
int result_size, void *result );
extern char *ammunition_unsigned_integer_to_string ( int size,
const void *operand,
char *result );
extern char *ammunition_integer_to_string ( int size, const void *operand,
char *result );
extern char *ammunition_unsigned_integer_from_string ( int size,
const char *operand,
void *result );
extern 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,313 @@
/*
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. */
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 min 0 max 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 min 0 max 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 min 0 max 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 min 0 max 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 min 0 max 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,60 @@
/*
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__ */

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__ */