[svn:mod_parrot] r635 - in mod_parrot/branches/configure: . build/lib build/lib/Generator build/maps/httpd config/gen/makefiles docs eg/perl6 eg/perl6/ModPerl6 eg/php eg/pir include languages/perl6/lib languages/perl6/lib/Apache languages/perl6/lib/ModParrot languages/perl6/lib/ModPerl6 lib lib/APR lib/Apache lib/ModParrot lib/ModParrot/APR lib/ModParrot/Apache lib/ModParrot/HLL patches src src/pmc t/conf t/legacy t/lib t/response/TestAPI

[email protected] Sat, 2 May 2009 06:55:05 -0700 (PDT)
Newsgroups perl.cvs.mod_parrot
Message-ID <[email protected]>
Author: jhorwitz
Date: Sat May  2 06:55:00 2009
New Revision: 635

Added:
   mod_parrot/branches/configure/README.modperl6
      - copied unchanged from r630, /mod_parrot/trunk/README.modperl6
   mod_parrot/branches/configure/build/lib/Generator/ApacheServerRec.pm
      - copied unchanged from r630, /mod_parrot/trunk/build/lib/Generator/ApacheServerRec.pm
   mod_parrot/branches/configure/build/lib/Generator/ModParrotConstants.pm
      - copied unchanged from r630, /mod_parrot/trunk/build/lib/Generator/ModParrotConstants.pm
   mod_parrot/branches/configure/build/maps/httpd/server_rec.map
      - copied unchanged from r630, /mod_parrot/trunk/build/maps/httpd/server_rec.map
   mod_parrot/branches/configure/languages/perl6/lib/Apache/
      - copied from r630, /mod_parrot/trunk/languages/perl6/lib/Apache/
   mod_parrot/branches/configure/languages/perl6/lib/Apache/Const.pm
      - copied unchanged from r630, /mod_parrot/trunk/languages/perl6/lib/Apache/Const.pm
   mod_parrot/branches/configure/languages/perl6/lib/ModParrot/
      - copied from r630, /mod_parrot/trunk/languages/perl6/lib/ModParrot/
   mod_parrot/branches/configure/languages/perl6/lib/ModParrot/Const.pm
      - copied unchanged from r630, /mod_parrot/trunk/languages/perl6/lib/ModParrot/Const.pm
   mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/Fudge.pir
      - copied unchanged from r630, /mod_parrot/trunk/languages/perl6/lib/ModPerl6/Fudge.pir
   mod_parrot/branches/configure/lib/ModParrot/APR/   (props changed)
      - copied from r630, /mod_parrot/trunk/lib/ModParrot/APR/
   mod_parrot/branches/configure/lib/ModParrot/APR/Pool.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/APR/Pool.pir
   mod_parrot/branches/configure/lib/ModParrot/APR/Table.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/APR/Table.pir
   mod_parrot/branches/configure/lib/ModParrot/Apache/   (props changed)
      - copied from r630, /mod_parrot/trunk/lib/ModParrot/Apache/
   mod_parrot/branches/configure/lib/ModParrot/Apache/CmdParms.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Apache/CmdParms.pir
   mod_parrot/branches/configure/lib/ModParrot/Apache/Constants.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Apache/Constants.pir
   mod_parrot/branches/configure/lib/ModParrot/Apache/Module.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Apache/Module.pir
   mod_parrot/branches/configure/lib/ModParrot/Apache/RequestRec.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Apache/RequestRec.pir
   mod_parrot/branches/configure/lib/ModParrot/Apache/ServerRec.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Apache/ServerRec.pir
   mod_parrot/branches/configure/lib/ModParrot/Constants.pir
      - copied unchanged from r630, /mod_parrot/trunk/lib/ModParrot/Constants.pir
   mod_parrot/branches/configure/src/modparrot_io.c
      - copied unchanged from r630, /mod_parrot/trunk/src/modparrot_io.c
   mod_parrot/branches/configure/src/pmc/   (props changed)
      - copied from r630, /mod_parrot/trunk/src/pmc/
   mod_parrot/branches/configure/src/pmc/modparrothandle.pmc
      - copied unchanged from r630, /mod_parrot/trunk/src/pmc/modparrothandle.pmc
   mod_parrot/branches/configure/t/response/TestAPI/apr_pool.pir
      - copied unchanged from r630, /mod_parrot/trunk/t/response/TestAPI/apr_pool.pir
   mod_parrot/branches/configure/t/response/TestAPI/context.pir
      - copied unchanged from r630, /mod_parrot/trunk/t/response/TestAPI/context.pir
   mod_parrot/branches/configure/t/response/TestAPI/modparrothandle.pir
      - copied unchanged from r630, /mod_parrot/trunk/t/response/TestAPI/modparrothandle.pir
   mod_parrot/branches/configure/t/response/TestAPI/server_rec.pir
      - copied unchanged from r630, /mod_parrot/trunk/t/response/TestAPI/server_rec.pir
Removed:
   mod_parrot/branches/configure/docs/handler-architecture.txt
   mod_parrot/branches/configure/lib/APR/
   mod_parrot/branches/configure/lib/Apache/
   mod_parrot/branches/configure/lib/ModParrot/HLL/nqp.pir
   mod_parrot/branches/configure/lib/ModParrot/HLL/perl6-pir.pir
   mod_parrot/branches/configure/patches/
Modified:
   mod_parrot/branches/configure/CHANGES
   mod_parrot/branches/configure/Configure.pl
   mod_parrot/branches/configure/README
   mod_parrot/branches/configure/TODO
   mod_parrot/branches/configure/VERSION
   mod_parrot/branches/configure/build/lib/Generator/ApacheConstants.pm
   mod_parrot/branches/configure/build/lib/Generator/ApacheRequestRec.pm
   mod_parrot/branches/configure/build/lib/generate_source.pl
   mod_parrot/branches/configure/build/maps/httpd/request_rec.map
   mod_parrot/branches/configure/call_list.txt
   mod_parrot/branches/configure/config/gen/makefiles/root.in
   mod_parrot/branches/configure/docs/apache-conf.txt
   mod_parrot/branches/configure/docs/nci.txt
   mod_parrot/branches/configure/eg/perl6/ModPerl6/Counter.pm
   mod_parrot/branches/configure/eg/perl6/ModPerl6/Polly.pm
   mod_parrot/branches/configure/eg/perl6/README
   mod_parrot/branches/configure/eg/perl6/counter
   mod_parrot/branches/configure/eg/php/README
   mod_parrot/branches/configure/eg/pir/authenhandler.pir
   mod_parrot/branches/configure/eg/pir/handler.pir
   mod_parrot/branches/configure/eg/pir/interpinfo.pir
   mod_parrot/branches/configure/include/mod_parrot.h
   mod_parrot/branches/configure/include/modparrot_config.h
   mod_parrot/branches/configure/include/modparrot_log.h
   mod_parrot/branches/configure/languages/perl6/lib/   (props changed)
   mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/   (props changed)
   mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/Registry.pm
   mod_parrot/branches/configure/languages/perl6/lib/mod_perl6.pm
   mod_parrot/branches/configure/lib/ModParrot/Context.pir
   mod_parrot/branches/configure/lib/ModParrot/HLL/lolcode.pir
   mod_parrot/branches/configure/lib/ModParrot/HLL/perl6.pir
   mod_parrot/branches/configure/lib/ModParrot/HLL/pipp.pir
   mod_parrot/branches/configure/lib/ModParrot/HLL/pir.pir
   mod_parrot/branches/configure/lib/ModParrot/Interpreter.pir
   mod_parrot/branches/configure/lib/mod_parrot.pir
   mod_parrot/branches/configure/src/context.c
   mod_parrot/branches/configure/src/mod_parrot.c
   mod_parrot/branches/configure/src/modparrot_config.c
   mod_parrot/branches/configure/src/module.c
   mod_parrot/branches/configure/src/nci.c
   mod_parrot/branches/configure/src/parrot_util.c
   mod_parrot/branches/configure/t/conf/extra.conf.in
   mod_parrot/branches/configure/t/legacy/03AuthenHandler.t
   mod_parrot/branches/configure/t/lib/handlers.pir
   mod_parrot/branches/configure/t/response/TestAPI/interpreter.pir
   mod_parrot/branches/configure/t/response/TestAPI/request_rec.pir

Log:
merge r387:HEAD from trunk
updates to build new components
still not linking properly


Modified: mod_parrot/branches/configure/CHANGES
==============================================================================
--- mod_parrot/branches/configure/CHANGES	(original)
+++ mod_parrot/branches/configure/CHANGES	Sat May  2 06:55:00 2009
@@ -1,5 +1,49 @@
 $Id$
 
+0.5    January 4, 2009
+       mod_parrot:
+         * Fixes for recent Parrot releases
+         * New architecture with one Apache module per HLL layer
+         * Apache;Module supports creating Apache modules from Parrot
+         * APR;Pool manages memory pools
+         * HLL cleanup handlers are managed by APR;Pool
+         * Custom HLL directives
+         * Per-HLL server & directory configurations
+         * HLL configuration merging
+         * Individual hook registration
+         * Initial support for threaded MPMs (all tests pass for worker MPM)
+         * Migrated mod_parrot modules under 'ModParrot' namespace
+         * Contexts are bound to pools so they persist over multiple phases
+         * Various GC fixes
+         * get_basic_auth_pw returns an array PMC
+         * more Apache constants
+         * Refactored initialization code to support early startup
+         * ParrotLoadImmediate starts interpreter early and loads bytecode/PIR
+         * Refactored C-based PIR handlers into the PIR HLL module
+         * Removed ParrotAddHandler and ParrotAddType
+         * ModParrot;Constants houses mod_parrot specific constants
+         * Apache;RequestRec.read() reads the HTTP body (POST data)
+         * Various configuration fixes
+         * Refactored lots of code to make it easier to maintain
+         * Refactored PIR compilation rules in Makefile
+         * New ModParrotHandle PMC ties Parrot I/O ops to Apache I/O
+         * New Apache directives ParrotLibPath and ParrotDynextPath
+         * Removed mod_nqp (PIR HLL module is now the spec)
+ 
+       mod_perl6:
+         * Replace PIR mod_perl6 with pure-perl mod_perl6
+         * Support for precompiled mod_perl6 & ModPerl6::Registry
+         * Merge handlers
+         * ModPerl6::Registry emulates CGI environment
+         * Perl6Module
+         * Perl6Options
+           * Enable (currently a no-op)
+           * ParseHandlers (currently a no-op)
+         * Method handlers
+         * Custom-named handlers (instead of 'handler')
+         * Rakudo no longer needs to be patched
+         * ModPerl6::Fudge implements missing functionality in Rakudo
+
 0.4    January 20, 2008
        * Support for Parrot 0.5.1 (Hatachi)
        * Many fixes for 64-bit platforms

Modified: mod_parrot/branches/configure/Configure.pl
==============================================================================
--- mod_parrot/branches/configure/Configure.pl	(original)
+++ mod_parrot/branches/configure/Configure.pl	Sat May  2 06:55:00 2009
@@ -34,6 +34,36 @@
 
 main( @ARGV ) unless caller;
 
+print "Creating testing infrastructure...";
+eval "use Apache::Test 1.26";
+unless ($@) {
+    no strict;
+    # don't use installed mod_parrot
+    package ModParrot::TestRun;
+    use base Apache::TestRunParrot;
+    use Apache::TestConfigParrot;
+
+    sub pre_configure
+    {
+        my $self = shift;
+        Apache::TestConfig::autoconfig_skip_module_add('mod_parrot.c');
+        $self->SUPER::pre_configure();
+    }
+
+    package main;
+    use Apache::TestMM;
+    push(@ARGV, '-apxs', '/usr/local/apache2/bin/apxs');
+    push(@ARGV, '-defines', "PARROT_BUILD_DIR='/home/jeff/build/parrot'");
+    Apache::TestMM::filter_args();
+    ModParrot::TestRun->generate_script();
+    print "done.\n";
+}
+else {
+    print "Apache::Test missing or earlier than 1.26.\n";
+    print "Skipping test setup!\n";
+}
+
+
 
 sub main {
     ## data store for directory operations
@@ -250,11 +280,8 @@
 
 $_ ^=~ { AUTHOR => 'particle' };
 
-
-# vim: et sw=4:
 __END__
 
-
 ## step gen::apache_test_config
 print "Creating testing infrastructure...";
 eval "use Apache::Test 1.26";
@@ -284,4 +311,4 @@
     print "Skipping test setup!\n";
 }
 
-
+# vim: et sw=4:

Modified: mod_parrot/branches/configure/README
==============================================================================
--- mod_parrot/branches/configure/README	(original)
+++ mod_parrot/branches/configure/README	Sat May  2 06:55:00 2009
@@ -6,9 +6,6 @@
 allowing you to write handlers in Parrot or any language targeted to the
 Parrot VM.
 
-This software is a complete rewrite of the original version developed by
-Ask Bjorn-Hansen, Robert Spier, and Kevin Falcone.
-
 STATUS
 ------
 mod_parrot is slowly maturing.  While its design is stable now, it should
@@ -18,8 +15,8 @@
 
 REQUIREMENTS
 ------------
-* Apache 2.0.x or 2.2.x
-* Parrot 0.5.1 (Hatachi) or a recent source tree (all tests pass as of r24887)
+* Apache 2.0.x or 2.2.x (2.4 may work but is untested)
+* A recent subversion checkout of Parrot (r35084 or later)
 * Perl 5.8.0 or later for configuration
 * Apache::Test 1.26 or later (for tests)
 
@@ -29,16 +26,14 @@
 
 1) perl Configure.pl --parrot-build-dir=/path/to/parrot --apxs=/path/to/apxs
 2) make
-3) make libraries
-4) make test
-5) make install
-6) Copy the lib directory to a directory of your choosing.  This *should* be
-   installed in a more standard place, but we'll just copy it anywhere for now.
+3) make test
+4) make install (as root, if appropriate)
 
 CONFIGURING APACHE
 ------------------
-NOTE: This is a very basic configuration for pure PIR handlers.  See the
-web site for documentation on configuring handlers in other languages.
+NOTE: This is a very basic configuration for a PIR response handler, and is
+only meant as an example.  In addition to this README, please see the
+documentation for the HLL module(s) you are interested in using.
 
 1) Verify mod_parrot is activated in httpd.conf:
 
@@ -46,17 +41,25 @@
 
 2) Tell Apache how to initialize mod_parrot using ParrotInit:
 
-   ParrotInit /path/to/lib/mod_parrot.pbc
+   ParrotInit /path/to/mod_parrot/lib/mod_parrot.pbc
 
    Alternatively you can copy mod_parrot.pbc to parrot's runtime directory
    and set the PARROT_RUNTIME environment variable to that directory.
    mod_parrot will then be able to find this file automatically.
 
-3) Preload your Parrot handler with ParrotLoad.  It can be PIR or compiled PBC.
+3) Tell mod_parrot where to find its libraries:
+
+   ParrotLibPath /path/to/mod_parrot/lib
+
+4) Load the PIR HLL layer:
+
+   ParrotLoadImmediate ModParrot/HLL/pir.pbc
+
+5) Load your Parrot handler with ParrotLoad.  It can be PIR or compiled PBC.
 
    ParrotLoad /path/to/your/code
 
-4) Configure a location and set the handler to "parrot-code", the official
+6) Configure a location and set the handler to "parrot-code", the official
    mod_parrot handler string.  Use ParrotHandler to tell mod_parrot what to
    run for the content handler by passing it the namespace you used in your
    code:
@@ -66,20 +69,11 @@
        ParrotHandler MyApp
    </Location>
 
-   Or use ParrotAuthenHandler for an authentication handler:
-
-   <Location /parrot/private>
-       ParrotAuthenHandler MyAuthHandler
-       AuthType basic
-       AuthName Test
-       Require valid-user
-   </Location>
-
    Or use one or more of the other Parrot*Handlers.
 
-5) Restart Apache.
+6) Restart Apache.
 
-6) Go to the URL you configured and try out your new handler.
+7) Go to the URL you configured and try out your new handler.
 
 DOCUMENTATION
 -------------

Modified: mod_parrot/branches/configure/TODO
==============================================================================
--- mod_parrot/branches/configure/TODO	(original)
+++ mod_parrot/branches/configure/TODO	Sat May  2 06:55:00 2009
@@ -1,12 +1,4 @@
 $Id$
 
-* complete request_rec coverage
-* add classes for conn_rec, server_rec, pools
-* filters
-* custom Apache directives
-* code blocks (e.g. <Perl>...</Perl>)
-* better handling of interpreter exceptions
-* autoloading of HLL compiler code (need a Parrot_load_hll_bytecode())
-* separate HLL impelmentations into their own distributions
-* support Apache 2.2+ auth providers
-* implement proper directory config merging
+The TODO list has been integrated into the formal roadmap on the mod_parrot
+web site at http://www.smashing.org/mod_parrot.

Modified: mod_parrot/branches/configure/VERSION
==============================================================================
--- mod_parrot/branches/configure/VERSION	(original)
+++ mod_parrot/branches/configure/VERSION	Sat May  2 06:55:00 2009
@@ -1 +1 @@
-0.4
+0.5

Modified: mod_parrot/branches/configure/build/lib/Generator/ApacheConstants.pm
==============================================================================
--- mod_parrot/branches/configure/build/lib/Generator/ApacheConstants.pm	(original)
+++ mod_parrot/branches/configure/build/lib/Generator/ApacheConstants.pm	Sat May  2 06:55:00 2009
@@ -32,7 +32,8 @@
     $self->generate_source(
         $self->to_string($constants{'handler'}),
         $self->to_string($constants{'http'}),
-        $self->to_string($constants{'log'})
+        $self->to_string($constants{'log'}),
+        $self->to_string($constants{'config'}),
     );
 }
 
@@ -68,6 +69,36 @@
     }
     close HTTP_LOG_H;
 
