summaryrefslogtreecommitdiffstats
path: root/kscreensaver/kdesavers/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'kscreensaver/kdesavers/vm.c')
-rw-r--r--kscreensaver/kdesavers/vm.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/kscreensaver/kdesavers/vm.c b/kscreensaver/kdesavers/vm.c
new file mode 100644
index 00000000..6d4a1af2
--- /dev/null
+++ b/kscreensaver/kdesavers/vm.c
@@ -0,0 +1,264 @@
+/*
+ * vm.c
+ *
+ * Copyright (c) 2000 Artur Rataj
+ * Distributed under the terms of the GNU General Public License
+ *
+ */
+
+#include "vm.h"
+
+#define ERROR_VALUE INT_MAX
+
+int vm_init_pool( struct tvm_pool** pool,
+ int area_size,
+ int max_stack_size,
+ int max_threads_num ) {
+ int position;
+
+ ( *pool ) = (struct tvm_pool*)malloc( sizeof(struct tvm_pool) );
+ ( *pool )->area_size = area_size;
+ ( *pool )->area = (int*)malloc( (*pool)->area_size*sizeof(int) );
+ ( *pool )->processes = NULL;
+ ( *pool )->max_stack_size = max_stack_size;
+ ( *pool )->max_threads_num = max_threads_num;
+ vm_enable_reverse( *pool, 0 );
+ for( position = 0; position < (*pool)->area_size; ++position )
+ ( *pool )->area[position] = VM_OP_STOP;
+ return 1;
+}
+
+void vm_done_pool( struct tvm_pool* pool ) {
+ struct tvm_process* curr_process;
+ free( pool->area );
+ curr_process = pool->processes;
+ while( curr_process ) {
+ struct tvm_process* tmp_process;
+
+ tmp_process = curr_process;
+ curr_process = curr_process->next;
+ free( tmp_process->stack );
+ free( tmp_process );
+ }
+ free( pool );
+}
+
+static int push( struct tvm_pool* pool,
+ struct tvm_process* process,
+ int value ) {
+ if( process->stack_top == pool->max_stack_size )
+ return ERROR_VALUE;
+ else
+ process->stack[process->stack_top++] = value;
+ return 1;
+}
+
+static int pop( struct tvm_pool* pool,
+ struct tvm_process* process ) {
+ if( process->stack_top == 0 )
+ return ERROR_VALUE;
+ else
+{
+ return process->stack[--process->stack_top];
+}
+}
+
+void vm_modify( struct tvm_pool* pool,
+ int position,
+ int op ) {
+ pool->area[position] = op;
+}
+
+void vm_exec( struct tvm_pool* pool,
+ int position,
+ int age,
+ int reverse ) {
+ struct tvm_process* new_process;
+
+ new_process = (struct tvm_process*)malloc( sizeof(struct tvm_process) );
+ new_process->position = position;
+ new_process->stack = (int*)malloc( pool->max_stack_size*sizeof(int) );
+ new_process->stack_top = 0;
+ new_process->age = age;
+ new_process->reverse = reverse;
+ new_process->next = pool->processes;
+ pool->processes = new_process;
+}
+
+void vm_enable_reverse( struct tvm_pool* pool,
+ const int enabled ) {
+ pool->reverse_enabled = enabled;
+}
+
+int vm_get_reverse( struct tvm_pool* pool ) {
+ if( pool->reverse_enabled )
+ return (int)( vm_random(&(pool->vm_random_data))*2.0/
+ ( VM_RAND_MAX + 1.0 ) );
+ else
+ return 0;
+}
+
+void vm_iterate( struct tvm_pool* pool,
+ char* modified ) {
+ struct tvm_process* prev_process;
+ struct tvm_process* curr_process;
+ struct tvm_process* next_process;
+ int processes_num;
+
+ processes_num = 0;
+ prev_process = NULL;
+ curr_process = pool->processes;
+ while( curr_process ) {
+ int op;
+ int arg;
+ int arg_2;
+ int arg_3;
+
+ ++curr_process->age;
+ next_process = curr_process->next;
+ op = pool->area[curr_process->position];
+ if( curr_process->reverse )
+ --curr_process->position;
+ else
+ ++curr_process->position;
+ curr_process->position = ( curr_process->position + pool->area_size )%
+ pool->area_size;
+ switch( op ) {
+ case VM_OP_WAIT:
+ break;
+
+ case VM_OP_STOP:
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ break;
+
+ case VM_OP_EXEC:
+ if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ } else {
+ arg = curr_process->position + arg;
+ if( arg < 0 )
+ arg += pool->area_size;
+ if( arg >= pool->area_size )
+ arg -= pool->area_size;
+ vm_exec( pool, arg, curr_process->age, vm_get_reverse(pool) );
+ }
+ break;
+
+ case VM_OP_COPY:
+ if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ } else if( (arg_2 = pop( pool, curr_process )) == ERROR_VALUE ) {
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ } else if( 1 && (arg_3 = pop( pool, curr_process )) == ERROR_VALUE ) {
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ } else {
+ int count;
+ int direction;
+
+ arg = curr_process->position + arg;
+ if( arg < 0 )
+ arg += pool->area_size;
+ if( arg >= pool->area_size )
+ arg -= pool->area_size;
+ arg_2 = curr_process->position + arg_2;
+ if( arg_2 < 0 )
+ arg_2 += pool->area_size;
+ if( arg_2 >= pool->area_size )
+ arg_2 -= pool->area_size;
+ if( curr_process->reverse )
+ direction = -1;
+ else
+ direction = 1;
+ for( count = 0; count < arg_3; ++count ) {
+ int i, j;
+ int offset;
+
+ offset = count*direction + pool->area_size;
+ i = pool->area[( arg_2 + offset )%pool->area_size];
+ j = pool->area[( arg_2 + offset )%pool->area_size] = pool->area[( arg + offset )%pool->area_size];
+ if( modified && i != j )
+ modified[( arg_2 + offset )%pool->area_size] = 1;
+ }
+ }
+ break;
+
+ default: /* >= VM_OP_PUSH */
+ arg = op - VM_OP_PUSH;
+ if( push(pool, curr_process, arg) == ERROR_VALUE ) {
+ if( !prev_process )
+ pool->processes = curr_process->next;
+ else
+ prev_process->next = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ curr_process = prev_process;
+ --processes_num;
+ }
+ break;
+ }
+ prev_process = curr_process;
+ curr_process = next_process;
+ ++processes_num;
+ }
+ while( processes_num > pool->max_threads_num ) {
+ int process_num;
+ int curr_process_num;
+
+ process_num = (int)( vm_random(&(pool->vm_random_data))*1.0*processes_num/
+ ( VM_RAND_MAX + 1.0 ) );
+/*
+ process_num = (int)( rand()*1.0*processes_num/
+ ( RAND_MAX + 1.0 ) );
+ */
+ curr_process_num = 0;
+ curr_process = pool->processes;
+ prev_process = NULL;
+ while( curr_process_num != process_num ) {
+ prev_process = curr_process;
+ curr_process = curr_process->next;
+ ++curr_process_num;
+ }
+ if( prev_process )
+ prev_process->next = curr_process->next;
+ else
+ pool->processes = curr_process->next;
+ free( curr_process->stack );
+ free( curr_process );
+ --processes_num;
+ }
+}