blob: 64e120f2716b317a9567c33a53a7a7a1a650c3d3 [file] [log] [blame]
#!/usr/bin/perl -w
#
# handlertree.pl
# ~~~~~~~~~~~~~~
# A tool for post-processing the debug output generated by Asio-based programs
# to print the tree of handlers that resulted in some specified handler ids.
# Programs write this output to the standard error stream when compiled with
# the define `ASIO_ENABLE_HANDLER_TRACKING'.
#
# Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
use strict;
my %target_handlers = ();
my @cached_output = ();
my %outstanding_handlers = ();
my %running_handlers = ();
#-------------------------------------------------------------------------------
# Build the initial list of target handlers from the command line arguments.
sub build_initial_target_handlers()
{
for my $handler (@ARGV)
{
$target_handlers{$handler} = 1;
}
}
#-------------------------------------------------------------------------------
# Parse the debugging output and cache the handler tracking lines.
sub parse_debug_output()
{
while (my $line = <STDIN>)
{
chomp($line);
if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/)
{
push(@cached_output, $line);
}
}
}
#-------------------------------------------------------------------------------
# Iterate over the cached output in revese and build a hash of all target
# handlers' ancestors.
sub build_target_handler_tree()
{
my $i = scalar(@cached_output) - 1;
while ($i >= 0)
{
my $line = $cached_output[$i];
if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/)
{
my $action = $2;
# Handler creation.
if ($action =~ /^([0-9]+)\*([0-9]+)$/)
{
if ($1 ne "0" and exists($target_handlers{$2}))
{
$target_handlers{$1} = 1;
}
}
}
--$i;
}
}
#-------------------------------------------------------------------------------
# Print out all handler tracking records associated with the target handlers.
sub print_target_handler_records()
{
for my $line (@cached_output)
{
if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/)
{
my $action = $2;
# Handler location.
if ($action =~ /^([0-9]+)\^([0-9]+)$/)
{
print("$line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2});
}
# Handler creation.
if ($action =~ /^([0-9]+)\*([0-9]+)$/)
{
print("$1, $2, $line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2});
}
# Begin handler invocation.
elsif ($action =~ /^>([0-9]+)$/)
{
print("$line\n") if (exists($target_handlers{$1}));
}
# End handler invocation.
elsif ($action =~ /^<([0-9]+)$/)
{
print("$line\n") if (exists($target_handlers{$1}));
}
# Handler threw exception.
elsif ($action =~ /^!([0-9]+)$/)
{
print("$line\n") if (exists($target_handlers{$1}));
}
# Handler was destroyed without being invoked.
elsif ($action =~ /^~([0-9]+)$/)
{
print("$line\n") if (exists($target_handlers{$1}));
}
# Operation associated with a handler.
elsif ($action =~ /^\.([0-9]+)$/)
{
print("$line\n") if (exists($target_handlers{$1}));
}
}
}
}
#-------------------------------------------------------------------------------
build_initial_target_handlers();
parse_debug_output();
build_target_handler_tree();
print_target_handler_records();