+    # Get constants from $APACHE/include/http_config.h
+    open (HTTP_CONFIG_H, $self->{'apache_include_dir'} . 'http_config.h')
+        or die $!;
+    while (<HTTP_CONFIG_H>) {
+        my $code;
+        if (/#define\s+(OR_\w+|RSRC_CONF|EXEC_ON_READ)\s+(\d+)/) {
+            $constants{'config'}{$1} = $2;
+        }
+        elsif (/enum\s+(\w+)\s+\{/) {
+            $code = $_;
+            unless ($code =~ /;\s*$/) {
+                local $_;
+                while (<HTTP_CONFIG_H>) {
+                    $code .= $_;
+                    last if /;\s*$/;
+                }
+            }
+            $code =~ s:/\*.*?\*/::sg;
+            $code =~ s/\s*=\s*\w+//g;
+            $code =~ s/^[^\{]*\{//s;
+            $code =~ s/\}[^;]*;?//s;
+            $code =~ s/^\s*\n//gm;
+            my $idx = 0;
+            while ($code =~ /\b(\w+)\b,?/g) {
+                $constants{'config'}{$1} = $idx++;
+            }
+        }
+    }
+    close HTTP_CONFIG_H;
+
     return %constants;
 }
 
@@ -78,7 +109,7 @@
     my $string = "";
   
     while (my ($k, $v) = each %$constants) {
-        $string .= "    ap_constants[ \"$k\" ] = $v\n";
+        $string .= "    table[ \"$k\" ] = $v\n";
     }
 
     return $string;
@@ -86,7 +117,7 @@
 
 sub generate_source
 {
-    my ($self, $handler, $http, $log) = @_;
+    my ($self, $handler, $http, $log, $config) = @_;
 
     my $template;
     {
@@ -97,6 +128,7 @@
     $template =~ s/%%HANDLER%%/$handler/;
     $template =~ s/%%HTTP%%/$http/;
     $template =~ s/%%LOG%%/$log/;
+    $template =~ s/%%CONFIG%%/$config/;
 
     $self->write_file('pir', 'ap_constants.pir', $template);
 }
@@ -105,9 +137,9 @@
 
 __DATA__
 .sub _init_const_table
-    .local pmc ap_constants
+    .local pmc table
 
-    ap_constants = new 'OrderedHash'
+    table = new 'Hash'
 
     # Handler Responses
 %%HANDLER%%
@@ -118,6 +150,19 @@
     # Log Severities
 %%LOG%%
 
-    set_root_global [ 'Apache'; 'Constants' ], 'ap_constants', ap_constants
+    # Apache Config
+%%CONFIG%%
+    $I0 = table[ "OR_LIMIT" ]
+    $I1 = table[ "OR_OPTIONS" ]
+    $I0 |= $I1
+    $I1 = table[ "OR_FILEINFO" ]
+    $I0 |= $I1
+    $I1 = table[ "OR_AUTHCFG" ]
+    $I0 |= $I1
+    $I1 = table[ "OR_INDEXES" ]
+    $I0 |= $I1
+    table[ "OR_ALL" ] = $I0
+
+    set_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table', table
 .end
 

Modified: mod_parrot/branches/configure/build/lib/Generator/ApacheRequestRec.pm
==============================================================================
--- mod_parrot/branches/configure/build/lib/Generator/ApacheRequestRec.pm	(original)
+++ mod_parrot/branches/configure/build/lib/Generator/ApacheRequestRec.pm	Sat May  2 06:55:00 2009
@@ -69,8 +69,8 @@
 sub get_dlfunc_template
 {
     my $template = <<'END'
-dlfunc func, nul, "mpnci_request_rec_%%NAME%%", "%%SIG%%"
-set_root_global [ '_modparrot'; 'NCI' ], "request_rec_%%NAME%%", func
+dlfunc func, lib, "mpnci_request_rec_%%NAME%%", "%%SIG%%"
+set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_%%NAME%%", func
 
 END
 ;
@@ -135,7 +135,7 @@
 
     getattribute r, self, 'r'
 
-    request_rec_%%NAME%% = get_root_global [ '_modparrot'; 'NCI' ], 'request_rec_%%NAME%%'
+    request_rec_%%NAME%% = get_root_global [ 'ModParrot'; 'NCI' ], 'request_rec_%%NAME%%'
     %%NAME%% = request_rec_%%NAME%%( r , data, update_r )
 
     .return(%%NAME%%)
@@ -165,7 +165,7 @@
     data = ""
 
 call_it:
-    request_rec_%%NAME%% = get_root_global [ '_modparrot'; 'NCI' ], 'request_rec_%%NAME%%'
+    request_rec_%%NAME%% = get_root_global [ 'ModParrot'; 'NCI' ], 'request_rec_%%NAME%%'
     %%NAME%% = request_rec_%%NAME%%( r , data, update_r )
 
     .return(%%NAME%%)

Modified: mod_parrot/branches/configure/build/lib/generate_source.pl
==============================================================================
--- mod_parrot/branches/configure/build/lib/generate_source.pl	(original)
+++ mod_parrot/branches/configure/build/lib/generate_source.pl	Sat May  2 06:55:00 2009
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 
-# Copyright (c) 2005, 2007 Ian Joyce, Jeff Horwitz
+# Copyright (c) 2005, 2007, 2008 Ian Joyce, Jeff Horwitz
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
 
 use Generator::ApacheConstants;
 use Generator::ApacheRequestRec;
+use Generator::ApacheServerRec;
+use Generator::ModParrotConstants;
 
 my $apache_include_dir = '/usr/local/apache2/include/';
 
@@ -47,4 +49,6 @@
 );
 
 ModParrot::Config::Generator::ApacheConstants->new(%args)->run();
+ModParrot::Config::Generator::ModParrotConstants->new(%args)->run();
 ModParrot::Config::Generator::ApacheRequestRec->new(%args)->run();
+ModParrot::Config::Generator::ApacheServerRec->new(%args)->run();

Modified: mod_parrot/branches/configure/build/maps/httpd/request_rec.map
==============================================================================
--- mod_parrot/branches/configure/build/maps/httpd/request_rec.map	(original)
+++ mod_parrot/branches/configure/build/maps/httpd/request_rec.map	Sat May  2 06:55:00 2009
@@ -15,7 +15,7 @@
 status             | int          | rw
 
 # reserved word conflict
-#method             | const char * | rw
+method             | const char * | rw
 method_number      | int          | rw
 chunked            | int          | rw
 range              | const char * | rw

Modified: mod_parrot/branches/configure/call_list.txt
==============================================================================
--- mod_parrot/branches/configure/call_list.txt	(original)
+++ mod_parrot/branches/configure/call_list.txt	Sat May  2 06:55:00 2009
@@ -18,5 +18,8 @@
 v       pit
 v       ptt
 v       Jtiiipt
-p       JtP
-P	Jtti
+p       JttPP
+P       Jtpi
+i       Vppp
+v       pt
+v       Jpt

Modified: mod_parrot/branches/configure/config/gen/makefiles/root.in
==============================================================================
--- mod_parrot/branches/configure/config/gen/makefiles/root.in	(original)
+++ mod_parrot/branches/configure/config/gen/makefiles/root.in	Sat May  2 06:55:00 2009
@@ -19,6 +19,10 @@
 PARROT_BLIB_DIR=@parrot_build_dir@@slash@@blib_dir@
 PARROT=@parrot_build_dir@@slash@parrot
 APACHE_INCLUDE_DIR=@apache_include_dir@
+PARROT_DYNEXT=$(PARROT_SOURCE)/runtime/parrot/dynext
+BUILD_DYNPMC=$(PERL) $(PARROT_SOURCE)/tools/build/dynpmc.pl
+MODPARROT_GROUP=modparrot_group.so
+export DYNPMC_INCLUDE=$(APACHE_INCLUDE_DIR),$(APR_INCLUDE_DIR),$(APU_INCLUDE_DIR),../../include
 
 SRC_DIR = src
 TEST_SRC_DIR = t/src
@@ -29,6 +33,7 @@
 	$(SRC_DIR)/modparrot_config.c \
 	$(SRC_DIR)/nci.c \
 	$(SRC_DIR)/context.c \
+	$(SRC_DIR)/modparrot_io.c \
 	$(SRC_DIR)/module.c
 
 OBJ_FILES= \
@@ -37,22 +42,30 @@
 	$(SRC_DIR)/modparrot_config.lo \
 	$(SRC_DIR)/nci.lo \
 	$(SRC_DIR)/context.lo \
+	$(SRC_DIR)/modparrot_io.lo \
 	$(SRC_DIR)/module.lo
 
-MPLIBS=	lib/Apache/RequestRec \
-	lib/Apache/Constants \
-	lib/Apache/Module \
-	lib/APR/Table \
-	lib/mod_parrot \
-	lib/ModParrot/Context \
-	lib/ModParrot/Interpreter \
-	lib/ModParrot/HLL/pir \
-	lib/ModParrot/HLL/perl6 \
-	lib/ModParrot/HLL/pipp \
-	lib/ModParrot/HLL/lolcode \
-	lib/ModParrot/HLL/nqp
+MPLIBS= lib/ModParrot/Apache/RequestRec.pbc \
+	lib/ModParrot/Apache/ServerRec.pbc \
+	lib/ModParrot/Apache/Constants.pbc \
+	lib/ModParrot/Apache/Module.pbc \
+	lib/ModParrot/Apache/CmdParms.pbc \
+	lib/ModParrot/APR/Pool.pbc \
+	lib/ModParrot/APR/Table.pbc \
+	lib/mod_parrot.pbc \
+	lib/ModParrot/Constants.pbc \
+	lib/ModParrot/Context.pbc \
+	lib/ModParrot/Interpreter.pbc \
+	lib/ModParrot/HLL/pir.pbc \
+	lib/ModParrot/HLL/perl6.pbc \
+	lib/ModParrot/HLL/pipp.pbc \
+	lib/ModParrot/HLL/lolcode.pbc
 
-all: gen-src $(SRC_DIR)/mod_parrot.la
+PMCS= modparrothandle
+
+PMC_SOURCES= $(SRC_DIR)/pmc/modparrothandle.pmc
+
+all: gen-src $(SRC_DIR)/mod_parrot.la libs $(MODPARROT_GROUP)
 
 %.lo: %.c
 	$(LIBTOOL) --mode=compile $(CC) -o $@ $(EXTRA_CPPFLAGS) $(DEBUG) $(CFLAGS) -I$(APACHE_INCLUDE_DIR) -I$(APR_INCLUDE_DIR) -I$(APU_INCLUDE_DIR) $(DEFINES) -c $<
@@ -64,13 +77,26 @@
 	rm -f $(SRC_DIR)/*.o $(SRC_DIR)/*.lo $(SRC_DIR)/*.slo $(SRC_DIR)/*.la core core.*
 	rm -rf $(SRC_DIR)/.libs
 
-libraries:
-	@echo Compiling libraries:
-	@for i in $(MPLIBS); \
-	do \
-		echo " $$i"; \
-		$(PARROT) -o $$i.pbc $$i.pir; \
-	done
+%.pbc: %.pir
+	 $(PARROT) -o $@ $<
+
+libs: $(MPLIBS)
+
+$(MODPARROT_GROUP): $(PMC_SOURCES)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) generate $(PMCS)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) compile $(PMCS)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) linklibs $(PMCS)
+
+modperl6: languages/perl6/lib/mod_perl6.pir languages/perl6/lib/ModPerl6/Registry.pir
+
+%.pir: %.pm
+	PERL6LIB=languages/perl6/lib \
+	$(PARROT) $(PARROT_SOURCE)/languages/rakudo/perl6.pbc \
+	--output=$@ --target=pir $<
+
+modperl6-clean:
+	rm -f languages/perl6/lib/mod_perl6.pir \
+	languages/perl6/lib/ModPerl6/Registry.pir
 
 gen-src:
 	@echo Generating Source...
@@ -79,24 +105,30 @@
 gen-src-clean:
 	rm -rf build/src
 
-libraries-clean:
-	for i in $(MPLIBS); \
-	do \
-		rm -f $$i.pbc; \
-	done
+libs-clean:
+	rm -f $(MPLIBS)
+
+pmcs-clean:
+	rm -f $(SRC_DIR)/pmc/$(MODPARROT_GROUP)
+	rm -f $(SRC_DIR)/pmc/*.c
+	rm -f $(SRC_DIR)/pmc/*.h
+	rm -f $(SRC_DIR)/pmc/*.o
+	rm -f $(SRC_DIR)/pmc/*.dump
+	rm -f $(SRC_DIR)/pmc/*.exp
 
 test-clean:
 	if [ -x t/TEST ]; then t/TEST -clean; fi
 	rm -f t/core.* t/lib/handlers.pbc t/TEST
 
-clean: files-clean libraries-clean gen-src-clean
+clean: files-clean libs-clean pmcs-clean gen-src-clean modperl6-clean
 
 distclean: clean test-clean
 	rm -f Makefile Makefile.old
 
-install: $(SRC_DIR)/mod_parrot.la
+install: $(SRC_DIR)/mod_parrot.la $(MODPARROT_GROUP)
 	$(APXS) -i -n parrot -a $(SRC_DIR)/mod_parrot.la
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) copy "--destination=$(PARROT_DYNEXT)" $(PMCS)
 
-test: $(SRC_DIR)/mod_parrot.la libraries
+test: $(SRC_DIR)/mod_parrot.la libs
 	$(PARROT) -o t/lib/handlers.pbc t/lib/handlers.pir
 	$(PERL) t/TEST

Modified: mod_parrot/branches/configure/docs/apache-conf.txt
==============================================================================
--- mod_parrot/branches/configure/docs/apache-conf.txt	(original)
+++ mod_parrot/branches/configure/docs/apache-conf.txt	Sat May  2 06:55:00 2009
@@ -1,10 +1,11 @@
+============================
 mod_parrot Apache Directives
 ============================
 
 ParrotInit
 ----------
 Syntax:      ParrotInit path
-Default:     parrot's runtime path
+Default:     PARROT_RUNTIME/runtime/parrot/library/mod_parrot.pbc
 Context:     server config
 Description: Specify path to mod_parrot.pbc
 
@@ -13,14 +14,28 @@
 Syntax:      ParrotIncludePath path1[:path2]...
 Default:     none
 Context:     server config
+Description: colon separated list of search paths for Parrot includes
+
+ParrotLibPath
+----------
+Syntax:      ParrotLibPath path1[:path2]...
+Default:     none
+Context:     server config
 Description: colon separated list of search paths for Parrot libraries
 
+ParrotDynextPath
+----------
+Syntax:      ParrotDynextPath path1[:path2]...
+Default:     none
+Context:     server config
+Description: colon separated list of search paths for Parrot extensions
+
 ParrotLoad
 ----------
 Syntax:      ParrotLoad path
 Default:     none
 Context:     server config (will eventually be allowed in directory config)
-Description: Load PBC, PIR, or high level language code
+Description: Load PBC, PIR
 
 ParrotLoadImmediate
 -------------------
@@ -29,47 +44,41 @@
 Context:     server config
 Description: Start the interpreter, load and run PBC or PIR
 
+ParrotDebugLevel
+----------------
+Syntax:      ParrotDebug level
+Default:     0
+Context:     server config
+Description: Set mod_parrot's debug level (VERY verbose output).  Levels are:
+             0 = none (default)
+             1 = Apache module activity
+             2 = mod_parrot context activity
+             4 = runtime hook activity
+             8 = Parrot activity
+             16 = HLL activity
+
 ParrotTrace
 -----------
 Syntax:      ParrotTrace level
-Default:     off
+Default:     0
 Context:     server config
 Description: Enable Parrot trace output to the error log.  See Parrot docs
              for the appropriate trace levels.
 
-ParrotLanguage
---------------
-Syntax:      ParrotLanguage language
-Default:     pir
-Context:     directory config
-Description: Sets the Parrot language for the containing block.  Since several
-             languages may be used in a single block, this syntax is subject
-             to change.
-
-ParrotAddType
--------------
-Syntax:      ParrotAddType hll mime-type [mime-type ...]
-Default:     none
-Context:     server config
-Description: associate a MIME type with a Parrot HLL
-
-ParrotAddHandler
-----------------
-Syntax:      ParrotAddHandler hll handler [handler ...]
-Default:     parrot-code
-Context:     server config
-Description: associate an Apache handler string with a Parrot HLL
+========================
+PIR HLL Layer Directives
+========================
 
 ParrotHandler
 -------------
-Syntax:      ParrotHandler [hll,]handler
+Syntax:      ParrotHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot response handler (hll overrides directory config)
 
 ParrotAuthenHandler
 -------------------
-Syntax:      ParrotAuthenHandler [hll,]handler
+Syntax:      ParrotAuthenHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot authentication handler (hll overrides directory
@@ -77,7 +86,7 @@
 
 ParrotAuthzHandler
 ------------------
-Syntax:      ParrotAuthzHandler [hll,]handler
+Syntax:      ParrotAuthzHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot authorization handler (hll overrides directory
@@ -85,98 +94,91 @@
  
 ParrotAccessHandler
 -------------------
-Syntax:      ParrotAccessHandler [hll,]handler
+Syntax:      ParrotAccessHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot access handler (hll overrides directory config)
 
 ParrotOpenLogsHandler
 ---------------------
-Syntax:      ParrotOpenLogsHandler [hll,]handler
+Syntax:      ParrotOpenLogsHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot open_logs handler
 
 ParrotChildInitHandler
 ----------------------
-Syntax:      ParrotChildInitHandler [hll,]handler
+Syntax:      ParrotChildInitHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot child_init handler
 
 ParrotPostConfigHandler
 -----------------------
-Syntax:      ParrotPostConfigHandler [hll,]handler
+Syntax:      ParrotPostConfigHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot post_config handler
 
 ParrotPreConnectionHandler
 --------------------------
-Syntax:      ParrotPreConnectionHandler [hll,]handler
+Syntax:      ParrotPreConnectionHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot pre_connection handler
 
 ParrotProcessConnectionHandler
 ------------------------------
-Syntax:      ParrotProcessConnectionHandler [hll,]handler
+Syntax:      ParrotProcessConnectionHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot process_connection handler
 
 ParrotMapToStorageHandler
 -------------------------
-Syntax:      ParrotMapToStorageHandler [hll,]handler
+Syntax:      ParrotMapToStorageHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot map_to_storage handler
 
 ParrotTransHandler
 ------------------
-Syntax:      ParrotTransHandler [hll,]handler
+Syntax:      ParrotTransHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot trans handler
 
 ParrotPostReadRequestHandler
 ----------------------------
-Syntax:      ParrotPostReadRequestHandler [hll,]handler
+Syntax:      ParrotPostReadRequestHandler handler
 Default:     none
 Context:     server config
 Description: Sets the Parrot post_read_request handler
 
 ParrotHeaderParserHandler
 -------------------------
-Syntax:      ParrotHeaderParserHandler [hll,]handler
+Syntax:      ParrotHeaderParserHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot header_parser handler
 
 ParrotTypeHandler
 -----------------
-Syntax:      ParrotTypeHandler [hll,]handler
+Syntax:      ParrotTypeHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot type handler
 
 ParrotFixupHandler
 ------------------
-Syntax:      ParrotFixupHandler [hll,]handler
+Syntax:      ParrotFixupHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot fixup handler
 
 ParrotLogHandler
 ----------------
-Syntax:      ParrotLogHandler [hll,]handler
+Syntax:      ParrotLogHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot log handler
-
-ParrotCleanupHandler
-----------------
-Syntax:      ParrotCleanupHandler [hll,]handler
-Default:     none
-Context:     directory config
-Description: Sets the Parrot request cleanup handler

Modified: mod_parrot/branches/configure/docs/nci.txt
==============================================================================
--- mod_parrot/branches/configure/docs/nci.txt	(original)
+++ mod_parrot/branches/configure/docs/nci.txt	Sat May  2 06:55:00 2009
@@ -17,12 +17,12 @@
 2) If an Apache API function cannot be called through NCI, it should be wrapped
    in a small C function that can be called through NCI.  This function should
    be placed in nci.c and its NCI object should be defined in the Parrot
-   namespace ['_modparrot';'NCI'].  The function should be prefixed with
+   namespace ['ModParrot';'NCI'].  The function should be prefixed with
    mpnci_.  The PIR code to load the object should be placed in
    lib/mod_parrot.pir.
 
 3) mod_parrot functions that should be callable via NCI should be placed in
-   nci.c and defined in the Parrot namespace ['_modparrot';'NCI'].  The first
+   nci.c and defined in the Parrot namespace ['ModParrot';'NCI'].  The first
    argument passed to the function should be the Parrot interpreter, which
    Parrot will handle for you if you use the 'J' signature.  Each function
    should be prefixed with mpnci_.  The PIR code to load these objects should

Modified: mod_parrot/branches/configure/eg/perl6/ModPerl6/Counter.pm
==============================================================================
--- mod_parrot/branches/configure/eg/perl6/ModPerl6/Counter.pm	(original)
+++ mod_parrot/branches/configure/eg/perl6/ModPerl6/Counter.pm	Sat May  2 06:55:00 2009
@@ -8,12 +8,11 @@
 #
 # Usage:
 #
-# ParrotIncludePath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/path/to/mod_parrot/lib
-# ParrotLoad ModParrot/HLL/perl6.pbc
-# ParrotAddHandler perl6 perl6-script
+# ParrotLibPath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/path/to/mod_parrot/lib
+# ParrotLoadImmediate ModParrot/HLL/perl6.pbc
 # <Location /perl6/counter>
 #     SetHandler perl6-script
-#     ParrotHandler ModPerl6::Counter
+#     Perl6ResponseHandler ModPerl6::Counter
 # </Location>
 #
 # Stop Apache
@@ -24,6 +23,7 @@
 module ModPerl6::Counter;
 
 use v6;
+use Apache::Const;
 
 sub handler($r)
 {
@@ -33,5 +33,5 @@
     }
     $r.puts("Page views for this interpreter: $x\n");
     $x++;
-    0; # Apache OK
+    return $Apache::Const::OK;
 }

Modified: mod_parrot/branches/configure/eg/perl6/ModPerl6/Polly.pm
==============================================================================
--- mod_parrot/branches/configure/eg/perl6/ModPerl6/Polly.pm	(original)
+++ mod_parrot/branches/configure/eg/perl6/ModPerl6/Polly.pm	Sat May  2 06:55:00 2009
@@ -5,12 +5,11 @@
 #
 # Usage:
 #
-# ParrotIncludePath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/path/to/mod_parrot/lib
-# ParrotLoad ModParrot/HLL/perl6.pbc
-# ParrotAddHandler perl6 perl6-script
+# ParrotLibPath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/path/to/mod_parrot/lib
+# ParrotLoadImmediate ModParrot/HLL/perl6.pbc
 # <Location /perl6/polly>
 #     SetHandler perl6-script
-#     ParrotHandler ModPerl6::Polly
+#     Perl6ResponseHandler ModPerl6::Polly
 # </Location>
 #
 # Stop Apache
@@ -21,6 +20,7 @@
 module ModPerl6::Polly;
 
 use v6;
+use Apache::Const;
 
 sub handler($r)
 {
@@ -29,5 +29,5 @@
         $r.puts("SQUAWK!  Polly says $text<p>");
     }
     $r.puts("Reload with a query string and Polly will repeat it.\n");
-    0; # Apache OK
+    return $Apache::Const::OK;
 }

Modified: mod_parrot/branches/configure/eg/perl6/README
==============================================================================
--- mod_parrot/branches/configure/eg/perl6/README	(original)
+++ mod_parrot/branches/configure/eg/perl6/README	Sat May  2 06:55:00 2009
@@ -2,12 +2,12 @@
 
 How to use mod_perl6:
 
-1) Apply the modperl6 patch in the patches directory to the parrot source tree.
-2) Rebuild perl6.
+1) In the top level directory, type "make modperl6" to precompile mod_perl6.
+   This is not required, but it does provide a 10x improvement in startup time.
 3) In the Apache's envvars script:
    a) set PERL6LIB to the absolute path to languages/perl6/lib, or add it to
       the path (colon-separated) if PERL6LIB is already set.
    b) Add any local Perl 6 include paths where your handler modules will live.
-   c) Add set PARROT_RUNTIME to your parrot source directory.
+   c) Set PARROT_RUNTIME to your parrot source directory.
 4) Configure your handlers in httpd.conf (the examples contain instructions)
 5) Restart Apache (do a full stop and start if you updated envvars).

Modified: mod_parrot/branches/configure/eg/perl6/counter
==============================================================================
--- mod_parrot/branches/configure/eg/perl6/counter	(original)
+++ mod_parrot/branches/configure/eg/perl6/counter	Sat May  2 06:55:00 2009
@@ -9,14 +9,12 @@
 # Create a perl6-bin directory
 # Copy this file to perl6-bin
 #
-# ParrotIncludePath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/pa
-th/to/mod_parrot/lib
-# ParrotLoad ModParrot/HLL/perl6.pbc
-# ParrotAddHandler perl6 perl6-script
+# ParrotLibPath /path/to/eg/perl6:/path/to/parrot/runtime/parrot/library:/path/to/mod_parrot/lib
+# ParrotLoadImmediate ModParrot/HLL/perl6.pbc
 # <Directory /path/to/perl6-bin>
 #     Options +ExecCGI
 #     SetHandler perl6-script
-#     ParrotHandler ModPerl6::Registry
+#     Perl6ResponseHandler ModPerl6::Registry
 # </Directory>
 
 our $x;

Modified: mod_parrot/branches/configure/eg/php/README
==============================================================================
--- mod_parrot/branches/configure/eg/php/README	(original)
+++ mod_parrot/branches/configure/eg/php/README	Sat May  2 06:55:00 2009
@@ -1,11 +1,10 @@
 This is a PHP implementation of "Polly" from the Perl 6 examples.  It uses
-the Plumhead compiler included with the Parrot distribution.  Place it in your
+the Pipp compiler included with the Parrot distribution.  Place it in your
 document root and configure as follows:
 
-ParrotIncludePath /path/to/parrot/runtime/library:/path/to/mod_parrot/lib
-ParrotLoad ModParrot/HLL/plumhead.pbc
+ParrotLibPath /path/to/parrot/runtime/library:/path/to/mod_parrot/lib
+ParrotLoadImmediate ModParrot/HLL/pipp.pbc
 AddType application/x-httpd-php .php
-ParrotAddType plumhead application/x-httpd-php
 
 You will also want to set the PARROT_RUNTIME environment variable to your
 parrot build directory before starting Apache.  You can do this on the command

Modified: mod_parrot/branches/configure/eg/pir/authenhandler.pir
==============================================================================
--- mod_parrot/branches/configure/eg/pir/authenhandler.pir	(original)
+++ mod_parrot/branches/configure/eg/pir/authenhandler.pir	Sat May  2 06:55:00 2009
@@ -25,7 +25,7 @@
     .local string pw
     .local int status
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
     $P0 = r.'get_basic_auth_pw'( )
     status = $P0[0]

Modified: mod_parrot/branches/configure/eg/pir/handler.pir
==============================================================================
--- mod_parrot/branches/configure/eg/pir/handler.pir	(original)
+++ mod_parrot/branches/configure/eg/pir/handler.pir	Sat May  2 06:55:00 2009
@@ -25,7 +25,7 @@
     r.'puts'($S0)
 
     # tell apache we're finished
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
     .return($I0)
 .end

Modified: mod_parrot/branches/configure/eg/pir/interpinfo.pir
==============================================================================
--- mod_parrot/branches/configure/eg/pir/interpinfo.pir	(original)
+++ mod_parrot/branches/configure/eg/pir/interpinfo.pir	Sat May  2 06:55:00 2009
@@ -5,6 +5,15 @@
 #
 # Usage:
 #
+# In /path/to/apache/bin/envvars, add:
+#
+# PARROT_RUNTIME=/path/to/parrot
+# export PARROT_RUNTIME
+#
+# Stop and start apache (don't use restart).
+#
+# In httpd.conf:
+#
 # ParrotLoad /path/to/this/file
 # <Location /parrot-status>
 #     SetHandler parrot-code
@@ -37,17 +46,21 @@
     r.'puts'("<h1>Parrot interpreter statistics</h1>\n")
     r.'puts'("<table>\n")
 
+    $P0 = new ['ModParrot'; 'Context']
+    $S0 = $P0.'pool_name'()
+    print_row(r, "POOL NAME", $S0)
+
     $I0 = interpinfo .INTERPINFO_TOTAL_MEM_ALLOC
     $S0 = $I0
     print_row(r, "TOTAL_MEM_ALLOC", $S0)
 
-    $I0 = interpinfo .INTERPINFO_DOD_RUNS
+    $I0 = interpinfo .INTERPINFO_GC_MARK_RUNS
     $S0 = $I0
-    print_row(r, "DOD_RUNS", $S0)
+    print_row(r, "GC_MARK_RUNS", $S0)
 
-    $I0 = interpinfo .INTERPINFO_COLLECT_RUNS
+    $I0 = interpinfo .INTERPINFO_GC_COLLECT_RUNS
     $S0 = $I0
-    print_row(r, "COLLECT_RUNS", $S0)
+    print_row(r, "GC_COLLECT_RUNS", $S0)
 
     $I0 = interpinfo .INTERPINFO_ACTIVE_PMCS
     $S0 = $I0
@@ -81,9 +94,9 @@
     $S0 = $I0
     print_row(r, "IMPATIENT_PMCS", $S0)
 
-    $I0 = interpinfo .INTERPINFO_LAZY_DOD_RUNS
+    $I0 = interpinfo .INTERPINFO_GC_LAZY_MARK_RUNS
     $S0 = $I0
-    print_row(r, "LAZY_DOD_RUNS", $S0)
+    print_row(r, "GC_LAZY_MARK_RUNS", $S0)
 
     $I0 = interpinfo .INTERPINFO_EXTENDED_PMCS
     $S0 = $I0
@@ -122,7 +135,7 @@
 
     # tell apache we're finished
     .local pmc ap_const
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
     .return($I0)
 .end

Modified: mod_parrot/branches/configure/include/mod_parrot.h
==============================================================================
--- mod_parrot/branches/configure/include/mod_parrot.h	(original)
+++ mod_parrot/branches/configure/include/mod_parrot.h	Sat May  2 06:55:00 2009
@@ -31,24 +31,48 @@
 #define MODPARROT_DEFAULT_INIT "mod_parrot.pbc"
 
 /* string macros */
-#define MAKE_PARROT_STRING(x) (string_from_cstring(interp, x, strlen(x)))
+#define MAKE_PARROT_STRING(x) (Parrot_str_new(interp, x, strlen(x)))
 
 /* context macros */
 #define MODPARROT_CTX_ISLOCKED(x) (x->locked == 1)
 #define MODPARROT_CTX_LOCK(x) (x->locked = 1)
 #define MODPARROT_CTX_UNLOCK(x) (x->locked = 0)
+#define MP_CTX_ANY (-1)
+
+/* keys */
+#define MP_KEY_CTX "modparrot-context"
 
 /* we need to move things around to avoid this */
 #include "modparrot_config.h"
 
+/* globals! */
+struct modparrot_globals
+{
+    apr_pool_t *pconf;
+    apr_hash_t *module_hash;
+    apr_array_header_t *module_array;
+    apr_array_header_t *handler_modules[MP_HOOK_LAST];
+    apr_hash_t *ctx_pool_hash;
+    Parrot_Interp root_interp;
+    server_rec *base_server;
+    int is_started;
+    int debug_level;
+    int hard_thread_limit;
+    int max_threads;
+};
+typedef struct modparrot_globals modparrot_globals;
+
 /* per-interpreter context */
 struct modparrot_context
 {
+    apr_array_header_t *ctx_pool; /* the pool containing this context */
+    const char *ctx_pool_name;    /* name of the context pool */
     Parrot_Interp interp;         /* this context's interpreter */
     Parrot_Interp parent_interp;  /* parent interpreter */
     long count;                   /* number of interpreter invocations */
     int locked;                   /* 0=available, 1=in use */
     request_rec *r;               /* request_rec structure for this request */
+    apr_pool_t *pool;             /* the pool most specific to this phase */
     apr_pool_t *pconf;
     apr_pool_t *plog;
     apr_pool_t *ptemp;
@@ -56,11 +80,22 @@
     server_rec *s;
     conn_rec *c;
     void *csd;
-    modparrot_dir_config *dircfg; /* used by HLL directives */
-    modparrot_srv_config *srvcfg; /* used by HLL directives */
+    modparrot_module_config *raw_srv_config;
+    modparrot_module_config *raw_dir_config;
+    int module_index;
 };
 typedef struct modparrot_context modparrot_context;
 
+/* internal info for pool cleanup handlers */
+struct modparrot_cleanup_info {
+    module *module;      /* the HLL module that registered us */
+    Parrot_PMC callback; /* callback subroutine */
+    Parrot_PMC hll_data; /* a PMC to pass to the callback */
+    apr_pool_t *pool;    /* the pool for which the cleanup was registered */
+    server_rec *s;       /* used for context init */
+};
+typedef struct modparrot_cleanup_info modparrot_cleanup_info;
+
 /* misc prototypes */
 Parrot_Interp modparrot_init_interpreter(Parrot_Interp);
 int modparrot_load_bytecode(Parrot_Interp, char *);
@@ -68,20 +103,44 @@
 int modparrot_call_sub(Parrot_Interp, char *, char *);
 int modparrot_call_sub_Iv(Parrot_Interp, char *, char *, int *);
 int modparrot_call_sub_IS(Parrot_Interp, char *, char *, int *, char *);
+int modparrot_call_sub_IP(Parrot_Interp, char *, char *, int *, Parrot_PMC);
 int modparrot_call_sub_IPS(Parrot_Interp, char *, char *, int *, Parrot_PMC,
     char *);
 char *modparrot_backtrace(Parrot_Interp);
-int modparrot_hll_handler(Parrot_Interp, char *, char *, char *, int *);
 Parrot_PMC get_sub_pmc(Parrot_Interp , char *, char *);
 apr_array_header_t *mp_ctx_pool_init(apr_pool_t *, Parrot_Interp, int);
 void mp_ctx_pool_destroy(apr_array_header_t *);
-modparrot_context *reserve_ctx(apr_array_header_t *);
+modparrot_context *reserve_ctx(apr_array_header_t *, int index);
 void release_ctx(modparrot_context *);
 modparrot_context *get_interp_ctx(Parrot_Interp);
 void set_interp_ctx(Parrot_Interp, modparrot_context *);
-modparrot_context *modparrot_startup(apr_pool_t *, server_rec *, Parrot_Interp);
-void modparrot_load_file(Parrot_Interp, server_rec *, char *, char *);
-module *modparrot_add_module(Parrot_Interp, apr_pool_t *, const char *,
-    Parrot_PMC);
+modparrot_context *modparrot_startup(apr_pool_t *, server_rec *, Parrot_Interp, const char *);
+void modparrot_load_file(Parrot_Interp, server_rec *, const char *);
+module *modparrot_add_module(Parrot_Interp, apr_pool_t *, const char *, char *,
+    Parrot_PMC, Parrot_PMC);
+modparrot_context *modparrot_get_current_ctx(apr_pool_t *);
+void modparrot_set_current_ctx(apr_pool_t *, modparrot_context *);
+apr_size_t modparrot_request_read(request_rec *, char *, apr_size_t);
+Parrot_PMC modparrot_wrap_apache_type(Parrot_Interp, char *, char *, void *);
+apr_array_header_t *modparrot_get_named_ctx_pool(const char *);
+void modparrot_set_named_ctx_pool(apr_pool_t *p, const char *,
+    apr_array_header_t *);
+const char *modparrot_get_ctx_pool_name(apr_array_header_t *);
+
+/* macros for wrapping apache types */
+#define modparrot_wrap_apr_pool(i, x) \
+    (modparrot_wrap_apache_type(i, "ModParrot;APR;Pool", "apr_pool", x))
+
+#define modparrot_wrap_conn_rec(i, x) \
+    (modparrot_wrap_apache_type(i, "ModParrot;Apache;ConnRec", \
+    "conn_rec", x))
+
+#define modparrot_wrap_server_rec(i, x) \
+    (modparrot_wrap_apache_type(i, "ModParrot;Apache;ServerRec", \
+    "server_rec", x))
+
+#define modparrot_wrap_cmd_parms(i, x) \
+    (modparrot_wrap_apache_type(i, "ModParrot;Apache;CmdParms", \
+    "cmd_parms", x))
 
 #endif /* _MODPARROT_H */

Modified: mod_parrot/branches/configure/include/modparrot_config.h
==============================================================================
--- mod_parrot/branches/configure/include/modparrot_config.h	(original)
+++ mod_parrot/branches/configure/include/modparrot_config.h	Sat May  2 06:55:00 2009
@@ -19,6 +19,7 @@
 #define _MODPARROT_CONFIG_H
 
 #include "apr_tables.h"
+#include "apr_hash.h"
 
 /* per-server options */
 #define MP_OPT_ENABLE 1
@@ -33,6 +34,12 @@
 #  define MP_INIT_CMD_TAKE3(c) (c.func.take3 = modparrot_module_cmd_take3)
 #  define MP_INIT_CMD_TAKE23(c) (c.func.take3 = modparrot_module_cmd_take3)
 #  define MP_INIT_CMD_TAKE123(c) (c.func.take3 = modparrot_module_cmd_take3)
+#  define MP_INIT_CMD_RAW_ARGS(c) (c.func.raw_args = \
+                                   modparrot_module_cmd_raw_args)
+#  define MP_INIT_CMD_NO_ARGS(c) (c.func.no_args = modparrot_module_cmd_no_args)
+#  define MP_INIT_CMD_ITERATE(c) (c.func.take1 = modparrot_module_cmd_iterate)
+#  define MP_INIT_CMD_ITERATE2(c) (c.func.take2 = modparrot_module_cmd_iterate2)
+#  define MP_INIT_CMD_FLAG(c) (c.func.flag = modparrot_module_cmd_flag)
 #else /* (AP_HAVE_DESIGNATED_INITIALIZER) || defined(DOXYGEN) */
 #  define MP_INIT_CMD_TAKE1(c) (c.func = modparrot_module_cmd_take1)
 #  define MP_INIT_CMD_TAKE2(c) (c.func = modparrot_module_cmd_take2)
@@ -40,61 +47,99 @@
 #  define MP_INIT_CMD_TAKE3(c) (c.func = modparrot_module_cmd_take3)
 #  define MP_INIT_CMD_TAKE23(c) (c.func = modparrot_module_cmd_take3)
 #  define MP_INIT_CMD_TAKE123(c) (c.func = modparrot_module_cmd_take3)
+#  define MP_INIT_CMD_RAW_ARGS(c) (c.func = modparrot_module_cmd_raw_args)
+#  define MP_INIT_CMD_NO_ARGS(c) (c.func = modparrot_module_cmd_no_args)
+#  define MP_INIT_CMD_ITERATE(c) (c.func = modparrot_module_cmd_iterate)
+#  define MP_INIT_CMD_ITERATE2(c) (c.func = modparrot_module_cmd_iterate2)
+#  define MP_INIT_CMD_FLAG(c) (c.func = modparrot_module_cmd_flag)
 #endif /* (AP_HAVE_DESIGNATED_INITIALIZER) || defined(DOXYGEN) */
 
-/* configuration */
-struct modparrot_handler_info
+/* hook types */
+enum modparrot_hooks {
+    /* server scope */
+    MP_HOOK_OPEN_LOGS,
+    MP_HOOK_POST_CONFIG,
+    MP_HOOK_CHILD_INIT,
+    MP_HOOK_PRE_CONNECTION,
+    MP_HOOK_PROCESS_CONNECTION,
+    MP_HOOK_POST_READ_REQUEST,
+    MP_HOOK_MAP_TO_STORAGE,
+    MP_HOOK_TRANS,
+
+    /* directory scope */
+    MP_HOOK_INPUT_FILTER,
+    MP_HOOK_HEADER_PARSER,
+    MP_HOOK_ACCESS,
+    MP_HOOK_AUTHEN,
+    MP_HOOK_AUTHZ,
+    MP_HOOK_RESPONSE,
+    MP_HOOK_OUTPUT_FILTER,
+    MP_HOOK_TYPE,
+    MP_HOOK_FIXUP,
+    MP_HOOK_LOG,
+
+    /* mark the end of the individual hooks */
+    MP_HOOK_LAST,
+
+    /* shortcut for all hooks */
+    MP_HOOK_ALL
+};
+
+struct modparrot_module_info
+{
+    const char *ctx_pool_name; /* default context pool name for this module */
+    apr_array_header_t *ctx_pool; /* cached pointer to default context pool */
+    Parrot_PMC server_create_sub;
+    Parrot_PMC server_merge_sub;
+    Parrot_PMC dir_create_sub;
+    Parrot_PMC dir_merge_sub;
+    char *namespace; /* can be a real namespace or the name of an HLL */
+    short hooks[MP_HOOK_LAST]; /* index is from modparrot_hooks enum */
+};
+typedef struct modparrot_module_info modparrot_module_info;
+
+/* container for HLL server and directory configs */
+struct modparrot_module_config
 {
-    char *id;  /* identifier of the code to load */
-    char *hll; /* HLL of the code */
+    char *name;
+    modparrot_module_info *minfo;
+    const char *ctx_pool_name; /* context pool name for this config */
+    apr_array_header_t *ctx_pool; /* cached pointer to the context pool */
+    Parrot_PMC cfg;
 };
-typedef struct modparrot_handler_info modparrot_handler_info; 
+typedef struct modparrot_module_config modparrot_module_config;
 
 struct modparrot_srv_config
 {
     apr_pool_t *pool;
     apr_array_header_t *ctx_pool;
+    int start_interp;
+    int minspare_interp;
+    int maxspare_interp;
+    int max_interp;
     char *init_path;
     int trace_flags;
     int enable_option_flags;
     int disable_option_flags;
     int option_flags;
     char *include_path;
+    char *dynext_path;
+    char *lib_path;
+    char *so_path;
     apr_array_header_t *preload;
-    apr_table_t *handler_map;
-    apr_table_t *type_map;
-    modparrot_handler_info *open_logs_handler;
-    modparrot_handler_info *child_init_handler;
-    modparrot_handler_info *child_exit_handler;
-    modparrot_handler_info *post_config_handler;
-    modparrot_handler_info *pre_connection_handler;
-    modparrot_handler_info *process_connection_handler;
-    modparrot_handler_info *map_to_storage_handler;
-    modparrot_handler_info *trans_handler;
-    modparrot_handler_info *post_read_request_handler;
 };
 typedef struct modparrot_srv_config modparrot_srv_config;
 
-struct modparrot_dir_config
-{
-    char *directory;
-    char *hll; /* default HLL handler for this block */
-    modparrot_handler_info *input_filter_handler;
-    modparrot_handler_info *output_filter_handler;
-    modparrot_handler_info *header_parser_handler;
-    modparrot_handler_info *handler;
-    modparrot_handler_info *access_handler;
-    modparrot_handler_info *authen_handler;
-    modparrot_handler_info *authz_handler;
-    modparrot_handler_info *type_handler;
-    modparrot_handler_info *fixup_handler;
-    modparrot_handler_info *log_handler;
-    modparrot_handler_info *cleanup_handler;
-};
-typedef struct modparrot_dir_config modparrot_dir_config;
+/* no directory config right now
+ * struct modparrot_dir_config
+ * {
+ * };
+ * typedef struct modparrot_dir_config modparrot_dir_config;
+ */
 
 struct modparrot_module_cmd_data
 {
+    module *modp;
     Parrot_PMC func;     /* parrot callback sub */
     Parrot_PMC cmd_data; /* directive-specific cmd_data */
 };
@@ -107,51 +152,38 @@
 void *merge_modparrot_dir_config(apr_pool_t *, void *, void *);
 void *merge_modparrot_srv_config(apr_pool_t *, void *, void *);
 
-/* handler directives */
-const char *modparrot_cmd_open_logs_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_post_config_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_child_init_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_child_exit_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_pre_connection_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_process_connection_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_input_filter_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_output_filter_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_post_read_request_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_trans_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_map_to_storage_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_header_parser_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_access_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_authen_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_authz_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_type_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_fixup_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_log_handler(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_cleanup_handler(cmd_parms *, void *, const char *);
-
-/* other directives */
+/* config directives */
 const char *modparrot_cmd_init(cmd_parms *, void *, const char *);
 const char *modparrot_cmd_trace(cmd_parms *, void *, const char *);
+const char *modparrot_cmd_debug(cmd_parms *, void *, const char *);
 const char *modparrot_cmd_language(cmd_parms *, void *, const char *);
 const char *modparrot_cmd_load(cmd_parms *, void *, const char *);
-const char *modparrot_cmd_load_immediate(cmd_parms *, void *, const char *);
+const char *modparrot_cmd_load_immediate(cmd_parms *, void *, const char *, const char *);
 const char *modparrot_cmd_include_path(cmd_parms *, void *, const char *);
+const char *modparrot_cmd_lib_path(cmd_parms *, void *, const char *);
+const char *modparrot_cmd_dynext_path(cmd_parms *, void *, const char *);
 const char *modparrot_cmd_add_type(cmd_parms *, void *, const char *, const char *);
 const char *modparrot_cmd_add_handler(cmd_parms *, void *, const char *, const char *);
 const char *modparrot_cmd_options(cmd_parms *, void *, const char *);
 
-/* for HLL apache modules */
-const char *modparrot_set_config_ptrs(cmd_parms *, void *);
-const char *modparrot_module_cmd_take1(cmd_parms *, void *, const char *);
-const char *modparrot_module_cmd_take2(cmd_parms *, void *, const char *,
-    const char*);
-const char *modparrot_module_cmd_take12(cmd_parms *, void *, const char *,
-    const char*);
-const char *modparrot_module_cmd_take3(cmd_parms *, void *, const char *,
-    const char *, const char*);
-const char *modparrot_module_cmd_take23(cmd_parms *, void *, const char *,
-    const char *, const char*);
-const char *modparrot_module_cmd_take123(cmd_parms *, void *, const char *,
-    const char *, const char*);
+/* handlers for HLL apache modules */
+int modparrot_meta_open_logs_handler(apr_pool_t *, apr_pool_t *, apr_pool_t *,
+    server_rec *);
+int modparrot_meta_post_config_handler(apr_pool_t *, apr_pool_t *,
+    apr_pool_t *, server_rec *);
+void modparrot_meta_child_init_handler(apr_pool_t *, server_rec *s);
+int modparrot_meta_pre_connection_handler(conn_rec *, void *);
+int modparrot_meta_process_connection_handler(conn_rec *);
+int modparrot_meta_map_to_storage_handler(request_rec *);
+int modparrot_meta_trans_handler(request_rec *);
+int modparrot_meta_post_read_request_handler(request_rec *);
+int modparrot_meta_header_parser_handler(request_rec *);
+int modparrot_meta_access_handler(request_rec *);
+int modparrot_meta_authen_handler(request_rec *);
+int modparrot_meta_authz_handler(request_rec *);
+int modparrot_meta_response_handler(request_rec *);
+int modparrot_meta_type_handler(request_rec *);
+int modparrot_meta_fixup_handler(request_rec *);
+int modparrot_meta_log_handler(request_rec *);
 
 #endif /* _MODPARROT_CONFIG_H */

Modified: mod_parrot/branches/configure/include/modparrot_log.h
==============================================================================
--- mod_parrot/branches/configure/include/modparrot_log.h	(original)
+++ mod_parrot/branches/configure/include/modparrot_log.h	Sat May  2 06:55:00 2009
@@ -42,4 +42,29 @@
 #define MPLOG_DEBUGF(s, fmt, msg) \
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, fmt, msg)
 
+void modparrot_trace(server_rec *, const char *, ...);
+
+#ifdef MODPARROT_DEBUG
+
+#define MP_DEBUG_NONE 0
+#define MP_DEBUG_MODULE 1
+#define MP_DEBUG_CONTEXT 2
+#define MP_DEBUG_HOOK 4
+#define MP_DEBUG_PARROT 8
+#define MP_DEBUG_HLL 16
+
+#define MP_TRACE_h if (mp_globals.debug_level & MP_DEBUG_HOOK) modparrot_trace
+#define MP_TRACE_c if (mp_globals.debug_level & MP_DEBUG_CONTEXT) modparrot_trace
+#define MP_TRACE_p if (mp_globals.debug_level & MP_DEBUG_PARROT) modparrot_trace
+#define MP_TRACE_m if (mp_globals.debug_level & MP_DEBUG_MODULE) modparrot_trace
+
+#else /* MODPARROT_DEBUG */
+
+#define MP_TRACE_h if (0) modparrot_trace
+#define MP_TRACE_c if (0) modparrot_trace
+#define MP_TRACE_p if (0) modparrot_trace
+#define MP_TRACE_m if (0) modparrot_trace
+
+#endif /* MODPARROT_DEBUG */
+
 #endif /* _MODPARROT_LOG_H */

Modified: mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/Registry.pm
==============================================================================
--- mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/Registry.pm	(original)
+++ mod_parrot/branches/configure/languages/perl6/lib/ModPerl6/Registry.pm	Sat May  2 06:55:00 2009
@@ -4,42 +4,116 @@
 
 use v6;
 
+# for perl 6 functionality not yet supported by rakudo
+use ModPerl6::Fudge;
+use Apache::Const;
+
 our %registry;
+regex header_regex { ^^ ([\w|'-']+) ':' <ws> (\N+) $$ };
 
 sub gen_module_name($path)
 {
-    # until we have substitutions, use split/join to sanitize the path.
-    my @pieces = split('/', $path);
-    my $name = join('_', @pieces);
-    @pieces = split('-', $name);
-    $name = join('_', @pieces);
-
-    my $mod = "ModPerl6::Registry::Script::$name";
+    my $name = $path;
+    # sanitize the module name
+    $name .= subst(/<-alnum>/, '_', :global);
+    return "ModPerl6::Registry::script_$name";
+}
 
-    return $mod;
+# this is temporary until mod_parrot supports output filters
+sub parse_headers($r, $in)
+{
+    my $headers_done = 0;
+    return $in if $r.notes.get('modperl6-parsed-headers');
+    my $out = '';
+    my $headers_out = $r.headers_out();
+    for $in.split(/\n/) -> $line {
+        if ($line eq '') {
+            if ($headers_done) {
+                $out ~= "\n";
+            }
+        }
+        elsif (!$headers_done && $line ~~ /<header_regex>/) {
+            my $key = ~$<header_regex>[0];
+            my $val = ~$<header_regex>[1];
+            given $key.lc {
+                when 'content-type' { $r.content_type($val); }
+                default { $headers_out.set($key, $val); }
+            }
+        }
+        # this will catch non-headers as well as the blank line postamble
+        else {
+            unless ($headers_done) {
+                $r.notes.set('modperl6-parsed-headers', 'yes');
+                $headers_done = 1;
+            }
+            if ($line.chars) {
+                $out ~= $line ~ "\n";
+            }
+        }
+    }
+    return $out;
 }
 
 sub handler($r)
 {
+    my %cfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    my %dircfg = ModParrot::Apache::Module::get_config(
+        "modparrot_perl6_module", $r.per_dir_config());
+
     my $script = $r.filename();
     unless (%registry{$script}) {
         my $data = slurp $script;
         my $mod = gen_module_name($script);
-        my $code = "module $mod; sub _handler \{ $data \}";
+        my $code = "module $mod; sub reg__handler \{ $data \}";
         eval $code;
+        if ($!) {
+            $r.log_rerror($script, 0, 0, $!);
+            return $Apache::Const::HTTP_INTERNAL_SERVER_ERROR;
+        }
         %registry{$script} = $mod;
         %registry{$mod} = $script;
     }
 
-    my $interp = ModParrot::Interpreter.new();
-    $interp.capture_stdout(1);
+    # grab interesting stuff from headers
+    my $headers_in = $r.headers_in();
+    my $content_length = $headers_in.get('Content-Length');
+    my $cookies = $headers_in.get('Cookie');
+
+    # set environment variables expected by CGI scripts
+    # XXX use %*ENV when Rakudo RT #61412 is fixed
+    my $args = $r.args();
+    my $uri = $args ?? ($r.uri() ~ '?' ~ $args) !! $r.uri();
+    ModPerl6::Fudge::setenv('MODPERL6', 1);
+    ModPerl6::Fudge::setenv('QUERY_STRING', $args);
+    ModPerl6::Fudge::setenv('PATH_INFO', $r.path_info);
+    ModPerl6::Fudge::setenv('REQUEST_METHOD', $r.method);
+    ModPerl6::Fudge::setenv('REQUEST_URI', $uri);
+    ModPerl6::Fudge::setenv('CONTENT_LENGTH', $content_length);
+    ModPerl6::Fudge::setenv('HTTP_COOKIE', $cookies);
+    ModPerl6::Fudge::setenv('SERVER_NAME', $r.hostname);
+    ## XXX requires server_rec
+    #ModPerl6::Fudge::setenv('SERVER_PORT', $server_port);
+
+    my $do_headers = %dircfg<options><parseheaders>;
+
     my $mod = %registry{$script};
-    ::($mod)::_handler();
-    my $buf = $interp.dump_stdout();
-    $interp.capture_stdout(0);
 
-    # should probably be write()
-    $r.puts($buf);
+    # tie I/O to $r, saving the old filehandles
+    my $mpi = ::ModParrot::Interpreter.new();
+    my $stdin = $mpi.stdin($r);
+    my $stdout = $mpi.stdout($r);
+    $*IN := $mpi.stdin;
+    $*OUT := $mpi.stdout;
+
+    # run our code
+    #::($mod)::_handler();
+    my $res = ModPerl6::Fudge::call_sub_with_namespace($mod, 'reg__handler');
+
+    # restore I/O filehandles
+    $mpi.stdin($stdin);
+    $mpi.stdout($stdout);
+    $*IN := $stdin;
+    $*OUT := $stdout;
 
-    return 0;
+    return $Apache::Const::OK;
 }

Modified: mod_parrot/branches/configure/languages/perl6/lib/mod_perl6.pm
==============================================================================
--- mod_parrot/branches/configure/languages/perl6/lib/mod_perl6.pm	(original)
+++ mod_parrot/branches/configure/languages/perl6/lib/mod_perl6.pm	Sat May  2 06:55:00 2009
@@ -17,8 +17,23 @@
 module ModParrot::HLL::perl6;
 
 use v6;
+use ModParrot::Const;
+use Apache::Const;
+
+# for perl 6 functionality not yet supported by rakudo
+use ModPerl6::Fudge;
 
 our %loaded_modules;
+our %valid_options = <
+    enable
+    parseheaders
+>.map({($_,1)});
+our @server_phases = <open_logs post_config child_init pre_connection
+     process_connection post_read_request map_to_storage>;
+# XXX workaround parsing bug w/ 8 elements
+@server_phases.push('trans'); 
+our @dir_phases = <header_parser access authen authz response type fixup log
+         cleanup>;
 
 sub load($handler)
 {
@@ -28,11 +43,387 @@
     }
 }
 
