unmangler 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/.gitignore +4 -0
- data/lib/unmangler.rb +6 -4
- data/lib/unmangler/base.rb +27 -0
- data/lib/unmangler/borland.rb +109 -128
- data/lib/unmangler/msvc.rb +1025 -0
- data/lib/unmangler/string_ptr.rb +26 -1
- data/lib/unmangler/version.rb +1 -1
- data/spec/borland_samples_spec.rb +28 -0
- data/spec/borland_spec.rb +2 -0
- data/spec/msvc_samples_spec.rb +28 -0
- data/spec/msvc_spec.rb +61 -0
- data/spec/samples_spec.rb +51 -0
- data/spec/spec_helper.rb +31 -6
- data/unmangler.gemspec +3 -1
- metadata +12 -2
data/lib/unmangler/string_ptr.rb
CHANGED
@@ -61,7 +61,11 @@ class StringPtr
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def index needle
|
64
|
-
@string[@pos..-1].index(needle)
|
64
|
+
(@string[@pos..-1] || '').index(needle)
|
65
|
+
end
|
66
|
+
|
67
|
+
def strlen
|
68
|
+
(@string[@pos..-1] || '').bytesize
|
65
69
|
end
|
66
70
|
|
67
71
|
def =~ re
|
@@ -71,6 +75,23 @@ class StringPtr
|
|
71
75
|
def inc!; @pos+=1; end
|
72
76
|
def dec!; @pos-=1; end
|
73
77
|
|
78
|
+
# get current character and then increment
|
79
|
+
# like in C:
|
80
|
+
# c = *p++
|
81
|
+
def get_inc!
|
82
|
+
c = @string[@pos]
|
83
|
+
@pos+=1
|
84
|
+
c
|
85
|
+
end
|
86
|
+
|
87
|
+
# increment and then get current character
|
88
|
+
# like in C:
|
89
|
+
# c = *++p
|
90
|
+
def inc_get!
|
91
|
+
@pos+=1
|
92
|
+
@string[@pos]
|
93
|
+
end
|
94
|
+
|
74
95
|
def trim!
|
75
96
|
return unless @string
|
76
97
|
if idx = @string.index("\x00")
|
@@ -94,6 +115,10 @@ class StringPtr
|
|
94
115
|
@pos - x.pos
|
95
116
|
end
|
96
117
|
end
|
118
|
+
|
119
|
+
def inspect
|
120
|
+
"#<StringPtr @pos=#{@pos.inspect}: #{@string[@pos..-1].inspect}>"
|
121
|
+
end
|
97
122
|
end
|
98
123
|
|
99
124
|
if $0 == __FILE__
|
data/lib/unmangler/version.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Unmangler::Borland do
|
4
|
+
if max_idx = ENV['LONG_RUN']
|
5
|
+
max_idx = max_idx.to_i
|
6
|
+
idx = 0
|
7
|
+
YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml")).each do |mangled, unmangled|
|
8
|
+
unmangled = preprocess_borland unmangled
|
9
|
+
idx += 1
|
10
|
+
break if idx > max_idx
|
11
|
+
it "should unmangle #{mangled}" do
|
12
|
+
Unmangler::Borland.unmangle(mangled).should == unmangled
|
13
|
+
end
|
14
|
+
end
|
15
|
+
else
|
16
|
+
it "should unmangle" do
|
17
|
+
YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml")).each do |mangled, unmangled|
|
18
|
+
unmangled = preprocess_borland unmangled
|
19
|
+
actual = Unmangler::Borland.unmangle(mangled)
|
20
|
+
actual.should eql(unmangled), [
|
21
|
+
"mangled : #{mangled.white}",
|
22
|
+
"expected: #{unmangled.green}",
|
23
|
+
"actual : #{actual.red}"
|
24
|
+
].join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/borland_spec.rb
CHANGED
@@ -70,4 +70,6 @@ describe Unmangler::Borland do
|
|
70
70
|
check "@Dbcommon@GetTableNameFromSQLEx$qqrx17System@WideString25Dbcommon@IDENTIFIEROption",
|
71
71
|
"__fastcall Dbcommon::GetTableNameFromSQLEx(const System::WideString, Dbcommon::IDENTIFIEROption)"
|
72
72
|
|
73
|
+
check '@Classes@TThread@$bcdtr$qqrv', '__fastcall Classes::TThread::`class destructor`()'
|
74
|
+
check '@Timespan@TTimeSpan@$bcctr$qqrv', '__fastcall Timespan::TTimeSpan::`class constructor`()'
|
73
75
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Unmangler::MSVC do
|
4
|
+
if max_idx = ENV['LONG_RUN']
|
5
|
+
max_idx = max_idx.to_i
|
6
|
+
idx = 0
|
7
|
+
YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml")).each do |mangled, unmangled|
|
8
|
+
idx += 1
|
9
|
+
break if idx > max_idx
|
10
|
+
it "should unmangle #{mangled}" do
|
11
|
+
unmangled = preprocess_msvc unmangled
|
12
|
+
Unmangler::MSVC.unmangle(mangled).should == unmangled
|
13
|
+
end
|
14
|
+
end
|
15
|
+
else
|
16
|
+
it "should unmangle" do
|
17
|
+
YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml")).each do |mangled, unmangled|
|
18
|
+
unmangled = preprocess_msvc unmangled
|
19
|
+
actual = Unmangler::MSVC.unmangle(mangled)
|
20
|
+
actual.should eql(unmangled), [
|
21
|
+
"mangled : #{mangled.white}",
|
22
|
+
"expected: #{unmangled.green}",
|
23
|
+
"actual : #{actual.red}"
|
24
|
+
].join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/msvc_spec.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Unmangler::MSVC do
|
4
|
+
|
5
|
+
it "keeps original name if not mangled" do
|
6
|
+
s = "foo::bar(@)"
|
7
|
+
Unmangler::MSVC.unmangle(s).should == s
|
8
|
+
end
|
9
|
+
|
10
|
+
# describe "#unmangle" do
|
11
|
+
# it "raises error on bad input" do
|
12
|
+
# lambda{
|
13
|
+
# Unmangler::MSVC.unmangle("@TTabPage@$bctr")
|
14
|
+
# }.should raise_error
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
|
18
|
+
describe "#safe_unmangle" do
|
19
|
+
it "raises no error and returns original on bad input" do
|
20
|
+
s = "@TTabPage@$bctr"
|
21
|
+
Unmangler::MSVC.safe_unmangle(s).should == s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.check mangled, unmangled, test_no_args = true
|
26
|
+
it "unmangles #{mangled}" do
|
27
|
+
Unmangler::MSVC.unmangle(mangled).should == unmangled
|
28
|
+
end
|
29
|
+
|
30
|
+
it "unmangles #{mangled} w/o args" do
|
31
|
+
x = unmangled.split('(').first.strip.
|
32
|
+
gsub(/(public|private|protected): /,'').
|
33
|
+
gsub(/(void|__ptr64|int|__thiscall|__cdecl|virtual|class|struct) /,'').
|
34
|
+
strip
|
35
|
+
|
36
|
+
Unmangler::MSVC.unmangle(mangled, :args => false).should == x
|
37
|
+
end if test_no_args
|
38
|
+
end
|
39
|
+
|
40
|
+
check "?h@@YAXH@Z", "void __cdecl h(int)"
|
41
|
+
check "?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z", "void __cdecl AFXSetTopLevelFrame(class CFrameWnd *)"
|
42
|
+
check "??0_Lockit@std@@QAE@XZ", "public: __thiscall std::_Lockit::_Lockit(void)"
|
43
|
+
|
44
|
+
check "?SetAt@CString@@QAEXHD@Z", "public: void __thiscall CString::SetAt(int, char)"
|
45
|
+
check "?LoadFrame@CMDIFrameWndEx@@UAEHIKPAVCWnd@@PAUCCreateContext@@@Z",
|
46
|
+
"public: virtual int __thiscall CMDIFrameWndEx::LoadFrame(unsigned int, unsigned long, class CWnd *, struct CCreateContext *)"
|
47
|
+
|
48
|
+
check "??0DNameStatusNode@@AEAA@W4DNameStatus@@@Z",
|
49
|
+
"private: __cdecl DNameStatusNode::DNameStatusNode(enum DNameStatus) __ptr64"
|
50
|
+
|
51
|
+
check "?Add@?$CArray@VCSize@@V1@@@QAEHVCSize@@@Z",
|
52
|
+
"public: int __thiscall CArray<class CSize, class CSize>::Add(class CSize)"
|
53
|
+
|
54
|
+
check "??$_Char_traits_cat@U?$char_traits@D@std@@@std@@YA?AU_Secure_char_traits_tag@0@XZ",
|
55
|
+
"struct std::_Secure_char_traits_tag __cdecl std::_Char_traits_cat<struct std::char_traits<char> >(void)",
|
56
|
+
false
|
57
|
+
|
58
|
+
check "?dtor$0@?0???0CDockSite@@QEAA@XZ@4HA",
|
59
|
+
"int `public: __cdecl CDockSite::CDockSite(void) __ptr64'::`1'::dtor$0",
|
60
|
+
false
|
61
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def combined_samples
|
4
|
+
@@combined_samples ||=
|
5
|
+
begin
|
6
|
+
msvc = YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml"))
|
7
|
+
borland = YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml"))
|
8
|
+
|
9
|
+
combined = {}
|
10
|
+
(msvc.keys + borland.keys).uniq.each do |key|
|
11
|
+
um = msvc[key]
|
12
|
+
ub = borland[key]
|
13
|
+
|
14
|
+
combined[key] =
|
15
|
+
if um && um != key
|
16
|
+
preprocess_msvc um
|
17
|
+
elsif ub && ub != key
|
18
|
+
preprocess_borland ub
|
19
|
+
else
|
20
|
+
# neither
|
21
|
+
key
|
22
|
+
end
|
23
|
+
end
|
24
|
+
combined
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Unmangler do
|
29
|
+
if max_idx = ENV['LONG_RUN']
|
30
|
+
max_idx = max_idx.to_i
|
31
|
+
idx = 0
|
32
|
+
combined_samples.each do |mangled, unmangled|
|
33
|
+
idx += 1
|
34
|
+
break if idx > max_idx
|
35
|
+
it "should unmangle #{mangled}" do
|
36
|
+
Unmangler.unmangle(mangled).should == unmangled
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
it "should unmangle" do
|
41
|
+
combined_samples.each do |mangled, unmangled|
|
42
|
+
actual = Unmangler.unmangle(mangled)
|
43
|
+
actual.should eql(unmangled), [
|
44
|
+
"mangled : #{mangled.white}",
|
45
|
+
"expected: #{unmangled.green}",
|
46
|
+
"actual : #{actual.red}"
|
47
|
+
].join("\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,39 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'awesome_print'
|
3
|
+
|
1
4
|
$: << File.expand_path("../lib", File.dirname(__FILE__))
|
2
5
|
require 'unmangler'
|
3
6
|
|
7
|
+
SAMPLES_DIR = File.expand_path("../samples", File.dirname(__FILE__))
|
8
|
+
|
9
|
+
def preprocess_msvc s
|
10
|
+
s.gsub(',',', ')
|
11
|
+
end
|
12
|
+
|
13
|
+
def preprocess_borland s
|
14
|
+
r = s.gsub('const const ','const ')
|
15
|
+
|
16
|
+
# move '__fastcall' to start of the string if its found in middle of string
|
17
|
+
pos = r.index(" __fastcall ")
|
18
|
+
if pos && pos != 0
|
19
|
+
r = "__fastcall " + r.sub("__fastcall ", "")
|
20
|
+
end
|
21
|
+
|
22
|
+
r
|
23
|
+
end
|
24
|
+
|
4
25
|
RSpec.configure do |config|
|
5
26
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
6
27
|
config.run_all_when_everything_filtered = true
|
7
|
-
#config.filter_run :focus
|
8
28
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
29
|
+
config.before(:suite) do
|
30
|
+
Dir[File.join(SAMPLES_DIR, "*.bz2")].each do |fname|
|
31
|
+
unless File.exist?(fname.sub(/\.bz2$/,''))
|
32
|
+
puts "[.] unpacking #{fname} .."
|
33
|
+
system("bunzip2", "-dk", fname)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
config.backtrace_clean_patterns = [/\/rspec/]
|
14
39
|
end
|
data/unmangler.gemspec
CHANGED
@@ -12,7 +12,9 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.summary = gem.description + %q{, i.e. '@myclass@func$qil' => 'myclass::func(int, long)'}
|
13
13
|
gem.homepage = "http://zed.0xff.me"
|
14
14
|
|
15
|
-
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.files = `git ls-files`.split($/).
|
16
|
+
delete_if{ |x| x.end_with?(".bz2") || x.include?("misc/") }
|
17
|
+
|
16
18
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
20
|
gem.require_paths = ["lib"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unmangler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey "Zed" Zaikin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Unmangles mangled C++/Delphi names"
|
14
14
|
email:
|
@@ -25,10 +25,16 @@ files:
|
|
25
25
|
- README.md.tpl
|
26
26
|
- Rakefile
|
27
27
|
- lib/unmangler.rb
|
28
|
+
- lib/unmangler/base.rb
|
28
29
|
- lib/unmangler/borland.rb
|
30
|
+
- lib/unmangler/msvc.rb
|
29
31
|
- lib/unmangler/string_ptr.rb
|
30
32
|
- lib/unmangler/version.rb
|
33
|
+
- spec/borland_samples_spec.rb
|
31
34
|
- spec/borland_spec.rb
|
35
|
+
- spec/msvc_samples_spec.rb
|
36
|
+
- spec/msvc_spec.rb
|
37
|
+
- spec/samples_spec.rb
|
32
38
|
- spec/spec_helper.rb
|
33
39
|
- unmangler.gemspec
|
34
40
|
homepage: http://zed.0xff.me
|
@@ -56,5 +62,9 @@ specification_version: 4
|
|
56
62
|
summary: Unmangles mangled C++/Delphi names", i.e. '@myclass@func$qil' => 'myclass::func(int,
|
57
63
|
long)'
|
58
64
|
test_files:
|
65
|
+
- spec/borland_samples_spec.rb
|
59
66
|
- spec/borland_spec.rb
|
67
|
+
- spec/msvc_samples_spec.rb
|
68
|
+
- spec/msvc_spec.rb
|
69
|
+
- spec/samples_spec.rb
|
60
70
|
- spec/spec_helper.rb
|