diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index cd35d9465..a18b00480 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2735,6 +2735,11 @@ and are only documented here for completeness: The oldval, newval or delta arguments may be used to specify additional constraints. Returns: *found_index*, or *nil* if end reached. +* ``dfhack.internal.cxxDemangle(mangled_name)`` + + Decodes a mangled C++ symbol name. Returns the demangled name on success, or + ``nil, error_message`` on failure. + * ``dfhack.internal.getDir(path)`` Lists files/directories in a directory. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index c19c10197..578bb4746 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -3333,6 +3333,24 @@ static int internal_diffscan(lua_State *L) return 1; } +static int internal_cxxDemangle(lua_State *L) +{ + std::string mangled = luaL_checkstring(L, 1); + std::string status; + std::string demangled = cxx_demangle(mangled, &status); + if (demangled.length()) + { + lua_pushstring(L, demangled.c_str()); + return 1; + } + else + { + lua_pushnil(L); + lua_pushstring(L, status.c_str()); + return 2; + } +} + static int internal_runCommand(lua_State *L) { color_ostream *out = NULL; @@ -3637,6 +3655,7 @@ static const luaL_Reg dfhack_internal_funcs[] = { { "memcmp", internal_memcmp }, { "memscan", internal_memscan }, { "diffscan", internal_diffscan }, + { "cxxDemangle", internal_cxxDemangle }, { "getDir", filesystem_listdir }, { "runCommand", internal_runCommand }, { "getModifiers", internal_getModifiers }, diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index 7ffd4e1c6..a90cf1208 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -36,6 +36,7 @@ distribution. #else #include #include + #include #endif #include @@ -472,3 +473,29 @@ DFHACK_EXPORT std::string DF2CONSOLE(DFHack::color_ostream &out, const std::stri { return out.is_console() ? DF2CONSOLE(in) : in; } + +DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::string *status_out) +{ +#ifdef __GNUC__ + int status; + char *demangled = abi::__cxa_demangle(mangled_name.c_str(), nullptr, nullptr, &status); + std::string out; + if (demangled) { + out = demangled; + free(demangled); + } + if (status_out) { + if (status == 0) *status_out = "success"; + else if (status == -1) *status_out = "memory allocation failure"; + else if (status == -2) *status_out = "invalid mangled name"; + else if (status == -3) *status_out = "invalid arguments"; + else *status_out = "unknown error"; + } + return out; +#else + if (status_out) { + *status_out = "not implemented on this platform"; + } + return ""; +#endif +} diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 59adcdbe5..06915fde5 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -474,3 +474,5 @@ DFHACK_EXPORT std::string UTF2DF(const std::string &in); DFHACK_EXPORT std::string DF2UTF(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(DFHack::color_ostream &out, const std::string &in); + +DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::string *status_out);