-sub handler($ctx, $handler)
+sub server_create($parms)
+{
+    my %cfg;
+
+    # preloading
+    %cfg<preloaded_modules> = [];
+    %cfg<postconfig_requires> = [];
+
+    # server-scope config
+    # XXX we shouldn't need to prepopulate these, but things segfault otherwise
+    for @server_phases.map({$_ ~ '_handler'}) -> $h {
+        %cfg{$h} = undef;
+    }
+
+    return %cfg;
+}
+
+sub dir_create($parms)
+{
+    my %cfg;
+
+    # section-scope config
+    # XXX we shouldn't need to prepopulate these, but things segfault otherwise
+    for @dir_phases.map({$_ ~ '_handler'}) -> $h {
+        %cfg{$h} = undef;
+    }
+
+    # options set with Perl6Options
+    %cfg<options> = {
+        parseheaders => False,
+    };
+
+    return %cfg;
+}
+
+sub server_merge(%base, %new)
+{
+    my %merged;
+
+    # XXX what to do with preloaded modules & postconfig requires???
+
+    # merge handlers -- never inherit
+    for @server_phases.map({$_ ~ '_handler'}) -> $h {
+        %merged{$h} = %new{$h};
+    }
+
+    return %merged;
+}
+
+sub dir_merge(%base, %new)
+{
+    my %merged;
+
+    # merge options -- inherit only if not set
+    %merged<options> = {};
+    for %valid_options.keys -> $k {
+        %merged<options>{$k} = %new<options>.exists($k) ??
+            %new<options>{$k} !! %base<options>{$k};
+    }
+
+    # merge handlers -- never inherit
+    for @dir_phases.map({$_ ~ '_handler'}) -> $h {
+        %merged{$h} = %new{$h};
+    }
+
+    return %merged;
+}
+
+# XXX should cache the handler form during configuration
+sub call_handler($handler, *@args)
+{
+    my $res;
+
+    return $Apache::Const::DECLINED unless defined($handler);
+
+    # resolve a method handler
+    my ($class, $method) = split('.', $handler);
+    # i'd like to run this later with the other forms, but the calling
+    # conventions are different for methods so just run it here
+    if ($method) {
+        load($class);
+        # XXX unfudge when namespace interpolation works
+        $res = ModPerl6::Fudge::call_class_method($class, $method, |@args);
+        return $res;
+    }
+
+    # resolve a literal $handler()
+    # do this first so we don't load() until we need to
+    my @names = split('::', $handler);
+    my $subname = @names.pop;
+    my $ns = join('::', @names);
+
+    # XXX unfudge when namespace interpolation works
+    # resolve_sub MUST return a failure if name exists but it's not a sub
+    my $sub = ModPerl6::Fudge::resolve_sub($ns, $subname);
+
+    unless ($sub.defined) {
+        # load $handler and try $handler::handler() (common convention)
+        load($handler);
+        # XXX unfudge when namespace interpolation works
+        $sub = ModPerl6::Fudge::resolve_sub($handler, 'handler');
+    }
+
+    # everything falls down to this block -- run the handler
+    if ($sub.defined) {
+        $res = $sub(|@args);
+        return $res;
+    }
+    else { 
+        # nothing worked -- return an error
+        # XXX should also log something here
+        $res = $Apache::Const::HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    return $Apache::Const::HTTP_INTERNAL_SERVER_ERROR;
+}
+ 
+sub header_parser_handler($ctx)
+{
+    my $r = $ctx.request_rec();
+    my %cfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    my %dircfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module",
+        $r.per_dir_config());
+
+    # first phase that has a dir config, so register any cleanup handlers
+    if (%dircfg<cleanup_handler>) {
+        $r.pool.cleanup_register(&cleanup_handler, %dircfg<cleanup_handler>);
+    }
+
+    # back to the post_read_request handler
+    my $handler = %dircfg<header_parser_handler>;
+    unless ($handler) {
+        return $Apache::Const::OK;
+    }
+
+    my $status = call_handler($handler, $r);
+    return $status;
+}
+
+sub response_handler($ctx)
 {
     my $r = $ctx.request_rec();
-    load($handler);
-    my $status = ::($handler)::handler($r);
-    # return $status;
-    $status;
+
+    unless ($r.handler() ~~ any(<modperl6 perl6-script>)) {
+        return $Apache::Const::DECLINED;
+    }
+
+    my %cfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    my %dircfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module",
+        $r.per_dir_config());
+
+    my $handler = %dircfg<response_handler>;
+
+    $r.content_type('text/html');
+    my $status = call_handler($handler, $r);
+    return $status;
+}
+
+sub open_logs_handler($ctx)
+{
+    return $Apache::Const::OK;
+}
+
+sub post_config_handler($ctx)
+{
+    my $conf_pool = $ctx.conf_pool();
+    my $log_pool = $ctx.log_pool();
+    my $temp_pool = $ctx.temp_pool();
+
+    # XXX uncomment when server_rec is implemented
+    #my $s = $ctx.server_rec();
+    my $s = undef;
+
+    my %cfg = ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+
+    # preload modules
+    # NOTE: Perl6Module is a directory scope directive
+    for %cfg<preloaded_modules>.values -> $m {
+        use $m;
+    }
+
+    # load postconfig requires
+    for %cfg<postconfig_requires>.values -> $r {
+        require $r;
+    }
+
+    my $handler = %cfg<post_config_handler>;
+    unless ($handler) {
+        return $Apache::Const::OK;
+    }
+
+    # run the postconfig handler
+    my $status = call_handler($handler, $conf_pool, $log_pool, $temp_pool, $s);
+    return $status;
+}
+
+sub cleanup_handler($handler)
+{
+    my $status = call_handler($handler);
+    return $status;
+}
+
+sub cmd_perl6openlogshandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<open_logs_handler> = @args[0];
+}
+
+sub cmd_perl6postconfighandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<post_config_handler> = @args[0];
+}
+
+sub cmd_perl6childinithandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<child_init_handler> = @args[0];
+}
+
+sub cmd_perl6preconnectionhandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<pre_connection_handler> = @args[0];
+}
+
+sub cmd_perl6processconnectionhandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<process_connection_handler> = @args[0];
+}
+
+sub cmd_perl6postreadrequesthandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<post_read_request_handler> = @args[0];
+}
+
+sub cmd_perl6maptostoragehandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<map_to_storage_handler> = @args[0];
+}
+
+sub cmd_perl6transhandler($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    %cfg<trans_handler> = @args[0];
+}
+
+sub cmd_perl6headerparserhandler($parms, %dircfg, @args)
+{
+    %dircfg<header_parser_handler> = @args[0];
+}
+
+sub cmd_perl6accesshandler($parms, %dircfg, @args)
+{
+    %dircfg<access_handler> = @args[0];
 }
+
+sub cmd_perl6authenhandler($parms, %dircfg, @args)
+{
+    %dircfg<authen_handler> = @args[0];
+}
+
+sub cmd_perl6authzhandler($parms, %dircfg, @args)
+{
+    %dircfg<authz_handler> = @args[0];
+}
+
+sub cmd_perl6responsehandler($parms, %dircfg, @args)
+{
+    %dircfg<response_handler> = @args[0];
+}
+
+sub cmd_perl6typehandler($parms, %dircfg, @args)
+{
+    %dircfg<type_handler> = @args[0];
+}
+
+sub cmd_perl6fixuphandler($parms, %dircfg, @args)
+{
+    %dircfg<fixup_handler> = @args[0];
+}
+
+sub cmd_perl6loghandler($parms, %dircfg, @args)
+{
+    %dircfg<log_handler> = @args[0];
+}
+
+sub cmd_perl6cleanuphandler($parms, %dircfg, @args)
+{
+    %dircfg<cleanup_handler> = @args[0];
+}
+
+sub cmd_perl6cleanuphandler($parms, %dircfg, @args)
+{
+    %dircfg<cleanup_handler> = @args[0];
+} 
+
+sub cmd_perl6module($parms, %mconfig, @args)
+{
+    my %cfg := ModParrot::Apache::Module::get_config("modparrot_perl6_module");
+    push(%cfg<preloaded_modules>, @args[0]);
+}
+
+sub cmd_perl6options($parms, %mconfig, @args)
+{
+    if (@args[0] ~~ /(\+|\-)(.+)/) {
+        my $modifier = ~$0;
+        my $option = (~$1).lc;
+        my $val = ($modifier eq '+');
+	if (%valid_options{$option}) {
+                %mconfig<options>{$option} = $val; 
+        }
+        else {
+            default { die "invalid option '$option'"; }
+        }
+    }
+    else {
+        die "missing modifier prefix (+ or -)";
+    }
+}
+
+# register configuration directives
+my @cmds = (
+    {
+        'name' => 'Perl6Options',
+        'args_how' => $Apache::Const::ITERATE,
+        'func' => &cmd_perl6options,
+        'req_override' => $Apache::Const::OR_ALL,
+        'errmsg' => 'usage: Perl6Options [+/-]option ...'
+    },
+    {
+        'name' => 'Perl6Module',
+        'args_how' => $Apache::Const::TAKE1,
+        'func' => &cmd_perl6module,
+        'req_override' => $Apache::Const::OR_ALL,
+        'errmsg' => 'usage: Perl6Module module'
+    },
+    {
+        'name' => 'Perl6PostConfigHandler',
+        'args_how' => $Apache::Const::TAKE1,
+        'func' => &cmd_perl6postconfighandler,
+        'req_override' => $Apache::Const::RSRC_CONF,
+        'errmsg' => 'usage: Perl6PostConfigHandler handler-name'
+    },
+    {
+        'name' => 'Perl6ResponseHandler',
+        'args_how' => $Apache::Const::TAKE1,
+        'func' => &cmd_perl6responsehandler,
+        'req_override' => $Apache::Const::OR_AUTHCFG,
+        'errmsg' => 'usage: Perl6ResponseHandler handler-name'
+    },
+    {
+        'name' => 'Perl6HeaderParserHandler',
+        'args_how' => $Apache::Const::TAKE1,
+        'func' => &cmd_perl6headerparserhandler,
+        'req_override' => $Apache::Const::OR_AUTHCFG,
+        'errmsg' => 'usage: Perl6HeaderParserHandler handler-name'
+    },
+    {
+        'name' => 'Perl6CleanupHandler',
+        'args_how' => $Apache::Const::TAKE1,
+        'func' => &cmd_perl6cleanuphandler,
+        'req_override' => $Apache::Const::OR_AUTHCFG,
+        'errmsg' => 'usage: Perl6CleanupHandler handler-name'
+    }
+);
+
+# register hooks
+my @hooks = (
+    $ModParrot::Const::MP_HOOK_OPEN_LOGS,
+    $ModParrot::Const::MP_HOOK_POST_CONFIG,
+    $ModParrot::Const::MP_HOOK_HEADER_PARSER,
+    $ModParrot::Const::MP_HOOK_RESPONSE
+);
+
+ModParrot::Apache::Module::add(
+    'modparrot_perl6_module',
+    'perl6',
+    @cmds,
+    @hooks
+);

Modified: mod_parrot/branches/configure/lib/ModParrot/Context.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/Context.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/Context.pir	Sat May  2 06:55:00 2009
@@ -73,29 +73,99 @@
 .sub request_rec :method
     .local pmc r
 
-    $P0 = new [ 'Apache'; 'RequestRec' ]
+    $P0 = new [ 'ModParrot'; 'Apache'; 'RequestRec' ]
 
     .return($P0)
 .end
 
 =back
 
-=head1 TODO
-
-=over 4
+=item conf_pool
 
-=item server_rec
+=cut
 
-=item conn_rec
+.sub conf_pool :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'conf_pool'
+    $P1 = new 'Hash'
+    $P1['apr_pool'] = $P0
+    $P2 = new [ 'ModParrot'; 'APR'; 'Pool' ], $P1
+    .return($P2)
+.end
 
-=item request_pool
+=item log_pool
 
-=item conf_pool
+=cut
 
-=item log_pool
+.sub log_pool :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'log_pool'
+    $P1 = new 'Hash'
+    $P1['apr_pool'] = $P0
+    $P2 = new [ 'ModParrot'; 'APR'; 'Pool' ], $P1
+    .return($P2)
+.end
 
 =item temp_pool
 
+=cut
+
+.sub temp_pool :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'temp_pool'
+    $P1 = new 'Hash'
+    $P1['apr_pool'] = $P0
+    $P2 = new [ 'ModParrot'; 'APR'; 'Pool' ], $P1
+    .return($P2)
+.end
+
+=item child_pool
+
+=cut
+
+.sub child_pool :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'child_pool'
+    $P1 = new 'Hash'
+    $P1['apr_pool'] = $P0
+    $P2 = new [ 'ModParrot'; 'APR'; 'Pool' ], $P1
+    .return($P2)
+.end
+
+=item raw_srv_config
+
+=cut
+
+.sub raw_srv_config :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'raw_srv_config'
+    $P1 = $P0()
+    .return($P1)
+.end
+
+=item raw_dir_config
+
+=cut
+
+.sub raw_dir_config :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'raw_dir_config'
+    $P1 = $P0()
+    .return($P1)
+.end
+
+=item ctx_pool_name
+
+=cut
+
+.sub pool_name :method
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'ctx_pool_name'
+    $S0 = $P0()
+    .return($S0)
+.end
+
+=head1 TODO
+
+=over 4
+
+=item server_rec
+
+=item conn_rec
+
 =back
 
 =head1 AUTHOR

Modified: mod_parrot/branches/configure/lib/ModParrot/HLL/lolcode.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/HLL/lolcode.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/HLL/lolcode.pir	Sat May  2 06:55:00 2009
@@ -17,10 +17,26 @@
 .namespace [ 'ModParrot'; 'HLL'; 'lolcode' ]
 
 .sub __onload :anon :load
+    .local pmc add_module, cmds, hooks, mp_const
+
     load_bytecode 'languages/lolcode/lolcode.pbc'
     load_bytecode 'CGI/QueryHash.pbc'
+    load_bytecode 'ModParrot/Apache/RequestRec.pbc'
+    load_bytecode 'ModParrot/Apache/Module.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
+
     $P0 = new 'Hash'
     set_hll_global 'lolcode_registry', $P0
+
+    # we have no directives, so this will remain empty
+    cmds = new 'ResizablePMCArray'
+
+    hooks = new 'ResizablePMCArray'
+    mp_const = get_root_global [ 'ModParrot'; 'Constants' ], 'table'
+    $I0 = mp_const['MP_HOOK_RESPONSE']
+    hooks[0] = $I0
+    add_module = get_hll_global [ 'ModParrot'; 'Apache'; 'Module' ], 'add'
+    $P1 = add_module("modparrot_lolcode_module", "lolcode", cmds, hooks)
 .end
 
 .sub load
@@ -31,8 +47,8 @@
     registry = get_hll_global 'lolcode_registry'
     $I0 = exists registry[file]
     if $I0 goto load_from_registry
-    $P0 = open file, '<'
-    source = $P0.'slurp'(0)
+    $P0 = open file, 'r'
+    source = $P0.'readall'()
     close $P0
     $P1 = compreg 'lolcode'
     $P2 = $P1.'compile'(source)
@@ -44,18 +60,15 @@
     .return($P2)
 .end
 
-#.sub config
-
 # response handler
-.sub handler
+.sub response_handler
     .param pmc ctx
-    .param pmc handler_name
     .local string script_path
     .local string output
     .local string key
     .local pmc r
     .local pmc ap_const
-    .local pmc interp
+    .local pmc interp, oldin, oldout
     .local pmc code
     .local pmc query_parse
     .local pmc query
@@ -63,17 +76,29 @@
     .local int status
 
     # get apache constants
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # is this LOLCODE?
+    $S0 = r.'handler'()
+    if $S0 == 'application/x-httpd-lolcode' goto have_lolcode
+    status = ap_const['DECLINED']
+    .return(status)
+
+  have_lolcode:
     # get the interpreter object
     interp = ctx.'interp'()
-    script_path = r.'filename'()
 
+    # tie I/O to the request
+    oldout = interp.'stdout'(r)
+    oldin = interp.'stdin'(r)
+
+    # load the code
+    script_path = r.'filename'()
     push_eh report_error
-        code = load(script_path)
+    code = load(script_path)
     pop_eh
 
     # set default content type
@@ -103,17 +128,15 @@
     goto query_loop
   query_loop_end:
 
-    interp.'capture_stdout'(1)
+    r.'content_type'("text/html")
     push_eh report_error
-        status = code()
+    code()
     pop_eh
-    output = interp.'dump_stdout'()
-    interp.'capture_stdout'(0)
-    r.'puts'(output)
-    status = 0
+    status = ap_const['OK']
     goto return_status
 
   report_error:
+    pop_eh
     get_results '0,0', $P0, $S0
     $S1 = script_path
     concat $S1, ": "
@@ -123,6 +146,9 @@
     status = ap_const['HTTP_INTERNAL_SERVER_ERROR']
 
   return_status:
+    # restore filehandles
+    interp.'stdout'(oldout)
+    interp.'stdin'(oldin)
     # return status code
     .return(status)
 .end

Modified: mod_parrot/branches/configure/lib/ModParrot/HLL/perl6.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/HLL/perl6.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/HLL/perl6.pir	Sat May  2 06:55:00 2009
@@ -15,69 +15,14 @@
 # limitations under the License.
 
 .sub __onload :anon :load
-    .local string mp6_path
-    .local pmc find_file_in_path
+    load_bytecode 'languages/rakudo/perl6.pbc'
 
-    load_bytecode 'languages/perl6/perl6.pbc'
-
-    $P0 = new 'Env'
-    $S0 = $P0['PERL6LIB']
-    find_file_in_path = get_hll_global ['_modparrot'], 'find_file_in_path'
-    mp6_path = find_file_in_path($S0, 'mod_perl6.pm')
+    # load mod_perl6.pm, which may be precompiled
     $P0 = compreg 'Perl6'
-    $P1 = $P0.'evalfiles'(mp6_path)
-
-    # register mod_parrot classes as Perl6 meta classes so Perl 6 can access
-    # them natively
-    $P0 = get_hll_global 'P6metaclass'
-    $P1 = get_class ['Apache'; 'RequestRec']
-    $P0.'register'($P1)
-    $P1 = get_class ['APR'; 'Table']
-    $P0.'register'($P1)
-    $P1 = get_class ['ModParrot'; 'Interpreter']
-    $P0.'register'($P1)
-    $P1 = get_class ['ModParrot'; 'Context']
-    $P0.'register'($P1)
-
-    # register apache directives
-    .local pmc add_module, cmds
-
-    load_bytecode 'Apache/Module.pbc'
-
-    cmds = new 'Array'
-    cmds = 1
-    $P0 = new 'Hash'
-
-    $P1 = new 'String'
-    $P1 = 'Perl6ResponseHandler'
-    $P0['name'] = $P1
-    $P1 = new 'Integer'
-    $P1 = 1 # TAKE1
-    $P0['args_how'] = $P1
-    $P1 = get_hll_global 'cmd_perl6responsehandler'
-    $P0['func'] = $P1
-    $P1 = new 'Integer'
-    $P1 = 8 # OR_AUTHCFG
-    $P0['req_override'] = $P1
-    $P1 = new 'String'
-    $P1 = "usage: Perl6ResponseHandler handler-name"
-    $P0['errmsg'] = $P1
-    cmds[0] = $P0
-
-    add_module = get_hll_global [ 'Apache'; 'Module' ], 'add'
-    $P1 = add_module("modparrot_perl6_module", cmds)
-.end
-
-.sub cmd_perl6responsehandler
-    .param pmc args
-    .local string handler
-    handler = args[0]
-    $P0 = get_hll_global ['Apache'; 'Module'], 'modparrot_dircfg_handler'
-    $P1 = $P0('perl6', handler)
+    $P1 = $P0.'compile'('use mod_perl6')
+    $P1()
 .end
 
 # declare namespace AFTER loading compiler
 # otherwise we get method resolution errors
 .namespace [ 'ModParrot'; 'HLL'; 'perl6' ]
-
-# helper functions go here

Modified: mod_parrot/branches/configure/lib/ModParrot/HLL/pipp.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/HLL/pipp.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/HLL/pipp.pir	Sat May  2 06:55:00 2009
@@ -19,6 +19,22 @@
 .sub __onload :anon :load
     load_bytecode 'languages/pipp/pipp.pbc'
     load_bytecode 'CGI/QueryHash.pbc'
+    load_bytecode 'ModParrot/Apache/RequestRec.pbc'
+    load_bytecode 'ModParrot/Apache/Module.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
+
+    .local pmc add_module, cmds, hooks, mp_const
+
+    mp_const = get_root_global [ 'ModParrot'; 'Constants' ], 'table'
+
+    # we have no directives, so this will remain empty
+    cmds = new 'ResizablePMCArray'
+
+    hooks = new 'ResizablePMCArray'
+    $I0 = mp_const['MP_HOOK_RESPONSE']
+    hooks[0] = $I0
+    add_module = get_hll_global [ 'ModParrot'; 'Apache'; 'Module' ], 'add'
+    $P1 = add_module("modparrot_pipp_module", "pipp", cmds, hooks)
 .end
 
 .sub run_php_file
@@ -30,44 +46,65 @@
     .return($P1)
 .end
 
-#.sub config
-
 # response handler
-.sub handler
+.sub response_handler
     .param pmc ctx
-    .param string php_file
+    .local string php_file
     .local pmc r
     .local pmc ap_const
-    .local string args
+    .local string args, data
     .local int status
     .local pmc query_parse
     .local pmc get_hash, post_hash
-    .local pmc interp
+    .local pmc interp, oldin, oldout, newin, newout
+
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # is this PHP?
+    $S0 = r.'handler'()
+    if $S0 == 'application/x-httpd-php' goto have_php
+    status = ap_const['DECLINED']
+    .return(status)
+
+  have_php:
     # get the interpreter object
     interp = ctx.'interp'()
 
-    # parse query string
+    # parse query string (do this regardless of method)
     args = r.'args'()
     query_parse = get_hll_global [ 'CGI'; 'QueryHash' ], 'parse'
     get_hash = new 'Hash'
     get_hash = query_parse(args)
-    set_hll_global '$_GET', get_hash
+    set_root_global ['pipp'], '$_GET', get_hash
+
+    # parse POST data
+    $S0 = r.'method'()
+    unless $S0 == 'POST' goto run_script
+    $I0 = 0
+    $I1 = 8192
+    $P0 = new 'String'
+    $P1 = new 'String'
+  post_read_loop:
+    $I0 = r.'read'($P0, $I1)
+    $P1 .= $P0
+    if $I0 == $I1 goto post_read_loop
+    data = $P1
+    post_hash = new 'Hash'
+    post_hash = query_parse(data)
+    set_root_global ['pipp'], '$_POST', post_hash
     
