Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

144
database/perl/vendor/lib/B/COW.pm vendored Normal file
View File

@@ -0,0 +1,144 @@
package B::COW;
use strict;
use warnings;
# ABSTRACT: B::COW additional B helpers to check COW status
use base 'Exporter';
our $VERSION = '0.004'; # VERSION: generated by DZP::OurPkgVersion
use XSLoader;
XSLoader::load(__PACKAGE__);
my @all_export = qw{ can_cow is_cow cowrefcnt cowrefcnt_max };
our @EXPORT_OK = (
@all_export,
);
our %EXPORT_TAGS = (
all => [@all_export],
);
1;
__END__
=pod
=encoding utf-8
=head1 NAME
B::COW - B::COW additional B helpers to check COW status
=head1 VERSION
version 0.004
=head1 SYNOPSIS
#!perl
use strict;
use warnings;
use Test::More; # just used for illustration purpose
use B::COW qw{:all};
if ( can_cow() ) { # $] >= 5.020
ok !is_cow(undef);
my $str = "abcdef";
ok is_cow($str);
is cowrefcnt($str), 1;
my @a;
push @a, $str for 1 .. 100;
ok is_cow($str);
ok is_cow( $a[0] );
ok is_cow( $a[99] );
is cowrefcnt($str), 101;
is cowrefcnt( $a[-1] ), 101;
delete $a[99];
is cowrefcnt($str), 100;
is cowrefcnt( $a[-1] ), 100;
{
my %h = ( 'a' .. 'd' );
foreach my $k ( sort keys %h ) {
ok is_cow($k);
is cowrefcnt($k), 0;
}
}
}
else {
my $str = "abcdef";
is is_cow($str), undef;
is cowrefcnt($str), undef;
is cowrefcnt_max(), undef;
}
done_testing;
=head1 DESCRIPTION
B::COW provides some naive additional B helpers to check the COW status of one SvPV.
=head2 COW or Copy On Write introduction
A COWed SvPV is sharing its string (the PV) with other SvPVs.
It's a (kind of) Read Only C string, that would be Copied On Write (COW).
More than one SV can share the same PV, but when one PV need to alter it,
it would perform a copy of it, decrease the COWREFCNT counter.
One SV can then drop the COW flag when it's the only one holding a pointer
to the PV.
The COWREFCNT is stored at the end of the PV, after the the "\0".
That value is limited to 255, when we reach 255, a new PV would be created,
=for markdown [![](https://github.com/atoomic/B-COW/workflows/linux/badge.svg)](https://github.com/atoomic/B-COW/actions) [![](https://github.com/atoomic/B-COW/workflows/macos/badge.svg)](https://github.com/atoomic/B-COW/actions) [![](https://github.com/atoomic/B-COW/workflows/windows/badge.svg)](https://github.com/atoomic/B-COW/actions)
=head1 FUNCTIONS
=head2 can_cow()
Return a boolean value. True if your Perl version support Copy On Write for SvPVs
=head2 is_cow( PV )
Return a boolean value. True if the SV is cowed SvPV. (check the SV FLAGS)
=head2 cowrefcnt( PV )
Return one integer representing the COW RefCount value.
If the string is not COW, then it will return undef.
=head2 cowrefcnt_max()
Will return the SV_COW_REFCNT_MAX of your Perl. (if COW is supported, this should
be 255 unless customized).
=head1 AUTHOR
Nicolas R. <atoomic@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2018 by Nicolas R.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,177 @@
package B::Hooks::EndOfScope; # git description: 0.23-2-ga391106
# ABSTRACT: Execute code after a scope finished compilation
# KEYWORDS: code hooks execution scope
use strict;
use warnings;
our $VERSION = '0.24';
use 5.006001;
BEGIN {
use Module::Implementation 0.05;
Module::Implementation::build_loader_sub(
implementations => [ 'XS', 'PP' ],
symbols => [ 'on_scope_end' ],
)->();
}
use Sub::Exporter::Progressive 0.001006 -setup => {
exports => [ 'on_scope_end' ],
groups => { default => ['on_scope_end'] },
};
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
B::Hooks::EndOfScope - Execute code after a scope finished compilation
=head1 VERSION
version 0.24
=head1 SYNOPSIS
on_scope_end { ... };
=head1 DESCRIPTION
This module allows you to execute code when perl finished compiling the
surrounding scope.
=head1 FUNCTIONS
=head2 on_scope_end
on_scope_end { ... };
on_scope_end $code;
Registers C<$code> to be executed after the surrounding scope has been
compiled.
This is exported by default. See L<Sub::Exporter> on how to customize it.
=head1 LIMITATIONS
=head2 Pure-perl mode caveat
This caveat applies to B<any> version of perl where L<Variable::Magic>
is unavailable or otherwise disabled.
While L<Variable::Magic> has access to some very dark sorcery to make it
possible to throw an exception from within a callback, the pure-perl
implementation does not have access to these hacks. Therefore, what
would have been a B<compile-time exception> is instead B<converted to a
warning>, and your execution will continue as if the exception never
happened.
To explicitly request an XS (or PP) implementation one has two choices. Either
to import from the desired implementation explicitly:
use B::Hooks::EndOfScope::XS
or
use B::Hooks::EndOfScope::PP
or by setting C<$ENV{B_HOOKS_ENDOFSCOPE_IMPLEMENTATION}> to either C<XS> or
C<PP>.
=head2 Perl 5.8.0 ~ 5.8.3
Due to a L<core interpreter bug
|https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797> present in
older perl versions, the implementation of B::Hooks::EndOfScope deliberately
leaks a single empty hash for every scope being cleaned. This is done to
avoid the memory corruption associated with the bug mentioned above.
In order to stabilize this workaround use of L<Variable::Magic> is disabled
on perls prior to version 5.8.4. On such systems loading/requesting
L<B::Hooks::EndOfScope::XS> explicitly will result in a compile-time
exception.
=head2 Perl versions 5.6.x
Versions of perl before 5.8.0 lack a feature allowing changing the visibility
of C<%^H> via setting bit 17 within C<$^H>. As such the only way to achieve
the effect necessary for this module to work, is to use the C<local> operator
explicitly on these platforms. This might lead to unexpected interference
with other scope-driven libraries relying on the same mechanism. On the flip
side there are no such known incompatibilities at the time this note was
written.
For further details on the unavailable behavior please refer to the test
file F<t/02-localise.t> included with the distribution.
=head1 SEE ALSO
L<Sub::Exporter>
L<Variable::Magic>
=head1 SUPPORT
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
(or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).
=head1 AUTHORS
=over 4
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Peter Rabbitson <ribasushi@leporine.io>
=back
=head1 CONTRIBUTORS
=for stopwords Karen Etheridge Tatsuhiko Miyagawa Christian Walde Tomas Doran Graham Knop Simon Wilper
=over 4
=item *
Karen Etheridge <ether@cpan.org>
=item *
Tatsuhiko Miyagawa <miyagawa@bulknews.net>
=item *
Christian Walde <walde.christian@googlemail.com>
=item *
Tomas Doran <bobtfish@bobtfish.net>
=item *
Graham Knop <haarg@haarg.org>
=item *
Simon Wilper <sxw@chronowerks.de>
=back
=head1 COPYRIGHT AND LICENCE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,110 @@
package B::Hooks::EndOfScope::PP;
# ABSTRACT: Execute code after a scope finished compilation - PP implementation
use warnings;
use strict;
our $VERSION = '0.24';
use constant _PERL_VERSION => "$]";
BEGIN {
if (_PERL_VERSION =~ /^5\.009/) {
# CBA to figure out where %^H got broken and which H::U::HH is sane enough
die "By design B::Hooks::EndOfScope does not operate in pure-perl mode on perl 5.9.X\n"
}
elsif (_PERL_VERSION < '5.010') {
require B::Hooks::EndOfScope::PP::HintHash;
*on_scope_end = \&B::Hooks::EndOfScope::PP::HintHash::on_scope_end;
}
else {
require B::Hooks::EndOfScope::PP::FieldHash;
*on_scope_end = \&B::Hooks::EndOfScope::PP::FieldHash::on_scope_end;
}
}
use Sub::Exporter::Progressive 0.001006 -setup => {
exports => ['on_scope_end'],
groups => { default => ['on_scope_end'] },
};
sub __invoke_callback {
local $@;
eval { $_[0]->(); 1 } or do {
my $err = $@;
require Carp;
Carp::cluck( (join ' ',
'A scope-end callback raised an exception, which can not be propagated when',
'B::Hooks::EndOfScope operates in pure-perl mode. Your program will CONTINUE',
'EXECUTION AS IF NOTHING HAPPENED AFTER THIS WARNING. Below is the complete',
'exception text, followed by a stack-trace of the callback execution:',
) . "\n\n$err\n\r" );
sleep 1 if -t *STDERR; # maybe a bad idea...?
};
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
B::Hooks::EndOfScope::PP - Execute code after a scope finished compilation - PP implementation
=head1 VERSION
version 0.24
=head1 DESCRIPTION
This is the pure-perl implementation of L<B::Hooks::EndOfScope> based only on
modules available as part of the perl core. Its leaner sibling
L<B::Hooks::EndOfScope::XS> will be automatically preferred if all
dependencies are available and C<$ENV{B_HOOKS_ENDOFSCOPE_IMPLEMENTATION}> is
not set to C<'PP'>.
=head1 FUNCTIONS
=head2 on_scope_end
on_scope_end { ... };
on_scope_end $code;
Registers C<$code> to be executed after the surrounding scope has been
compiled.
This is exported by default. See L<Sub::Exporter> on how to customize it.
=head1 SUPPORT
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
(or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).
=head1 AUTHORS
=over 4
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Peter Rabbitson <ribasushi@leporine.io>
=back
=head1 COPYRIGHT AND LICENCE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,45 @@
# Implementation of a pure-perl on_scope_end for perls > 5.10
# (relies on Hash::Util:FieldHash)
package # hide from pause
B::Hooks::EndOfScope::PP::FieldHash;
use strict;
use warnings;
our $VERSION = '0.24';
use Tie::Hash ();
use Hash::Util::FieldHash 'fieldhash';
# Here we rely on a combination of several behaviors:
#
# * %^H is deallocated on scope exit, so any references to it disappear
# * A lost weakref in a fieldhash causes the corresponding key to be deleted
# * Deletion of a key on a tied hash triggers DELETE
#
# Therefore the DELETE of a tied fieldhash containing a %^H reference will
# be the hook to fire all our callbacks.
fieldhash my %hh;
{
package # hide from pause too
B::Hooks::EndOfScope::PP::_TieHintHashFieldHash;
our @ISA = ( 'Tie::StdHash' ); # in Tie::Hash, in core
sub DELETE {
my $ret = shift->SUPER::DELETE(@_);
B::Hooks::EndOfScope::PP::__invoke_callback($_) for @$ret;
$ret;
}
}
sub on_scope_end (&) {
$^H |= 0x020000;
tie(%hh, 'B::Hooks::EndOfScope::PP::_TieHintHashFieldHash')
unless tied %hh;
push @{ $hh{\%^H} ||= [] }, $_[0];
}
1;

View File

@@ -0,0 +1,94 @@
# Implementation of a pure-perl on_scope_end for perls < 5.10
# (relies on lack of compile/runtime duality of %^H before 5.10
# which makes guard object operation possible)
package # hide from the pauses
B::Hooks::EndOfScope::PP::HintHash;
use strict;
use warnings;
our $VERSION = '0.24';
use Scalar::Util ();
use constant _NEEDS_MEMORY_CORRUPTION_FIXUP => (
"$]" >= 5.008
and
"$]" < 5.008004
) ? 1 : 0;
use constant _PERL_VERSION => "$]";
# This is the original implementation, which sadly is broken
# on perl 5.10+ within string evals
sub on_scope_end (&) {
# the scope-implicit %^H localization is a 5.8+ feature
$^H |= 0x020000
if _PERL_VERSION >= 5.008;
# the explicit localization of %^H works on anything < 5.10
# but we use it only on 5.6 where fiddling $^H has no effect
local %^H = %^H
if _PERL_VERSION < 5.008;
# Workaround for memory corruption during implicit $^H-induced
# localization of %^H on 5.8.0~5.8.3, see extended comment below
bless \%^H, 'B::Hooks::EndOfScope::PP::HintHash::__GraveyardTransport' if (
_NEEDS_MEMORY_CORRUPTION_FIXUP
and
ref \%^H eq 'HASH' # only bless if it is a "pure hash" to start with
);
# localised %^H behaves funny on 5.8 - a
# 'local %^H;'
# is in effect the same as
# 'local %^H = %^H;'
# therefore make sure we use different keys so that things do not
# fire too early due to hashkey overwrite
push @{
$^H{sprintf '__B_H_EOS__guardstack_0X%x', Scalar::Util::refaddr(\%^H) }
||= bless ([], 'B::Hooks::EndOfScope::PP::_SG_STACK')
}, $_[0];
}
sub B::Hooks::EndOfScope::PP::_SG_STACK::DESTROY {
B::Hooks::EndOfScope::PP::__invoke_callback($_) for @{$_[0]};
}
# This scope implements a clunky yet effective workaround for a core perl bug
# https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797
#
# While we can not prevent the hinthash being marked for destruction twice,
# we *can* intercept the first DESTROY pass, and squirrel away the entire
# structure, until a time it can (hopefully) no longer do any visible harm
#
# There still *will* be corruption by the time we get to free it for real,
# since we can not prevent Perl's erroneous SAVEFREESV mark. What we hope is
# that by then the corruption will no longer matter
#
# Yes, this code does leak by design. Yes it is better than the alternative.
{
my @Hint_Hash_Graveyard;
# "Leak" this entire structure: ensures it and its contents will not be
# garbage collected until the very very very end
push @Hint_Hash_Graveyard, \@Hint_Hash_Graveyard
if _NEEDS_MEMORY_CORRUPTION_FIXUP;
sub B::Hooks::EndOfScope::PP::HintHash::__GraveyardTransport::DESTROY {
# Resurrect the hinthash being destroyed, persist it into the graveyard
push @Hint_Hash_Graveyard, $_[0];
# ensure we won't try to re-resurrect during GlobalDestroy
bless $_[0], 'B::Hooks::EndOfScope::PP::HintHash::__DeactivateGraveyardTransport';
# Perform explicit free of elements (if any) triggering all callbacks
# This is what would have happened without this code being active
%{$_[0]} = ();
}
}
1;

View File

@@ -0,0 +1,108 @@
package B::Hooks::EndOfScope::XS;
# ABSTRACT: Execute code after a scope finished compilation - XS implementation
use strict;
use warnings;
our $VERSION = '0.24';
# Limit the V::M-based (XS) version to perl 5.8.4+
#
# Given the unorthodox stuff we do to work around the hinthash double-free
# might as well play it safe and only implement it in the PP version
# and leave it at that
# https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797
#
use 5.008004;
use Variable::Magic 0.48 ();
use Sub::Exporter::Progressive 0.001006 -setup => {
exports => ['on_scope_end'],
groups => { default => ['on_scope_end'] },
};
my $wiz = Variable::Magic::wizard
data => sub { [$_[1]] },
free => sub { $_->() for @{ $_[1] }; () },
# When someone localise %^H, our magic doesn't want to be copied
# down. We want it to be around only for the scope we've initially
# attached ourselves to. Merely having MGf_LOCAL and a noop svt_local
# callback achieves this. If anything wants to attach more magic of our
# kind to a localised %^H, things will continue to just work as we'll be
# attached with a new and empty callback list.
local => \undef
;
sub on_scope_end (&) {
$^H |= 0x020000;
if (my $stack = Variable::Magic::getdata %^H, $wiz) {
push @{ $stack }, $_[0];
}
else {
Variable::Magic::cast %^H, $wiz, $_[0];
}
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
B::Hooks::EndOfScope::XS - Execute code after a scope finished compilation - XS implementation
=head1 VERSION
version 0.24
=head1 DESCRIPTION
This is the implementation of L<B::Hooks::EndOfScope> based on
L<Variable::Magic>, which is an XS module dependent on a compiler. It will
always be automatically preferred if L<Variable::Magic> is available.
=head1 FUNCTIONS
=head2 on_scope_end
on_scope_end { ... };
on_scope_end $code;
Registers C<$code> to be executed after the surrounding scope has been
compiled.
This is exported by default. See L<Sub::Exporter> on how to customize it.
=head1 SUPPORT
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
(or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).
=head1 AUTHORS
=over 4
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Peter Rabbitson <ribasushi@leporine.io>
=back
=head1 COPYRIGHT AND LICENCE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,129 @@
use strict;
use warnings;
package B::Hooks::OP::Check; # git description: 0.21-5-g968d5ca
# ABSTRACT: Wrap OP check callbacks
require 5.008001;
use parent qw/DynaLoader/;
our $VERSION = '0.22';
sub dl_load_flags { 0x01 }
__PACKAGE__->bootstrap($VERSION);
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
B::Hooks::OP::Check - Wrap OP check callbacks
=head1 VERSION
version 0.22
=head1 SYNOPSIS
# include "hook_op_check.h"
STATIC OP *my_const_check_op (pTHX_ OP *op, void *user_data) {
/* ... */
return op;
}
STATIC hook_op_check_id my_hook_id = 0;
void
setup ()
CODE:
my_hook_id = hook_op_check (OP_CONST, my_const_check_op, NULL);
void
teardown ()
CODE:
hook_op_check_remove (OP_CONST, my_hook_id);
=head1 DESCRIPTION
This module provides a C API for XS modules to hook into the callbacks of
C<PL_check>.
L<ExtUtils::Depends> is used to export all functions for other XS modules to
use. Include the following in your Makefile.PL:
my $pkg = ExtUtils::Depends->new('Your::XSModule', 'B::Hooks::OP::Check');
WriteMakefile(
... # your normal makefile flags
$pkg->get_makefile_vars,
);
Your XS module can now include C<hook_op_check.h>.
=for stopwords cb
=head1 TYPES
=head2 typedef OP *(*hook_op_check_cb) (pTHX_ OP *, void *);
Type that callbacks need to implement.
=head2 typedef UV hook_op_check_id
Type to identify a callback.
=head1 FUNCTIONS
=head2 hook_op_check_id hook_op_check (opcode type, hook_op_check_cb cb, void *user_data)
Register the callback C<cb> to be called after the C<PL_check> function for
opcodes of the given C<type>. C<user_data> will be passed to the callback as
the last argument. Returns an id that can be used to remove the callback later
on.
=head2 void *hook_op_check_remove (opcode type, hook_op_check_id id)
Remove the callback identified by C<id>. Returns the user_data that the callback had.
=head1 SUPPORT
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-OP-Check>
(or L<bug-B-Hooks-OP-Check@rt.cpan.org|mailto:bug-B-Hooks-OP-Check@rt.cpan.org>).
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 CONTRIBUTORS
=for stopwords Karen Etheridge Zefram Alexandr Ciornii
=over 4
=item *
Karen Etheridge <ether@cpan.org>
=item *
Zefram <zefram@fysh.org>
=item *
Alexandr Ciornii <alexchorny@gmail.com>
=back
=head1 COPYRIGHT AND LICENCE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,35 @@
package B::Hooks::OP::Check::Install::Files;
$self = {
'deps' => [],
'inc' => '',
'libs' => '',
'typemaps' => []
};
@deps = @{ $self->{deps} };
@typemaps = @{ $self->{typemaps} };
$libs = $self->{libs};
$inc = $self->{inc};
$CORE = undef;
foreach (@INC) {
if ( -f $_ . "/B/Hooks/OP/Check/Install/Files.pm") {
$CORE = $_ . "/B/Hooks/OP/Check/Install/";
last;
}
}
sub deps { @{ $self->{deps} }; }
sub Inline {
my ($class, $lang) = @_;
if ($lang ne 'C') {
warn "Warning: Inline hints not available for $lang language
";
return;
}
+{ map { (uc($_) => $self->{$_}) } qw(inc libs typemaps) };
}
1;

View File

@@ -0,0 +1,16 @@
#ifndef __HOOK_OP_CHECK_H__
#define __HOOK_OP_CHECK_H__
#include "perl.h"
START_EXTERN_C
typedef UV hook_op_check_id;
typedef OP *(*hook_op_check_cb) (pTHX_ OP *, void *);
hook_op_check_id hook_op_check (opcode type, hook_op_check_cb cb, void *user_data);
void *hook_op_check_remove (opcode type, hook_op_check_id id);
END_EXTERN_C
#endif

796
database/perl/vendor/lib/B/Lint.pm vendored Normal file
View File

@@ -0,0 +1,796 @@
package B::Lint;
use if $] > 5.017, 'deprecate';
our $VERSION = '1.20'; ## no critic
=head1 NAME
B::Lint - Perl lint
=head1 SYNOPSIS
perl -MO=Lint[,OPTIONS] foo.pl
=head1 DESCRIPTION
The B::Lint module is equivalent to an extended version of the B<-w>
option of B<perl>. It is named after the program F<lint> which carries
out a similar process for C programs.
=head1 OPTIONS AND LINT CHECKS
Option words are separated by commas (not whitespace) and follow the
usual conventions of compiler backend options. Following any options
(indicated by a leading B<->) come lint check arguments. Each such
argument (apart from the special B<all> and B<none> options) is a
word representing one possible lint check (turning on that check) or
is B<no-foo> (turning off that check). Before processing the check
arguments, a standard list of checks is turned on. Later options
override earlier ones. Available options are:
=over 8
=item B<magic-diamond>
Produces a warning whenever the magic C<E<lt>E<gt>> readline is
used. Internally it uses perl's two-argument open which itself treats
filenames with special characters specially. This could allow
interestingly named files to have unexpected effects when reading.
% touch 'rm *|'
% perl -pe 1
The above creates a file named C<rm *|>. When perl opens it with
C<E<lt>E<gt>> it actually executes the shell program C<rm *>. This
makes C<E<lt>E<gt>> dangerous to use carelessly.
=item B<context>
Produces a warning whenever an array is used in an implicit scalar
context. For example, both of the lines
$foo = length(@bar);
$foo = @bar;
will elicit a warning. Using an explicit B<scalar()> silences the
warning. For example,
$foo = scalar(@bar);
=item B<implicit-read> and B<implicit-write>
These options produce a warning whenever an operation implicitly
reads or (respectively) writes to one of Perl's special variables.
For example, B<implicit-read> will warn about these:
/foo/;
and B<implicit-write> will warn about these:
s/foo/bar/;
Both B<implicit-read> and B<implicit-write> warn about this:
for (@a) { ... }
=item B<bare-subs>
This option warns whenever a bareword is implicitly quoted, but is also
the name of a subroutine in the current package. Typical mistakes that it will
trap are:
use constant foo => 'bar';
@a = ( foo => 1 );
$b{foo} = 2;
Neither of these will do what a naive user would expect.
=item B<dollar-underscore>
This option warns whenever C<$_> is used either explicitly anywhere or
as the implicit argument of a B<print> statement.
=item B<private-names>
This option warns on each use of any variable, subroutine or
method name that lives in a non-current package but begins with
an underscore ("_"). Warnings aren't issued for the special case
of the single character name "_" by itself (e.g. C<$_> and C<@_>).
=item B<undefined-subs>
This option warns whenever an undefined subroutine is invoked.
This option will only catch explicitly invoked subroutines such
as C<foo()> and not indirect invocations such as C<&$subref()>
or C<$obj-E<gt>meth()>. Note that some programs or modules delay
definition of subs until runtime by means of the AUTOLOAD
mechanism.
=item B<regexp-variables>
This option warns whenever one of the regexp variables C<$`>, C<$&> or C<$'>
is used. Any occurrence of any of these variables in your
program can slow your whole program down. See L<perlre> for
details.
=item B<all>
Turn all warnings on.
=item B<none>
Turn all warnings off.
=back
=head1 NON LINT-CHECK OPTIONS
=over 8
=item B<-u Package>
Normally, Lint only checks the main code of the program together
with all subs defined in package main. The B<-u> option lets you
include other package names whose subs are then checked by Lint.
=back
=head1 EXTENDING LINT
Lint can be extended by with plugins. Lint uses L<Module::Pluggable>
to find available plugins. Plugins are expected but not required to
inform Lint of which checks they are adding.
The C<< B::Lint->register_plugin( MyPlugin => \@new_checks ) >> method
adds the list of C<@new_checks> to the list of valid checks. If your
module wasn't loaded by L<Module::Pluggable> then your class name is
added to the list of plugins.
You must create a C<match( \%checks )> method in your plugin class or one
of its parents. It will be called on every op as a regular method call
with a hash ref of checks as its parameter.
The class methods C<< B::Lint->file >> and C<< B::Lint->line >> contain
the current filename and line number.
package Sample;
use B::Lint;
B::Lint->register_plugin( Sample => [ 'good_taste' ] );
sub match {
my ( $op, $checks_href ) = shift @_;
if ( $checks_href->{good_taste} ) {
...
}
}
=head1 TODO
=over
=item while(<FH>) stomps $_
=item strict oo
=item unchecked system calls
=item more tests, validate against older perls
=back
=head1 BUGS
This is only a very preliminary version.
=head1 AUTHOR
Malcolm Beattie, mbeattie@sable.ox.ac.uk.
=head1 ACKNOWLEDGEMENTS
Sebastien Aperghis-Tramoni - bug fixes
=cut
use strict;
use B qw( walkoptree_slow
main_root main_cv walksymtable parents
OPpOUR_INTRO
OPf_WANT_VOID OPf_WANT_LIST OPf_WANT OPf_STACKED SVf_POK SVf_ROK );
use Carp 'carp';
# The current M::P doesn't know about .pmc files.
use Module::Pluggable ( require => 1 );
use List::Util 'first';
## no critic Prototypes
sub any (&@) { my $test = shift @_; $test->() and return 1 for @_; return 0 }
BEGIN {
# Import or create some constants from B. B doesn't provide
# everything I need so some things like OPpCONST_BARE are defined
# here.
for my $sym ( qw( begin_av check_av init_av end_av ),
[ 'OPpCONST_BARE' => 64 ] )
{
my $val;
( $sym, $val ) = @$sym if ref $sym;
if ( any { $sym eq $_ } @B::EXPORT_OK, @B::EXPORT ) {
B->import($sym);
}
else {
require constant;
constant->import( $sym => $val );
}
}
}
my $file = "unknown"; # shadows current filename
my $line = 0; # shadows current line number
my $curstash = "main"; # shadows current stash
my $curcv; # shadows current B::CV for pad lookups
sub file {$file}
sub line {$line}
sub curstash {$curstash}
sub curcv {$curcv}
# Lint checks
my %check;
my %implies_ok_context;
map( $implies_ok_context{$_}++,
qw(scalar av2arylen aelem aslice helem hslice
keys values hslice defined undef delete) );
# Lint checks turned on by default
my @default_checks
= qw(context magic_diamond undefined_subs regexp_variables);
my %valid_check;
# All valid checks
for my $check (
qw(context implicit_read implicit_write dollar_underscore
private_names bare_subs undefined_subs regexp_variables
magic_diamond )
)
{
$valid_check{$check} = __PACKAGE__;
}
# Debugging options
my ($debug_op);
my %done_cv; # used to mark which subs have already been linted
my @extra_packages; # Lint checks mainline code and all subs which are
# in main:: or in one of these packages.
sub warning {
my $format = ( @_ < 2 ) ? "%s" : shift @_;
warn sprintf( "$format at %s line %d\n", @_, $file, $line );
return undef; ## no critic undef
}
# This gimme can't cope with context that's only determined
# at runtime via dowantarray().
sub gimme {
my $op = shift @_;
my $flags = $op->flags;
if ( $flags & OPf_WANT ) {
return ( ( $flags & OPf_WANT ) == OPf_WANT_LIST ? 1 : 0 );
}
return undef; ## no critic undef
}
my @plugins = __PACKAGE__->plugins;
sub inside_grepmap {
# A boolean function to be used while inside a B::walkoptree_slow
# call. If we are in the EXPR part of C<grep EXPR, ...> or C<grep
# { EXPR } ...>, this returns true.
return any { $_->name =~ m/\A(?:grep|map)/xms } @{ parents() };
}
sub inside_foreach_modifier {
# TODO: use any()
# A boolean function to be used while inside a B::walkoptree_slow
# call. If we are in the EXPR part of C<EXPR foreach ...> this
# returns true.
for my $ancestor ( @{ parents() } ) {
next unless $ancestor->name eq 'leaveloop';
my $first = $ancestor->first;
next unless $first->name eq 'enteriter';
next if $first->redoop->name =~ m/\A(?:next|db|set)state\z/xms;
return 1;
}
return 0;
}
for (
[qw[ B::PADOP::gv_harder gv padix]],
[qw[ B::SVOP::sv_harder sv targ]],
[qw[ B::METHOP::sv_harder meth_sv targ]],
[qw[ B::SVOP::gv_harder gv padix]]
)
{
# I'm generating some functions here because they're mostly
# similar. It's all for compatibility with threaded
# perl. Perhaps... this code should inspect $Config{usethreads}
# and generate a *specific* function. I'm leaving it generic for
# the moment.
#
# In threaded perl SVs and GVs aren't used directly in the optrees
# like they are in non-threaded perls. The ops that would use a SV
# or GV keep an index into the subroutine's scratchpad. I'm
# currently ignoring $cv->DEPTH and that might be at my peril.
my ( $subname, $attr, $pad_attr ) = @$_;
my $target = do { ## no critic strict
no strict 'refs';
\*$subname;
};
*$target = sub {
my ($op) = @_;
my $elt;
if ( not $op->isa('B::PADOP') ) {
$elt = $op->$attr;
}
return $elt if eval { $elt->isa('B::SV') };
my $ix = $op->$pad_attr;
my @entire_pad = $curcv->PADLIST->ARRAY;
my @elts = map +( $_->ARRAY )[$ix], @entire_pad;
($elt) = first {
eval { $_->isa('B::SV') } ? $_ : ();
}
@elts[ 0, reverse 1 .. $#elts ];
return $elt;
};
}
sub B::OP::lint {
my ($op) = @_;
# This is a fallback ->lint for all the ops where I haven't
# defined something more specific. Nothing happens here.
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
sub B::COP::lint {
my ($op) = @_;
# nextstate ops sit between statements. Whenever I see one I
# update the current info on file, line, and stash. This code also
# updates it when it sees a dbstate or setstate op. I have no idea
# what those are but having seen them mentioned together in other
# parts of the perl I think they're kind of equivalent.
if ( $op->name =~ m/\A(?:next|db|set)state\z/ ) {
$file = $op->file;
$line = $op->line;
$curstash = $op->stash->NAME;
}
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
sub B::UNOP::lint {
my ($op) = @_;
my $opname = $op->name;
CONTEXT: {
# Check arrays and hashes in scalar or void context where
# scalar() hasn't been used.
next
unless $check{context}
and $opname =~ m/\Arv2[ah]v\z/xms
and not gimme($op);
my ( $parent, $gparent ) = @{ parents() }[ 0, 1 ];
my $pname = $parent->name;
next if $implies_ok_context{$pname};
# Three special cases to deal with: "foreach (@foo)", "delete
# $a{$b}", and "exists $a{$b}" null out the parent so we have to
# check for a parent of pp_null and a grandparent of
# pp_enteriter, pp_delete, pp_exists
next
if $pname eq "null"
and $gparent->name =~ m/\A(?:delete|enteriter|exists)\z/xms;
# our( @bar ); would also trigger this error so I exclude
# that.
next
if $op->private & OPpOUR_INTRO
and ( $op->flags & OPf_WANT ) == OPf_WANT_VOID;
warning 'Implicit scalar context for %s in %s',
$opname eq "rv2av" ? "array" : "hash", $parent->desc;
}
PRIVATE_NAMES: {
# Looks for calls to methods with names that begin with _ and
# that aren't visible within the current package. Maybe this
# should look at @ISA.
next
unless $check{private_names}
and $opname =~ m/\Amethod/xms;
my $methop = $op->first;
next unless $methop->name eq "const";
my $method = $methop->sv_harder->PV;
next
unless $method =~ m/\A_/xms
and not defined &{"$curstash\::$method"};
warning q[Illegal reference to private method name '%s'], $method;
}
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
sub B::PMOP::lint {
my ($op) = @_;
IMPLICIT_READ: {
# Look for /.../ that doesn't use =~ to bind to something.
next
unless $check{implicit_read}
and $op->name eq "match"
and not( $op->flags & OPf_STACKED
or inside_grepmap() );
warning 'Implicit match on $_';
}
IMPLICIT_WRITE: {
# Look for s/.../.../ that doesn't use =~ to bind to
# something.
next
unless $check{implicit_write}
and $op->name eq "subst"
and not $op->flags & OPf_STACKED;
warning 'Implicit substitution on $_';
}
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
sub B::LOOP::lint {
my ($op) = @_;
IMPLICIT_FOO: {
# Look for C<for ( ... )>.
next
unless ( $check{implicit_read} or $check{implicit_write} )
and $op->name eq "enteriter";
my $last = $op->last;
next
unless $last->name eq "gv"
and $last->gv_harder->NAME eq "_"
and $op->redoop->name =~ m/\A(?:next|db|set)state\z/xms;
warning 'Implicit use of $_ in foreach';
}
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
# In threaded vs non-threaded perls you'll find that threaded perls
# use PADOP in place of SVOPs so they can do lookups into the
# scratchpad to find things. I suppose this is so a optree can be
# shared between threads and all symbol table muckery will just get
# written to a scratchpad.
*B::METHOP::lint = *B::PADOP::lint = *B::PADOP::lint = \&B::SVOP::lint;
sub B::SVOP::lint {
my ($op) = @_;
MAGIC_DIAMOND: {
next
unless $check{magic_diamond}
and parents()->[0]->name eq 'readline'
and $op->gv_harder->NAME eq 'ARGV';
warning 'Use of <>';
}
BARE_SUBS: {
next
unless $check{bare_subs}
and $op->name eq 'const'
and $op->private & OPpCONST_BARE;
my $sv = $op->sv_harder;
next unless $sv->FLAGS & SVf_POK;
my $sub = $sv->PV;
my $subname = "$curstash\::$sub";
# I want to skip over things that were declared with the
# constant pragma. Well... sometimes. Hmm. I want to ignore
# C<<use constant FOO => ...>> but warn on C<<FOO => ...>>
# later. The former is typical declaration syntax and the
# latter would be an error.
#
# Skipping over both could be handled by looking if
# $constant::declared{$subname} is true.
# Check that it's a function.
next
unless exists &{"$curstash\::$sub"};
warning q[Bare sub name '%s' interpreted as string], $sub;
}
PRIVATE_NAMES: {
next unless $check{private_names};
my $opname = $op->name;
if ( $opname =~ m/\Agv(?:sv)?\z/xms ) {
# Looks for uses of variables and stuff that are named
# private and we're not in the same package.
my $gv = $op->gv_harder;
my $name = $gv->NAME;
next
unless $name =~ m/\A_./xms
and $gv->STASH->NAME ne $curstash;
warning q[Illegal reference to private name '%s'], $name;
}
elsif ( $opname eq "method_named" ) {
my $method = $op->sv_harder->PV;
next unless $method =~ m/\A_./xms;
warning q[Illegal reference to private method name '%s'], $method;
}
}
DOLLAR_UNDERSCORE: {
# Warn on uses of $_ with a few exceptions. I'm not warning on
# $_ inside grep, map, or statement modifier foreach because
# they localize $_ and it'd be impossible to use these
# features without getting warnings.
next
unless $check{dollar_underscore}
and $op->name eq "gvsv"
and $op->gv_harder->NAME eq "_"
and not( inside_grepmap
or inside_foreach_modifier );
warning 'Use of $_';
}
REGEXP_VARIABLES: {
# Look for any uses of $`, $&, or $'.
next
unless $check{regexp_variables}
and $op->name eq "gvsv";
my $name = $op->gv_harder->NAME;
next unless $name =~ m/\A[\&\'\`]\z/xms;
warning 'Use of regexp variable $%s', $name;
}
UNDEFINED_SUBS: {
# Look for calls to functions that either don't exist or don't
# have a definition.
next
unless $check{undefined_subs}
and $op->name eq "gv"
and $op->next->name eq "entersub";
my $gv = $op->gv_harder;
my $cv = $gv->FLAGS & SVf_ROK ? $gv->RV : undef;
my $subname = ($cv || $gv)->STASH->NAME . "::"
. ($cv ? $cv->NAME_HEK || $cv->GV->NAME : $gv->NAME);
no strict 'refs'; ## no critic strict
if ( not exists &$subname ) {
$subname =~ s/\Amain:://;
warning q[Nonexistent subroutine '%s' called], $subname;
}
elsif ( not defined &$subname ) {
$subname =~ s/\A\&?main:://;
warning q[Undefined subroutine '%s' called], $subname;
}
}
# Call all registered plugins
my $m;
$m = $_->can('match'), $op->$m( \%check ) for @plugins;
return;
}
sub B::GV::lintcv {
# Example: B::svref_2object( \ *A::Glob )->lintcv
my $gv = shift @_;
my $cv = $gv->CV;
return unless $cv->can('lintcv');
$cv->lintcv;
return;
}
sub B::CV::lintcv {
# Example: B::svref_2object( \ &foo )->lintcv
# Write to the *global* $
$curcv = shift @_;
#warn sprintf("lintcv: %s::%s (done=%d)\n",
# $gv->STASH->NAME, $gv->NAME, $done_cv{$$curcv});#debug
return unless ref($curcv) and $$curcv and not $done_cv{$$curcv}++;
my $root = $curcv->ROOT;
#warn " root = $root (0x$$root)\n";#debug
walkoptree_slow( $root, "lint" ) if $$root;
return;
}
sub do_lint {
my %search_pack;
# Copy to the global $curcv for use in pad lookups.
$curcv = main_cv;
walkoptree_slow( main_root, "lint" ) if ${ main_root() };
# Do all the miscellaneous non-sub blocks.
for my $av ( begin_av, init_av, check_av, end_av ) {
next unless eval { $av->isa('B::AV') };
for my $cv ( $av->ARRAY ) {
next unless ref($cv) and $cv->FILE eq $0;
$cv->lintcv;
}
}
walksymtable(
\%main::,
sub {
if ( $_[0]->FILE eq $0 ) { $_[0]->lintcv }
},
sub {1}
);
return;
}
sub compile {
my @options = @_;
# Turn on default lint checks
for my $opt (@default_checks) {
$check{$opt} = 1;
}
OPTION:
while ( my $option = shift @options ) {
my ( $opt, $arg );
unless ( ( $opt, $arg ) = $option =~ m/\A-(.)(.*)/xms ) {
unshift @options, $option;
last OPTION;
}
if ( $opt eq "-" && $arg eq "-" ) {
shift @options;
last OPTION;
}
elsif ( $opt eq "D" ) {
$arg ||= shift @options;
foreach my $arg ( split //, $arg ) {
if ( $arg eq "o" ) {
B->debug(1);
}
elsif ( $arg eq "O" ) {
$debug_op = 1;
}
}
}
elsif ( $opt eq "u" ) {
$arg ||= shift @options;
push @extra_packages, $arg;
}
}
foreach my $opt ( @default_checks, @options ) {
$opt =~ tr/-/_/;
if ( $opt eq "all" ) {
%check = %valid_check;
}
elsif ( $opt eq "none" ) {
%check = ();
}
else {
if ( $opt =~ s/\Ano_//xms ) {
$check{$opt} = 0;
}
else {
$check{$opt} = 1;
}
carp "No such check: $opt"
unless defined $valid_check{$opt};
}
}
# Remaining arguments are things to check. So why aren't I
# capturing them or something? I don't know.
return \&do_lint;
}
sub register_plugin {
my ( undef, $plugin, $new_checks ) = @_;
# Allow the user to be lazy and not give us a name.
$plugin = caller unless defined $plugin;
# Register the plugin's named checks, if any.
for my $check ( eval {@$new_checks} ) {
if ( not defined $check ) {
carp 'Undefined value in checks.';
next;
}
if ( exists $valid_check{$check} ) {
carp
"$check is already registered as a $valid_check{$check} feature.";
next;
}
$valid_check{$check} = $plugin;
}
# Register a non-Module::Pluggable loaded module. @plugins already
# contains whatever M::P found on disk. The user might load a
# plugin manually from some arbitrary namespace and ask for it to
# be registered.
if ( not any { $_ eq $plugin } @plugins ) {
push @plugins, $plugin;
}
return;
}
1;

View File

@@ -0,0 +1,73 @@
package B::Lint::Debug;
use if $] > 5.017, 'deprecate';
our $VERSION = '1.20';
=head1 NAME
B::Lint::Debug - Adds debugging stringification to B::
=head1 DESCRIPTION
This module injects stringification to a B::OP*/B::SPECIAL. This
should not be loaded unless you're debugging.
=cut
package # hide from PAUSE
B::SPECIAL;
use overload '""' => sub {
my $self = shift @_;
"SPECIAL($$self)";
};
package # hide from PAUSE
B::OP;
use overload '""' => sub {
my $self = shift @_;
my $class = ref $self;
$class =~ s/\AB:://xms;
my $name = $self->name;
"$class($name)";
};
package # hide from PAUSE
B::SVOP;
use overload '""' => sub {
my $self = shift @_;
my $class = ref $self;
$class =~ s/\AB:://xms;
my $name = $self->name;
"$class($name," . $self->sv . "," . $self->gv . ")";
};
package # hide from PAUSE
B::SPECIAL;
sub DESTROY { }
our $AUTOLOAD;
sub AUTOLOAD {
my $cx = 0;
print "AUTOLOAD $AUTOLOAD\n";
package # hide from PAUSE
DB;
while ( my @stuff = caller $cx ) {
print "$cx: [@DB::args] [@stuff]\n";
if ( ref $DB::args[0] ) {
if ( $DB::args[0]->can('padix') ) {
print " PADIX: " . $DB::args[0]->padix . "\n";
}
if ( $DB::args[0]->can('targ') ) {
print " TARG: " . $DB::args[0]->targ . "\n";
for ( B::Lint::cv()->PADLIST->ARRAY ) {
print +( $_->ARRAY )[ $DB::args[0]->targ ] . "\n";
}
}
}
++$cx;
}
}
1;

1177
database/perl/vendor/lib/B/Utils.pm vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
#ifndef _BUTILS_H_
#define _BUTILS_H_
typedef OP *B__OP;
typedef UNOP *B__UNOP;
typedef BINOP *B__BINOP;
typedef LOGOP *B__LOGOP;
typedef LISTOP *B__LISTOP;
typedef PMOP *B__PMOP;
typedef SVOP *B__SVOP;
typedef PADOP *B__PADOP;
typedef PVOP *B__PVOP;
typedef LOOP *B__LOOP;
typedef COP *B__COP;
typedef SV *B__SV;
typedef SV *B__IV;
typedef SV *B__PV;
typedef SV *B__NV;
typedef SV *B__PVMG;
typedef SV *B__PVLV;
typedef SV *B__BM;
typedef SV *B__RV;
typedef SV *B__FM;
typedef AV *B__AV;
typedef HV *B__HV;
typedef CV *B__CV;
typedef GV *B__GV;
typedef IO *B__IO;
extern char *BUtils_cc_opclassname(pTHX_ const OP *o);
extern SV *BUtils_make_sv_object(pTHX_ SV *arg, SV *sv);
extern I32 BUtils_op_name_to_num(SV * name);
#endif

View File

@@ -0,0 +1,37 @@
package B::Utils::Install::Files;
$self = {
'deps' => [],
'inc' => '',
'libs' => '',
'typemaps' => [
'typemap'
]
};
@deps = @{ $self->{deps} };
@typemaps = @{ $self->{typemaps} };
$libs = $self->{libs};
$inc = $self->{inc};
$CORE = undef;
foreach (@INC) {
if ( -f $_ . "/B/Utils/Install/Files.pm") {
$CORE = $_ . "/B/Utils/Install/";
last;
}
}
sub deps { @{ $self->{deps} }; }
sub Inline {
my ($class, $lang) = @_;
if ($lang ne 'C') {
warn "Warning: Inline hints not available for $lang language
";
return;
}
+{ map { (uc($_) => $self->{$_}) } qw(inc libs typemaps) };
}
1;

View File

@@ -0,0 +1,96 @@
TYPEMAP
OP * T_OP_OBJ
B::OP T_OP_OBJ
B::UNOP T_OP_OBJ
B::BINOP T_OP_OBJ
B::LOGOP T_OP_OBJ
B::LISTOP T_OP_OBJ
B::PMOP T_OP_OBJ
B::SVOP T_OP_OBJ
B::PADOP T_OP_OBJ
B::PVOP T_OP_OBJ
B::LOOP T_OP_OBJ
B::COP T_OP_OBJ
B::SV T_SV_OBJ
B::PV T_SV_OBJ
B::IV T_SV_OBJ
B::NV T_SV_OBJ
B::PVMG T_SV_OBJ
B::REGEXP T_SV_OBJ
B::PVLV T_SV_OBJ
B::BM T_SV_OBJ
B::RV T_SV_OBJ
B::GV T_SV_OBJ
B::CV T_SV_OBJ
B::HV T_SV_OBJ
B::AV T_SV_OBJ
B::IO T_SV_OBJ
B::FM T_SV_OBJ
B::MAGIC T_MG_OBJ
SSize_t T_IV
STRLEN T_UV
PADOFFSET T_UV
B::HE T_HE_OBJ
B::RHE T_RHE_OBJ
INPUT
T_OP_OBJ
if (SvROK($arg)) {
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}
else
croak(\"$var is not a reference\")
T_SV_OBJ
if (SvROK($arg)) {
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}
else
croak(\"$var is not a reference\")
T_MG_OBJ
if (SvROK($arg)) {
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}
else
croak(\"$var is not a reference\")
T_HE_OBJ
if (SvROK($arg)) {
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}
else
croak(\"$var is not a reference\")
T_RHE_OBJ
if (SvROK($arg)) {
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}
else
croak(\"$var is not a reference\")
OUTPUT
T_OP_OBJ
sv_setiv(newSVrv($arg, BUtils_cc_opclassname(aTHX_ (OP*)$var)), PTR2IV($var));
T_SV_OBJ
BUtils_make_sv_object(aTHX_ ($arg), (SV*)($var));
T_MG_OBJ
sv_setiv(newSVrv($arg, "B::MAGIC"), PTR2IV($var));
T_HE_OBJ
sv_setiv(newSVrv($arg, "B::HE"), PTR2IV($var));
T_RHE_OBJ
sv_setiv(newSVrv($arg, "B::RHE"), PTR2IV($var));

115
database/perl/vendor/lib/B/Utils/OP.pm vendored Normal file
View File

@@ -0,0 +1,115 @@
package B::Utils::OP;
require 5.006;
use Carp 'croak';
use strict;
use warnings;
use B::Utils ();
our @ISA = 'Exporter';
require Exporter;
our $VERSION = '0.27';
our @EXPORT = qw(parent_op return_op);
push @ISA, 'DynaLoader';
# the boot symbol is in B::Utils. bootstrap doesn't like it, so we
# need to load it manually.
my $bootname = 'boot_B__Utils__OP';
if (my $boot_symbol_ref = DynaLoader::dl_find_symbol_anywhere($bootname)) {
DynaLoader::dl_install_xsub(__PACKAGE__."::bootstrap", $boot_symbol_ref, __FILE__)->(__PACKAGE__, $VERSION);
}
=head1 NAME
B::Utils::OP - op related utility functions for perl
=head1 VERSION
version 0.27
=head1 SYNOPSIS
use B::Utils::OP qw(parent_op return_op);
sub foo {
my $pop = parent_op(0);
my $rop = return_op(0);
}
=head1 DESCRIPTION
sub foo {
dothis(1);
find_things();
return;
}
has the following optree:
d <1> leavesub[1 ref] K/REFC,1 ->(end)
- <@> lineseq KP ->d
1 <;> nextstate(main -371 bah.pl:8) v/2 ->2
5 <1> entersub[t2] vKS/TARG,3 ->6
- <1> ex-list K ->5
2 <0> pushmark s ->3
3 <$> const[IV 1] sM ->4
- <1> ex-rv2cv sK/3 ->-
4 <#> gv[*dothis] s ->5
6 <;> nextstate(main -371 bah.pl:9) v/2 ->7
9 <1> entersub[t4] vKS/TARG,3 ->a
- <1> ex-list K ->9
7 <0> pushmark s ->8
- <1> ex-rv2cv sK/3 ->-
8 <#> gv[*find_things] s/EARLYCV ->9
a <;> nextstate(main -371 bah.pl:10) v/2 ->b
c <@> return K ->d
b <0> pushmark s ->c
The C<find_things> in C<foo> is called in the C<entersub> in #9. If
you call C<parent_op> function with level 0, you get the C<nextstate>
op that is before the entersub, which is #6. And C<return_op> gives
you the next op that the caller is returning to, in this case, the
C<nextstate> in #a.
=head2 EXPORTED PERL FUNCTIONS
=over
=item parent_op($lv)
In runtime, returns the L<B::OP> object whose next is the C<entersub> of the current context up level C<$lv>
=item return_op($lv)
In runtime, returns the L<B::OP> object that the current context is returning to at level C<$lv>
=back
=head2 B::CV METHODS
=over
=item $cv->NEW_with_start($root, $start)
Clone the C<$cv> but with different C<$root> and C<$start>
=back
=head1 AUTHORS
Chia-liang Kao E<lt>clkao@clkao.orgE<gt>
=head1 COPYRIGHT
Copyright 2008 by Chia-liang Kao
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See L<http://www.perl.com/perl/misc/Artistic.html>
=cut
1;