diff options
author | rtk0c <[email protected]> | 2022-05-24 21:47:55 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-05-24 21:47:55 -0700 |
commit | d18a28a9659092952aef70a30a47726e7c16d31a (patch) | |
tree | b1d6304e631961a797225912ed1ef7ee55864f86 /buildtools/codegen | |
parent | 123f741e3f5374b93ac39887b62bfa0d66762ae2 (diff) |
Changeset: 38 Branch comment: [] Add infrastructure for codegen
Diffstat (limited to 'buildtools/codegen')
-rw-r--r-- | buildtools/codegen/README.md | 5 | ||||
-rw-r--r-- | buildtools/codegen/main.cpp | 102 |
2 files changed, 107 insertions, 0 deletions
diff --git a/buildtools/codegen/README.md b/buildtools/codegen/README.md new file mode 100644 index 0000000..7164132 --- /dev/null +++ b/buildtools/codegen/README.md @@ -0,0 +1,5 @@ +# Code Generator +The main code generator. + +## Folder structure +The main program's source files are all located in this folder directly. Text tempaltes are located in `templates/` and none of the files are compiled (even if they end with .c or .cpp). diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp new file mode 100644 index 0000000..4a1d486 --- /dev/null +++ b/buildtools/codegen/main.cpp @@ -0,0 +1,102 @@ +#include "ScopeGuard.hpp" +#include "Utils.hpp" + +#include <stb_c_lexer.h> +#include <filesystem> +#include <string> +#include <string_view> + +using namespace std::literals; +namespace fs = std::filesystem; + +enum InputOpcode { + IOP_ProcessSingleFile, + IOP_ProcessRecursively, + IOP_COUNT, +}; + +InputOpcode ParseInputOpcode(std::string_view text) { + if (text == "single"sv) { + return IOP_ProcessSingleFile; + } else if (text == "rec"sv) { + return IOP_ProcessRecursively; + } + return IOP_COUNT; +} + +void HandleInputFile(std::string_view source) { + stb_lexer lexer; + char stringStorage[65536]; + const char* srcBegin = source.data(); + const char* srcEnd = srcBegin + source.length(); + stb_c_lexer_init(&lexer, srcBegin, srcEnd, stringStorage, sizeof(stringStorage)); + + // TODO +} + +std::string ReadFileAtOnce(const fs::path& path) { + auto file = Utils::OpenCstdioFile(path, Utils::Read); + if (!file) throw std::runtime_error("Failed to open source file."); + DEFER { fclose(file); }; + + fseek(file, 0, SEEK_END); + auto fileSize = ftell(file); + rewind(file); + + std::string result(fileSize, '\0'); + fread(result.data(), fileSize, 1, file); + + return result; +} + +void HandleArgument(InputOpcode opcode, std::string_view operand) { + switch (opcode) { + case IOP_ProcessSingleFile: { + fs::path filePath(operand); + auto source = ReadFileAtOnce(filePath); + HandleInputFile(source); + } break; + + case IOP_ProcessRecursively: { + fs::path startPath(operand); + for (auto& item : fs::directory_iterator(startPath)) { + if (!item.is_regular_file()) { + continue; + } + + auto& path = item.path(); + auto filename = path.filename().string(); + if (filename != ".c" || + filename != ".cpp") + { + continue; + } + + auto source = ReadFileAtOnce(path); + HandleInputFile(source); + } + } break; + + case IOP_COUNT: break; + } +} + +int main(int argc, char* argv[]) { + // TODO better arg parser + // option 1: use cxxopts and positional arguments + // option 1: take one argument only, being a json objecet + + // If no cli is provided (argv[0]), this loop will do nothing + // Otherwise, start with the 2nd element which is the 1st argument + for (int i = 1; i < argc; ++i) { + std::string_view arg(argv[i]); + auto separatorLoc = arg.find(':'); + if (separatorLoc != std::string_view::npos) { + auto opcode = ParseInputOpcode(arg.substr(0, separatorLoc)); + auto operand = arg.substr(separatorLoc); + HandleArgument(opcode, operand); + } + } + + return 0; +} |