You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.4 KiB
C++
195 lines
5.4 KiB
C++
3 years ago
|
/**
|
||
|
* @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 <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#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 <cstdio>
|
||
|
#include <filesystem>
|
||
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <string>
|
||
|
|
||
|
extern std::string tempFileName;
|
||
|
extern std::string statusMessage;
|
||
|
extern stmdsp::device *m_device;
|
||
|
|
||
|
TextEditor editor; // file.cpp
|
||
|
static std::string editorCompiled;
|
||
|
static std::string compileMessage;
|
||
|
|
||
|
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, 635}, true);
|
||
|
|
||
|
if (ImGui::BeginPopup("compile", ImGuiWindowFlags_AlwaysHorizontalScrollbar)) {
|
||
|
ImGui::Text(compileMessage.c_str());
|
||
|
if (ImGui::Button("Close"))
|
||
|
ImGui::CloseCurrentPopup();
|
||
|
ImGui::EndPopup();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void compileEditorCode()
|
||
|
{
|
||
|
// 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();
|
||
|
compileMessage = sstr.str();
|
||
|
|
||
|
std::filesystem::remove(tempFileName);
|
||
|
std::filesystem::remove(tempFileName + script_ext);
|
||
|
std::filesystem::remove(makeOutput);
|
||
|
|
||
|
if (result == 0) {
|
||
|
editorCompiled = editor.GetText();
|
||
|
statusMessage = "Compilation succeeded.";
|
||
|
} else {
|
||
|
statusMessage = "Compilation failed.";
|
||
|
ImGui::OpenPopup("compile");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void disassembleCode()
|
||
|
{
|
||
|
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();
|
||
|
compileMessage = sstr.str();
|
||
|
}
|
||
|
|
||
|
ImGui::OpenPopup("compile");
|
||
|
std::filesystem::remove(output);
|
||
|
|
||
|
statusMessage = "Ready.";
|
||
|
} else {
|
||
|
statusMessage = "Failed to load disassembly.";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::string newTempFileName()
|
||
|
{
|
||
|
auto tempPath = std::filesystem::temp_directory_path();
|
||
|
tempPath /= "stmdspgui_build";
|
||
|
return tempPath.string();
|
||
|
}
|
||
|
|