1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#! /usr/bin/perl -w
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown##--------------------------------------------------------------------##
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown##--- Control supervision of applications run with callgrind       ---##
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown##---                                            callgrind_control ---##
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown##--------------------------------------------------------------------##
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  This file is part of Callgrind, a cache-simulator and call graph
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  tracer built on Valgrind.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  Copyright (C) 2003-2011 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  This program is free software; you can redistribute it and/or
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  modify it under the terms of the GNU General Public License as
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  published by the Free Software Foundation; either version 2 of the
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  License, or (at your option) any later version.
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  This program is distributed in the hope that it will be useful, but
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  WITHOUT ANY WARRANTY; without even the implied warranty of
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  General Public License for more details.
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  You should have received a copy of the GNU General Public License
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  along with this program; if not, write to the Free Software
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  02111-1307, USA.
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub getCallgrindPids {
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @pids = ();
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  open LIST, "vgdb $vgdbPrefixOption -l|";
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  while(<LIST>) {
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (/^use --pid=(\d+) for \S*?valgrind\s+(.*?)\s*$/) {
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $pid = $1;
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $cmd = $2;
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  if (!($cmd =~ /--tool=callgrind/)) { next; }
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  while($cmd =~ s/^-+\S+\s+//) {}
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $cmdline{$pid} = $cmd;
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $cmd =~ s/^(\S*).*/$1/;
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $cmd{$pid} = $cmd;
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  #print "Found PID $pid, cmd '$cmd{$pid}', cmdline '$cmdline{$pid}'.\n";
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  push(@pids, $pid);
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  close LIST;
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub printHeader {
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($headerPrinted) { return; }
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $headerPrinted = 1;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "Observe the status and control currently active callgrind runs.\n";
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "(C) 2003-2011, Josef Weidendorfer (Josef.Weidendorfer\@gmx.de)\n\n";
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub printVersion {
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "callgrind_control-@VERSION@\n";
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exit;
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub shortHelp {
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "See '$0 -h' for help.\n";
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exit;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub printHelp {
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printHeader;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "Usage: callgrind_control [options] [pid|program-name...]\n\n";
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "If no pids/names are given, an action is applied to all currently\n";
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "active Callgrind runs. Default action is printing short information.\n\n";
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "Options:\n";
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -h --help         Show this help text\n";
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  --version         Show version\n";
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -s --stat         Show statistics\n";
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -b --back         Show stack/back trace\n";
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -e [<A>,...]      Show event counters for <A>,... (default: all)\n";
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  --dump[=<s>]      Request a dump optionally using <s> as description\n";
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -z --zero         Zero all event counters\n";
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -k --kill         Kill\n";
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  print "  -i --instr=on|off Switch instrumentation state on/off\n";
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  print "Uncommon options:\n";
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  print "  --vgdb-prefix=<prefix> Only provide this if the same was given to Valgrind\n";
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "\n";
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exit;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# Parts more or less copied from cg_annotate (author: Nicholas Nethercote)
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub prepareEvents {
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @events = split(/\s+/, $events);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %events = ();
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $n = 0;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  foreach $event (@events) {
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    $events{$event} = $n;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    $n++;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (@show_events) {
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach my $show_event (@show_events) {
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (defined $events{$show_event}) or
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print "Warning: Event `$show_event' is not being collected\n";
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } else {
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    @show_events = @events;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @show_order = ();
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  foreach my $show_event (@show_events) {
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    push(@show_order, $events{$show_event});
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub max ($$) 
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my ($x, $y) = @_;
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ($x > $y ? $x : $y);
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub line_to_CC ($)
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my @CC = (split /\s+/, $_[0]);
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    (@CC <= @events) or die("Line $.: too many event counts\n");
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return \@CC;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub commify ($) {
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my ($val) = @_;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    1 while ($val =~ s/^(\d+)(\d{3})/$1,$2/);
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return $val;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub compute_CC_col_widths (@) 
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my @CCs = @_;
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my $CC_col_widths = [];
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    # Initialise with minimum widths (from event names)
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach my $event (@events) {
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        push(@$CC_col_widths, length($event));
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    # Find maximum width count for each column.  @CC_col_width positions
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    # correspond to @CC positions.
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach my $CC (@CCs) {
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        foreach my $i (0 .. scalar(@$CC)-1) {
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (defined $CC->[$i]) {
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                # Find length, accounting for commas that will be added
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                my $length = length $CC->[$i];
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                my $clength = $length + int(($length - 1) / 3);
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                $CC_col_widths->[$i] = max($CC_col_widths->[$i], $clength); 
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return $CC_col_widths;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# Print the CC with each column's size dictated by $CC_col_widths.
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub print_CC ($$) 
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my ($CC, $CC_col_widths) = @_;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach my $i (@show_order) {
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $count = (defined $CC->[$i] ? commify($CC->[$i]) : ".");
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $space = ' ' x ($CC_col_widths->[$i] - length($count));
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        print("$space$count ");
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsub print_events ($)
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my ($CC_col_widths) = @_;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach my $i (@show_order) { 
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $event       = $events[$i];
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $event_width = length($event);
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $col_width   = $CC_col_widths->[$i];
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        my $space       = ' ' x ($col_width - $event_width);
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        print("$space$event ");
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# Main
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# To find the list of active pids, we need to have
191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# the --vgdb-prefix option if given.
192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov$vgdbPrefixOption = "";
193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovforeach $arg (@ARGV) {
194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    if ($arg =~ /^--vgdb-prefix=.*$/) {
195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        $vgdbPrefixOption=$arg;
196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    }
197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    next;
198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrowngetCallgrindPids;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$requestEvents = 0;
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$requestDump = 0;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$switchInstr = 0;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$headerPrinted = 0;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$dumpHint = "";
207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov$verbose = 0;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown%spids = ();
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownforeach $arg (@ARGV) {
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($arg =~ /^-/) {
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestDump == 1) { $requestDump = 2; }
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestEvents == 1) { $requestEvents = 2; }
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($arg =~ /^(-h|--help)$/) {
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	printHelp;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^--version$/) {
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	printVersion;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    elsif ($arg =~ /^--vgdb-prefix=.*$/) {
223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        # handled during the initial parsing.
224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        next;
225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    }
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    elsif ($arg =~ /^-v$/) {
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	$verbose++;
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-s|--stat)$/) {
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$printStatus = 1;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-b|--back)$/) {
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$printBacktrace = 1;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^-e$/) {
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$requestEvents = 1;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-d|--dump)(|=.*)$/) {
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ($2 ne "") {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    $requestDump = 2;
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    $dumpHint = substr($2,1);
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    # take next argument as dump hint
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    $requestDump = 1;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-z|--zero)$/) {
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$requestZero = 1;
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-k|--kill)$/) {
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$requestKill = 1;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif ($arg =~ /^(-i|--instr)(|=on|=off)$/) {
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$switchInstr = 2;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ($2 eq "=on") {
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    $switchInstrMode = "on";
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	elsif ($2 eq "=off") {
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    $switchInstrMode = "off";
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    # check next argument for "on" or "off"
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    $switchInstr = 1;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print "Error: unknown command line option '$arg'.\n";
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	shortHelp;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($arg =~ /^[A-Za-z_]/) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    # arguments of -d/-e/-i are non-numeric
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestDump == 1) {
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $requestDump = 2;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $dumpHint = $arg;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      next;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestEvents == 1) {
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $requestEvents = 2;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      @show_events = split(/,/, $arg);
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      next;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($switchInstr == 1) {
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $switchInstr = 2;
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ($arg eq "on") {
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $switchInstrMode = "on";
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      elsif ($arg eq "off") {
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  $switchInstrMode = "off";
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  print "Error: need to specify 'on' or 'off' after '-i'.\n";
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  shortHelp;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      next;
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (defined $cmd{$arg}) { $spids{$arg} = 1; next; }
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $nameFound = 0;
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  foreach $p (@pids) {
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if ($cmd{$p} =~ /$arg$/) {
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $nameFound = 1;
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $spids{$p} = 1;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($nameFound) { next; }
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "Error: Callgrind task with PID/name '$arg' not detected.\n";
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  shortHelp;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownif ($switchInstr == 1) {
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "Error: need to specify 'on' or 'off' after '-i'.\n";
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  shortHelp;
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownif (scalar @pids == 0) {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "No active callgrind runs detected.\n";
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exit;
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown@spids = keys %spids;
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownif (scalar @spids >0) { @pids = @spids; }
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov$vgdbCommand = "";
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown$waitForAnswer = 0;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownif ($requestDump) {
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  $vgdbCommand = "dump";
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if ($dumpHint ne "") { $vgdbCommand .= " ".$dumpHint; }
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovif ($requestZero) { $vgdbCommand = "zero"; }
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovif ($requestKill) { $vgdbCommand = "v.kill"; }
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovif ($switchInstr) { $vgdbCommand = "instrumentation ".$switchInstrMode; }
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownif ($printStatus || $printBacktrace || $requestEvents) {
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  $vgdbCommand = "status internal";
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $waitForAnswer = 1;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownforeach $pid (@pids) {
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $pidstr = "PID $pid: ";
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if ($pid >0) { print $pidstr.$cmdline{$pid}; }
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if ($vgdbCommand eq "") {
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "\n";
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      next;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if ($verbose>0) {
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      print " [requesting '$vgdbCommand']\n";
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  } else {
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      print "\n";
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  open RESULT, "vgdb $vgdbPrefixOption --pid=$pid $vgdbCommand|";
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @tids = ();
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $ctid = 0;
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %fcount = ();
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %func = ();
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %calls = ();
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %events = ();
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @events = ();
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  @threads = ();
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  %totals = ();
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $exec_bbs = 0;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $dist_bbs = 0;
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $exec_calls = 0;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $dist_calls = 0;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $dist_ctxs = 0;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $dist_funcs = 0;
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $threads = "";
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  $events = "";
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(<RESULT>) {
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (/function-(\d+)-(\d+): (.+)$/) {
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ($ctid != $1) {
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$ctid = $1;
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	push(@tids, $ctid);
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$fcount{$ctid} = 0;
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $fcount{$ctid}++;
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $func{$ctid,$fcount{$ctid}} = $3;
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/calls-(\d+)-(\d+): (.+)$/) {
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ($ctid != $1) { next; }
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $calls{$ctid,$fcount{$ctid}} = $3;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/events-(\d+)-(\d+): (.+)$/) {
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ($ctid != $1) { next; }
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $events{$ctid,$fcount{$ctid}} = line_to_CC($3);
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/events-(\d+): (.+)$/) {
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (scalar @events == 0) { next; }
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $totals{$1} = line_to_CC($2);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/executed-bbs: (\d+)/) { $exec_bbs = $1; }
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/distinct-bbs: (\d+)/) { $dist_bbs = $1; }
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/executed-calls: (\d+)/) { $exec_calls = $1; }
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/distinct-calls: (\d+)/) { $dist_calls = $1; }
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/distinct-functions: (\d+)/) { $dist_funcs = $1; }
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/distinct-contexts: (\d+)/) { $dist_ctxs = $1; }
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/events: (.+)$/) { $events = $1; prepareEvents; }
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/threads: (.+)$/) { $threads = $1; @threads = split " ", $threads; }
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elsif (/instrumentation: (\w+)$/) { $instrumentation = $1; }
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  #if ($? ne "0") { print " Got Error $?\n"; }
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if (!$waitForAnswer) { print "  OK.\n"; next; }
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($instrumentation eq "off") {
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print "  No information available as instrumentation is switched off.\n\n";
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    exit;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($printStatus) {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestEvents <1) {
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "  Number of running threads: " .($#threads+1). ", thread IDs: $threads\n";
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "  Events collected: $events\n";
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print "  Functions: ".commify($dist_funcs);
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print " (executed ".commify($exec_calls);
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print ", contexts ".commify($dist_ctxs).")\n";
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print "  Basic blocks: ".commify($dist_bbs);
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print " (executed ".commify($exec_bbs);
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print ", call sites ".commify($dist_calls).")\n";
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($requestEvents >0) {
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    $totals_width = compute_CC_col_widths(values %totals);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print "\n  Totals:";
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print_events($totals_width);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print("\n");
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach $tid (@tids) {
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "   Th".substr("  ".$tid,-2)."  ";
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print_CC($totals{$tid}, $totals_width);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print("\n");
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ($printBacktrace) {
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ($requestEvents >0) {
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $totals_width = compute_CC_col_widths(values %events);
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foreach $tid (@tids) {
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "\n  Frame: ";
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ($requestEvents >0) {
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_events($totals_width);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "Backtrace for Thread $tid\n";
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $i = $fcount{$tid};
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      $c = 0;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while($i>0 && $c<100) {
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$fc = substr(" $c",-2);
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print "   [$fc]  ";
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ($requestEvents >0) {
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  print_CC($events{$tid,$i-1}, $totals_width);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print $func{$tid,$i};
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ($i > 1) {
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  print " (".$calls{$tid,$i-1}." x)";
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print "\n";
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$i--;
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	$c++;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print "\n";
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print "\n";
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	
490