/** * @file code.cpp * @brief Contains code for algorithm-code-related UI elements and logic. * * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. * If not, see . */ #include "imgui.h" #include "backends/imgui_impl_sdl.h" #include "backends/imgui_impl_opengl2.h" #include "TextEditor.h" #include "config.h" #include "stmdsp.hpp" #include "stmdsp_code.hpp" #include #include #include #include #include extern std::string tempFileName; extern stmdsp::device *m_device; extern void log(const std::string& str); TextEditor editor; // file.cpp static std::string editorCompiled; static std::string newTempFileName(); static void compileEditorCode(); static void disassembleCode(); void codeEditorInit() { editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus()); editor.SetPalette(TextEditor::GetLightPalette()); } void codeRenderMenu() { if (ImGui::BeginMenu("Code")) { if (ImGui::MenuItem("Compile code")) compileEditorCode(); if (ImGui::MenuItem("Show disassembly")) disassembleCode(); ImGui::EndMenu(); } } void codeRenderToolbar() { if (ImGui::Button("Compile")) compileEditorCode(); ImGui::SameLine(); ImGui::Button("Upload"); } void codeRenderWidgets() { editor.Render("code", {WINDOW_WIDTH - 15, 450}, true); } void compileEditorCode() { log("Compiling..."); // Scrap cached build if there are changes if (editor.GetText().compare(editorCompiled) != 0) { std::filesystem::remove(tempFileName + ".o"); std::filesystem::remove(tempFileName + ".orig.o"); } stmdsp::platform platform; if (m_device != nullptr) { platform = m_device->get_platform(); } else { // Assume a default. platform = stmdsp::platform::L4; } if (tempFileName.size() == 0) tempFileName = newTempFileName(); { std::ofstream file (tempFileName, std::ios::trunc | std::ios::binary); auto file_text = platform == stmdsp::platform::L4 ? stmdsp::file_header_l4 : stmdsp::file_header_h7; auto samples_text = std::to_string(m_device ? m_device->get_buffer_size() : stmdsp::SAMPLES_MAX); for (std::size_t i = 0; (i = file_text.find("$0", i)) != std::string::npos;) { file_text.replace(i, 2, samples_text); i += 2; } file << file_text; file << "\n"; file << editor.GetText(); } constexpr const char *script_ext = #ifndef STMDSP_WIN32 ".sh"; #else ".bat"; #endif { std::ofstream makefile (tempFileName + script_ext, std::ios::binary); auto make_text = platform == stmdsp::platform::L4 ? stmdsp::makefile_text_l4 : stmdsp::makefile_text_h7; auto cwd = std::filesystem::current_path().string(); for (std::size_t i = 0; (i = make_text.find("$0", i)) != std::string::npos;) { make_text.replace(i, 2, tempFileName); i += 2; } for (std::size_t i = 0; (i = make_text.find("$1", i)) != std::string::npos;) { make_text.replace(i, 2, cwd); i += 2; } makefile << make_text; } auto makeOutput = tempFileName + script_ext + ".log"; auto makeCommand = tempFileName + script_ext + " > " + makeOutput + " 2>&1"; #ifndef STMDSP_WIN32 system((std::string("chmod +x ") + tempFileName + script_ext).c_str()); #endif int result = system(makeCommand.c_str()); std::ifstream result_file (makeOutput); std::ostringstream sstr; sstr << result_file.rdbuf(); log(sstr.str().c_str()); std::filesystem::remove(tempFileName); std::filesystem::remove(tempFileName + script_ext); std::filesystem::remove(makeOutput); if (result == 0) { editorCompiled = editor.GetText(); log("Compilation succeeded."); } else { log("Compilation failed."); } } void disassembleCode() { log("Disassembling..."); if (tempFileName.size() == 0 || editor.GetText().compare(editorCompiled) != 0) { compileEditorCode(); } auto output = tempFileName + ".asm.log"; auto command = std::string("arm-none-eabi-objdump -d --no-show-raw-insn ") + tempFileName + ".orig.o > " + output + " 2>&1"; if (system(command.c_str()) == 0) { { std::ifstream result_file (output); std::ostringstream sstr; sstr << result_file.rdbuf(); log(sstr.str().c_str()); } ImGui::OpenPopup("compile"); std::filesystem::remove(output); log("Ready."); } else { log("Failed to load disassembly."); } } std::string newTempFileName() { auto tempPath = std::filesystem::temp_directory_path(); tempPath /= "stmdspgui_build"; return tempPath.string(); }