0
|
1 #include "structs.h"
|
|
2 #include "datum.h"
|
|
3 #include "interp.h"
|
|
4 #include <stdio.h>
|
|
5 #include <stdlib.h>
|
|
6 #include <string.h>
|
|
7 #ifdef WIN32
|
|
8 #include <winsock.h>
|
|
9 #else
|
|
10 #include <sys/types.h>
|
|
11 #include <sys/socket.h>
|
|
12 #include <netinet/in.h>
|
|
13 #include <netdb.h>
|
|
14 #include <arpa/inet.h>
|
|
15 #endif
|
|
16
|
|
17 #ifdef TEXT_FILE_DEBUG
|
|
18 extern FILE * debugfile;
|
|
19 #endif
|
|
20
|
|
21 extern char * debugbuffer;
|
|
22
|
|
23 datum_storage first_datum_storage;
|
|
24 datum_storage * first_free;
|
|
25
|
|
26 VIS_CRITICAL_SECTION(datum_alloc_lock)
|
|
27
|
|
28 void init_datum_storage()
|
|
29 {
|
|
30 short i;
|
|
31 first_datum_storage.available = DATUMS_PER_STORAGE;
|
|
32 for(i = 0; i < DATUMS_PER_STORAGE/8; ++i)
|
|
33 first_datum_storage.inuse[i] = 0;
|
|
34 first_datum_storage.next = NULL;
|
|
35 //first_datum_storage.num = 0;
|
|
36 //first_free = &first_datum_storage;
|
|
37 VIS_InitializeCriticalSection(datum_alloc_lock);
|
|
38 }
|
|
39
|
|
40 datum * datum_alloc()
|
|
41 {
|
|
42 short i, j;
|
|
43 datum_storage *last, *current = /*first_free;*/&first_datum_storage;
|
|
44 VIS_PROFILE_START(PROF_DATUM_ALLOC);
|
|
45 //DEBUGPUTS("Begin datum_alloc()\n");
|
|
46 VIS_EnterCriticalSection(datum_alloc_lock);
|
|
47 while(current && !(current->available))
|
|
48 {
|
|
49 last = current;
|
|
50 current = current->next;
|
|
51 }
|
|
52 if(current)
|
|
53 {
|
|
54 for(i = 0; i < (DATUMS_PER_STORAGE >> 3); ++i)
|
|
55 if(current->inuse[i] != 0xFF)
|
|
56 break;
|
|
57 for(j = 0; j < 8; ++j)
|
|
58 if(!CHECK_INUSE(current, i, j))
|
|
59 break;
|
|
60 //DEBUGPRINTF("inuse[%d] = %X\n", i, current->inuse[i]);
|
|
61 i = (i << 3) | j;
|
|
62 //DEBUGPRINTF("Allocated datum %X:%d\n", current, i);
|
|
63 SET_INUSE(current, i);
|
|
64 --(current->available);
|
|
65 VIS_LeaveCriticalSection(datum_alloc_lock);
|
|
66 //DEBUGPUTS("End datum_alloc()\n");
|
|
67 //DEBUGPRINTF("datum_alloc(%X)\n", current->datums + i);
|
|
68 VIS_PROFILE_END(PROF_DATUM_ALLOC);
|
|
69 return current->datums + i;
|
|
70 }
|
|
71 else
|
|
72 {
|
|
73 current = MALLOC(sizeof(datum_storage),"datum storage");
|
|
74 //first_free = current;
|
|
75 //DEBUGPRINTF("New datum_storage %X\n", current);
|
|
76 last->next = current;
|
|
77 current->available = DATUMS_PER_STORAGE - 1;
|
|
78 current->inuse[0] = 1;
|
|
79 //current->num = last->num+1;
|
|
80 for(i = 1; i < DATUMS_PER_STORAGE>>3; ++i)
|
|
81 current->inuse[i] = 0;
|
|
82 current->next = NULL;
|
|
83 VIS_LeaveCriticalSection(datum_alloc_lock);
|
|
84 //DEBUGPUTS("End datum_alloc()\n");
|
|
85 //DEBUGPRINTF("datum_alloc(%X)\n", current->datums);
|
|
86 VIS_PROFILE_END(PROF_DATUM_ALLOC);
|
|
87 return current->datums;
|
|
88 }
|
|
89
|
|
90 }
|
|
91
|
|
92 void free_datum(datum * adatum)
|
|
93 {
|
|
94 datum_storage *last=NULL, *current = &first_datum_storage;
|
|
95 // DEBUGPUTS("Begin free_datum()\n");
|
|
96 VIS_EnterCriticalSection(datum_alloc_lock);
|
|
97 while(current && !(adatum >= (datum *)current && adatum <= (((datum *)current) + DATUMS_PER_STORAGE)))
|
|
98 {
|
|
99 last = current;
|
|
100 current = current->next;
|
|
101 }
|
|
102 if(current)
|
|
103 {
|
|
104 //DEBUGPRINTF("Freed datum %X:%d\n", current, adatum-((datum *)current));
|
|
105 //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]);
|
|
106 //DEBUGPRINTF("&= %X\n", ~(1 << ((adatum-(current->datums)) & 3)));
|
|
107 CLEAR_INUSE(current, adatum-(current->datums));
|
|
108 //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]);
|
|
109 ++(current->available);
|
|
110 if(current->available == DATUMS_PER_STORAGE && last && last->available)
|
|
111 {
|
|
112 last->next = NULL;
|
|
113 /*last->next = current->next;
|
|
114 if(last->num < first_free->num || first_free == current)
|
|
115 first_free = last;*/
|
|
116 //DEBUGPRINTF("Freeing datum_storage %X\n", current);
|
|
117 VIS_FREE(current, "free datum block");
|
|
118 }
|
|
119 /*else
|
|
120 {
|
|
121 if(current->num < first_free->num)
|
|
122 first_free = current;
|
|
123 }*/
|
|
124 }
|
|
125 VIS_LeaveCriticalSection(datum_alloc_lock);
|
|
126 //DEBUGPUTS("End free_datum()\n");
|
|
127 }
|
|
128
|
|
129
|
|
130
|
|
131 datum * new_datum_comp(company * comp, unsigned char union_type, int generic_len)
|
|
132 {
|
|
133 datum * adatum;
|
|
134 VIS_PROFILE_START(PROF_NEW_DATUM);
|
|
135 //adatum = datum_alloc();
|
|
136 adatum = MALLOC(sizeof(datum),"datum");
|
|
137 DEBUGPRINTF("Allocated: %X\n", adatum);
|
|
138 //DEBUGPRINTF("datum_alloc returned %X.\n", adatum);
|
|
139 adatum->company = comp;
|
|
140 adatum->union_type = union_type;
|
|
141 /*if(type > 0)
|
|
142 adatum->methods = get_method_list(type);*/
|
|
143 if(union_type == 1)//generic data
|
|
144 {
|
|
145 //DEBUGPUTS("union_type == 1\n");
|
|
146 adatum->c.generic.len = generic_len;
|
|
147 if(generic_len > 0)
|
|
148 {
|
|
149 //DEBUGPRINTF("malloc(%d);\n", generic_len);
|
|
150 adatum->c.generic.data = MALLOC(generic_len,"datum generic data");
|
|
151 //DEBUGPUTS("after malloc");
|
|
152 }
|
|
153 else
|
|
154 adatum->c.generic.data = NULL;
|
|
155 }
|
|
156 adatum->ref_count = 1;
|
|
157 // DEBUGPUTS("Initializing lock.\n");
|
|
158 VIS_InitializeCriticalSection(adatum->lock);
|
|
159 //DEBUGPRINTF( "New datum at: %X\n", adatum);
|
|
160 VIS_PROFILE_END(PROF_NEW_DATUM);
|
|
161 return adatum;
|
|
162 }
|
|
163
|
|
164 datum * new_datum(unsigned short type, unsigned char union_type, int generic_len, program * prog)
|
|
165 {
|
|
166 return new_datum_comp(prog->companylist + type, union_type, generic_len);
|
|
167 }
|
|
168
|
|
169 datum * copy_datum(datum * adatum, int newsize)
|
|
170 {
|
|
171 //NOTE: This function makes some assumptions that might not be safe everywhere in the interpretter, needs more thought
|
|
172 int ref_count, real_len, new_entry_count;
|
|
173 dict_data * dict;
|
|
174 datum * output;
|
|
175 worker_datum * work;
|
|
176 int i;
|
|
177 VIS_EnterCriticalSection(adatum->lock);
|
|
178 ref_count = adatum->ref_count;
|
|
179 VIS_LeaveCriticalSection(adatum->lock);
|
|
180 if(adatum->union_type == 1)
|
|
181 if(adatum->company->type_id == BUILTIN_TYPE_LIST)
|
|
182 real_len = (adatum->c.generic.len-1) * sizeof(datum *) + sizeof(list_data);
|
|
183 else
|
|
184 {
|
|
185 real_len = adatum->c.generic.len;
|
|
186 }
|
|
187 else
|
|
188 real_len = 0;
|
|
189 if(ref_count > 1 || newsize > real_len)
|
|
190 {
|
|
191 if(adatum->company->type_id == BUILTIN_TYPE_FILE)
|
|
192 {
|
|
193 VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
194 ((file_data *)adatum->c.generic.data)->shared->ref_count++;
|
|
195 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
196 }
|
|
197 if(newsize)
|
|
198 output = new_datum_comp(adatum->company, adatum->union_type, newsize);
|
|
199 else
|
|
200 output = new_datum_comp(adatum->company, adatum->union_type, real_len);
|
|
201 switch(adatum->union_type)
|
|
202 {
|
|
203 case 1:
|
|
204 if(adatum->company->type_id == BUILTIN_TYPE_LIST)
|
|
205 {
|
|
206 ((list_data *)output->c.generic.data)->num_entries = ((list_data *)adatum->c.generic.data)->num_entries;
|
|
207 for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i)
|
|
208 ((list_data *)output->c.generic.data)->entries[i] = add_ref(((list_data *)adatum->c.generic.data)->entries[i]);
|
|
209 }
|
|
210 #ifdef GUI_LIB
|
|
211 else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW)
|
|
212 {
|
|
213 ((vis_window *)output->c.generic.data)->title = add_ref(((vis_window *)adatum->c.generic.data)->title);
|
|
214 ((vis_window *)output->c.generic.data)->widget_dict = add_ref(((vis_window *)adatum->c.generic.data)->widget_dict);
|
|
215 ((vis_window *)output->c.generic.data)->widget_xpos = add_ref(((vis_window *)adatum->c.generic.data)->widget_xpos);
|
|
216 ((vis_window *)output->c.generic.data)->widget_ypos = add_ref(((vis_window *)adatum->c.generic.data)->widget_ypos);
|
|
217 ((vis_window *)output->c.generic.data)->id_list = add_ref(((vis_window *)adatum->c.generic.data)->id_list);
|
|
218 ((vis_window *)output->c.generic.data)->width = ((vis_window *)adatum->c.generic.data)->width;
|
|
219 ((vis_window *)output->c.generic.data)->height = ((vis_window *)adatum->c.generic.data)->height;
|
|
220 }
|
|
221 #ifdef SYLLABLE
|
|
222 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX || adatum->company->type_id == BUILTIN_TYPE_CHECKBOX || adatum->company->type_id == BUILTIN_TYPE_DROPDOWN)
|
|
223 #else
|
|
224 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX)
|
|
225 #endif
|
|
226 {
|
|
227 ((vis_widget *)output->c.generic.data)->label = add_ref(((vis_widget *)adatum->c.generic.data)->label);
|
|
228 ((vis_widget *)output->c.generic.data)->value = add_ref(((vis_widget *)adatum->c.generic.data)->value);
|
|
229 ((vis_widget *)output->c.generic.data)->handler_dict = add_ref(((vis_widget *)adatum->c.generic.data)->handler_dict);
|
|
230 ((vis_widget *)output->c.generic.data)->width = ((vis_widget *)adatum->c.generic.data)->width;
|
|
231 ((vis_widget *)output->c.generic.data)->height = ((vis_widget *)adatum->c.generic.data)->height;
|
|
232 ((vis_widget *)output->c.generic.data)->flags = ((vis_widget *)adatum->c.generic.data)->flags;
|
|
233 }
|
|
234 #endif
|
|
235 else if(real_len >= newsize && newsize)
|
|
236 memcpy(output->c.generic.data, adatum->c.generic.data, newsize);
|
|
237 else
|
|
238 memcpy(output->c.generic.data, adatum->c.generic.data, real_len);
|
|
239
|
|
240 if(adatum->company->build_size > 0)
|
|
241 {
|
|
242 for(i = 0; i < adatum->company->num_rooms; ++i)
|
|
243 if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF)
|
|
244 {
|
|
245 //DEBUGPRINTF("Member add ref (get_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func), adatum->c.generic.data);
|
|
246 add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func)));
|
|
247 }
|
|
248 else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF)
|
|
249 {
|
|
250 //DEBUGPRINTF("Member add ref (set_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func), adatum->c.generic.data);
|
|
251 add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func)));
|
|
252 }
|
|
253 }
|
|
254 else if(adatum->company->type_id == BUILTIN_TYPE_DICT)
|
|
255 {
|
|
256 dict = output->c.generic.data;
|
|
257 for(i = 0; i < dict->num_nodes; ++i)
|
|
258 add_ref(dict->nodes[i].payload);
|
|
259 }
|
|
260 else if(adatum->company->type_id == BUILTIN_TYPE_WORKER)
|
|
261 {
|
|
262 work = output->c.generic.data;
|
|
263 add_program_ref(work->def->program);
|
|
264 for(i = 0; i < work->def->num_inputs; ++i)
|
|
265 add_ref(work->params[i]);
|
|
266 }
|
|
267
|
|
268 if(adatum->c.generic.len != real_len)
|
|
269 output->c.generic.len = adatum->c.generic.len;
|
|
270 break;
|
|
271 case 2:
|
|
272 output->c.integers.num_a = adatum->c.integers.num_a;
|
|
273 output->c.integers.num_b = adatum->c.integers.num_b;
|
|
274 break;
|
|
275 case 3:
|
|
276 output->c.real = adatum->c.real;
|
|
277 break;
|
|
278 default:
|
|
279 //oops;
|
|
280 break;
|
|
281 }
|
|
282 release_ref(adatum);
|
|
283 }
|
|
284 else if(newsize && real_len == adatum->c.generic.len)
|
|
285 {
|
|
286 adatum->c.generic.len = newsize;
|
|
287 output = adatum;
|
|
288 }
|
|
289 else
|
|
290 output = adatum;
|
|
291 return output;
|
|
292 }
|
|
293
|
|
294 datum * add_ref(datum * adatum)
|
|
295 {
|
|
296 int tmp;
|
|
297 VIS_PROFILE_START(PROF_ADDREF);
|
|
298 if(!adatum)
|
|
299 {
|
|
300 //DEBUGPUTS("add_ref on NULL datum\n");
|
|
301 return NULL;
|
|
302 }
|
|
303 DEBUGPRINTF("add_ref: %X\n",adatum);
|
|
304 /*tmp = (int)(&(adatum->ref_count));
|
|
305 __asm
|
|
306 {
|
|
307 mov ebx, tmp
|
|
308 lock inc dword ptr [ebx]
|
|
309 }*/
|
|
310
|
|
311 VIS_EnterCriticalSection(adatum->lock);
|
|
312 ++(adatum->ref_count);
|
|
313 VIS_LeaveCriticalSection(adatum->lock);
|
|
314 VIS_PROFILE_END(PROF_ADDREF);
|
|
315 return adatum;
|
|
316 }
|
|
317
|
|
318 void release_ref(datum * adatum)
|
|
319 {
|
|
320 int i,tmp;
|
|
321 dict_data * dict;
|
|
322 worker_datum * worker;
|
|
323 VIS_PROFILE_START(PROF_RELEASE);
|
|
324 DEBUGPRINTF( "relase_ref: %X\n",adatum);
|
|
325 if(!adatum)
|
|
326 return;
|
|
327
|
|
328 /*tmp = (int)(&(adatum->ref_count));
|
|
329 __asm
|
|
330 {
|
|
331 mov ebx, tmp
|
|
332 lock dec dword ptr [ebx]
|
|
333 }*/
|
|
334 //DEBUGPUTS("entering lock");
|
|
335 VIS_EnterCriticalSection(adatum->lock);
|
|
336 //DEBUGPUTS("got critical section\n");
|
|
337 --(adatum->ref_count);
|
|
338 if(adatum->ref_count == 0)
|
|
339 {
|
|
340 //DEBUGPRINTF("datum_free(%X)\n", adatum);
|
|
341
|
|
342 VIS_LeaveCriticalSection(adatum->lock);
|
|
343 //DEBUGPUTS("left lock");
|
|
344 VIS_DeleteCriticalSection(adatum->lock);
|
|
345 if(adatum->union_type == 1)
|
|
346 {
|
|
347 //DEBUGPRINTF( "Freeing adatum->c.generic.data(%X)\n",(int)adatum->c.generic.data);
|
|
348 if(adatum->company->build_size > 0)
|
|
349 {
|
|
350 for(i = 0; i < adatum->company->num_rooms; ++i)
|
|
351 if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF)
|
|
352 {
|
|
353 //DEBUGPRINTF("Member release ref (get_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func), adatum->c.generic.data);
|
|
354 release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func)));
|
|
355 }
|
|
356 else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF)
|
|
357 {
|
|
358 //DEBUGPRINTF("Member release ref (set_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func), adatum->c.generic.data);
|
|
359 release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func)));
|
|
360 }
|
|
361 }
|
|
362 else if(adatum->company->type_id == BUILTIN_TYPE_LIST)
|
|
363 for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i)
|
|
364 release_ref(((list_data *)adatum->c.generic.data)->entries[i]);
|
|
365 else if(adatum->company->type_id == BUILTIN_TYPE_FILE)
|
|
366 {
|
|
367 VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
368 --(((file_data *)adatum->c.generic.data)->shared->ref_count);
|
|
369 if(((file_data *)adatum->c.generic.data)->shared->ref_count == 0)
|
|
370 {
|
|
371 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
372 VIS_DeleteCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
373 #ifndef SEGA
|
|
374 if(((file_data *)adatum->c.generic.data)->shared->status == FILE_READ || ((file_data *)adatum->c.generic.data)->shared->status == FILE_WRITE)
|
|
375 fclose(((file_data *)adatum->c.generic.data)->shared->file);
|
|
376 #endif
|
|
377 VIS_FREE(((file_data *)adatum->c.generic.data)->shared, "Shared file struct");
|
|
378 }
|
|
379 else
|
|
380 {
|
|
381 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
|
|
382 }
|
|
383 }
|
|
384 else if(adatum->company->type_id == BUILTIN_TYPE_DICT)
|
|
385 {
|
|
386 dict = adatum->c.generic.data;
|
|
387 for(i = 0; i < dict->num_nodes; ++i)
|
|
388 release_ref(dict->nodes[i].payload);
|
|
389 }
|
|
390 else if(adatum->company->type_id == BUILTIN_TYPE_WORKER)
|
|
391 {
|
|
392 worker = adatum->c.generic.data;
|
|
393 for(i = 0; i < worker->def->num_inputs; ++i)
|
|
394 if(worker->params[i])
|
|
395 {
|
|
396 DEBUGPRINTF("Releasing worker param %d\n", i);
|
|
397 release_ref(worker->params[i]);
|
|
398 }
|
|
399 release_program_ref(worker->def->program);
|
|
400 }
|
13
|
401 #ifdef GUI_LIB
|
0
|
402 else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW)
|
|
403 {
|
|
404 release_ref(((vis_window *)adatum->c.generic.data)->title);
|
|
405 release_ref(((vis_window *)adatum->c.generic.data)->widget_dict);
|
|
406 release_ref(((vis_window *)adatum->c.generic.data)->widget_xpos);
|
|
407 release_ref(((vis_window *)adatum->c.generic.data)->widget_ypos);
|
|
408 release_ref(((vis_window *)adatum->c.generic.data)->id_list);
|
|
409 }
|
|
410 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON)
|
|
411 {
|
|
412 release_ref(((vis_widget *)adatum->c.generic.data)->label);
|
|
413 release_ref(((vis_widget *)adatum->c.generic.data)->handler_dict);
|
|
414 }
|
|
415 #endif
|
|
416 VIS_FREE(adatum->c.generic.data, "datum->c.generic.data");
|
|
417 } else if(adatum->company->type_id == BUILTIN_TYPE_NETCLIENT)
|
|
418 #ifdef WIN32
|
|
419 closesocket(adatum->c.integers.num_a);
|
|
420 #else
|
|
421 close(adatum->c.integers.num_a);
|
|
422 #endif
|
|
423 else if(adatum->company->type_id == BUILTIN_TYPE_PROGRAM)
|
|
424 release_program_ref(adatum->c.generic.data);
|
|
425 DEBUGPRINTF("Freeing: %X\n",adatum);
|
|
426 //free_datum(adatum);
|
|
427 free(adatum);
|
|
428 }
|
|
429 else
|
|
430 {
|
|
431 VIS_LeaveCriticalSection(adatum->lock);
|
|
432 //DEBUGPUTS("left lock");
|
|
433 }
|
|
434 VIS_PROFILE_END(PROF_RELEASE);
|
|
435 //DEBUGPUTS("exit release_ref\n");
|
|
436
|
|
437 }
|
|
438
|
|
439 void datum_set_yesno(datum * adatum, int val)
|
|
440 {
|
|
441 adatum->c.integers.num_a = val;
|
|
442 }
|
|
443
|
|
444
|
|
445
|
|
446
|
|
447
|
|
448
|