From 8e19f7ce0dd092a1a98c6faf5625c5c4f3aef0db Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 7 Jul 2023 11:38:31 +0200 Subject: [PATCH] WIP: handling vtable generation --- btparser/main.cpp | 262 +++++++++++++++++++++++++++++----------------- 1 file changed, 165 insertions(+), 97 deletions(-) diff --git a/btparser/main.cpp b/btparser/main.cpp index 21bddd9..ff8e53f 100644 --- a/btparser/main.cpp +++ b/btparser/main.cpp @@ -6,132 +6,200 @@ #include "helpers.h" #include "preprocessor.h" #include "types.h" +#include -bool TestLexer(Lexer & lexer, const std::string & filename) +bool TestLexer(Lexer& lexer, const std::string& filename) { - if(!lexer.ReadInputFile("tests\\" + filename)) - { - printf("failed to read \"%s\"\n", filename.c_str()); - return false; - } - std::string actual; - actual.reserve(65536); - auto success = lexer.Test([&](const std::string & line) - { - actual.append(line); - }); - std::string expected; - if(FileHelper::ReadAllText("tests\\exp_lex\\" + filename, expected) && expected == actual) - { - printf("lexer test for \"%s\" success!\n", filename.c_str()); - return true; - } - if(success) - return true; - printf("lexer test for \"%s\" failed...\n", filename.c_str()); - FileHelper::WriteAllText("expected.out", expected); - FileHelper::WriteAllText("actual.out", actual); - return false; + if (!lexer.ReadInputFile("tests\\" + filename)) + { + printf("failed to read \"%s\"\n", filename.c_str()); + return false; + } + std::string actual; + actual.reserve(65536); + auto success = lexer.Test([&](const std::string& line) + { + actual.append(line); + }); + std::string expected; + if (FileHelper::ReadAllText("tests\\exp_lex\\" + filename, expected) && expected == actual) + { + printf("lexer test for \"%s\" success!\n", filename.c_str()); + return true; + } + if (success) + return true; + printf("lexer test for \"%s\" failed...\n", filename.c_str()); + FileHelper::WriteAllText("expected.out", expected); + FileHelper::WriteAllText("actual.out", actual); + return false; } -bool DebugLexer(Lexer & lexer, const std::string & filename, bool output) +bool DebugLexer(Lexer& lexer, const std::string& filename, bool output) { - if(!lexer.ReadInputFile("tests\\" + filename)) - { - printf("failed to read \"%s\"\n", filename.c_str()); - return false; - } - auto success = lexer.Test([](const std::string & line) - { - printf("%s", line.c_str()); - }, output); - if(output) - puts(""); - return success; + if (!lexer.ReadInputFile("tests\\" + filename)) + { + printf("failed to read \"%s\"\n", filename.c_str()); + return false; + } + auto success = lexer.Test([](const std::string& line) + { + printf("%s", line.c_str()); + }, output); + if (output) + puts(""); + return success; } -void GenerateExpected(Lexer & lexer, const std::string & filename) +void GenerateExpected(Lexer& lexer, const std::string& filename) { - if(!lexer.ReadInputFile("tests\\" + filename)) - { - printf("failed to read \"%s\"\n", filename.c_str()); - return; - } - std::string actual; - actual.reserve(65536); - lexer.Test([&](const std::string & line) - { - actual.append(line); - }); - FileHelper::WriteAllText("tests\\exp_lex\\" + filename, actual); + if (!lexer.ReadInputFile("tests\\" + filename)) + { + printf("failed to read \"%s\"\n", filename.c_str()); + return; + } + std::string actual; + actual.reserve(65536); + lexer.Test([&](const std::string& line) + { + actual.append(line); + }); + FileHelper::WriteAllText("tests\\exp_lex\\" + filename, actual); } void GenerateExpectedTests() { - Lexer lexer; - for(auto file : testFiles) - GenerateExpected(lexer, file); + Lexer lexer; + for (auto file : testFiles) + GenerateExpected(lexer, file); } void RunLexerTests() { - Lexer lexer; - for(auto file : testFiles) - TestLexer(lexer, file); + Lexer lexer; + for (auto file : testFiles) + TestLexer(lexer, file); } void DebugLexerTests(bool output = true) { - Lexer lexer; - for(auto file : testFiles) - DebugLexer(lexer, file, output); + Lexer lexer; + for (auto file : testFiles) + DebugLexer(lexer, file, output); } -bool DebugParser(const std::string & filename) +static std::vector SplitNamespace(const std::string& name, std::string& type) { - std::string data; - if (!FileHelper::ReadAllText("tests\\" + filename, data)) - { - printf("Failed to read: %s\n", filename.c_str()); - return false; - } + auto namespaces = StringUtils::Split(name, ':'); + if (namespaces.empty()) + { + type.clear(); + } + else + { + type = namespaces.back(); + namespaces.pop_back(); + } + return namespaces; +} - std::string pperror; - std::unordered_map definitions; - definitions["WIN32"] = ""; - definitions["_MSC_VER"] = "1337"; - auto ppData = preprocess(data, pperror, definitions); - if (!pperror.empty()) - { - printf("Preprocess error: %s\n", pperror.c_str()); - return false; - } +static void HandleVTable(Types::Model& model) +{ + std::unordered_set classes; + std::unordered_set visited; + auto handleType = [&](const Types::QualifiedType& type) + { + if (!type.kind.empty()) + { + const auto& name = type.name; + const auto& kind = type.kind; + if (visited.count(name) != 0) + return; + visited.insert(name); + std::string rettype; + auto namespaces = SplitNamespace(name, rettype); + if (kind == "class" && rettype[0] == 'I') + classes.insert(name); + for (const auto& ns : namespaces) + { + printf("namespace %s {\n", ns.c_str()); + } + printf(" %s %s {\n };\n", kind.c_str(), rettype.c_str()); + for (const auto& ns : namespaces) + printf("}\n"); + } + }; + for (const auto& su : model.structUnions) + { + for (const auto& vf : su.vtable) + { + handleType(vf.rettype); + for (const auto& arg : vf.args) + handleType(arg.type); + } + } + for (const auto& f : model.functions) + { + handleType(f.rettype); + for (const auto& arg : f.args) + handleType(arg.type); + } - FileHelper::WriteAllText("tests\\" + filename + ".pp.h", ppData); + puts("Used classes:"); + for (const auto& name : classes) + { + printf("%s\n", name.c_str()); + } + puts("vtable chuj"); +} - std::vector errors; - Types::TypeManager typeManager(sizeof(void*)); - if (!typeManager.ParseTypes(ppData, filename, errors)) - { - puts("Failed to parse types:"); - for (const auto& error : errors) - puts(error.c_str()); - return false; - } +bool DebugParser(const std::string& filename) +{ + std::string data; + if (!FileHelper::ReadAllText("tests\\" + filename, data)) + { + printf("Failed to read: %s\n", filename.c_str()); + return false; + } - puts("ParseFile success!"); - return true; + std::string pperror; + std::unordered_map definitions; + definitions["WIN32"] = ""; + definitions["_MSC_VER"] = "1337"; + auto ppData = preprocess(data, pperror, definitions); + if (!pperror.empty()) + { + printf("Preprocess error: %s\n", pperror.c_str()); + return false; + } + + FileHelper::WriteAllText("tests\\" + filename + ".pp.h", ppData); + + std::vector errors; + Types::Model model; + if (!Types::ParseModel(ppData, filename, errors, model)) + { + puts("Failed to parse types:"); + for (const auto& error : errors) + puts(error.c_str()); + return false; + } + puts("ParseModel success!"); + + HandleVTable(model); + + return true; } int main() { - //GenerateExpectedTests(); - auto ticks = GetTickCount(); - DebugParser("cursor.hpp"); - //Lexer lexer; - //DebugLexer(lexer, "AndroidManifestTemplate.bt", false); - //RunLexerTests(); - printf("finished in %ums\n", GetTickCount() - ticks); - system("pause"); - return 0; + //GenerateExpectedTests(); + auto ticks = GetTickCount(); + DebugParser("cursor.hpp"); + //Lexer lexer; + //DebugLexer(lexer, "AndroidManifestTemplate.bt", false); + //RunLexerTests(); + printf("finished in %ums\n", (unsigned int)(GetTickCount() - ticks)); + system("pause"); + return 0; } \ No newline at end of file