Skip to content

Commit 9719296

Browse files
committed
fixup calltree.pl
1 parent f1af9a0 commit 9719296

File tree

6 files changed

+266
-17
lines changed

6 files changed

+266
-17
lines changed

calltree.pl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ ($)
369369
}
370370

371371
sub replace_whitespaces($) {
372-
$_[0] =~ s/(?:^\s+)|(?:\s+$)|(?:(?<=\p{IsPunct})\s+)|(?:\s+(?=\p{IsPunct}))//gr;
372+
$_[0] =~ s/(?:^\s+)|(?:\s+$)|(?:(?<=\W)\s+)|(?:\s+(?=\W))//gr;
373373
}
374374

375375
sub remove_misc($) {
@@ -938,7 +938,13 @@ ($$$$$$$$)
938938
}
939939
}
940940

941-
@child_nodes = grep {defined($_)} @child_nodes;
941+
@child_nodes = grep {
942+
my $real_node = $_;
943+
if (exists($_->{cache_key}) && exists($pruned->{$_->{cache_key}})) {
944+
$real_node = $pruned->{$_->{cache_key}};
945+
}
946+
(exists($real_node->{child}) && scalar(@{$real_node->{child}}) > 0) || $matched;
947+
} grep {defined($_)} @child_nodes;
942948

943949
if (@child_nodes) {
944950
$install_child->($node, [ @child_nodes ]);
@@ -1172,7 +1178,7 @@ ($$$$$)
11721178
simple_name => $name,
11731179
file_info => "",
11741180
};
1175-
return &eliminate_empty_children(&sub_tree($called_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache));
1181+
return &sub_tree($called_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache);
11761182
}
11771183

11781184
sub fuzzy_called_tree($$$$$$) {
@@ -1182,7 +1188,7 @@ ($$$$$$)
11821188

11831189
$root->{child} = [
11841190
grep {defined($_)} map {
1185-
&called_tree($called, $_, $func_match_rule, $file_match_rule, $depth);
1191+
&eliminate_empty_children(&called_tree($called, $_, $func_match_rule, $file_match_rule, $depth));
11861192
} @names
11871193
];
11881194
return $root;
@@ -1413,7 +1419,7 @@ ($$$$$$)
14131419

14141420
my $node = $new_callee_or_match_node->({ name => $name, call => $name, simple_name => $name });
14151421

1416-
return &eliminate_empty_children(&sub_tree($calling_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache));
1422+
return &sub_tree($calling_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache);
14171423
}
14181424

14191425
sub adjust_calling_tree($) {
@@ -1444,7 +1450,7 @@ ($$$$$$)
14441450
my $child0_name = $child0->{name};
14451451
my $child0_unique_id = "$child0_file_info.$child0_name";
14461452
next if exists $uniques->{$child0_unique_id};
1447-
my $tree = calling_tree($calling_graph, $name, $func_match_rule, $file_match_rule, $depth, $uniques);
1453+
my $tree = &eliminate_empty_children(&calling_tree($calling_graph, $name, $func_match_rule, $file_match_rule, $depth, {}));
14481454
push @trees, $tree if defined($tree);
14491455
}
14501456
return {
@@ -1906,4 +1912,4 @@ ()
19061912
}
19071913

19081914
print get_cache_or_run_keyed(@key, cached_sha256_file(@key), \&show_tree);
1909-
# print show_tree();
1915+
#print show_tree();