+  run_script:
     php_file = r.'filename'()
-    interp.'capture_stdout'(1)
-    run_php_file(php_file)
+    oldout = interp.'stdout'(r)
+    oldin = interp.'stdin'(r)
     r.'content_type'("text/html")
+    run_php_file(php_file)
+    interp.'stdout'(oldout)
+    interp.'stdin'(oldin)
 
-    $S0 = interp.'dump_stdout'()
-    interp.'capture_stdout'(0)
-    r.'puts'($S0)
-
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
     status = ap_const['OK']
-
     .return(status)
 .end

Modified: mod_parrot/branches/configure/lib/ModParrot/HLL/pir.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/HLL/pir.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/HLL/pir.pir	Sat May  2 06:55:00 2009
@@ -14,47 +14,376 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+.sub __onload :anon :load
+    load_bytecode 'ModParrot/Apache/Module.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
+
+    # register apache directives
+    .local pmc add_module, cmds, hooks, mp_const
+
+    mp_const = get_root_global [ 'ModParrot'; 'Constants' ], 'table'
+
+    cmds = new 'ResizablePMCArray'
+
+    $P0 = new_cmd('ParrotInterp', 'TAKE1', 'cmd_parrotinterp', 'RSRC_CONF', 'usage: ParrotInterp pool-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotOpenLogsHandler', 'TAKE1', 'cmd_parrotopenlogshandler', 'RSRC_CONF', 'usage: ParrotOpenLogsHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotPostConfigHandler', 'TAKE1', 'cmd_parrotpostconfighandler', 'RSRC_CONF', 'usage: ParrotPostConfigHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotChildInitHandler', 'TAKE1', 'cmd_parrotchildinithandler', 'RSRC_CONF', 'usage: ParrotChildInitHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotPreConnectionHandler', 'TAKE1', 'cmd_parrotpreconnectionhandler', 'RSRC_CONF', 'usage: ParrotPreConnectionHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotProcessConnectionHandler', 'TAKE1', 'cmd_parrotprocessconnectionhandler', 'RSRC_CONF', 'usage: ParrotProcessConnectionHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotMapToStorageHandler', 'TAKE1', 'cmd_parrotmaptostoragehandler', 'OR_AUTHCFG', 'usage: ParrotMapToStorageHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotTransHandler', 'TAKE1', 'cmd_parrottranshandler', 'OR_AUTHCFG', 'usage: ParrotTransHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotPostReadRequestHandler', 'TAKE1', 'cmd_parrotpostreadrequesthandler', 'OR_AUTHCFG', 'usage: ParrotPostReadRequestHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotHeaderParserHandler', 'TAKE1', 'cmd_parrotheaderparserhandler', 'OR_AUTHCFG', 'usage: ParrotHeaderParserHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotAccessHandler', 'TAKE1', 'cmd_parrotaccesshandler', 'OR_AUTHCFG', 'usage: ParrotAccessHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotAuthenHandler', 'TAKE1', 'cmd_parrotauthenhandler', 'OR_AUTHCFG', 'usage: ParrotAuthenHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotAuthzHandler', 'TAKE1', 'cmd_parrotauthzhandler', 'OR_AUTHCFG', 'usage: ParrotAuthzHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotResponseHandler', 'TAKE1', 'cmd_parrothandler', 'OR_AUTHCFG', 'usage: ParrotResponseHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotHandler', 'TAKE1', 'cmd_parrothandler', 'OR_AUTHCFG', 'usage: ParrotHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotTypeHandler', 'TAKE1', 'cmd_parrottypehandler', 'OR_AUTHCFG', 'usage: ParrotTypeHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotFixupHandler', 'TAKE1', 'cmd_parrotfixuphandler', 'OR_AUTHCFG', 'usage: ParrotFixupHandler handler-name')
+    cmds.'push'($P0)
+    $P0 = new_cmd('ParrotLogHandler', 'TAKE1', 'cmd_parrotloghandler', 'OR_AUTHCFG', 'usage: ParrotlogHandler handler-name')
+    cmds.'push'($P0)
+
+    # we want *all* the hooks
+    hooks = new 'ResizablePMCArray'
+    $I0 = mp_const['MP_HOOK_ALL']
+    hooks[0] = $I0 
+    add_module = get_hll_global [ 'ModParrot'; 'Apache'; 'Module' ], 'add'
+    $P1 = add_module("modparrot_pir_module", "PIR", cmds, hooks)
+.end
+
+.sub new_cmd
+    .param string name
+    .param string how
+    .param string func
+    .param string override
+    .param string errmsg
+    .local pmc ap_const
+    .local pmc cmd
+
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+    
+    cmd = new 'Hash'
+    $P0 = new 'String'
+    $P0 = name
+    cmd['name'] = $P0
+    $P0 = new 'Integer'
+    $P0 = ap_const[how]
+    cmd['args_how'] = $P0
+    $P0 = get_hll_global [ 'ModParrot'; 'HLL'; 'PIR' ], func 
+    cmd['func'] = $P0
+    $P0 = new 'Integer'
+    $P0 = ap_const[override]
+    cmd['req_override'] = $P0
+    $P0 = new 'String'
+    $P0 = errmsg
+    cmd['errmsg'] = $P0
+
+    .return(cmd)
+.end
+    
 .namespace [ 'ModParrot'; 'HLL'; 'PIR' ]
 
+.sub server_create
+    .param pmc parms
+    $P0 = new 'Hash'
+    .return($P0)
+.end
+
+.sub dir_create
+    .param pmc parms
+    $P0 = new 'Hash'
+    .return($P0)
+.end
+
+# XXX implement merging
+
+#.sub server_merge
+#.end
+
+.sub dir_merge
+    .param pmc basecfg
+    .param pmc newcfg
+
+    .return(newcfg)
+.end
+
+.sub cmd_parrotinterp
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+    .local pmc ctx, cfg, set_pool
+
+    ctx = new ['ModParrot'; 'Context']
+    cfg = ctx.'raw_srv_config'()
+    set_pool = get_root_global ['ModParrot'; 'NCI'], 'set_config_ctx_pool'
+    $S0 = args[0]
+    set_pool(cfg, $S0)
+.end
+
+.sub cmd_parrotopenlogshandler
+    .param pmc parms
+    .param pmc mconfig
+    .param pmc args
+    .local pmc cfg, get_config
+
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $S0 = args[0]
+    cfg['open_logs_handler'] = $S0
+.end
+
+.sub cmd_parrotpostconfighandler
+    .param pmc parms
+    .param pmc mconfig
+    .param pmc args
+    .local pmc cfg, get_config
+
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $S0 = args[0]
+    cfg['post_config_handler'] = $S0
+.end
+
+.sub cmd_parrotchildinithandler
+    .param pmc parms
+    .param pmc mconfig
+    .param pmc args
+    .local pmc cfg, get_config
+
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $S0 = args[0]
+    cfg['child_init_handler'] = $S0
+.end
+
+.sub cmd_parrotpreconnectionhandler
+    .param pmc parms
+    .param pmc mconfig
+    .param pmc args
+    .local pmc cfg, get_config
+
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $S0 = args[0]
+    cfg['pre_connection_handler'] = $S0
+.end
+
+.sub cmd_parrotprocessconnectionhandler
+    .param pmc parms
+    .param pmc mconfig
+    .param pmc args
+    .local pmc cfg, get_config
+
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $S0 = args[0]
+    cfg['process_connection_handler'] = $S0
+.end
+
+.sub cmd_parrotmaptostoragehandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['map_to_storage_handler'] = $S0
+.end
+
+.sub cmd_parrottranshandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['trans_handler'] = $S0
+.end
+
+.sub cmd_parrotpostreadrequesthandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['post_read_request_handler'] = $S0
+.end
+
+.sub cmd_parrotheaderparserhandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['header_parser_handler'] = $S0
+.end
+
+.sub cmd_parrotauthenhandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['authen_handler'] = $S0
+.end
+
+.sub cmd_parrotauthzhandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['authz_handler'] = $S0
+.end
+
+.sub cmd_parrotaccesshandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['access_handler'] = $S0
+.end
+
+.sub cmd_parrothandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['response_handler'] = $S0
+.end
+
+.sub cmd_parrottypehandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['type_handler'] = $S0
+.end
+
+.sub cmd_parrotfixuphandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['fixup_handler'] = $S0
+.end
+
+.sub cmd_parrotloghandler
+    .param pmc parms
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['log_handler'] = $S0
+.end
+
 .sub load
     .param string path
     load_bytecode path
 .end
 
-#.sub config
-
 # response handler
