aboutsummaryrefslogtreecommitdiff
path: root/modules/mod_proc/mod_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mod_proc/mod_proc.c')
-rw-r--r--modules/mod_proc/mod_proc.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/modules/mod_proc/mod_proc.c b/modules/mod_proc/mod_proc.c
new file mode 100644
index 0000000..9d8c31d
--- /dev/null
+++ b/modules/mod_proc/mod_proc.c
@@ -0,0 +1,514 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+
+#include "bgdrtm.h"
+
+#include "bgddl.h"
+#include "dlvaracc.h"
+#include "instance.h"
+
+#include "xstrings.h"
+
+#include "mod_proc.h"
+
+/* ----------------------------------------------------------------- */
+
+enum
+{
+ PROCESS_ID = 0,
+ PROCESS_TYPE,
+ STATUS,
+ ID_SCAN,
+ TYPE_SCAN,
+ CONTEXT,
+ SIGNAL_ACTION
+} ;
+
+/* ----------------------------------------------------------------- */
+/* Son las variables que se desea acceder. */
+/* El interprete completa esta estructura, si la variable existe. */
+/* (usada en tiempo de ejecucion) */
+DLVARFIXUP __bgdexport( mod_proc, locals_fixup )[] =
+{
+ /* Nombre de variable local, offset al dato, tamaño del elemento, cantidad de elementos */
+ { "id", NULL, -1, -1 },
+ { "reserved.process_type", NULL, -1, -1 },
+ { "reserved.status", NULL, -1, -1 },
+ { "mod_proc_reserved.id_scan", NULL, -1, -1 },
+ { "mod_proc_reserved.type_scan", NULL, -1, -1 },
+ { "mod_proc_reserved.context", NULL, -1, -1 },
+ { "mod_proc_reserved.signal_action", NULL, -1, -1 },
+ { NULL, NULL, -1, -1 }
+};
+
+/* ----------------------------------------------------------------- */
+
+void __bgdexport( mod_proc, process_exec_hook )( INSTANCE * r )
+{
+ LOCDWORD( mod_proc, r, TYPE_SCAN ) = 0;
+ LOCDWORD( mod_proc, r, ID_SCAN ) = 0;
+ LOCDWORD( mod_proc, r, CONTEXT ) = 0;
+}
+
+/* ----------------------------------------------------------------- */
+/* Interacción entre procesos */
+
+static void _modproc_kill_all()
+{
+ INSTANCE * i = first_instance ;
+ while ( i )
+ {
+ LOCDWORD( mod_proc, i, STATUS ) = STATUS_KILLED ;
+ i = i->next ;
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/** EXIT ()
+ * Leaves the program at next frame
+ */
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_exit_0( INSTANCE * my, int * params )
+{
+ exit_value = 0;
+ must_exit = 1 ;
+
+ return 1 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_exit_1( INSTANCE * my, int * params )
+{
+ printf( string_get( params[0] ) );
+ printf( "\n" );
+ fflush( stdout );
+ string_discard( params[0] );
+
+ exit_value = 0;
+ must_exit = 1 ;
+
+ return 1 ;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static int modproc_exit( INSTANCE * my, int * params )
+{
+ _modproc_kill_all();
+
+ printf( string_get( params[0] ) );
+ printf( "\n" );
+ fflush( stdout );
+ string_discard( params[0] );
+
+ exit_value = params[1];
+ must_exit = 1 ;
+
+ return 1 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_running( INSTANCE * my, int * params )
+{
+ INSTANCE * i, * ctx;
+
+ if ( params[0] == 0 ) return 0;
+
+ if ( params[0] >= FIRST_INSTANCE_ID )
+ {
+ i = instance_get( params[0] ) ;
+ if ( i && ( LOCDWORD( mod_proc, i, STATUS ) & ~STATUS_WAITING_MASK ) >= STATUS_RUNNING ) return 1;
+ return 0;
+ }
+
+ ctx = NULL;
+ while ( ( i = instance_get_by_type( params[0], &ctx ) ) )
+ {
+ if ( ( LOCDWORD( mod_proc, i, STATUS ) & ~STATUS_WAITING_MASK ) >= STATUS_RUNNING ) return 1;
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_signal( INSTANCE * my, int * params )
+{
+ INSTANCE * i, * ctx;
+ int fake_params[2] ;
+
+ if ( params[0] == ALL_PROCESS )
+ {
+ /* Signal all process but my */
+ int myid = LOCDWORD( mod_proc, my, PROCESS_ID );
+ fake_params[1] = ( params[1] >= S_TREE ) ? params[1] - S_TREE : params[1] ;
+ i = first_instance ;
+ while ( i )
+ {
+ if ( LOCDWORD( mod_proc, i, PROCESS_ID ) != myid && ( LOCDWORD( mod_proc, i, STATUS ) & ~STATUS_WAITING_MASK ) > STATUS_KILLED )
+ {
+ fake_params[0] = LOCDWORD( mod_proc, i, PROCESS_ID ) ;
+ modproc_signal( my, fake_params ) ;
+ }
+ i = i->next ;
+ }
+ return 0 ;
+ }
+ else if ( params[0] < FIRST_INSTANCE_ID )
+ {
+ /* Signal by type */
+ fake_params[1] = params[1] ;
+
+ ctx = NULL;
+ while ( ( i = instance_get_by_type( params[0], &ctx ) ) )
+ {
+ fake_params[0] = LOCDWORD( mod_proc, i, PROCESS_ID ) ;
+ modproc_signal( my, fake_params ) ;
+ }
+ return 0 ;
+ }
+
+ i = instance_get( params[0] ) ;
+ if ( i )
+ {
+ if (( LOCDWORD( mod_proc, i, STATUS ) & ~STATUS_WAITING_MASK ) > STATUS_KILLED )
+ {
+ switch ( params[1] )
+ {
+ case S_KILL:
+ case S_KILL_FORCE:
+ if ( params[1] == S_KILL_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_KILL ) )
+ LOCDWORD( mod_proc, i, STATUS ) = STATUS_KILLED ;
+ break ;
+
+ case S_WAKEUP:
+ case S_WAKEUP_FORCE:
+ if ( params[1] == S_WAKEUP_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_WAKEUP ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_RUNNING ;
+ break ;
+
+ case S_SLEEP:
+ case S_SLEEP_FORCE:
+ if ( params[1] == S_SLEEP_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_SLEEP ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_SLEEPING ;
+ break ;
+
+ case S_FREEZE:
+ case S_FREEZE_FORCE:
+ if ( params[1] == S_FREEZE_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_FREEZE ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_FROZEN ;
+ break ;
+
+ case S_KILL_TREE:
+ case S_KILL_TREE_FORCE:
+ if ( params[1] == S_KILL_TREE_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_KILL_TREE ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_KILLED ;
+ break ;
+
+ case S_WAKEUP_TREE:
+ case S_WAKEUP_TREE_FORCE:
+ if ( params[1] == S_WAKEUP_TREE_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_WAKEUP_TREE ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_RUNNING ;
+ break ;
+
+ case S_SLEEP_TREE:
+ case S_SLEEP_TREE_FORCE:
+ if ( params[1] == S_SLEEP_TREE_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_SLEEP_TREE ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_SLEEPING ;
+ break ;
+
+ case S_FREEZE_TREE:
+ case S_FREEZE_TREE_FORCE:
+ if ( params[1] == S_FREEZE_TREE_FORCE || !( LOCDWORD( mod_proc, i, SIGNAL_ACTION ) & SMASK_FREEZE_TREE ) )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_FROZEN ;
+ break ;
+
+ default:
+ return 1 ;
+ }
+ }
+
+ if ( params[1] >= S_TREE )
+ {
+ fake_params[1] = params[1] ;
+ i = instance_getson( i ) ;
+ while ( i )
+ {
+ fake_params[0] = LOCDWORD( mod_proc, i, PROCESS_ID ) ;
+ modproc_signal( my, fake_params ) ;
+ i = instance_getbigbro( i ) ;
+ }
+ }
+ }
+ return 1 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_signal_action( INSTANCE * my, int * params )
+{
+ int action = params[1];
+
+ if ( my )
+ {
+ switch ( params[0] )
+ {
+ case S_KILL:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_KILL;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_KILL;
+ break;
+ }
+ break ;
+
+ case S_WAKEUP:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_WAKEUP;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_WAKEUP;
+ break;
+ }
+ break ;
+
+ case S_SLEEP:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_SLEEP;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_SLEEP;
+ break;
+ }
+ break ;
+
+ case S_FREEZE:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_FREEZE;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_FREEZE;
+ break;
+ }
+ break ;
+
+ case S_KILL_TREE:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_KILL_TREE;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_KILL_TREE;
+ break;
+ }
+ break ;
+
+ case S_WAKEUP_TREE:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_WAKEUP_TREE;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_WAKEUP_TREE;
+ break;
+ }
+ break ;
+
+ case S_SLEEP_TREE:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_SLEEP_TREE;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_SLEEP_TREE;
+ break;
+ }
+ break ;
+
+ case S_FREEZE_TREE:
+ switch ( action )
+ {
+ case S_IGN:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) |= SMASK_FREEZE_TREE;
+ break;
+
+ case S_DFL:
+ LOCDWORD( mod_proc, my, SIGNAL_ACTION ) &= ~SMASK_FREEZE_TREE;
+ break;
+ }
+ break ;
+ }
+ }
+ return 1 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_signal_action3( INSTANCE * my, int * params )
+{
+ INSTANCE * i, * ctx ;
+
+ if ( params[0] == ALL_PROCESS )
+ {
+ i = first_instance ;
+ while ( i )
+ {
+ modproc_signal_action( i, &params[1] ) ;
+ i = i->next ;
+ }
+ return 0 ;
+ }
+ else if ( params[0] < FIRST_INSTANCE_ID )
+ {
+ ctx = NULL;
+ while ( ( i = instance_get_by_type( params[0], &ctx ) ) )
+ {
+ modproc_signal_action( i, &params[1] ) ;
+ }
+ return 0 ;
+ }
+
+ i = instance_get( params[0] ) ;
+ if ( i ) modproc_signal_action( i, &params[1] ) ;
+
+ return 1;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_let_me_alone( INSTANCE * my, int * params )
+{
+ INSTANCE * i = first_instance ;
+
+ while ( i )
+ {
+ if ( i != my && ( LOCDWORD( mod_proc, i, STATUS ) & ~STATUS_WAITING_MASK ) != STATUS_DEAD )
+ LOCDWORD( mod_proc, i, STATUS ) = ( LOCDWORD( mod_proc, i, STATUS ) & STATUS_WAITING_MASK ) | STATUS_KILLED ;
+ i = i->next ;
+ }
+ if ( LOCDWORD( mod_proc, my, STATUS ) > STATUS_KILLED ) LOCDWORD( mod_proc, my, STATUS ) = STATUS_RUNNING;
+ return 1 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_get_id( INSTANCE * my, int * params )
+{
+ INSTANCE * ptr = first_instance, ** ctx ;
+
+ if ( !params[0] )
+ {
+ LOCDWORD( mod_proc, my, TYPE_SCAN ) = 0 ;
+ if ( LOCDWORD( mod_proc, my, ID_SCAN ) )
+ {
+ ptr = instance_get( LOCDWORD( mod_proc, my, ID_SCAN ) ) ;
+ if ( ptr ) ptr = ptr->next ;
+ }
+
+ while ( ptr )
+ {
+ if (( LOCDWORD( mod_proc, ptr, STATUS ) & ~STATUS_WAITING_MASK ) >= STATUS_RUNNING )
+ {
+ LOCDWORD( mod_proc, my, ID_SCAN ) = LOCDWORD( mod_proc, ptr, PROCESS_ID ) ;
+ return LOCDWORD( mod_proc, ptr, PROCESS_ID ) ;
+ }
+ ptr = ptr->next ;
+ }
+ return 0 ;
+ }
+
+ LOCDWORD( mod_proc, my, ID_SCAN ) = 0 ;
+ /* Check if already in scan by type and we reach limit */
+ ctx = ( INSTANCE ** ) LOCADDR( mod_proc, my, CONTEXT );
+/*
+ if ( !*ctx && LOCDWORD( mod_proc, my, TYPE_SCAN ) )
+ {
+ LOCDWORD( mod_proc, my, TYPE_SCAN ) = 0;
+ return 0;
+ }
+*/
+ /* Check if type change from last call */
+ if ( LOCDWORD( mod_proc, my, TYPE_SCAN ) != params[0] )
+ {
+ *ctx = NULL;
+ LOCDWORD( mod_proc, my, TYPE_SCAN ) = params[0];
+ }
+
+ while ( ( ptr = instance_get_by_type( params[0], ctx ) ) )
+ {
+ if ( /*ptr != my &&*/ ( LOCDWORD( mod_proc, ptr, STATUS ) & ~STATUS_WAITING_MASK ) >= STATUS_RUNNING )
+ {
+ return LOCDWORD( mod_proc, ptr, PROCESS_ID ) ;
+ }
+ }
+
+ return 0 ;
+}
+
+/* ----------------------------------------------------------------- */
+
+static int modproc_get_status( INSTANCE * my, int * params )
+{
+ INSTANCE * i ;
+ if ( !params[0] || !( i = instance_get( params[0] ) ) ) return 0;
+ return LOCDWORD( mod_proc, i, STATUS ) ;
+}
+
+/* ----------------------------------------------------------------- */
+/* exports */
+/* ----------------------------------------------------------------- */
+
+#include "mod_proc_exports.h"
+
+/* ----------------------------------------------------------------- */