void CBuzzController::SetBytecode(const std::string& str_bc_fname, const std::string& str_dbg_fname) { /* Reset the BuzzVM */ if(m_tBuzzVM) buzzvm_destroy(&m_tBuzzVM); m_tBuzzVM = buzzvm_new(m_unRobotId); /* Get rid of debug info */ if(m_tBuzzDbgInfo) buzzdebug_destroy(&m_tBuzzDbgInfo); m_tBuzzDbgInfo = buzzdebug_new(); /* Save the filenames */ m_strBytecodeFName = str_bc_fname; m_strDbgInfoFName = str_dbg_fname; /* Load the bytecode */ std::ifstream cBCodeFile(str_bc_fname.c_str(), std::ios::binary | std::ios::ate); if(cBCodeFile.fail()) { THROW_ARGOSEXCEPTION("Can't open file \"" << str_bc_fname << "\": " << strerror(errno)); } std::ifstream::pos_type unFileSize = cBCodeFile.tellg(); m_cBytecode.Clear(); m_cBytecode.Resize(unFileSize); cBCodeFile.seekg(0, std::ios::beg); cBCodeFile.read(reinterpret_cast<char*>(m_cBytecode.ToCArray()), unFileSize); /* Load the debug symbols */ if(!buzzdebug_fromfile(m_tBuzzDbgInfo, m_strDbgInfoFName.c_str())) { THROW_ARGOSEXCEPTION("Can't open file \"" << str_dbg_fname << "\": " << strerror(errno)); } /* Load the script */ if(buzzvm_set_bcode(m_tBuzzVM, m_cBytecode.ToCArray(), m_cBytecode.Size()) != BUZZVM_STATE_READY) { THROW_ARGOSEXCEPTION("Error loading Buzz script \"" << str_bc_fname << "\": " << ErrorInfo()); } /* Register basic function */ if(RegisterFunctions() != BUZZVM_STATE_READY) { THROW_ARGOSEXCEPTION("Error while registering functions: " << ErrorInfo()); } /* Execute the global part of the script */ buzzvm_execute_script(m_tBuzzVM); /* Call the Init() function */ buzzvm_function_call(m_tBuzzVM, "init", 0); }
int main(int argc, char** argv) { /* The bytecode filename */ char* bcfname; /* The debugging information file name */ char* dbgfname; /* Whether or not to show the assembly information */ int trace = 0; /* Parse command line */ if(argc < 3 || argc > 4) usage(argv[0], 0); if(argc == 3) { bcfname = argv[1]; dbgfname = argv[2]; } else { bcfname = argv[2]; dbgfname = argv[3]; if(strcmp(argv[1], "--trace") != 0) { fprintf(stderr, "error: %s: unrecognized option '%s'\n", argv[0], argv[1]); usage(argv[0], 1); } trace = 1; } /* Read bytecode and fill in data structure */ FILE* fd = fopen(bcfname, "rb"); if(!fd) perror(bcfname); fseek(fd, 0, SEEK_END); size_t bcode_size = ftell(fd); rewind(fd); uint8_t* bcode_buf = (uint8_t*)malloc(bcode_size); if(fread(bcode_buf, 1, bcode_size, fd) < bcode_size) { perror(bcfname); } fclose(fd); /* Read debug information */ buzzdebug_t dbg_buf = buzzdebug_new(); if(!buzzdebug_fromfile(dbg_buf, dbgfname)) { perror(dbgfname); } /* Create new VM */ buzzvm_t vm = buzzvm_new(1); /* Set byte code */ buzzvm_set_bcode(vm, bcode_buf, bcode_size); /* Register hook functions */ buzzvm_pushs(vm, buzzvm_string_register(vm, "print", 1)); buzzvm_pushcc(vm, buzzvm_function_register(vm, print)); buzzvm_gstore(vm); /* Run byte code */ do if(trace) buzzdebug_stack_dump(vm, 1, stdout); while(buzzvm_step(vm) == BUZZVM_STATE_READY); /* Done running, check final state */ int retval; if(vm->state == BUZZVM_STATE_DONE) { /* Execution terminated without errors */ if(trace) buzzdebug_stack_dump(vm, 1, stdout); fprintf(stdout, "%s: execution terminated correctly\n\n", bcfname); retval = 0; } else { /* Execution terminated with errors */ if(trace) buzzdebug_stack_dump(vm, 1, stdout); buzzdebug_entry_t dbg = *buzzdebug_info_get_fromoffset(dbg_buf, &vm->pc); if(dbg != NULL) { fprintf(stderr, "%s: execution terminated abnormally at %s:%" PRIu64 ":%" PRIu64 " : %s\n\n", bcfname, dbg->fname, dbg->line, dbg->col, vm->errormsg); } else { fprintf(stderr, "%s: execution terminated abnormally at bytecode offset %d: %s\n\n", bcfname, vm->pc, vm->errormsg); } retval = 1; } /* Destroy VM */ free(bcode_buf); buzzdebug_destroy(&dbg_buf); buzzvm_destroy(&vm); /* All done */ return retval; }