From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- core/bgdrtm/src/interpreter.c | 2192 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2192 insertions(+) create mode 100644 core/bgdrtm/src/interpreter.c (limited to 'core/bgdrtm/src/interpreter.c') diff --git a/core/bgdrtm/src/interpreter.c b/core/bgdrtm/src/interpreter.c new file mode 100644 index 0000000..4904987 --- /dev/null +++ b/core/bgdrtm/src/interpreter.c @@ -0,0 +1,2192 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include +#include +#include + +#include "bgdrtm.h" +#include "dcb.h" + +#include "sysprocs_p.h" +#include "pslang.h" +#include "instance.h" +#include "offsets.h" +#include "xstrings.h" + +#include + +/* ---------------------------------------------------------------------- */ +/* Interpreter's main module */ +/* ---------------------------------------------------------------------- */ + +int debug_mode = 0 ; + +int exit_value = 0 ; +int must_exit = 0 ; + +int force_debug = 0 ; +int debug_next = 0 ; + +int trace_sentence = -1; +INSTANCE * trace_instance = NULL; + +/* ---------------------------------------------------------------------- */ + +static INSTANCE * last_instance_run = NULL; + +/* ---------------------------------------------------------------------- */ + +static int stack_dump( INSTANCE * r ) +{ + register int * ptr = &r->stack[1] ; + register int i = 0; + + while ( ptr < r->stack_ptr ) + { + if ( i == 5 ) + { + i = 0; + printf( "\n" ); + } + printf( "%08X ", *ptr++ ) ; + i++; + } + + return i; +} + +/* ---------------------------------------------------------------------- */ + +int instance_go_all() +{ + INSTANCE * i = NULL; + int i_count = 0 ; + int n; + int status; + + must_exit = 0 ; + + while ( first_instance ) + { + if ( debug_mode ) + { + /* Hook */ + if ( handler_hook_count ) + for ( n = 0; n < handler_hook_count; n++ ) + handler_hook_list[n].hook(); + /* Hook */ + if ( must_exit ) break ; + + } + else + { + if ( last_instance_run ) + { + if ( instance_exists( last_instance_run ) ) + { + i = last_instance_run; + } + else + { + last_instance_run = NULL; + i = instance_next_by_priority(); + } + } + else + { + i = instance_next_by_priority(); + i_count = 0 ; + } + + while ( i ) + { + status = LOCDWORD( i, STATUS ); + /* If instance is KILLED or DEAD or return from some debug command, then execute it again. + No exec_hook is executed. + */ + if ( status == STATUS_KILLED || status == STATUS_DEAD || last_instance_run ) + { + /* Run instance */ + } + else if ( status == STATUS_RUNNING && LOCINT32( i, FRAME_PERCENT ) < 100 ) + { + /* Run instance */ + /* Hook */ + if ( process_exec_hook_count ) + for ( n = 0; n < process_exec_hook_count; n++ ) + process_exec_hook_list[n]( i ); + /* Hook */ + } + else + { + i = instance_next_by_priority(); + last_instance_run = NULL; + continue; + } + + i_count++; + + last_instance_run = NULL; + + instance_go( i ); + + if ( force_debug ) + { + debug_mode = 1; + last_instance_run = trace_instance; + break; + } + + if ( must_exit ) break; + + i = instance_next_by_priority(); + } + + if ( must_exit ) break ; + + /* If frame is complete, then update internal vars and execute main hooks. */ + + if ( !i_count && !force_debug ) + { + /* Honors the signal-changed status of the process and + * saves so it is used in this loop the next frame + */ + + i = first_instance ; + while ( i ) + { + status = LOCDWORD( i, STATUS ); + if ( status == STATUS_RUNNING ) LOCINT32( i, FRAME_PERCENT ) -= 100 ; + LOCDWORD( i, SAVED_STATUS ) = status ; + + if ( LOCINT32( i, SAVED_PRIORITY ) != LOCINT32( i, PRIORITY ) ) + { + LOCINT32( i, SAVED_PRIORITY ) = LOCINT32( i, PRIORITY ); + instance_dirty( i ); + } + + i = i->next ; + } + + if ( !first_instance ) break ; + + /* Hook */ + if ( handler_hook_count ) + for ( n = 0; n < handler_hook_count; n++ ) + handler_hook_list[n].hook(); + /* Hook */ + + continue ; + } + } + } + + return exit_value; + +} + +/* ---------------------------------------------------------------------- */ + +int instance_go( INSTANCE * r ) +{ + if ( !r ) return 0 ; + + register int * ptr = r->codeptr ; + + int n, return_value = LOCDWORD( r, PROCESS_ID ) ; + SYSPROC * p = NULL ; + INSTANCE * i = NULL ; + static char buffer[16]; + char * str = NULL ; + int status ; + + /* Pointer to the current process's code (it may be a called one) */ + + int child_is_alive = 0; + + /* ------------------------------------------------------------------------------- */ + /* Restore if exit by debug */ + + if ( debug > 0 ) + { + printf( "\n>>> Instance:%s ProcID:%d StackUsed:%d/%d\n", r->proc->name, + LOCDWORD( r, PROCESS_ID ), + ( r->stack_ptr - r->stack ) / sizeof( r->stack[0] ), + ( r->stack[0] & ~STACK_RETURN_VALUE ) + ) ; + } + + /* Hook */ + if ( instance_pre_execute_hook_count ) + for ( n = 0; n < instance_pre_execute_hook_count; n++ ) + instance_pre_execute_hook_list[n]( r ); + /* Hook */ + + if (( r->proc->breakpoint || r->breakpoint ) && trace_instance != r ) debug_next = 1; + + trace_sentence = -1; + + while ( !must_exit ) + { + /* If I was killed or I'm waiting status, then exit */ + status = LOCDWORD( r, STATUS ); + if (( status & ~STATUS_WAITING_MASK ) == STATUS_KILLED || ( status & STATUS_WAITING_MASK ) ) + { + r->codeptr = ptr; + return_value = LOCDWORD( r, PROCESS_ID ); + goto break_all ; + } + + if ( debug_next && trace_sentence != -1 ) + { + force_debug = 1; + debug_next = 0; + r->codeptr = ptr ; + return_value = LOCDWORD( r, PROCESS_ID ); + break; + } + + /* debug output */ + if ( debug > 0 ) + { + if ( debug > 2 ) + { + int c = 45 - stack_dump( r ) * 9; + if ( debug > 1 ) printf( "%*.*s[%4u] ", c, c, "", ( ptr - r->code ) ) ; + } + else if ( debug > 1 ) printf( "[%4u] ", ( ptr - r->code ) ) ; + mnemonic_dump( *ptr, ptr[1] ) ; + fflush(stdout); + } + + switch ( *ptr ) + { + /* Stack manipulation */ + + case MN_DUP: + *r->stack_ptr = r->stack_ptr[-1] ; + r->stack_ptr++; + ptr++ ; + break ; + + case MN_PUSH: + *r->stack_ptr++ = ptr[1] ; + ptr += 2 ; + break ; + + case MN_POP: + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_INDEX: + case MN_INDEX | MN_UNSIGNED: + case MN_INDEX | MN_STRING: + case MN_INDEX | MN_WORD: + case MN_INDEX | MN_WORD | MN_UNSIGNED: + case MN_INDEX | MN_BYTE: + case MN_INDEX | MN_BYTE | MN_UNSIGNED: + case MN_INDEX | MN_FLOAT: /* Add float, I don't know why it was missing (SplinterGU) */ + r->stack_ptr[-1] += ptr[1] ; + ptr += 2 ; + break ; + + case MN_ARRAY: + r->stack_ptr[-2] += ( ptr[1] * r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr += 2 ; + break ; + + /* Process calls */ + + case MN_CLONE: + i = instance_duplicate( r ) ; + i->codeptr = ptr + 2 ; + ptr = r->code + ptr[1] ; + continue ; + + case MN_CALL: + case MN_PROC: + { + PROCDEF * proc = procdef_get( ptr[1] ) ; + + if ( !proc ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Unknown process\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + + /* Process uses FRAME or locals, must create an instance */ + i = instance_new( proc, r ) ; + + assert ( i ) ; + + for ( n = 0; n < proc->params; n++ ) + PRIDWORD( i, 4 * n ) = r->stack_ptr[-proc->params+n] ; + + r->stack_ptr -= proc->params ; + + /* I go to waiting status (by default) */ + LOCDWORD( r, STATUS ) |= STATUS_WAITING_MASK; + i->called_by = r; + + /* Run the process/function */ + if ( *ptr == MN_CALL ) + { + r->stack[0] |= STACK_RETURN_VALUE; + r->stack_ptr++; + *r->stack_ptr = instance_go( i ); + } + else + { + r->stack[0] &= ~STACK_RETURN_VALUE; + instance_go( i ); + } + + child_is_alive = instance_exists( i ); + + ptr += 2 ; + + /* If the process is a function in a frame, save the stack and leave */ + /* If the process/function still running, then it is in a FRAME. + If the process/function is running code, then it his status is RUNNING */ + if ( child_is_alive && + ( + (( status = LOCDWORD( r, STATUS ) ) & STATUS_WAITING_MASK ) || + ( status & ~STATUS_WAITING_MASK ) == STATUS_FROZEN || + ( status & ~STATUS_WAITING_MASK ) == STATUS_SLEEPING + ) + ) + { + /* I go to sleep and return from this process/function */ + i->called_by = r; + + /* Save the instruction pointer */ + /* This instance don't run other code until the child return */ + r->codeptr = ptr ; + + /* If it don't was a CALL, then I set a flag in "len" for no return value */ + if ( ptr[-2] == MN_CALL ) + r->stack[0] |= STACK_RETURN_VALUE; + else + r->stack[0] &= ~STACK_RETURN_VALUE; + + if ( debug_next && trace_sentence != -1 ) + { + force_debug = 1; + debug_next = 0; + } + return 0; + } + + /* Wake up! */ + LOCDWORD( r, STATUS ) &= ~STATUS_WAITING_MASK; + if ( child_is_alive ) i->called_by = NULL; + + break ; + } + + case MN_SYSCALL: + p = sysproc_get( ptr[1] ) ; + if ( !p ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Unknown system function\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + + r->stack_ptr -= p->params ; + *r->stack_ptr = ( *p->func )( r, r->stack_ptr ) ; + r->stack_ptr++ ; + ptr += 2 ; + break ; + + case MN_SYSPROC: + p = sysproc_get( ptr[1] ) ; + if ( !p ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Unknown system process\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + r->stack_ptr -= p->params ; + ( *p->func )( r, r->stack_ptr ) ; + ptr += 2 ; + break ; + + /* Access to variables address */ + + case MN_PRIVATE: + case MN_PRIVATE | MN_UNSIGNED: + case MN_PRIVATE | MN_WORD: + case MN_PRIVATE | MN_BYTE: + case MN_PRIVATE | MN_WORD | MN_UNSIGNED: + case MN_PRIVATE | MN_BYTE | MN_UNSIGNED: + case MN_PRIVATE | MN_STRING: + case MN_PRIVATE | MN_FLOAT: + *r->stack_ptr++ = ( uint32_t ) & PRIDWORD( r, ptr[1] ); + ptr += 2 ; + break ; + + case MN_PUBLIC: + case MN_PUBLIC | MN_UNSIGNED: + case MN_PUBLIC | MN_WORD: + case MN_PUBLIC | MN_BYTE: + case MN_PUBLIC | MN_WORD | MN_UNSIGNED: + case MN_PUBLIC | MN_BYTE | MN_UNSIGNED: + case MN_PUBLIC | MN_STRING: + case MN_PUBLIC | MN_FLOAT: + *r->stack_ptr++ = ( uint32_t ) & PUBDWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_LOCAL: + case MN_LOCAL | MN_UNSIGNED: + case MN_LOCAL | MN_WORD: + case MN_LOCAL | MN_BYTE: + case MN_LOCAL | MN_WORD | MN_UNSIGNED: + case MN_LOCAL | MN_BYTE | MN_UNSIGNED: + case MN_LOCAL | MN_STRING: + case MN_LOCAL | MN_FLOAT: + *r->stack_ptr++ = ( uint32_t ) & LOCDWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GLOBAL: + case MN_GLOBAL | MN_UNSIGNED: + case MN_GLOBAL | MN_WORD: + case MN_GLOBAL | MN_BYTE: + case MN_GLOBAL | MN_WORD | MN_UNSIGNED: + case MN_GLOBAL | MN_BYTE | MN_UNSIGNED: + case MN_GLOBAL | MN_STRING: + case MN_GLOBAL | MN_FLOAT: + *r->stack_ptr++ = ( uint32_t ) & GLODWORD( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_REMOTE: + case MN_REMOTE | MN_UNSIGNED: + case MN_REMOTE | MN_WORD: + case MN_REMOTE | MN_BYTE: + case MN_REMOTE | MN_WORD | MN_UNSIGNED: + case MN_REMOTE | MN_BYTE | MN_UNSIGNED: + case MN_REMOTE | MN_STRING: + case MN_REMOTE | MN_FLOAT: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = ( uint32_t ) & LOCDWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_REMOTE_PUBLIC: + case MN_REMOTE_PUBLIC | MN_UNSIGNED: + case MN_REMOTE_PUBLIC | MN_WORD: + case MN_REMOTE_PUBLIC | MN_BYTE: + case MN_REMOTE_PUBLIC | MN_WORD | MN_UNSIGNED: + case MN_REMOTE_PUBLIC | MN_BYTE | MN_UNSIGNED: + case MN_REMOTE_PUBLIC | MN_STRING: + case MN_REMOTE_PUBLIC | MN_FLOAT: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = ( uint32_t ) & PUBDWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + /* Access to variables DWORD type */ + + case MN_GET_PRIV: + case MN_GET_PRIV | MN_FLOAT: + case MN_GET_PRIV | MN_UNSIGNED: + *r->stack_ptr++ = PRIDWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GET_PUBLIC: + case MN_GET_PUBLIC | MN_FLOAT: + case MN_GET_PUBLIC | MN_UNSIGNED: + *r->stack_ptr++ = PUBDWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GET_LOCAL: + case MN_GET_LOCAL | MN_FLOAT: + case MN_GET_LOCAL | MN_UNSIGNED: + *r->stack_ptr++ = LOCDWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GET_GLOBAL: + case MN_GET_GLOBAL | MN_FLOAT: + case MN_GET_GLOBAL | MN_UNSIGNED: + *r->stack_ptr++ = GLODWORD( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GET_REMOTE: + case MN_GET_REMOTE | MN_FLOAT: + case MN_GET_REMOTE | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCDWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_GET_REMOTE_PUBLIC: + case MN_GET_REMOTE_PUBLIC | MN_FLOAT: + case MN_GET_REMOTE_PUBLIC | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBDWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_PTR: + case MN_PTR | MN_UNSIGNED: + case MN_PTR | MN_FLOAT: + r->stack_ptr[-1] = *( int32_t * )r->stack_ptr[-1] ; + ptr++ ; + break ; + + /* Access to variables STRING type */ + + case MN_PUSH | MN_STRING: + *r->stack_ptr++ = ptr[1]; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_PRIV | MN_STRING: + *r->stack_ptr++ = PRIDWORD( r, ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_PUBLIC | MN_STRING: + *r->stack_ptr++ = PUBDWORD( r, ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_LOCAL | MN_STRING: + *r->stack_ptr++ = LOCDWORD( r, ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_GLOBAL | MN_STRING: + *r->stack_ptr++ = GLODWORD( ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_REMOTE | MN_STRING: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCDWORD( i, ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_GET_REMOTE_PUBLIC | MN_STRING: + i = instance_get( r->stack_ptr[-1] ); + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBDWORD( i, ptr[1] ) ; + string_use( r->stack_ptr[-1] ); + ptr += 2 ; + break ; + + case MN_STRING | MN_PTR: + r->stack_ptr[-1] = *( int32_t * )r->stack_ptr[-1] ; + string_use( r->stack_ptr[-1] ); + ptr++ ; + break ; + + case MN_STRING | MN_POP: + string_discard( r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Access to variables WORD type */ + + case MN_WORD | MN_GET_PRIV: + *r->stack_ptr++ = PRIINT16( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_PRIV | MN_UNSIGNED: + *r->stack_ptr++ = PRIWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_PUBLIC: + *r->stack_ptr++ = PUBINT16( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_PUBLIC | MN_UNSIGNED: + *r->stack_ptr++ = PUBWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_LOCAL: + *r->stack_ptr++ = LOCINT16( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_LOCAL | MN_UNSIGNED: + *r->stack_ptr++ = LOCWORD( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_GLOBAL: + *r->stack_ptr++ = GLOINT16( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_GLOBAL | MN_UNSIGNED: + *r->stack_ptr++ = GLOWORD( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_REMOTE: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCINT16( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_REMOTE | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_REMOTE_PUBLIC: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBINT16( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_GET_REMOTE_PUBLIC | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBWORD( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_WORD | MN_PTR: + r->stack_ptr[-1] = *( int16_t * )r->stack_ptr[-1] ; + ptr++ ; + break ; + + case MN_WORD | MN_PTR | MN_UNSIGNED: + r->stack_ptr[-1] = *( uint16_t * )r->stack_ptr[-1] ; + ptr++ ; + break ; + + /* Access to variables BYTE type */ + + case MN_BYTE | MN_GET_PRIV: + *r->stack_ptr++ = PRIINT8( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_PRIV | MN_UNSIGNED: + *r->stack_ptr++ = PRIBYTE( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_PUBLIC: + *r->stack_ptr++ = PUBINT8( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_PUBLIC | MN_UNSIGNED: + *r->stack_ptr++ = PUBBYTE( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_LOCAL: + *r->stack_ptr++ = LOCINT8( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_LOCAL | MN_UNSIGNED: + *r->stack_ptr++ = LOCBYTE( r, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_GLOBAL: + *r->stack_ptr++ = GLOINT8( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_GLOBAL | MN_UNSIGNED: + *r->stack_ptr++ = GLOBYTE( ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_REMOTE: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCINT8( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_REMOTE | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = LOCBYTE( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_REMOTE_PUBLIC: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBINT8( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_GET_REMOTE_PUBLIC | MN_UNSIGNED: + i = instance_get( r->stack_ptr[-1] ) ; + if ( !i ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Process %d not active\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), r->stack_ptr[-1] ) ; + exit( 0 ); + } + else + r->stack_ptr[-1] = PUBBYTE( i, ptr[1] ) ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_PTR: + r->stack_ptr[-1] = *(( int8_t * )r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_BYTE | MN_PTR | MN_UNSIGNED: + r->stack_ptr[-1] = *(( uint8_t * )r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + /* Floating point math */ + + case MN_FLOAT | MN_NEG: + *( float * )&r->stack_ptr[-1] = -*(( float * ) & r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_FLOAT | MN_NOT: + *( float * )&r->stack_ptr[-1] = ( float ) !*(( float * ) & r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_FLOAT | MN_ADD: + *( float * )&r->stack_ptr[-2] += *(( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_SUB: + *( float * )&r->stack_ptr[-2] -= *(( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_MUL: + *( float * )&r->stack_ptr[-2] *= *(( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_DIV: + *( float * )&r->stack_ptr[-2] /= *(( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT2INT: + *( int32_t * )&( r->stack_ptr[-ptr[1] - 1] ) = ( int32_t ) * ( float * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2FLOAT: + case MN_INT2FLOAT | MN_UNSIGNED: + *( float * )&( r->stack_ptr[-ptr[1] - 1] ) = ( float ) * ( int32_t * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2FLOAT | MN_UNSIGNED | MN_WORD: + *( float * )&( r->stack_ptr[-ptr[1] - 1] ) = ( float ) * ( uint16_t * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2FLOAT | MN_UNSIGNED | MN_BYTE: + *( float * )&( r->stack_ptr[-ptr[1] - 1] ) = ( float ) * ( uint8_t * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2WORD: + case MN_INT2WORD | MN_UNSIGNED: + *( uint32_t * )&( r->stack_ptr[-ptr[1] - 1] ) = ( int32_t )( uint16_t ) * ( int32_t * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2; + break; + + case MN_INT2BYTE: + case MN_INT2BYTE | MN_UNSIGNED: + *( uint32_t * )&( r->stack_ptr[-ptr[1] - 1] ) = ( int32_t )( uint8_t ) * ( int32_t * ) & ( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2; + break; + + /* Mathematical operations */ + + case MN_NEG: + case MN_NEG | MN_UNSIGNED: + r->stack_ptr[-1] = -r->stack_ptr[-1] ; + ptr++ ; + break ; + + case MN_NOT: + case MN_NOT | MN_UNSIGNED: + r->stack_ptr[-1] = !( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_ADD: + r->stack_ptr[-2] += r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_SUB: + r->stack_ptr[-2] -= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_MUL | MN_WORD: + case MN_MUL | MN_BYTE: + case MN_MUL: + r->stack_ptr[-2] *= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_MUL | MN_WORD | MN_UNSIGNED: + case MN_MUL | MN_BYTE | MN_UNSIGNED: + case MN_MUL | MN_UNSIGNED: + r->stack_ptr[-2] = ( uint32_t )r->stack_ptr[-2] * ( uint32_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_DIV | MN_WORD: + case MN_DIV | MN_BYTE: + case MN_DIV: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + r->stack_ptr[-2] /= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_DIV | MN_WORD | MN_UNSIGNED: + case MN_DIV | MN_BYTE | MN_UNSIGNED: + case MN_DIV | MN_UNSIGNED: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + r->stack_ptr[-2] = ( uint32_t )r->stack_ptr[-2] / ( uint32_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_MOD | MN_WORD: + case MN_MOD | MN_BYTE: + case MN_MOD: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + r->stack_ptr[-2] %= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_MOD | MN_WORD | MN_UNSIGNED: + case MN_MOD | MN_BYTE | MN_UNSIGNED: + case MN_MOD | MN_UNSIGNED: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + r->stack_ptr[-2] = ( uint32_t )r->stack_ptr[-2] % ( uint32_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Bitwise operations */ + + case MN_ROR: + ( r->stack_ptr[-2] ) = (( int32_t )r->stack_ptr[-2] ) >> r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_ROR | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint32_t ) r->stack_ptr[-2] ) >> r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_ROR: + r->stack_ptr[-2] = (( int16_t ) r->stack_ptr[-2] ) >> r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_ROR | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint16_t ) r->stack_ptr[-2] ) >> r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_ROR: + r->stack_ptr[-2] = (( int8_t ) r->stack_ptr[-2] >> r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_ROR | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint8_t ) r->stack_ptr[-2] ) >> r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_ROL: + ( r->stack_ptr[-2] ) = (( int32_t )r->stack_ptr[-2] ) << r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* All the next ROL operations, don't could be necessaries, but well... */ + + case MN_ROL | MN_UNSIGNED: + ( r->stack_ptr[-2] ) = ( uint32_t )( r->stack_ptr[-2] << r->stack_ptr[-1] ); + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_ROL: + ( r->stack_ptr[-2] ) = (( int16_t )r->stack_ptr[-2] ) << r->stack_ptr[-1]; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_ROL | MN_UNSIGNED: + ( r->stack_ptr[-2] ) = ( uint16_t )( r->stack_ptr[-2] << r->stack_ptr[-1] ); + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_ROL: + ( r->stack_ptr[-2] ) = (( int8_t )r->stack_ptr[-2] ) << r->stack_ptr[-1]; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_ROL | MN_UNSIGNED: + ( r->stack_ptr[-2] ) = ( uint8_t )( r->stack_ptr[-2] << r->stack_ptr[-1] ); + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BAND: + case MN_BAND | MN_UNSIGNED: + r->stack_ptr[-2] &= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BOR: + case MN_BOR | MN_UNSIGNED: + r->stack_ptr[-2] |= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BXOR: + case MN_BXOR | MN_UNSIGNED: + r->stack_ptr[-2] ^= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BNOT: + case MN_BNOT | MN_UNSIGNED: + r->stack_ptr[-1] = ~( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_BYTE | MN_BNOT: + r->stack_ptr[-1] = ( int8_t ) ~( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_BYTE | MN_BNOT | MN_UNSIGNED: + r->stack_ptr[-1] = ( uint8_t ) ~( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_WORD | MN_BNOT: + r->stack_ptr[-1] = ( int16_t ) ~( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + case MN_WORD | MN_BNOT | MN_UNSIGNED: + r->stack_ptr[-1] = ( uint16_t ) ~( r->stack_ptr[-1] ) ; + ptr++ ; + break ; + + /* Logical operations */ + + case MN_AND: + r->stack_ptr[-2] = r->stack_ptr[-2] && r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_OR: + r->stack_ptr[-2] = r->stack_ptr[-2] || r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_XOR: + r->stack_ptr[-2] = ( r->stack_ptr[-2] != 0 ) ^( r->stack_ptr[-1] != 0 ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Comparisons */ + + case MN_EQ: + r->stack_ptr[-2] = ( r->stack_ptr[-2] == r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_NE: + r->stack_ptr[-2] = ( r->stack_ptr[-2] != r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GTE: + r->stack_ptr[-2] = ( r->stack_ptr[-2] >= r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GTE | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint32_t )r->stack_ptr[-2] >= ( uint32_t )r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LTE: + r->stack_ptr[-2] = ( r->stack_ptr[-2] <= r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LTE | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint32_t )r->stack_ptr[-2] <= ( uint32_t )r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LT: + r->stack_ptr[-2] = ( r->stack_ptr[-2] < r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LT | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint32_t )r->stack_ptr[-2] < ( uint32_t )r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GT: + r->stack_ptr[-2] = ( r->stack_ptr[-2] > r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GT | MN_UNSIGNED: + r->stack_ptr[-2] = (( uint32_t )r->stack_ptr[-2] > ( uint32_t )r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Floating point comparisons */ + + case MN_EQ | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] == *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_NE | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] != *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GTE | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] >= *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LTE | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] <= *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LT | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] < *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GT | MN_FLOAT: + r->stack_ptr[-2] = ( *( float * ) & r->stack_ptr[-2] > *( float * ) & r->stack_ptr[-1] ) ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* String comparisons */ + + case MN_EQ | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) == 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_NE | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) != 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GTE | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) >= 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LTE | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) <= 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LT | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) < 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_GT | MN_STRING : + n = string_comp( r->stack_ptr[-2], r->stack_ptr[-1] ) > 0 ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr[-2] = n; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* String operations */ + + case MN_VARADD | MN_STRING: + n = *( int32_t * )( r->stack_ptr[-2] ) ; + *( int32_t * )( r->stack_ptr[-2] ) = string_add( n, r->stack_ptr[-1] ) ; + string_use( *( int32_t * )( r->stack_ptr[-2] ) ); + string_discard( n ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_LETNP | MN_STRING: + string_discard( *( int32_t * )( r->stack_ptr[-2] ) ); + ( *( int32_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1]; + r->stack_ptr -= 2 ; + ptr++ ; + break ; + + case MN_LET | MN_STRING: + string_discard( *( int32_t * )( r->stack_ptr[-2] ) ); + ( *( int32_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1]; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_ADD | MN_STRING: + n = string_add( r->stack_ptr[-2], r->stack_ptr[-1] ); + string_use( n ) ; + string_discard( r->stack_ptr[-2] ); + string_discard( r->stack_ptr[-1] ); + r->stack_ptr-- ; + r->stack_ptr[-1] = n ; + ptr++ ; + break ; + + case MN_INT2STR: + r->stack_ptr[-ptr[1] - 1] = string_itoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2STR | MN_UNSIGNED: + r->stack_ptr[-ptr[1] - 1] = string_uitoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2STR | MN_WORD: + r->stack_ptr[-ptr[1] - 1] = string_itoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2STR | MN_UNSIGNED | MN_WORD: + r->stack_ptr[-ptr[1] - 1] = string_uitoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2STR | MN_BYTE: + r->stack_ptr[-ptr[1] - 1] = string_itoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_INT2STR | MN_UNSIGNED | MN_BYTE: + r->stack_ptr[-ptr[1] - 1] = string_uitoa( r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_FLOAT2STR: + r->stack_ptr[-ptr[1] - 1] = string_ftoa( *( float * ) & r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_CHR2STR: + buffer[0] = ( uint8_t )r->stack_ptr[-ptr[1] - 1] ; + buffer[1] = 0 ; + r->stack_ptr[-ptr[1] - 1] = string_new( buffer ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_STRI2CHR: + n = string_char( r->stack_ptr[-2], r->stack_ptr[-1] ) ; + string_discard( r->stack_ptr[-2] ); + r->stack_ptr-- ; + r->stack_ptr[-1] = n ; + ptr++ ; + break ; + + case MN_STR2CHR: + n = r->stack_ptr[-ptr[1] - 1] ; + r->stack_ptr[-1] = *string_get( n ) ; + string_discard( n ); + ptr += 2 ; + break ; + + case MN_POINTER2STR: + r->stack_ptr[-ptr[1] - 1] = string_ptoa( *( void ** ) & r->stack_ptr[-ptr[1] - 1] ) ; + string_use( r->stack_ptr[-ptr[1] - 1] ) ; + ptr += 2 ; + break ; + + case MN_STR2FLOAT: + n = r->stack_ptr[-ptr[1] - 1] ; + str = ( char * )string_get( n ) ; + *( float * )( &r->stack_ptr[-ptr[1] - 1] ) = str ? ( float )atof( str ) : 0.0f ; + string_discard( n ) ; + ptr += 2 ; + break ; + + case MN_STR2INT: + n = r->stack_ptr[-ptr[1] - 1] ; + str = ( char * )string_get( n ) ; + r->stack_ptr[-ptr[1] - 1] = str ? atoi( str ) : 0 ; + string_discard( n ) ; + ptr += 2 ; + break ; + + /* Fixed-length strings operations*/ + + case MN_A2STR: + str = *( char ** )( &r->stack_ptr[-ptr[1] - 1] ) ; + n = string_new( str ); + string_use( n ); + r->stack_ptr[-ptr[1] - 1] = n ; + ptr += 2 ; + break ; + + case MN_STR2A: + n = r->stack_ptr[-1]; + strncpy( *( char ** )( &r->stack_ptr[-2] ), string_get( n ), ptr[1] ) ; + (( char * )( r->stack_ptr[-2] ) )[ptr[1]] = 0; + r->stack_ptr[-2] = r->stack_ptr[-1]; + r->stack_ptr--; + ptr += 2 ; + break ; + + case MN_STRACAT: + n = r->stack_ptr[-1]; + strncat( *( char ** )( &r->stack_ptr[-2] ), string_get( n ), (ptr[1]-1) - strlen( *( char ** )( &r->stack_ptr[-2] ) ) ) ; + (( char * )( r->stack_ptr[-2] ) )[ptr[1]-1] = 0; + r->stack_ptr[-2] = r->stack_ptr[-1]; + r->stack_ptr--; + ptr += 2 ; + break ; + + /* Direct operations with variables DWORD type */ + + case MN_LETNP: + case MN_LETNP | MN_UNSIGNED: + ( *( int32_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr -= 2 ; + ptr++ ; + break ; + + case MN_LET: + case MN_LET | MN_UNSIGNED: + ( *( int32_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_INC: + case MN_INC | MN_UNSIGNED: + ( *( int32_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + ptr += 2 ; + break ; + + case MN_DEC: + case MN_DEC | MN_UNSIGNED: + ( *( int32_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + ptr += 2 ; + break ; + + case MN_POSTDEC: + case MN_POSTDEC | MN_UNSIGNED: + ( *( int32_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + r->stack_ptr[-1] = *( int32_t * )( r->stack_ptr[-1] ) + ptr[1] ; + ptr += 2 ; + break ; + + case MN_POSTINC: + case MN_POSTINC | MN_UNSIGNED: + *(( int32_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + r->stack_ptr[-1] = *( int32_t * )( r->stack_ptr[-1] ) - ptr[1] ; + ptr += 2 ; + break ; + + case MN_VARADD: + case MN_VARADD | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) += r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARSUB: + case MN_VARSUB | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) -= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARMUL: + case MN_VARMUL | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) *= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARDIV: + case MN_VARDIV | MN_UNSIGNED: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( int32_t * )( r->stack_ptr[-2] ) /= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARMOD: + case MN_VARMOD | MN_UNSIGNED: + if ( r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( int32_t * )( r->stack_ptr[-2] ) %= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VAROR: + case MN_VAROR | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) |= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARXOR: + case MN_VARXOR | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) ^= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARAND: + case MN_VARAND | MN_UNSIGNED: + *( int32_t * )( r->stack_ptr[-2] ) &= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARROR: + *( int32_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARROR | MN_UNSIGNED: + *( uint32_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARROL: + *( int32_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_VARROL | MN_UNSIGNED: + *( uint32_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Direct operations with variables WORD type */ + + case MN_WORD | MN_LETNP: + case MN_WORD | MN_LETNP | MN_UNSIGNED: + ( *( int16_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr -= 2 ; + ptr++ ; + break ; + + case MN_WORD | MN_LET: + case MN_WORD | MN_LET | MN_UNSIGNED: + ( *( int16_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_INC: + case MN_WORD | MN_INC | MN_UNSIGNED: + ( *( int16_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + ptr += 2 ; + break ; + + case MN_WORD | MN_DEC: + case MN_WORD | MN_DEC | MN_UNSIGNED: + ( *( int16_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + ptr += 2 ; + break ; + + case MN_WORD | MN_POSTDEC: + case MN_WORD | MN_POSTDEC | MN_UNSIGNED: + ( *( int16_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + r->stack_ptr[-1] = *( int16_t * )( r->stack_ptr[-1] ) + ptr[1] ; + ptr += 2 ; + break ; + + case MN_WORD | MN_POSTINC: + case MN_WORD | MN_POSTINC | MN_UNSIGNED: + *(( int16_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + r->stack_ptr[-1] = *( int16_t * )( r->stack_ptr[-1] ) - ptr[1] ; + ptr += 2 ; + break ; + + case MN_WORD | MN_VARADD: + case MN_WORD | MN_VARADD | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) += r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARSUB: + case MN_WORD | MN_VARSUB | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) -= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARMUL: + case MN_WORD | MN_VARMUL | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) *= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARDIV: + case MN_WORD | MN_VARDIV | MN_UNSIGNED: + if (( int16_t )r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( int16_t * )( r->stack_ptr[-2] ) /= ( int16_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARMOD: + case MN_WORD | MN_VARMOD | MN_UNSIGNED: + if (( int16_t )r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( int16_t * )( r->stack_ptr[-2] ) %= ( int16_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VAROR: + case MN_WORD | MN_VAROR | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) |= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARXOR: + case MN_WORD | MN_VARXOR | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) ^= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARAND: + case MN_WORD | MN_VARAND | MN_UNSIGNED: + *( int16_t * )( r->stack_ptr[-2] ) &= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARROR: + *( int16_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARROR | MN_UNSIGNED: + *( uint16_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARROL: + *( int16_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_WORD | MN_VARROL | MN_UNSIGNED: + *( uint16_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Direct operations with variables BYTE type */ + + case MN_BYTE | MN_LETNP: + case MN_BYTE | MN_LETNP | MN_UNSIGNED: + ( *( uint8_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr -= 2 ; + ptr++ ; + break ; + + case MN_BYTE | MN_LET: + case MN_BYTE | MN_LET | MN_UNSIGNED: + ( *( uint8_t * )( r->stack_ptr[-2] ) ) = r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_INC: + case MN_BYTE | MN_INC | MN_UNSIGNED: + ( *( uint8_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_DEC: + case MN_BYTE | MN_DEC | MN_UNSIGNED: + ( *( uint8_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_POSTDEC: + case MN_BYTE | MN_POSTDEC | MN_UNSIGNED: + ( *( uint8_t * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + r->stack_ptr[-1] = *( uint8_t * )( r->stack_ptr[-1] ) + ptr[1] ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_POSTINC: + case MN_BYTE | MN_POSTINC | MN_UNSIGNED: + *(( uint8_t * )( r->stack_ptr[-1] ) ) += ptr[1] ; + r->stack_ptr[-1] = *( uint8_t * )( r->stack_ptr[-1] ) - ptr[1] ; + ptr += 2 ; + break ; + + case MN_BYTE | MN_VARADD: + case MN_BYTE | MN_VARADD | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) += r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARSUB: + case MN_BYTE | MN_VARSUB | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) -= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARMUL: + case MN_BYTE | MN_VARMUL | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) *= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARDIV: + case MN_BYTE | MN_VARDIV | MN_UNSIGNED: + if (( uint8_t )r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( uint8_t * )( r->stack_ptr[-2] ) /= ( uint8_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARMOD: + case MN_BYTE | MN_VARMOD | MN_UNSIGNED: + if (( uint8_t )r->stack_ptr[-1] == 0 ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Division by zero\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *( uint8_t * )( r->stack_ptr[-2] ) %= ( uint8_t )r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VAROR: + case MN_BYTE | MN_VAROR | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) |= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARXOR: + case MN_BYTE | MN_VARXOR | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) ^= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARAND: + case MN_BYTE | MN_VARAND | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) &= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARROR: + *( int8_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARROR | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) >>= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARROL: + *( int8_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_BYTE | MN_VARROL | MN_UNSIGNED: + *( uint8_t * )( r->stack_ptr[-2] ) <<= r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Direct operations with variables FLOAT type */ + + case MN_FLOAT | MN_LETNP: + ( *( float * )( r->stack_ptr[-2] ) ) = *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr -= 2 ; + ptr++ ; + break ; + + case MN_FLOAT | MN_LET : + ( *( float * )( r->stack_ptr[-2] ) ) = *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_INC: + ( *( float * )( r->stack_ptr[-1] ) ) += ptr[1] ; + ptr += 2 ; + break ; + + case MN_FLOAT | MN_DEC: + ( *( float * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + ptr += 2 ; + break ; + + case MN_FLOAT | MN_POSTDEC: + ( *( float * )( r->stack_ptr[-1] ) ) -= ptr[1] ; + r->stack_ptr[-1] = *( uint32_t * )( r->stack_ptr[-1] ) + ptr[1] ; + ptr += 2 ; + break ; + + case MN_FLOAT | MN_POSTINC: + *(( float * )( r->stack_ptr[-1] ) ) += ptr[1] ; + r->stack_ptr[-1] = *( uint32_t * )( r->stack_ptr[-1] ) - ptr[1] ; + ptr += 2 ; + break ; + + case MN_FLOAT | MN_VARADD: + *( float * )( r->stack_ptr[-2] ) += *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_VARSUB: + *( float * )( r->stack_ptr[-2] ) -= *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_VARMUL: + *( float * )( r->stack_ptr[-2] ) *= *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + case MN_FLOAT | MN_VARDIV: + *( float * )( r->stack_ptr[-2] ) /= *( float * ) & r->stack_ptr[-1] ; + r->stack_ptr-- ; + ptr++ ; + break ; + + /* Jumps */ + + case MN_JUMP: + ptr = r->code + ptr[1] ; + continue ; + + case MN_JTRUE: + r->stack_ptr-- ; + if ( *r->stack_ptr ) + { + ptr = r->code + ptr[1] ; + continue ; + } + ptr += 2 ; + break ; + + case MN_JFALSE: + r->stack_ptr-- ; + if ( !*r->stack_ptr ) + { + ptr = r->code + ptr[1] ; + continue ; + } + ptr += 2 ; + break ; + + case MN_JTTRUE: + if ( r->stack_ptr[-1] ) + { + ptr = r->code + ptr[1] ; + continue ; + } + ptr += 2 ; + break ; + + case MN_JTFALSE: + if ( !r->stack_ptr[-1] ) + { + ptr = r->code + ptr[1] ; + continue ; + } + ptr += 2 ; + break ; + + case MN_NCALL: + *r->stack_ptr++ = ptr - r->code + 2 ; /* Push next address */ + ptr = r->code + ptr[1] ; /* Call function */ + r->call_level++; + break ; + + /* Switch */ + + case MN_SWITCH: + r->switchval = *--r->stack_ptr ; + r->cased = 0 ; + ptr++ ; + break ; + + case MN_SWITCH | MN_STRING: + if ( r->switchval_string != 0 ) string_discard( r->switchval_string ); + r->switchval_string = *--r->stack_ptr; + r->cased = 0; + ptr++; + break; + + case MN_CASE: + if ( r->switchval == *--r->stack_ptr ) r->cased = 2 ; + ptr++ ; + break ; + + case MN_CASE | MN_STRING: + if ( string_comp( r->switchval_string, *--r->stack_ptr ) == 0 ) r->cased = 2 ; + string_discard( *r->stack_ptr ); + string_discard( r->stack_ptr[-1] ); + ptr++; + break; + + case MN_CASE_R: + r->stack_ptr -= 2 ; + if ( r->switchval >= r->stack_ptr[0] && r->switchval <= r->stack_ptr[1] ) r->cased = 1 ; + ptr++ ; + break ; + + case MN_CASE_R | MN_STRING: + r->stack_ptr -= 2; + if ( string_comp( r->switchval_string, r->stack_ptr[0] ) >= 0 && + string_comp( r->switchval_string, r->stack_ptr[1] ) <= 0 ) + r->cased = 1; + string_discard( r->stack_ptr[0] ); + string_discard( r->stack_ptr[1] ); + ptr++; + break; + + case MN_JNOCASE: + if ( r->cased < 1 ) + { + ptr = r->code + ptr[1] ; + continue ; + } + ptr += 2 ; + break ; + + /* Process control */ + + case MN_TYPE: + { + PROCDEF * proct = procdef_get( ptr[1] ) ; + if ( !proct ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Invalid type\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + exit( 0 ); + } + *r->stack_ptr++ = proct->type ; + ptr += 2 ; + break ; + } + + case MN_FRAME: + LOCINT32( r, FRAME_PERCENT ) += r->stack_ptr[-1]; + r->stack_ptr-- ; + r->codeptr = ptr + 1 ; + return_value = LOCDWORD( r, PROCESS_ID ); + + if ( !( r->proc->flags & PROC_FUNCTION ) && + r->called_by && instance_exists( r->called_by ) && ( LOCDWORD( r->called_by, STATUS ) & STATUS_WAITING_MASK ) ) + { + /* We're returning and the parent is waiting: wake it up */ + if ( r->called_by->stack && ( r->called_by->stack[0] & STACK_RETURN_VALUE ) ) + r->called_by->stack_ptr[-1] = return_value; + + LOCDWORD( r->called_by, STATUS ) &= ~STATUS_WAITING_MASK; + r->called_by = NULL; + } + goto break_all ; + + case MN_END: + if ( r->call_level > 0 ) + { + ptr = r->code + *--r->stack_ptr ; + r->call_level--; + continue; + } + + if ( LOCDWORD( r, STATUS ) != STATUS_DEAD ) LOCDWORD( r, STATUS ) = STATUS_KILLED ; + goto break_all ; + + case MN_RETURN: + if ( r->call_level > 0 ) + { + ptr = r->code + *--r->stack_ptr ; + r->call_level--; + continue; + } + + if ( LOCDWORD( r, STATUS ) != STATUS_DEAD ) LOCDWORD( r, STATUS ) = STATUS_KILLED ; + r->stack_ptr-- ; + return_value = *r->stack_ptr ; + goto break_all ; + + /* Handlers */ + + case MN_EXITHNDLR: + r->exitcode = ptr[1] ; + ptr += 2 ; + break; + + case MN_ERRHNDLR: + r->errorcode = ptr[1] ; + ptr += 2 ; + break; + + /* Others */ + + case MN_DEBUG: + if ( dcb.data.NSourceFiles ) + { + if ( debug > 0 ) printf( "\n::: DEBUG from %s(%d)\n", r->proc->name, LOCDWORD( r, PROCESS_ID ) ) ; + debug_next = 1; + } + ptr++; + break ; + + case MN_SENTENCE: + trace_sentence = ptr[1]; + trace_instance = r; + ptr += 2 ; + break ; + + default: + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Mnemonic 0x%02X not implemented\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), *ptr ) ; + exit( 0 ); + } + + if ( r->stack_ptr < r->stack ) + { + fprintf( stderr, "ERROR: Runtime error in %s(%d) - Critical Stack Problem StackBase=%p StackPTR=%p\n", r->proc->name, LOCDWORD( r, PROCESS_ID ), (void *)r->stack, (void *)r->stack_ptr ) ; + exit( 0 ); + } + +#ifdef EXIT_ON_EMPTY_STACK + if ( r->stack_ptr == r->stack ) + { + r->codeptr = ptr ; + if ( LOCDWORD( r, STATUS ) != STATUS_RUNNING && LOCDWORD( r, STATUS ) != STATUS_DEAD ) break ; + } +#endif + + } + + /* *** GENERAL EXIT *** */ +break_all: + + if ( !*ptr || *ptr == MN_RETURN || *ptr == MN_END || LOCDWORD( r, STATUS ) == STATUS_KILLED ) + { + /* Check for waiting parent */ + if ( r->called_by && instance_exists( r->called_by ) && ( LOCDWORD( r->called_by, STATUS ) & STATUS_WAITING_MASK ) ) + { + /* We're returning and the parent is waiting: wake it up */ + if ( r->called_by->stack && ( r->called_by->stack[0] & STACK_RETURN_VALUE ) ) + r->called_by->stack_ptr[-1] = return_value; + + LOCDWORD( r->called_by, STATUS ) &= ~STATUS_WAITING_MASK; + } + r->called_by = NULL; + + /* The process should be destroyed immediately, it is a function-type one */ + /* Run ONEXIT */ + if (( LOCDWORD( r, STATUS ) & ~STATUS_WAITING_MASK ) != STATUS_DEAD && r->exitcode ) + { + LOCDWORD( r, STATUS ) = STATUS_DEAD; + r->codeptr = r->code + r->exitcode; + instance_go( r ); + if ( !instance_exists( r ) ) r = NULL; + } + else + { + instance_destroy( r ); + r = NULL ; + } + } + + /* Hook */ + if ( r && instance_pos_execute_hook_count ) + { + for ( n = 0; n < instance_pos_execute_hook_count; n++ ) + instance_pos_execute_hook_list[n]( r ); + } + /* Hook */ + if ( r && LOCDWORD( r, STATUS ) != STATUS_KILLED && r->first_run ) r->first_run = 0; + + if ( debug_next && trace_sentence != -1 ) + { + force_debug = 1; + debug_next = 0; + } + + return return_value; +} + +/* ---------------------------------------------------------------------- */ -- cgit v1.2.3