Mercurial > repos > rhope
annotate datum.c @ 14:69dfca29565f
C backend close to being useable
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 26 May 2009 23:52:32 +0000 |
parents | 76568becd6d6 |
children |
rev | line source |
---|---|
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 } | |
14
69dfca29565f
C backend close to being useable
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
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 |