From d2ad800b836548f59f5818ecf0a2d9cf8771e49e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 16:54:27 +0300 Subject: [PATCH 01/18] Avoid Boost.Spirit usage --- include/boost/dll/alias.hpp | 6 +- include/boost/dll/detail/demangling/msvc.hpp | 112 ++++++++++++++++--- test/Jamfile.v2 | 1 + test/cpp_mangling.cpp | 36 ++++++ test/shared_library_errors.cpp | 1 - 5 files changed, 136 insertions(+), 20 deletions(-) create mode 100644 test/cpp_mangling.cpp diff --git a/include/boost/dll/alias.hpp b/include/boost/dll/alias.hpp index a30fbb5b..711fbe17 100644 --- a/include/boost/dll/alias.hpp +++ b/include/boost/dll/alias.hpp @@ -44,7 +44,7 @@ namespace boost { namespace dll { #define BOOST_DLL_SELECTANY __declspec(selectany) #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ @@ -83,7 +83,7 @@ namespace boost { namespace dll { * \param Permissions Can be "read" or "write" (without quotes!). */ #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ @@ -92,7 +92,7 @@ namespace boost { namespace dll { #else // #if !BOOST_OS_MACOS && !BOOST_OS_IOS #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 927428d4..ab536f03 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -8,6 +8,9 @@ #define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ #include + +#include + #include #include #include @@ -106,9 +109,50 @@ namespace parser return ptr_rule_impl(std::integral_constant()); } + inline boost::core::string_view trim_ptrs(boost::core::string_view s) { + bool retry = false; + do { + retry = false; + while (s.starts_with(" ")) { + s.remove_prefix(1); + } + + if (s.starts_with("__ptr32") || s.starts_with("__ptr64")) { + s.remove_prefix(sizeof("__ptr64") - 1); + retry = true; + } + } while (retry); + + return s; + } + auto const visibility = ("public:" | x3::lit("protected:") | "private:"); + inline std::string::size_type find_visibility(boost::core::string_view s) { + if (s.starts_with("public:")) { + return sizeof("public:") - 1; + } else if (s.starts_with("protected:")) { + return sizeof("protected:") - 1; + } else if (s.starts_with("private:")) { + return sizeof("private:") - 1; + } + return std::string::npos; + } + auto const virtual_ = x3::space >> "virtual"; + inline std::string::size_type find_virtual(boost::core::string_view s) { + if (s.starts_with(" virtual")) { + return sizeof(" virtual") - 1; + } + return std::string::npos; + } + auto const static_ = x3::space >> x3::lit("static") ; + inline std::string::size_type find_static(boost::core::string_view s) { + if (s.starts_with(" static")) { + return sizeof(" static") - 1; + } + return std::string::npos; + } inline auto const_rule_impl(std::true_type ) {return x3::space >> "const";}; inline auto const_rule_impl(std::false_type) {return x3::eps;}; @@ -164,6 +208,18 @@ namespace parser #else auto const thiscall = "__thiscall" >> x3::space; #endif + inline std::string::size_type find_thiscall(boost::core::string_view s) { +#if defined(_WIN64)//seems to be necessary by msvc 14-x64 + if (s.starts_with(" __cdecl ")) { + return sizeof(" __cdecl ") - 1; + } +#else + if (s.starts_with(" __thiscall ")) { + return sizeof(" __thiscall ") - 1; + } +#endif + return std::string::npos; + } template auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) @@ -183,6 +239,45 @@ namespace parser { return x3::string("void"); } + + struct is_destructor_with_name { + const std::string dtor_name; + + inline bool operator()(boost::core::string_view s) const { + { + const auto visibility_pos = find_visibility(s); + if (visibility_pos == std::string::npos) { + return false; + } + s.remove_prefix(visibility_pos); + } + { + const auto virtual_pos = find_visibility(s); + if (virtual_pos != std::string::npos) { + return false; + } + } + { + // cdecl declaration for methods. stdcall cannot be + const auto thiscall_pos = find_thiscall(s); + if (thiscall_pos == std::string::npos) { + return false; + } + s.remove_prefix(thiscall_pos); + } + + if (!s.starts_with(dtor_name)) { + return false; + } + s.remove_prefix(dtor_name.size()); + s = trim_ptrs(s); + return s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; } @@ -367,22 +462,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym } } - auto matcher = - visibility >> -virtual_ >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - dtor_name >> parser::ptr_rule(); - - - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); + auto found = std::find_if(storage_.begin(), storage_.end(), is_destructor_with_name{dtor_name}); if (found != storage_.end()) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 692422e4..5779e7bf 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -99,6 +99,7 @@ project [ compile-fail section_name_too_big.cpp ] [ run shared_library_concurrent_load_test.cpp /boost/thread//boost_thread : : library1 library2 my_plugin_aggregator refcounting_plugin : shared ] [ run cpp_mangle_test.cpp : : cpp_plugin ] + [ run cpp_mangling.cpp ] [ run cpp_load_test.cpp : : cpp_plugin ] [ run cpp_import_test.cpp : : cpp_plugin ] [ run template_method_linux_test.cpp : : cpp_plugin ] diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp new file mode 100644 index 00000000..45dfd940 --- /dev/null +++ b/test/cpp_mangling.cpp @@ -0,0 +1,36 @@ +// Copyright 2024 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include + +#include + +int main(int argc, char* argv[]) +{ + namespace parser = boost::dll::detail::parser; + +#if defined(_WIN64) + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __cdecl foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __cdecl foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __cdecl foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __cdecl foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __cdecl foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __cdecl foo(void) __ptr64")); +#else + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __thiscall foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __thiscall foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __thiscall foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __thiscall foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __thiscall foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __thiscall foo(void) __ptr32")); +#endif + + return boost::report_errors(); +} diff --git a/test/shared_library_errors.cpp b/test/shared_library_errors.cpp index b5f532cf..5fce7f43 100644 --- a/test/shared_library_errors.cpp +++ b/test/shared_library_errors.cpp @@ -12,7 +12,6 @@ #include #include #include -#include // Unit Tests From 6bfec84ba6779b34d00081684f6b4af83d9edf17 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 17:41:32 +0300 Subject: [PATCH 02/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 63 +++++++++++++++++--- test/cpp_mangling.cpp | 45 ++++++++------ 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index ab536f03..d5a5c7cb 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -126,6 +126,13 @@ namespace parser return s; } + boost::core::string_view trim_prefix(boost::core::string_view s, boost::core::string_view prefix) { + if (s.starts_with(prefix)) { + s.remove_prefix(prefix.size()); + } + return s; + } + auto const visibility = ("public:" | x3::lit("protected:") | "private:"); inline std::string::size_type find_visibility(boost::core::string_view s) { if (s.starts_with("public:")) { @@ -201,6 +208,49 @@ namespace parser template<> inline auto type_rule(const std::string &) { return x3::string("void"); }; + template + std::string::size_type find_type(const mangled_storage_impl& ms, boost::core::string_view s_orig) { + if (std::is_void::value) { + if (s_orig.starts_with("void")) { + return sizeof("void") - 1; + } + return std::string::npos; + } + + auto s = s_orig; + s = trim_prefix(s, "class "); + s = trim_prefix(s, "struct "); + + const auto& mangled_name = ms.get_name(); + if (!s.starts_with(mangled_name)) { + return std::string::npos; + } + s.remove_prefix(mangled_name.size()); + + if (std::is_const::value && !s.starts_with(" const")) { + return std::string::npos; + } + s.remove_prefix(sizeof(" const") - 1); + + if (std::is_volatile::value && !s.starts_with(" volatile")) { + return std::string::npos; + } + s.remove_prefix(sizeof(" volatile") - 1); + + if (std::is_rvalue_reference::value && !s.starts_with(" &&")) { + return std::string::npos; + } + s.remove_prefix(sizeof(" &&") - 1); + + if (std::is_lvalue_reference::value && !s.starts_with(" &")) { + return std::string::npos; + } + s.remove_prefix(sizeof(" &") - 1); + + s = trim_ptrs(s); + return s_orig.size() - s.size(); + } + auto const cdecl_ = "__cdecl" >> x3::space; auto const stdcall = "__stdcall" >> x3::space; #if defined(_WIN64)//seems to be necessary by msvc 14-x64 @@ -209,15 +259,11 @@ namespace parser auto const thiscall = "__thiscall" >> x3::space; #endif inline std::string::size_type find_thiscall(boost::core::string_view s) { -#if defined(_WIN64)//seems to be necessary by msvc 14-x64 - if (s.starts_with(" __cdecl ")) { + if (s.starts_with(" __cdecl ")) { // Win 64bit return sizeof(" __cdecl ") - 1; - } -#else - if (s.starts_with(" __thiscall ")) { + } else if (s.starts_with(" __thiscall ")) { // Win 32bit return sizeof(" __thiscall ") - 1; } -#endif return std::string::npos; } @@ -257,6 +303,7 @@ namespace parser return false; } } + s = trim_prefix(s, " virtual"); { // cdecl declaration for methods. stdcall cannot be const auto thiscall_pos = find_thiscall(s); @@ -443,7 +490,6 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym template auto mangled_storage_impl::get_destructor() const -> dtor_sym { - namespace x3 = spirit::x3; using namespace parser; std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name @@ -462,8 +508,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym } } - auto found = std::find_if(storage_.begin(), storage_.end(), is_destructor_with_name{dtor_name}); - + const auto found = std::find_if(storage_.begin(), storage_.end(), is_destructor_with_name{dtor_name}); if (found != storage_.end()) return found->mangled; diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 45dfd940..3138632a 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -14,23 +14,34 @@ int main(int argc, char* argv[]) { namespace parser = boost::dll::detail::parser; -#if defined(_WIN64) - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __cdecl foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __cdecl foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __cdecl foo(void)")); - - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __cdecl foo(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __cdecl foo(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __cdecl foo(void) __ptr64")); -#else - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __thiscall foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __thiscall foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __thiscall foo(void)")); - - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("public: __thiscall foo(void) __ptr32")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("private: __thiscall foo(void) __ptr32")); - BOOST_TEST(parser::is_destructor_with_name{"foo(void)"}("protected: __thiscall foo(void) __ptr32")); -#endif + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __cdecl foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: virtual __cdecl foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __cdecl foo::~foo(void) __ptr64")); + + BOOST_TEST(parser::is_destructor_with_name{"some_space::some_father::~some_father(void)"}("public: __cdecl some_space::some_father::~some_father(void) __ptr64")); + + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __thiscall foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: virtual __thiscall foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __thiscall foo::~foo(void) __ptr32")); + + BOOST_TEST(parser::is_destructor_with_name{"some_space::some_father::~some_father(void)"}("public: __thiscall some_space::some_father::~some_father(void) __ptr64")); + return boost::report_errors(); } From ff420ae1188ef0c8e6a680ae85641500b09b04e8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 18:46:47 +0300 Subject: [PATCH 03/18] wip --- include/boost/dll/detail/demangling/msvc.hpp | 161 ++++++++++++++----- test/cpp_mangling.cpp | 36 +++++ 2 files changed, 154 insertions(+), 43 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index d5a5c7cb..b9e51ce1 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -110,7 +110,7 @@ namespace parser } inline boost::core::string_view trim_ptrs(boost::core::string_view s) { - bool retry = false; + bool retry = false; do { retry = false; while (s.starts_with(" ")) { @@ -227,25 +227,37 @@ namespace parser } s.remove_prefix(mangled_name.size()); - if (std::is_const::value && !s.starts_with(" const")) { - return std::string::npos; + if (std::is_const::value) { + if (!s.starts_with(" const")) { + return std::string::npos; + } else { + s.remove_prefix(sizeof(" const") - 1); + } } - s.remove_prefix(sizeof(" const") - 1); - if (std::is_volatile::value && !s.starts_with(" volatile")) { - return std::string::npos; + if (std::is_volatile::value) { + if (!s.starts_with(" volatile")) { + return std::string::npos; + } else { + s.remove_prefix(sizeof(" volatile") - 1); + } } - s.remove_prefix(sizeof(" volatile") - 1); - if (std::is_rvalue_reference::value && !s.starts_with(" &&")) { - return std::string::npos; + if (std::is_rvalue_reference::value) { + if (!s.starts_with(" &&")) { + return std::string::npos; + } else { + s.remove_prefix(sizeof(" &&") - 1); + } } - s.remove_prefix(sizeof(" &&") - 1); - if (std::is_lvalue_reference::value && !s.starts_with(" &")) { - return std::string::npos; + if (std::is_lvalue_reference::value) { + if (!s.starts_with(" &")) { + return std::string::npos; + } else { + s.remove_prefix(sizeof(" &") - 1); + } } - s.remove_prefix(sizeof(" &") - 1); s = trim_ptrs(s); return s_orig.size() - s.size(); @@ -286,38 +298,121 @@ namespace parser return x3::string("void"); } + + template + std::string::size_type find_arg_list(const mangled_storage_impl& ms, boost::core::string_view s, Return (*)(Arg)) + { + return parser::find_type(ms, s); + } + + template + std::string::size_type find_arg_list(const mangled_storage_impl & ms, boost::core::string_view s, Return (*)(First, Second, Args...)) + { + using next_type = Return (*)(Second, Args...); + + const auto res = parser::find_type(ms, s); + if (res == std::string::npos) { + return std::string::npos; + } + s.remove_prefix(res); + if (!s.starts_with(",")) { + return std::string::npos; + } + s.remove_prefix(1); + + const auto new_res = parser::find_arg_list(ms, s, next_type()); + if (new_res == std::string::npos) { + return std::string::npos; + } + + return res + 1 + new_res; + } + + template + std::string::size_type find_arg_list(const mangled_storage_impl& ms, boost::core::string_view s, Return (*)()) { + return parser::find_type(ms, s); + } + struct is_destructor_with_name { const std::string dtor_name; inline bool operator()(boost::core::string_view s) const { { - const auto visibility_pos = find_visibility(s); + const auto visibility_pos = parser::find_visibility(s); if (visibility_pos == std::string::npos) { return false; } s.remove_prefix(visibility_pos); } + s = trim_prefix(s, " virtual"); { - const auto virtual_pos = find_visibility(s); - if (virtual_pos != std::string::npos) { + // cdecl declaration for methods. stdcall cannot be + const auto thiscall_pos = parser::find_thiscall(s); + if (thiscall_pos == std::string::npos) { return false; } + s.remove_prefix(thiscall_pos); + } + + if (!s.starts_with(dtor_name)) { + return false; + } + s.remove_prefix(dtor_name.size()); + s = parser::trim_ptrs(s); + return s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; + + template + struct is_constructor_with_name { + const std::string ctor_name; + const mangled_storage_impl& ms; + + inline bool operator()(boost::core::string_view s) const { + { + const auto visibility_pos = parser::find_visibility(s); + if (visibility_pos == std::string::npos) { + return false; + } + s.remove_prefix(visibility_pos); } - s = trim_prefix(s, " virtual"); { // cdecl declaration for methods. stdcall cannot be - const auto thiscall_pos = find_thiscall(s); + const auto thiscall_pos = parser::find_thiscall(s); if (thiscall_pos == std::string::npos) { return false; } s.remove_prefix(thiscall_pos); } - if (!s.starts_with(dtor_name)) { + if (!s.starts_with(ctor_name)) { return false; } - s.remove_prefix(dtor_name.size()); - s = trim_ptrs(s); + s.remove_prefix(ctor_name.size()); + + if (!s.starts_with("(")) { + return false; + } + s.remove_prefix(1); + + { + const auto arg_list_pos = parser::find_arg_list(ms, s, Signature()); + if (arg_list_pos == std::string::npos) { + return false; + } + s.remove_prefix(arg_list_pos); + } + + if (!s.starts_with(")")) { + return false; + } + s.remove_prefix(1); + + s = parser::trim_ptrs(s); return s.empty(); } @@ -438,11 +533,7 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) const template -auto mangled_storage_impl::get_constructor() const -> ctor_sym -{ - namespace x3 = spirit::x3; - using namespace parser; - +auto mangled_storage_impl::get_constructor() const -> ctor_sym { using func_type = Signature*; @@ -463,23 +554,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym } } - auto matcher = - visibility >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - ctor_name >> - x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); - - - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto f = std::find_if(storage_.begin(), storage_.end(), predicate); + const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name{ctor_name, *this}); if (f != storage_.end()) return f->mangled; diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 3138632a..b8688911 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -8,6 +8,7 @@ #include +#if (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201402L) #include int main(int argc, char* argv[]) @@ -43,5 +44,40 @@ int main(int argc, char* argv[]) BOOST_TEST(parser::is_destructor_with_name{"some_space::some_father::~some_father(void)"}("public: __thiscall some_space::some_father::~some_father(void) __ptr64")); + boost::dll::detail::mangled_storage_impl ms; + { + void(*ptr1)(int) = nullptr; + BOOST_TEST_EQ(parser::find_arg_list(ms, "int", ptr1), 3); + } + { + void(*ptr2)() = nullptr; + BOOST_TEST_EQ(parser::find_arg_list(ms, "void", ptr2), 4); + } + { + void(*ptr3)(int,int) = nullptr; + BOOST_TEST_EQ(parser::find_arg_list(ms, "int,int", ptr3), 7); + } + { + void(*ptr4)(int,short,long) = nullptr; + BOOST_TEST_EQ(parser::find_arg_list(ms, "int,short,long", ptr4), 14); + } + + + BOOST_TEST(( + parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + ("public: __cdecl some_space::some_class::some_class(void) __ptr64") + )); + BOOST_TEST(( + parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + ("private: __cdecl some_space::some_class::some_class(int)") + )); + BOOST_TEST(( + parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + ("private: __cdecl some_space::some_class::some_class(int,int)") + )); + return boost::report_errors(); } +#else +int main() {return 0;} +#endif From 3b8134cb7efb327c916af247abbdb2e6746c348a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 19:08:54 +0300 Subject: [PATCH 04/18] wip --- include/boost/dll/detail/demangling/msvc.hpp | 65 +++++++++++--------- test/cpp_mangling.cpp | 21 +++++++ 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index b9e51ce1..09a2abcb 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -126,7 +126,7 @@ namespace parser return s; } - boost::core::string_view trim_prefix(boost::core::string_view s, boost::core::string_view prefix) { + inline boost::core::string_view trim_prefix(boost::core::string_view s, boost::core::string_view prefix) { if (s.starts_with(prefix)) { s.remove_prefix(prefix.size()); } @@ -367,6 +367,39 @@ namespace parser } }; + template + struct is_variable_with_name { + const std::string variable_name; + const mangled_storage_impl& ms; + + inline bool operator()(boost::core::string_view s) const { + { + const auto visibility_pos = parser::find_visibility(s); + if (visibility_pos != std::string::npos) { + s.remove_prefix(visibility_pos); + s = trim_prefix(s, " static "); + } + } + { + const auto type_pos = parser::find_type(ms, s); + if (type_pos == std::string::npos) { + return std::string::npos; + } + s.remove_prefix(type_pos); + } + + if (!s.starts_with(variable_name)) { + return false; + } + s.remove_prefix(variable_name.size()); + return s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; + template struct is_constructor_with_name { const std::string ctor_name; @@ -423,33 +456,9 @@ namespace parser } -template std::string mangled_storage_impl::get_variable(const std::string &name) const -{ - using namespace std; - using namespace boost; - - namespace x3 = spirit::x3; - using namespace parser; - - auto type_name = get_name(); - - auto matcher = - -(visibility >> static_ >> x3::space) >> //it may be a static class-member - parser::type_rule(type_name) >> x3::space >> - name; - - auto predicate = [&](const mangled_storage_base::entry & e) - { - if (e.demangled == name)//maybe not mangled, - return true; - - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - return res && (itr == end); - }; - - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); +template +std::string mangled_storage_impl::get_variable(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name{name}); if (found != storage_.end()) return found->mangled; diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index b8688911..0943b601 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -76,6 +76,27 @@ int main(int argc, char* argv[]) ("private: __cdecl some_space::some_class::some_class(int,int)") )); + + BOOST_TEST(( + parser::is_variable_with_name{"some_space::some_class::value", ms} + ("public: static int some_space::some_class::value") + )); + + BOOST_TEST(( + parser::is_variable_with_name{"some_space::some_class::value", ms} + ("int some_space::some_class::value") + )); + + BOOST_TEST(( + parser::is_variable_with_name{"some_space::variable", ms} + ("public: static int some_space::variable") + )); + + BOOST_TEST(( + parser::is_variable_with_name{"unscoped_c_var", ms} + ("double const unscoped_c_var") + )); + return boost::report_errors(); } #else From 7bec25e2c6434118aa3daf30c80c47a5112678e7 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 20:06:24 +0300 Subject: [PATCH 05/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 43 ++++++++++------ test/cpp_mangling.cpp | 54 ++++++++++---------- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 09a2abcb..70ac64aa 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -333,8 +333,11 @@ namespace parser return parser::find_type(ms, s); } - struct is_destructor_with_name { - const std::string dtor_name; + class is_destructor_with_name { + const std::string dtor_name_; + + public: + explicit is_destructor_with_name(std::string dtor_name) : dtor_name_(std::move(dtor_name)) {} inline bool operator()(boost::core::string_view s) const { { @@ -354,10 +357,10 @@ namespace parser s.remove_prefix(thiscall_pos); } - if (!s.starts_with(dtor_name)) { + if (!s.starts_with(dtor_name_)) { return false; } - s.remove_prefix(dtor_name.size()); + s.remove_prefix(dtor_name_.size()); s = parser::trim_ptrs(s); return s.empty(); } @@ -368,9 +371,13 @@ namespace parser }; template - struct is_variable_with_name { - const std::string variable_name; - const mangled_storage_impl& ms; + class is_variable_with_name { + const std::string variable_name_; + const mangled_storage_impl& ms_; + + public: + is_variable_with_name(std::string variable_name, const mangled_storage_impl& ms) + : variable_name_(std::move(variable_name)), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { { @@ -381,17 +388,17 @@ namespace parser } } { - const auto type_pos = parser::find_type(ms, s); + const auto type_pos = parser::find_type(ms_, s); if (type_pos == std::string::npos) { return std::string::npos; } s.remove_prefix(type_pos); } - if (!s.starts_with(variable_name)) { + if (!s.starts_with(variable_name_)) { return false; } - s.remove_prefix(variable_name.size()); + s.remove_prefix(variable_name_.size()); return s.empty(); } @@ -401,9 +408,13 @@ namespace parser }; template - struct is_constructor_with_name { - const std::string ctor_name; - const mangled_storage_impl& ms; + class is_constructor_with_name { + const std::string ctor_name_; + const mangled_storage_impl& ms_; + + public: + is_constructor_with_name(std::string ctor_name, const mangled_storage_impl& ms) + : ctor_name_(std::move(ctor_name)), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { { @@ -422,10 +433,10 @@ namespace parser s.remove_prefix(thiscall_pos); } - if (!s.starts_with(ctor_name)) { + if (!s.starts_with(ctor_name_)) { return false; } - s.remove_prefix(ctor_name.size()); + s.remove_prefix(ctor_name_.size()); if (!s.starts_with("(")) { return false; @@ -433,7 +444,7 @@ namespace parser s.remove_prefix(1); { - const auto arg_list_pos = parser::find_arg_list(ms, s, Signature()); + const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); if (arg_list_pos == std::string::npos) { return false; } diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 0943b601..9df54c02 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -15,33 +15,33 @@ int main(int argc, char* argv[]) { namespace parser = boost::dll::detail::parser; - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: virtual __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: virtual __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: virtual __cdecl foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __cdecl foo::~foo(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __cdecl foo::~foo(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __cdecl foo::~foo(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"some_space::some_father::~some_father(void)"}("public: __cdecl some_space::some_father::~some_father(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("some_space::some_father::~some_father(void)")("public: __cdecl some_space::some_father::~some_father(void) __ptr64")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: virtual __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: virtual __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: virtual __thiscall foo::~foo(void)")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("public: __thiscall foo::~foo(void) __ptr32")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("private: __thiscall foo::~foo(void) __ptr32")); - BOOST_TEST(parser::is_destructor_with_name{"foo::~foo(void)"}("protected: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __thiscall foo::~foo(void) __ptr32")); - BOOST_TEST(parser::is_destructor_with_name{"some_space::some_father::~some_father(void)"}("public: __thiscall some_space::some_father::~some_father(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("some_space::some_father::~some_father(void)")("public: __thiscall some_space::some_father::~some_father(void) __ptr64")); boost::dll::detail::mangled_storage_impl ms; @@ -64,36 +64,36 @@ int main(int argc, char* argv[]) BOOST_TEST(( - parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + parser::is_constructor_with_name("some_space::some_class::some_class", ms) ("public: __cdecl some_space::some_class::some_class(void) __ptr64") )); BOOST_TEST(( - parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + parser::is_constructor_with_name("some_space::some_class::some_class", ms) ("private: __cdecl some_space::some_class::some_class(int)") )); BOOST_TEST(( - parser::is_constructor_with_name{"some_space::some_class::some_class", ms} + parser::is_constructor_with_name("some_space::some_class::some_class", ms) ("private: __cdecl some_space::some_class::some_class(int,int)") )); BOOST_TEST(( - parser::is_variable_with_name{"some_space::some_class::value", ms} + parser::is_variable_with_name("some_space::some_class::value", ms) ("public: static int some_space::some_class::value") )); BOOST_TEST(( - parser::is_variable_with_name{"some_space::some_class::value", ms} + parser::is_variable_with_name("some_space::some_class::value", ms) ("int some_space::some_class::value") )); BOOST_TEST(( - parser::is_variable_with_name{"some_space::variable", ms} + parser::is_variable_with_name("some_space::variable", ms) ("public: static int some_space::variable") )); BOOST_TEST(( - parser::is_variable_with_name{"unscoped_c_var", ms} + parser::is_variable_with_name("unscoped_c_var", ms) ("double const unscoped_c_var") )); From acc6f980e803801c911df9f8740cde98db2e7d52 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 20:50:28 +0300 Subject: [PATCH 06/18] fix attempt --- include/boost/dll/detail/demangling/msvc.hpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 70ac64aa..208659ae 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -469,7 +469,7 @@ namespace parser template std::string mangled_storage_impl::get_variable(const std::string &name) const { - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name{name}); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(std::move(name))); if (found != storage_.end()) return found->mangled; @@ -574,7 +574,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym { } } - const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name{ctor_name, *this}); + const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name(std::move(ctor_name), *this)); if (f != storage_.end()) return f->mangled; @@ -583,9 +583,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym { } template -auto mangled_storage_impl::get_destructor() const -> dtor_sym -{ - using namespace parser; +auto mangled_storage_impl::get_destructor() const -> dtor_sym { std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { @@ -603,7 +601,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym } } - const auto found = std::find_if(storage_.begin(), storage_.end(), is_destructor_with_name{dtor_name}); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_destructor_with_name(std::move(dtor_name))); if (found != storage_.end()) return found->mangled; From 086d098c49d0ec4855ba65d93947b4251619272c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Dec 2024 23:56:09 +0300 Subject: [PATCH 07/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 65 ++++++++++++++++++++ test/cpp_mangling.cpp | 11 ++++ 2 files changed, 76 insertions(+) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 208659ae..a31ac1c2 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -464,6 +464,71 @@ namespace parser return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); } }; + + template + class is_function_with_name; + + template + class is_function_with_name { + const std::string function_name_; + const mangled_storage_impl& ms_; + + public: + is_function_with_name(std::string function_name, const mangled_storage_impl& ms) + : function_name_(std::move(function_name)), ms_(ms) {} + + inline bool operator()(boost::core::string_view s) const { + { + const auto visibility_pos = parser::find_visibility(s); + if (visibility_pos != std::string::npos) { + s.remove_prefix(visibility_pos); + s = trim_prefix(s, " static "); + } + } + { + const auto type_pos = parser::find_type(ms_, s); + if (type_pos == std::string::npos) { + return false; + } + s.remove_prefix(type_pos); + } + if (!s.starts_with(" __cdecl ")) { + return false; + } + s.remove_prefix(sizeof(" __cdecl ") - 1); + + if (!s.starts_with(function_name_)) { + return false; + } + s.remove_prefix(function_name_.size()); + + if (!s.starts_with("(")) { + return false; + } + s.remove_prefix(1); + + { + using Signature = Result(*)(Args...); + const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); + if (arg_list_pos == std::string::npos) { + return false; + } + s.remove_prefix(arg_list_pos); + } + + if (!s.starts_with(")")) { + return false; + } + s.remove_prefix(1); + + s = parser::trim_ptrs(s); + return s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; } diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 9df54c02..e89ad137 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -97,6 +97,17 @@ int main(int argc, char* argv[]) ("double const unscoped_c_var") )); + + BOOST_TEST(( + parser::is_function_with_name("overloaded", ms) + ("void __cdecl overloaded(int)") + )); + + BOOST_TEST(( + parser::is_function_with_name("overloaded", ms) + ("void __cdecl overloaded(double)") + )); + return boost::report_errors(); } #else From c1b825cee3b656b4ecb7f75b01fa456d2a390aae Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 00:41:58 +0300 Subject: [PATCH 08/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 204 +++++++++++-------- test/cpp_mangling.cpp | 9 + 2 files changed, 132 insertions(+), 81 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index a31ac1c2..b520b540 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -334,10 +334,11 @@ namespace parser } class is_destructor_with_name { - const std::string dtor_name_; + const std::string& dtor_name_; public: - explicit is_destructor_with_name(std::string dtor_name) : dtor_name_(std::move(dtor_name)) {} + explicit is_destructor_with_name(const std::string& dtor_name) + : dtor_name_(dtor_name) {} inline bool operator()(boost::core::string_view s) const { { @@ -372,12 +373,12 @@ namespace parser template class is_variable_with_name { - const std::string variable_name_; + const std::string& variable_name_; const mangled_storage_impl& ms_; public: - is_variable_with_name(std::string variable_name, const mangled_storage_impl& ms) - : variable_name_(std::move(variable_name)), ms_(ms) {} + is_variable_with_name(const std::string& variable_name, const mangled_storage_impl& ms) + : variable_name_(variable_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { { @@ -409,12 +410,12 @@ namespace parser template class is_constructor_with_name { - const std::string ctor_name_; + const std::string& ctor_name_; const mangled_storage_impl& ms_; public: - is_constructor_with_name(std::string ctor_name, const mangled_storage_impl& ms) - : ctor_name_(std::move(ctor_name)), ms_(ms) {} + is_constructor_with_name(const std::string& ctor_name, const mangled_storage_impl& ms) + : ctor_name_(ctor_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { { @@ -470,12 +471,12 @@ namespace parser template class is_function_with_name { - const std::string function_name_; + const std::string& function_name_; const mangled_storage_impl& ms_; public: - is_function_with_name(std::string function_name, const mangled_storage_impl& ms) - : function_name_(std::move(function_name)), ms_(ms) {} + is_function_with_name(const std::string& function_name, const mangled_storage_impl& ms) + : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { { @@ -529,86 +530,134 @@ namespace parser return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); } }; -} + template + class is_mem_fn_with_name; -template -std::string mangled_storage_impl::get_variable(const std::string &name) const { - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(std::move(name))); + template + class is_mem_fn_with_name { + const std::string& function_name_; + const mangled_storage_impl& ms_; - if (found != storage_.end()) - return found->mangled; - else - return ""; -} + public: + is_mem_fn_with_name(const std::string& function_name, const mangled_storage_impl& ms) + : function_name_(function_name), ms_(ms) {} -template std::string mangled_storage_impl::get_function(const std::string &name) const -{ - namespace x3 = spirit::x3; - using namespace parser; - using func_type = Func*; - using return_type = typename function_traits::result_type; - std::string return_type_name = get_name(); + inline bool operator()(boost::core::string_view s) const { + { + const auto visibility_pos = parser::find_visibility(s); + if (visibility_pos == std::string::npos) { + return false; + } + s.remove_prefix(visibility_pos); + } + s = trim_prefix(s, " virtual"); + if (!s.starts_with(" ")) { + return false; + } + s.remove_prefix(1); - auto matcher = - -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute. - parser::type_rule(return_type_name) >> x3::space >> - cdecl_ >> //cdecl declaration for methods. stdcall cannot be - name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); + { + const auto type_pos = parser::find_type(ms_, s); + if (type_pos == std::string::npos) { + return false; + } + s.remove_prefix(type_pos); + } + if (!s.starts_with("__thiscall ")) { + return false; + } + s.remove_prefix(sizeof("__thiscall ") - 1); - auto predicate = [&](const mangled_storage_base::entry & e) { - if (e.demangled == name)//maybe not mangled, - return true; + const auto type_pos = parser::find_type::type>(ms_, s); + if (type_pos == std::string::npos) { + return false; + } + s.remove_prefix(type_pos); + } - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); + if (!s.starts_with("::")) { + return false; + } + s.remove_prefix(sizeof("::") - 1); - return res && (itr == end); - }; + if (!s.starts_with(function_name_)) { + return false; + } + s.remove_prefix(function_name_.size()); - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); + if (!s.starts_with("(")) { + return false; + } + s.remove_prefix(1); - if (found != storage_.end()) - return found->mangled; - else - return ""; + { + using Signature = Result(*)(Args...); + const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); + if (arg_list_pos == std::string::npos) { + return false; + } + s.remove_prefix(arg_list_pos); + } -} + if (!s.starts_with(")")) { + return false; + } + s.remove_prefix(1); -template -std::string mangled_storage_impl::get_mem_fn(const std::string &name) const -{ - namespace x3 = spirit::x3; - using namespace parser; - using func_type = Func*; - using return_type = typename function_traits::result_type; - auto return_type_name = get_name(); + if (std::is_const::value) { + if (!s.starts_with("const ")) { + return false; + } else { + s.remove_prefix(sizeof("const ") - 1); + } + } + + if (std::is_volatile::value) { + if (!s.starts_with("volatile ")) { + return false; + } else { + s.remove_prefix(sizeof("volatile ") - 1); + } + } + + s = parser::trim_ptrs(s); + return s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; +} - auto cname = get_name(); +template +std::string mangled_storage_impl::get_variable(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(name)); - auto matcher = - visibility >> -virtual_ >> x3::space >> - parser::type_rule(return_type_name) >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - cname >> "::" >> name >> - x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> - inv_const_rule() >> inv_volatile_rule() >> parser::ptr_rule(); + if (found != storage_.end()) + return found->mangled; + else + return ""; +} - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); +template +std::string mangled_storage_impl::get_function(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_function_with_name(name)); - return res && (itr == end); - }; + if (found != storage_.end()) + return found->mangled; + else + return ""; +} - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); +template +std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_mem_fn_with_name(name)); if (found != storage_.end()) return found->mangled; @@ -619,9 +668,6 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) const template auto mangled_storage_impl::get_constructor() const -> ctor_sym { - using func_type = Signature*; - - std::string ctor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { @@ -639,7 +685,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym { } } - const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name(std::move(ctor_name), *this)); + const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name(ctor_name, *this)); if (f != storage_.end()) return f->mangled; @@ -666,7 +712,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym { } } - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_destructor_with_name(std::move(dtor_name))); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_destructor_with_name(dtor_name)); if (found != storage_.end()) return found->mangled; @@ -675,8 +721,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym { } template -std::string mangled_storage_impl::get_vtable() const -{ +std::string mangled_storage_impl::get_vtable() const { std::string id = "const " + get_name() + "::`vftable'"; auto predicate = [&](const mangled_storage_base::entry & e) @@ -694,8 +739,7 @@ std::string mangled_storage_impl::get_vtable() const } template -std::vector mangled_storage_impl::get_related() const -{ +std::vector mangled_storage_impl::get_related() const { std::vector ret; auto name = get_name(); @@ -711,6 +755,4 @@ std::vector mangled_storage_impl::get_related() const }}} - - #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */ diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index e89ad137..7e49c71d 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -108,6 +108,15 @@ int main(int argc, char* argv[]) ("void __cdecl overloaded(double)") )); + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: int __thiscall int::func(int,int)volatile ") + )); + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("private: double __thiscall int::func(double)const volatile ") + )); + return boost::report_errors(); } #else From 87bfab19187607fcce5c10a9efcfcf1a0d8fb2b6 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 00:58:55 +0300 Subject: [PATCH 09/18] fixes --- CMakeLists.txt | 1 - build.jam | 1 - include/boost/dll/detail/demangling/msvc.hpp | 109 +------------------ test/cpp_mangling.cpp | 4 +- 4 files changed, 7 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 888283fb..42542d55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ target_link_libraries(boost_dll Boost::filesystem Boost::predef Boost::smart_ptr - Boost::spirit Boost::system Boost::throw_exception Boost::type_index diff --git a/build.jam b/build.jam index 19c19dd2..f5d93e2b 100644 --- a/build.jam +++ b/build.jam @@ -12,7 +12,6 @@ constant boost_dependencies : /boost/filesystem//boost_filesystem /boost/predef//boost_predef /boost/smart_ptr//boost_smart_ptr - /boost/spirit//boost_spirit /boost/system//boost_system /boost/throw_exception//boost_throw_exception /boost/type_index//boost_type_index diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index b520b540..61c1a11c 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -15,8 +15,6 @@ #include #include -#include - namespace boost { namespace dll { namespace detail { class mangled_storage_impl : public mangled_storage_base @@ -24,11 +22,6 @@ class mangled_storage_impl : public mangled_storage_base template struct dummy {}; - template - std::vector get_func_params(dummy) const - { - return {get_name()...}; - } template std::string get_return_type(dummy) const { @@ -92,22 +85,7 @@ void mangled_storage_impl::trim_typename(std::string & val) } -namespace parser -{ - namespace x3 = spirit::x3; - - inline auto ptr_rule_impl(std::integral_constant) - { - return -((-x3::space) >> "__ptr32"); - } - inline auto ptr_rule_impl(std::integral_constant) - { - return -((-x3::space) >> "__ptr64"); - } - - inline auto ptr_rule() { - return ptr_rule_impl(std::integral_constant()); - } +namespace parser { inline boost::core::string_view trim_ptrs(boost::core::string_view s) { bool retry = false; @@ -133,7 +111,6 @@ namespace parser return s; } - auto const visibility = ("public:" | x3::lit("protected:") | "private:"); inline std::string::size_type find_visibility(boost::core::string_view s) { if (s.starts_with("public:")) { return sizeof("public:") - 1; @@ -145,7 +122,6 @@ namespace parser return std::string::npos; } - auto const virtual_ = x3::space >> "virtual"; inline std::string::size_type find_virtual(boost::core::string_view s) { if (s.starts_with(" virtual")) { return sizeof(" virtual") - 1; @@ -153,7 +129,6 @@ namespace parser return std::string::npos; } - auto const static_ = x3::space >> x3::lit("static") ; inline std::string::size_type find_static(boost::core::string_view s) { if (s.starts_with(" static")) { return sizeof(" static") - 1; @@ -161,53 +136,6 @@ namespace parser return std::string::npos; } - inline auto const_rule_impl(std::true_type ) {return x3::space >> "const";}; - inline auto const_rule_impl(std::false_type) {return x3::eps;}; - template - auto const_rule() {using t = std::is_const::type>; return const_rule_impl(t());} - - inline auto volatile_rule_impl(std::true_type ) {return x3::space >> "volatile";}; - inline auto volatile_rule_impl(std::false_type) {return x3::eps;}; - template - auto volatile_rule() {using t = std::is_volatile::type>; return volatile_rule_impl(t());} - - - inline auto inv_const_rule_impl(std::true_type ) {return "const" >> x3::space ;}; - inline auto inv_const_rule_impl(std::false_type) {return x3::eps;}; - template - auto inv_const_rule() {using t = std::is_const::type>; return inv_const_rule_impl(t());} - - inline auto inv_volatile_rule_impl(std::true_type ) {return "volatile" >> x3::space;}; - inline auto inv_volatile_rule_impl(std::false_type) {return x3::eps;}; - template - auto inv_volatile_rule() {using t = std::is_volatile::type>; return inv_volatile_rule_impl(t());} - - - inline auto reference_rule_impl(std::false_type, std::false_type) {return x3::eps;} - inline auto reference_rule_impl(std::true_type, std::false_type) {return x3::space >>"&" ;} - inline auto reference_rule_impl(std::false_type, std::true_type ) {return x3::space >>"&&" ;} - - - template - auto reference_rule() {using t_l = std::is_lvalue_reference; using t_r = std::is_rvalue_reference; return reference_rule_impl(t_l(), t_r());} - - auto const class_ = ("class" | x3::lit("struct")); - - //it takes a string, because it may be overloaded. - template - auto type_rule(const std::string & type_name) - { - using namespace std; - - return -(class_ >> x3::space)>> x3::string(type_name) >> - const_rule() >> - volatile_rule() >> - reference_rule() >> - ptr_rule(); - } - template<> - inline auto type_rule(const std::string &) { return x3::string("void"); }; - template std::string::size_type find_type(const mangled_storage_impl& ms, boost::core::string_view s_orig) { if (std::is_void::value) { @@ -259,17 +187,10 @@ namespace parser } } - s = trim_ptrs(s); + s = parser::trim_ptrs(s); return s_orig.size() - s.size(); } - auto const cdecl_ = "__cdecl" >> x3::space; - auto const stdcall = "__stdcall" >> x3::space; -#if defined(_WIN64)//seems to be necessary by msvc 14-x64 - auto const thiscall = "__cdecl" >> x3::space; -#else - auto const thiscall = "__thiscall" >> x3::space; -#endif inline std::string::size_type find_thiscall(boost::core::string_view s) { if (s.starts_with(" __cdecl ")) { // Win 64bit return sizeof(" __cdecl ") - 1; @@ -279,26 +200,6 @@ namespace parser return std::string::npos; } - template - auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) - { - return type_rule(ms.get_name()); - } - - template - auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...)) - { - using next_type = Return (*)(Second, Args...); - return type_rule(ms.get_name()) >> x3::char_(',') >> arg_list(ms, next_type()); - } - - template - auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)()) - { - return x3::string("void"); - } - - template std::string::size_type find_arg_list(const mangled_storage_impl& ms, boost::core::string_view s, Return (*)(Arg)) { @@ -637,7 +538,7 @@ namespace parser template std::string mangled_storage_impl::get_variable(const std::string &name) const { - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(name)); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(name, *this)); if (found != storage_.end()) return found->mangled; @@ -647,7 +548,7 @@ std::string mangled_storage_impl::get_variable(const std::string &name) const { template std::string mangled_storage_impl::get_function(const std::string &name) const { - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_function_with_name(name)); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_function_with_name(name, *this)); if (found != storage_.end()) return found->mangled; @@ -657,7 +558,7 @@ std::string mangled_storage_impl::get_function(const std::string &name) const { template std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { - const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_mem_fn_with_name(name)); + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_mem_fn_with_name(name, *this)); if (found != storage_.end()) return found->mangled; diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 7e49c71d..00c600d9 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -58,8 +58,8 @@ int main(int argc, char* argv[]) BOOST_TEST_EQ(parser::find_arg_list(ms, "int,int", ptr3), 7); } { - void(*ptr4)(int,short,long) = nullptr; - BOOST_TEST_EQ(parser::find_arg_list(ms, "int,short,long", ptr4), 14); + void(*ptr4)(int,int,int) = nullptr; + BOOST_TEST_EQ(parser::find_arg_list(ms, "int,int,int", ptr4), 11); } From a3aec0f0912a8c0860013b538c9976add040d6ca Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 01:36:32 +0300 Subject: [PATCH 10/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 21 ++++++++++++++------ test/cpp_mangling.cpp | 13 +++++++++++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 61c1a11c..6fab7fcf 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -155,7 +155,7 @@ namespace parser { } s.remove_prefix(mangled_name.size()); - if (std::is_const::value) { + if (std::is_const::type>::value) { if (!s.starts_with(" const")) { return std::string::npos; } else { @@ -163,7 +163,7 @@ namespace parser { } } - if (std::is_volatile::value) { + if (std::is_volatile::type>::value) { if (!s.starts_with(" volatile")) { return std::string::npos; } else { @@ -286,13 +286,13 @@ namespace parser { const auto visibility_pos = parser::find_visibility(s); if (visibility_pos != std::string::npos) { s.remove_prefix(visibility_pos); - s = trim_prefix(s, " static "); + s = parser::trim_prefix(s, " static "); } } { const auto type_pos = parser::find_type(ms_, s); if (type_pos == std::string::npos) { - return std::string::npos; + return false; } s.remove_prefix(type_pos); } @@ -390,21 +390,28 @@ namespace parser { { const auto type_pos = parser::find_type(ms_, s); if (type_pos == std::string::npos) { + BOOST_ASSERT(false); return false; } s.remove_prefix(type_pos); } - if (!s.starts_with(" __cdecl ")) { + + if (s.starts_with(" ")) s.remove_prefix(1); + if (!s.starts_with("__cdecl ")) { + throw std::runtime_error(s); + BOOST_ASSERT(false); return false; } - s.remove_prefix(sizeof(" __cdecl ") - 1); + s.remove_prefix(sizeof("__cdecl ") - 1); if (!s.starts_with(function_name_)) { + BOOST_ASSERT(false); return false; } s.remove_prefix(function_name_.size()); if (!s.starts_with("(")) { + BOOST_ASSERT(false); return false; } s.remove_prefix(1); @@ -413,12 +420,14 @@ namespace parser { using Signature = Result(*)(Args...); const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); if (arg_list_pos == std::string::npos) { + BOOST_ASSERT(false); return false; } s.remove_prefix(arg_list_pos); } if (!s.starts_with(")")) { + BOOST_ASSERT(false); return false; } s.remove_prefix(1); diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 00c600d9..f4bd6573 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -89,7 +89,12 @@ int main(int argc, char* argv[]) BOOST_TEST(( parser::is_variable_with_name("some_space::variable", ms) - ("public: static int some_space::variable") + ("public: static double some_space::variable") + )); + + BOOST_TEST(( + !parser::is_variable_with_name("some_space::variable", ms) + ("public: static int some_space::variable_that_is_not_exist") )); BOOST_TEST(( @@ -108,6 +113,12 @@ int main(int argc, char* argv[]) ("void __cdecl overloaded(double)") )); + BOOST_TEST(( + parser::is_function_with_name("some_space::scoped_fun", ms) + ("int const & __ptr64 __cdecl some_space::scoped_fun(void)") + )); + + BOOST_TEST(( parser::is_mem_fn_with_name("func", ms) ("public: int __thiscall int::func(int,int)volatile ") From de1eabd38b027519f42e0002fd314fcc34d50fb5 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 02:03:14 +0300 Subject: [PATCH 11/18] fixes --- include/boost/dll/detail/demangling/msvc.hpp | 108 ++++++------------- test/cpp_mangling.cpp | 10 ++ 2 files changed, 44 insertions(+), 74 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 6fab7fcf..814e4507 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -111,29 +111,17 @@ namespace parser { return s; } - inline std::string::size_type find_visibility(boost::core::string_view s) { + inline bool consume_visibility(boost::core::string_view& s) { if (s.starts_with("public:")) { - return sizeof("public:") - 1; + s.remove_prefix(sizeof("public:") - 1); } else if (s.starts_with("protected:")) { - return sizeof("protected:") - 1; + s.remove_prefix(sizeof("protected:") - 1); } else if (s.starts_with("private:")) { - return sizeof("private:") - 1; + s.remove_prefix(sizeof("private:") - 1); + } else { + return false; } - return std::string::npos; - } - - inline std::string::size_type find_virtual(boost::core::string_view s) { - if (s.starts_with(" virtual")) { - return sizeof(" virtual") - 1; - } - return std::string::npos; - } - - inline std::string::size_type find_static(boost::core::string_view s) { - if (s.starts_with(" static")) { - return sizeof(" static") - 1; - } - return std::string::npos; + return true; } template @@ -191,13 +179,17 @@ namespace parser { return s_orig.size() - s.size(); } - inline std::string::size_type find_thiscall(boost::core::string_view s) { - if (s.starts_with(" __cdecl ")) { // Win 64bit - return sizeof(" __cdecl ") - 1; - } else if (s.starts_with(" __thiscall ")) { // Win 32bit - return sizeof(" __thiscall ") - 1; + inline bool consume_thiscall(boost::core::string_view& s) { + if (s.starts_with(" ")) s.remove_prefix(1); + + if (s.starts_with("__cdecl ")) { // Win 64bit + s.remove_prefix(sizeof("__cdecl ") - 1); + return true; + } else if (s.starts_with("__thiscall ")) { // Win 32bit + s.remove_prefix(sizeof("__thiscall ") - 1); + return true; } - return std::string::npos; + return false; } template @@ -242,23 +234,15 @@ namespace parser { : dtor_name_(dtor_name) {} inline bool operator()(boost::core::string_view s) const { - { - const auto visibility_pos = parser::find_visibility(s); - if (visibility_pos == std::string::npos) { - return false; - } - s.remove_prefix(visibility_pos); + if (!parser::consume_visibility(s)) { + return false; } s = trim_prefix(s, " virtual"); - { - // cdecl declaration for methods. stdcall cannot be - const auto thiscall_pos = parser::find_thiscall(s); - if (thiscall_pos == std::string::npos) { - return false; - } - s.remove_prefix(thiscall_pos); + + if (!parser::consume_thiscall(s)) { + return false; } - + if (!s.starts_with(dtor_name_)) { return false; } @@ -282,12 +266,8 @@ namespace parser { : variable_name_(variable_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - { - const auto visibility_pos = parser::find_visibility(s); - if (visibility_pos != std::string::npos) { - s.remove_prefix(visibility_pos); - s = parser::trim_prefix(s, " static "); - } + if (parser::consume_visibility(s)) { + s = parser::trim_prefix(s, " static "); } { const auto type_pos = parser::find_type(ms_, s); @@ -319,20 +299,11 @@ namespace parser { : ctor_name_(ctor_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - { - const auto visibility_pos = parser::find_visibility(s); - if (visibility_pos == std::string::npos) { - return false; - } - s.remove_prefix(visibility_pos); + if (!parser::consume_visibility(s)) { + return false; } - { - // cdecl declaration for methods. stdcall cannot be - const auto thiscall_pos = parser::find_thiscall(s); - if (thiscall_pos == std::string::npos) { - return false; - } - s.remove_prefix(thiscall_pos); + if (!parser::consume_thiscall(s)) { + return false; } if (!s.starts_with(ctor_name_)) { @@ -380,12 +351,8 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - { - const auto visibility_pos = parser::find_visibility(s); - if (visibility_pos != std::string::npos) { - s.remove_prefix(visibility_pos); - s = trim_prefix(s, " static "); - } + if (parser::consume_visibility(s)) { + s = trim_prefix(s, " static "); } { const auto type_pos = parser::find_type(ms_, s); @@ -454,12 +421,8 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - { - const auto visibility_pos = parser::find_visibility(s); - if (visibility_pos == std::string::npos) { - return false; - } - s.remove_prefix(visibility_pos); + if (!parser::consume_visibility(s)) { + return false; } s = trim_prefix(s, " virtual"); @@ -475,12 +438,9 @@ namespace parser { } s.remove_prefix(type_pos); } - - if (!s.starts_with("__thiscall ")) { + if (!parser::consume_thiscall(s)) { return false; } - s.remove_prefix(sizeof("__thiscall ") - 1); - { const auto type_pos = parser::find_type::type>(ms_, s); if (type_pos == std::string::npos) { diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index f4bd6573..30f3a57c 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -128,6 +128,16 @@ int main(int argc, char* argv[]) ("private: double __thiscall int::func(double)const volatile ") )); + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: int __cdecl int::func(int,int)volatile __ptr64") + )); + + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: virtual int __cdecl int::func(int,int)volatile __ptr64") + )); + return boost::report_errors(); } #else From 8cdfb71c16048aa7a2b4fe97b18feaf6d2e7dcfa Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 10:37:36 +0300 Subject: [PATCH 12/18] rm debug helpers --- include/boost/dll/detail/demangling/msvc.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 814e4507..57c66536 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -357,7 +357,6 @@ namespace parser { { const auto type_pos = parser::find_type(ms_, s); if (type_pos == std::string::npos) { - BOOST_ASSERT(false); return false; } s.remove_prefix(type_pos); @@ -366,19 +365,16 @@ namespace parser { if (s.starts_with(" ")) s.remove_prefix(1); if (!s.starts_with("__cdecl ")) { throw std::runtime_error(s); - BOOST_ASSERT(false); return false; } s.remove_prefix(sizeof("__cdecl ") - 1); if (!s.starts_with(function_name_)) { - BOOST_ASSERT(false); return false; } s.remove_prefix(function_name_.size()); if (!s.starts_with("(")) { - BOOST_ASSERT(false); return false; } s.remove_prefix(1); @@ -387,14 +383,12 @@ namespace parser { using Signature = Result(*)(Args...); const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); if (arg_list_pos == std::string::npos) { - BOOST_ASSERT(false); return false; } s.remove_prefix(arg_list_pos); } if (!s.starts_with(")")) { - BOOST_ASSERT(false); return false; } s.remove_prefix(1); From fdc0c1da685431e15897f70f466b118ab50e8904 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 21:26:34 +0300 Subject: [PATCH 13/18] simplify --- include/boost/dll/detail/demangling/msvc.hpp | 58 +++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 57c66536..e09b0a48 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -87,7 +87,15 @@ void mangled_storage_impl::trim_typename(std::string & val) namespace parser { - inline boost::core::string_view trim_ptrs(boost::core::string_view s) { + inline bool consume_string(boost::core::string_view& s, boost::core::string_view str) { + const bool result = s.starts_with(str); + if (result) { + s.remove_prefix(str.size()); + } + return result; + } + + inline void consume_ptrs(boost::core::string_view& s) { bool retry = false; do { retry = false; @@ -100,28 +108,12 @@ namespace parser { retry = true; } } while (retry); - - return s; - } - - inline boost::core::string_view trim_prefix(boost::core::string_view s, boost::core::string_view prefix) { - if (s.starts_with(prefix)) { - s.remove_prefix(prefix.size()); - } - return s; } inline bool consume_visibility(boost::core::string_view& s) { - if (s.starts_with("public:")) { - s.remove_prefix(sizeof("public:") - 1); - } else if (s.starts_with("protected:")) { - s.remove_prefix(sizeof("protected:") - 1); - } else if (s.starts_with("private:")) { - s.remove_prefix(sizeof("private:") - 1); - } else { - return false; - } - return true; + return parser::consume_string(s ,"public:") + || parser::consume_string(s, "protected:") + || parser::consume_string(s, "private:"); } template @@ -134,8 +126,8 @@ namespace parser { } auto s = s_orig; - s = trim_prefix(s, "class "); - s = trim_prefix(s, "struct "); + parser::consume_string(s, "class "); + parser::consume_string(s, "struct "); const auto& mangled_name = ms.get_name(); if (!s.starts_with(mangled_name)) { @@ -175,7 +167,7 @@ namespace parser { } } - s = parser::trim_ptrs(s); + parser::consume_ptrs(s); return s_orig.size() - s.size(); } @@ -237,7 +229,7 @@ namespace parser { if (!parser::consume_visibility(s)) { return false; } - s = trim_prefix(s, " virtual"); + parser::consume_string(s, " virtual"); if (!parser::consume_thiscall(s)) { return false; @@ -247,7 +239,7 @@ namespace parser { return false; } s.remove_prefix(dtor_name_.size()); - s = parser::trim_ptrs(s); + parser::consume_ptrs(s); return s.empty(); } @@ -266,8 +258,8 @@ namespace parser { : variable_name_(variable_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (parser::consume_visibility(s)) { - s = parser::trim_prefix(s, " static "); + if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { + return false; } { const auto type_pos = parser::find_type(ms_, s); @@ -329,7 +321,7 @@ namespace parser { } s.remove_prefix(1); - s = parser::trim_ptrs(s); + parser::consume_ptrs(s); return s.empty(); } @@ -351,8 +343,8 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (parser::consume_visibility(s)) { - s = trim_prefix(s, " static "); + if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { + return false; } { const auto type_pos = parser::find_type(ms_, s); @@ -393,7 +385,7 @@ namespace parser { } s.remove_prefix(1); - s = parser::trim_ptrs(s); + parser::consume_ptrs(s); return s.empty(); } @@ -418,7 +410,7 @@ namespace parser { if (!parser::consume_visibility(s)) { return false; } - s = trim_prefix(s, " virtual"); + parser::consume_string(s, " virtual"); if (!s.starts_with(" ")) { return false; @@ -488,7 +480,7 @@ namespace parser { } } - s = parser::trim_ptrs(s); + parser::consume_ptrs(s); return s.empty(); } From ddd0f88fae5458dcc6cff3f8c0de84499d54d571 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 21:47:54 +0300 Subject: [PATCH 14/18] simplify --- include/boost/dll/detail/demangling/msvc.hpp | 152 ++++++------------- test/cpp_mangling.cpp | 22 ++- 2 files changed, 62 insertions(+), 112 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index e09b0a48..7202dff2 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -96,79 +96,57 @@ namespace parser { } inline void consume_ptrs(boost::core::string_view& s) { - bool retry = false; do { - retry = false; - while (s.starts_with(" ")) { - s.remove_prefix(1); - } - - if (s.starts_with("__ptr32") || s.starts_with("__ptr64")) { - s.remove_prefix(sizeof("__ptr64") - 1); - retry = true; - } - } while (retry); + while (parser::consume_string(s, " ")) {} + } while (parser::consume_string(s, "__ptr32") || parser::consume_string(s, "__ptr64")); } inline bool consume_visibility(boost::core::string_view& s) { - return parser::consume_string(s ,"public:") + return parser::consume_string(s, "public:") || parser::consume_string(s, "protected:") || parser::consume_string(s, "private:"); } template - std::string::size_type find_type(const mangled_storage_impl& ms, boost::core::string_view s_orig) { + bool consume_type(boost::core::string_view& s, const mangled_storage_impl& ms) { if (std::is_void::value) { - if (s_orig.starts_with("void")) { - return sizeof("void") - 1; - } - return std::string::npos; + return parser::consume_string(s, "void"); } - auto s = s_orig; parser::consume_string(s, "class "); parser::consume_string(s, "struct "); const auto& mangled_name = ms.get_name(); - if (!s.starts_with(mangled_name)) { - return std::string::npos; + if (!parser::consume_string(s, mangled_name)) { + return false; } - s.remove_prefix(mangled_name.size()); if (std::is_const::type>::value) { - if (!s.starts_with(" const")) { - return std::string::npos; - } else { - s.remove_prefix(sizeof(" const") - 1); + if (!parser::consume_string(s, " const")) { + return false; } } if (std::is_volatile::type>::value) { - if (!s.starts_with(" volatile")) { - return std::string::npos; - } else { - s.remove_prefix(sizeof(" volatile") - 1); + if (!parser::consume_string(s, " volatile")) { + return false; } } if (std::is_rvalue_reference::value) { - if (!s.starts_with(" &&")) { - return std::string::npos; - } else { - s.remove_prefix(sizeof(" &&") - 1); + if (!parser::consume_string(s, " &&")) { + return false; } } if (std::is_lvalue_reference::value) { - if (!s.starts_with(" &")) { - return std::string::npos; - } else { - s.remove_prefix(sizeof(" &") - 1); + if (!parser::consume_string(s, " &")) { + return false; } } parser::consume_ptrs(s); - return s_orig.size() - s.size(); + return true; } inline bool consume_thiscall(boost::core::string_view& s) { @@ -185,37 +163,23 @@ namespace parser { } template - std::string::size_type find_arg_list(const mangled_storage_impl& ms, boost::core::string_view s, Return (*)(Arg)) + bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) { - return parser::find_type(ms, s); + return parser::consume_type(s, ms); } template - std::string::size_type find_arg_list(const mangled_storage_impl & ms, boost::core::string_view s, Return (*)(First, Second, Args...)) + bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); - - const auto res = parser::find_type(ms, s); - if (res == std::string::npos) { - return std::string::npos; - } - s.remove_prefix(res); - if (!s.starts_with(",")) { - return std::string::npos; - } - s.remove_prefix(1); - - const auto new_res = parser::find_arg_list(ms, s, next_type()); - if (new_res == std::string::npos) { - return std::string::npos; - } - - return res + 1 + new_res; + return parser::consume_type(s, ms) + && parser::consume_string(s, ",") + && parser::consume_arg_list(s, ms, next_type()); } template - std::string::size_type find_arg_list(const mangled_storage_impl& ms, boost::core::string_view s, Return (*)()) { - return parser::find_type(ms, s); + bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)()) { + return parser::consume_type(s, ms); } class is_destructor_with_name { @@ -261,18 +225,14 @@ namespace parser { if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { return false; } - { - const auto type_pos = parser::find_type(ms_, s); - if (type_pos == std::string::npos) { - return false; - } - s.remove_prefix(type_pos); - } - if (!s.starts_with(variable_name_)) { + if (!parser::consume_type(s, ms_)) { + return false; + } + + if (!parser::consume_string(s, variable_name_)) { return false; } - s.remove_prefix(variable_name_.size()); return s.empty(); } @@ -308,12 +268,8 @@ namespace parser { } s.remove_prefix(1); - { - const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); - if (arg_list_pos == std::string::npos) { - return false; - } - s.remove_prefix(arg_list_pos); + if (!parser::consume_arg_list(s, ms_, Signature())) { + return false; } if (!s.starts_with(")")) { @@ -346,12 +302,8 @@ namespace parser { if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { return false; } - { - const auto type_pos = parser::find_type(ms_, s); - if (type_pos == std::string::npos) { - return false; - } - s.remove_prefix(type_pos); + if (!parser::consume_type(s, ms_)) { + return false; } if (s.starts_with(" ")) s.remove_prefix(1); @@ -371,13 +323,9 @@ namespace parser { } s.remove_prefix(1); - { - using Signature = Result(*)(Args...); - const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); - if (arg_list_pos == std::string::npos) { - return false; - } - s.remove_prefix(arg_list_pos); + using Signature = Result(*)(Args...); + if (!parser::consume_arg_list(s, ms_, Signature())) { + return false; } if (!s.starts_with(")")) { @@ -417,24 +365,16 @@ namespace parser { } s.remove_prefix(1); - { - const auto type_pos = parser::find_type(ms_, s); - if (type_pos == std::string::npos) { - return false; - } - s.remove_prefix(type_pos); + if (!parser::consume_type(s, ms_)) { + return false; } + if (!parser::consume_thiscall(s)) { return false; } - { - const auto type_pos = parser::find_type::type>(ms_, s); - if (type_pos == std::string::npos) { - return false; - } - s.remove_prefix(type_pos); + if (!parser::consume_type::type>(s, ms_)) { + return false; } - if (!s.starts_with("::")) { return false; } @@ -450,13 +390,9 @@ namespace parser { } s.remove_prefix(1); - { - using Signature = Result(*)(Args...); - const auto arg_list_pos = parser::find_arg_list(ms_, s, Signature()); - if (arg_list_pos == std::string::npos) { - return false; - } - s.remove_prefix(arg_list_pos); + using Signature = Result(*)(Args...); + if (!parser::consume_arg_list(s, ms_, Signature())) { + return false; } if (!s.starts_with(")")) { diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 30f3a57c..749d543c 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -45,21 +45,35 @@ int main(int argc, char* argv[]) boost::dll::detail::mangled_storage_impl ms; + { + void(*ptr0)(int) = nullptr; + boost::core::string_view s = "integer"; + BOOST_TEST(parser::consume_arg_list(s, ms, ptr0)); + BOOST_TEST_EQ(s, "eger"); + } { void(*ptr1)(int) = nullptr; - BOOST_TEST_EQ(parser::find_arg_list(ms, "int", ptr1), 3); + boost::core::string_view s = "int"; + BOOST_TEST(parser::consume_arg_list(s, ms, ptr1)); + BOOST_TEST(s.empty()); } { void(*ptr2)() = nullptr; - BOOST_TEST_EQ(parser::find_arg_list(ms, "void", ptr2), 4); + boost::core::string_view s = "void"; + BOOST_TEST(parser::consume_arg_list(s, ms, ptr2)); + BOOST_TEST(s.empty()); } { void(*ptr3)(int,int) = nullptr; - BOOST_TEST_EQ(parser::find_arg_list(ms, "int,int", ptr3), 7); + boost::core::string_view s = "int,int"; + BOOST_TEST(parser::consume_arg_list(s, ms, ptr3)); + BOOST_TEST(s.empty()); } { void(*ptr4)(int,int,int) = nullptr; - BOOST_TEST_EQ(parser::find_arg_list(ms, "int,int,int", ptr4), 11); + boost::core::string_view s = "int,int,int"; + BOOST_TEST(parser::consume_arg_list(s, ms, ptr4)); + BOOST_TEST(s.empty()); } From fdb0d4918530da5b649b6edc824d12ac0552d2a3 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 21:54:57 +0300 Subject: [PATCH 15/18] simplify --- include/boost/dll/detail/demangling/msvc.hpp | 85 ++++++-------------- 1 file changed, 26 insertions(+), 59 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 7202dff2..7b704fd2 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -150,27 +150,18 @@ namespace parser { } inline bool consume_thiscall(boost::core::string_view& s) { - if (s.starts_with(" ")) s.remove_prefix(1); - - if (s.starts_with("__cdecl ")) { // Win 64bit - s.remove_prefix(sizeof("__cdecl ") - 1); - return true; - } else if (s.starts_with("__thiscall ")) { // Win 32bit - s.remove_prefix(sizeof("__thiscall ") - 1); - return true; - } - return false; + parser::consume_string(s, " "); + return parser::consume_string(s, "__cdecl ") // Win 64bit + || parser::consume_string(s, "__thiscall "); // Win 32bit } template - bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) - { + bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) { return parser::consume_type(s, ms); } template - bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) - { + bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); return parser::consume_type(s, ms) && parser::consume_string(s, ",") @@ -199,10 +190,9 @@ namespace parser { return false; } - if (!s.starts_with(dtor_name_)) { + if (!parser::consume_string(s, dtor_name_)) { return false; } - s.remove_prefix(dtor_name_.size()); parser::consume_ptrs(s); return s.empty(); } @@ -226,14 +216,9 @@ namespace parser { return false; } - if (!parser::consume_type(s, ms_)) { - return false; - } - - if (!parser::consume_string(s, variable_name_)) { - return false; - } - return s.empty(); + return parser::consume_type(s, ms_) + && parser::consume_string(s, variable_name_) + && s.empty(); } inline bool operator()(const mangled_storage_base::entry& e) const { @@ -258,24 +243,21 @@ namespace parser { return false; } - if (!s.starts_with(ctor_name_)) { + if (!parser::consume_string(s, ctor_name_)) { return false; } - s.remove_prefix(ctor_name_.size()); - if (!s.starts_with("(")) { + if (!parser::consume_string(s, "(")) { return false; } - s.remove_prefix(1); if (!parser::consume_arg_list(s, ms_, Signature())) { return false; } - if (!s.starts_with(")")) { + if (!parser::consume_string(s, ")")) { return false; } - s.remove_prefix(1); parser::consume_ptrs(s); return s.empty(); @@ -306,32 +288,28 @@ namespace parser { return false; } - if (s.starts_with(" ")) s.remove_prefix(1); - if (!s.starts_with("__cdecl ")) { - throw std::runtime_error(s); + parser::consume_string(s, " "); + + if (!parser::consume_string(s, "__cdecl ")) { return false; } - s.remove_prefix(sizeof("__cdecl ") - 1); - if (!s.starts_with(function_name_)) { + if (!parser::consume_string(s, function_name_)) { return false; } - s.remove_prefix(function_name_.size()); - - if (!s.starts_with("(")) { + + if (!parser::consume_string(s, "(")) { return false; } - s.remove_prefix(1); using Signature = Result(*)(Args...); if (!parser::consume_arg_list(s, ms_, Signature())) { return false; } - if (!s.starts_with(")")) { + if (!parser::consume_string(s, ")")) { return false; } - s.remove_prefix(1); parser::consume_ptrs(s); return s.empty(); @@ -360,10 +338,9 @@ namespace parser { } parser::consume_string(s, " virtual"); - if (!s.starts_with(" ")) { + if (!parser::consume_string(s, " ")) { return false; } - s.remove_prefix(1); if (!parser::consume_type(s, ms_)) { return false; @@ -375,44 +352,34 @@ namespace parser { if (!parser::consume_type::type>(s, ms_)) { return false; } - if (!s.starts_with("::")) { + if (!parser::consume_string(s, "::")) { return false; } - s.remove_prefix(sizeof("::") - 1); - - if (!s.starts_with(function_name_)) { + if (!parser::consume_string(s, function_name_)) { return false; } - s.remove_prefix(function_name_.size()); - - if (!s.starts_with("(")) { + if (!parser::consume_string(s, "(")) { return false; } - s.remove_prefix(1); using Signature = Result(*)(Args...); if (!parser::consume_arg_list(s, ms_, Signature())) { return false; } - if (!s.starts_with(")")) { + if (!parser::consume_string(s, ")")) { return false; } - s.remove_prefix(1); if (std::is_const::value) { - if (!s.starts_with("const ")) { + if (!parser::consume_string(s, "const ")) { return false; - } else { - s.remove_prefix(sizeof("const ") - 1); } } if (std::is_volatile::value) { - if (!s.starts_with("volatile ")) { + if (!parser::consume_string(s, "volatile ")) { return false; - } else { - s.remove_prefix(sizeof("volatile ") - 1); } } From 03c88d86f9f8700378399abe75cb0d84a3bf3edf Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 22:21:52 +0300 Subject: [PATCH 16/18] fixes and cleanups --- include/boost/dll/detail/demangling/msvc.hpp | 83 ++++++-------------- 1 file changed, 25 insertions(+), 58 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 7b704fd2..ff9ac03b 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -101,6 +101,11 @@ namespace parser { } while (parser::consume_string(s, "__ptr32") || parser::consume_string(s, "__ptr64")); } + inline bool ignore_ptrs(boost::core::string_view& s) { + parser::consume_ptrs(s); + return true; + } + inline bool consume_visibility(boost::core::string_view& s) { return parser::consume_string(s, "public:") || parser::consume_string(s, "protected:") @@ -145,8 +150,7 @@ namespace parser { } } - parser::consume_ptrs(s); - return true; + return parser::ignore_ptrs(s); } inline bool consume_thiscall(boost::core::string_view& s) { @@ -186,15 +190,10 @@ namespace parser { } parser::consume_string(s, " virtual"); - if (!parser::consume_thiscall(s)) { - return false; - } - - if (!parser::consume_string(s, dtor_name_)) { - return false; - } - parser::consume_ptrs(s); - return s.empty(); + return parser::consume_thiscall(s) + && parser::consume_string(s, dtor_name_) + && parser::ignore_ptrs(s) + && s.empty(); } inline bool operator()(const mangled_storage_base::entry& e) const { @@ -236,31 +235,14 @@ namespace parser { : ctor_name_(ctor_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (!parser::consume_visibility(s)) { - return false; - } - if (!parser::consume_thiscall(s)) { - return false; - } - - if (!parser::consume_string(s, ctor_name_)) { - return false; - } - - if (!parser::consume_string(s, "(")) { - return false; - } - - if (!parser::consume_arg_list(s, ms_, Signature())) { - return false; - } - - if (!parser::consume_string(s, ")")) { - return false; - } - - parser::consume_ptrs(s); - return s.empty(); + return parser::consume_visibility(s) + && parser::consume_thiscall(s) + && parser::consume_string(s, ctor_name_) + && parser::consume_string(s, "(") + && parser::consume_arg_list(s, ms_, Signature()) + && parser::consume_string(s, ")") + && parser::ignore_ptrs(s) + && s.empty(); } inline bool operator()(const mangled_storage_base::entry& e) const { @@ -290,29 +272,14 @@ namespace parser { parser::consume_string(s, " "); - if (!parser::consume_string(s, "__cdecl ")) { - return false; - } - - if (!parser::consume_string(s, function_name_)) { - return false; - } - - if (!parser::consume_string(s, "(")) { - return false; - } - using Signature = Result(*)(Args...); - if (!parser::consume_arg_list(s, ms_, Signature())) { - return false; - } - - if (!parser::consume_string(s, ")")) { - return false; - } - - parser::consume_ptrs(s); - return s.empty(); + return parser::consume_string(s, "__cdecl ") + && parser::consume_string(s, function_name_) + && parser::consume_string(s, "(") + && parser::consume_arg_list(s, ms_, Signature()) + && parser::consume_string(s, ")") + && parser::ignore_ptrs(s) + && s.empty(); } inline bool operator()(const mangled_storage_base::entry& e) const { From 654dd46ec797008e7516cced5bfd6d9700009dcc Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 22:29:05 +0300 Subject: [PATCH 17/18] polishings --- include/boost/dll/detail/demangling/msvc.hpp | 156 ++++++++----------- test/cpp_mangling.cpp | 10 +- 2 files changed, 72 insertions(+), 94 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index ff9ac03b..9e455a71 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -84,21 +84,20 @@ void mangled_storage_impl::trim_typename(std::string & val) } } - namespace parser { - inline bool consume_string(boost::core::string_view& s, boost::core::string_view str) { - const bool result = s.starts_with(str); + inline bool try_consume_prefix(boost::core::string_view& s, boost::core::string_view prefix) { + const bool result = s.starts_with(prefix); if (result) { - s.remove_prefix(str.size()); + s.remove_prefix(prefix.size()); } return result; } inline void consume_ptrs(boost::core::string_view& s) { do { - while (parser::consume_string(s, " ")) {} - } while (parser::consume_string(s, "__ptr32") || parser::consume_string(s, "__ptr64")); + while (parser::try_consume_prefix(s, " ")) {} + } while (parser::try_consume_prefix(s, "__ptr32") || parser::try_consume_prefix(s, "__ptr64")); } inline bool ignore_ptrs(boost::core::string_view& s) { @@ -106,46 +105,46 @@ namespace parser { return true; } - inline bool consume_visibility(boost::core::string_view& s) { - return parser::consume_string(s, "public:") - || parser::consume_string(s, "protected:") - || parser::consume_string(s, "private:"); + inline bool try_consume_visibility(boost::core::string_view& s) { + return parser::try_consume_prefix(s, "public:") + || parser::try_consume_prefix(s, "protected:") + || parser::try_consume_prefix(s, "private:"); } template - bool consume_type(boost::core::string_view& s, const mangled_storage_impl& ms) { + bool try_consume_type(boost::core::string_view& s, const mangled_storage_impl& ms) { if (std::is_void::value) { - return parser::consume_string(s, "void"); + return parser::try_consume_prefix(s, "void"); } - parser::consume_string(s, "class "); - parser::consume_string(s, "struct "); + parser::try_consume_prefix(s, "class "); + parser::try_consume_prefix(s, "struct "); const auto& mangled_name = ms.get_name(); - if (!parser::consume_string(s, mangled_name)) { + if (!parser::try_consume_prefix(s, mangled_name)) { return false; } if (std::is_const::type>::value) { - if (!parser::consume_string(s, " const")) { + if (!parser::try_consume_prefix(s, " const")) { return false; } } if (std::is_volatile::type>::value) { - if (!parser::consume_string(s, " volatile")) { + if (!parser::try_consume_prefix(s, " volatile")) { return false; } } if (std::is_rvalue_reference::value) { - if (!parser::consume_string(s, " &&")) { + if (!parser::try_consume_prefix(s, " &&")) { return false; } } if (std::is_lvalue_reference::value) { - if (!parser::consume_string(s, " &")) { + if (!parser::try_consume_prefix(s, " &")) { return false; } } @@ -153,28 +152,28 @@ namespace parser { return parser::ignore_ptrs(s); } - inline bool consume_thiscall(boost::core::string_view& s) { - parser::consume_string(s, " "); - return parser::consume_string(s, "__cdecl ") // Win 64bit - || parser::consume_string(s, "__thiscall "); // Win 32bit + inline bool try_consume_thiscall(boost::core::string_view& s) { + parser::try_consume_prefix(s, " "); + return parser::try_consume_prefix(s, "__cdecl ") // Win 64bit + || parser::try_consume_prefix(s, "__thiscall "); // Win 32bit } template - bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) { - return parser::consume_type(s, ms); + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) { + return parser::try_consume_type(s, ms); } template - bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) { + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); - return parser::consume_type(s, ms) - && parser::consume_string(s, ",") - && parser::consume_arg_list(s, ms, next_type()); + return parser::try_consume_type(s, ms) + && parser::try_consume_prefix(s, ",") + && parser::try_consume_arg_list(s, ms, next_type()); } template - bool consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)()) { - return parser::consume_type(s, ms); + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)()) { + return parser::try_consume_type(s, ms); } class is_destructor_with_name { @@ -185,13 +184,13 @@ namespace parser { : dtor_name_(dtor_name) {} inline bool operator()(boost::core::string_view s) const { - if (!parser::consume_visibility(s)) { + if (!parser::try_consume_visibility(s)) { return false; } - parser::consume_string(s, " virtual"); + parser::try_consume_prefix(s, " virtual"); - return parser::consume_thiscall(s) - && parser::consume_string(s, dtor_name_) + return parser::try_consume_thiscall(s) + && parser::try_consume_prefix(s, dtor_name_) && parser::ignore_ptrs(s) && s.empty(); } @@ -211,12 +210,12 @@ namespace parser { : variable_name_(variable_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { + if (parser::try_consume_visibility(s) && !parser::try_consume_prefix(s, " static ")) { return false; } - return parser::consume_type(s, ms_) - && parser::consume_string(s, variable_name_) + return parser::try_consume_type(s, ms_) + && parser::try_consume_prefix(s, variable_name_) && s.empty(); } @@ -235,12 +234,12 @@ namespace parser { : ctor_name_(ctor_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - return parser::consume_visibility(s) - && parser::consume_thiscall(s) - && parser::consume_string(s, ctor_name_) - && parser::consume_string(s, "(") - && parser::consume_arg_list(s, ms_, Signature()) - && parser::consume_string(s, ")") + return parser::try_consume_visibility(s) + && parser::try_consume_thiscall(s) + && parser::try_consume_prefix(s, ctor_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")") && parser::ignore_ptrs(s) && s.empty(); } @@ -263,21 +262,21 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (parser::consume_visibility(s) && !parser::consume_string(s, " static ")) { + if (parser::try_consume_visibility(s) && !parser::try_consume_prefix(s, " static ")) { return false; } - if (!parser::consume_type(s, ms_)) { + if (!parser::try_consume_type(s, ms_)) { return false; } - parser::consume_string(s, " "); + parser::try_consume_prefix(s, " "); using Signature = Result(*)(Args...); - return parser::consume_string(s, "__cdecl ") - && parser::consume_string(s, function_name_) - && parser::consume_string(s, "(") - && parser::consume_arg_list(s, ms_, Signature()) - && parser::consume_string(s, ")") + return parser::try_consume_prefix(s, "__cdecl ") + && parser::try_consume_prefix(s, function_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")") && parser::ignore_ptrs(s) && s.empty(); } @@ -300,57 +299,38 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (!parser::consume_visibility(s)) { - return false; - } - parser::consume_string(s, " virtual"); - - if (!parser::consume_string(s, " ")) { - return false; - } - - if (!parser::consume_type(s, ms_)) { - return false; - } - - if (!parser::consume_thiscall(s)) { - return false; - } - if (!parser::consume_type::type>(s, ms_)) { - return false; - } - if (!parser::consume_string(s, "::")) { - return false; - } - if (!parser::consume_string(s, function_name_)) { - return false; - } - if (!parser::consume_string(s, "(")) { + if (!parser::try_consume_visibility(s)) { return false; } + parser::try_consume_prefix(s, " virtual"); using Signature = Result(*)(Args...); - if (!parser::consume_arg_list(s, ms_, Signature())) { - return false; - } - - if (!parser::consume_string(s, ")")) { + const bool is_name_and_args_ok = parser::try_consume_prefix(s, " ") + && parser::try_consume_type(s, ms_) + && parser::try_consume_thiscall(s) + && parser::try_consume_type::type>(s, ms_) + && parser::try_consume_prefix(s, "::") + && parser::try_consume_prefix(s, function_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")"); + if (!is_name_and_args_ok) { return false; } if (std::is_const::value) { - if (!parser::consume_string(s, "const ")) { + if (!parser::try_consume_prefix(s, "const ")) { return false; } } if (std::is_volatile::value) { - if (!parser::consume_string(s, "volatile ")) { + if (!parser::try_consume_prefix(s, "volatile ")) { return false; } } - parser::consume_ptrs(s); + parser::ignore_ptrs(s); return s.empty(); } @@ -358,8 +338,7 @@ namespace parser { return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); } }; -} - +} // namespace parser template std::string mangled_storage_impl::get_variable(const std::string &name) const { @@ -478,7 +457,6 @@ std::vector mangled_storage_impl::get_related() const { return ret; } - }}} #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */ diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp index 749d543c..34ba9901 100644 --- a/test/cpp_mangling.cpp +++ b/test/cpp_mangling.cpp @@ -48,31 +48,31 @@ int main(int argc, char* argv[]) { void(*ptr0)(int) = nullptr; boost::core::string_view s = "integer"; - BOOST_TEST(parser::consume_arg_list(s, ms, ptr0)); + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr0)); BOOST_TEST_EQ(s, "eger"); } { void(*ptr1)(int) = nullptr; boost::core::string_view s = "int"; - BOOST_TEST(parser::consume_arg_list(s, ms, ptr1)); + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr1)); BOOST_TEST(s.empty()); } { void(*ptr2)() = nullptr; boost::core::string_view s = "void"; - BOOST_TEST(parser::consume_arg_list(s, ms, ptr2)); + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr2)); BOOST_TEST(s.empty()); } { void(*ptr3)(int,int) = nullptr; boost::core::string_view s = "int,int"; - BOOST_TEST(parser::consume_arg_list(s, ms, ptr3)); + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr3)); BOOST_TEST(s.empty()); } { void(*ptr4)(int,int,int) = nullptr; boost::core::string_view s = "int,int,int"; - BOOST_TEST(parser::consume_arg_list(s, ms, ptr4)); + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr4)); BOOST_TEST(s.empty()); } From 4ca9b3b75533e85eb5d8dbaadc149a99c186f8e3 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 18 Dec 2024 22:42:31 +0300 Subject: [PATCH 18/18] more cleanups --- include/boost/dll/detail/demangling/msvc.hpp | 60 +++++++------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 9e455a71..e5b5aa04 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -93,6 +93,11 @@ namespace parser { } return result; } + + inline bool ignore_prefix(boost::core::string_view& s, boost::core::string_view prefix) { + parser::try_consume_prefix(s, prefix); + return true; + } inline void consume_ptrs(boost::core::string_view& s) { do { @@ -117,8 +122,8 @@ namespace parser { return parser::try_consume_prefix(s, "void"); } - parser::try_consume_prefix(s, "class "); - parser::try_consume_prefix(s, "struct "); + parser::ignore_prefix(s, "class "); + parser::ignore_prefix(s, "struct "); const auto& mangled_name = ms.get_name(); if (!parser::try_consume_prefix(s, mangled_name)) { @@ -184,12 +189,9 @@ namespace parser { : dtor_name_(dtor_name) {} inline bool operator()(boost::core::string_view s) const { - if (!parser::try_consume_visibility(s)) { - return false; - } - parser::try_consume_prefix(s, " virtual"); - - return parser::try_consume_thiscall(s) + return parser::try_consume_visibility(s) + && parser::ignore_prefix(s, " virtual") + && parser::try_consume_thiscall(s) && parser::try_consume_prefix(s, dtor_name_) && parser::ignore_ptrs(s) && s.empty(); @@ -265,14 +267,11 @@ namespace parser { if (parser::try_consume_visibility(s) && !parser::try_consume_prefix(s, " static ")) { return false; } - if (!parser::try_consume_type(s, ms_)) { - return false; - } - - parser::try_consume_prefix(s, " "); using Signature = Result(*)(Args...); - return parser::try_consume_prefix(s, "__cdecl ") + return parser::try_consume_type(s, ms_) + && parser::ignore_prefix(s, " ") + && parser::try_consume_prefix(s, "__cdecl ") && parser::try_consume_prefix(s, function_name_) && parser::try_consume_prefix(s, "(") && parser::try_consume_arg_list(s, ms_, Signature()) @@ -299,13 +298,10 @@ namespace parser { : function_name_(function_name), ms_(ms) {} inline bool operator()(boost::core::string_view s) const { - if (!parser::try_consume_visibility(s)) { - return false; - } - parser::try_consume_prefix(s, " virtual"); - using Signature = Result(*)(Args...); - const bool is_name_and_args_ok = parser::try_consume_prefix(s, " ") + return parser::try_consume_visibility(s) + && parser::ignore_prefix(s, " virtual") + && parser::try_consume_prefix(s, " ") && parser::try_consume_type(s, ms_) && parser::try_consume_thiscall(s) && parser::try_consume_type::type>(s, ms_) @@ -313,25 +309,11 @@ namespace parser { && parser::try_consume_prefix(s, function_name_) && parser::try_consume_prefix(s, "(") && parser::try_consume_arg_list(s, ms_, Signature()) - && parser::try_consume_prefix(s, ")"); - if (!is_name_and_args_ok) { - return false; - } - - if (std::is_const::value) { - if (!parser::try_consume_prefix(s, "const ")) { - return false; - } - } - - if (std::is_volatile::value) { - if (!parser::try_consume_prefix(s, "volatile ")) { - return false; - } - } - - parser::ignore_ptrs(s); - return s.empty(); + && parser::try_consume_prefix(s, ")") + && (!std::is_const::value || parser::try_consume_prefix(s, "const ")) + && (!std::is_volatile::value || parser::try_consume_prefix(s, "volatile ")) + && parser::ignore_ptrs(s) + && s.empty(); } inline bool operator()(const mangled_storage_base::entry& e) const {