From 3c8e452e0ad0c05f55a347e90d7cc001a4271422 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 8 Sep 2022 23:13:54 -0400 Subject: [PATCH] Support function-local static variables --- src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 80697c7..9aa3162 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -248,6 +248,22 @@ pub fn demangle(mut str: &str) -> Option { let mut return_type_pre = String::new(); let mut return_type_post = String::new(); let mut qualified = String::new(); + let mut static_var = String::new(); + + // Handle new static function variables (Wii CW) + let guard = str.starts_with("@GUARD@"); + if guard || str.starts_with("@LOCAL@") { + str = &str[7..]; + let idx = str.rfind('@')?; + let (rest, var) = str.split_at(idx); + if guard { + static_var = format!("{} guard", &var[1..]); + } else { + static_var = var[1..].to_string(); + } + str = rest; + } + if str.starts_with("__") { special = true; str = &str[2..]; @@ -268,6 +284,24 @@ pub fn demangle(mut str: &str) -> Option { let (name, args) = demangle_template_args(fn_name_out)?; fn_name = format!("{}{}", name, args); } + + // Handle old static function variables (GC CW) + if let Some(first_idx) = fn_name.find('$') { + let second_idx = fn_name[first_idx + 1..].find('$')?; + let (var, rest) = fn_name.split_at(first_idx); + let (var_type, rest) = rest[1..].split_at(second_idx); + if !var_type.starts_with("localstatic") { + return None; + } + if var == "init" { + // Sadly, $localstatic doesn't provide the variable name in guard/init + static_var = format!("{} guard", var_type); + } else { + static_var = var.to_string(); + } + fn_name = rest[1..].to_string(); + } + str = &rest[2..]; } let mut class_name = String::new(); @@ -313,6 +347,9 @@ pub fn demangle(mut str: &str) -> Option { if !return_type_pre.is_empty() { fn_name = format!("{} {}{}", return_type_pre, fn_name, return_type_post); } + if !static_var.is_empty() { + fn_name = format!("{}::{}", fn_name, static_var); + } Some(fn_name) } @@ -532,5 +569,23 @@ mod tests { demangle("__ct__Q210Metrowerks683compressed_pair,Q33std131__multimap_do_transform,Q23std53allocator>,0>13value_compare,Q23std53allocator>>4node>,Q210Metrowerks337compressed_pair,PQ33std276__tree_deleter,Q33std131__multimap_do_transform,Q23std53allocator>,0>13value_compare,Q23std53allocator>>4node>>FRQ23std301allocator,Q33std131__multimap_do_transform,Q23std53allocator>,0>13value_compare,Q23std53allocator>>4node>Q210Metrowerks337compressed_pair,PQ33std276__tree_deleter,Q33std131__multimap_do_transform,Q23std53allocator>,0>13value_compare,Q23std53allocator>>4node>"), Some("Metrowerks::compressed_pair, std::__multimap_do_transform, std::allocator>, 0>::value_compare, std::allocator>>::node>&, Metrowerks::compressed_pair, std::__tree_deleter, std::__multimap_do_transform, std::allocator>, 0>::value_compare, std::allocator>>::node*>>::compressed_pair(std::allocator, std::__multimap_do_transform, std::allocator>, 0>::value_compare, std::allocator>>::node>&, Metrowerks::compressed_pair, std::__tree_deleter, std::__multimap_do_transform, std::allocator>, 0>::value_compare, std::allocator>>::node*>)".to_string()) ); + assert_eq!( + demangle("skBadString$localstatic3$GetNameByToken__31TTokenSet<18EScriptObjectState>CF18EScriptObjectState"), + Some("TTokenSet::GetNameByToken(EScriptObjectState) const::skBadString".to_string()) + ); + assert_eq!( + demangle("init$localstatic4$GetNameByToken__31TTokenSet<18EScriptObjectState>CF18EScriptObjectState"), + Some("TTokenSet::GetNameByToken(EScriptObjectState) const::localstatic4 guard".to_string()) + ); + assert_eq!( + demangle("@LOCAL@GetAnmPlayPolicy__Q24nw4r3g3dFQ34nw4r3g3d9AnmPolicy@policyTable"), + Some("nw4r::g3d::GetAnmPlayPolicy(nw4r::g3d::AnmPolicy)::policyTable".to_string()) + ); + assert_eq!( + demangle("@GUARD@GetAnmPlayPolicy__Q24nw4r3g3dFQ34nw4r3g3d9AnmPolicy@policyTable"), + Some( + "nw4r::g3d::GetAnmPlayPolicy(nw4r::g3d::AnmPolicy)::policyTable guard".to_string() + ) + ); } }