diff options
| author | kx <kx@radix-linux.su> | 2026-10-01 12:02:28 +0300 |
|---|---|---|
| committer | kx <kx@radix-linux.su> | 2026-10-01 12:02:28 +0300 |
| commit | ba1b04d64bdfaf377915b22f77520216ebe47674 (patch) | |
| tree | 044343035c28b2b04ca9725f26e9b7c39342d19c /src/mcpp-semantic.c | |
| parent | 124b140798456778e2a96851cc7268aa9a726698 (diff) | |
| download | mcpu-cpp-1.0.2.tar.xz | |
Version 1.0.21.0.2
Diffstat (limited to 'src/mcpp-semantic.c')
| -rw-r--r-- | src/mcpp-semantic.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/mcpp-semantic.c b/src/mcpp-semantic.c new file mode 100644 index 0000000..3063139 --- /dev/null +++ b/src/mcpp-semantic.c @@ -0,0 +1,349 @@ +#include <defs.h> + +#define MCPP_INTEGER_BITS 64U + +static __mpu_int64_t +mcpp_semantic_signed( mcpp_integer value ) +{ + if( value.value <= (__mpu_uint64_t)INT64_MAX ) + return( (__mpu_int64_t)value.value ); + + return( -1 - (__mpu_int64_t)(UINT64_MAX - value.value) ); +} + +static __mpu_uint64_t +mcpp_semantic_unsigned_from_signed( __mpu_int64_t value ) +{ + if( value >= 0 ) + return( (__mpu_uint64_t)value ); + + return( UINT64_MAX - (__mpu_uint64_t)(-(value + 1)) ); +} + +static unsigned +mcpp_semantic_shift_count( mcpp_integer value, int *negative ) +{ + __mpu_uint64_t magnitude; + + *negative = 0; + if( !value.unsignedp && mcpp_semantic_signed(value) < 0 ) + { + *negative = 1; + magnitude = (__mpu_uint64_t)0 - value.value; + } + else + magnitude = value.value; + + if( magnitude >= MCPP_INTEGER_BITS ) + return( MCPP_INTEGER_BITS ); + + return( (unsigned)magnitude ); +} + +static mcpp_integer +mcpp_semantic_shift_left_count( mcpp_integer value, unsigned shift ) +{ + mcpp_integer result; + + result.unsignedp = value.unsignedp; + if( shift >= MCPP_INTEGER_BITS ) + result.value = 0; + else + result.value = value.value << shift; + + return( result ); +} + +static mcpp_integer +mcpp_semantic_shift_right_count( mcpp_integer value, unsigned shift ) +{ + mcpp_integer result; + int negative; + + result.unsignedp = value.unsignedp; + negative = !value.unsignedp && mcpp_semantic_signed(value) < 0; + + if( shift >= MCPP_INTEGER_BITS ) + { + result.value = negative ? UINT64_MAX : 0; + return( result ); + } + + if( shift == 0 || value.unsignedp || !negative ) + { + result.value = value.value >> shift; + return( result ); + } + + result.value = (value.value >> shift) | + (UINT64_MAX << (MCPP_INTEGER_BITS - shift)); + return( result ); +} + +void +mcpp_semantic_context_init( mcpp_semantic_context *context, + const char *filename, + unsigned line_number, + const mcpp_options *options ) +{ + context->filename = filename; + context->line_number = line_number; + context->options = options; + context->failed = 0; +} + +void +mcpp_semantic_error( mcpp_semantic_context *context, const char *message ) +{ + if( context->failed ) + return; + + fprintf( stderr, "%s:%u: error: %s\n", + context->filename, context->line_number, message ); + context->failed = 1; +} + +void +mcpp_semantic_warning( mcpp_semantic_context *context, + const char *message ) +{ + if( mcpp_diagnostic_warning(context->options, + context->filename, context->line_number, + "%s", message) != 0 ) + context->failed = 1; +} + +int +mcpp_semantic_failed( const mcpp_semantic_context *context ) +{ + return( context->failed ); +} + +mcpp_integer +mcpp_semantic_make( __mpu_uint64_t value, int unsignedp ) +{ + mcpp_integer result; + + result.value = value; + result.unsignedp = unsignedp ? 1 : 0; + return( result ); +} + +int +mcpp_semantic_true( mcpp_integer value ) +{ + return( value.value != 0 ); +} + +mcpp_integer +mcpp_semantic_neg( mcpp_integer value ) +{ + value.value = (__mpu_uint64_t)0 - value.value; + return( value ); +} + +mcpp_integer +mcpp_semantic_not( mcpp_integer value ) +{ + return( mcpp_semantic_make(!mcpp_semantic_true(value), 0) ); +} + +mcpp_integer +mcpp_semantic_compl( mcpp_integer value ) +{ + value.value = ~value.value; + return( value ); +} + +mcpp_integer +mcpp_semantic_mul( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value * right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_div( mcpp_semantic_context *context, + mcpp_integer left, mcpp_integer right, int evaluate ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + + if( right.value == 0 ) + { + if( evaluate ) + mcpp_semantic_error( context, "division by zero in #if expression" ); + return( mcpp_semantic_make(0, unsignedp) ); + } + + if( unsignedp ) + return( mcpp_semantic_make(left.value / right.value, 1) ); + + if( mcpp_semantic_signed(left) == INT64_MIN && + mcpp_semantic_signed(right) == -1 ) + return( mcpp_semantic_make((__mpu_uint64_t)1 << 63, 0) ); + + return( mcpp_semantic_make( + mcpp_semantic_unsigned_from_signed( + mcpp_semantic_signed(left) / mcpp_semantic_signed(right)), 0) ); +} + +mcpp_integer +mcpp_semantic_mod( mcpp_semantic_context *context, + mcpp_integer left, mcpp_integer right, int evaluate ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + + if( right.value == 0 ) + { + if( evaluate ) + mcpp_semantic_error( context, "division by zero in #if expression" ); + return( mcpp_semantic_make(0, unsignedp) ); + } + + if( unsignedp ) + return( mcpp_semantic_make(left.value % right.value, 1) ); + + if( mcpp_semantic_signed(left) == INT64_MIN && + mcpp_semantic_signed(right) == -1 ) + return( mcpp_semantic_make(0, 0) ); + + return( mcpp_semantic_make( + mcpp_semantic_unsigned_from_signed( + mcpp_semantic_signed(left) % mcpp_semantic_signed(right)), 0) ); +} + +mcpp_integer +mcpp_semantic_add( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value + right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_sub( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value - right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_lshift( mcpp_integer left, mcpp_integer right ) +{ + unsigned shift; + int negative; + + shift = mcpp_semantic_shift_count( right, &negative ); + if( negative ) + return( mcpp_semantic_shift_right_count(left, shift) ); + + return( mcpp_semantic_shift_left_count(left, shift) ); +} + +mcpp_integer +mcpp_semantic_rshift( mcpp_integer left, mcpp_integer right ) +{ + unsigned shift; + int negative; + + shift = mcpp_semantic_shift_count( right, &negative ); + if( negative ) + return( mcpp_semantic_shift_left_count(left, shift) ); + + return( mcpp_semantic_shift_right_count(left, shift) ); +} + +mcpp_integer +mcpp_semantic_equal( mcpp_integer left, mcpp_integer right ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + int value = unsignedp ? left.value == right.value : + mcpp_semantic_signed(left) == mcpp_semantic_signed(right); + return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); +} + +mcpp_integer +mcpp_semantic_notequal( mcpp_integer left, mcpp_integer right ) +{ + mcpp_integer result = mcpp_semantic_equal( left, right ); + result.value = !result.value; + return( result ); +} + +mcpp_integer +mcpp_semantic_less( mcpp_integer left, mcpp_integer right ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + int value = unsignedp ? left.value < right.value : + mcpp_semantic_signed(left) < mcpp_semantic_signed(right); + return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); +} + +mcpp_integer +mcpp_semantic_greater( mcpp_integer left, mcpp_integer right ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + int value = unsignedp ? left.value > right.value : + mcpp_semantic_signed(left) > mcpp_semantic_signed(right); + return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); +} + +mcpp_integer +mcpp_semantic_leq( mcpp_integer left, mcpp_integer right ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + int value = unsignedp ? left.value <= right.value : + mcpp_semantic_signed(left) <= mcpp_semantic_signed(right); + return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); +} + +mcpp_integer +mcpp_semantic_geq( mcpp_integer left, mcpp_integer right ) +{ + int unsignedp = left.unsignedp || right.unsignedp; + int value = unsignedp ? left.value >= right.value : + mcpp_semantic_signed(left) >= mcpp_semantic_signed(right); + return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); +} + +mcpp_integer +mcpp_semantic_bitand( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value & right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_bitxor( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value ^ right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_bitor( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(left.value | right.value, + left.unsignedp || right.unsignedp) ); +} + +mcpp_integer +mcpp_semantic_and( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(mcpp_semantic_true(left) && mcpp_semantic_true(right), 0) ); +} + +mcpp_integer +mcpp_semantic_or( mcpp_integer left, mcpp_integer right ) +{ + return( mcpp_semantic_make(mcpp_semantic_true(left) || mcpp_semantic_true(right), 0) ); +} + +mcpp_integer +mcpp_semantic_conditional( mcpp_integer condition, + mcpp_integer yes, mcpp_integer no ) +{ + mcpp_integer result = mcpp_semantic_true(condition) ? yes : no; + + result.unsignedp = yes.unsignedp || no.unsignedp; + return( result ); +} |
