Deprecated--
[kdeartwork.git] / kscreensaver / kdesavers / vm.c
blob6d4a1af2071aa7f28b2d91050a5674621c5704a5
1 /*
2 * vm.c
4 * Copyright (c) 2000 Artur Rataj
5 * Distributed under the terms of the GNU General Public License
7 */
9 #include "vm.h"
11 #define ERROR_VALUE INT_MAX
13 int vm_init_pool( struct tvm_pool** pool,
14 int area_size,
15 int max_stack_size,
16 int max_threads_num ) {
17 int position;
19 ( *pool ) = (struct tvm_pool*)malloc( sizeof(struct tvm_pool) );
20 ( *pool )->area_size = area_size;
21 ( *pool )->area = (int*)malloc( (*pool)->area_size*sizeof(int) );
22 ( *pool )->processes = NULL;
23 ( *pool )->max_stack_size = max_stack_size;
24 ( *pool )->max_threads_num = max_threads_num;
25 vm_enable_reverse( *pool, 0 );
26 for( position = 0; position < (*pool)->area_size; ++position )
27 ( *pool )->area[position] = VM_OP_STOP;
28 return 1;
31 void vm_done_pool( struct tvm_pool* pool ) {
32 struct tvm_process* curr_process;
33 free( pool->area );
34 curr_process = pool->processes;
35 while( curr_process ) {
36 struct tvm_process* tmp_process;
38 tmp_process = curr_process;
39 curr_process = curr_process->next;
40 free( tmp_process->stack );
41 free( tmp_process );
43 free( pool );
46 static int push( struct tvm_pool* pool,
47 struct tvm_process* process,
48 int value ) {
49 if( process->stack_top == pool->max_stack_size )
50 return ERROR_VALUE;
51 else
52 process->stack[process->stack_top++] = value;
53 return 1;
56 static int pop( struct tvm_pool* pool,
57 struct tvm_process* process ) {
58 if( process->stack_top == 0 )
59 return ERROR_VALUE;
60 else
62 return process->stack[--process->stack_top];
66 void vm_modify( struct tvm_pool* pool,
67 int position,
68 int op ) {
69 pool->area[position] = op;
72 void vm_exec( struct tvm_pool* pool,
73 int position,
74 int age,
75 int reverse ) {
76 struct tvm_process* new_process;
78 new_process = (struct tvm_process*)malloc( sizeof(struct tvm_process) );
79 new_process->position = position;
80 new_process->stack = (int*)malloc( pool->max_stack_size*sizeof(int) );
81 new_process->stack_top = 0;
82 new_process->age = age;
83 new_process->reverse = reverse;
84 new_process->next = pool->processes;
85 pool->processes = new_process;
88 void vm_enable_reverse( struct tvm_pool* pool,
89 const int enabled ) {
90 pool->reverse_enabled = enabled;
93 int vm_get_reverse( struct tvm_pool* pool ) {
94 if( pool->reverse_enabled )
95 return (int)( vm_random(&(pool->vm_random_data))*2.0/
96 ( VM_RAND_MAX + 1.0 ) );
97 else
98 return 0;
101 void vm_iterate( struct tvm_pool* pool,
102 char* modified ) {
103 struct tvm_process* prev_process;
104 struct tvm_process* curr_process;
105 struct tvm_process* next_process;
106 int processes_num;
108 processes_num = 0;
109 prev_process = NULL;
110 curr_process = pool->processes;
111 while( curr_process ) {
112 int op;
113 int arg;
114 int arg_2;
115 int arg_3;
117 ++curr_process->age;
118 next_process = curr_process->next;
119 op = pool->area[curr_process->position];
120 if( curr_process->reverse )
121 --curr_process->position;
122 else
123 ++curr_process->position;
124 curr_process->position = ( curr_process->position + pool->area_size )%
125 pool->area_size;
126 switch( op ) {
127 case VM_OP_WAIT:
128 break;
130 case VM_OP_STOP:
131 if( !prev_process )
132 pool->processes = curr_process->next;
133 else
134 prev_process->next = curr_process->next;
135 free( curr_process->stack );
136 free( curr_process );
137 curr_process = prev_process;
138 --processes_num;
139 break;
141 case VM_OP_EXEC:
142 if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
143 if( !prev_process )
144 pool->processes = curr_process->next;
145 else
146 prev_process->next = curr_process->next;
147 free( curr_process->stack );
148 free( curr_process );
149 curr_process = prev_process;
150 --processes_num;
151 } else {
152 arg = curr_process->position + arg;
153 if( arg < 0 )
154 arg += pool->area_size;
155 if( arg >= pool->area_size )
156 arg -= pool->area_size;
157 vm_exec( pool, arg, curr_process->age, vm_get_reverse(pool) );
159 break;
161 case VM_OP_COPY:
162 if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
163 if( !prev_process )
164 pool->processes = curr_process->next;
165 else
166 prev_process->next = curr_process->next;
167 free( curr_process->stack );
168 free( curr_process );
169 curr_process = prev_process;
170 --processes_num;
171 } else if( (arg_2 = pop( pool, curr_process )) == ERROR_VALUE ) {
172 if( !prev_process )
173 pool->processes = curr_process->next;
174 else
175 prev_process->next = curr_process->next;
176 free( curr_process->stack );
177 free( curr_process );
178 curr_process = prev_process;
179 --processes_num;
180 } else if( 1 && (arg_3 = pop( pool, curr_process )) == ERROR_VALUE ) {
181 if( !prev_process )
182 pool->processes = curr_process->next;
183 else
184 prev_process->next = curr_process->next;
185 free( curr_process->stack );
186 free( curr_process );
187 curr_process = prev_process;
188 --processes_num;
189 } else {
190 int count;
191 int direction;
193 arg = curr_process->position + arg;
194 if( arg < 0 )
195 arg += pool->area_size;
196 if( arg >= pool->area_size )
197 arg -= pool->area_size;
198 arg_2 = curr_process->position + arg_2;
199 if( arg_2 < 0 )
200 arg_2 += pool->area_size;
201 if( arg_2 >= pool->area_size )
202 arg_2 -= pool->area_size;
203 if( curr_process->reverse )
204 direction = -1;
205 else
206 direction = 1;
207 for( count = 0; count < arg_3; ++count ) {
208 int i, j;
209 int offset;
211 offset = count*direction + pool->area_size;
212 i = pool->area[( arg_2 + offset )%pool->area_size];
213 j = pool->area[( arg_2 + offset )%pool->area_size] = pool->area[( arg + offset )%pool->area_size];
214 if( modified && i != j )
215 modified[( arg_2 + offset )%pool->area_size] = 1;
218 break;
220 default: /* >= VM_OP_PUSH */
221 arg = op - VM_OP_PUSH;
222 if( push(pool, curr_process, arg) == ERROR_VALUE ) {
223 if( !prev_process )
224 pool->processes = curr_process->next;
225 else
226 prev_process->next = curr_process->next;
227 free( curr_process->stack );
228 free( curr_process );
229 curr_process = prev_process;
230 --processes_num;
232 break;
234 prev_process = curr_process;
235 curr_process = next_process;
236 ++processes_num;
238 while( processes_num > pool->max_threads_num ) {
239 int process_num;
240 int curr_process_num;
242 process_num = (int)( vm_random(&(pool->vm_random_data))*1.0*processes_num/
243 ( VM_RAND_MAX + 1.0 ) );
245 process_num = (int)( rand()*1.0*processes_num/
246 ( RAND_MAX + 1.0 ) );
248 curr_process_num = 0;
249 curr_process = pool->processes;
250 prev_process = NULL;
251 while( curr_process_num != process_num ) {
252 prev_process = curr_process;
253 curr_process = curr_process->next;
254 ++curr_process_num;
256 if( prev_process )
257 prev_process->next = curr_process->next;
258 else
259 pool->processes = curr_process->next;
260 free( curr_process->stack );
261 free( curr_process );
262 --processes_num;