From f440728644ad3698ffd6af1abcfcc07aad5793c3 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Tue, 8 Aug 2023 23:10:02 -0400
Subject: 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
---
 gui/source/code.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)
 create mode 100644 gui/source/code.cpp

(limited to 'gui/source/code.cpp')

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();
+    }
+};
+
-- 
cgit v1.2.3