+# Avoid generating "subroutine redefined" warnings with the following
+# hack (from CGI::Carp):
+if (!defined $DB::VERSION) {
+ local $^W=0;
+ eval qq( sub confess {
+ \$SIG{__DIE__} = 'DEFAULT';
+ DXDebug::dbgprintring() if DXDebug::isdbg('nologchan');
+ DXDebug::dbg(\$@);
+# DXDebug::dbg(Carp::shortmess(\@_));
+ DXDebug::longmess(\@_);
+ exit(-1);
+ }
+ sub croak {
+ \$SIG{__DIE__} = 'DEFAULT';
+ DXDebug::dbgprintring() if DXDebug::isdbg('nologchan');
+ DXDebug::dbg(\$@);
+# DXDebug::dbg(Carp::longmess(\@_));
+ DXDebug::shortmess(\@_);
+ exit(-1);
+ }
+ sub carp {
+ DXDebug::dbgprintring(25) if DXDebug('nologchan');
+# DXDebug::dbg(Carp::shortmess(\@_));
+ DXDebug::longmess(\@_);
+ }
+ sub cluck {
+ DXDebug::dbgprintring(25) if DXDebug('nologchan');
+# DXDebug::dbg(Carp::longmess(\@_));
+ DXDebug::longmess(\@_);
+ } );
+
+ CORE::die(Carp::shortmess($@)) if $@;
+} else {
+ eval qq( sub confess { die Carp::longmess(\@_); };
+ sub croak { die Carp::shortmess(\@_); };
+ sub cluck { warn Carp::longmess(\@_); };
+ sub carp { warn Carp::shortmess(\@_); };
+ );
+}
+
+
+my $_isdbg = ''; # current dbg level we are processing
+
+# print stack trace
+sub dbgtrace
+{
+# say "*** in dbgtrace";
+ $_isdbg = 'trace';
+ dbg(@_);
+ for (my $i = 1; (my ($pkg, $fn, $l, $subr) = caller($i)); ++$i) {
+# say "*** in dbgtrace $i";
+ next if $pkg eq 'DXDebug';
+# say "*** in dbgtrace after package";
+ last if $pkg =~ /Mojo/;
+# say "*** in dbgtrace $i after mojo";
+ $_isdbg = 'trace';
+ dbg("Stack ($i): ${pkg}::$subr in $fn line: $l");
+ }
+ $_isdbg = '';
+}