diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2023-08-08 23:10:02 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2023-08-08 23:10:02 -0400 |
commit | f440728644ad3698ffd6af1abcfcc07aad5793c3 (patch) | |
tree | 68aff014ff17933717616f2f8d407b51611afe2b /gui/source/code.cpp |
initial commit
* combine all source files into this monorepo
* convert all third-party source packages into submodules
* small fixes due to changes in latest third-part packages
Diffstat (limited to 'gui/source/code.cpp')
-rw-r--r-- | gui/source/code.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/gui/source/code.cpp b/gui/source/code.cpp new file mode 100644 index 0000000..f24bb5c --- /dev/null +++ b/gui/source/code.cpp @@ -0,0 +1,172 @@ +/** + * @file code.cpp + * @brief Functionality for compiling and disassembling source code. + * + * Copyright (C) 2022 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 "main.hpp" +#include "stmdsp.hpp" +#include "stmdsp_code.hpp" + +#include <cstdio> +#include <filesystem> +#include <fstream> +#include <iostream> +#include <memory> +#include <string> + +extern std::shared_ptr<stmdsp::device> m_device; + +// Stores the temporary file name currently used for compiling the algorithm. +static std::string tempFileName; + +/** + * Generates a new temporary file name. + * @return A string containing the path and file name. + */ +static std::string newTempFileName(); + +/** + * Executes the given command using system(), collecting the text output in the + * given file. + * @param command The command to be executed. + * @param file The file to write command output to. + * @return True if the command was successful (i.e. returned zero). + */ +static bool codeExecuteCommand(const std::string& command, const std::string& file); + +/** + * Does an in-place replacement of all occurances of "what" with "with". + * @param str The text string to operate on. + * @param what The text to search for. + * @param with The text that will replace occurances of "what". + */ +static void stringReplaceAll(std::string& str, const std::string& what, + const std::string& with); + +std::ifstream compileOpenBinaryFile() +{ + if (!tempFileName.empty()) + return std::ifstream(tempFileName + ".o"); + else + return std::ifstream(); +} + +void compileEditorCode(const std::string& code) +{ + log("Compiling..."); + + if (tempFileName.empty()) { + tempFileName = newTempFileName(); + } else { + std::filesystem::remove(tempFileName + ".o"); + std::filesystem::remove(tempFileName + ".orig.o"); + } + + const auto platform = m_device ? m_device->get_platform() + : stmdsp::platform::L4; + + { + 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; + const auto buffer_size = m_device ? m_device->get_buffer_size() + : stmdsp::SAMPLES_MAX; + + stringReplaceAll(file_text, "$0", std::to_string(buffer_size)); + + file << file_text << '\n' << code; + } + + const auto scriptFile = tempFileName + +#ifndef STMDSP_WIN32 + ".sh"; +#else + ".bat"; +#endif + + { + std::ofstream makefile (scriptFile, std::ios::binary); + auto make_text = + platform == stmdsp::platform::L4 ? stmdsp::makefile_text_l4 + : stmdsp::makefile_text_h7; + + stringReplaceAll(make_text, "$0", tempFileName); + stringReplaceAll(make_text, "$1", + std::filesystem::current_path().string()); + + makefile << make_text; + } + +#ifndef STMDSP_WIN32 + system((std::string("chmod +x ") + scriptFile).c_str()); +#endif + + const auto makeOutput = scriptFile + ".log"; + const auto makeCommand = scriptFile + " > " + makeOutput + " 2>&1"; + if (codeExecuteCommand(makeCommand, makeOutput)) + log("Compilation succeeded."); + else + log("Compilation failed."); + + std::filesystem::remove(tempFileName); + std::filesystem::remove(scriptFile); +} + +void disassembleCode() +{ + log("Disassembling..."); + + //if (tempFileName.empty()) + // compileEditorCode(); + + const auto output = tempFileName + ".asm.log"; + const auto command = + std::string("arm-none-eabi-objdump -d --no-show-raw-insn ") + + tempFileName + ".orig.o > " + output + " 2>&1"; + + if (codeExecuteCommand(command, output)) + log("Ready."); + else + log("Failed to load disassembly."); +} + +std::string newTempFileName() +{ + const auto path = std::filesystem::temp_directory_path() / "stmdspgui_build"; + return path.string(); +} + +bool codeExecuteCommand(const std::string& command, const std::string& file) +{ + bool success = system(command.c_str()) == 0; + + if (std::ifstream output (file); output.good()) { + std::ostringstream sstr; + sstr << output.rdbuf(); + log(sstr.str().c_str()); + } else { + log("Could not read command output!"); + } + + std::filesystem::remove(file); + + return success; +} + +void stringReplaceAll(std::string& str, const std::string& what, const std::string& with) +{ + std::size_t i; + while ((i = str.find(what)) != std::string::npos) { + str.replace(i, what.size(), with); + i += what.size(); + } +}; + |