machine::machine(const string& file, const size_t th, const scheduler_type _sched_type, const machine_arguments& margs, const string& data_file): filename(file), sched_type(_sched_type), alarm_thread(NULL), slices(th) /* th = number of threads, slices is for statistics */ { bool added_data_file(false); vm::All = new vm::all(); vm::All->PROGRAM = new vm::program(file); vm::theProgram = vm::All->PROGRAM; if(vm::All->PROGRAM->is_data()) throw machine_error(string("cannot run data files")); if(data_file != string("")) { if(file_exists(data_file)) { vm::program data(data_file); if(!vm::All->PROGRAM->add_data_file(data)) { throw machine_error(string("could not import data file")); } added_data_file = true; } else { throw machine_error(string("data file ") + data_file + string(" not found")); } } if(margs.size() < vm::All->PROGRAM->num_args_needed()) throw machine_error(string("this program requires ") + utils::to_string(vm::All->PROGRAM->num_args_needed()) + " arguments"); vm::All->MACHINE = this; vm::All->ARGUMENTS = margs; vm::All->DATABASE = new database(added_data_file ? data_file : filename, get_creation_function(_sched_type)); vm::All->NUM_THREADS = th; // Instantiate the scheduler object switch(sched_type) { case SCHED_SERIAL: vm::All->ALL_THREADS.push_back(dynamic_cast<sched::base*>(new sched::serial_local())); break; case SCHED_UNKNOWN: assert(false); break; default: break; } assert(vm::All->ALL_THREADS.size() == vm::All->NUM_THREADS); }
void exec_gfread(int oid, char* format){ Odescr *specifier = pop_tstack(); FILE *in_file = fopen(specifier->inst.sval, "r"); if(in_file == NULL){ machine_error("Could not open input file."); } exec_gread(oid, format, 0, in_file); free_odescr(specifier); fclose(in_file); }
void exec_fwr(char* format){ Odescr *specifier = pop_tstack(); FILE *out = fopen(specifier->inst.sval, "w"); if(out == NULL){ machine_error("Could not open output file."); } exec_wr(format, 0, out); free_odescr(specifier); fclose(out); }
void exec_cat(int num_fields, int size){ int size_done = 0; int fields_done = 0; char *instance = newmem(size); while(fields_done < num_fields){ Odescr *op = pop_tstack(); int dest_start = size - size_done - op->size; // if there is an error reverse it, starting from 0 -- using size_done as index if(op->mode == EMB){ switch(op->size){ case sizeof(char): instance[dest_start] = op->inst.cval; break; case sizeof(int): *((int *)(instance+dest_start)) = op->inst.ival; break; case sizeof(char *):{ char *actual_address = instance+dest_start; char** act = (char **)actual_address; act[0] = op->inst.sval; //printf("%s %s\n",op->inst.sval, act[0]); //printf("%p %s\n%p %s\n\n", act[0],act[0], op->inst.sval,op->inst.sval); break; } default: machine_error("Unknown type for op->size"); break; } } else{ memcpy(instance + dest_start, op->inst.sval, op->size); } size_done += op->size; fields_done++; free_odescr(op); } Odescr *op2 = push_tstack(); op2->size = size; op2->mode = STA; op2->inst.sval = instance; // this allocates space on the instance stack and than copies byte by byte all the elements on the stack // taking them to the tstack (?) /* TSTACK: expr1_res expr2_res ... INSTANCE -> expr1_res, expr2_res, ... creates a single record on the tstack with SIZE, STA and with the pointer to the allocated instance */ }
/* Implementation specific function */ static inline database::create_node_fn get_creation_function(const scheduler_type sched_type) { switch(sched_type) { case SCHED_SERIAL: return database::create_node_fn(sched::serial_local::create_node); case SCHED_UNKNOWN: return NULL; default: return NULL; } throw machine_error("unknown scheduler type"); }
void exec_ist(){ Odescr *val = pop_tstack(); Odescr *dest_addr = pop_tstack(); Odescr *dest = dest_addr->original; if(dest->mode == EMB) { //printf("A\n"); dest->inst = val->inst; } else{ if(val->mode == EMB){ //printf("B\n"); char *instance = dest_addr->inst.sval; switch(val->size){ case sizeof(int): { // works with float too int *inst = (int *)instance; inst[0] = val->inst.ival; break; } case sizeof(char): { char *inst = (char *)instance; inst[0] = val->inst.cval; break; } case sizeof(char *): { char **inst = (char **)instance; inst[0] = val->inst.sval; break; } default: { machine_error("Unrecognized size for IST."); break; } } } else { //printf("C\n"); memcpy(dest_addr->inst.sval, val->inst.sval, val->size); } } free_odescr(val); freemem((char *)dest_addr, sizeof(Odescr)); // pop expression result // pop address // *adress = result }
/** * @brief This functin opens the input file and do the initial memory allocation of data structures. * @param input the s_code filename. */ void start_machine(char * input) { str_const_table = (Str_c_node **)newmem(sizeof(Str_c_node*)*STR_CONST_DIM); FILE *input_file = fopen(input, "r"); if (!input_file){ machine_error("ERRORE nel caricamento del file"); } load_scode(input_file); fclose (input_file); pc = ap = op = ip = 0; astack = (Adescr**)newmem(sizeof(Adescr*)*ASTACK_UNIT); asize = ASTACK_UNIT; ostack = (Odescr**)newmem(sizeof(Odescr*)*OSTACK_UNIT); osize = OSTACK_UNIT; istack = (char*)newmem(ISTACK_UNIT); isize = ISTACK_UNIT; }
void exec_eil(int field_size){ Odescr *address = pop_tstack(); switch(field_size){ case sizeof(int):{ push_int(*((int *)address->inst.sval)); break; } case sizeof(char):{ push_char(*((char *)address->inst.sval)); break; } case sizeof(char *):{ char** act = (char **)address->inst.sval; push_string(act[0]); break; } default:{ machine_error("EIL field_size error."); break; } } freemem((char*)address, sizeof(Odescr)); // only dealloc the object and not the inst }
int get_schema_size(Pschema schema){ int size = 0; switch(schema->type){ case TY_INT: size = sizeof(int); break; case TY_REAL: size = sizeof(float); break; case TY_CHAR: size = sizeof(char); break; case TY_BOOL: size = sizeof(char); break; // bool is '1' or '0' case TY_STRING: size = sizeof(char *); break; case TY_ARRAY: size = get_schema_size(schema->child)*schema->size; break; case TY_RECORD: { Pschema p = schema->child; while ( p != NULL ){ size += get_schema_size( p->child ); // child of TY_ATTR p = p->brother; } break; } default: machine_error("Error in code generation: get_schema_size() default."); break; } return size; }
void exec(Pystat stat){ Arg arg0 = stat->args[0]; Arg arg1 = stat->args[1]; switch(stat->op){ case Y_PUSH: { exec_push(arg0.ival, pc+1); // num_objects break; } case Y_GOTO: { exec_goto(arg0.ival); // absolute line break; } case Y_POP: { exec_pop(); break; } case Y_NEW: { exec_new(arg0.ival); // obj size break; } case Y_NEWS: { exec_news(arg0.ival); // obj size break; } case Y_LDC: { exec_ldc(arg0.ival); break; } case Y_LDI: { exec_ldi(arg0.ival); break; } case Y_LDR: { exec_ldr(arg0.rval); break; } case Y_LDS: { exec_lds(arg0.sval); break; } case Y_LOD: { exec_lod(arg0.ival); // oid break; } case Y_GLOD: { exec_glod(arg0.ival); // oid break; } case Y_CAT: { exec_cat(arg0.ival, arg1.ival); // num fields, record/array size break; } case Y_LDA: { exec_lda(arg0.ival); // oid break; } case Y_GLDA: { exec_glda(arg0.ival); // oid break; } case Y_FDA: { exec_fda(arg0.ival); // field offset break; } case Y_EIL: { exec_eil(arg0.ival); // field size, embedded break; } case Y_SIL: { exec_sil(arg0.ival); // field size, on stack break; } case Y_IXA: { exec_ixa(arg0.ival); // elem size break; } case Y_STO: { exec_sto(arg0.ival); // oid break; } case Y_GSTO: { exec_gsto(arg0.ival); // oid break; } case Y_IST: { exec_ist(); // indirect store break; } case Y_JMF: { exec_jmf(arg0.ival); // offset break; } case Y_JMP: { exec_jmp(arg0.ival); // offset break; } case Y_EQU: { exec_equ(); // for all types of objects break; } case Y_NEQ: { exec_neq(); // for all types of objects break; } case Y_IGT: { exec_igt(); break; } case Y_IGE: { exec_ige(); break; } case Y_ILT: { exec_ilt(); break; } case Y_ILE: { exec_ile(); break; } case Y_RGT: { exec_rgt(); break; } case Y_RGE: { exec_rge(); break; } case Y_RLT: { exec_rlt(); break; } case Y_RLE: { exec_rle(); break; } case Y_SGT: { exec_sgt(); break; } case Y_SGE: { exec_sge(); break; } case Y_SLT: { exec_slt(); break; } case Y_SLE: { exec_sle(); break; } case Y_IPLUS: { exec_iplus(); break; } case Y_IMINUS: { exec_iminus(); break; } case Y_ITIMES: { exec_itimes(); break; } case Y_IDIV: { exec_idiv(); break; } case Y_RPLUS: { exec_rplus(); break; } case Y_RMINUS: { exec_rminus(); break; } case Y_RTIMES: { exec_rtimes(); break; } case Y_RDIV: { exec_rdiv(); break; } case Y_IUMI: { exec_iumi(); break; } case Y_RUMI: { exec_rumi(); break; } case Y_NEG: { exec_neg(); break; } case Y_WR: { exec_wr(arg0.sval, 1, stdout); // schema break; } case Y_FWR: { exec_fwr(arg0.sval); // schema break; } case Y_RD: { exec_rd(arg0.sval, 1, stdin); // schema break; } case Y_FRD: { exec_frd(arg0.sval); // schema break; } case Y_TOINT: { exec_toint(); break; } case Y_TOINTUP: { exec_tointup(); break; } case Y_TOREAL: { exec_toreal(); break; } case Y_READ: { exec_read(arg0.ival, arg1.sval, 1, stdin); // oid, schema break; } case Y_GREAD: { exec_gread(arg0.ival, arg1.sval, 1, stdin); // oid, schema break; } case Y_FREAD: { exec_fread(arg0.ival, arg1.sval); // oid, schema break; } case Y_GFREAD: { exec_gfread(arg0.ival, arg1.sval); // oid, schema break; } case Y_WRITE: { exec_write(arg0.sval); // schema break; } case Y_FWRITE: { exec_fwrite(arg0.sval); // schema break; } case Y_TDUP: { exec_tdup(); break; } case Y_TPOP: { exec_tpop(arg0.ival); // num objects break; } case Y_MODULE: { // nothing to do here, the instruction is useless break; } case Y_RETURN: { exec_return(); break; } default: { machine_error("Unknown instruction."); break; } } }
void print_instance(char *instance, Pschema s, char *attr_name, int spaces, Mode mode, int pretty, FILE *out){ if(attr_name!=NULL && pretty){ print_spaces(spaces, out); fprintf(out, "WR for record attribute \"%s\"\n",attr_name); } if(pretty){ print_spaces(spaces, out); } if(s->type == TY_RECORD || s->type == TY_ARRAY || s->type == TY_ATTR){ switch(s->type){ case TY_RECORD:{ if(pretty){ fprintf(out, "WR for a record\n"); } int printed_size = 0; Pschema temp = s->child; while(temp){ print_instance(instance + printed_size, temp->child, temp->id, spaces+1, mode, pretty, out); printed_size += get_schema_size(temp->child); temp = temp->brother; } break; } case TY_ARRAY:{ int i; if(pretty){ fprintf(out, "WR for an array\n"); } int field_size = get_schema_size(s->child); int nfields = s->size; for(i=0; i<nfields; i++){ print_instance(instance + field_size * i, s->child, NULL, spaces+1, mode, pretty, out); } break; } default: machine_error("TY_ATTR cannot be used in input_schema()."); break; } } else{ if(mode == EMB){ Arg inst; inst.sval = instance; if(pretty){ fprintf(out, "WR "); } switch(s->type){ case TY_INT: { fprintf(out, "%d\n",inst.ival); break; } case TY_CHAR: { fprintf(out, "%c\n",inst.cval); break; } case TY_REAL: { fprintf(out, "%f\n",inst.rval); break; } case TY_STRING: { fprintf(out, "%s\n",inst.sval); break; } case TY_BOOL: { fprintf(out, "%s\n",inst.cval == '1' ? "true" : "false"); break; } default: { break; } } } else{ if(pretty){ fprintf(out, "WR "); } switch(s->type){ case TY_INT: { int *inst = (int *)instance; fprintf(out, "%d\n",inst[0]); break; } case TY_CHAR: { char *inst = (char *)instance; fprintf(out, "%c\n",inst[0]); break; } case TY_REAL: { float *inst = (float *)instance; fprintf(out, "%f\n",inst[0]); break; } case TY_STRING: { char **inst = (char **)instance; fprintf(out, "%s\n",inst[0]); break; } case TY_BOOL: { char *inst = (char *)instance; fprintf(out, "%s\n",inst[0] == '1' ? "true" : "false"); break; } default: { break; } } } } }
/** * return a pointer the top of the ostack. * @return The Odescr* on top of the astack. */ Odescr * top_ostack(){ if (op==0) { machine_error("top_ostack"); } return ostack[op-1]; }
/** * This function returns a pointer to the top of the astack. * @return The Adescr* on top of the astack. */ Adescr * top_astack(){ if (ap==0) { machine_error("top_astack"); } return astack[ap-1]; }
/** * @brief This function shift down the memory chunk express by to move of the quantity express by this much. * @param to_move how much bytes are to move. * @param this_much How much byte shift down the memory block */ void move_down_istack(int to_move, int this_much){ if(ip - to_move - this_much < 0) machine_error("move_down_istack()"); if (to_move<0 || this_much<0) machine_error("move_down_istack() parameters"); memmove(&istack[ip-to_move-this_much], &istack[ip-to_move], to_move); ip -= this_much; }
/** * @brief Decrement the istack with the size and return the new top. * * @param size how much increment the istack. */ void pop_istack(int size) { if(ip < size) machine_error("pop_istack()"); ip = ip-size; }
/** * @brief Free the odescr on the top of the ostack. */ void pop_ostack() { if(op == 0) machine_error("pop_odescr()"); freemem((char*)ostack[--op], sizeof(Odescr)); }
/** * return a pointer the element below the element on top of the ostack. * @return The Odescr* to the Odescr below the Odescr on top of the astack. */ Odescr * under_top_ostack(){ if (op<=1) { machine_error("under_top_ostack"); } return ostack[op-2]; }
void input_schema(Pschema s, char *attr_name, int spaces, int pretty, FILE *in_file){ // reads a schema and puts it on the top op tstack if(attr_name!=NULL && pretty){ print_spaces(spaces, stdout); fprintf(stdout, "Input record attribute \"%s\"\n",attr_name); } if(pretty){ print_spaces(spaces, stdout); } if(s->type == TY_RECORD || s->type == TY_ARRAY || s->type == TY_ATTR){ int size = get_schema_size(s); int nfields = 0; switch(s->type){ case TY_RECORD:{ if(pretty){ fprintf(stdout,"Input for a record\n"); } Pschema temp = s->child; while(temp){ input_schema(temp->child, temp->id, spaces+1, pretty, in_file); nfields++; temp = temp->brother; } break; } case TY_ARRAY:{ int i; if(pretty){ fprintf(stdout, "Input for an array\n"); } nfields = s->size; for(i=0; i<nfields; i++){ input_schema(s->child, NULL, spaces+1, pretty, in_file); } break; } default: print_schema(s,0); machine_error("TY_ATTR cannot be used in input_schema()."); break; } exec_cat(nfields,size); } else{ switch(s->type){ case TY_INT: { int in = read_int(stdout, in_file, "Insert an integer: ", pretty); push_int(in); break; } case TY_CHAR: { char in = read_char(stdout, in_file, "Insert a char: ", pretty); push_char(in); break; } case TY_REAL: { float in = read_real(stdout, in_file, "Insert a number of type real: ", pretty); push_real(in); break; } case TY_STRING: { char *in = read_string(stdout, in_file, "Insert a string: ", pretty); char *strig_to_store = stringtable_store(in, stringtable); freemem(in, strlen(in) + 1); push_string(strig_to_store); break; } case TY_BOOL: { char in = read_char(stdout, in_file, "Insert a boolean (0 or 1): ", pretty); push_bool(in == '1'); break; } default: {machine_error("Unknown type of schema in input_schema()."); break;} } } }
/** * @brief Free the adescr on the top of the astack. */ void pop_astack() { if(ap == 0) machine_error("pop_adescr()"); freemem((char*)astack[--ap], sizeof(Adescr)); }