-.sub handler
+.sub response_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # decline if not our handler
+    $S0 = r.'handler'()
+    if $S0 == 'parrot-code' goto get_configs
+    status = ap_const['DECLINED']
+    goto return_status
+
+  get_configs:
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['response_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
+    # set our default content type
+    r.'content_type'('text/html')
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
-    # return status code
+  return_status:
     .return(status)
 .end
 
 # authen handler
 .sub authen_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['authen_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
     status = handler(r)
 
     # return status code
@@ -64,16 +393,36 @@
 # authz handler
 .sub authz_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['authz_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -83,16 +432,36 @@
 # access handler
 .sub access_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['access_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -102,29 +471,37 @@
 # open logs handler
 .sub open_logs_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc pconf
-    .local pmc plog
-    .local pmc ptemp
-    .local pmc s
-    .local pmc handler
-    .local pmc func
+    .local pmc s, handler, cfg, get_config, ap_const, pconf, plog, ptemp, s
+    .local pmc pconf, plog, ptemp
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+
+    # decline if we have no handler in this section
+    $S0 = cfg['open_logs_handler']
+    if $S0 goto run_handler
+    # open_logs handlers must return OK
+    status = ap_const['OK']
+    .return(status)
+
+  run_handler:
+    # find the handler sub and call it
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
     # get the pool objects
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'conf_pool'
-    pconf = func()
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'log_pool'
-    plog = func()
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'temp_pool'
-    ptemp = func()
+    pconf = ctx.'conf_pool'()
+    plog = ctx.'log_pool'()
+    ptemp = ctx.'temp_pool'()
 
     # get the server_rec object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'server_rec'
-    s = func()
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'server_rec'
+    s = $P0()
 
-    # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
     status = handler(pconf, plog, ptemp, s)
 
     # return status code
@@ -134,29 +511,36 @@
 # post_config handler
 .sub post_config_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc pconf
-    .local pmc plog
-    .local pmc ptemp
-    .local pmc s
-    .local pmc handler
-    .local pmc func
+    .local pmc s, handler, cfg, get_config, ap_const, pconf, plog, ptemp, s
+    .local pmc pconf, plog, ptemp
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+
+    # decline if we have no handler in this section
+    $S0 = cfg['post_config_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
+    # find the handler sub and call it
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
     # get the pool objects
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'conf_pool'
-    pconf = func()
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'log_pool'
-    plog = func()
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'temp_pool'
-    ptemp = func()
+    pconf = ctx.'conf_pool'()
+    plog = ctx.'log_pool'()
+    ptemp = ctx.'temp_pool'()
 
     # get the server_rec object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'server_rec'
-    s = func()
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'server_rec'
+    s = $P0()
 
-    # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
     status = handler(pconf, plog, ptemp, s)
 
     # return status code
@@ -166,23 +550,34 @@
 # child init handler
 .sub child_init_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc pchild
-    .local pmc s
-    .local pmc handler
-    .local pmc func
+    .local pmc s, handler, cfg, get_config, ap_const, pchild, s
+    .local pmc pconf, plog, ptemp
     .local int status
 
-    # get the pool object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'child_pool'
-    pchild = func()
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
 
-    # get the server_rec object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'server_rec'
-    s = func()
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
 
+    # decline if we have no handler in this section
+    $S0 = cfg['child_init_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
+    # get the pool objects
+    pchild = ctx.'child_pool'()
+
+    # get the server_rec object
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'server_rec'
+    s = $P0()
+
     status = handler(pchild, s)
 
     # return status code
@@ -192,23 +587,34 @@
 # pre connection handler
 .sub pre_connection_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc c
-    .local pmc csd
-    .local pmc handler
-    .local pmc func
+    .local pmc s, handler, cfg, get_config, ap_const, c, csd
+    .local pmc pconf, plog, ptemp
     .local int status
 
-    # get the conn_rec object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'conn_rec'
-    c = func()
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
 
-    # get the csd object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'csd'
-    csd = func()
+    # decline if we have no handler in this section
+    $S0 = cfg['pre_connection_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
 
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
+    # get the pool objects
+    # XXX need access to these from the context!
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'conn_rec'
+    c = $P0()
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'csd'
+    csd = $P0()
+
     status = handler(c, csd)
 
     # return status code
@@ -218,38 +624,72 @@
 # process connection handler
 .sub process_connection_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc c
-    .local pmc handler
-    .local pmc func
+    .local pmc s, handler, cfg, get_config, ap_const, c
+    .local pmc pconf, plog, ptemp
     .local int status
 
-    # get the pool object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'conn_rec'
-    c = func()
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+
+    # decline if we have no handler in this section
+    $S0 = cfg['process_connection_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
+
+    # get the pool objects
+    # XXX need access to these from the context!
+    $P0 = get_root_global [ 'ModParrot'; 'NCI' ], 'conn_rec'
+    c = $P0()
+
     status = handler(c)
 
     # return status code
     .return(status)
+
 .end
 
 # trans handler
 .sub trans_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['trans_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -259,17 +699,36 @@
 # fixup handler
 .sub fixup_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['fixup_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -279,17 +738,36 @@
 # type handler
 .sub type_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['type_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -299,17 +777,36 @@
 # log handler
 .sub log_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['log_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -319,17 +816,36 @@
 # map_to_storage handler
 .sub map_to_storage_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['map_to_storage_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
@@ -339,55 +855,76 @@
 # post_read_request handler
 .sub post_read_request_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local pmc func
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
+
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['post_read_request_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
+
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code
     .return(status)
+
 .end
 
 # header_parser handler
 .sub header_parser_handler
     .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
+    .local pmc r, handler, cfg, dircfg, get_config, ap_const
     .local int status
 
+    ap_const = get_root_global ['ModParrot'; 'Apache'; 'Constants'], 'table'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
-    # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
-    status = handler(r)
+    # get configs
+    get_config = get_hll_global ['ModParrot'; 'Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
+    $P0 = r.'per_dir_config'()
+    dircfg = get_config('modparrot_pir_module', $P0)
 
-    # return status code
+    # decline if we have no config in this section
+    unless null dircfg goto get_handler
+    status = ap_const['DECLINED']
     .return(status)
-.end
-
-# cleanup handler
-.sub cleanup_handler
-    .param pmc ctx
-    .param string handler_name
-    .local pmc r
-    .local pmc handler
-    .local int status
 
-    # get the request_rec object
-    r = ctx.'request_rec'()
+  get_handler:
+    # decline if we have no handler in this section
+    $S0 = dircfg['header_parser_handler']
+    if $S0 goto run_handler
+    status = ap_const['DECLINED']
+    .return(status)
 
+  run_handler:
     # find the handler sub and call it
-    find_global handler, handler_name, 'handler'
+    $P0 = split ';', $S0
+    get_hll_global handler, $P0, 'handler'
     status = handler(r)
 
     # return status code

Modified: mod_parrot/branches/configure/lib/ModParrot/Interpreter.pir
==============================================================================
--- mod_parrot/branches/configure/lib/ModParrot/Interpreter.pir	(original)
+++ mod_parrot/branches/configure/lib/ModParrot/Interpreter.pir	Sat May  2 06:55:00 2009
@@ -140,55 +140,104 @@
     .return($S0)
 .end
 
-=item C<capture_stdout(INT flag)>
+=item C<PMC stdout(PMC handle :optional)>
 
 =over 4
 
-WARNING: This method is temporary and WILL go away.  Enables capture of
-standard output to an internal string buffer.
+With no arguments, returns the current stdout.
+
+If C<handle> is provided, this method will assign it to stdout.  If the
+C<handle> is a ModParrot;Apache;RequestRec object, a new ModParrotHandle will
+be created and tied to stdout.  FileHandles and ModParrotHandles will be
+assigned directly to stdout.  After assignment, returns the previous stdout.
 
 =back
 
 =cut
 
-.sub capture_stdout :method
-    .param int enabled
-    .local pmc pio
-
-    pio = getstdout
-    unless enabled goto disable_capture
-    push pio, "string"
+.sub stdout :method
+    .param pmc handle :optional
+    .param int got_handle :opt_flag
+    .local pmc stdout, fh
+
+    stdout = getstdout
+    unless got_handle goto done
+    $I0 = isa handle, ['ModParrot';'Apache';'RequestRec']
+    if $I0 goto have_r
+    $I0 = isa handle, ['FileHandle']
+    if $I0 goto have_filehandle
+    $I0 = isa handle, ['ModParrotHandle']
+    if $I0 goto have_modparrothandle
+    $P0 = new 'Exception'
+    $P0 = 'Cannot set stdout to an incompatible PMC'
+    throw $P0
+
+  have_r:
+    fh = new 'ModParrotHandle'
+    fh.'open'(handle, 'w')
+    fh.'setstdout'(fh)
+    goto done
+
+  have_filehandle:
+    fh = new 'ModParrotHandle'
+    fh.'setstdout'(handle)
     goto done
-  disable_capture:
-    $S0 = pop pio
+
+  have_modparrothandle:
+    handle.'setstdout'()
+
   done:
-.end
+    .return(stdout)
+.end 
 
-=item C<STRING dump_stdout(INT flag)>
+=item C<PMC stdin(PMC handle :optional)>
 
 =over 4
 
-WARNING: This method is temporary and WILL go away.  Returns the contents of
-the stdout string buffer created by C<capture_stdout()>.
+With no arguments, returns the current stdin.
+
+If C<handle> is provided, this method will assign it to stdin.  If the
+C<handle> is a ModParrot;Apache;RequestRec object, a new ModParrotHandle will
+be created and tied to stdin.  FileHandles and ModParrotHandles will be
+assigned directly to stdin.  After assignment, returns the previous stdin.
 
 =back
 
 =cut
 
-.sub dump_stdout :method
-    .local pmc pio
-    .local string buf, data
-
-    pio = getstdout
-    data = ""
-
-  read_loop:
-    buf = read pio, 4096
-    data .= buf
-    $I0 = length buf
-    if $I0 == 4096 goto read_loop
+.sub stdin :method
+    .param pmc handle :optional
+    .param int got_handle :opt_flag
+    .local pmc stdin, fh
+
+    stdin = getstdin
+    unless got_handle goto done
+    $I0 = isa handle, ['ModParrot';'Apache';'RequestRec']
+    if $I0 goto have_r
+    $I0 = isa handle, ['FileHandle']
+    if $I0 goto have_filehandle
+    $I0 = isa handle, ['ModParrotHandle']
+    if $I0 goto have_modparrothandle
+    $P0 = new 'Exception'
+    $P0 = 'Cannot set stdin to an incompatible PMC'
+    throw $P0
+
+  have_r:
+    fh = new 'ModParrotHandle'
+    fh.'open'(handle, 'r')
+    fh.'setstdin'(fh)
+    goto done
+
+  have_filehandle:
+    fh = new 'ModParrotHandle'
+    fh.'setstdin'(handle)
+    goto done
+
+  have_modparrothandle:
+    handle.'setstdin'()
 
-  .return(data)
+  done:
+    .return(stdin)
 .end
 
 =back

Modified: mod_parrot/branches/configure/lib/mod_parrot.pir
==============================================================================
--- mod_parrot/branches/configure/lib/mod_parrot.pir	(original)
+++ mod_parrot/branches/configure/lib/mod_parrot.pir	Sat May  2 06:55:00 2009
@@ -14,81 +14,180 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-.namespace [ '_modparrot' ]
+.namespace [ 'ModParrot' ]
 
 .include 'iglobals.pasm'
 
 # use when NCI can dlfunc from the current image
 .sub modparrot_init
     .local pmc func
-    .local pmc nul
+    .local pmc lib
 
-    null nul
+    null $S0
+    $P0 = get_hll_global ['_modparrot'], '__module_path'
+    if null $P0 goto do_loadlib
+    $S0 = $P0
+  do_loadlib:
+    loadlib lib, $S0
+
+    # loadlib here instead of as a pragma in case we set the dynext path
+    loadlib $P0, 'modparrot_group.so'
 
     .include "build/src/pir/request_rec_dlfunc.pir"
+    .include "build/src/pir/server_rec_dlfunc.pir"
+
+    dlfunc func, lib, "mpnci_null", "p"
+    set_root_global [ 'ModParrot'; 'NCI' ], "null", func
+
+    dlfunc func, lib, "mpnci_backtrace", "tJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "backtrace", func
+
+    dlfunc func, lib, "mpnci_request_rec", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec", func
+
+    dlfunc func, lib, "mpnci_request_rec_main", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_main", func
+
+    dlfunc func, lib, "mpnci_request_rec_next", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_next", func
+
+    dlfunc func, lib, "mpnci_request_rec_prev", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_prev", func
+
+    dlfunc func, lib, "mpnci_request_rec_user", "tJpti"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_user", func
+
+    dlfunc func, lib, "mpnci_request_rec_notes", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_notes", func
+
+    dlfunc func, lib, "mpnci_request_rec_get_basic_auth_pw", "iJpP"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_get_basic_auth_pw", func
+
+    dlfunc func, lib, "mpnci_request_rec_per_dir_config", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_per_dir_config", func
+
+    dlfunc func, lib, "mpnci_request_rec_headers_in", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_headers_in", func
+
+    dlfunc func, lib, "mpnci_request_rec_headers_out", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_headers_out", func
+
+    dlfunc func, lib, "mpnci_request_rec_err_headers_out", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_err_headers_out", func
+
+    dlfunc func, lib, "mpnci_request_rec_pool", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_pool", func
+
+    dlfunc func, lib, "mpnci_request_rec_server", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_rec_server", func
+
+    dlfunc func, lib, "mpnci_rwrite", "iJPip"
+    set_root_global [ 'ModParrot'; 'NCI' ], "rwrite", func
 
-    dlfunc func, nul, "mpnci_backtrace", "tJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "backtrace", func
+    dlfunc func, lib, "mpnci_ap_log_rerror", "vJtiiipt"
+    set_root_global [ 'ModParrot'; 'NCI' ], "ap_log_rerror", func
 
-    dlfunc func, nul, "mpnci_request_rec", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec", func
+    dlfunc func, lib, "mpnci_conf_pool", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "conf_pool", func
 
-    dlfunc func, nul, "mpnci_request_rec_main", "pJp"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_main", func
+    dlfunc func, lib, "mpnci_temp_pool", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "temp_pool", func
 
-    dlfunc func, nul, "mpnci_request_rec_next", "pJp"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_next", func
+    dlfunc func, lib, "mpnci_log_pool", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "log_pool", func
 
-    dlfunc func, nul, "mpnci_request_rec_prev", "pJp"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_prev", func
+    dlfunc func, lib, "mpnci_child_pool", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "child_pool", func
 
-    dlfunc func, nul, "mpnci_request_rec_user", "tJpti"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_user", func
+    dlfunc func, lib, "mpnci_server_rec", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "server_rec", func
 
-    dlfunc func, nul, "mpnci_request_rec_notes", "pJp"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_notes", func
+    dlfunc func, lib, "mpnci_conn_rec", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "conn_rec", func
 
-    dlfunc func, nul, "mpnci_request_rec_get_basic_auth_pw", "iJpP"
-    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_get_basic_auth_pw", func
+    dlfunc func, lib, "mpnci_csd", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "csd", func
 
-    dlfunc func, nul, "mpnci_rwrite", "iJPip"
-    set_root_global [ '_modparrot'; 'NCI' ], "rwrite", func
+    dlfunc func, lib, "mpnci_ctx_pool_name", "tJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "ctx_pool_name", func
 
-    dlfunc func, nul, "mpnci_ap_log_rerror", "vJtiiipt"
-    set_root_global [ '_modparrot'; 'NCI' ], "ap_log_rerror", func
+    dlfunc func, lib, "mpnci_raw_srv_config", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "raw_srv_config", func
 
-    dlfunc func, nul, "mpnci_conf_pool", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "conf_pool", func
+    dlfunc func, lib, "mpnci_raw_dir_config", "pJ"
+    set_root_global [ 'ModParrot'; 'NCI' ], "raw_dir_config", func
 
-    dlfunc func, nul, "mpnci_temp_pool", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "temp_pool", func
+    dlfunc func, lib, "mpnci_request_read", "iJPip"
+    set_root_global [ 'ModParrot'; 'NCI' ], "request_read", func
 
-    dlfunc func, nul, "mpnci_log_pool", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "log_pool", func
+    dlfunc func, lib, "mpnci_register_pool_cleanup", "vJpPP"
+    set_root_global [ 'ModParrot'; 'NCI' ], "register_pool_cleanup", func
 
-    dlfunc func, nul, "mpnci_child_pool", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "child_pool", func
+    dlfunc func, lib, "mpnci_add_apache_module", "pJttPP"
+    set_root_global [ 'ModParrot'; 'NCI' ], "add_apache_module", func
 
-    dlfunc func, nul, "mpnci_server_rec", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "server_rec", func
+    dlfunc func, lib, "mpnci_get_module_config", "PJtpi"
+    set_root_global [ 'ModParrot'; 'NCI' ], "get_module_config", func
 
-    dlfunc func, nul, "mpnci_conn_rec", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "conn_rec", func
+    dlfunc func, lib, "mpnci_cmd_parms_server", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "cmd_parms_server", func
 
-    dlfunc func, nul, "mpnci_csd", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "csd", func
+    dlfunc func, lib, "mpnci_cmd_parms_pool", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "cmd_parms_pool", func
 
-    dlfunc func, nul, "mpnci_dirconfig", "pJ"
-    set_root_global [ '_modparrot'; 'NCI' ], "modparrot_dirconfig", func
+    dlfunc func, lib, "mpnci_cmd_parms_temp_poolserver", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "cmd_parms_temp_poolserver", func
+
+    dlfunc func, lib, "mpnci_cmd_parms_cmd", "pJp"
+    set_root_global [ 'ModParrot'; 'NCI' ], "cmd_parms_cmd", func
+
+    dlfunc func, lib, "mpnci_set_config_ctx_pool", "vJpt"
+    set_root_global [ 'ModParrot'; 'NCI' ], "set_config_ctx_pool", func
 
     # load required libraries
-    load_bytecode 'Protoobject.pbc'
+    load_bytecode 'P6object.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
     load_bytecode 'ModParrot/Interpreter.pbc'
     load_bytecode 'ModParrot/Context.pbc'
-    load_bytecode 'Apache/Constants.pbc'
-    load_bytecode 'Apache/RequestRec.pbc'
-    load_bytecode 'APR/Table.pbc'
-    load_bytecode 'ModParrot/HLL/pir.pbc'
+    load_bytecode 'ModParrot/Apache/Constants.pbc'
+    load_bytecode 'ModParrot/Apache/Module.pbc'
+    load_bytecode 'ModParrot/Apache/RequestRec.pbc'
+    load_bytecode 'ModParrot/Apache/ServerRec.pbc'
+    load_bytecode 'ModParrot/Apache/CmdParms.pbc'
+    load_bytecode 'ModParrot/APR/Pool.pbc'
+    load_bytecode 'ModParrot/APR/Table.pbc'
+
+    # some languages make use of the Perl6 metamodel, so we register several
+    # mod_parrot classes as Perl6 meta classes so languages can access them
+    # natively.  use 'name' to register the class under a different name,
+    # letting mod_parrot provide scaffolding for functionality not yet
+    # available in the HLL layer.
+
+    # XXX this MUST be done before the mod_parrot classes are instantiated,
+    # so it can't be done in the HLL modules.  this needs to be fixed.
+
+    $P0 = get_hll_global 'P6metaclass'
+    $P1 = get_class ['ModParrot'; 'Apache'; 'RequestRec']
+    $P0.'register'($P1, 'name' => 'Apache;RequestRec')
+    $P1 = get_class ['ModParrot'; 'Apache'; 'ServerRec']
+    $P0.'register'($P1, 'name' => 'Apache;ServerRec')
+    $P1 = get_class ['ModParrot'; 'Apache'; 'CmdParms']
+    $P0.'register'($P1, 'name' => 'Apache;CmdParms')
+    $P1 = get_class ['ModParrot';'APR'; 'Pool']
+    $P0.'register'($P1, 'name' => 'APR;Pool')
+    $P1 = get_class ['ModParrot';'APR'; 'Table']
+    $P0.'register'($P1, 'name' => 'APR;Table')
+    $P1 = get_class ['ModParrot'; 'Interpreter']
+    $P0.'register'($P1)
+    $P1 = get_class ['ModParrot'; 'Context']
+    $P0.'register'($P1)
+    $P1 = get_class ['ModParrotHandle']
+    $P0.'register'($P1)
+
+    # global to indicate that we're actually running
+    $P0 = new 'Integer'
+    $P0 = 1
+    set_root_global '!MODPARROT_RUNTIME', $P0
 .end
 
 .sub modparrot_set_include_path
@@ -104,6 +203,34 @@
     lib_paths = interp[.IGLOBALS_LIB_PATHS]
 
     # XXX replace magic constant -- see parrot's t/compilers/imcc/syn/file.t
+    include_paths = lib_paths[0]
+
+    pathlist = split ':', pathstring
+    count = elements pathlist
+    $I0 = count
+
+  path_loop:
+    dec $I0
+    path = pathlist[$I0]
+    unshift include_paths, path
+    if $I0 > 0 goto path_loop
+
+    .return(count)
+.end
+
+.sub modparrot_set_lib_path
+    .param string pathstring
+    .local string path
+    .local pmc pathlist
+    .local pmc interp
+    .local pmc lib_paths
+    .local pmc include_paths
+    .local int count
+
+    getinterp interp
+    lib_paths = interp[.IGLOBALS_LIB_PATHS]
+
+    # XXX replace magic constant -- see parrot's t/compilers/imcc/syn/file.t
     include_paths = lib_paths[1]
 
     pathlist = split ':', pathstring
@@ -119,23 +246,30 @@
     .return(count)
 .end
 
-.sub find_file_in_path
-    .param string search_path
-    .param string filename
+.sub modparrot_set_dynext_path
+    .param string pathstring
     .local string path
-    .local pmc iter
+    .local pmc pathlist
+    .local pmc interp
+    .local pmc lib_paths
+    .local pmc include_paths
+    .local int count
+
+    getinterp interp
+    lib_paths = interp[.IGLOBALS_LIB_PATHS]
+
+    # XXX replace magic constant -- see parrot's t/compilers/imcc/syn/file.t
+    include_paths = lib_paths[2]
+
+    pathlist = split ':', pathstring
+    count = elements pathlist
+    $I0 = count
 
-    $P0 = split ':', search_path
-    iter = new 'Iterator', $P0
-  iter_start:
-    null path
-    unless iter goto return_path
-    $S0 = shift iter
-    path = concat $S0, '/'
-    path .= filename
-    $I0 = stat path, 0
-    unless $I0 goto iter_start
+  path_loop:
+    dec $I0
+    path = pathlist[$I0]
+    unshift include_paths, path
+    if $I0 > 0 goto path_loop
 
-  return_path:
-    .return(path)
+    .return(count)
 .end

Modified: mod_parrot/branches/configure/src/context.c
==============================================================================
--- mod_parrot/branches/configure/src/context.c	(original)
+++ mod_parrot/branches/configure/src/context.c	Sat May  2 06:55:00 2009
@@ -24,6 +24,7 @@
 #include "http_connection.h"
 #include "http_main.h"
 #include "mpm.h"
+#include "apr_thread_mutex.h"
 
 #include "parrot/parrot.h"
 #include "parrot/embed.h"
@@ -31,6 +32,18 @@
 
 #include "mod_parrot.h"
 #include "modparrot_config.h"
+#include "modparrot_log.h"
+
+#ifdef MPM_IS_THREADED
+apr_thread_mutex_t *ctx_pool_mutex;
+#endif /* MPM_IS_THREADED */
+
+/* APR_ARRAY_IDX seems to be missing in earlier apaches */
+#ifndef APR_ARRAY_IDX
+#define APR_ARRAY_IDX(ary,i,type) (((type*)(ary)->elts)[i])
+#endif /* APR_ARRAY_IDX */
+
+extern modparrot_globals mp_globals;
 
 /* initialize pool of contexts */
 apr_array_header_t * mp_ctx_pool_init(apr_pool_t *p,
@@ -40,6 +53,8 @@
     apr_array_header_t *ctx_pool;
     modparrot_context *ctx;
 
+    MP_TRACE_c(mp_globals.base_server, "creating context pool of size %d", num);
+
     if (!(ctx_pool = apr_array_make(p, num, sizeof(modparrot_context)))) {
         return NULL;
     }
@@ -47,9 +62,19 @@
     for (i = 0; i < num; i++) {
         ctx = (*(modparrot_context **)apr_array_push(ctx_pool) =
             (modparrot_context *)apr_pcalloc(p, sizeof(modparrot_context)));
+        ctx->ctx_pool = ctx_pool;
         ctx->parent_interp = parent_interp;
     }
 
+#ifdef MPM_IS_THREADED
+    if (apr_thread_mutex_create(&ctx_pool_mutex, APR_THREAD_MUTEX_DEFAULT, p)
+        != APR_SUCCESS) {
+        return NULL;
+    }
+#endif /* MPM_IS_THREADED */
+        
+    MP_TRACE_c(mp_globals.base_server, "created context pool %p (size %d)", ctx_pool, num);
+
     return ctx_pool;
 }
 
@@ -60,47 +85,97 @@
 
     if (!ctx_pool) return;
 
+    MP_TRACE_c(mp_globals.base_server, "destroying context pool %p", ctx_pool);
+
     /* pop each context off the list and destroy its interpreter */
+#ifdef MPM_IS_THREADED
+    apr_thread_mutex_lock(ctx_pool_mutex);
+#endif /* MPM_IS_THREADED */
     while ((ctxpp = apr_array_pop(ctx_pool))) {
         if ((*ctxpp)->interp) {
             modparrot_destroy_interpreter((*ctxpp)->interp);
             (*ctxpp)->interp = NULL;
         }
     }
+#ifdef MPM_IS_THREADED
+    apr_thread_mutex_unlock(ctx_pool_mutex);
+    apr_thread_mutex_destroy(ctx_pool_mutex);
+#endif /* MPM_IS_THREADED */
 
     /* apache will take care of destroying the actual context pool array */
 }
 
+/* destroy all context pools */
+void mp_ctx_pool_destroy_all(void)
+{
+    apr_pool_t *p;
+    apr_hash_index_t *idx;
+    char *name = NULL;
+
+    apr_pool_create(&p, NULL);
+
+    for (idx = apr_hash_first(p, mp_globals.ctx_pool_hash); idx;
+        idx = apr_hash_next(idx)) {
+        const void *key;
+        apr_ssize_t klen;
+        void *val;
+        apr_hash_this(idx, &key, &klen, &val);
+        mp_ctx_pool_destroy((apr_array_header_t *)val);
+    }
+
+    apr_pool_destroy(p);
+}
+
 /* finds and reserves a context for use by a handler */
-modparrot_context *reserve_ctx(apr_array_header_t *ctx_pool)
+modparrot_context *reserve_ctx(apr_array_header_t *ctx_pool, int index)
 {
 #ifdef MPM_IS_THREADED
     int i;
-#endif
-    modparrot_context *ctx;
+#endif /* MPM_IS_THREADED */
+    modparrot_context *ctxp = (modparrot_context *)NULL;
 
     if (!ctx_pool) return NULL;
+
+    MP_TRACE_c(mp_globals.base_server, "reserving a context from pool %p", ctx_pool);
+
 #ifdef MPM_IS_THREADED
-    for (i = 0; i < ctx_pool->nelts; i++) {
-        ctx = ((modparrot_context **)ctx_pool->elts)[i];
-        if (MODPARROT_CTX_ISLOCKED(ctx)) continue;
-        MODPARROT_CTX_LOCK(ctx);
-        return(ctx);
+    apr_thread_mutex_lock(ctx_pool_mutex);
+    if (index == MP_CTX_ANY) {
+        for (i = 0; i < ctx_pool->nelts; i++) {
+            modparrot_context *c;
+            c = ((modparrot_context **)ctx_pool->elts)[i];
+            if (MODPARROT_CTX_ISLOCKED(c)) continue;
+            MODPARROT_CTX_LOCK(c);
+            ctxp = c;
+            break;
+        }
+    }
+    else {
+        if (ctxp = ((modparrot_context **)ctx_pool->elts)[index]) {
+            if (MODPARROT_CTX_ISLOCKED(ctxp)) {
+                ctxp = NULL;
+            }
+            else {
+                MODPARROT_CTX_LOCK(ctxp);
+            }
+        }
     }
+    apr_thread_mutex_unlock(ctx_pool_mutex);
+#else /* MPM_IS_THREADED */
+    ctxp = ((modparrot_context **)ctx_pool->elts)[0];
+    MODPARROT_CTX_LOCK(ctxp); /* no threads here, just for consistency */
+#endif /* MPM_IS_THREADED */
 
-    /* XXX should wait for free context here instead of bailing */
-    return (modparrot_context *)NULL;
-#else
-    ctx = ((modparrot_context **)ctx_pool->elts)[0];
-    MODPARROT_CTX_LOCK(ctx); /* no threads here, just for consistency */
-    return ctx;
-#endif
+    MP_TRACE_c(mp_globals.base_server, "reserved context %p from pool %p", ctxp, ctx_pool);
+
+    return(ctxp);
 }
 
 /* releases a context back into the pool of available contexts */
-void release_ctx(modparrot_context *ctx)
+void release_ctx(modparrot_context *ctxp)
 {
-    MODPARROT_CTX_UNLOCK(ctx);
+    MP_TRACE_c(mp_globals.base_server, "releasing context %p", ctxp);
+    MODPARROT_CTX_UNLOCK(ctxp);
 }
 
 void set_interp_ctx(Parrot_Interp interp, modparrot_context *ctx)
@@ -110,6 +185,7 @@
 
     typenum = Parrot_PMC_typenum(interp, "UnManagedStruct");
     p = Parrot_PMC_new(interp, typenum);
+    Parrot_register_pmc(interp, p);
     Parrot_PMC_set_pointer(interp, p, ctx);
     Parrot_store_global_s(
         interp,
@@ -137,3 +213,55 @@
 
     return ctx;
 }
+
+modparrot_context *modparrot_get_current_ctx(apr_pool_t *p)
+{
+    modparrot_context *ctxp;
+    assert(p);
+    apr_pool_userdata_get((void **)&ctxp, MP_KEY_CTX, p);
+    return(ctxp);
+}
+
+static apr_status_t modparrot_ctx_cleanup(void *data)
+{
+    Parrot_PMC p;
+    modparrot_context *ctxp = (modparrot_context *)data;
+    if (ctxp->interp) {
+        p = Parrot_find_global_s(
+            ctxp->interp,
+            string_from_literal(ctxp->interp, "_modparrot"),
+            string_from_literal(ctxp->interp, "__context")
+        );
+        Parrot_unregister_pmc(ctxp->interp, p);
+    }
+    release_ctx(ctxp);
+}
+
+void modparrot_set_current_ctx(apr_pool_t *p, modparrot_context *ctxp)
+{
+    MP_TRACE_c(mp_globals.base_server, "binding context %p to APR pool %p", ctxp, p);
+    apr_pool_userdata_set(ctxp, MP_KEY_CTX, modparrot_ctx_cleanup, p);
+}
+
+void modparrot_set_named_ctx_pool(apr_pool_t *p, const char *name,
+    apr_array_header_t *cp)
+{
+    apr_hash_set(mp_globals.ctx_pool_hash, name, APR_HASH_KEY_STRING, cp);
+    /* we always have 1 valid context, so use it to store the pool name */
+    APR_ARRAY_IDX(cp, 0, modparrot_context *)->ctx_pool_name =
+        (const char *)apr_pstrdup(p, name);
+}
+
+apr_array_header_t *modparrot_get_named_ctx_pool(const char *name)
+{
+    apr_array_header_t *cp;
+
+    cp = apr_hash_get(mp_globals.ctx_pool_hash, name, APR_HASH_KEY_STRING);
+    return cp;
+}
+
+const char *modparrot_get_ctx_pool_name(apr_array_header_t *cp)
+{
+    /* we always have 1 valid context, so use it to retreive the pool name */
+    return APR_ARRAY_IDX(cp, 0, modparrot_context *)->ctx_pool_name;
+}

Modified: mod_parrot/branches/configure/src/mod_parrot.c
==============================================================================
--- mod_parrot/branches/configure/src/mod_parrot.c	(original)
+++ mod_parrot/branches/configure/src/mod_parrot.c	Sat May  2 06:55:00 2009
@@ -27,53 +27,74 @@
 #include "http_core.h"
 #include "http_connection.h"
 #include "http_main.h"
+#include "ap_mpm.h"
 
 #include "parrot/parrot.h"
 #include "parrot/embed.h"
 #include "parrot/extend.h"
 
+#define HAVE_LOCAL_DEBUG_LEVEL 1
 #include "mod_parrot.h"
 #include "modparrot_config.h"
 #include "modparrot_log.h"
 
-#define MODPARROT_VERSION "0.4"
+#define MODPARROT_VERSION "0.5"
 
-#define DEFAULT_HANDLER "handler"
-#define SHOULD_HANDLE(x) (x->handler ? \
- (strncmp(x->handler, MODPARROT_MAGIC, strlen(MODPARROT_MAGIC)) ? 0 : 1) : 0)
+#define NEXT_HANDLER_MODULE(x) (mp_globals.handler_modules[x] ? ((module **)mp_globals.module_array->elts)[((int *)mp_globals.handler_modules[x]->elts)[++(ctxp->module_index)]] : NULL);
+
+/* a single structure for globals */
+modparrot_globals mp_globals;
 
 /* declare our module */
 extern module AP_MODULE_DECLARE_DATA parrot_module;
 
-/* we need to forward declare this */
-static apr_status_t modparrot_request_cleanup(void *data);
-
 /* XXX mod_parrot can crash on x86_64 w/o this.
  * there's no prototype in the standard parrot includes, so compiler assumes
  * return type of 'int', and sizeof(int) != sizeof(pointer) on x86_64.
  */
 Parrot_PMC Parrot_Class_instantiate(PARROT_INTERP, PMC *, PMC *init);
 
-/* have we started?  this can be global since it's written to at startup */
-int mp_is_started = 0;
+void modparrot_init_globals(apr_pool_t *p)
+{
+    int i;
+
+    mp_globals.pconf = p;
+    mp_globals.is_started = 0;
+    mp_globals.debug_level = 0;
+    mp_globals.max_threads = 0;
+    mp_globals.hard_thread_limit = 0;
+    mp_globals.base_server = NULL;
+    mp_globals.module_hash = apr_hash_make(p);
+    mp_globals.module_array = apr_array_make(p, 1, sizeof(module *));;
+    mp_globals.ctx_pool_hash = apr_hash_make(p);
+    for (i = 0; i < MP_HOOK_LAST; i++) {
+        mp_globals.handler_modules[i] = NULL;
+    }
+}
+
+void modparrot_trace(server_rec *s, const char *fmt, ...)
+{
+    va_list ap;
+    char log[1000];
+
+    va_start(ap, fmt);
+    vsnprintf(log, sizeof(log), fmt, ap);
+    va_end(ap);
+    MPLOG_DEBUG(s, log);
+}
 
-void modparrot_load_file(Parrot_Interp interp, server_rec *s, char *hll,
-                         char *file)
+void modparrot_load_file(Parrot_Interp interp, server_rec *s, const char *file)
 {
     int ret;
 
     char *ext = strrchr(file, '.');
-    /* load any PBC files */
+    /* load any valid parrot files (PIR, PBC, PASM) */
     if (ext && (!strcmp(ext, ".pbc") || !strcmp(ext, ".pir") ||
         !strcmp(ext, ".pasm"))) {
-        modparrot_load_bytecode(interp, file);
+        modparrot_load_bytecode(interp, (char *)file);
     }
     else {
-        /* call the HLL load handler to handle the loading */
-        if (!modparrot_hll_handler(interp, hll, "load", file,
-            &ret)) {
-             MPLOG_ERRORF(s, "no HLL load handler for '%s'", hll);
-        }
+        MPLOG_ERRORF(s, "'%s' is not a valid Parrot file", file);
     }
 }
 
@@ -84,9 +105,9 @@
     int i, ret;
 
     for (i = 0; i < files->nelts; i++) {
-        modparrot_handler_info *l =
-            &((modparrot_handler_info *)files->elts)[i];
-        modparrot_load_file(interp, s, l->hll, l->id);
+        const char *path =
+            ((char **)files->elts)[i];
+        modparrot_load_file(interp, s, path);
     }
 }
 
@@ -100,24 +121,49 @@
     if (cfg->trace_flags == -1) cfg->trace_flags = 0;
 
     /* initialize interpreter */
-    interp = modparrot_init_interpreter(ctx->parent_interp);
+    interp = modparrot_init_interpreter(mp_globals.root_interp);
+    if (!mp_globals.root_interp) mp_globals.root_interp = interp;
 
     /* enable tracing */
     Parrot_set_trace(interp, (cfg->option_flags & MP_OPT_TRACE_INIT) ?
         cfg->trace_flags : 0);
 
+    /* if appropriate, set path to mod_parrot module (for some dlopens) */
+    if (cfg->so_path) {
+        Parrot_PMC path;
+        int typenum = Parrot_PMC_typenum(interp, "String");
+        path = Parrot_PMC_new(interp, typenum);
+        Parrot_register_pmc(interp, path);
+        Parrot_PMC_set_cstring(interp, path, cfg->so_path);
+        Parrot_store_global_s(
+            interp,
+            string_from_literal(interp, "_modparrot"),
+            string_from_literal(interp, "__module_path"),
+            path
+        );
+    }
+
     /* load the init code */
     modparrot_load_bytecode(interp,
         cfg->init_path ? cfg->init_path : MODPARROT_DEFAULT_INIT);
 
-    /* set additional include paths from apache config */
+    /* set additional paths from apache config */
     if (cfg->include_path) {
-        modparrot_call_sub_IS(interp, "_modparrot",
-            "modparrot_set_include_path", &i, cfg->include_path);
+        /* XXX set to "include_path" when tests & docs are updated */
+        modparrot_call_sub_IS(interp, "ModParrot",
+            "modparrot_set_lib_path", &i, cfg->include_path);
+    }
+    if (cfg->lib_path) {
+        modparrot_call_sub_IS(interp, "ModParrot",
+            "modparrot_set_lib_path", &i, cfg->lib_path);
+    }
+    if (cfg->dynext_path) {
+        modparrot_call_sub_IS(interp, "ModParrot",
+            "modparrot_set_dynext_path", &i, cfg->dynext_path);
     }
 
     /* initialize parrot side */
-    modparrot_call_sub(interp, "_modparrot", "modparrot_init");
+    modparrot_call_sub(interp, "ModParrot", "modparrot_init");
 
     /* set our context
      * Since there is a one-to-one relationship between threads and
@@ -128,69 +174,182 @@
     return(interp);
 }
 
-static modparrot_context *init_ctx(server_rec *s)
+static apr_array_header_t *select_ctx_pool(module *modp, server_rec *s,
+    ap_conf_vector_t *per_dir_config)
+{
+    modparrot_module_config *cfg;
+    modparrot_module_info *minfo = modp->dynamic_load_handle;
+    apr_array_header_t *cp;
+
+    /* try section scope first */
+    if (per_dir_config) {
+        cfg = ap_get_module_config(per_dir_config, modp);
+        if (cfg) {
+            /* section pools might be dynamic, so always look up by name */
+            if (cfg->ctx_pool_name) {
+                MP_TRACE_c(s, "select_ctx_pool: using section pool '%s'", cfg->ctx_pool_name);
+                cp = modparrot_get_named_ctx_pool(cfg->ctx_pool_name);
+                if (!cp) {
+                    /* XXX need a startup w/o init_ctx side-effect */
+                    modparrot_context *ctxp = modparrot_startup(
+                        mp_globals.pconf, s, NULL, cfg->ctx_pool_name);
+                    release_ctx(ctxp);
+                }
+                return(cp);
+            }
+        }
+    }
+
+    /* now try server scope */
+    cfg = ap_get_module_config(s->module_config, modp);
+    if (cfg) {
+        if (cfg->ctx_pool) {
+            MP_TRACE_c(s, "select_ctx_pool: using server pool '%s'", cfg->ctx_pool_name);
+            /* server pools are static, so return the cached pool */
+            return(cfg->ctx_pool);
+        }
+    }
+
+    /* fall back to the module's default pool */
+    MP_TRACE_c(s, "select_ctx_pool: using module default pool");
+    /* module pools are static, so return the cached pool */
+    return(minfo->ctx_pool);
+}
+
+static modparrot_context *init_ctx(server_rec *s, apr_pool_t *p,
+    apr_array_header_t *ctx_pool)
 {
     Parrot_Interp interp;
-    modparrot_context *ctxp;
+    modparrot_context *ctxp = (modparrot_context *)NULL;
     modparrot_srv_config *cfg;
 
     cfg = ap_get_module_config(s->module_config, &parrot_module);
 
-    if ((ctxp = reserve_ctx(cfg->ctx_pool))) {
-        if (!ctxp->interp) {
-            if (!(interp = modparrot_init(ctxp, s))) {
-                MPLOG_ERROR(s,
-                    "init_ctx: interpreter initialization failed");
-                return (modparrot_context *)NULL;
+    /* grab the current context... */
+    if (p) ctxp = modparrot_get_current_ctx(p);
+
+    /* ...but ignore it if it doesn't belong to the requested context pool */
+    if (ctxp && ctx_pool) {
+        if (ctxp->ctx_pool != ctx_pool) ctxp = NULL;
+    }
+
+    if (!ctxp) {
+        apr_array_header_t *cp = ctx_pool ? ctx_pool : cfg->ctx_pool;
+        if ((ctxp = reserve_ctx(cp, MP_CTX_ANY))) {
+            if (!ctxp->interp) {
+                if (!(interp = modparrot_init(ctxp, s))) {
+                    MPLOG_ERROR(s,
+                        "init_ctx: interpreter initialization failed");
+                    return (modparrot_context *)NULL;
+                }
+                ctxp->interp = interp;
+            }
+            else {
+                interp = ctxp->interp;
             }
-            ctxp->interp = interp;
+
+            /* remember this context for next time */
+            if (p) modparrot_set_current_ctx(p, ctxp);
         }
         else {
-            interp = ctxp->interp;
+            MPLOG_ERROR(s, "init_ctx: no free contexts");
         }
     }
-    else {
-        MPLOG_ERROR(s, "init_ctx: no free contexts");
-        ctxp = (modparrot_context *)NULL;
+
+    /* usually set s in a hook, but need it here for the config phase */
+    if (ctxp) {
+        ctxp->s = s;
+    }
+
+    MP_TRACE_c(s, "init_ctx: using context %p", ctxp);
+
+    return(ctxp);
+}
+
+static modparrot_context *clone_ctx_state(modparrot_context *cur_ctxp,
+    apr_array_header_t *new_ctx_pool, server_rec *s, apr_pool_t *p)
+{
+    modparrot_context *ctxp;
+
+    /* don't clone from same pool, just return current context */
+    if (cur_ctxp->ctx_pool == new_ctx_pool) return cur_ctxp;
+
+    /* grab a context from the requested pool */
+    if (!(ctxp = init_ctx(s, p, new_ctx_pool))) {
+        MPLOG_ERROR(s, "context initialization failed");
+        return NULL;
     }
 
+    MP_TRACE_c(s, "cloning context %p -> %p", cur_ctxp, ctxp);
+
+    /* copy relevant cached data from current context */
+    ctxp->r = cur_ctxp->r;
+    ctxp->s = cur_ctxp->s;
+    ctxp->pconf = cur_ctxp->pconf;
+    ctxp->plog = cur_ctxp->plog;
+    ctxp->ptemp = cur_ctxp->ptemp;
+    ctxp->pchild = cur_ctxp->pchild;
+    ctxp->c = cur_ctxp->c;
+    ctxp->csd = cur_ctxp->csd;
+    ctxp->module_index = cur_ctxp->module_index;
+
+    /* NOTE: caller must release the old context */
+
     return(ctxp);
 }
 
 /* public interface for starting an interpreter */
 modparrot_context *modparrot_startup(apr_pool_t *p, server_rec *s,
-    Parrot_Interp parent_interp)
+    Parrot_Interp parent_interp, const char *pool_name)
 {
     modparrot_context *ctxp;
     modparrot_srv_config *cfg;
+    apr_array_header_t *ctx_pool = NULL;
+    const char *name;
 
     cfg = ap_get_module_config(s->module_config, &parrot_module);
 
-    if (!mp_is_started || (!cfg->ctx_pool && s->is_virtual)) {
-        if (!(cfg->ctx_pool = mp_ctx_pool_init(p, parent_interp, 1))) {
+    if (!mp_globals.is_started) mp_globals.base_server = s;
+
+    name = pool_name ? pool_name : "default";
+    if (mp_globals.is_started) {
+        ctx_pool = modparrot_get_named_ctx_pool(name);
+    }
+
+    if (!ctx_pool) {
+        if (!(ctx_pool = mp_ctx_pool_init(p, parent_interp, 1))) {
             MPLOG_ERROR(s, "context pool creation failed");
             return NULL;
         }
+        /* name the pool so we can reference it later */
+        modparrot_set_named_ctx_pool(p, name, ctx_pool);
+        MP_TRACE_c(s, "modparrot_startup: context pool %p is named '%s'", ctx_pool, name);
+
+        /* if server doesn't have a context pool, assign this one */
+        if (!cfg->ctx_pool) {
+            cfg->ctx_pool = ctx_pool;
+            MP_TRACE_c(s, "context pool %p (%s) is default for server %p", ctx_pool, name, s);
+        }
     }
 
-    if ((ctxp = init_ctx(s))) {
-        mp_is_started = 1;
+    MP_TRACE_c(s, "modparrot_startup: using context pool %p (%s)", ctx_pool, name);
+
+    /* grab a context from the pool */
+    if ((ctxp = init_ctx(s, p, ctx_pool))) {
+        if (!mp_globals.is_started) {
+            mp_globals.is_started = 1;
+        }
     }
     else {
         MPLOG_ERROR(s, "context initialization failed");
         return NULL;
     }
 
-    /* we assume that the passed in pool is the configuration pool.  we'll use
-     * this for early startups, but it will be overwritten by later handlers.
-     */
-    ctxp->pconf = p;
-
     return(ctxp);
 }
 
-int modparrot_hll_handler(Parrot_Interp interp, char *hll, char *hll_handler,
-    char *handler, int *ret)
+static int modparrot_call_meta_handler(Parrot_Interp interp, char *hll,
+    char *hook, int *ret)
 {
     Parrot_PMC ctx_class;
     Parrot_PMC ctx_pmc;
@@ -211,704 +370,407 @@
     Parrot_register_pmc(interp, ctx_pmc);
 
     if (!hll) hll = MODPARROT_DEFAULT_HLL;
-    res = modparrot_call_sub_IPS(interp, hll, hll_handler, ret, ctx_pmc,
-        handler);
+    res = modparrot_call_sub_IP(interp, hll, hook, ret, ctx_pmc);
     Parrot_unregister_pmc(interp, ctx_pmc);
     return res ? 1 : 0;
 }
 
-static char *get_request_hll(request_rec *r, const char *handler,
-    const char *content_type)
+static int modparrot_request_phase_handler(request_rec *r)
 {
-    modparrot_srv_config *cfg;
-    char *hll;
-
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    /* check handler name */
-    hll = (char *)apr_table_get(cfg->handler_map, handler);
-    if (hll) return hll;
-
-    /* check mime type */
-    if (content_type) {
-        hll = (char *)apr_table_get(cfg->type_map, content_type);
-        if (hll) return hll;
-    }
-
-    return NULL;
-}
-
-/* This macro checks whether we should handle a particular phase, and if so,
- * sets the HLL and handler name accordingly.
- */
-#define SET_HLL_HANDLER(x) \
-    if (!dircfg->x) return DECLINED; \
-    hll = NULL; \
-    hll = dircfg->x->hll ? dircfg->x->hll : dircfg->hll; \
-    if (!hll) { \
-        if (!(hll = (get_request_hll(r, r->handler, r->content_type)))) { \
-            hll = MODPARROT_DEFAULT_HLL; \
-        } \
-    } \
-    hll_handler = dircfg->x ? dircfg->x->id : (char *)r->handler;
-
-static int modparrot_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* take this opportunity to register the mod_parrot cleanup handler here,
-     * as we may not handle any other part of the request until then.
-     */
-    apr_pool_cleanup_register(r->pool, r, modparrot_request_cleanup,
-        apr_pool_cleanup_null);
-
-    if (!r->handler) return DECLINED;
 
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    /* we don't use SET_HLL_HANDLER here because it may still be appropriate
-     * to run this handler without a corresponding ParrotHandler directive.
-     * This is true for type maps and handler maps.
-     */
-    hll = NULL;
-    if (dircfg->handler) {
-        hll = dircfg->handler->hll ? dircfg->handler->hll : dircfg->hll;
-    }
-    if (!hll) {
-        if (!(hll = (get_request_hll(r, r->handler, r->content_type)))) {
-            if (!dircfg->handler) return DECLINED;
-            hll = MODPARROT_DEFAULT_HLL;
-        }
-    }
-
-    hll_handler = dircfg->handler ? dircfg->handler->id : (char *)r->handler;
-
-    /* set default content type */
-    r->content_type = "text/html";
-
-    /* just headers? */
-    if (r->header_only) {
-        return OK;
-    }
+    MP_TRACE_h(r->server, "in modparrot_request_phase_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for handler '%s'",
-            dircfg->handler->id);
+    if (!(ctxp = init_ctx(r->server, r->connection->pool, NULL))) {
+        MPLOG_ERROR(r->server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
+    /* we're FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
-    /* call HLL handler */
-    sub = "handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server,
-            "no subroutine found for handler '%s'", hll_handler);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* set the most specific pool */
+    ctxp->pool = r->pool;
 
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
+    return DECLINED;
 }
 
 static int modparrot_pre_connection_handler(conn_rec *c, void *csd)
 {
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
 
-    /* get apache configs */
-    cfg = ap_get_module_config(c->base_server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) || !cfg->pre_connection_handler) {
-        return DECLINED;
-    }
+    MP_TRACE_h(c->base_server, "in modparrot_pre_connection_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(c->base_server))) {
+    if (!(ctxp = init_ctx(c->base_server, c->pool, NULL))) {
         MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->c = c;
-    ctxp->csd = csd;
+    /* we're REALLY_FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
-    /* call HLL handler */
-    sub = "pre_connection_handler";
-    hll = cfg->pre_connection_handler->hll ?
-        cfg->pre_connection_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->pre_connection_handler->id, &handler_status)) {
-        MPLOG_ERRORF(c->base_server, "no subroutine found for handler '%s'",
-            cfg->pre_connection_handler->id);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* set the most specific pool */
+    ctxp->pool = c->pool;
 
-    /* clean up */
-    release_ctx(ctxp);
+    /* we only do setup */
+    return DECLINED;
+}
 
-    /* tell apache we're done */
-    return handler_status;
+/* XXX if we're not doing anything here, don't register it! */
+static apr_status_t modparrot_request_cleanup(void *data)
+{
+    return APR_SUCCESS;
 }
 
-static int modparrot_map_to_storage_handler(request_rec *r)
+apr_status_t modparrot_meta_cleanup_handler(void *data)
 {
-    modparrot_srv_config *cfg;
+    modparrot_cleanup_info *ci = (modparrot_cleanup_info *)data;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
-
-    /* get apache configs */
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) || !cfg->map_to_storage_handler) {
-        return DECLINED;
-    }
+    int status;
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
+    if (!(ctxp = init_ctx(ci->s, ci->pool, NULL))) {
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
+    /* call cleanup sub, passing HLL data from ci */
+    status = Parrot_call_sub_ret_int(ctxp->interp, ci->callback, "IP",
+        ci->hll_data ? ci->hll_data : PMCNULL);
 
-    /* call HLL handler */
-    sub = "map_to_storage_handler";
-    hll = cfg->map_to_storage_handler->hll ?
-        cfg->map_to_storage_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->map_to_storage_handler->id, &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            cfg->map_to_storage_handler->id);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
+    /* we don't need the data PMC anymore */
+    if (!PMC_IS_NULL(data)) {
+        Parrot_unregister_pmc(ctxp->interp, data);
     }
 
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
+    return status;
 }
 
-static int modparrot_header_parser_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
+#define MP_REQUEST_METAHANDLER(hname, henum, register_cleanup) \
+    int modparrot_meta_##hname(request_rec *r) \
+    { \
+        modparrot_context *ctxp, *cloned; \
+        modparrot_module_config *dircfg; \
+        modparrot_srv_config *mpcfg; \
+        module *modp; \
+        modparrot_module_info *minfo; \
+        Parrot_PMC sub; \
+        int status; \
+        MP_TRACE_h(r->server, "in modparrot_meta_%s", #hname); \
+        /* initialize context */ \
+        if (!(ctxp = init_ctx(r->server, r->connection->pool, NULL))) { \
+            MPLOG_ERROR(r->server, "context initialization failed"); \
+            return HTTP_INTERNAL_SERVER_ERROR; \
+        } \
+        /* decline if mod_parrot isn't enabled */ \
+        mpcfg = ap_get_module_config(r->server->module_config, \
+            &parrot_module); \
+        /* get next module in line */ \
+        if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED; \
+        modp = NEXT_HANDLER_MODULE(henum); \
+        cloned = clone_ctx_state(ctxp, \
+            select_ctx_pool(modp, r->server, r->per_dir_config), r->server, \
+                r->pool); \
+        if (cloned != ctxp) { \
+            release_ctx(ctxp); \
+            ctxp = cloned; \
+        } \
+        /* take this opportunity to register the request cleanup handler \
+         * here, as we may not handle any other part of the request until \
+         * then. NOTE: this is mod_parrot internal only and NOT for HLLs. \
+         */ \
+        if (register_cleanup) { \
+            /* XXX if callback doesn't do anything, don't register it! */ \
+            apr_pool_cleanup_register(r->pool, r, \
+                modparrot_request_cleanup, apr_pool_cleanup_null); \
+        } \
+        ctxp->r = r; \
+        /* XXX does header_only check belong in the meta handler? */ \
+        if (r->header_only) { \
+            return OK; \
+        } \
+        /* get HLL config */ \
+        minfo = (modparrot_module_info *)modp->dynamic_load_handle; \
+        dircfg = (modparrot_module_config *)ap_get_module_config( \
+            r->per_dir_config, modp); \
+        /* call meta handler */ \
+        MP_TRACE_h(r->server, "calling %s for %s", #hname, minfo->namespace); \
+        if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace, \
+            #hname , &status)) { \
+            MPLOG_ERRORF(r->server, \
+                #hname " not found in module '%s'", \
+                modp->name); \
+            status = HTTP_INTERNAL_SERVER_ERROR; \
+        } \
+        /* tell apache we're done */ \
+        return status; \
+    }
 
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
+MP_REQUEST_METAHANDLER(post_read_request_handler, MP_HOOK_POST_READ_REQUEST, 1)
+MP_REQUEST_METAHANDLER(map_to_storage_handler, MP_HOOK_MAP_TO_STORAGE, 0)
+MP_REQUEST_METAHANDLER(trans_handler, MP_HOOK_TRANS, 0)
+MP_REQUEST_METAHANDLER(header_parser_handler, MP_HOOK_HEADER_PARSER, 0)
+MP_REQUEST_METAHANDLER(access_handler, MP_HOOK_ACCESS, 0)
+MP_REQUEST_METAHANDLER(authen_handler, MP_HOOK_AUTHEN, 0)
+MP_REQUEST_METAHANDLER(authz_handler, MP_HOOK_AUTHZ, 0)
+MP_REQUEST_METAHANDLER(response_handler, MP_HOOK_RESPONSE, 0)
+MP_REQUEST_METAHANDLER(type_handler, MP_HOOK_TYPE, 0)
+MP_REQUEST_METAHANDLER(fixup_handler, MP_HOOK_FIXUP, 0)
+MP_REQUEST_METAHANDLER(log_handler, MP_HOOK_LOG, 0)
+
+int modparrot_meta_pre_connection_handler(conn_rec *c, void *csd)
+{
+    modparrot_context *ctxp, *cloned;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
-    SET_HLL_HANDLER(header_parser_handler);
+    MP_TRACE_h(c->base_server, "in modparrot_meta_pre_connection_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
+    if (!(ctxp = init_ctx(c->base_server, c->pool, NULL))) {
+        MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "header_parser_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
+    /* decline if mod_parrot isn't enabled */
+    mpcfg = ap_get_module_config(c->base_server->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
+
+    /* get next module in line */
+    modp = NEXT_HANDLER_MODULE(MP_HOOK_PRE_CONNECTION);
+
+    cloned = clone_ctx_state(ctxp, select_ctx_pool(modp, c->base_server, NULL),
+        c->base_server, c->pool);
+    if (cloned != ctxp) {
         release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
+        ctxp = cloned;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
+    ctxp->c = c;
+    ctxp->csd = csd;
+
+    /* get HLL config */
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    MP_TRACE_h(c->base_server, "calling pre_connection_handler for %s", minfo->namespace); 
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "pre_connection_handler", &status)) {
+        MPLOG_ERRORF(c->base_server,
+            "no pre_connection metahandler found for module '%s'", modp->name);
+        status = HTTP_INTERNAL_SERVER_ERROR;
+    }
 
     /* tell apache we're done */
-    return handler_status;
+    return status;
 }
 
-static int modparrot_post_read_request_handler(request_rec *r)
+static int modparrot_process_connection_handler(conn_rec *c)
 {
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
-
-    /* get apache configs */
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
 
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) ||
-        !cfg->post_read_request_handler) {
-        return DECLINED;
-    }
+    MP_TRACE_h(c->base_server, "in modparrot_process_connection_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
+    if (!(ctxp = init_ctx(c->base_server, c->pool, NULL))) {
+        MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
+    /* we're REALLY_FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
-    /* call HLL handler */
-    sub = "post_read_request_handler";
-    hll = cfg->post_read_request_handler->hll ?
-        cfg->post_read_request_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->post_read_request_handler->id, &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            cfg->post_read_request_handler->id);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* set the most specific pool */
+    ctxp->pool = c->pool;
 
-    /* tell apache we're done */
-    return handler_status;
+    /* we only do setup */
+    return DECLINED;
 }
 
-static int modparrot_process_connection_handler(conn_rec *c)
+int modparrot_meta_process_connection_handler(conn_rec *c)
 {
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
+    modparrot_context *ctxp, *cloned;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
-    /* get apache configs */
-    cfg = ap_get_module_config(c->base_server->module_config, &parrot_module);
-
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) ||
-        !cfg->process_connection_handler) {
-        return DECLINED;
-    }
+    MP_TRACE_h(c->base_server, "in modparrot_meta_process_connection_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(c->base_server))) {
+    if (!(ctxp = init_ctx(c->base_server, c->pool, NULL))) {
         MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->c = c;
-
-    /* call HLL handler */
-    sub = "process_connection_handler";
-    hll = cfg->process_connection_handler->hll ?
-        cfg->process_connection_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->process_connection_handler->id, &handler_status)) {
-        MPLOG_ERRORF(c->base_server, "no subroutine found for handler '%s'",
-            cfg->process_connection_handler->id);
+    /* decline if mod_parrot isn't enabled */
+    mpcfg = ap_get_module_config(c->base_server->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
+
+    /* get next module in line */
+    modp = NEXT_HANDLER_MODULE(MP_HOOK_PROCESS_CONNECTION);
+
+    cloned = clone_ctx_state(ctxp, select_ctx_pool(modp, c->base_server, NULL),
+        c->base_server, c->pool);
+    if (cloned != ctxp) {
         release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
+        ctxp = cloned;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
+    ctxp->c = c;
+
+    /* get HLL config */
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    MP_TRACE_h(c->base_server, "calling process_connection_handler for %s", minfo->namespace); 
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "process_connection_handler", &status)) {
+        MPLOG_ERRORF(c->base_server,
+            "no process_connection metahandler found for module '%s'",
+            modp->name);
+        status = HTTP_INTERNAL_SERVER_ERROR;
+    }
 
     /* tell apache we're done */
-    return handler_status;
+    return status;
 }
 
-/* XXX - how do we notify apache of failures with a void return??? */
 static void modparrot_child_init_handler(apr_pool_t *p, server_rec *s)
 {
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
 
-    /* get apache configs */
-    cfg = ap_get_module_config(s->module_config, &parrot_module);
-
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) || !cfg->child_init_handler) {
-        return;
-    }
+    MP_TRACE_h(s, "in modparrot_child_init_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(s))) {
+    if (!(ctxp = init_ctx(s, NULL, NULL))) {
         MPLOG_ERROR(s, "context initialization failed");
         return;
     }
 
-    ctxp->pchild = p;
-    ctxp->s = s;
-
-    /* call HLL handler */
-    sub = "child_init_handler";
-    hll = cfg->child_init_handler->hll ?
-        cfg->child_init_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->child_init_handler->id, &handler_status)) {
-        MPLOG_ERRORF(s, "no subroutine found for handler '%s'",
-            cfg->child_init_handler->id);
-        return;
-    }
-
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return;
-}
-
-static int modparrot_trans_handler(request_rec *r)
-{
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
-
-    /* get apache configs */
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    /* politely decline request if not our handler */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) || !cfg->trans_handler) {
-        return DECLINED;
-    }
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* we're FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
-    ctxp->r = r;
+    /* query apache mpm for thread limits */
+#ifdef MPM_IS_THREADED
+    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &mp_globals.hard_thread_limit);
+    ap_mpm_query(AP_MPMQ_MAX_THREADS, &mp_globals.max_threads);
+#else /* MPM_IS_THREADED */
+    mp_globals.hard_thread_limit = 1;
+    mp_globals.max_threads = 1;
+#endif /* MPM_IS_THREADED */
 
-    /* call HLL handler */
-    sub = "trans_handler";
-    hll = cfg->trans_handler->hll ? 
-        cfg->trans_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->trans_handler->id, &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            cfg->trans_handler->id);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* set the most specific pool */
+    ctxp->pool = p;
 
-    /* clean up */
     release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
 }
 
-static int modparrot_fixup_handler(request_rec *r)
+/* XXX - how do we notify apache of failures with a void return??? */
+void modparrot_meta_child_init_handler(apr_pool_t *p, server_rec *s)
 {
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
+    modparrot_context *ctxp, *cloned;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(fixup_handler);
+    MP_TRACE_h(s, "in modparrot_meta_child_init_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "fixup_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
+    if (!(ctxp = init_ctx(s, NULL, NULL))) {
+        MPLOG_ERROR(s, "context initialization failed");
+        return;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
-}
-
-static int modparrot_type_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(type_handler);
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* decline if mod_parrot isn't enabled */
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return;
 
-    ctxp->r = r;
+    /* get next module in line */
+    modp = NEXT_HANDLER_MODULE(MP_HOOK_CHILD_INIT);
 
-    /* call HLL handler */
-    sub = "type_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
+    cloned = clone_ctx_state(ctxp, select_ctx_pool(modp, s, NULL), s, p);
+    if (cloned != ctxp) {
         release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
-}
-
-static int modparrot_log_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* politely decline request if we shouldn't be handling this */
-    if (!SHOULD_HANDLE(r)) {
-        return DECLINED;
-    }
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(log_handler);
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
+        ctxp = cloned;
     }
 
-    ctxp->r = r;
+    ctxp->pchild = p;
+    ctxp->s = s;
 
-    /* call HLL handler */
-    sub = "log_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
+    /* get HLL config */
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    MP_TRACE_h(s, "calling child_init_handler for %s", minfo->namespace);
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "child_init_handler", &status)) {
+        MPLOG_ERRORF(s, "no child_init metahandler found for module '%s'",
+            modp->name);
     }
 
-    /* clean up */
     release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
 }
 
-static int modparrot_access_handler(request_rec *r)
+static int modparrot_post_config_handler(apr_pool_t *pconf, apr_pool_t *plog,
+    apr_pool_t *ptemp, server_rec *s)
 {
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
 
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
+    MP_TRACE_h(s, "in modparrot_post_config_handler");
 
-    SET_HLL_HANDLER(access_handler);
+    /* add our version component */
+    ap_add_version_component(pconf, "mod_parrot/" MODPARROT_VERSION);
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for access handler '%s'",
-            dircfg->access_handler->id);
+    if (!(ctxp = init_ctx(s, ptemp, NULL))) {
+        MPLOG_ERROR(s, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-    ctxp->r = r;
 
-    /* call HLL handler */
-    sub = "access_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-            &handler_status)) {
-	MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
-    }
+    /* we're FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
-    /* clean up */
-    release_ctx(ctxp);
+    /* set the most specific pool */
+    ctxp->pool = pconf;
 
-    /* tell apache we're done */
-    return handler_status;
+    /* we only do setup */
+    return DECLINED;
 }
 
-static int modparrot_authen_handler(request_rec *r)
+int modparrot_meta_post_config_handler(apr_pool_t *pconf,
+    apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 {
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
+    modparrot_context *ctxp, *cloned;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(authen_handler);
+    MP_TRACE_h(s, "in modparrot_meta_post_config_handler");
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for authen handler '%s'",
-            dircfg->authen_handler->id);
+    if (!(ctxp = init_ctx(s, ptemp, NULL))) {
+        MPLOG_ERROR(s, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "authen_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-	MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
-    }
 
-    /* clean up */
-    release_ctx(ctxp);
+    /* decline if mod_parrot isn't enabled */
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
 
-    /* tell apache we're done */
-    return handler_status;
-}
+    /* get next module in line */
+    modp = NEXT_HANDLER_MODULE(MP_HOOK_POST_CONFIG);
 
-static int modparrot_authz_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
-
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(authz_handler);
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for authz handler '%s'",
-            dircfg->authz_handler->id);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "authz_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-	MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
+    cloned = clone_ctx_state(ctxp, select_ctx_pool(modp, s, NULL), s, ptemp);
+    if (cloned != ctxp) {
         release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
-}
-
-static int modparrot_post_config_handler(apr_pool_t *pconf, apr_pool_t *plog,
-    apr_pool_t *ptemp, server_rec *s)
-{
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
-
-    /* add our info to apache's version string */
-    ap_add_version_component(pconf, "mod_parrot/" MODPARROT_VERSION);
-
-    /* get apache configs */
-    cfg = ap_get_module_config(s->module_config, &parrot_module);
-
-    /* if not our handler, return OK (post_config must return OK) */
-    if (!(cfg->option_flags & MP_OPT_ENABLE) || !cfg->post_config_handler) {
-        return OK;
-    }
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(s))) {
-        MPLOG_ERROR(s, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
+        ctxp = cloned;
     }
 
     ctxp->pconf = pconf;
@@ -916,51 +778,52 @@
     ctxp->ptemp = ptemp;
     ctxp->s = s;
 
-    /* call HLL handler */
-    sub = "post_config_handler";
-    hll = cfg->post_config_handler->hll ?
-        cfg->post_config_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->post_config_handler->id, &handler_status)) {
-	MPLOG_ERRORF(s, "no subroutine found for handler '%s'",
-            cfg->post_config_handler->id);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
+    /* get HLL config */
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    MP_TRACE_h(s, "calling post_config_handler for %s", minfo->namespace);
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "post_config_handler", &status)) {
+        MPLOG_ERRORF(s, "no post_config metahandler found for module '%s'",
+            modp->name);
+        status = HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
-
     /* tell apache we're done */
-    return handler_status;
+    return status;
 }
 
 static int modparrot_open_logs_handler(apr_pool_t *pconf, apr_pool_t *plog,
     apr_pool_t *ptemp, server_rec *s)
 {
-    modparrot_srv_config *cfg;
     modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll;
+    modparrot_srv_config *mpcfg;
+    Parrot_Interp parent_interp;
     server_rec *vs;
-    Parrot_Interp parent_interp = NULL;
 
+    MP_TRACE_h(s, "in modparrot_open_logs_handler");
     /* get apache configs */
-    cfg = ap_get_module_config(s->module_config, &parrot_module);
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
 
-    if (cfg->option_flags & MP_OPT_ENABLE) {
-        if (!(ctxp = modparrot_startup(pconf, s, NULL))) {
+    if (mpcfg->option_flags & MP_OPT_ENABLE) {
+        if (!(ctxp = modparrot_startup(ptemp, s, NULL, NULL))) {
             return HTTP_INTERNAL_SERVER_ERROR;
         }
+        ctxp->pconf = pconf;
         parent_interp = ctxp->interp;
 
+        /* we're FIRST, so reset the module index */
+        ctxp->module_index = -1;
+
+        /* set the most specific pool */
+        ctxp->pool = pconf;
+
         /* load ParrotLoad files */
-        modparrot_load_files(ctxp->interp, s, cfg->preload);
+        modparrot_load_files(ctxp->interp, s, mpcfg->preload);
 
         /* if we weren't tracing the initialization phase, enable tracing now */
-        if (!(cfg->option_flags & MP_OPT_TRACE_INIT)) {
-            Parrot_set_trace(ctxp->interp, cfg->trace_flags);
+        if (!(mpcfg->option_flags & MP_OPT_TRACE_INIT)) {
+            Parrot_set_trace(ctxp->interp, mpcfg->trace_flags);
         }
     }
 
@@ -971,9 +834,16 @@
         vscfg = ap_get_module_config(vs->module_config, &parrot_module);
         if (!(vscfg->option_flags & MP_OPT_ENABLE)) continue;
         if (vscfg->option_flags & MP_OPT_PARENT) {
-            if (!(vsctxp = modparrot_startup(pconf, vs, parent_interp))) {
+            if (!(vsctxp = modparrot_startup(ptemp, vs, parent_interp, NULL))) {
                 return HTTP_INTERNAL_SERVER_ERROR;
             }
+            vsctxp->pconf = pconf;
+
+            /* we're FIRST, so reset the module index */
+            vsctxp->module_index = -1;
+
+            /* set the most specific pool */
+            ctxp->pool = pconf;
 
             /* load ParrotLoad files */
             modparrot_load_files(vsctxp->interp, vs, vscfg->preload);
@@ -984,115 +854,186 @@
             }
         }
         else {
+            /* XXX is this check redundant (MP_OPT_ENABLE is checked above) */
             if (vscfg->option_flags & MP_OPT_ENABLE) {
-                vscfg->ctx_pool = cfg->ctx_pool;
+                vscfg->ctx_pool = mpcfg->ctx_pool;
             }
             else {
-                MPLOG_ERROR(vs, "must use +Parent if mod_parrot is disabled in main server");
+                MPLOG_ERROR(vs,
+                "must use +Parent if mod_parrot is disabled in main server");
             }
         }
     }
 
-    /* if not our handler, return OK (open_logs must return OK) */
-    if (!cfg->open_logs_handler) {
-        return OK;
+    /* tell apache we're done -- open_logs handler must return OK */
+    return OK;
+}
+
+int modparrot_meta_open_logs_handler(apr_pool_t *pconf,
+    apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+{
+    apr_array_header_t *ctx_pool;
+    modparrot_context *ctxp, *cloned;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    server_rec *vs;
+    int status;
+
+    MP_TRACE_h(s, "in modparrot_meta_open_logs_handler (main server)");
+
+    /* initialize context */
+    if (!(ctxp = init_ctx(s, ptemp, NULL))) {
+        MPLOG_ERROR(s, "context initialization failed");
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* get next module in line */
+    modp = NEXT_HANDLER_MODULE(MP_HOOK_OPEN_LOGS);
+
+    cloned = clone_ctx_state(ctxp, select_ctx_pool(modp, s, NULL), s, ptemp);
+    if (cloned != ctxp) {
+        release_ctx(ctxp);
+        ctxp = cloned;
     }
 
+    /* decline if mod_parrot isn't enabled -- but open_logs must return OK */
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return OK;
+
     ctxp->pconf = pconf;
     ctxp->plog = plog;
     ctxp->ptemp = ptemp;
     ctxp->s = s;
 
-    /* call HLL handler */
-    sub = "open_logs_handler";
-    hll = cfg->open_logs_handler->hll ?
-        cfg->open_logs_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub,
-        cfg->open_logs_handler->id, &handler_status)) {
-	MPLOG_ERRORF(s, "no subroutine found for handler '%s'",
-            cfg->open_logs_handler->id);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
+    /* get HLL config */
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    MP_TRACE_h(s, "calling open_logs_handler for %s", minfo->namespace);
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "open_logs_handler", &status)) {
+        MPLOG_ERRORF(s, "no open_logs metahandler found for module '%s'",
+            modp->name);
+        status = HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
+    /* all open_logs handlers must return OK, so stop here if it didn't */
+    if (status != OK) return status;
 
-    /* tell apache we're done */
-    return handler_status;
-}
+    /* now do the same thing with each virtual host */
+    for (vs = s->next; vs; vs = vs->next) {
+        modparrot_srv_config *vscfg;
+        modparrot_module_config *cfg;
 
-static int modparrot_cleanup_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
+        vscfg = ap_get_module_config(vs->module_config, &parrot_module);
+        if (!(vscfg->option_flags & MP_OPT_ENABLE)) continue;
 
-    /* get apache configs */
-    dircfg = (modparrot_dir_config *)ap_get_module_config(r->per_dir_config, &parrot_module);
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
+        MP_TRACE_h(vs, "in modparrot_meta_open_logs_handler (s=%p)", vs);
 
-    SET_HLL_HANDLER(cleanup_handler);
+        /* we duplicate some efforts here because we only find out about
+         * named context pools configured from an HLL when we're already in
+         * that HLL's meta handler. got that? */
+
+        /* check for a per-server context pool */
+        cfg = ap_get_module_config(vs->module_config, modp);
+        if (cfg->ctx_pool_name) {
+            MP_TRACE_c(vs, "server %p has a per-server context pool '%s'", vs, cfg->ctx_pool_name);
+            if (!(ctxp = modparrot_startup(pconf, vs, NULL,
+                cfg->ctx_pool_name))) {
+                return HTTP_INTERNAL_SERVER_ERROR;
+            }
+            /* cache for later -- select_ctx_pool depends on it! */
+            cfg->ctx_pool = ctxp->ctx_pool;
+        }
+        else {
+            MP_TRACE_c(vs, "using default context pool for server %p", vs);
+        }
 
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for cleanup handler '%s'",
-            dircfg->cleanup_handler->id);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-    ctxp->r = r;
+        cloned = clone_ctx_state(ctxp,
+            select_ctx_pool(modp, vs, NULL), vs, ptemp);
+        if (cloned != ctxp) {
+            release_ctx(ctxp);
+            ctxp = cloned;
+        }
 
-    /* call HLL handler */
-    sub = "cleanup_handler";
-    if (!modparrot_hll_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
+        /* reset the server_rec, but everything else should be ok */
+        ctxp->s = vs;
 
-    /* clean up */
-    release_ctx(ctxp);
+        /* load ParrotLoad files */
+        modparrot_load_files(ctxp->interp, vs, vscfg->preload);
 
-    /* tell apache we're done */
-    return handler_status;
-}
+        /* if we weren't tracing the initialization phase, enable tracing */
+        if (!(vscfg->option_flags & MP_OPT_TRACE_INIT)) {
+            Parrot_set_trace(ctxp->interp, vscfg->trace_flags);
+        }
 
-static apr_status_t modparrot_request_cleanup(void *data)
-{
-    request_rec *r = (request_rec *)data;
-    modparrot_cleanup_handler(r);
-    return APR_SUCCESS;
+        /* get HLL config */
+        minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+
+        /* call meta handler */
+        MP_TRACE_h(vs, "calling open_logs_handler for %s", minfo->namespace);
+        if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+           "open_logs_handler", &status)) {
+            MPLOG_ERRORF(vs, "no open_logs metahandler found for module '%s'",
+                modp->name);
+            status = HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        /* all open_logs handlers must return OK, so stop here if it didn't */
+        if (status != OK) break;
+    }
+
+    /* tell apache we're done */
+    return status;
 }
 
 static void register_hooks(apr_pool_t *p)
 {
+    MP_TRACE_h(mp_globals.base_server, "in register_hooks");
+
+    /* initialize globals before we do anything else */
+    modparrot_init_globals(p);
+
     /* this allows <IfDefine MODPARROT> blocks */
     *(char **)apr_array_push(ap_server_config_defines) =
         (char *)apr_pstrdup(p, "MODPARROT");
 
-    /* register the various hooks */
-    ap_hook_post_config(modparrot_post_config_handler, NULL, NULL, APR_HOOK_FIRST);
-    ap_hook_child_init(modparrot_child_init_handler, NULL, NULL, APR_HOOK_FIRST);
-    ap_hook_pre_connection(modparrot_pre_connection_handler, NULL, NULL, APR_HOOK_FIRST);
-    ap_hook_process_connection(modparrot_process_connection_handler, NULL, NULL, APR_HOOK_FIRST);
-    ap_hook_map_to_storage(modparrot_map_to_storage_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_translate_name(modparrot_trans_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_post_read_request(modparrot_post_read_request_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_header_parser(modparrot_header_parser_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_handler(modparrot_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_type_checker(modparrot_type_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_fixups(modparrot_fixup_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_log_transaction(modparrot_log_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
+    /* register the various hooks.  all request phase hooks are handled by
+     * modparrot_request_phase_handler, as the calling conventions and
+     * and semantics of each hook in this phase are identical.
+     */
     ap_hook_open_logs(modparrot_open_logs_handler, NULL, NULL, APR_HOOK_FIRST);
-    ap_hook_access_checker(modparrot_access_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_check_user_id(modparrot_authen_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
-    ap_hook_auth_checker(modparrot_authz_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
+    ap_hook_post_config(modparrot_post_config_handler, NULL, NULL,
+        APR_HOOK_FIRST);
+    ap_hook_child_init(modparrot_child_init_handler, NULL, NULL,
+        APR_HOOK_FIRST);
+    ap_hook_pre_connection(modparrot_pre_connection_handler, NULL, NULL,
+        APR_HOOK_FIRST);
+    ap_hook_process_connection(modparrot_process_connection_handler, NULL,
+        NULL, APR_HOOK_FIRST);
+    ap_hook_map_to_storage(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_translate_name(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_post_read_request(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_header_parser(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_access_checker(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_check_user_id(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_auth_checker(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_handler(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_type_checker(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_fixups(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
+    ap_hook_log_transaction(modparrot_request_phase_handler, NULL, NULL,
+        APR_HOOK_REALLY_FIRST);
 }
 
 static const command_rec modparrot_cmds[] =
@@ -1105,144 +1046,18 @@
         "modparrot initialization file"
     ),
     AP_INIT_TAKE1(
-        "ParrotTrace",
-        modparrot_cmd_trace,
-        NULL,
-        RSRC_CONF,
-        "enable Parrot opcode tracing (default is off)"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotOpenLogsHandler",
-        modparrot_cmd_open_logs_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot open logs handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotChildInitHandler",
-        modparrot_cmd_child_init_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot child init handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotChildExitHandler",
-        modparrot_cmd_child_exit_handler,
+        "ParrotDebugLevel",
+        modparrot_cmd_debug,
         NULL,
         RSRC_CONF,
-        "set the Parrot child exit handler"
+        "set mod_parrot debugging level (default is 0)"
     ),
     AP_INIT_TAKE1(
-        "ParrotPostConfigHandler",
-        modparrot_cmd_post_config_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot child exit handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotPreConnectionHandler",
-        modparrot_cmd_pre_connection_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot pre-connection handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotProcessConnectionHandler",
-        modparrot_cmd_process_connection_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot process-connection handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotMapToStorageHandler",
-        modparrot_cmd_map_to_storage_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot map to storage handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotTransHandler",
-        modparrot_cmd_trans_handler,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot trans handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotPostReadRequestHandler",
-        modparrot_cmd_post_read_request_handler,
+        "ParrotTrace",
+        modparrot_cmd_trace,
         NULL,
         RSRC_CONF,
-        "set the Parrot post read request handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotHeaderParserHandler",
-        modparrot_cmd_header_parser_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot header parser handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotHandler",
-        modparrot_cmd_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot response handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotAccessHandler",
-        modparrot_cmd_access_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot access handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotAuthenHandler",
-        modparrot_cmd_authen_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot authentication handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotAuthzHandler",
-        modparrot_cmd_authz_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot authorization handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotTypeHandler",
-        modparrot_cmd_type_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot type handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotFixupHandler",
-        modparrot_cmd_fixup_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot fixup handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotLogHandler",
-        modparrot_cmd_log_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot log handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotCleanupHandler",
-        modparrot_cmd_cleanup_handler,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot cleanup handler"
-    ),
-    AP_INIT_TAKE1(
-        "ParrotLanguage",
-        modparrot_cmd_language,
-        NULL,
-        OR_AUTHCFG,
-        "set the Parrot language"
+        "set Parrot opcode tracing level (default is 0)"
     ),
     AP_INIT_ITERATE(
         "ParrotLoad",
@@ -1251,7 +1066,7 @@
         RSRC_CONF,
         "preload Parrot code"
     ),
-    AP_INIT_ITERATE(
+    AP_INIT_TAKE12(
         "ParrotLoadImmediate",
         modparrot_cmd_load_immediate,
         NULL,
@@ -1265,19 +1080,19 @@
         RSRC_CONF,
         "set the Parrot include path"
     ),
-    AP_INIT_ITERATE2(
-        "ParrotAddType",
-        modparrot_cmd_add_type,
+    AP_INIT_TAKE1(
+        "ParrotLibPath",
+        modparrot_cmd_lib_path,
         NULL,
         RSRC_CONF,
-        "associate a MIME type with a mod_parrot HLL"
+        "set the Parrot library path"
     ),
-    AP_INIT_ITERATE2(
-        "ParrotAddHandler",
-        modparrot_cmd_add_handler,
+    AP_INIT_TAKE1(
+        "ParrotDynextPath",
+        modparrot_cmd_dynext_path,
         NULL,
         RSRC_CONF,
-        "associate a handler string with a mod_parrot HLL"
+        "set the Parrot dynext path"
     ),
     AP_INIT_ITERATE(
         "ParrotOptions",
@@ -1292,8 +1107,8 @@
 module AP_MODULE_DECLARE_DATA parrot_module =
 {
     STANDARD20_MODULE_STUFF,
-    create_modparrot_dir_config,
-    NULL, /* merge_modparrot_dir_config, */
+    NULL, /* create_modparrot_dir_config */
+    NULL, /* merge_modparrot_dir_config */
     create_modparrot_srv_config,
     merge_modparrot_srv_config,
     modparrot_cmds,

Modified: mod_parrot/branches/configure/src/modparrot_config.c
==============================================================================
--- mod_parrot/branches/configure/src/modparrot_config.c	(original)
+++ mod_parrot/branches/configure/src/modparrot_config.c	Sat May  2 06:55:00 2009
@@ -29,6 +29,11 @@
 #include "modparrot_config.h"
 #include "modparrot_log.h"
 
+#if (__FreeBSD__)
+# include <dlfcn.h>
+# include "apr_dso.h"
+#endif /* (__FreeBSD__) */
+
 #define GET_SERVER_CONFIG(x) \
  ((modparrot_srv_config *)ap_get_module_config(\
  x->server->module_config, &parrot_module))
@@ -36,48 +41,82 @@
 #define DEFAULT_OPTION_FLAGS (MP_OPT_ENABLE)
 
 extern module AP_MODULE_DECLARE_DATA parrot_module;
-extern int mp_is_started;
+extern modparrot_globals mp_globals;
 
 static apr_status_t modparrot_cleanup(void *data)
 {
     modparrot_srv_config *cfg;
     server_rec *s = (server_rec *)data;
+    int i;
 
     cfg = ap_get_module_config(s->module_config, &parrot_module);
-    mp_ctx_pool_destroy(cfg->ctx_pool);
+
+    /* destroy context pools and interpreters */
+    mp_ctx_pool_destroy_all();
     cfg->ctx_pool = NULL;
-    mp_is_started = 0;
+    mp_globals.is_started = 0;
 
+    /* reset module configs so we recreate them on restart */
+    for (i = 0; i < mp_globals.module_array->nelts; i++) {
+        modparrot_module_config *modcfg;
+        modcfg = ((modparrot_module_config **)mp_globals.module_array->elts)[i];
+        modcfg->cfg = NULL;
+    }
     return APR_SUCCESS;
 }
 
 void *create_modparrot_srv_config(apr_pool_t *p, server_rec *s)
 {
     modparrot_srv_config *cfg;
+    int i;
 
     cfg = (modparrot_srv_config *)apr_pcalloc(p, sizeof(modparrot_srv_config));
+    cfg->ctx_pool = NULL;
     cfg->pool = p;
     cfg->trace_flags = -1; /* -1 == unspecified */
     cfg->enable_option_flags = 0; /* only used during configuration merge */
     cfg->disable_option_flags = 0; /* only used during configuration merge */
     cfg->option_flags = DEFAULT_OPTION_FLAGS; /* set default options here */
     cfg->init_path = NULL;
-    cfg->preload = apr_array_make(p, 2, sizeof(modparrot_handler_info));
+    cfg->preload = apr_array_make(p, 2, sizeof(char *));
     cfg->include_path = NULL;
-    cfg->type_map = apr_table_make(p, 2);
-    cfg->handler_map = apr_table_make(p, 2);
+    cfg->lib_path = NULL;
+    cfg->dynext_path = NULL;
 
-    /* destroy context pool on cleanup */
-    apr_pool_cleanup_register(p, s, modparrot_cleanup, apr_pool_cleanup_null);
-
-    /* set default HLL to PIR */
-    apr_table_set(cfg->handler_map, MODPARROT_MAGIC, MODPARROT_DEFAULT_HLL);
+    /* unfortunately, some OS-specific stuff */
+#if (__FreeBSD__)
+    {
+        apr_os_dso_handle_t *osdso;
+        char origin[PATH_MAX];
+        apr_os_dso_handle_get((void *)&osdso,
+            parrot_module.dynamic_load_handle);
+        if (dlinfo(osdso, RTLD_DI_ORIGIN, &origin) != -1) {
+            /* we know it's a Unix variant, so we can assume '/' and .so */
+            char *path = apr_pstrcat(p, origin, "/", "mod_parrot.so", NULL);
+            cfg->so_path = path;
+        }
+        else {
+            cfg->so_path = NULL;
+            fprintf(stderr, "dlinfo: %s", dlerror());
+        }
+    }
+#else /* (__FreeBSD__) */
+    cfg->so_path = NULL;
+#endif /* (__FreeBSD__) */
+
+    /* if we will have our own pool, destroy context pool on cleanup */
+    if (!s->is_virtual ||
+        (s->is_virtual && (cfg->option_flags | MP_OPT_PARENT))) {
+        apr_pool_cleanup_register(p, s, modparrot_cleanup,
+            apr_pool_cleanup_null);
+    }
 
     return (void *)cfg;
 }
 
 void *merge_modparrot_srv_config(apr_pool_t *p, void *base, void *new)
 {
+    int i;
     modparrot_srv_config *basecfg = (modparrot_srv_config *)base;
     modparrot_srv_config *newcfg = (modparrot_srv_config *)new;
     modparrot_srv_config *merged = (modparrot_srv_config *)
@@ -101,26 +140,26 @@
         merged->option_flags &= ~(newcfg->disable_option_flags);
     }
 
-    /* merge type and handler maps */
-    merged->type_map = apr_table_copy(p, basecfg->type_map);
-    apr_table_overlap(merged->type_map, newcfg->type_map,
-        APR_OVERLAP_TABLES_SET);
-    merged->handler_map = apr_table_copy(p, basecfg->handler_map);
-    apr_table_overlap(merged->handler_map, newcfg->handler_map,
-        APR_OVERLAP_TABLES_SET);
+    /* inherit the init_path, since it's rare it will change for a vhost */
+    merged->init_path = newcfg->init_path ?
+        newcfg->init_path : basecfg->init_path;
 
     /* merges specific to the Parent option */
     if (newcfg->option_flags & MP_OPT_PARENT) {
-        merged->include_path = newcfg->include_path ?
-            newcfg->include_path : basecfg->include_path;
         merged->trace_flags = newcfg->trace_flags;
-        merged->init_path = newcfg->init_path;
         merged->preload = apr_array_copy(p, newcfg->preload);
+        merged->include_path = newcfg->include_path;
+        merged->lib_path = newcfg->lib_path;
+        merged->dynext_path = newcfg->dynext_path;
     }
     else {
         /* just override the scalars */
-        merged->init_path = newcfg->init_path ?
-            newcfg->init_path : basecfg->init_path;
+        merged->include_path = newcfg->include_path ?
+            newcfg->include_path : basecfg->include_path;
+        merged->lib_path = newcfg->lib_path ?
+            newcfg->lib_path : basecfg->lib_path;
+        merged->dynext_path = newcfg->dynext_path ?
+            newcfg->dynext_path : basecfg->dynext_path;
         merged->trace_flags = (newcfg->trace_flags != -1) ?
             newcfg->trace_flags : basecfg->trace_flags;
 
@@ -132,104 +171,6 @@
     return (void *)merged;
 }
 
-void *create_modparrot_dir_config(apr_pool_t *p, char *path)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)apr_pcalloc(p, sizeof(modparrot_dir_config));
-    if (path == NULL) {
-        cfg->directory = NULL;
-    }
-    else {
-        cfg->directory = (char *)apr_pstrdup(p, path);
-    }
-    cfg->hll = NULL;
-    cfg->handler = NULL;
-
-    return (void *)cfg;
-}
-
-/* this is too messy for a simple override merge -- punt for now */
-#if 0
-void *merge_modparrot_dir_config(apr_pool_t *p, void *base, void *new)
-{
-    modparrot_dir_config *basecfg = (modparrot_dir_config *)base;
-    modparrot_dir_config *newcfg = (modparrot_dir_config *)new;
-    modparrot_dir_config *merged = (modparrot_dir_config *)
-        apr_pcalloc(p, sizeof(modparrot_dir_config));
-
-    merged->directory = (char *)apr_pstrdup(p, newcfg->directory);
-
-    if (newcfg->hll) {
-        merged->hll = (char *)apr_pstrdup(p, newcfg->hll);
-    }
-    else {
-        merged->hll =
-            basecfg->hll ? (char *)apr_pstrdup(p, basecfg->hll) : NULL;
-    }
-
-    if (newcfg->handler) {
-        merged->handler = (modparrot_handler_info *)apr_pmemdup(p, newcfg->handler, sizeof(modparrot_handler_info));
-    }
-    else {
-        merged->handler =
-            basecfg->handler ? (modparrot_handler_info *)apr_pmemdup(p, basecfg->handler, sizeof(modparrot_handler_info)) : NULL;
-    }
-
-    if (newcfg->access_handler) {
-        merged->access_handler = (modparrot_handler_info *)apr_pmemdup(p, newcfg->access_handler, sizeof(modparrot_handler_info));
-    }
-    else {
-        merged->access_handler =
-            basecfg->access_handler ? (modparrot_handler_info *)apr_pmemdup(p, basecfg->access_handler, sizeof(modparrot_handler_info)) : NULL;
-    }
-
-    if (newcfg->authen_handler) {
-        merged->authen_handler = (modparrot_handler_info *)apr_pmemdup(p, newcfg->authen_handler, sizeof(modparrot_handler_info));
-    }
-    else {
-        merged->authen_handler =
-            basecfg->authen_handler ? (modparrot_handler_info *)apr_pmemdup(p, basecfg->authen_handler, sizeof(modparrot_handler_info)) : NULL;
-    }
-
-    if (newcfg->authz_handler) {
-        merged->authz_handler = (modparrot_handler_info *)apr_pmemdup(p, newcfg->authz_handler, sizeof(modparrot_handler_info));
-    }
-    else {
-        merged->authz_handler = 
-            basecfg->authz_handler ? (modparrot_handler_info *)apr_pmemdup(p, basecfg->authz_handler, sizeof(modparrot_handler_info)) : NULL;
-    }
-
-    return (void *)merged;
-}
-#endif
-
-/* parses a handler into the handler ID and the HLL
- * if 'l' is NULL, will allocate handler info itself
- */
-static modparrot_handler_info *parse_handler(apr_pool_t *p, const char *handler,
-    modparrot_handler_info *l)
-{
-    char *part;
-
-    if (!l) {
-        l = (modparrot_handler_info *)apr_pcalloc(p,
-            sizeof(modparrot_handler_info));
-    }
-
-    /* split handler into HLL and ID */
-    if ((part = strchr((char *)handler, ','))) {
-        l->hll = apr_pstrndup(p, handler, part-handler);
-        l->id = apr_pstrdup(p, part+1);
-    }
-    else {
-        l->hll = 0;
-        l->id = apr_pstrdup(p, handler);
-    }
-
-    return(l);
-}
-
 /* calculate option bit vector from enabled and disabled bits */
 void modparrot_recalc_options(modparrot_srv_config *cfg)
 {
@@ -264,6 +205,18 @@
     return 1;
 }
 
+const char *modparrot_cmd_debug(cmd_parms *cmd, void *mconfig, const char *f)
+{
+    if (cmd->server->is_virtual) {
+        MPLOG_WARN(cmd->server, "WARNING: ignoring ParrotDebugLevel in VirtualHost");
+    }
+    else {
+        mp_globals.debug_level = atoi(f);
+    }
+
+    return NULL;
+}
+
 const char *modparrot_cmd_trace(cmd_parms *cmd, void *mconfig, const char *f)
 {
     modparrot_srv_config *cfg;
@@ -276,228 +229,40 @@
 }
 
 const char *modparrot_cmd_load(cmd_parms *cmd, void *mconfig,
-    const char *handler)
+    const char *path)
 {
     modparrot_srv_config *cfg;
-    modparrot_handler_info *l;
 
     cfg = GET_SERVER_CONFIG(cmd);
-    l = (modparrot_handler_info *)apr_array_push(cfg->preload);
-    parse_handler(cmd->pool, handler, l);
+    *(char **)apr_array_push(cfg->preload) = apr_pstrdup(cmd->pool, path);
 
     return NULL;
 }
 
 const char *modparrot_cmd_load_immediate(cmd_parms *cmd, void *mconfig,
-    const char *handler)
+    const char *path, const char *pool_name)
 {
     modparrot_srv_config *cfg;
-    modparrot_handler_info *l;
     modparrot_context *ctxp;
 
     cfg = GET_SERVER_CONFIG(cmd);
-    l = (modparrot_handler_info *)apr_array_push(cfg->preload);
-
-    /* XXX how do we get the context if we've already started? */
-    if (!mp_is_started) {
-        ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    }
 
-    parse_handler(cmd->pool, handler, l);
-    modparrot_load_file(ctxp->interp, cmd->server, l->hll, l->id);
+    /* this will start the interpreter if necessary and return a context */
+    ctxp = modparrot_startup(cmd->temp_pool, cmd->server, NULL, pool_name);
+    ctxp->pconf = cmd->pool;
+
+    modparrot_load_file(ctxp->interp, cmd->server, path);
+
+    /* push onto the preload array so other interpreters can see the HLL
+     * module.  modparrot_add_module won't add the module to apache again,
+     * and parrot *shouldn't* try to load the bytecode again for the same
+     * interpreter.
+     */
+    *(char **)apr_array_push(cfg->preload) = apr_pstrdup(cmd->pool, path);
 
     return NULL;
 }
 
-const char *modparrot_cmd_open_logs_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->open_logs_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_post_config_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->post_config_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_child_init_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->child_init_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_child_exit_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->child_exit_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_pre_connection_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->pre_connection_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_process_connection_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->process_connection_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_map_to_storage_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->map_to_storage_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_trans_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->trans_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_post_read_request_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_srv_config *cfg;
-
-    cfg = GET_SERVER_CONFIG(cmd);
-    cfg->post_read_request_handler =parse_handler(cmd->pool, handler, NULL); 
-    return NULL;
-}
-
-const char *modparrot_cmd_input_filter_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->input_filter_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_output_filter_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->output_filter_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_header_parser_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->header_parser_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_access_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->access_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_authen_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->authen_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_authz_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-                                                                                                                             
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->authz_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_type_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->type_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_fixup_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->fixup_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_log_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->log_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_cleanup_handler(cmd_parms *cmd, void *mconfig, const char *handler)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->cleanup_handler = parse_handler(cmd->pool, handler, NULL);
-    return NULL;
-}
-
-const char *modparrot_cmd_language(cmd_parms *cmd, void *mconfig, const char *hll)
-{
-    modparrot_dir_config *cfg;
-
-    cfg = (modparrot_dir_config *)mconfig;
-    cfg->hll = (char *)apr_pstrdup(cmd->pool, hll);
-    return NULL;
-}
-
 const char *modparrot_cmd_init(cmd_parms *cmd, void *mconfig, const char *path)
 {
     modparrot_srv_config *cfg;
@@ -516,21 +281,21 @@
     return NULL;
 }
 
-const char *modparrot_cmd_add_type(cmd_parms *cmd, void *mconfig, const char *hll, const char *mtype)
+const char *modparrot_cmd_lib_path(cmd_parms *cmd, void *mconfig, const char *path)
 {
     modparrot_srv_config *cfg;
 
     cfg = GET_SERVER_CONFIG(cmd);
-    apr_table_set(cfg->type_map, mtype, hll);
+    cfg->lib_path = (char *)apr_pstrdup(cmd->pool, path);
     return NULL;
 }
 
-const char *modparrot_cmd_add_handler(cmd_parms *cmd, void *mconfig, const char *hll, const char *handler)
+const char *modparrot_cmd_dynext_path(cmd_parms *cmd, void *mconfig, const char *path)
 {
     modparrot_srv_config *cfg;
 
     cfg = GET_SERVER_CONFIG(cmd);
-    apr_table_set(cfg->handler_map, handler, hll);
+    cfg->dynext_path = (char *)apr_pstrdup(cmd->pool, path);
     return NULL;
 }
 
@@ -559,128 +324,3 @@
     }
     return errmsg;
 }
-
-static Parrot_PMC make_cmd_args_array(Parrot_Interp interp, apr_pool_t *p,
-    int nargs, ...)
-{
-    va_list ap;
-    Parrot_PMC args;
-    int i=0, typenum;
-
-    typenum = Parrot_PMC_typenum(interp, "SArray");
-    args = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
-    Parrot_register_pmc(interp, args);
-    Parrot_PMC_set_intval(interp, args, nargs);
-
-    va_start(ap, nargs);
-    for (i = 0; i < nargs; i++) {
-        char *arg = va_arg(ap, char *);
-        Parrot_PMC_set_cstring_intkey(interp, args, i, arg);
-    }
-    va_end(ap);
-
-    return(args);
-}
-
-static void set_mp_config_vectors(modparrot_context *ctxp, cmd_parms *cmd)
-{
-    modparrot_dir_config *cfg = (modparrot_dir_config *)ap_set_config_vectors(
-        cmd->server, cmd->context, cmd->path, &parrot_module, cmd->pool);
-    ctxp->dircfg = cfg;
-    ctxp->srvcfg = (modparrot_srv_config *)ap_get_module_config(
-        cmd->server->module_config, &parrot_module);
-}
-
-const char *modparrot_module_cmd_take1(cmd_parms *cmd, void *mconfig,
-                                       const char *arg)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC dircfg;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    set_mp_config_vectors(ctxp, cmd);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 1, arg);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}
-
-const char *modparrot_module_cmd_take2(cmd_parms *cmd, void *mconfig,
-                                       const char *arg1,
-                                       const char *arg2)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 2, arg1, arg2);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}
-
-const char *modparrot_module_cmd_take12(cmd_parms *cmd, void *mconfig,
-                                       const char *arg1,
-                                       const char *arg2)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 2, arg1, arg2);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}
-
-const char *modparrot_module_cmd_take3(cmd_parms *cmd, void *mconfig,
-                                       const char *arg1,
-                                       const char *arg2,
-                                       const char *arg3)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 3, arg1, arg2, arg3);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}
-
-const char *modparrot_module_cmd_take23(cmd_parms *cmd, void *mconfig,
-                                       const char *arg1,
-                                       const char *arg2,
-                                       const char *arg3)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 3, arg1, arg2, arg3);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}
-
-const char *modparrot_module_cmd_take123(cmd_parms *cmd, void *mconfig,
-                                       const char *arg1,
-                                       const char *arg2,
-                                       const char *arg3)
-{
-    modparrot_context *ctxp;
-    Parrot_PMC args;
-    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
-    int ret;
-
-    ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    args = make_cmd_args_array(ctxp->interp, cmd->pool, 3, arg1, arg2, arg3);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
-    return NULL;
-}

Modified: mod_parrot/branches/configure/src/module.c
==============================================================================
--- mod_parrot/branches/configure/src/module.c	(original)
+++ mod_parrot/branches/configure/src/module.c	Sat May  2 06:55:00 2009
@@ -24,6 +24,7 @@
 #include "http_connection.h"
 #include "http_main.h"
 #include "mpm.h"
+#include "apr_strings.h"
 
 #include "parrot/parrot.h"
 #include "parrot/embed.h"
@@ -33,9 +34,9 @@
 #include "modparrot_config.h"
 #include "modparrot_log.h"
 
-extern module AP_MODULE_DECLARE_DATA parrot_module;
 AP_DECLARE_DATA extern module *ap_top_module;
-const char *modparrot_cmd_test(cmd_parms *, void *, const char *);
+extern module AP_MODULE_DECLARE_DATA parrot_module;
+extern modparrot_globals mp_globals;
 
 static apr_status_t modparrot_remove_module(void *data)
 {
@@ -58,19 +59,416 @@
     }
 }
 
+static modparrot_module_config *modparrot_create_module_config(apr_pool_t *p)
+{
+    modparrot_module_config *cfg = (modparrot_module_config *)apr_pcalloc(p,
+        sizeof(modparrot_module_config));
+    return(cfg);
+}
+
+void *modparrot_module_srv_create(apr_pool_t *p, server_rec *s)
+{
+    modparrot_module_config *cfg = modparrot_create_module_config(p);
+    return(cfg);
+}
+
+void *modparrot_module_srv_merge(apr_pool_t *p, void *base, void *new)
+{
+    modparrot_module_config *basecfg =(modparrot_module_config *)base;
+    modparrot_module_config *newcfg =(modparrot_module_config *)new;
+    modparrot_module_config *mergedcfg = modparrot_create_module_config(p);
+    modparrot_srv_config *mpcfg =
+        ap_get_module_config(mp_globals.base_server->module_config, &parrot_module);
+    module *modp = apr_hash_get(mp_globals.module_hash, basecfg->name,
+        APR_HASH_KEY_STRING);
+    modparrot_module_info *minfo = modp->dynamic_load_handle;
+
+    /* if we're here, then by definition we have a merge sub -- MAKE SURE! */
+    assert(minfo->server_merge_sub);
+
+    /* grab our current context.  the pool should be the config pool */
+    modparrot_context *ctxp = modparrot_get_current_ctx(p);
+    assert(ctxp);
+
+    mergedcfg->name = basecfg->name; /* XXX should we copy this instead? */
+    mergedcfg->minfo = basecfg->minfo;
+    mergedcfg->ctx_pool_name = apr_pstrdup(p, newcfg->ctx_pool_name ?
+        newcfg->ctx_pool_name : basecfg->ctx_pool_name);
+    mergedcfg->ctx_pool = newcfg->ctx_pool ?
+        newcfg->ctx_pool : basecfg->ctx_pool;
+
+    /* unregister existing config */
+    if (mergedcfg->cfg) {
+        if (!PMC_IS_NULL(mergedcfg->cfg)) {
+            Parrot_unregister_pmc(ctxp->interp, mergedcfg->cfg);
+        }
+    }
+
+    /* call merge routine */
+    MP_TRACE_m(mp_globals.base_server, "calling server_merge for module '%s'", modp->name);
+    mergedcfg->cfg = Parrot_call_sub(ctxp->interp, minfo->server_merge_sub,
+        "PPP", basecfg->cfg, newcfg->cfg);
+
+    /* register merged config */
+    if (!PMC_IS_NULL(mergedcfg->cfg)) {
+        Parrot_register_pmc(ctxp->interp, mergedcfg->cfg);
+    }
+
+    return mergedcfg;
+}
+
+void *modparrot_module_dir_create(apr_pool_t *p, char *path)
+{
+    modparrot_module_config *cfg = modparrot_create_module_config(p);
+    return(cfg);
+}
+
+void *modparrot_module_dir_merge(apr_pool_t *p, void *base, void *new)
+{
+    modparrot_module_config *basecfg =(modparrot_module_config *)base;
+    modparrot_module_config *newcfg =(modparrot_module_config *)new;
+    modparrot_module_config *mergedcfg = modparrot_create_module_config(p);
+    modparrot_srv_config *mpcfg =
+        ap_get_module_config(mp_globals.base_server->module_config, &parrot_module);
+    module *modp = apr_hash_get(mp_globals.module_hash, basecfg->name,
+        APR_HASH_KEY_STRING);
+    modparrot_module_info *minfo = modp->dynamic_load_handle;
+
+    /* if we're here, then by definition we have a merge sub -- MAKE SURE! */
+    assert(minfo->dir_merge_sub);
+
+    /* grab our current context.  we might be using the request pool before
+     * we've begun the request phase, also check for the context bound to
+     * the connection pool, which is the parent of the request pool */
+    modparrot_context *ctxp = modparrot_get_current_ctx(p);
+    if (!ctxp) ctxp = modparrot_get_current_ctx(apr_pool_parent_get(p));
+    assert(ctxp);
+    
+    mergedcfg->name = basecfg->name; /* XXX should we copy this instead? */
+    mergedcfg->minfo = basecfg->minfo;
+    mergedcfg->ctx_pool_name = apr_pstrdup(p, newcfg->ctx_pool_name ?
+        newcfg->ctx_pool_name : basecfg->ctx_pool_name);
+    mergedcfg->ctx_pool = newcfg->ctx_pool ?
+        newcfg->ctx_pool : basecfg->ctx_pool;
+
+    /* unregister existing config */
+    if (mergedcfg->cfg) {
+        if (!PMC_IS_NULL(mergedcfg->cfg)) {
+            Parrot_unregister_pmc(ctxp->interp, mergedcfg->cfg);
+        }
+    }
+
+    /* call merge routine */
+    MP_TRACE_m(mp_globals.base_server, "calling dir_merge for module '%s'", modp->name);
+    mergedcfg->cfg = Parrot_call_sub(ctxp->interp, minfo->dir_merge_sub,
+        "PPP", basecfg->cfg, newcfg->cfg);
+
+    /* register merged config */
+    if (!PMC_IS_NULL(mergedcfg->cfg)) {
+        Parrot_register_pmc(ctxp->interp, mergedcfg->cfg);
+    }
+ 
+    return(mergedcfg);
+}
+
+static Parrot_PMC make_cmd_args_array(Parrot_Interp interp, apr_pool_t *p,
+    int nargs, ...)
+{
+    va_list ap;
+    Parrot_PMC args;
+    int i=0, typenum;
+
+    typenum = Parrot_PMC_typenum(interp, "ResizablePMCArray");
+    args = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
+    Parrot_register_pmc(interp, args);
+    Parrot_PMC_set_intval(interp, args, nargs);
+
+    va_start(ap, nargs);
+    for (i = 0; i < nargs; i++) {
+        char *arg = va_arg(ap, char *);
+        if (arg) {
+            Parrot_PMC_set_cstring_intkey(interp, args, i, arg);
+        }
+        else {
+            Parrot_PMC_set_pmc_intkey(interp, args, i, PMCNULL);
+        }
+    }
+    va_end(ap);
+
+    return(args);
+}
+
+static const char *modparrot_module_cmd_take123(cmd_parms *cmd, void *mconfig,
+                                       const char *arg1,
+                                       const char *arg2,
+                                       const char *arg3)
+{
+    modparrot_context *ctxp;
+    Parrot_PMC args;
+    Parrot_PMC parms_pmc;
+    modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
+    modparrot_module_info *minfo = data->modp->dynamic_load_handle;
+    modparrot_module_config *srvcfg, *dircfg;
+    const char *ctx_pool_name;
+    int ret;
+
+    MP_TRACE_m(cmd->server, \
+               "in modparrot_module_cmd_take123 for directive '%s'", \
+               cmd->directive->directive);
+
+    /* mod_parrot specific stuff */
+    if (!minfo->ctx_pool_name) {
+        ctx_pool_name = modparrot_get_ctx_pool_name(minfo->ctx_pool);
+        minfo->ctx_pool_name = ctx_pool_name;
+    }
+    else {
+        ctx_pool_name = minfo->ctx_pool_name;
+    }
+    ctxp = modparrot_startup(cmd->temp_pool, cmd->server, NULL, ctx_pool_name);
+    ctxp->pconf = cmd->pool;
+
+    /* create a ModParrot;Apache;CmdParms object to pass to the handlers */
+    parms_pmc = modparrot_wrap_cmd_parms(ctxp->interp, cmd);
+    Parrot_register_pmc(ctxp->interp, parms_pmc);
+
+    /* create/fetch module server config */
+    srvcfg = (modparrot_module_config *)ap_get_module_config(
+        cmd->server->module_config, data->modp);
+    ctxp->raw_srv_config = srvcfg;
+    if (srvcfg) {
+        if (!srvcfg->cfg) {
+            srvcfg->name = apr_pstrdup(cmd->pool, data->modp->name);
+            if (minfo->server_create_sub) {
+                MP_TRACE_m(cmd->server, \
+                    "calling server_create for module '%s'", srvcfg->name);
+                srvcfg->cfg = Parrot_call_sub(ctxp->interp,
+                    minfo->server_create_sub, "PP", parms_pmc);
+                if (!PMC_IS_NULL(srvcfg->cfg)) {
+                    Parrot_register_pmc(ctxp->interp, srvcfg->cfg);
+                }
+            }
+        }
+    }
+
+    /* create/fetch module directory config */
+    dircfg = (modparrot_module_config *)mconfig;
+    ctxp->raw_dir_config = dircfg;
+    if (dircfg) {
+        if (!dircfg->cfg) {
+            dircfg->name = apr_pstrdup(cmd->pool, data->modp->name);
+            if (minfo->dir_create_sub) {
+                MP_TRACE_m(cmd->server, \
+                    "calling dir_create for module '%s'", srvcfg->name);
+                dircfg->cfg = Parrot_call_sub(ctxp->interp,
+                    minfo->dir_create_sub, "PP", parms_pmc);
+                if (!PMC_IS_NULL(dircfg->cfg)) {
+                    Parrot_register_pmc(ctxp->interp, dircfg->cfg);
+                }
+            }
+        }
+    }
+
+    args = make_cmd_args_array(ctxp->interp, cmd->pool, 3, arg1, arg2, arg3);
+
+    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IPPP", parms_pmc,
+        dircfg->cfg, args);
+
+    /* we might not get a chance to clear these later, so do it now */
+    ctxp->raw_srv_config = ctxp->raw_dir_config = NULL;
+
+    Parrot_unregister_pmc(ctxp->interp, parms_pmc);
+
+    return NULL;
+}
+
+static const char *modparrot_module_cmd_take1(cmd_parms *cmd, void *mconfig,
+                                      const char *arg)
+{
+    return modparrot_module_cmd_take123(cmd, mconfig, arg, NULL, NULL);
+}
+
+
+static const char *modparrot_module_cmd_take2(cmd_parms *cmd, void *mconfig,
+                                      const char *arg1, const char *arg2)
+{
+    return modparrot_module_cmd_take123(cmd, mconfig, arg1, arg2, NULL);
+}
+
+static const char *modparrot_module_cmd_no_args(cmd_parms *cmd, void *mconfig)
+{
+    return modparrot_module_cmd_take123(cmd, mconfig, NULL, NULL, NULL);
+}
+
+static const char *modparrot_module_cmd_flag(cmd_parms *cmd, void *mconfig,
+                                             int flag)
+{
+    char buf[2];
+
+    apr_snprintf(buf, sizeof(buf), "%d", flag);
+    return modparrot_module_cmd_take123(cmd, mconfig, NULL, NULL, NULL);
+}
+
+#define modparrot_module_cmd_raw_args modparrot_module_cmd_take1
+#define modparrot_module_cmd_iterate  modparrot_module_cmd_take1
+#define modparrot_module_cmd_iterate2 modparrot_module_cmd_take2
+#define modparrot_module_cmd_take12   modparrot_module_cmd_take2
+#define modparrot_module_cmd_take23   modparrot_module_cmd_take123
+#define modparrot_module_cmd_take3    modparrot_module_cmd_take123
+#define modparrot_module_cmd_take13   modparrot_module_cmd_take123
+
+static void register_meta_hooks(apr_pool_t *p)
+{
+    modparrot_srv_config *mpcfg;
+    modparrot_module_config *cfg;
+    modparrot_module_info *minfo;
+    module *modp;
+    int i;
+
+    /* XXX does this also work for Apache >= 2.3 */
+    static const char *aszSucc[] = { "mod_auth.c", NULL };
+
+    /* initialize the index to 0 for the first module only */
+    static int module_index = 0;
+
+    /* this assumes we're called in the same order modules were added */
+    mpcfg = ap_get_module_config(mp_globals.base_server->module_config,
+        &parrot_module);
+    modp = ((module **)mp_globals.module_array->elts)[module_index];
+    minfo = modp->dynamic_load_handle;
+
+    for (i = 0; i < MP_HOOK_LAST; i++) {
+        if (minfo->hooks[i]) {
+            int *pidx;
+            /* add module to handler index so meta handlers know who we are */
+            if (!mp_globals.handler_modules[i]) {
+                mp_globals.handler_modules[i] =
+                    apr_array_make(p, 1, sizeof(int));
+            }
+            pidx = (int *)apr_array_push(mp_globals.handler_modules[i]);
+            *pidx = module_index;
+
+            MP_TRACE_m(mp_globals.base_server, "registering hook %d for module '%s'", i, modp->name);
+
+            /* register this hook with apache */
+            switch(i) {
+                case MP_HOOK_OPEN_LOGS:
+                    ap_hook_open_logs(modparrot_meta_open_logs_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_POST_CONFIG:
+                    ap_hook_post_config(modparrot_meta_post_config_handler,
+                        NULL, NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_CHILD_INIT:
+                    ap_hook_child_init(modparrot_meta_child_init_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_PRE_CONNECTION:
+                    ap_hook_pre_connection(
+                        modparrot_meta_pre_connection_handler, NULL, NULL,
+                            APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_PROCESS_CONNECTION:
+                    ap_hook_process_connection(
+                        modparrot_meta_process_connection_handler, NULL, NULL,
+                            APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_POST_READ_REQUEST:
+                    ap_hook_post_read_request(
+                        modparrot_meta_post_read_request_handler, NULL, NULL,
+                            APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_MAP_TO_STORAGE:
+                    ap_hook_map_to_storage(
+                        modparrot_meta_map_to_storage_handler, NULL, NULL,
+                            APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_TRANS:
+                    ap_hook_translate_name(modparrot_meta_trans_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_HEADER_PARSER:
+                    ap_hook_header_parser(modparrot_meta_header_parser_handler,
+                        NULL, NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_ACCESS:
+                    ap_hook_access_checker(modparrot_meta_access_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_AUTHEN:
+                    ap_hook_check_user_id(modparrot_meta_authen_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_AUTHZ:
+                    ap_hook_auth_checker(modparrot_meta_authz_handler, NULL,
+                        aszSucc, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_RESPONSE:
+                    ap_hook_handler(modparrot_meta_response_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_TYPE:
+                    ap_hook_type_checker(modparrot_meta_type_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_FIXUP:
+                    ap_hook_fixups(modparrot_meta_fixup_handler, NULL, NULL,
+                        APR_HOOK_FIRST);
+                    break;
+                case MP_HOOK_LOG:
+                    ap_hook_log_transaction(modparrot_meta_log_handler, NULL,
+                        NULL, APR_HOOK_FIRST);
+                    break;
+                default:
+                    /* we should NEVER get here by definition */
+                    break;
+            }
+        }
+    }
+
+    /* prepare for the next module */
+    module_index++;
+}
+
 /* this is very leaky */
 module *modparrot_add_module(Parrot_Interp interp, apr_pool_t *p,
-                          const char *name, Parrot_PMC cmd_array)
+                             const char *name,
+                             char *namespace,
+                             Parrot_PMC cmd_array,
+                             Parrot_PMC hook_array)
 {
-    int i, num;
-    module *modp = (module *)apr_pcalloc(p, sizeof(*modp));
+    int i, num, hook_index, do_all=0;
+    modparrot_srv_config *mpcfg;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    Parrot_PMC hpmc;
+    module *modp;
+    modparrot_context *ctxp = get_interp_ctx(interp);
+    server_rec *s = ctxp->s;
+
+    if (modp =
+        apr_hash_get(mp_globals.module_hash, name, APR_HASH_KEY_STRING)) {
+        MP_TRACE_m(s, "already added module '%s' - skipping", name);
+        return(modp);
+    }
+
+    MP_TRACE_m(s, "adding module '%s'", name);
 
-    if (!cmd_array) return(NULL);
-    num = Parrot_PMC_get_intval(interp, cmd_array);
-    if (!num) return(NULL);
+    modp = (module *)apr_pcalloc(p, sizeof(*modp));
 
-    command_rec *cmds =
-        (command_rec *)apr_pcalloc(p, sizeof(command_rec)*(num+1));
+    /* custom directives are optional */
+    command_rec *cmds = NULL;
+    if (PMC_IS_NULL(cmd_array)) {
+        num = 0;
+    }
+    else {
+        num = Parrot_PMC_get_intval(interp, cmd_array);
+        if (num) {
+            cmds = (command_rec *)apr_pcalloc(p, sizeof(command_rec)*(num+1));
+        }
+    }
+
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
 
     for (i = 0; i < num; i++) {
         Parrot_PMC val;
@@ -106,6 +504,21 @@
             case TAKE123:
                 MP_INIT_CMD_TAKE123(cmds[i]);
                 break;
+            case ITERATE:
+                MP_INIT_CMD_ITERATE(cmds[i]);
+                break;
+            case ITERATE2:
+                MP_INIT_CMD_ITERATE2(cmds[i]);
+                break;
+            case FLAG:
+                MP_INIT_CMD_FLAG(cmds[i]);
+                break;
+            case NO_ARGS:
+                MP_INIT_CMD_NO_ARGS(cmds[i]);
+                break;
+            case RAW_ARGS:
+                MP_INIT_CMD_RAW_ARGS(cmds[i]);
+                break;
             default: /* XXX how do we error out here??? */
                 break;
         }
@@ -118,11 +531,21 @@
                                         MAKE_PARROT_STRING("errmsg"));
         cmds[i].errmsg = Parrot_PMC_get_cstring(interp, val);
 
+        data->modp = modp;
         data->func = Parrot_PMC_get_pmc_keyed_str(interp, cmd,
                                         MAKE_PARROT_STRING("func"));
+        if (PMC_IS_NULL(data->func)) {
+            MPLOG_ERRORF(s, "callback not found for directive '%s'", \
+               cmds[i].name);
+            /* XXX is exit() the right thing to do here? */
+            exit(1);
+        }
+
         data->cmd_data = Parrot_PMC_get_pmc_keyed_str(interp, cmd,
                                         MAKE_PARROT_STRING("cmd_data"));
         cmds[i].cmd_data = data;
+
+    MP_TRACE_m(s, "registered directive '%s' for module '%s'", cmds[i].name, name);
     }
 
     modp->version       = MODULE_MAGIC_NUMBER_MAJOR;
@@ -131,14 +554,74 @@
     modp->name          = (char *)apr_pstrdup(p, name);
     modp->magic         = MODULE_MAGIC_COOKIE;
 
-    modp->dynamic_load_handle = NULL; /* use for our data */
+    minfo = apr_pcalloc(p, sizeof(modparrot_module_info));
+    minfo->namespace = (char *)apr_pstrdup(p, namespace);
+
+    /* populate hook array for use by register_meta_hooks */
+    num = Parrot_PMC_get_intval(interp, hook_array);
+    if (num) {
+        hpmc = Parrot_PMC_get_pmc_keyed_int(interp, hook_array, 0);
+        hook_index = Parrot_PMC_get_intval(interp, hpmc);
+        if (hook_index == MP_HOOK_ALL) {
+            do_all = 1;
+            for (i = 0; i < MP_HOOK_LAST; i++) {
+                minfo->hooks[i] = 1;
+            }
+        }
+    }
+    for (i = 0; i < num && !do_all; i++) {
+        hpmc = Parrot_PMC_get_pmc_keyed_int(interp, hook_array, i);
+        hook_index = Parrot_PMC_get_intval(interp, hpmc);
+        if (hook_index < 0 || hook_index >= MP_HOOK_LAST) {
+            MPLOG_ERRORF(s, "invalid hook value in module '%s'", name);
+	    /* XXX is exit() the right thing to do here? */
+            exit(1);
+        }
+        minfo->hooks[hook_index] = 1;
+    }
+    modp->dynamic_load_handle = minfo;
+
+    if (sub = get_sub_pmc(interp, namespace, "server_create")) {
+        MP_TRACE_m(s, "registering server_create for module '%s'", name);
+        modp->create_server_config = modparrot_module_srv_create;
+        minfo->server_create_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "server_merge")) {
+        MP_TRACE_m(s, "registering server_merge for module '%s'", name);
+        modp->merge_server_config = modparrot_module_srv_merge;
+        minfo->server_merge_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "dir_create")) {
+        MP_TRACE_m(s, "registering dir_create for module '%s'", name);
+        modp->create_dir_config = modparrot_module_dir_create;
+        minfo->dir_create_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "dir_merge")) {
+        MP_TRACE_m(s, "registering dir_merge for module '%s'", name);
+        modp->merge_dir_config = modparrot_module_dir_merge;
+        minfo->dir_merge_sub = sub;
+    }
+
+    /* remember our context pool */
+    minfo->ctx_pool = ctxp->ctx_pool;
 
     modp->cmds = cmds; /* our command vector */
 
+    modp->register_hooks = register_meta_hooks;
+
+    /* module_array lets us access modules in sequence */
+    *(module **)apr_array_push(mp_globals.module_array) = modp;
+
+    /* module_hash lets us access modules by name */
+    apr_hash_set(mp_globals.module_hash, (char *)apr_pstrdup(p, modp->name),
+        APR_HASH_KEY_STRING, modp);
+
     modparrot_insert_module(modp);
 
     ap_add_loaded_module(modp, p);
 
+    MP_TRACE_m(s, "registration complete for module '%s'", name);
+
     apr_pool_cleanup_register(p, modp, modparrot_remove_module,
                               apr_pool_cleanup_null);
 

Modified: mod_parrot/branches/configure/src/nci.c
==============================================================================
--- mod_parrot/branches/configure/src/nci.c	(original)
+++ mod_parrot/branches/configure/src/nci.c	Sat May  2 06:55:00 2009
@@ -23,6 +23,7 @@
 #include "http_protocol.h"
 #include "http_config.h"
 #include "apr_strings.h"
+#include "apr_hash.h"
 
 #include "parrot/parrot.h"
 #include "parrot/embed.h"
@@ -32,6 +33,16 @@
 #include "modparrot_config.h"
 
 #include "../build/src/nci/request_rec.c"
+#include "../build/src/nci/server_rec.c"
+
+extern module AP_MODULE_DECLARE_DATA parrot_module;
+extern modparrot_globals mp_globals;
+
+/* used from PIR to pass C-style NULLs to NCI functions */
+void *mpnci_null(void)
+{
+    return (void *)NULL;
+}
 
 request_rec *mpnci_request_rec(Parrot_Interp interp)
 {
@@ -42,6 +53,18 @@
     return(ctxp->r);
 }
 
+struct ap_conf_vector_t *mpnci_request_rec_per_dir_config(Parrot_Interp interp,
+    request_rec *r)
+{
+    return(r->per_dir_config);
+}
+
+server_rec *mpnci_request_rec_server(Parrot_Interp interp,
+    request_rec *r)
+{
+    return(r->server);
+}
+
 apr_pool_t *mpnci_conf_pool(Parrot_Interp interp)
 {
     modparrot_context *ctxp;
@@ -105,6 +128,34 @@
     return(ctxp->csd);
 }
 
+modparrot_module_config *mpnci_raw_srv_config(Parrot_Interp interp)
+{
+    modparrot_context *ctxp;
+
+    ctxp = get_interp_ctx(interp);
+    if (!ctxp) return NULL;
+    return(ctxp->raw_srv_config);
+}
+
+modparrot_module_config *mpnci_raw_dir_config(Parrot_Interp interp)
+{
+    modparrot_context *ctxp;
+
+    ctxp = get_interp_ctx(interp);
+    if (!ctxp) return NULL;
+    return(ctxp->raw_dir_config);
+}
+
+const char *mpnci_ctx_pool_name(Parrot_Interp interp)
+{
+    modparrot_context *ctxp;
+    const char *name;
+
+    ctxp = get_interp_ctx(interp);
+    name = modparrot_get_ctx_pool_name(ctxp->ctx_pool);
+    return(name);
+}
+
 request_rec *mpnci_request_rec_main(Parrot_Interp interp, request_rec *r)
 {
     return(r->main);
@@ -125,6 +176,22 @@
     return(r->notes);
 }
 
+apr_table_t *mpnci_request_rec_headers_in(Parrot_Interp interp, request_rec *r)
+{
+    return(r->headers_in);
+}
+
+apr_table_t *mpnci_request_rec_headers_out(Parrot_Interp interp, request_rec *r)
+{
+    return(r->headers_out);
+}
+
+apr_table_t *mpnci_request_rec_err_headers_out(Parrot_Interp interp,
+                                               request_rec *r)
+{
+    return(r->err_headers_out);
+}
+
 /* We implement ap_get_basic_auth_pw as a wrapper because there is no NCI
  * signature type that handles the function's char ** password parameter.
  * Instead, we return the results in a PMC array passed in from the caller.
@@ -150,19 +217,36 @@
 int mpnci_rwrite(Parrot_Interp interp, Parrot_PMC p, int size, request_rec *r)
 {
     modparrot_context *ctxp;
+    Parrot_Int plen;
+    int len;
+    char *buf;
+
+    ctxp = get_interp_ctx(interp);
+    if (!ctxp) return 0;
+
+    buf = Parrot_PMC_get_cstringn(ctxp->interp, p, &plen);
+    len = ap_rwrite(buf, (plen < size) ? len : size, r);
+    Parrot_str_free_cstring(buf);
+
+    return(len);
+}
+
+size_t mpnci_request_read(Parrot_Interp interp, Parrot_PMC pbuf, size_t len,
+    request_rec *r)
+{
+    modparrot_context *ctxp;
     Parrot_Interp interpreter;
+    char *buf;
     int bytes;
-    char *tmp;
 
     ctxp = get_interp_ctx(interp);
     if (!ctxp) return 0;
     interpreter = ctxp->interp;
 
-    /* will this work for binary data??? */
-    tmp = (char *)string_to_cstring(interpreter, PMC_str_val(p));
-
-    bytes = ap_rwrite(tmp, size, r);
-    string_cstring_free(tmp);
+    /* buf should be freed by apache when the request pool is destroyed */
+    buf = apr_pcalloc(r->pool, len);
+    bytes = modparrot_request_read(r, buf, len);
+    Parrot_PMC_set_cstringn(interp, pbuf, buf, bytes);
 
     return(bytes);
 }
@@ -178,53 +262,115 @@
     ap_log_rerror(file, line, level, status, r, "%s", msg);
 }
 
-module *mpnci_add_apache_module(Parrot_Interp interp, char *name,
-    Parrot_PMC cmd_array)
+module *mpnci_add_apache_module(Parrot_Interp interp,
+                                const char *name,
+                                char *namespace,
+                                Parrot_PMC cmd_array,
+                                Parrot_PMC hook_array)
 {
     modparrot_context *ctxp;
     module *modp;
 
     ctxp = get_interp_ctx(interp);
     if (!ctxp) return NULL;
-    modp = modparrot_add_module(interp, ctxp->pconf, name, cmd_array);
+    modp = modparrot_add_module(interp, ctxp->pconf, name, namespace, 
+        cmd_array, hook_array);
     return(modp);
 }
 
-Parrot_PMC mpnci_dircfg_handler(Parrot_Interp interp, char *hll, char *id,
-    int update)
+Parrot_PMC mpnci_get_module_config(Parrot_Interp interp, char *name,
+    ap_conf_vector_t *per_dir_config, int is_directory)
 {
     modparrot_context *ctxp;
-    Parrot_PMC handler;
-    int typenum;
+    modparrot_srv_config *mpcfg;
+    modparrot_module_config *cfg;
+    module *modp;
 
     ctxp = get_interp_ctx(interp);
     if (!ctxp) return NULL;
 
-    if (update) {
-        if (!ctxp->dircfg->handler) {
-            ctxp->dircfg->handler = (modparrot_handler_info *)apr_pcalloc(
-                ctxp->pconf, sizeof(modparrot_handler_info));
-        }
-        ctxp->dircfg->handler->hll = apr_pstrdup(ctxp->pconf, hll);
-        ctxp->dircfg->handler->id = apr_pstrdup(ctxp->pconf, id);
+    mpcfg = ap_get_module_config(ctxp->s->module_config, &parrot_module);
+    modp = apr_hash_get(mp_globals.module_hash, name, APR_HASH_KEY_STRING);
+    if (!modp) {
+        return(NULL);
     }
 
-    typenum = Parrot_PMC_typenum(interp, "SArray");
-    handler = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
-    /* XXX how do we unregister this after it's used? */
-    Parrot_register_pmc(interp, handler);
-    Parrot_PMC_set_intval(interp, handler, 2);
-
-    if (ctxp->dircfg->handler) {
-        Parrot_PMC_set_cstring_intkey(interp, handler, 0,
-            ctxp->dircfg->handler ? ctxp->dircfg->handler->hll : "");
-        Parrot_PMC_set_cstring_intkey(interp, handler, 1,
-            ctxp->dircfg->handler ? ctxp->dircfg->handler->id : "");
+    if (is_directory) {
+        /* possibly do more here if not in a request */
+        cfg = ap_get_module_config(ctxp->r->per_dir_config, modp);
     }
     else {
-        Parrot_PMC_set_pmc_intkey(interp, handler, 0, PMCNULL);
-        Parrot_PMC_set_pmc_intkey(interp, handler, 1, PMCNULL);
+        cfg = ap_get_module_config(ctxp->s->module_config, modp);
+    }
+
+    /* return the PMC cfg inside the modparrot_module_config struct. if we
+     * have no directives in the section, we'll have no dircfg, so we should
+     * return PMCNULL.
+     */
+    return cfg ? cfg->cfg : PMCNULL;
+}
+ 
+server_rec *mpnci_cmd_parms_server(Parrot_Interp interp, cmd_parms *cmd)
+{
+    return(cmd->server);
+}
+
+apr_pool_t *mpnci_cmd_parms_pool(Parrot_Interp interp, cmd_parms *cmd)
+{
+    return(cmd->pool);
+}
+
+apr_pool_t *mpnci_cmd_parms_temp_pool(Parrot_Interp interp, cmd_parms *cmd)
+{
+    return(cmd->temp_pool);
+}
+
+const command_rec *mpnci_cmd_parms_cmd(Parrot_Interp interp, cmd_parms *cmd)
+{
+    return(cmd->cmd);
+}
+
+apr_pool_t *mpnci_request_rec_pool(Parrot_Interp interp, request_rec *r)
+{
+    return(r->pool);
+}
+
+apr_status_t modparrot_meta_cleanup_handler(void *);
+void mpnci_register_pool_cleanup(Parrot_Interp interp, apr_pool_t *p,
+    Parrot_PMC sub, Parrot_PMC data)
+{
+    modparrot_cleanup_info *ci;
+    modparrot_context *ctxp;
+    modparrot_srv_config *cfg;
+    module *modp;
+
+    ctxp = get_interp_ctx(interp);
+    if (!ctxp) return;
+
+    /* get current module */
+    cfg = ap_get_module_config(ctxp->s->module_config, &parrot_module);
+    modp = ((module **)mp_globals.module_array->elts)[ctxp->module_index];
+
+    /* register the data PMC b/c it will likely go out of scope in the HLL */
+    if (!PMC_IS_NULL(data)) {
+        Parrot_register_pmc(interp, data);
     }
 
-    return(handler);
+    /* populate cleanup info */
+    ci = apr_pcalloc(p, sizeof(modparrot_cleanup_info));
+    ci->module = modp;
+    ci->callback = sub;
+    ci->hll_data = data;
+    ci->s = ctxp->s;
+    ci->pool = p;
+
+    /* register the handler */
+    apr_pool_cleanup_register(p, ci, modparrot_meta_cleanup_handler, NULL);
+}
+
+void mpnci_set_config_ctx_pool(Parrot_Interp interp,
+    modparrot_module_config *cfg, char *pool_name)
+{
+    modparrot_context *ctxp = get_interp_ctx(interp);
+    cfg->ctx_pool_name = (char *)apr_pstrdup(ctxp->pconf, pool_name);
 }

Modified: mod_parrot/branches/configure/src/parrot_util.c
==============================================================================
--- mod_parrot/branches/configure/src/parrot_util.c	(original)
+++ mod_parrot/branches/configure/src/parrot_util.c	Sat May  2 06:55:00 2009
@@ -21,6 +21,14 @@
 #include "parrot/embed.h"
 #include "parrot/extend.h"
 #include "mod_parrot.h"
+#include "../src/pmc/pmc_continuation.h"
+
+
+/* XXX mod_parrot can crash on x86_64 w/o this.
+ * there's no prototype in the standard parrot includes, so compiler assumes
+ * return type of 'int', and sizeof(int) != sizeof(pointer) on x86_64.
+ */
+Parrot_PMC Parrot_Class_instantiate(PARROT_INTERP, PMC *, PMC *init);
 
 static Parrot_PMC get_sub_pmc_s(Parrot_Interp interp, char *namespace, char *name)
 {
@@ -49,7 +57,7 @@
     Parrot_PMC namespace;
     int typenum;
 
-    typenum = Parrot_PMC_typenum(interp, "SArray");
+    typenum = Parrot_PMC_typenum(interp, "ResizablePMCArray");
     namespace = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
     Parrot_register_pmc(interp, namespace);
     Parrot_PMC_set_intval(interp, namespace, 3);
@@ -155,6 +163,19 @@
     return(1);
 }
 
+int modparrot_call_sub_IP(Parrot_Interp interp, char *namespace, char *name,
+    int *ret, Parrot_PMC pmc)
+{
+    Parrot_PMC sub;
+
+    sub = get_sub_pmc(interp, namespace, name);
+    if (!sub) {
+        return(0);
+    }
+    *ret = Parrot_call_sub_ret_int(interp, sub, "IP", pmc);
+    return(1);
+}
+
 int modparrot_call_sub_IPS(Parrot_Interp interp, char *namespace, char *name,
     int *ret, Parrot_PMC pmc, char *arg)
 {
@@ -176,7 +197,7 @@
     PMC *sub;
     PMC *old = PMCNULL;
     int rec_level = 0;
-    parrot_context_t *ctx = CONTEXT(interp);
+    Parrot_Context *ctx = CONTEXT(interp);
     char *trace_string;
 
     /* information about the current sub */
@@ -184,7 +205,7 @@
     if (!PMC_IS_NULL(sub)) {
         str = Parrot_Context_infostr(interp, ctx);
         if (str)
-            buf = string_concat(interp, buf, str, 0);
+            buf = Parrot_str_concat(interp, buf, str, 0);
     }
 
     /* backtrace: follow the continuation chain */
@@ -205,15 +226,15 @@
             PMC_cont(sub)->to_ctx->current_sub) {
             ++rec_level;
         } else if (rec_level != 0) {
-            buf = string_printf(interp, "... call repeated %d times\n",
+            buf = Parrot_sprintf_c(interp, "... call repeated %d times\n",
                 rec_level);
-            buf = string_concat(interp, buf, str, 0);
+            buf = Parrot_str_concat(interp, buf, str, 0);
             rec_level = 0;
         }
 
         /* print the context description */
         if (rec_level == 0)
-            buf = string_concat(interp, buf, str, 0);
+            buf = Parrot_str_concat(interp, buf, str, 0);
 
         /* get the next Continuation */
         ctx = PMC_cont(sub)->to_ctx;
@@ -222,9 +243,49 @@
             break;
     }
     if (rec_level != 0) {
-        buf = string_printf(interp, "... call repeated %d times\n", rec_level);
+        buf = Parrot_sprintf_c(interp,"... call repeated %d times\n",
+            rec_level);
     }
 
-    trace_string = string_to_cstring(interp, buf);
+    trace_string = Parrot_str_to_cstring(interp, buf);
     return(trace_string);
 }
+
+Parrot_PMC modparrot_wrap_apache_type(Parrot_Interp interp, char *classname,
+    char *init_key, void *init_val)
+{
+    Parrot_PMC _class;
+    Parrot_PMC obj;
+    Parrot_PMC pointer_pmc;
+    Parrot_PMC namespace;
+    Parrot_PMC init;
+    int typenum;
+
+    namespace = Parrot_str_split(interp, string_from_literal(interp, ";"),
+        Parrot_str_new(interp, classname, strlen(classname)));
+    Parrot_register_pmc(interp, namespace);
+    _class = Parrot_oo_get_class(interp, namespace);
+    Parrot_unregister_pmc(interp, namespace);
+
+    typenum = Parrot_PMC_typenum(interp, "UnManagedStruct");
+    pointer_pmc = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
+    Parrot_PMC_set_pointer(interp, pointer_pmc, init_val);
+
+    if (init_key && init_val) {
+        typenum = Parrot_PMC_typenum(interp, "Hash");
+        init = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
+        Parrot_register_pmc(interp, init);
+        Parrot_PMC_set_pmc_keyed_str(interp, init,
+            Parrot_str_new(interp, init_key, strlen(init_key)),
+                pointer_pmc);
+        obj = Parrot_Class_instantiate(interp, _class, init);
+    }
+    else {
+        obj = Parrot_Class_instantiate(interp, _class, PMCNULL);
+    }
+    Parrot_unregister_pmc(interp, init);
+    Parrot_unregister_pmc(interp, _class);
+
+    /* NOTE: we leave it up to the caller to register the PMC */
+    return(obj);
+}

Modified: mod_parrot/branches/configure/t/conf/extra.conf.in
==============================================================================
--- mod_parrot/branches/configure/t/conf/extra.conf.in	(original)
+++ mod_parrot/branches/configure/t/conf/extra.conf.in	Sat May  2 06:55:00 2009
@@ -3,69 +3,17 @@
 </IfModule>
 
 ParrotIncludePath @ServerRoot@/../lib
+ParrotLibPath @ServerRoot@/../lib
+ParrotDynextPath @ServerRoot@/../src/pmc
 ParrotInit @ServerRoot@/../lib/mod_parrot.pbc
+ParrotLoadImmediate @ServerRoot@/../lib/ModParrot/HLL/pir.pbc
 ParrotLoad @ServerRoot@/lib/handlers.pbc
 
 # enable for test debugging
 ParrotTrace 0
 
-<Location /parrot-test/RequestRec-content_type>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::content_type
-</Location>
-
-<Location /parrot-test/RequestRec-puts>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::puts
-</Location>
-
-<Location /parrot-test/RequestRec-write>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::write
-</Location>
-
-<Location /parrot-test/RequestRec-args>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::args
-</Location>
-
-<Location /parrot-test/RequestRec-hostname>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::hostname
-</Location>
-
-<Location /parrot-test/RequestRec-notes>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::notes
-</Location>
-
-<Location /parrot-test/RequestRec-pmc_notes>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::pmc_notes
-</Location>
-
-<Location /parrot-test/RequestRec-status>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::status
-</Location>
-
-<Location /parrot-test/RequestRec-log_rerror>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::log_rerror
-</Location>
-
 <Location /parrot-test/RequestRec-get_basic_auth_pw>
     SetHandler parrot-code
-    ParrotLanguage PIR
     ParrotHandler ModParrot::Test::get_basic_auth_pw
     ParrotAuthenHandler ModParrot::Test::AuthenHandler
     AuthType Basic
@@ -75,7 +23,6 @@
 
 <Location /parrot-test/RequestRec-auth_type>
     SetHandler parrot-code
-    ParrotLanguage PIR
     ParrotHandler ModParrot::Test::auth_type
     ParrotAuthenHandler ModParrot::Test::AuthenHandler
     AuthType Basic
@@ -85,7 +32,6 @@
 
 <Location /parrot-test/RequestRec-auth_name>
     SetHandler parrot-code
-    ParrotLanguage PIR
     ParrotHandler ModParrot::Test::auth_name
     ParrotAuthenHandler ModParrot::Test::AuthenHandler
     AuthType Basic
@@ -95,14 +41,12 @@
 
 <Location /parrot-test/ParrotAccessHandler>
     SetHandler parrot-code
-    ParrotLanguage PIR
     ParrotAccessHandler ModParrot::Test::AccessHandler
     ParrotHandler ModParrot::Test::HelloWorld
 </Location>
 
 <Location /parrot-test/ParrotAuthzHandler>
     SetHandler parrot-code
-    ParrotLanguage PIR
     ParrotHandler ModParrot::Test::HelloWorld
     ParrotAuthenHandler ModParrot::Test::AuthenHandler
     ParrotAuthzHandler ModParrot::Test::AuthzHandler
@@ -110,135 +54,3 @@
     AuthName "Parrot Test"
     Require valid-user
 </Location>
-
-<Location /parrot-test/RequestRec-the_request>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::the_request
-</Location>
-
-<Location /parrot-test/RequestRec-protocol>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::protocol
-</Location>
-
-<Location /parrot-test/RequestRec-status_line>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::status_line
-</Location>
-
-<Location /parrot-test/RequestRec-range>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::range
-</Location>
-
-<Location /parrot-test/RequestRec-handler>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::handler
-</Location>
-
-<Location /parrot-test/RequestRec-content_encoding>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::content_encoding
-</Location>
-
-<Location /parrot-test/RequestRec-vlist_validator>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::vlist_validator
-</Location>
-
-<Location /parrot-test/RequestRec-unparsed_uri>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::unparsed_uri
-</Location>
-
-<Location /parrot-test/RequestRec-uri>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::uri
-</Location>
-
-<Location /parrot-test/RequestRec-path_info>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::path_info
-</Location>
-
-<Location /parrot-test/RequestRec-assbackwards>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::assbackwards
-</Location>
-
-<Location /parrot-test/RequestRec-proxyreq>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::proxyreq
-</Location>
-
-<Location /parrot-test/RequestRec-header_only>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::header_only
-</Location>
-
-<Location /parrot-test/RequestRec-proto_num>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::proto_num
-</Location>
-
-<Location /parrot-test/RequestRec-method_number>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::method_number
-</Location>
-
-<Location /parrot-test/RequestRec-chunked>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::chunked
-</Location>
-
-<Location /parrot-test/RequestRec-read_body>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::read_body
-</Location>
-
-<Location /parrot-test/RequestRec-read_chunked>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::read_chunked
-</Location>
-
-<Location /parrot-test/RequestRec-no_cache>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::no_cache
-</Location>
-
-<Location /parrot-test/RequestRec-no_local_copy>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::no_local_copy
-</Location>
-
-<Location /parrot-test/RequestRec-used_path_info>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::used_path_info
-</Location>
-
-<Location /parrot-test/RequestRec-eos_sent>
-    SetHandler parrot-code
-    ParrotLanguage PIR
-    ParrotHandler ModParrot::Test::eos_sent
-</Location>

Modified: mod_parrot/branches/configure/t/legacy/03AuthenHandler.t
==============================================================================
--- mod_parrot/branches/configure/t/legacy/03AuthenHandler.t	(original)
+++ mod_parrot/branches/configure/t/legacy/03AuthenHandler.t	Sat May  2 06:55:00 2009
@@ -1,11 +1,10 @@
-use Apache::Test qw(:withtestmore);
+use Apache::Test qw(-withtestmore);
 use Apache::TestRequest;
 use Apache::TestUtil qw(t_cmp);
-use Test::More;
 
 my ($content, $res);
 
-plan tests =>2, (need_lwp);
+plan tests => 2, need qw(LWP mod_auth_basic.c);
 
 # Apache::RequestRec->RequestRec-get_basic_auth_pw
 $res = GET '/parrot-test/RequestRec-get_basic_auth_pw';

Modified: mod_parrot/branches/configure/t/lib/handlers.pir
==============================================================================
--- mod_parrot/branches/configure/t/lib/handlers.pir	(original)
+++ mod_parrot/branches/configure/t/lib/handlers.pir	Sat May  2 06:55:00 2009
@@ -6,7 +6,7 @@
     .param pmc r
     .local pmc ap_const
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
 
     r.'puts'('Hello World')
@@ -22,7 +22,7 @@
 
     r.'puts'("Access granted.")
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
 
     .return($I0)
@@ -34,7 +34,7 @@
     .param pmc r
     .local pmc ap_const
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
 
     $S0 = r.'args'( )
@@ -60,7 +60,7 @@
 
     $S0 = r.'user'( )
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
     if $S0 != 'joeuser' goto auth_failed
     if $S1 != 'password' goto auth_failed
@@ -81,7 +81,7 @@
     .param pmc r
     .local pmc ap_const
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
     $I0 = ap_const['OK']
 
     $S0 = r.'args'( )

Modified: mod_parrot/branches/configure/t/response/TestAPI/interpreter.pir
==============================================================================
--- mod_parrot/branches/configure/t/response/TestAPI/interpreter.pir	(original)
+++ mod_parrot/branches/configure/t/response/TestAPI/interpreter.pir	Sat May  2 06:55:00 2009
@@ -7,7 +7,7 @@
     .local pmc mpi, ap_const
     .local string results
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
     r.'puts'("1..7\n")
 
@@ -59,7 +59,7 @@
   OK_6:
     r.'puts'("ok 6 - object\n")
 
-  START_r76:
+  START_7:
     $P0 = mpi.'dynext_path_str'()
     $S0 = typeof $P0
     if $S0 == "String" goto OK_7

Modified: mod_parrot/branches/configure/t/response/TestAPI/request_rec.pir
==============================================================================
--- mod_parrot/branches/configure/t/response/TestAPI/request_rec.pir	(original)
+++ mod_parrot/branches/configure/t/response/TestAPI/request_rec.pir	Sat May  2 06:55:00 2009
@@ -7,14 +7,14 @@
     .local pmc ap_const
     .local string results
 
-    ap_const = get_root_global [ 'Apache'; 'Constants' ], 'ap_constants'
+    ap_const = get_root_global [ 'ModParrot'; 'Apache'; 'Constants' ], 'table'
 
-    r.'puts'("1..32\n")
+    r.'puts'("1..39\n")
 
   # XXX this should be fatal on failure
   START_1:
     $S0 = typeof r
-    if $S0 == "Apache;RequestRec" goto OK_1
+    if $S0 == "ModParrot;Apache;RequestRec" goto OK_1
   NOT_OK_1:
     r.'puts'("not ")
   OK_1:
@@ -25,6 +25,7 @@
   OK_2:
     r.'puts'("ok 2 - puts()\n")
 
+  # XXX failure here may cause all subsequent tests to fail
   START_3:
     push_eh NOT_OK_3
     $I0 = r.'write'("# testing 123\n", 14)
@@ -366,6 +367,82 @@
   #  r.'puts'("ok 32 - putc()\n")
   r.'puts'("not ok 32 - putc() # TODO succeeds with incorrect output\n")
 
+  START_33:
+    push_eh NOT_OK_33
+    $S0 = r.'method'()
+    pop_eh
+    if $S0 == 'GET' goto OK_33
+  NOT_OK_33:
+    r.'puts'("not ")
+  OK_33:
+    r.'puts'("ok 33 - method()\n")
+
+  START_34:
+    push_eh NOT_OK_34
+    $P0 = new 'String'
+    $I0 = r.'read'($P0, 1024)
+    pop_eh
+    if $I0 == 0 goto OK_34
+  NOT_OK_34:
+    r.'puts'("not ")
+  OK_34:
+    r.'puts'("ok 34 - null read()\n")
+
+  START_35:
+    push_eh NOT_OK_35
+    $P0 = r.'headers_in'()
+    pop_eh
+    $S0 = typeof $P0
+    if $S0 == 'ModParrot;APR;Table' goto OK_35
+  NOT_OK_35:
+    r.'puts'("not ")
+  OK_35:
+    r.'puts'("ok 35 - headers_in()\n")
+
+  START_36:
+    push_eh NOT_OK_36
+    $P0 = r.'headers_out'()
+    pop_eh
+    $S0 = typeof $P0
+    if $S0 == 'ModParrot;APR;Table' goto OK_36
+  NOT_OK_36:
+    r.'puts'("not ")
+  OK_36:
+    r.'puts'("ok 36 - headers_in()\n")
+
+  START_37:
+    push_eh NOT_OK_37
+    $P0 = r.'err_headers_out'()
+    pop_eh
+    $S0 = typeof $P0
+    if $S0 == 'ModParrot;APR;Table' goto OK_37
+  NOT_OK_37:
+    r.'puts'("not ")
+  OK_37:
+    r.'puts'("ok 37 - headers_in()\n")
+
+  START_38:
+    push_eh NOT_OK_38
+    $P0 = r.'pool'()
+    pop_eh
+    $S0 = typeof $P0
+    if $S0 == 'ModParrot;APR;Pool' goto OK_38
+  NOT_OK_38:
+    r.'puts'("not ")
+  OK_38:
+    r.'puts'("ok 38 - pool()\n")
+
+  START_39:
+    push_eh NOT_OK_39
+    $P0 = r.'server'()
+    pop_eh
+    $S0 = typeof $P0
+    if $S0 == 'ModParrot;Apache;ServerRec' goto OK_39
+  NOT_OK_39:
+    r.'puts'("not ")
+  OK_39:
+    r.'puts'("ok 39 - server()\n")
+
     # STILL TODO (not tested in original client-side tests)
     # assbackwards
     # proxyreq