package Devel::SawAmpersand;

use strict;
use vars qw($VERSION @ISA @EXPORT_OK);

use Exporter;
*import = \&Exporter::import;
require DynaLoader;
@ISA = qw(DynaLoader);
@EXPORT_OK = qw(sawampersand);
$VERSION = '0.33';

bootstrap Devel::SawAmpersand $VERSION;

1;

__END__

=head1 NAME

Devel::SawAmpersand - Perl extension querying PL_sawampersand variable

=head1 SYNOPSIS

  use Devel::SawAmpersand qw(sawampersand);

  sawampersand();

=head1 DESCRIPTION

This module provides one single function:

=over

=item $bool = Devel::SawAmpersand::sawampersand()

Returns a true value if the compiled code has the C-level global
variable PL_sawampersand set.

=back

There's a global variable in the perl source, called PL_sawampersand.
It gets set to true in that moment in which the parser sees one of $`,
$', and $&. It never can be set to false again. Trying to set it to
false breaks the handling of the $`, $&, and $' completely.

If the global variable C<PL_sawampersand> is set to true, all
subsequent RE operations will be accompanied by massive in-memory
copying, because there is nobody in the perl source who could predict,
B<when> the (necessary) copy for the ampersand family will be needed.
So B<all> subsequent REs are considerable slower than necessary.

There are at least three impacts for developers:

=over 4

=item *

never use $& and friends in a library. Use /p if you have perl 5.10 or later.

=item *

Don't "use English" in a library, because it contains the three bad
fellows. Corollary: if you really want to use English, do it like so:

    use English qw( -no_match_vars ) ;

=item *

before you release a module or program, check
if PL_sawampersand is set by any of the modules you use or require.

=back

=head2 Workarounds

Fortunately, perl offers easy to use alternatives. If you have perl 5.10
or later, you can use the /p match operator flag to turn on per-match
variables that do the same thing:

       instead of this              you can use this

     $`   of   /pattern/          ${^PREMATCH}  of  /pattern/p
     $&   of   /pattern/          ${^MATCH}     of  /pattern/p
     $'   of   /pattern/          ${^POSTMATCH} of  /pattern/p

If you are using an older perl, you can use these workarounds:

       instead of this              you can use this

     $`   of   /pattern/          $1   of  /(.*?)pattern/s
     $&   of   /pattern/          $1   of  /(pattern)/
     $'   of   /pattern/          $+   of  /pattern(.*)/s

In general, apply C</^(.*)(pattern)(.*)$/s> and use $1 for $`, $2 for
$& and $+ for $' ($+ is not dependent on the number of parens in the
original pattern). Note that the C</s> switch can alter the meaning of
C<.> in your pattern.


=head1 AUTHOR

Andreas Koenig, special thanks to Johan Vromans, John Macdonald, and
brian d foy for parts of the manpage and to Doug MacEachern for the
FindAmpersand.

=head1 LICENSE

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>

=head1 SEE ALSO

Devel::FindAmpersand, B::FindAmpersand

=cut