Mercurial > repos > rhope
view file.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 | 20d40cb8abf3 |
children |
line wrap: on
line source
#include "structs.h" #include "datum.h" #include <string.h> #include <stdio.h> #include <stdlib.h> int vis_file_from_string(datum ** inputlist, queue_entry * worker_entry) { datum * output; file_data * file; output = new_datum(BUILTIN_TYPE_FILE, 1, sizeof(file_data), worker_entry->instance->def->program); file = output->c.generic.data; file->shared = malloc(sizeof(shared_file) + inputlist[0]->c.generic.len-1); strcpy(file->shared->name, inputlist[0]->c.generic.data); DEBUGPRINTF("File from string name: %s\n", file->shared->name); release_ref(inputlist[0]); file->shared->status = FILE_NOSIZE; VIS_InitializeCriticalSection(file->shared->lock); file->shared->ref_count = 1; file->offset = 0; inputlist[0] = output; return 0; } void vis_file_read_open_check(file_data * file) { switch(file->shared->status) { case FILE_NOSIZE: case FILE_CLOSED: DEBUGPUTS("File is closed, opening...\n"); DEBUGPRINTF("File name: %s\n", file->shared->name); file->shared->file = fopen(file->shared->name, "rb"); if(!file->shared->file) { file->shared->status = FILE_CANT_OPEN; file->shared->size = 0; break; } if(file->shared->status == FILE_NOSIZE) { DEBUGPUTS("Getting file size.\n"); fseek(file->shared->file, 0, SEEK_END); file->shared->size = ftell(file->shared->file); DEBUGPRINTF("File size: %d.\n", file->shared->size); } file->shared->status = FILE_READ; break; default://file is already open break; } DEBUGPRINTF("Seeking to %d\n", file->offset); if(file->shared->file) fseek(file->shared->file, file->offset, SEEK_SET); DEBUGPUTS("Done.\n"); } int vis_file_get_fstring(datum ** inputlist, queue_entry * worker_entry) { file_data * file; datum * output = new_datum(BUILTIN_TYPE_STRING, 1, inputlist[1]->c.integers.num_a+1, worker_entry->instance->def->program); inputlist[0] = copy_datum(inputlist[0], 0); if(inputlist[1]->c.integers.num_a > 0) { file = (file_data *)inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); vis_file_read_open_check(file); fread(output->c.generic.data,1,inputlist[1]->c.integers.num_a, file->shared->file); VIS_LeaveCriticalSection(file->shared->lock); file->offset += inputlist[1]->c.integers.num_a; } ((char *)output->c.generic.data)[inputlist[1]->c.integers.num_a] = '\0'; release_ref(inputlist[1]); inputlist[1] = output; return 0; } #define FILE_SEARCH_BUFFER_SIZE 512 typedef struct bufferlist { char buffer[FILE_SEARCH_BUFFER_SIZE]; int index; struct bufferlist * next; } bufferlist; int vis_file_get_dstring(datum ** inputlist, queue_entry * worker_entry) { BOOL found = FALSE; bufferlist buffers; bufferlist * current, *temp,*temp2; int i,j,k,startk; int found_entry; int string_offset; int search_offset; bufferlist * search_start; int search_start_offset; int *search_offsets; bufferlist ** search_starts; int *search_start_offsets; int read_bytes; list_data * list; file_data * file; inputlist[0] = copy_datum(inputlist[0], 0); file = (file_data *)inputlist[0]->c.generic.data; buffers.next = NULL; DEBUGPUTS("Entering critical section.\n"); VIS_EnterCriticalSection(file->shared->lock); if(file->offset >= file->shared->size) { VIS_LeaveCriticalSection(file->shared->lock); release_ref(inputlist[0]); release_ref(inputlist[1]); inputlist[0] = inputlist[1] = inputlist[2] = NULL; inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[3], 1); return 0; } if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST) { list = ((list_data *)inputlist[1]->c.generic.data); DEBUGPRINTF("Delimeter input is a list with %d entries.\n", list->num_entries); search_offsets = malloc(sizeof(int) * (list->num_entries)); DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries)); search_starts = malloc(sizeof(bufferlist *) * (list->num_entries)); DEBUGPRINTF("Allocated %d bytes.\n", sizeof(bufferlist *) * (list->num_entries)); search_start_offsets = malloc(sizeof(int) * (list->num_entries)); DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries)); for(i = 0; i < list->num_entries; ++i) { DEBUGPRINTF("Setting search_offsets[%d] = 0.\n", i); search_offsets[i] = 0; } } search_offset = 0; current = &buffers; current->index = 0; DEBUGPUTS("In critical section.\n"); vis_file_read_open_check(file); DEBUGPUTS("File open."); while(!found && !feof(file->shared->file)) { DEBUGPRINTF("Reading %d bytes from file\n", FILE_SEARCH_BUFFER_SIZE); read_bytes = fread(current->buffer, 1, FILE_SEARCH_BUFFER_SIZE, file->shared->file); DEBUGPRINTF("fread read %d bytes\n", read_bytes); for(i = 0; i < read_bytes && !found; ++i) { DEBUGPRINTF("Checking character #%d (%c)\n", i, current->buffer[i]); switch(inputlist[1]->company->type_id) { case BUILTIN_TYPE_WHOLE: if((int)current->buffer[i] == inputlist[1]->c.integers.num_a) { found = TRUE; search_offset = 1; search_start = current; search_start_offset = i; } break; case BUILTIN_TYPE_STRING: if(current->buffer[i] == ((char *)inputlist[1]->c.generic.data)[search_offset]) { if(search_offset == 0) { search_start = current; search_start_offset = i; } ++search_offset; if(search_offset == (inputlist[1]->c.generic.len-1)) found = TRUE; } else { if(search_offset > 0) { current = search_start; i = search_start_offset; } search_offset = 0; } break; case BUILTIN_TYPE_LIST: for(j = 0; j < list->num_entries; ++j) { DEBUGPRINTF("Testing list entry %d against character %d in buffer %d\n", j, i, current->index); if(list->entries[j]->company->type_id == BUILTIN_TYPE_WHOLE && (int)current->buffer[i] == list->entries[j]->c.integers.num_a) { DEBUGPUTS("Matched whole number entry.\n"); found = TRUE; found_entry = j; search_offset = 1; search_start = current; search_start_offset = i; break; } else if(list->entries[j]->company->type_id == BUILTIN_TYPE_STRING) { DEBUGPUTS("String entry.\n"); if(current->buffer[i] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]]) { DEBUGPRINTF("%c in buffer matches character #%d in entry.\n", current->buffer[i], search_offsets[j]); if(search_offsets[j] == 0) { search_starts[j] = current; search_start_offsets[j] = i; } ++search_offsets[j]; if(search_offsets[j] == (list->entries[j]->c.generic.len-1)) { DEBUGPUTS("Entire string matched.\n"); found = TRUE; found_entry = j; search_offset = search_offsets[j]; search_start = search_starts[j]; search_start_offset = search_start_offsets[j]; break; } } else if(search_offsets[j] > 0) { DEBUGPRINTF("%c in bufer does not match character #%d in entry.\n", current->buffer[i], search_offsets[j]); temp = search_starts[j]; search_offsets[j] = 0; startk = search_start_offsets[j]; while(temp && !found) { DEBUGPRINTF("Scanning block %d for possible missed match from %d to %d.\n", temp->index, startk, (temp == current ? i : FILE_SEARCH_BUFFER_SIZE)-1); for(k = startk; k < (temp == current ? i : FILE_SEARCH_BUFFER_SIZE); ++k) { if(temp->buffer[k] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]]) { if(!search_offsets[j]) { search_starts[j] = temp; search_start_offsets[j] = k; } ++search_offsets[j]; if(search_offset == (list->entries[j]->c.generic.len-1)) { found = TRUE; found_entry = j; search_start = search_starts[j]; search_start_offset = search_start_offsets[j]; } } else { if(search_offsets[j] > 0) { temp = search_starts[j]; k = search_start_offsets[j]; } search_offsets[j] = 0; } } startk = 0; temp = temp->next; } } else search_offsets[j] = 0; } } break; } } if(!found && !feof(file->shared->file)) { current->next = malloc(sizeof(bufferlist)); DEBUGPRINTF("Allocated next buffer at %X (%d bytes)\n", current->next, sizeof(bufferlist)); current->next->index = current->index+1; current->next->next = NULL; current = current->next; } } VIS_LeaveCriticalSection(file->shared->lock); if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST) { VIS_FREE(search_offsets, "Get DString@File, search offsets"); VIS_FREE(search_starts, "Get DString@File, search starts"); VIS_FREE(search_start_offsets, "Get DString@File, search start offsets"); } if(found) { DEBUGPUTS("Found a delimeter"); if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST) { inputlist[2] = add_ref(list->entries[found_entry]); release_ref(inputlist[1]); } else inputlist[2] = inputlist[1]; inputlist[3] = NULL; } else { DEBUGPUTS("Didn't find a delimeter"); release_ref(inputlist[1]); inputlist[2] = NULL; inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[3], 0); } //Does this need to be here still or was it just working around another bug? if(search_start_offset < 0) search_start_offset = 0; if(!found) { search_start = current; search_start_offset = i; } if(found) { inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset+1, worker_entry->instance->def->program); //file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset + search_offset; file->offset += FILE_SEARCH_BUFFER_SIZE * search_start->index + search_start_offset + search_offset; } else { inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes+1, worker_entry->instance->def->program); file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes; } temp = &buffers; string_offset = 0; while(temp) { DEBUGPRINTF("Copying from index %d to offset %X\n", temp->index, string_offset); if(temp == search_start) { //if(found) //{ temp->buffer[search_start_offset] = '\0'; memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, search_start_offset); string_offset += search_start_offset; /*} else { memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, i); string_offset += i; }*/ break; } else { memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, FILE_SEARCH_BUFFER_SIZE); string_offset += FILE_SEARCH_BUFFER_SIZE; } if(temp != &buffers) { temp2 = temp->next; VIS_FREE(temp, "Get DString@File, buffer node"); temp = temp2; } else temp = temp->next; } while(temp) { if(temp != &buffers) { temp2 = temp->next; DEBUGPRINTF("Freeing %X\n", temp); VIS_FREE(temp, "Get DString@File, buffer node"); temp = temp2; } else temp = temp->next; } ((char *)inputlist[1]->c.generic.data)[string_offset] = '\0'; DEBUGPRINTF("Output string: %s\n", inputlist[1]->c.generic.data); return 0; } int vis_file_get_byte(datum ** inputlist, queue_entry * worker_entry) { file_data * file; BOOL eof; char num; inputlist[0] = copy_datum(inputlist[0], 0); file = (file_data *)inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); if(!(eof = (file->offset >= file->shared->size))) { vis_file_read_open_check(file); fread(&num,sizeof(char),1, file->shared->file); } VIS_LeaveCriticalSection(file->shared->lock); if(eof) { release_ref(inputlist[0]); inputlist[0] = inputlist[1] = NULL; inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[2], 1); } else { inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = num; inputlist[2] = NULL; file->offset += sizeof(char); } return 0; } int vis_file_get_word(datum ** inputlist, queue_entry * worker_entry) { file_data * file; BOOL eof; short num; inputlist[0] = copy_datum(inputlist[0], 0); file = (file_data *)inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); if(!(eof = (file->offset >= file->shared->size))) { vis_file_read_open_check(file); fread(&num,sizeof(short),1, file->shared->file); } VIS_LeaveCriticalSection(file->shared->lock); if(eof) { release_ref(inputlist[0]); inputlist[0] = inputlist[1] = NULL; inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[2], 1); } else { inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = num; inputlist[2] = NULL; file->offset += sizeof(short); } return 0; } int vis_file_get_long(datum ** inputlist, queue_entry * worker_entry) { file_data * file; BOOL eof; long num; inputlist[0] = copy_datum(inputlist[0], 0); file = (file_data *)inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); if(!(eof = (file->offset >= file->shared->size))) { vis_file_read_open_check(file); fread(&num,sizeof(long),1, file->shared->file); } VIS_LeaveCriticalSection(file->shared->lock); if(eof) { release_ref(inputlist[0]); inputlist[0] = inputlist[1] = NULL; inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[2], 1); } else { inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = num; inputlist[2] = NULL; file->offset += sizeof(long); } return 0; } int vis_file_get_double(datum ** inputlist, queue_entry * worker_entry) { file_data * file; BOOL eof; double num; inputlist[0] = copy_datum(inputlist[0], 0); file = (file_data *)inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); if(!(eof = (file->offset >= file->shared->size))) { vis_file_read_open_check(file); fread(&num,sizeof(num),1, file->shared->file); } VIS_LeaveCriticalSection(file->shared->lock); if(eof) { release_ref(inputlist[0]); inputlist[0] = inputlist[1] = NULL; inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); datum_set_yesno(inputlist[2], 1); } else { inputlist[1] = new_datum(BUILTIN_TYPE_REAL, 3, 0, worker_entry->instance->def->program); inputlist[1]->c.real = num; inputlist[2] = NULL; file->offset += sizeof(num); } return 0; } void vis_file_write_open_check(file_data * file) { switch(file->shared->status) { case FILE_READ: fclose(file->shared->file); case FILE_NOSIZE: case FILE_CLOSED: DEBUGPUTS("File is closed, opening...\n"); DEBUGPRINTF("File name: %s\n", file->shared->name); file->shared->file = fopen(file->shared->name, "r+b"); if(!file->shared->file) file->shared->file = fopen(file->shared->name,"w+b"); if(!file->shared->file) { file->shared->status = FILE_CANT_OPEN; file->shared->size = 0; break; } if(file->shared->status == FILE_NOSIZE) { DEBUGPUTS("Getting file size.\n"); fseek(file->shared->file, 0, SEEK_END); file->shared->size = ftell(file->shared->file); DEBUGPRINTF("File size: %d.\n", file->shared->size); } file->shared->status = FILE_WRITE; break; default://file is already open break; } DEBUGPRINTF("Seeking to %d\n", file->offset); if(file->shared->file) fseek(file->shared->file, file->offset, SEEK_SET); DEBUGPUTS("Done.\n"); } int vis_file_put_string(datum ** inputlist, queue_entry * worker_entry) { file_data * file; int written; inputlist[0] = copy_datum(inputlist[0], 0); file = ((file_data *)inputlist[0]->c.generic.data); VIS_EnterCriticalSection(file->shared->lock); vis_file_write_open_check(file); written = fwrite(inputlist[1]->c.generic.data,1,inputlist[1]->c.generic.len-1,file->shared->file); file->offset += written; if(file->offset > file->shared->size) file->shared->size = file->offset; VIS_LeaveCriticalSection(file->shared->lock); release_ref(inputlist[1]); return 0; } int vis_file_length(datum ** inputlist, queue_entry * worker_entry) { file_data * file; int written; int size; file = ((file_data *)inputlist[0]->c.generic.data); VIS_EnterCriticalSection(file->shared->lock); vis_file_read_open_check(file); size = file->shared->size; VIS_LeaveCriticalSection(file->shared->lock); release_ref(inputlist[0]); inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[0]->c.integers.num_a = size; return 0; } int vis_file_truncate(datum ** inputlist, queue_entry * worker_entry) { file_data * file; inputlist[0] = copy_datum(inputlist[0], 0); file = inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); switch(file->shared->status) { case FILE_READ: case FILE_WRITE: fclose(file->shared->file); default: break; } file->shared->file = fopen(file->shared->name,"wb"); file->shared->size = 0; file->shared->status = FILE_WRITE; VIS_LeaveCriticalSection(file->shared->lock); file->offset = 0; return 0; }