Mercurial > repos > rhope
diff parser.c @ 0:76568becd6d6
Rhope Alpha 2a source import
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 28 Apr 2009 23:06:07 +0000 |
parents | |
children | 9749109b3198 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser.c Tue Apr 28 23:06:07 2009 +0000 @@ -0,0 +1,1633 @@ +#include "structs.h" +#include "visuality.h" +#include "debugmacros.h" +#ifdef WIN32 + #include "windows.h" +#endif +#include <stdio.h> +#include "interp.h" +#include "parser.h" +#include <string.h> +#include <stdlib.h> + +extern int num_workers; +extern int num_wires; + +/*#ifdef SEGA +#define NUM_WORKERS_START 40 +#define NUM_WIRES_START 80 +#else +#define NUM_WORKERS_START 1024 +#define NUM_WIRES_START 2048 +#endif*/ +#define NUM_WORKERS_START 20 +#define NUM_WIRES_START 40 +//TODO: Figure out why setting those defines to 16 and 32 respectively causes problems + +BOOL is_whitespace(char c) +{ + if(c == ' ' || c == '\t' || c == '\n' || c == '\r') + return TRUE; + return FALSE; +} + +company * create_company(program * prog, char * name, int num_workers, int num_rooms, BOOL buildable) +{ + company * this_comp = &(prog->companylist[prog->num_companies]); + DEBUGPRINTF("create_company %s with %d workers and %d rooms\n", name, num_workers, num_rooms); + this_comp->type_id = prog->num_companies++; + strncpy(this_comp->name, name, 256); + this_comp->name[255] = '\0'; + if(num_workers) + this_comp->methodlist = MALLOC(sizeof(worker_def *) * num_workers, "company methodlist"); + else + this_comp->methodlist = NULL; + this_comp->num_methods = 0;//num_workers; + this_comp->method_storage = num_workers; + if(num_rooms) + { + this_comp->room_list = MALLOC(sizeof(company_room) * num_rooms, "company roomlist"); + DEBUGPRINTF("Allocated %d bytes at %X for room_list\n", sizeof(company_room) * num_rooms, this_comp->room_list); + } + else + this_comp->room_list = NULL; + this_comp->num_rooms = 0;//num_rooms; + this_comp->room_storage = num_rooms; + if(buildable) + this_comp->build_size = 0; + else + this_comp->build_size = -1; + VIS_InitializeCriticalSection(this_comp->lock); + return this_comp; +} + +int add_method(company * this_comp, worker_def * def) +{ + worker_def ** temp; + int i; + DEBUGPUTS("add_method: "); + DEBUGPRINTF("%s\n", def->name); + VIS_EnterCriticalSection(this_comp->lock); + if(this_comp->method_storage - this_comp->num_methods <= 0) + { + if(this_comp->method_storage < 2) + this_comp->method_storage = 4; + else + this_comp->method_storage = this_comp->method_storage + ((this_comp->method_storage) >> 1); + temp = MALLOC(sizeof(worker_def *) * this_comp->method_storage, "company method storage"); + for(i = 0; i < this_comp->num_methods; ++i) + temp[i] = this_comp->methodlist[i]; + VIS_FREE(this_comp->methodlist, "company methodlist"); + this_comp->methodlist = temp; + } + i = this_comp->num_methods; + this_comp->methodlist[this_comp->num_methods++] = def; + DEBUGPRINTF("%s now has %d methods\n", this_comp->name, this_comp->num_methods); + VIS_LeaveCriticalSection(this_comp->lock); + return i; +} +int room_build_sizes[] = {0, sizeof(char), sizeof(short), sizeof(long), sizeof(float), sizeof(double), -1, -1, -1, -1, -1, sizeof(datum *), 0}; +int add_comp_room(company * this_comp, char * name, int set_func, int get_func, short set_func_type, short get_func_type) +{ + company_room * temp; + int i; + int min_build_size; + VIS_EnterCriticalSection(this_comp->lock); + DEBUGPRINTF("add_comp_room: %s", name); + DEBUGPRINTF(", num_rooms: %d, room_storage: %d\n", this_comp->num_rooms, this_comp->room_storage); + if(this_comp->room_storage - this_comp->num_rooms <= 0) + { + if(this_comp->room_storage < 2) + this_comp->room_storage = 4; + else + this_comp->room_storage = this_comp->room_storage + ((this_comp->room_storage) >> 1); + temp = MALLOC(sizeof(company_room) * this_comp->room_storage, "company room storage"); + memcpy(temp, this_comp->room_list, sizeof(company_room)*this_comp->num_rooms); + VIS_FREE(this_comp->room_list, "company room list"); + this_comp->room_list = temp; + } + if(this_comp->build_size >= 0) + { + DEBUGPRINTF("get_func_type: %d, room_build_sizes[%d] = %d\n", get_func_type, get_func_type, room_build_sizes[get_func_type]); + if(get_func_type && get_func_type != ROOM_WORKER && get_func == -1) + get_func = this_comp->build_size; + if(set_func_type && set_func_type != ROOM_WORKER && set_func == -1) + set_func = this_comp->build_size; + if(room_build_sizes[set_func_type]) + if(room_build_sizes[set_func_type] > room_build_sizes[get_func_type]) + min_build_size = room_build_sizes[set_func_type] + set_func; + else + min_build_size = room_build_sizes[get_func_type] + get_func; + else if(room_build_sizes[get_func_type]) + min_build_size = room_build_sizes[get_func_type] + get_func; + if(min_build_size > this_comp->build_size) + this_comp->build_size = min_build_size; + } + i = this_comp->num_rooms; + DEBUGPUTS("Copying name\n"); + this_comp->room_list[this_comp->num_rooms++].name = MALLOC(strlen(name) + 1, "company room name"); + strcpy(this_comp->room_list[i].name, name); + DEBUGPUTS("Setting func types\n"); + this_comp->room_list[i].set_func_type = set_func_type; + this_comp->room_list[i].get_func_type = get_func_type; + DEBUGPRINTF("Setting funcs: get = %d, set = %d\n", get_func, set_func); + //TODO: Change the signature of this function so that get_func and set_func are void * so we can safely pass in pointers for future get_func types + this_comp->room_list[i].get_func = (void *)get_func; + this_comp->room_list[i].set_func = (void *)set_func; + DEBUGPRINTF("Build size is now: %d\n", this_comp->build_size); + DEBUGPUTS("before return\n"); + VIS_LeaveCriticalSection(this_comp->lock); + return i; +} + +worker_def * create_worker(program * prog, char * name, int num_inputs, int num_outputs, short type) +{ + custom_worker * aworker; + int i, j; + int thisdef; + worker_def * deflist; + DEBUGPRINTF("create_worker: %s with %d inputs and %d outputs\n", name, num_inputs, num_outputs); + if(!strcmp(name, "Main")) + { + thisdef = 0; + deflist = prog->defs->deflist; + } + else + { + if(prog->current->num_defs >= prog->current->defs_storage) { + prog->current->next = MALLOC(sizeof(defchunk) + (START_DEF_STORAGE - 1) * sizeof(worker_def), "worker def storage"); + prog->current = prog->current->next; + prog->current->defs_storage = START_DEF_STORAGE; + prog->current->num_defs = 0; + prog->current->next = NULL; + } + if(prog->current == prog->defs && prog->current->num_defs == 0) + prog->current->num_defs = 1; + thisdef = prog->current->num_defs; + deflist = prog->current->deflist; + } + DEBUGPRINTF("new deflist index: %d\n", thisdef); + if(type & USER_FLAG && (type & TYPE_MASK) == WORKER_TYPE) + { + //puts("Creating custom worker."); + aworker = MALLOC(sizeof(custom_worker), "custom worker implementation"); + aworker->num_workers = 0; + aworker->num_wires = 0; + aworker->workerlist = MALLOC(sizeof(worker)*NUM_WORKERS_START, "custom worker workerlist"); + aworker->worker_storage = NUM_WORKERS_START; + aworker->wirelist = MALLOC(sizeof(wire)*NUM_WIRES_START, "custom worker wirelist"); + aworker->wire_storage = NUM_WIRES_START; + aworker->workers_to_wires_up = MALLOC(sizeof(int)*(NUM_WIRES_START+1),"custom worker workers to wires up"); + aworker->workers_to_wires_down = MALLOC(sizeof(int)*(NUM_WIRES_START+1),"custom worker workers to wires down"); + aworker->dirty = TRUE; + VIS_InitializeCriticalSection(aworker->lock); + deflist[thisdef].implement_func = aworker; + } + DEBUGPUTS("Setting properties\n"); + deflist[thisdef].num_inputs = num_inputs; + deflist[thisdef].num_outputs = num_outputs; + deflist[thisdef].type = type; + DEBUGPUTS("Calling malloc\n"); + deflist[thisdef].name = MALLOC(strlen(name)+1, "worker def name"); + DEBUGPRINTF("malloc return: %X, calling strcpy\n", deflist[thisdef].name); + strcpy(deflist[thisdef].name, name); + DEBUGPUTS("strcpy done\n"); + + if(num_inputs) + deflist[thisdef].input_types = MALLOC(sizeof(short) * num_inputs, "worker def input types"); + else + deflist[thisdef].input_types = NULL; + if(num_outputs) + deflist[thisdef].output_types = MALLOC(sizeof(short) * num_outputs, "worker def output types"); + else + deflist[thisdef].output_types = NULL; + for(i = 0; i < num_inputs; ++i) + deflist[thisdef].input_types[i] = ANY_TYPE; + deflist[thisdef].num_stores = 0; + deflist[thisdef].uses_stores = NULL; + deflist[thisdef].transaction_flags = TRANSACTION_RETRY; + if(thisdef >= prog->current->num_defs) + prog->current->num_defs = thisdef+1; + for(i = 0; name[i] != '\0'; ++i) + { + if(name[i] == '@') + { + DEBUGPRINTF("Name ends in %s\n", name+i); + for(j = 0; j < prog->num_companies; ++j) + { + if(!strcmp(name+i+1, prog->companylist[j].name)) + { + DEBUGPRINTF("Worker is a method of company %d, ", j); + DEBUGPRINTF("%s\n", prog->companylist[j].name); + add_method(prog->companylist+j, deflist+thisdef); + break; + } + } + break; + } + } + deflist[thisdef].program = prog; + return deflist + thisdef; +} + +int find_worker(char * name, int * num_inputs, int * num_outputs, program * prog, worker_def ** def) +{ + int i; + int term; + int len; + defchunk * current; + worker_def * temp; + DEBUGPRINTF("Calling strlen on name: %X\n", name); + len = strlen(name); + DEBUGPRINTF("find_worker: %s\n", name); + if(len >= 2 && !strcmp(name+len-2, ">>")) + { + DEBUGPUTS("Get property\n"); + term = len-2; + for(i = term-1; i > 0; --i) + { + if(name[i] == ' ') + term = i; + else + break; + } + DEBUGPRINTF("term: %d\n", term); + name[term] = '\0'; + DEBUGPRINTF("name: %s\n", name); + if(num_inputs); + *num_inputs = 1; + if(num_outputs) + *num_outputs = 1; + return -1; + } + if(len >= 2 && !strcmp(name+len-2, "<<")) + { + DEBUGPUTS("Set property\n"); + term = len-2; + for(i = term-1; i > 0; --i) + { + if(name[i] == ' ') + term = i; + else + break; + } + DEBUGPRINTF("term: %d\n", term); + name[term] = '\0'; + DEBUGPRINTF("name: %s\n", name); + if(num_inputs); + *num_inputs = 2; + if(num_outputs) + *num_outputs = 1; + return -2; + } + current = prog->defs; + while(current) + { + for(i = 0; i < current->num_defs; ++i) + { + if(current->deflist[i].name && !strcmp(current->deflist[i].name, name)) + { + DEBUGPRINTF("Found worker #%d\n", i); + if(num_inputs) + *num_inputs = current->deflist[i].num_inputs; + if(num_outputs) + *num_outputs = current->deflist[i].num_outputs; + if(def) + *def = current->deflist + i; + return i; + } + } + current = current->next; + } + if(num_inputs && num_outputs) + { + for(i = 1; i < prog->num_companies; ++i) + { + temp = find_method(i, name, *num_inputs, prog); + if(temp && temp->num_outputs >= *num_outputs) + { + *def = create_worker(prog, name, temp->num_inputs, temp->num_outputs, MAGIC_TYPE); + return 1; + } + } + } + else + { + for(i = 1; i < prog->num_companies; ++i) + { + temp = find_method_noinputcheck(i, name, prog); + if(temp) + { + *def = create_worker(prog, name, temp->num_inputs, temp->num_outputs, MAGIC_TYPE); + return 1; + } + } + } + DEBUGPUTS("Could not find worker\n"); + return -3; +} + +int generic_add_to_def(worker_def * parent, char * name,int display_type, int type, int num_inputs, int num_outputs, double xpos, double ypos) +{ + int returnval; + worker * temp; + VIS_EnterCriticalSection(parent->implement_func->lock); + if(parent->implement_func->num_workers >= parent->implement_func->worker_storage) { + parent->implement_func->worker_storage = parent->implement_func->num_workers + (parent->implement_func->num_workers >> 1); + parent->implement_func->workerlist = realloc(parent->implement_func->workerlist, parent->implement_func->worker_storage * sizeof(worker)); + } + strcpy(parent->implement_func->workerlist[parent->implement_func->num_workers].name, name); + parent->implement_func->workerlist[parent->implement_func->num_workers].type=type; + parent->implement_func->workerlist[parent->implement_func->num_workers].num_inputs = num_inputs; + parent->implement_func->workerlist[parent->implement_func->num_workers].num_outputs = num_outputs; + parent->implement_func->workerlist[parent->implement_func->num_workers].null_input = FALSE; + parent->implement_func->workerlist[parent->implement_func->num_workers].magic_cache_implement = NULL; + parent->implement_func->workerlist[parent->implement_func->num_workers].magic_cache_type = 0; + VIS_InitializeCriticalSection(parent->implement_func->workerlist[parent->implement_func->num_workers].lock); + parent->implement_func->dirty = TRUE; + //puts("end generic_add_to_def"); + DEBUGPRINTF("generic_add_to_def: %s with type %d and num_inputs %d and num_outputs %d returned %d\n", name, type, num_inputs, num_outputs, parent->implement_func->num_workers); + returnval = parent->implement_func->num_workers++; + VIS_LeaveCriticalSection(parent->implement_func->lock); + return returnval; +} + +int add_worker_to_def(worker_def * parent, worker_def * worker, double xpos, double ypos) +{ + int list_index; + list_index = generic_add_to_def(parent, worker->name, TRAPEZOID, WORKER, worker->num_inputs, worker->num_outputs, xpos, ypos); + + parent->implement_func->workerlist[list_index].value_index = worker; + return list_index; +} + +int add_get_comp_room(worker_def * parent, char * name, double xpos, double ypos) +{ + return generic_add_to_def(parent, name, RECTANGLE, GET_COMP, 1, 2, xpos, ypos); +} + +int add_set_comp_room(worker_def * parent, char * name, double xpos, double ypos) +{ + return generic_add_to_def(parent, name, RECTANGLE, SET_COMP, 2, 1, xpos, ypos); +} + +int add_global(worker_def * parent, char * name, double xpos, double ypos, int type) +{ + int i,j; + int thisdef; + int num_in, num_out; + if(type == SET_GLOBAL) + { + num_in = 1; + num_out = 0; + parent->transaction_flags |= TRANSACTION_WRITE; + } + else + { + num_in = 0; + num_out = 1; + } + thisdef = generic_add_to_def(parent, name, RECTANGLE, type, num_in, num_out, xpos, ypos); + for(i = 0; name[i+1] != '\0'; ++i) + { + if(name[i] == ':' && name[i+1] == ':') + { + parent->implement_func->workerlist[thisdef].value_index = (void *)-1; + if(i > 0) + { + for(j = 0; j < parent->num_stores; ++j) + { + if(strlen(parent->uses_stores[j]) == i && !memcmp(parent->uses_stores[j], name, i)) + { + parent->implement_func->workerlist[thisdef].value_index = (void *)j; + break; + } + } + if(parent->implement_func->workerlist[thisdef].value_index < 0) + { + name[i] = '\0'; + printf("Error: Worker %s is not declared to use global store %s but references it.\n", parent->name, name); + exit(-1); + } + } + else if(type == SET_GLOBAL) + parent->implement_func->workerlist[thisdef].value_index = 0; + parent->implement_func->workerlist[thisdef].io_num = i+2; + break; + } + } + return thisdef; +} + +int add_global_get(worker_def * parent, char * name, double xpos, double ypos) +{ + return add_global(parent, name, xpos, ypos, GET_GLOBAL); +} + +int add_global_set(worker_def * parent, char * name, double xpos, double ypos) +{ + return add_global(parent, name, xpos, ypos, SET_GLOBAL); +} + +int find_object(worker_def * def, char * name, int type) +{ + int i; + for(i = 0; i < def->implement_func->num_workers; ++i) + if(!strcmp(def->implement_func->workerlist[i].name, name) && def->implement_func->workerlist[i].type == 1) + break; + if(i < def->implement_func->num_workers) + return i; + return -1; +} + +int create_find_room(worker_def * def, char * name, double xpos, double ypos) +{ + int found = find_object(def, name, ROOM); + if(found >= 0) + return found; + return generic_add_to_def(def, name, RECTANGLE, ROOM, 1, 1, xpos, ypos); +} + +int add_constant(worker_def * def, char * value, double xpos, double ypos) +{ + int index = generic_add_to_def(def, value, RECTANGLE, CONSTANT, 0, 1, xpos, ypos); + def->implement_func->workerlist[index].value_index = get_constant(value, -1, def->program); + return index; +} + +int add_input_num(worker_def * def, char * name, int input_num, double xpos, double ypos) +{ + int i; + unsigned short * temp_types; + int found; + if(def->num_inputs <= input_num) + { + temp_types = def->input_types; + def->input_types = MALLOC(sizeof(short)*(input_num+1), "worker def input types"); + if(temp_types) { + memcpy(def->input_types, temp_types, sizeof(short)*def->num_inputs); + VIS_FREE(temp_types, "temp types?"); + } + for(i = def->num_inputs; i <= input_num; ++i) + def->input_types[i] = ANY_TYPE; + def->num_inputs = input_num+1; + } + found = generic_add_to_def(def, name, RECTANGLE, INPUT, 0, 1, xpos, ypos); + def->implement_func->workerlist[found].io_num = input_num; + return found; +} +int add_input(worker_def * def, char * name, double xpos, double ypos) +{ + + int input_num; + int i; + for(i = 0; name[i] != 0; ++i) + if(name[i] == '(') + { + input_num = atol(name+i+1); + break; + } + return add_input_num(def, name, input_num, xpos, ypos); +} + +int add_output_num(worker_def * def, char * name, int output_num, double xpos, double ypos) +{ + int i; + unsigned short * temp_types; + int found; + if(def->num_outputs <= output_num) + { + temp_types = def->output_types; + def->output_types = MALLOC(sizeof(short)*(output_num+1), "worker def output types"); + if(temp_types) + { + memcpy(def->output_types, temp_types, sizeof(short)*def->num_outputs); + VIS_FREE(temp_types, "temp types?"); + } + for(i = def->num_outputs; i <= output_num; ++i) + def->output_types[i] = ANY_TYPE; + def->num_outputs = output_num+1; + } + found = generic_add_to_def(def, name, RECTANGLE, OUTPUT, 1, 0, xpos, ypos); + def->implement_func->workerlist[found].io_num = output_num; + return found; +} +int add_output(worker_def * def, char * name, double xpos, double ypos) +{ + int output_num; + int i; + + for(i = 0; name[i] != 0; ++i) + if(name[i] == '(') + { + output_num = atol(name+i+1); + break; + } + return add_output_num(def, name, output_num, xpos, ypos); +} + +int create_find_output(worker_def * def, char * name, double xpos, double ypos) +{ + int output_num; + int i; + unsigned short * temp_types; + int found = find_object(def, name, OUTPUT); + if(found >= 0) + return found; + return add_output(def, name, xpos, ypos); +} + +void add_wire(worker_def * def, int start, int output_num, int end, int input_num) +{ + VIS_EnterCriticalSection(def->implement_func->lock); + if(def->implement_func->num_wires >= def->implement_func->wire_storage) { + def->implement_func->wire_storage = def->implement_func->num_wires + (def->implement_func->num_wires >> 1); + def->implement_func->wirelist = realloc(def->implement_func->wirelist, def->implement_func->wire_storage * sizeof(wire)); + def->implement_func->workers_to_wires_up = realloc(def->implement_func->workers_to_wires_up, (def->implement_func->wire_storage+1) * sizeof(int)); + def->implement_func->workers_to_wires_down = realloc(def->implement_func->workers_to_wires_down, (def->implement_func->wire_storage+1) * sizeof(int)); + } + def->implement_func->wirelist[def->implement_func->num_wires].start_worker = start; + def->implement_func->wirelist[def->implement_func->num_wires].end_worker = end; + def->implement_func->wirelist[def->implement_func->num_wires].output_num = output_num; + def->implement_func->wirelist[def->implement_func->num_wires].input_num = input_num; + def->implement_func->dirty = TRUE; + ++def->implement_func->num_wires; + if(input_num == -1) + { + def->implement_func->workerlist[end].null_input = TRUE; + } + VIS_LeaveCriticalSection(def->implement_func->lock); +} + +int process_expression(worker_def * def, int num_outputs, char ** outvars, int num_inputs, char ** inputs, char * workername, BOOL worker_expr, int block_depth, int * block_workers, int * block_output, int last_worker) +{ + int i,j; + int current; + int this_worker;// = ++return_worker; + int expected_in, expected_out; + int input_num=-1; + int worker_num; + worker_def * call_def; + BOOL block_attach=FALSE; + BOOL room = FALSE; + BOOL global_flag; + if(worker_expr) + { + DEBUGPUTS("calling find_worker\n"); + expected_in = num_inputs; + expected_out = num_outputs; + worker_num = find_worker(workername, &expected_in, &expected_out, def->program, &call_def); + DEBUGPRINTF("\nWorker %s with %d inputs and %d outputs expects %d inputs and %d outputs\n", workername, num_inputs, num_outputs, expected_in, expected_out); + if(worker_num >= 0) + this_worker = add_worker_to_def(def, call_def, 1.0, 1.0); + else if(worker_num == -1) + this_worker = add_get_comp_room(def, workername, 1.0, 1.0); + else if(worker_num == -2) + this_worker = add_set_comp_room(def, workername, 1.0, 1.0); + else + { + ERRORPRINTF("Could not find a worker named %s or a method of the same name with %d inputs and at least %d outputs\n", workername, num_inputs, num_outputs); + for(i = 0; i < num_inputs; ++i) + { + ERRORPRINTF("Input %d was %s\n", i, inputs[i]); + } + exit(-1); + } + } + else + { + if(workername[0] == '{' || workername[0] == '"' || (workername[0] >= '0' && workername[0] <= '9') || strcmp(workername, "Yes") == 0 || strcmp(workername, "No") == 0) + { + //Constant expression + this_worker = add_constant(def, workername, 1.0, 1.0); + } + /*else if(workername[0] == '"') + { + //printf("\nString %s\n", workername); + workername[strlen(workername)-1] = '\0'; + this_worker = add_constant(def, workername+1, 1.0, 1.0); + } + else if(workername[0] >= '0' && workername[0] <= '9') + { + //printf("\nNumber %s\n", workername); + this_worker = add_constant(def, workername, 1.0, 1.0); + } + else if(strcmp(workername, "Yes") == 0 || strcmp(workername, "No") == 0) + { + this_worker = add_constant(def, workername, 1.0, 1.0); + }*/ + else + { + for(i = 0; workername[i] != 0; ++i) + if(workername[i] == '(') + { + input_num = atol(workername + i+1); + break; + } + if(input_num >= 0) + { + //printf("\nInput %d %s\n", input_num, workername); + this_worker = add_input(def, workername, 1.0, 1.0); + } + else + { + room = TRUE; + //printf("\nRoom %s\n", workername); + for(i = 0; i < strlen(workername)-1; ++i) + { + if(workername[i] == ':' && workername[i+1] == ':') + { + room = FALSE; + break; + } + } + if(room) + this_worker = create_find_room(def, workername, 1.0, 1.0); + else + this_worker = add_global_get(def, workername, 1.0, 1.0); + + } + } + } + for(i = 0; i < num_inputs; ++i) + if(inputs[i]) + { + if(!strcmp(inputs[i], "~")) + { + //printf("Input %d = ~ (parent block)\n", i); + if(!block_depth) + { + printf("Error: Reference to parent block (~) for input %d of worker %s, but block depth is 0", i, workername); + exit(-2); + } + add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, i); + block_attach = TRUE; + } + else + { + DEBUGPRINTF("Processing input %d (%s)\n", i, inputs[i]); + if(block_depth) + current = parse_body(def, inputs[i], strlen(inputs[i]), block_depth, block_output, block_workers); + else + current = parse_body(def, inputs[i], strlen(inputs[i]), 0, NULL, NULL); + add_wire(def, current, 0, this_worker, i); + } + } + else + { + //printf("Input %d = last_worker(%d)\n", i, last_worker); + add_wire(def, last_worker, 0, this_worker, i); + } + for(i = 0; i < num_outputs; ++i) + { + global_flag = FALSE; + //printf("Output %d = %s\n", i, outvars[i]); + for(j = 0; outvars[i][j] != '\0'; ++j) + if(outvars[i][j] == '(') + break; + else if(outvars[i][j] == ':' && outvars[i][j+1] == ':') + break; + if(outvars[i][j] == '\0') + current = create_find_room(def, outvars[i], 2.0, 2.0); + else if(outvars[i][j] == ':') + current = add_global_set(def, outvars[i], 2.0, 2.0); + else + current = create_find_output(def, outvars[i], 2.0, 2.0); + add_wire(def, this_worker, i, current, 0); + } + + //printf("Current blockdepth: %d\n", block_depth); + if(block_depth > 0) + { + //printf("Block Worker: %d\nBlock Output: %d\n", block_workers[block_depth-1], block_output[block_depth-1]); + if(worker_expr && num_inputs < expected_in) + { + if(block_attach) + printf("Warning: Worker %s is attached to block both explicityly and implicity (i.e. at least one input was stated as ~, but there are still unsatisfied inputs)\n", workername); + if(expected_in - num_inputs > 1) + printf("Warning: More than one input of worker %s implicitly tied to block (%d inputs implicitly tied)", workername, expected_in - num_inputs); + for(i = num_inputs; i < expected_in; ++i) + add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, i); + + } + else if(!block_attach && !room) + { + add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, -1); + //def->implement_func->workerlist[this_worker].null_input = TRUE; + } + } + else if(worker_expr && num_inputs < expected_in) + { + ERRORPRINTF("Error: Worker %s expects %d input(s), but was only given %d input(s)\n", workername, expected_in, num_inputs); + exit(-1); + } + //printf("Returning %d\n\n", this_worker); + return this_worker; +} +typedef enum {NULL_STATE, OUT_STATE, BETWEEN_OUT, BEFORE_WORK, PRE_IN_STATE, BETWEEN_PRE_IN, WORK_STATE, IN_STATE, BETWEEN_IN, AFTER_IN, BLOCK_FIND, LINE_COMMENT_STATE} parse_state; +char state_txt[12][20] = {"Null","Out","Between Out","Before Work","Pre Input","Between Pre-Input","Worker","Input","Between Input","After Input","Block Find"}; +int parse_body(worker_def * def, char * code, int len, int prev_block_depth, int * prev_block_output, int * prev_block_workers) +{ + char * outputs[32]; + char * inputs[32]; + char * worker; + short saw_line=0; + int num_inputs=0, num_outputs=0; + int left_bracket=0; + int left_curly=0; + int block_depth = 0; + int block_workers[32]; + int block_output[32]; + int last_worker = 0; + BOOL worker_expr = FALSE; + BOOL in_string = FALSE; + BOOL literal = FALSE; + BOOL do_curly = FALSE; + BOOL saw_newline = FALSE; + int i,j; + int start; + int line_comment_start; + parse_state state = NULL_STATE; + parse_state old_state; + DEBUGPRINTF("code: %X\n", code); + //printf("prev_block_depth: %d\n", prev_block_depth); + for(i=0; i < len; ++i) + { + //printf("i: %d, code[i]: '%c', state: %s(%d)\n", i, code[i], state_txt[state],state); + DEBUGPRINTF("i: %d, code[i]: '%c', state: %s(%d), left_bracket: %d, num_inputs: %d\n", i, code[i], state_txt[state],state, left_bracket, num_inputs); + if(!in_string) + { + if(state != LINE_COMMENT_STATE) + { + if(code[i] == '/' && code[i+1] == '/') + { + old_state = state; + state = LINE_COMMENT_STATE; + line_comment_start = i; + i += 2; + } + else if(code[i] == '[') + ++left_bracket; + else if(code[i] == ']') + --left_bracket; + else if(code[i] == '{') + do_curly = TRUE; + else if(code[i] == '}') + --left_curly; + else if(code[i] == '"') + { + in_string = TRUE; + //continue; + } + } + if(left_curly == 0) + { + switch(state) + { + case NULL_STATE: + + if(code[i] == '[') + { + //puts("worker_expr = TRUE"); + worker_expr = TRUE; + state = BETWEEN_PRE_IN; + } + else if(code[i] == ':' && code[i+1] == '|') + { + ++i; + state = BLOCK_FIND; + } + else if(code[i] == '|' && code[i+1] == ':') + { + block_workers[block_depth] = last_worker; + block_output[block_depth++] = 0; + //puts("Found |: increasing block depth"); + ++i; + } + else if(!is_whitespace(code[i])) + { + start = i; + for(j = i; j < len-1; ++j) + if(code[j] == '<' && code[j+1] == '-') + { + state = OUT_STATE; + --i; + break; + } + else if(code[j] == '[' || code[j] == '\n' || (code[j] == '|' && code[j+1] == ':') || code[j] == '#' || code[j] == '"') + { + state = WORK_STATE; + break; + } + if(state == NULL_STATE) + state = WORK_STATE; + } + break; + case OUT_STATE: + if(code[i] == ',' || (code[i] == '<' && code[i+1] == '-')) + { + outputs[num_outputs++] = code + start; + for(j = i-1; j > start; --j) + if(!is_whitespace(code[j])) + break; + if(code[i] == ',') + state = BETWEEN_OUT; + else + { + state = BEFORE_WORK; + ++i; + } + code[j+1] = '\0'; + } + break; + case BETWEEN_OUT: + if(!is_whitespace(code[i])) + { + start = i; + state = OUT_STATE; + --i; + } + break; + case BEFORE_WORK: + if(code[i] == '[') + { + //puts("worker_expr = TRUE"); + worker_expr = TRUE; + state = BETWEEN_PRE_IN; + } + else if(code[i] == ':' && code[i+1] == '|') + { + start = i; + while(i < len && (code[i] != '\n' || saw_line < 5)) + { + if(code[i] == '\n') + ++saw_line; + ++i; + } + code[i] = '\0'; + ERRORPRINTF("Error: Expected a worker name, but found a closing bracket (:|) instead at:\n%s", code + start); + exit(-1); + } + else if(!is_whitespace(code[i])) + { + start = i; + state = WORK_STATE; + } + break; + case PRE_IN_STATE: + if((code[i] == ',' && left_bracket == 1) || (code[i] == ']' && left_bracket == 0) ) + { + inputs[num_inputs++] = code + start; + for(j = i-1; j > start; --j) + if(!is_whitespace(code[j])) + break; + if(code[i] == ',') + state = BETWEEN_PRE_IN; + else + state = BEFORE_WORK; + code[j+1] = '\0'; + } + break; + case BETWEEN_PRE_IN: + if(code[i] == ']') + { + state = BEFORE_WORK; + } + else if(!is_whitespace(code[i])) + { + start = i; + state = PRE_IN_STATE; + } + break; + case WORK_STATE: + if(code[i] == '[' || code[i] == '#' || (code[i] == '|' && code[i+1] == ':') || (code[i] == ':' && code[i+1] == '|') || code[i] == '\n') + { + for(j = i-1; j > start; --j) + if(!is_whitespace(code[j])) + break; + + worker = code+start; + + if(code[i] == '[') + { + code[j+1] = '\0'; + // puts("Worker to Between Input"); + // puts("worker_expr = TRUE;"); + worker_expr = TRUE; + state = BETWEEN_IN; + } + else if(code[i] == '#' || code[i] == '\n') + { + code[j+1] = '\0'; + // puts("Worker to Null State(#)"); + //printf("worker_expr: %d\n", worker_expr); + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + state = NULL_STATE; + } + else if(code[i] == ':') + { + code[j+1] = '\0'; + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + state = BLOCK_FIND; + ++i; + } + else + { + //puts("Worker to Null State(else)"); + code[j+1] = '\0'; + if(block_depth) + last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + block_output[block_depth++] = 0; + //puts("Found |:, increasinb block depth"); + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + state = NULL_STATE; + ++i; + } + + } + break; + case BETWEEN_IN: + if(code[i] == ']') + { + state = AFTER_IN; + } + else if(!is_whitespace(code[i])) + { + start = i; + state = IN_STATE; + } + break; + case IN_STATE: + if((code[i] == ',' && left_bracket == 1) || (code[i] == ']' && left_bracket == 0) ) + { + inputs[num_inputs++] = code + start; + for(j = i-1; j > start; --j) + if(!is_whitespace(code[j])) + break; + + if(code[i] == ',') + state = BETWEEN_IN; + else + state = AFTER_IN; + code[j+1] = '\0'; + } + break; + case AFTER_IN: + //puts("AFTER_IN test"); + if(code[i] == '\n') + saw_newline = TRUE; + if(code[i] == '|' && code[i+1] == ':') + { + if(block_depth) + last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + block_output[block_depth++] = 0; + //puts("Found |: increasing block depth"); + state = NULL_STATE; + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + ++i; + } + else if(code[i] == '#') + { + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + state = NULL_STATE; + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + } + else if(code[i] == '[') + { + if(saw_newline) + { + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + saw_newline = FALSE; + state = NULL_STATE; + num_inputs = 0; + num_outputs = 0; + worker_expr = FALSE; + --left_bracket; + --i; + } + else + { + puts("Error: Too many input blocks at"); + code[i+1] = '\0'; + for(j = i-1; j > 0; --j) + if(code[j] == '\n') + { + ++j; + break; + } + puts(code + j); + exit(-1); + } + } + else if(!is_whitespace(code[i])) + { + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + if(saw_newline) + { + saw_newline = FALSE; + num_inputs = 0; + } + else + { + num_inputs = 1; + inputs[0] = NULL; + } + state = NULL_STATE; + + num_outputs = 0; + worker_expr = FALSE; + --i; + } + break; + case BLOCK_FIND: + if(code[i] == '|' && code[i+1] == ':') + { + //puts("Found |: increasing output number (not block depth)"); + ++block_output[block_depth-1]; + ++i; + state = NULL_STATE; + } + else if(!is_whitespace(code[i])) + { + //puts("Found :| without another |: following; decreasing block depth"); + --block_depth; + if(code[i] == '[') + --left_bracket; + --i; + num_inputs = 0; + state = NULL_STATE; + + } + break; + case LINE_COMMENT_STATE: + if(code[i+1] == '\n') + { + for(;line_comment_start <= i; ++line_comment_start) + code[line_comment_start] = ' '; + state = old_state; + } + break; + } + } + if(do_curly) + { + ++left_curly; + do_curly = FALSE; + } + } + else if(literal) + literal = FALSE; + else if(code[i] == '"') + in_string = FALSE; + else if(code[i] == '\\') + literal = TRUE; + } + //printf("State at end of code chunk: %s(%d)\n", state_txt[state], state); + if((state != BLOCK_FIND && block_depth != 0) || (state == BLOCK_FIND && block_depth > 1)) + { + ERRORPRINTF("Syntax Error: Missing %d block close symbol(s) (:|)\n", block_depth); + exit(-1); + } + else + { + switch(state) + { + case WORK_STATE: + for(j = i-1; j > start; --j) + if(!is_whitespace(code[j])) + break; + + worker = code+start; + code[j+1] = '\0'; + case AFTER_IN: + if(block_depth) + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker); + else + last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker); + break; + case BLOCK_FIND: + case NULL_STATE: + break; + default: + printf("Syntax Error: State is %s but there are no more characters left to process.\n", state_txt[state]); + puts(code + start); + exit(-1); + } + } + return last_worker; +} +typedef struct parse_worker +{ + char * worker_name; + int num_inputs; + int num_outputs; + worker_def * def; + char * block; + int block_len; + struct parse_worker * next; +} parse_worker; + +void parse_company(char * name, char * code, int len, program * prog) +{ + char * type_name; + char * field_name; + int i; + int part_start; + int part_end; + int type; + company * comp; + BOOL saw_newline; + field_name = type_name = NULL; + comp = create_company(prog, name, 0, 0, TRUE); + i = 0; + while(i < len) + { + saw_newline = FALSE; + part_start = -1; + for(; i < len; ++i) + { + DEBUGPRINTF("i: %d, code[i]: %c ", i, code[i]); + if(part_start < 0) + { + if(!is_whitespace(code[i])) + part_end = part_start = i; + } + else if(code[i] == ':' && code[i-1] == ':') + { + type_name = code + part_start; + type_name[part_end - part_start-1] = '\0'; + part_start = -1; + ++i; + break; + } + else if(!is_whitespace(code[i])) + { + DEBUGPUTS("Not whitespace\n"); + if(saw_newline) + { + code[part_end] = '\0'; + add_comp_room(comp, code + part_start, -1, -1, ROOM_VIS_REF, ROOM_VIS_REF); + --i; + part_start = -1; + saw_newline = FALSE; + } + else + part_end = i+1; + } + + else if(code[i] == '\n') + { + DEBUGPUTS("saw newline\n"); + saw_newline = TRUE; + } + } + if(i >= len && part_start >= 0 && part_end > part_start) + { + code[part_end] = '\0'; + add_comp_room(comp, code + part_start, -1, -1, ROOM_VIS_REF, ROOM_VIS_REF); + part_start = -1; + } + for(; i < len; ++i) + { + DEBUGPRINTF("i: %d, code[i]: %c ", i, code[i]); + if(part_start < 0) + { + if(!is_whitespace(code[i])) + part_end = part_start = i; + DEBUGPRINTF("part_start: %d\n", part_start); + } + else if(!is_whitespace(code[i])) + { + DEBUGPRINTF("part_end: %d\n", part_end); + part_end = i+1; + } + else if(code[i] == '\n') + { + DEBUGPRINTF("saw newline, type name: %s\n", type_name); + if(!strcmp("Byte", type_name)) + type = ROOM_BYTE; + else if(!strcmp("Word", type_name)) + type = ROOM_SHORT; + else if(!strcmp("Long", type_name)) + type = ROOM_LONG; + else + type = ROOM_VIS_REF; + code[part_end] = '\0'; + add_comp_room(comp, code + part_start, -1, -1, type, type); + break; + } + } + } + if(part_start >= 0 && part_end > part_start) + { + if(!strcmp("Byte", type_name)) + type = ROOM_BYTE; + else if(!strcmp("Word", type_name)) + type = ROOM_SHORT; + else if(!strcmp("Long", type_name)) + type = ROOM_LONG; + else + type = ROOM_VIS_REF; + code[part_end] = '\0'; + add_comp_room(comp, code + part_start, -1, -1, type, type); + } +} + +void import(char * filename, program * prog) +{ + int size; + char * code; + FILE * imp; + imp = fopen(filename, "rb"); + if(imp) + { + fseek(imp, 0, SEEK_END); + size = ftell(imp); + fseek(imp, 0, SEEK_SET); + code = MALLOC(size, "code from imported file"); + fread(code, 1, size, imp); + DEBUGPRINTF("Read %d bytes\n", size); + parse(code, size, prog); + DEBUGPUTS("Finished parsing import file\n"); + VIS_FREE(code, "code buffer"); + fclose(imp); + } + else + { + ERRORPRINTF("Warning: Could not open import file: %s\n", filename); + } +} + +typedef enum {NULL_PARSE, WORKER_STATE, BLOCK_STATE, STRING_STATE, LITERAL_STATE, LIST_STATE, LIST_STRING, LIST_LITERAL, LINE_COMMENT} super_state; +char super_state_txt[9][30] = {"Null", "Worker", "Block", "String", "String Literal", "List", "String in List", "String Literal in List", "Single Line Comment"}; +void parse(char * code, int len, program * prog) +{ + parse_worker *list=NULL, *current=NULL, *temp; + short saw_line = 0; + int i,j,k; + int block_count = 0; + int start; + int end; + int num_inputs; + int num_outputs; + int company_len, import_len; + char * worker_name; + int left_curly=0; + int block_done = -1; + int comp_start, comp_end; + char * company_name; + char * comp_block; + int comp_block_len; + int num_uses; + char * importfiles[32]; + int num_imported = 0; + super_state old_state; + char ** uses_names = NULL; + BOOL lastwasspace = FALSE; + super_state state = NULL_PARSE; + company_len = strlen("Company"); + import_len = strlen("Import"); + for(i = 0; i < len; ++i) + { + DEBUGPRINTF("i: %d, code[i]: %c, state: %s(%d)\n", i, code[i], super_state_txt[state], state); + if(code[i] == '/' && code[i+1] == '/' && state != STRING_STATE && state != LIST_STRING) + { + old_state = state; + state = LINE_COMMENT; + i += 2; + } + switch(state) + { + case NULL_PARSE: + if(len - i >= import_len && !memcmp("Import", code + i, import_len)) + { + start = end = -1; + for(j = i+import_len; j < len && code[j] != '\n'; ++j) + { + if(start < 0) + { + if(!is_whitespace(code[j])) + start = j; + } + else + { + if(!is_whitespace(code[j])) + end = j; + } + } + if(end < 0) + { + puts("Error: Import statement with no file name"); + exit(-1); + } + ++end; + code[end] = '\0'; + i = end; + if(num_imported < 32) + importfiles[num_imported++] = code+start; + else + { + puts("Error: You cannot have more than 32 import statements in the same file"); + exit(-1); + } + } + else if(code[i] == ':' && code[i+1] == '|') + { + start = i; + while((code[i] != '\n' || saw_line < 5) && i < len) + { + if(code[i] == '\n') + ++saw_line; + ++i; + } + code[i] = '\0'; + ERRORPRINTF("Error: Unexpected closing bracket (:|) found:\n%s", code + start); + exit(-1); + } + else if(!is_whitespace(code[i])) + { + start = i; + state = WORKER_STATE; + } + break; + case WORKER_STATE: + if(is_whitespace(code[i])) + lastwasspace = TRUE; + else if(code[i] == '|' && code[i+1] == ':') + { + if(!strncmp(code+start, "Company",company_len) && is_whitespace(code[start+company_len])) + { + comp_start = -1; + comp_end = 0; + for(j = start+company_len+1; j < len-1; ++j) + { + if(comp_start >= 0) + { + if(code[j] == '|' && code[j+1] == ':') + break; + else if(!is_whitespace(code[j])) + comp_end = j+1; + } + else + { + if(!is_whitespace(code[j])) + comp_start = j; + } + } + if(comp_start >= 0 && comp_end > comp_start) + { + company_name = code + comp_start; + code[comp_end] = '\0'; + comp_start = -1; + for(j = comp_end+1; j < len-1; ++j) + { + if(comp_start < 0) + { + if(code[j] == '|' && code[j+1] == ':') + comp_start = j+2; + } + else + { + if(code[j] == ':' && code[j+1] == '|') + { + comp_end = j; + break; + } + } + } + if(comp_start > 0) + { + comp_block = code+comp_start; + comp_block_len = comp_end-comp_start; + DEBUGPRINTF("Company block start: %d, end: %d, length: %d\n", comp_start, comp_end, comp_block_len); + code[comp_end] = '\0'; + i = comp_end+1; + parse_company(company_name, comp_block, comp_block_len, prog); + } + else + { + printf("Error parsing Company, comp_start is %d\n", comp_start); + } + + } + else + { + puts("Error parsing Company\n"); + } + state = NULL_STATE; + + } + else + { + for(j = i-1; j > start; --j) + if(code[j] != ' ' && code[j] != '\t' && code[j] != '\n' && code[j] != '\r') + break; + for(k = start; k <= j; ++k) + if(code[k] == '(') + { + code[k] = '\0'; + num_inputs = atol(code + k + 1); + } + else if(code[k] == ',') + num_outputs = atol(code + k + 1); + worker_name = code + start; + //printf("Found worker def: %s with %d outputs and %d inputs\n", worker_name, num_outputs, num_inputs); + start = i+2; + ++i; + num_uses = 0; + state = BLOCK_STATE; + } + } + else if(lastwasspace && !strncmp(code+i, "uses", 4)) + { + for(j = i-1; j > start; --j) + if(code[j] != ' ' && code[j] != '\t' && code[j] != '\n' && code[j] != '\r') + break; + for(k = start; k <= j; ++k) + if(code[k] == '(') + { + code[k] = '\0'; + num_inputs = atol(code + k + 1); + } + else if(code[k] == ',') + num_outputs = atol(code + k + 1); + worker_name = code + start; + num_uses = 1; + for(j = i + strlen("uses"); code[j] != '|' && j < len; ++j) + if(code[j] == ',') + ++num_uses; + DEBUGPRINTF("num_uses: %d\n", num_uses); + i += strlen("uses"); + uses_names = MALLOC(sizeof(char *) * num_uses, "uses stores names"); + end = -1; + start = i; + j = 0; + while(code[i] != '|' && i < len) + { + if(code[i] == ',') + { + uses_names[j] = MALLOC(sizeof(char) * (end-start+1), "global store name for uses stores"); + memcpy(uses_names[j], code+start, end-start); + uses_names[j][end-start] = '\0'; + DEBUGPRINTF("uses: %s\n", uses_names[j]); + end = -1; + ++j; + } + else if(code[i] != ' ' && code[i] != '\t' && code[i] != '\r' && code[i] != '\n') + end = i+1; + else if(end < 0) + start = i+1; + ++i; + } + if(end >= 0) + { + uses_names[j] = MALLOC(sizeof(char) * (end-start+1), "global store name for uses stores"); + memcpy(uses_names[j], code+start, end-start); + uses_names[j][end-start] = '\0'; + DEBUGPRINTF("uses: %s\n", uses_names[j]); + end = -1; + ++j; + } + start = i+2; + ++i; + state = BLOCK_STATE; + + } + break; + case BLOCK_STATE: + //printf("Block count: %d\n", block_count); + if((i-block_done)>1 && code[i] == ':' && code[i-1] == '|') + { + ++block_count; + } + else if(code[i] == '"') { + state = STRING_STATE; + } + else if(code[i] == '{') { + state = LIST_STATE; + } + else if(code[i] == '|' && code[i-1] == ':') + { + if(block_count == 0) + { + if(current) + { + current->next = MALLOC(sizeof(parse_worker),"parse worker"); + current = current->next; + } + else + { + list = current = MALLOC(sizeof(parse_worker),"parse worker"); + } + current->num_inputs = num_inputs; + current->num_outputs = num_outputs; + current->worker_name = worker_name; + current->block = code + start; + current->block_len = i-start-1; + current->next = NULL; + current->def = create_worker(prog, current->worker_name, current->num_inputs, current->num_outputs, USER_FLAG | WORKER_TYPE); + current->def->uses_stores = uses_names; + current->def->num_stores = num_uses; + uses_names = NULL; + num_uses = 0; + state = NULL_PARSE; + block_done = -1; + } + else + { + block_done = i; + --block_count; + } + } + break; + case STRING_STATE: + if(code[i] == '\\') + state = LITERAL_STATE; + else if(code[i] == '"') + state = BLOCK_STATE; + break; + case LITERAL_STATE: + state = STRING_STATE; + break; + case LIST_STATE: + if(code[i] == '{') + ++left_curly; + else if(code[i] == '}') + if(left_curly) + --left_curly; + else + state = BLOCK_STATE; + else if(code[i] == '"') + state = LIST_STRING; + break; + case LIST_STRING: + if(code[i] == '\\') + state = LIST_LITERAL; + else if(code[i] == '"') + state = LIST_STATE; + break; + case LIST_LITERAL: + state = LIST_STRING; + break; + case LINE_COMMENT: + if(code[i+1] == '\n') + state = old_state; + break; + } + } + if(state != NULL_PARSE) + { + printf("Error: Current parse state is %s(%d) in first pass but there are no more characters to parse.\n", super_state_txt[state], state); + if(state == BLOCK_STATE) + { + printf("Worker %s appears to be missing a closing bracket (:|)\n", worker_name); + } + exit(-3); + } + for(i = 0; i < num_imported; ++i) + { + import(importfiles[i], prog); + } + current = list; + while(current) + { + DEBUGPRINTF("Processing worker %s with %d inputs and %d outputs\n\n", current->worker_name, current->num_inputs, current->num_outputs); + parse_body(current->def, current->block, current->block_len, 0, NULL, NULL); + temp = current; + current = current->next; + free(temp); + } +} + +