The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

—
—
—
—
# -----------------------------------------------------------------------------
=encoding utf8
=head1 NAME
Quiq::Stacktrace - Generiere und visualisiere einen Stacktrace
=head1 SYNOPSIS
use Quiq::Stacktrace;
my $st = Quiq::Stacktrace->new; # generiere Stacktrace
print $st->asString,"\n"; # visualisiere Stacktrace
-or-
print Quiq::Stacktrace->asString,"\n"; # in einem Aufruf
=head1 DESCRIPTION
Ein Objekt der Klasse repräsentiert die Aufrufhierarchie des
laufenden Perl-Programms zum Zeitpunkt der Instantiierung des
Stacktrace-Objektes.
Die Klasse kann zum Debuggen verwendet werden oder bei der
Erzeugung von Exceptions.
Folgendes Beispielprogramm (test.pl)
#!/usr/bin/env perl
use Quiq::Stacktrace;
sub a {
b();
}
sub b {
c();
}
sub c {
print Quiq::Stacktrace->asString,"\n";
}
a();
erzeugt die Ausgabe
main::a() [+17 ./test.pl]
main::b() [+6 ./test.pl]
main::c() [+10 ./test.pl]
Quiq::Stacktrace::asString() [+14 ./test.pl]
Von oben nach unten gelesen gibt der Stacktrace die Hierarchie der
Subroutine-Aufrufe (= Methoden oder Funktionsaufrufe) in der
Aufrufreihenfolge wieder. Jede Zeile beschreibt einen Subroutine-Aufruf:
main::a() [+17 ./test.pl]
^ ^ ^ ^
| | | +-- Datei, in der der Aufruf steht
| | +-- Zeilennummer, an der der Aufruf in der Datei steht
| +-- Name der aufgerufenen Subroutine
+-- Package, zu dem die Subroutine gehört
Die in eckigen Klammern genannte Quelltextposition kann bei
Aufruf von vi(1), emacs(1) oder less(1) benutzt werden,
um unmittelbar auf die entsprechende Zeile zu positionieren:
$ less +17 ./test.pl
Der unterste Eintrag im Stacktrace ist der Aufruf des
Konstruktors L<new|"new() - Konstruktor">() oder der Methode L<asString|"asString() - Visualisiere Stacktrace-Objekt">(), wenn sie
als Klassenmethode gerufen wird. Sollen Stacktrace-Frames am
Ende weggelassen werden, kann dies durch Angabe des Parameters
$i erreicht werden.
=cut
# -----------------------------------------------------------------------------
use v5.10;
use strict;
our $VERSION = '1.225';
# -----------------------------------------------------------------------------
=head1 METHODS
=head2 Instantiierung
=head3 new() - Konstruktor
=head4 Synopsis
$st = $class->new;
$st = $class->new($i);
=head4 Arguments
=over 4
=item $i (Default: 0)
Anzahl der Stackframes vom Ende des Stacktrace, die nicht
berĂĽcksichtigt werden. Ist $i == 0 (was der Default ist), werden
alle Frames berĂĽcksichtigt.
=back
=head4 Description
Instantiiere ein Stacktrace-Objekt und liefere eine Referenz auf diese
Objekt zurück. Das Stacktrace-Objekt repräsentiert die Aufruf-Hierarchie
des laufenden Perl-Programms zum Zeitpunkt der Instantiierung. Letztes
Element in der Hierarchie ist der Konstruktor-Aufruf. Soll der
Stacktrace vorher enden, wird der Parameter $i gesetzt.
=cut
# -----------------------------------------------------------------------------
sub new {
my $class = shift;
my $i = shift || 0;
my @frames;
while (my (undef,$file,$line,$sub) = caller $i++) {
push @frames,[$file,$line,$sub];
}
return bless \@frames,$class;
}
# -----------------------------------------------------------------------------
=head2 Externe Repräsentation
=head3 asString() - Visualisiere Stacktrace-Objekt
=head4 Synopsis
$str = $st->asString;
$str = $class->asString($i);
=head4 Arguments
=over 4
=item $i (Default: 0)
Siehe L<new|"new() - Konstruktor">().
=back
=head4 Description
Visualisiere das Stacktrace-Objekt in Form einer Zeichenkette und liefere
diese zurĂĽck. Aufbau der Zeichenkette siehe Abschnitt DESCRIPTION.
=cut
# -----------------------------------------------------------------------------
sub asString {
my $self = ref $_[0]? $_[0]: $_[0]->new(($_[1] || 0)+1);
if (!ref $self) {
my $i = shift || 0;
$self = $self->new($i);
}
my $str = '';
my $i = 0;
for my $frame (reverse @$self) {
my ($file,$line,$sub) = @$frame;
$sub .= "()" if $sub ne '(eval)';
$str .= sprintf "%s%s [+%s %s]\n",(' 'x$i++),$sub,$line,$file;
}
chomp $str;
return $str;
}
# -----------------------------------------------------------------------------
=head1 VERSION
1.225
=head1 AUTHOR
Frank Seitz, L<http://fseitz.de/>
=head1 COPYRIGHT
Copyright (C) 2025 Frank Seitz
=head1 LICENSE
This code is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# -----------------------------------------------------------------------------
1;
# eof