summaryrefslogtreecommitdiff
path: root/src/mcpp-semantic.c
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-10-01 12:02:28 +0300
committerkx <kx@radix-linux.su>2026-10-01 12:02:28 +0300
commitba1b04d64bdfaf377915b22f77520216ebe47674 (patch)
tree044343035c28b2b04ca9725f26e9b7c39342d19c /src/mcpp-semantic.c
parent124b140798456778e2a96851cc7268aa9a726698 (diff)
downloadmcpu-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.c349
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 );
+}