color_palette.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
my @fg = (31 .. 37, 90 .. 97);
1414
my @bg = (31 .. 47, 100 .. 106);
15-
my @ef = (0 .. 8);
15+
my @ef = (1 .. 7);
1616
my $count = 0;
1717
for (1 .. @fg * @bg * @ef) {
1818
#my $i=($_-1)/(@bg*@ef);
@@ -29,7 +29,7 @@
2929
(!defined($expect_bg) || $expect_bg == $bg) &&
3030
(!defined($expect_ef) || $expect_ef == $ef)) {
3131
print "\e[${fg};${bg};${ef}m \\e[${fg};${bg};${ef}m\\e[m\e[m";
32-
if (($count+1) % 8 == 0) {
32+
if (($count) % 7 == 6) {
3333
print "\n";
3434
}
3535
else {

java_calltree.pl

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ ()
235235
sub gen_re_func_call() {
236236
my $cs_tokens = "$RE_WS* (?:(?: $RE_SCOPED_IDENTIFIER $RE_WS* , $RE_WS*)* $RE_SCOPED_IDENTIFIER $RE_WS*)?";
237237
#my $re_func_call = "((?:($RE_SCOPED_IDENTIFIER) $RE_WS *(?:\\($cs_tokens\\))? $RE_WS* (?: \\. | -> | :: ) $RE_WS* )? ($RE_SCOPED_IDENTIFIER)) $RE_WS* [(]";
238-
my $re_func_call = "((?:($RE_SCOPED_IDENTIFIER) $RE_WS* (?: \\. | -> | :: ) $RE_WS* )? ($RE_SCOPED_IDENTIFIER)) $RE_WS* [(]";
238+
my $re_func_call = "((?:($RE_SCOPED_IDENTIFIER) $RE_WS (?: \\. | -> | :: ) $RE_WS* )? ($RE_SCOPED_IDENTIFIER)) $RE_WS* [(]";
239239
return $re_func_call =~ s/ //gr;
240240
}
241241

@@ -329,7 +329,7 @@ ($)
329329
}
330330

331331
sub replace_whitespaces($) {
332-
$_[0] =~ s/(?:^\s+)|(?:\s+$)|(?:(?<=\p{IsPunct})\s+)|(?:\s+(?=\p{IsPunct}))//gr;
332+
$_[0] =~ s/(?:^\s+)|(?:\s+$)|(?:(?<=\W)\s+)|(?:\s+(?=\W))//gr;
333333
}
334334

335335
sub replace_template_args_1layer($) {
@@ -886,7 +886,13 @@ ($$$$$$$$)
886886
}
887887
}
888888

889-
@child_nodes = grep {defined($_)} @child_nodes;
889+
@child_nodes = grep {
890+
my $real_node = $_;
891+
if (exists($_->{cache_key}) && exists($pruned->{$_->{cache_key}})) {
892+
$real_node = $pruned->{$_->{cache_key}};
893+
}
894+
(exists($real_node->{child}) && scalar(@{$real_node->{child}}) > 0) || $matched;
895+
} grep {defined($_)} @child_nodes;
890896

891897
if (@child_nodes) {
892898
$install_child->($node, [ @child_nodes ]);
@@ -1120,7 +1126,7 @@ ($$$$$)
11201126
simple_name => $name,
11211127
file_info => "",
11221128
};
1123-
return &eliminate_empty_children(&sub_tree($called_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache));
1129+
return &sub_tree($called_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache);
11241130
}
11251131

11261132
sub fuzzy_called_tree($$$$$$) {
@@ -1130,7 +1136,7 @@ ($$$$$$)
11301136

11311137
$root->{child} = [
11321138
grep {defined($_)} map {
1133-
&called_tree($called, $_, $func_match_rule, $file_match_rule, $depth);
1139+
&eliminate_empty_children(&called_tree($called, $_, $func_match_rule, $file_match_rule, $depth));
11341140
} @names
11351141
];
11361142
return $root;
@@ -1361,7 +1367,7 @@ ($$$$$$)
13611367

13621368
my $node = $new_callee_or_match_node->({ name => $name, call => $name, simple_name => $name });
13631369

1364-
return &eliminate_empty_children(&sub_tree($calling_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache));
1370+
return &sub_tree($calling_graph, $node, 0, $depth, {}, $get_id_and_child, $install_child, $Global_pruned_cache);
13651371
}
13661372

13671373
sub adjust_calling_tree($) {
@@ -1392,7 +1398,7 @@ ($$$$$$)
13921398
my $child0_name = $child0->{name};
13931399
my $child0_unique_id = "$child0_file_info.$child0_name";
13941400
next if exists $uniques->{$child0_unique_id};
1395-
my $tree = calling_tree($calling_graph, $name, $func_match_rule, $file_match_rule, $depth, $uniques);
1401+
my $tree = &eliminate_empty_children(&calling_tree($calling_graph, $name, $func_match_rule, $file_match_rule, $depth, {}));
13961402
push @trees, $tree if defined($tree);
13971403
}
13981404
return {
@@ -1813,7 +1819,7 @@ ($)
18131819
}
18141820

