Mercurial > repos > rhope
view datum.c @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -0400 |
parents | 23dd9c766699 |
children |
line wrap: on
line source
#include "structs.h" #include "datum.h" #include "interp.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32 #include <winsock.h> #else #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #endif #ifdef TEXT_FILE_DEBUG extern FILE * debugfile; #endif extern char * debugbuffer; datum_storage first_datum_storage; datum_storage * first_free; VIS_CRITICAL_SECTION(datum_alloc_lock) void init_datum_storage() { short i; first_datum_storage.available = DATUMS_PER_STORAGE; for(i = 0; i < DATUMS_PER_STORAGE/8; ++i) first_datum_storage.inuse[i] = 0; first_datum_storage.next = NULL; //first_datum_storage.num = 0; //first_free = &first_datum_storage; VIS_InitializeCriticalSection(datum_alloc_lock); } datum * datum_alloc() { short i, j; datum_storage *last, *current = /*first_free;*/&first_datum_storage; VIS_PROFILE_START(PROF_DATUM_ALLOC); //DEBUGPUTS("Begin datum_alloc()\n"); VIS_EnterCriticalSection(datum_alloc_lock); while(current && !(current->available)) { last = current; current = current->next; } if(current) { for(i = 0; i < (DATUMS_PER_STORAGE >> 3); ++i) if(current->inuse[i] != 0xFF) break; for(j = 0; j < 8; ++j) if(!CHECK_INUSE(current, i, j)) break; //DEBUGPRINTF("inuse[%d] = %X\n", i, current->inuse[i]); i = (i << 3) | j; //DEBUGPRINTF("Allocated datum %X:%d\n", current, i); SET_INUSE(current, i); --(current->available); VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End datum_alloc()\n"); //DEBUGPRINTF("datum_alloc(%X)\n", current->datums + i); VIS_PROFILE_END(PROF_DATUM_ALLOC); return current->datums + i; } else { current = MALLOC(sizeof(datum_storage),"datum storage"); //first_free = current; //DEBUGPRINTF("New datum_storage %X\n", current); last->next = current; current->available = DATUMS_PER_STORAGE - 1; current->inuse[0] = 1; //current->num = last->num+1; for(i = 1; i < DATUMS_PER_STORAGE>>3; ++i) current->inuse[i] = 0; current->next = NULL; VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End datum_alloc()\n"); //DEBUGPRINTF("datum_alloc(%X)\n", current->datums); VIS_PROFILE_END(PROF_DATUM_ALLOC); return current->datums; } } void free_datum(datum * adatum) { datum_storage *last=NULL, *current = &first_datum_storage; // DEBUGPUTS("Begin free_datum()\n"); VIS_EnterCriticalSection(datum_alloc_lock); while(current && !(adatum >= (datum *)current && adatum <= (((datum *)current) + DATUMS_PER_STORAGE))) { last = current; current = current->next; } if(current) { //DEBUGPRINTF("Freed datum %X:%d\n", current, adatum-((datum *)current)); //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]); //DEBUGPRINTF("&= %X\n", ~(1 << ((adatum-(current->datums)) & 3))); CLEAR_INUSE(current, adatum-(current->datums)); //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]); ++(current->available); if(current->available == DATUMS_PER_STORAGE && last && last->available) { last->next = NULL; /*last->next = current->next; if(last->num < first_free->num || first_free == current) first_free = last;*/ //DEBUGPRINTF("Freeing datum_storage %X\n", current); VIS_FREE(current, "free datum block"); } /*else { if(current->num < first_free->num) first_free = current; }*/ } VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End free_datum()\n"); } datum * new_datum_comp(company * comp, unsigned char union_type, int generic_len) { datum * adatum; VIS_PROFILE_START(PROF_NEW_DATUM); //adatum = datum_alloc(); adatum = MALLOC(sizeof(datum),"datum"); DEBUGPRINTF("Allocated: %X\n", adatum); //DEBUGPRINTF("datum_alloc returned %X.\n", adatum); adatum->company = comp; adatum->union_type = union_type; /*if(type > 0) adatum->methods = get_method_list(type);*/ if(union_type == 1)//generic data { //DEBUGPUTS("union_type == 1\n"); adatum->c.generic.len = generic_len; if(generic_len > 0) { //DEBUGPRINTF("malloc(%d);\n", generic_len); adatum->c.generic.data = MALLOC(generic_len,"datum generic data"); //DEBUGPUTS("after malloc"); } else adatum->c.generic.data = NULL; } adatum->ref_count = 1; // DEBUGPUTS("Initializing lock.\n"); VIS_InitializeCriticalSection(adatum->lock); //DEBUGPRINTF( "New datum at: %X\n", adatum); VIS_PROFILE_END(PROF_NEW_DATUM); return adatum; } datum * new_datum(unsigned short type, unsigned char union_type, int generic_len, program * prog) { return new_datum_comp(prog->companylist + type, union_type, generic_len); } datum * copy_datum(datum * adatum, int newsize) { //NOTE: This function makes some assumptions that might not be safe everywhere in the interpretter, needs more thought int ref_count, real_len, new_entry_count; dict_data * dict; datum * output; worker_datum * work; int i; VIS_EnterCriticalSection(adatum->lock); ref_count = adatum->ref_count; VIS_LeaveCriticalSection(adatum->lock); if(adatum->union_type == 1) if(adatum->company->type_id == BUILTIN_TYPE_LIST) real_len = (adatum->c.generic.len-1) * sizeof(datum *) + sizeof(list_data); else { real_len = adatum->c.generic.len; } else real_len = 0; if(ref_count > 1 || newsize > real_len) { if(adatum->company->type_id == BUILTIN_TYPE_FILE) { VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); ((file_data *)adatum->c.generic.data)->shared->ref_count++; VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); } if(newsize) output = new_datum_comp(adatum->company, adatum->union_type, newsize); else output = new_datum_comp(adatum->company, adatum->union_type, real_len); switch(adatum->union_type) { case 1: if(adatum->company->type_id == BUILTIN_TYPE_LIST) { ((list_data *)output->c.generic.data)->num_entries = ((list_data *)adatum->c.generic.data)->num_entries; for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i) ((list_data *)output->c.generic.data)->entries[i] = add_ref(((list_data *)adatum->c.generic.data)->entries[i]); } #ifdef GUI_LIB else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW) { ((vis_window *)output->c.generic.data)->title = add_ref(((vis_window *)adatum->c.generic.data)->title); ((vis_window *)output->c.generic.data)->widget_dict = add_ref(((vis_window *)adatum->c.generic.data)->widget_dict); ((vis_window *)output->c.generic.data)->widget_xpos = add_ref(((vis_window *)adatum->c.generic.data)->widget_xpos); ((vis_window *)output->c.generic.data)->widget_ypos = add_ref(((vis_window *)adatum->c.generic.data)->widget_ypos); ((vis_window *)output->c.generic.data)->id_list = add_ref(((vis_window *)adatum->c.generic.data)->id_list); ((vis_window *)output->c.generic.data)->width = ((vis_window *)adatum->c.generic.data)->width; ((vis_window *)output->c.generic.data)->height = ((vis_window *)adatum->c.generic.data)->height; } #ifdef SYLLABLE 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) #else else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX) #endif { ((vis_widget *)output->c.generic.data)->label = add_ref(((vis_widget *)adatum->c.generic.data)->label); ((vis_widget *)output->c.generic.data)->value = add_ref(((vis_widget *)adatum->c.generic.data)->value); ((vis_widget *)output->c.generic.data)->handler_dict = add_ref(((vis_widget *)adatum->c.generic.data)->handler_dict); ((vis_widget *)output->c.generic.data)->width = ((vis_widget *)adatum->c.generic.data)->width; ((vis_widget *)output->c.generic.data)->height = ((vis_widget *)adatum->c.generic.data)->height; ((vis_widget *)output->c.generic.data)->flags = ((vis_widget *)adatum->c.generic.data)->flags; } #endif else if(real_len >= newsize && newsize) memcpy(output->c.generic.data, adatum->c.generic.data, newsize); else memcpy(output->c.generic.data, adatum->c.generic.data, real_len); if(adatum->company->build_size > 0) { for(i = 0; i < adatum->company->num_rooms; ++i) if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF) { //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); add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func))); } else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF) { //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); add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func))); } } else if(adatum->company->type_id == BUILTIN_TYPE_DICT) { dict = output->c.generic.data; for(i = 0; i < dict->num_nodes; ++i) add_ref(dict->nodes[i].payload); } else if(adatum->company->type_id == BUILTIN_TYPE_WORKER) { work = output->c.generic.data; add_program_ref(work->def->program); for(i = 0; i < work->def->num_inputs; ++i) add_ref(work->params[i]); } if(adatum->c.generic.len != real_len) output->c.generic.len = adatum->c.generic.len; break; case 2: output->c.integers.num_a = adatum->c.integers.num_a; output->c.integers.num_b = adatum->c.integers.num_b; break; case 3: output->c.real = adatum->c.real; break; default: //oops; break; } release_ref(adatum); } else if(newsize && real_len == adatum->c.generic.len) { adatum->c.generic.len = newsize; output = adatum; } else output = adatum; return output; } datum * add_ref(datum * adatum) { int tmp; VIS_PROFILE_START(PROF_ADDREF); if(!adatum) { //DEBUGPUTS("add_ref on NULL datum\n"); return NULL; } DEBUGPRINTF("add_ref: %X\n",adatum); /*tmp = (int)(&(adatum->ref_count)); __asm { mov ebx, tmp lock inc dword ptr [ebx] }*/ VIS_EnterCriticalSection(adatum->lock); ++(adatum->ref_count); VIS_LeaveCriticalSection(adatum->lock); VIS_PROFILE_END(PROF_ADDREF); return adatum; } void release_ref(datum * adatum) { int i,tmp; dict_data * dict; worker_datum * worker; VIS_PROFILE_START(PROF_RELEASE); DEBUGPRINTF( "relase_ref: %X\n",adatum); if(!adatum) return; /*tmp = (int)(&(adatum->ref_count)); __asm { mov ebx, tmp lock dec dword ptr [ebx] }*/ //DEBUGPUTS("entering lock"); VIS_EnterCriticalSection(adatum->lock); //DEBUGPUTS("got critical section\n"); --(adatum->ref_count); if(adatum->ref_count == 0) { //DEBUGPRINTF("datum_free(%X)\n", adatum); VIS_LeaveCriticalSection(adatum->lock); //DEBUGPUTS("left lock"); VIS_DeleteCriticalSection(adatum->lock); if(adatum->union_type == 1) { //DEBUGPRINTF( "Freeing adatum->c.generic.data(%X)\n",(int)adatum->c.generic.data); if(adatum->company->build_size > 0) { for(i = 0; i < adatum->company->num_rooms; ++i) if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF) { //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); release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func))); } else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF) { //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); release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func))); } } else if(adatum->company->type_id == BUILTIN_TYPE_LIST) for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i) release_ref(((list_data *)adatum->c.generic.data)->entries[i]); else if(adatum->company->type_id == BUILTIN_TYPE_FILE) { VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); --(((file_data *)adatum->c.generic.data)->shared->ref_count); if(((file_data *)adatum->c.generic.data)->shared->ref_count == 0) { VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); VIS_DeleteCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); #ifndef SEGA if(((file_data *)adatum->c.generic.data)->shared->status == FILE_READ || ((file_data *)adatum->c.generic.data)->shared->status == FILE_WRITE) fclose(((file_data *)adatum->c.generic.data)->shared->file); #endif VIS_FREE(((file_data *)adatum->c.generic.data)->shared, "Shared file struct"); } else { VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); } } else if(adatum->company->type_id == BUILTIN_TYPE_DICT) { dict = adatum->c.generic.data; for(i = 0; i < dict->num_nodes; ++i) release_ref(dict->nodes[i].payload); } else if(adatum->company->type_id == BUILTIN_TYPE_WORKER) { worker = adatum->c.generic.data; for(i = 0; i < worker->def->num_inputs; ++i) if(worker->params[i]) { DEBUGPRINTF("Releasing worker param %d\n", i); release_ref(worker->params[i]); } release_program_ref(worker->def->program); } #ifdef GUI_LIB else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW) { release_ref(((vis_window *)adatum->c.generic.data)->title); release_ref(((vis_window *)adatum->c.generic.data)->widget_dict); release_ref(((vis_window *)adatum->c.generic.data)->widget_xpos); release_ref(((vis_window *)adatum->c.generic.data)->widget_ypos); release_ref(((vis_window *)adatum->c.generic.data)->id_list); } else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON) { release_ref(((vis_widget *)adatum->c.generic.data)->label); release_ref(((vis_widget *)adatum->c.generic.data)->handler_dict); } #endif VIS_FREE(adatum->c.generic.data, "datum->c.generic.data"); } else if(adatum->company->type_id == BUILTIN_TYPE_NETCLIENT) #ifdef WIN32 closesocket(adatum->c.integers.num_a); #else close(adatum->c.integers.num_a); #endif else if(adatum->company->type_id == BUILTIN_TYPE_PROGRAM) release_program_ref(adatum->c.generic.data); DEBUGPRINTF("Freeing: %X\n",adatum); //free_datum(adatum); free(adatum); } else { VIS_LeaveCriticalSection(adatum->lock); //DEBUGPUTS("left lock"); } VIS_PROFILE_END(PROF_RELEASE); //DEBUGPUTS("exit release_ref\n"); } void datum_set_yesno(datum * adatum, int val) { adatum->c.integers.num_a = val; }