/// /// Stores the application path in a global context. /// /// Stores the application path (arg0) in a global context so that /// libraries can retrieve it later using osutil_getarg0. All applications /// using a DCPU-16 Toolchain library should invoke this method after /// parsing their arguments. If this value is not set, some libraries /// may be unable to resolve their required runtime components. /// /// @param arg0 The string containing argument 0. /// void osutil_setarg0(freed_bstring arg0) { if (osutil_arg0 != NULL) bdestroy(osutil_arg0); osutil_arg0 = bstrcpy(arg0.ref); bautodestroy(arg0); }
/// /// Performs preprocessing. /// void ppimpl(freed_bstring filename, int line, freed_bstring lang, has_t has_input, pop_t input, push_t output) { state_t state; list_init(&state.cached_input); list_init(&state.cached_output); list_init(&state.handlers); list_init(&state.scopes); list_attributes_comparator(&state.cached_input, list_comparator_char_t); list_attributes_comparator(&state.cached_output, list_comparator_char_t); list_attributes_copy(&state.cached_input, list_meter_char_t, false); list_attributes_copy(&state.cached_output, list_meter_char_t, false); list_attributes_hash_computer(&state.cached_input, list_hashcomputer_char_t); list_attributes_hash_computer(&state.cached_output, list_hashcomputer_char_t); state.has_input = has_input; state.input = input; state.output = output; state.current_line = line; state.current_filename = bstrcpy(filename.ref); state.default_filename = bfromcstr("<unknown>"); state.in_single_string = false; state.in_double_string = false; if (biseqcstrcaseless(lang.ref, "asm")) { ppimpl_asm_line_register(&state); ppimpl_asm_expr_register(&state); ppimpl_asm_define_register(&state); ppimpl_asm_include_register(&state); ppimpl_asm_lua_register(&state); ppimpl_asm_init(&state); } else if (biseqcstrcaseless(lang.ref, "c")) { ppimpl_c_line_register(&state); ppimpl_c_expr_register(&state); ppimpl_c_define_register(&state); ppimpl_c_include_register(&state); ppimpl_c_init(&state); } ppimpl_process(&state); bautodestroy(lang); bautodestroy(filename); }
/// /// Writes a word of data into the specified bin. /// /// @param path The path to load. /// @return Whether the bin was loaded successfully. /// bool bins_write(freed_bstring name, uint16_t word) { struct ldbin* bin = list_seek(&ldbins.bins, name.ref); if (bin == NULL) { bautodestroy(name); return false; } bin_write(bin, word); return true; }
void version_print(freed_bstring application) { bstring ver = version_get(); if (debug_getlevel() < LEVEL_VERBOSE) { bdestroy(ver); bautodestroy(application); return; } fprintf(stderr, "DCPU-16 Toolchain "); fprintf(stderr, "%s", application.ref->data); fprintf(stderr, " ("); fprintf(stderr, "%s", ver->data); fprintf(stderr, ")\n"); fprintf(stderr, "This software is MIT licensed.\n"); fprintf(stderr, "\n"); bdestroy(ver); bautodestroy(application); }
/// /// Saves the bin with the specified name to the specified path. /// /// @param name The name of the bin to save. /// @param path The path to save the bin to. /// void bins_save(freed_bstring name, freed_bstring path) { FILE* out; struct ldbin* bin = list_seek(&ldbins.bins, name.ref); assert(bin != NULL); // Open the output file. out = fopen(path.ref->data, "wb"); // Write each byte from the bin. list_iterator_start(&bin->words); while (list_iterator_hasnext(&bin->words)) fwrite(list_iterator_next(&bin->words), sizeof(uint16_t), 1, out); list_iterator_stop(&bin->words); // Close the output file. fclose(out); // Free strings. bautodestroy(name); bautodestroy(path); }
void dbg_lua_handle_hook(struct dbg_state* state, void* ud, freed_bstring type, uint16_t pos) { struct lua_debugst* ds; unsigned int i; char* cstr; // Convert the name to lowercase. btolower(type.ref); cstr = bstr2cstr(type.ref, '0'); printd(LEVEL_EVERYTHING, "firing hook %s.\n", cstr); // Loop through all of the modules. for (i = 0; i < list_size(&modules); i++) { ds = list_get_at(&modules, i); // Set stack top (I don't know why the top of the // stack is negative!) lua_settop(ds->state, 0); // Search handler table for entries. lua_getglobal(ds->state, HANDLER_TABLE_HOOKS_NAME); lua_getfield(ds->state, -1, cstr); if (!lua_istable(ds->state, -1)) { // No such entry. printd(LEVEL_EVERYTHING, "no matching hook for %s.\n", cstr); lua_pop(ds->state, 2); continue; } // Call the handler function. printd(LEVEL_EVERYTHING, "calling hook %s.\n", cstr); lua_getfield(ds->state, -1, HANDLER_FIELD_FUNCTION_NAME); dbg_lua_push_state(ds, state, ud); lua_pushnumber(ds->state, pos); if (lua_pcall(ds->state, 2, 0, 0) != 0) { printd(LEVEL_ERROR, "error: unable to call debugger hook handler for '%s'.\n", type.ref->data); printd(LEVEL_ERROR, "%s\n", lua_tostring(ds->state, -1)); lua_pop(ds->state, 2); continue; } } // Clean up. bcstrfree(cstr); bautodestroy(type); }
void dbg_lua_handle_hook_symbol(struct dbg_state* state, void* ud, freed_bstring symbol) { struct lua_debugst* ds; unsigned int i; // Loop through all of the modules. for (i = 0; i < list_size(&modules); i++) { ds = list_get_at(&modules, i); // Set stack top (I don't know why the top of the // stack is negative!) lua_settop(ds->state, 0); // Search handler table for entries. lua_getglobal(ds->state, HANDLER_TABLE_SYMBOLS_NAME); lua_getfield(ds->state, -1, HANDLER_ENTRY_SYMBOL_HOOK); if (!lua_istable(ds->state, -1)) { // No such entry. lua_pop(ds->state, 2); continue; } // Call the handler function. lua_getfield(ds->state, -1, HANDLER_FIELD_FUNCTION_NAME); dbg_lua_push_state(ds, state, ud); lua_pushstring(ds->state, symbol.ref->data); if (lua_pcall(ds->state, 2, 0, 0) != 0) { printd(LEVEL_ERROR, "error: unable to call debugger symbol hook handler.\n"); printd(LEVEL_ERROR, "%s\n", lua_tostring(ds->state, -1)); lua_pop(ds->state, 2); continue; } } // Clean up. bautodestroy(symbol); }
void micro_write_file(BFILE* out, BFILE* in, freed_bstring name) { int written = 0; uint16_t store; size_t pos; // Check to make sure we don't have too many entries. if (micro_table_count >= MICRO_MAX_ENTRIES) { printd(LEVEL_WARNING, "ignoring file %s; maximum limit of %u files hit.\n", name.ref->data, MICRO_MAX_ENTRIES); exit(1); } // Copy data. store = (uint16_t)(bftell(out) / 2); while (!bfeof(in)) { bfputc(bfgetc(in), out); written++; } // Store the position so we can jump back to // this position. pos = bftell(out); // Write the entry. bfseek(out, micro_table_addr + micro_table_count * 2, SEEK_SET); bfiwrite(&store, out); store = written / 2; bfiwrite(&store, out); printd(LEVEL_VERBOSE, "wrote file %s at index %u (0x%04X words).\n", name.ref->data, micro_table_count, written / 2); micro_table_count++; // Seek back again. bfseek(out, pos, SEEK_SET); // Clear memory. bautodestroy(name); }
void dbg_lua_handle_command(struct dbg_state* state, void* ud, freed_bstring name, list_t* parameters) { struct lua_debugst* ds; struct customarg_entry* carg; char* cstr; unsigned int i, k; int paramtbl; // Convert the name to lowercase. btolower(name.ref); cstr = bstr2cstr(name.ref, '0'); // Loop through all of the modules. for (k = 0; k < list_size(&modules); k++) { ds = list_get_at(&modules, k); // Set stack top (I don't know why the top of the // stack is negative!) lua_settop(ds->state, 0); // Search handler table for entries. lua_getglobal(ds->state, HANDLER_TABLE_COMMANDS_NAME); lua_getfield(ds->state, -1, cstr); if (!lua_istable(ds->state, -1)) { // No such entry. lua_pop(ds->state, 2); continue; } // Call the handler function. lua_getfield(ds->state, -1, HANDLER_FIELD_FUNCTION_NAME); dbg_lua_push_state(ds, state, ud); lua_newtable(ds->state); paramtbl = lua_gettop(ds->state); for (i = 0; i < list_size(parameters); i++) { carg = list_get_at(parameters, i); lua_newtable(ds->state); if (carg->type == DBG_CUSTOMARG_TYPE_PATH) lua_pushstring(ds->state, "PATH"); else if (carg->type == DBG_CUSTOMARG_TYPE_PARAM) lua_pushstring(ds->state, "PARAM"); else if (carg->type == DBG_CUSTOMARG_TYPE_STRING) lua_pushstring(ds->state, "STRING"); else lua_pushstring(ds->state, "NUMBER"); lua_setfield(ds->state, -2, "type"); if (carg->type == DBG_CUSTOMARG_TYPE_PATH) lua_pushstring(ds->state, carg->path->data); else if (carg->type == DBG_CUSTOMARG_TYPE_PARAM) lua_pushstring(ds->state, carg->param->data); else if (carg->type == DBG_CUSTOMARG_TYPE_STRING) lua_pushstring(ds->state, carg->string->data); else lua_pushnumber(ds->state, carg->number); lua_setfield(ds->state, -2, "value"); lua_rawseti(ds->state, paramtbl, i + 1); } if (lua_pcall(ds->state, 2, 0, 0) != 0) { printd(LEVEL_ERROR, "error: unable to call debugger command handler for '%s'.\n", name.ref->data); printd(LEVEL_ERROR, "%s\n", lua_tostring(ds->state, -1)); bautodestroy(name); bcstrfree(cstr); lua_pop(ds->state, 2); list_iterator_stop(&modules); list_destroy(parameters); return; } bautodestroy(name); bcstrfree(cstr); lua_pop(ds->state, 2); list_iterator_stop(&modules); list_destroy(parameters); // The command may have started the virtual machine, check the // status of the VM and execute if needed. if (state->get_vm()->halted == false) vm_execute(state->get_vm(), NULL); return; } // There is no command to handle this. printd(LEVEL_ERROR, "no such command found.\n"); // Clean up. list_destroy(parameters); bautodestroy(name); bcstrfree(cstr); }