18151821
my @lines = map {chomp;
1816-
$_} qx(ag $multiline_break -U -G $cpp_filename_pattern $ignore_pattern '$re');
1822+
$_} qx(ag $multiline_break -U -G $java_filename_pattern $ignore_pattern '$re');
18171823
@lines = merge_lines(@lines);
18181824
@lines = grep {defined($_->[2])} map {
18191825
my $match = ($_->[3] =~ qr/($re)/, $1);

mind.pl

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/perl
2+
use strict;
3+
use warnings;
4+
use Data::Dumper;
5+
6+
sub mind(@) {
7+
my ($title, @lines) = @_;
8+
# [level, content, children]
9+
my @stk=([0, $title, []]);
10+
foreach my $ln (@lines) {
11+
if ($ln =~/^([-]*)\s*(.*)/) {
12+
my ($dashes, $content) = ($1, $2);
13+
my $level = length($dashes);
14+
while (scalar(@stk) > 0 && $stk[-1][0] + 1 != $level) {
15+
pop @stk;
16+
}
17+
die "Ill-formed mind input" if (scalar(@stk) == 0);
18+
my $top = $stk[-1];
19+
my $curr = [$level, $content, []];
20+
push @stk, $curr;
21+
my ($top_level,$parent_content,$top_children) = @$top;
22+
push @$top_children, $curr;
23+
}
24+
}
25+
return $stk[0];
26+
}
27+
28+
my $lines =<<DONE
29+
calltree.pl
30+
- prerequisites
31+
-- perl 5.10+: Most Linux distributions and MacOS have intalled perl 5.10+.
32+
-- ag(the_silver_searcher):
33+
--- Must be installed,
34+
--- Although calltree.pl can leverage official https://github.com/ggreer/the_silver_searcher, but not the best choice.
35+
--- Suggest to install customized https://github.com/satanson/the_silver_searcher that extract function body precisely.
36+
-- calltree.pl/java_calltree.pl/cpptree.pl/javatree.pl/deptree.pl are standalone scripts with no others dependencies.
37+
-
38+
- format: calltree.pl '<src_regex>' '[[-]<dst_regex>]' <mode(0|1|2|3|4)> <verbose> <[-]depth> [[-]file_name_regex]
39+
- REGEX in calltree.pl are perl regex, and must be enclosed by quotes.
40+
-
41+
- arguments:
42+
-- <src_regex>: (required) Search since functions match `src_regex`, these functions will be root of subtrees.
43+
--- demos
44+
---- calltree.pl '(\\bfsync|fdatasync|sync_file_range\\b)' 'Write' 1 1 3 # rocksdb
45+
---- calltree.pl '((?i)\\b\\w*compaction\\w*\\b)' '' 1 1 3 # rocksdb
46+
-- [[-]<dst_regex>]: (required) Search till functions match `dst_regex`, these functions will be leaf of subtrees.
47+
--- demos
48+
---- calltree.pl '(\\bfsync|fdatasync|sync_file_range\\b)' '' 1 1 3 # empty '' means match any functions
49+
---- calltree.pl '(\\bfsync|fdatasync|sync_file_range\\b)' '-Write' 1 1 3 # '-<regex>' means interested in functions not match the regex
50+
---- calltree.pl '(\\bfsync|fdatasync|sync_file_range\\b)' '(?i)compaction' 1 1 3 # '<regex>' means interested in functions match the regex
51+
--
52+
-- <mode>: (required)
53+
--- 0: show calling tree(caller is parent node, callee is child node).
54+
---- demos
55+
----- calltree.pl 'parsePassPipeline' '(Pass|Analysis|Pipeline)\$' 0 1 2 # llvm
56+
----- calltree.pl 'main' 'Pipeline' 0 1 3 # llvm
57+
--- 1: show called tree(callee is parent node, caller is child node).
58+
---- demos
59+
-----
60+
-----
61+
--- 2: show outermost functions that call others and have no callers.
62+
--- 3: show intermost functions that are called by others and have no callees.
63+
--- 4: show called tree and used to find functions/files that enclosing the contents matches <src_regex>.
64+
--
65+
-- <verbose>: (required)
66+
--- 0: not show file-lineno infos, take effect on all modes.
67+
--- 1: show file-lineno infos, take effect on all modes.
68+
--- qhcv or hcv: a four-digit or three-digit number, take effect only on mode 0.
69+
---- q: quiet, 0 for non-quiet(default) and 1 for quiet, not show common subtrees when quiet.
70+
---- h: height of common subtrees, >=3(default), subtrees height than `h` will be extracted as common subtrees.
71+
---- c: repetition count of common subtrees, >=2(default), subtrees ocurrs at least for `c` times will be considered as common subtrees.
72+
---- v: verbose, 0 for not showing file-lineno infos and 1 for showing file-lineno infos.
73+
---- motivation: mode 0(show calling tree) leverages qhcv and hcv to speed up searching and collapse duplicate calling patterns.
74+
---- demos:
75+
----- a
76+
----- b
77+
----- c
78+
--
79+
-- [-]<depth>: (required) the depth of the tree output, a larger depth means cost more times to generate trees.
80+
--- depth > 0: take effect on all modes.
81+
--- depth < 0: only take effect on mode 1 (show called tree),
82+
---- It is quite similar to |depth|, but adjacent functions with the name will be collapsed to only one.
83+
---- It is very useful when your are reading codes that designed in Visitor or Iterator pattern.
84+
--- demos:
85+
---- a
86+
---- b
87+
---- c
88+
--
89+
-- [[-]<file_name_regex>]: (optional) Sometimes, your are only interested in functions in files whose names match the regex or not match.
90+
--- demos
91+
---- a
92+
---- b
93+
-
94+
- How to reach me:
95+
-- E-Mail: ranpanf\@gmail.com
96+
DONE
97+
;
98+
99+
sub should_prune_subtree($$) {
100+
}
101+
102+
sub format_tree($$$$\&\&) {
103+
my ($root, $level, $verbose, $enable_prune, $get_entry, $get_child) = @_;
104+
$root->{level} = $level;
105+
unless (defined($root) && %$root) {
106+
return ();
107+
}
108+
109+
my ($common_idx) = should_prune_subtree($root, $enable_prune);
110+
my $entry = $get_entry->($root, $verbose, $common_idx);
111+
my @result = ($entry);
112+
113+
my @child = $get_child->($root);
114+
if (!scalar(@child)) {
115+
return @result;
116+
}
117+
118+
my $last_child = pop @child;
119+
120+
foreach my $chd (@child) {
121+
my ($first, @rest) = &format_tree($chd, $level + 1, $verbose, $enable_prune, $get_entry, $get_child);
122+
if ((!defined($first) || $first =~/^\s*$/) && scalar(@rest)==0) {
123+
push @result, "";
124+
next;
125+
}
126+
push @result, "├── $first";
127+
push @result, map {"│   $_"} @rest;
128+
}
129+
130+
my ($first, @rest) = &format_tree($last_child, $level + 1, $verbose, $enable_prune, $get_entry, $get_child);
131+
push @result, "└── $first";
132+
push @result, map {" $_"} @rest;
133+
return @result;
134+
}
135+
sub format_mind($) {
136+
my $root = shift;
137+
my $get_entry = sub($$$) {
138+
my $root = shift;
139+
return $root->{name};
140+
};
141+
my $get_child = sub($) {
142+
my $root = shift;
143+
return map {+{level=>$_->[0], name=>$_->[1], child=>$_->[2]}} @{$root->{child}};
144+
};
145+
my $tree_root = {
146+
level=>$root->[0],
147+
name=>$root->[1],
148+
child=>$root->[2],
149+
};
150+
151+
&format_tree($tree_root, 0, 0, 0, $get_entry, $get_child);
152+
}
153+
154+
my @lines = split /\n/, $lines;
155+
print join qq//, map{"$_\n"} format_mind(mind(@lines));

unittest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ set(TESTS
2727
test_seq_mutex.cc
2828
test_analysis.cc
2929
test_memory_leak.cc
30+
test_llvm.cc
3031
)
3132
foreach (src ${TESTS})
3233
get_filename_component(exe ${src} NAME_WE)

0 commit comments

Comments
 (0)