NAME
    Devel::Hook - Mess around with BEGIN/CHECK/INIT/END blocks

SYNOPSIS
      use Devel::Hook ();

      INIT {
        print "INIT #2\n";
      }

      BEGIN {
        Devel::Hook->push_INIT_hook( sub { print "INIT #3 (hook)\n" } );
        Devel::Hook->unshift_INIT_hook( sub { print "INIT #1 (hook)\n" } );
      }

      print "RUNTIME\n";

    Output will be:

      INIT #1 (hook)
      INIT #2
      INIT #3 (hook)
      RUNTIME

DESCRIPTION
    Perl keeps arrays of subroutines that are executed at the beginning and
    at the end of a running Perl program and its program units. These
    subroutines correspond to the special code blocks: `BEGIN', `UNITCHECK',
    `CHECK', `INIT' and `END'. (See details at perlmod.) This module
    provides limited capabilities to manipulate these arrays.

    Such arrays belong to Perl's internals that you're not supposed to see.
    Entries in these arrays get consumed by the interpreter as it enters
    distinct compilation phases, triggered by statements like `require',
    `use', `do', `eval', etc. To play as safest as possible, the only
    allowed operations are to add entries to the start and to the end of
    these arrays.

      # add code hooks to the start of <BLOCK> array
      Devel::Hook->unshift_<BLOCK>_hook( @blocks );

      # add code hooks to the end of <BLOCK> array
      Devel::Hook->push_<BLOCK>_hook( @blocks );

    where <BLOCK> is one of: `BEGIN', `UNITCHECK', `CHECK', `INIT' or `END'.

    The hooks execute first if they are at the start of the array and last
    if they are at the end. Notice that the FIFO or LIFO nature of blocks
    according to their textual order of appearance at Perl source does not
    matter here. For example, BEGIN and INIT are FIFO (first-in, first-out)
    blocks while CHECK, UNITCHECK and END are LIFO (last-in, first-out). But
    the Perl interpreter and the user of this module inserts blocks at the
    start of arrays if they should execute earlier and at the end if they
    are to be executed later, with a homogeneous treatment with respect to
    the block arrays.

    If you are curious about the content of these arrays, read more at
    Manip::END and proceed to the innards of Perl.

  WHAT IS IT GOOD FOR
    If you want to inject code into Perl compilation phases or at the end of
    the program, this module may be useful.

    If it can be done with literal `BEGIN/UNITCHECK/CHECK/INIT/END' blocks,
    it should be. For weirder things, maybe `Devel::Hook' can solve it.

    As an example of application, Devel::Sub::Trace uses this module to
    insert a `INIT' hook which will run just before any other runtime code
    in the caller's package, wrapping subs after they were
    compiled/generated but before they get called by runtime code.

  HOW TO USE IT
      (not yet finished)

    With care. We are in the terrain of Perl internals we are not supposed
    to mess with. And furthermore, if you don't understand the implications
    of what you are doing with this module, it is likely not to do what you
    want.

      (to be finished)

METHODS
    * unshift_BEGIN_hook
    * push_BEGIN_hook
          Devel::Hook->unshift_BEGIN_hook( @blocks );
          Devel::Hook->push_BEGIN_hook( @blocks );

        This will add the blocks to the start (`unshift_BEGIN_hook') and to
        the end (`push_BEGIN_hook') of the array of BEGIN hooks.

        `@blocks' is an array of subroutine references.

    * unshift_UNITCHECK_hook
    * push_UNITCHECK_hook
          Devel::Hook->unshift_UNITCHECK_hook( @blocks );
          Devel::Hook->push_UNITCHECK_hook( @blocks );

        This will add the blocks to the start (`unshift_UNITCHECK_hook') and
        to the end (`push_UNITCHECK_hook') of the array of UNITCHECK hooks.

        `@blocks' is an array of subroutine references.

        The first stable release with `UNITCHECK' was 5.10.0. For earlier
        releases, these methods die.

    * unshift_CHECK_hook
    * push_CHECK_hook
          Devel::Hook->unshift_CHECK_hook( @blocks );
          Devel::Hook->push_CHECK_hook( @blocks );

        This will add the blocks to the start (`unshift_CHECK_hook') and to
        the end (`push_CHECK_hook') of the array of CHECK hooks.

        `@blocks' is an array of subroutine references.

    * unshift_INIT_hook
    * push_INIT_hook
          Devel::Hook->unshift_INIT_hook( @blocks );
          Devel::Hook->push_INIT_hook( @blocks );

        This will add the blocks to the start (`unshift_INIT_hook') and to
        the end (`push_INIT_hook') of the array of INIT hooks.

        `@blocks' is an array of subroutine references.

    * unshift_END_hook
    * push_END_hook
          Devel::Hook->unshift_END_hook( @blocks );
          Devel::Hook->push_END_hook( @blocks );

        This will add the blocks to the start (`unshift_END_hook') and to
        the end (`push_END_hook') of the array of END hooks.

        For END hooks, by adding to the start of the array (unshift), they
        will be the first code blocks executed by Perl when it is exiting.

        For END hooks, by adding to the end of the array (push), they will
        be the last code blocks executed by Perl when it is exiting.

        `@blocks' is an array of subroutine references.

SEE ALSO
    perlmod

    Manip::END

    B::CompilerPhase::Hook

BUGS
    Please report bugs via CPAN RT
    http://rt.cpan.org/NoAuth/Bugs.html?Dist=Devel-Hook or mailto:

TODO
    *   finish docs

    *   finish tests

    *   this module will be soon renamed into `Devel::Hooks::BLOCK'

    *   test support for UNITCHECK blocks (needs Perl 5.10.0+)

ACKNOWLEDGEMENTS
    Everything I needed to learn about XS to write this module was borrowed
    from Manip::END written by Fergal Daly. To be really honest, the code
    was all there and I pruned it to a safer/limited/smaller API and
    included the manipulation to other hooks besides END blocks. And I also
    plagiarized his documentation.

AUTHOR
    Fergal Daly (for the code in Manip::END)

    Adriano R. Ferreira, <ferreira@cpan.org>

COPYRIGHT AND LICENSE
    Copyright (C) 2008-2017 by Adriano R. Ferreira

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

