Home  |  Linux  | Mysql  | PHP  | XML
From:jhorwitz@cvs.perl.org Date:Sun Sep 21 13:23:19 2008
Subject:[svn:mod_parrot] r449 - in mod_parrot/trunk: . docs include languages/perl6/lib lib lib/Apache lib/ModParrot/HLL src t/conf
Author: jhorwitz
Date: Sun Sep 21 12:23:18 2008
New Revision: 449

Modified:
   mod_parrot/trunk/call_list.txt
   mod_parrot/trunk/docs/apache-conf.txt
   mod_parrot/trunk/docs/handler-architecture.txt
   mod_parrot/trunk/include/mod_parrot.h
   mod_parrot/trunk/include/modparrot_config.h
   mod_parrot/trunk/languages/perl6/lib/mod_perl6.pm
   mod_parrot/trunk/lib/Apache/Module.pir
   mod_parrot/trunk/lib/Apache/RequestRec.pir
   mod_parrot/trunk/lib/ModParrot/HLL/perl6.pir
   mod_parrot/trunk/lib/ModParrot/HLL/pir.pir
   mod_parrot/trunk/lib/mod_parrot.pir
   mod_parrot/trunk/src/mod_parrot.c
   mod_parrot/trunk/src/modparrot_config.c
   mod_parrot/trunk/src/module.c
   mod_parrot/trunk/src/nci.c
   mod_parrot/trunk/src/parrot_util.c
   mod_parrot/trunk/t/conf/extra.conf.in

Log:
merge hll-modules branch back into trunk
svn merge -r419:448 https://svn.perl.org/parrot-modules/mod_parrot/branches/hll-modules


Modified: mod_parrot/trunk/call_list.txt
==============================================================================
--- mod_parrot/trunk/call_list.txt	(original)
+++ mod_parrot/trunk/call_list.txt	Sun Sep 21 12:23:18 2008
@@ -18,5 +18,5 @@
 v       pit
 v       ptt
 v       Jtiiipt
-p       JtP
-P	Jitti
+p       JttPP
+P       Jtpi

Modified: mod_parrot/trunk/docs/apache-conf.txt
==============================================================================
--- mod_parrot/trunk/docs/apache-conf.txt	(original)
+++ mod_parrot/trunk/docs/apache-conf.txt	Sun Sep 21 12:23:18 2008
@@ -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
 
@@ -20,7 +21,7 @@
 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
 -------------------
@@ -37,39 +38,20 @@
 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 +59,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 +67,98 @@
  
 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
+Syntax:      ParrotCleanupHandler handler
 Default:     none
 Context:     directory config
 Description: Sets the Parrot request cleanup handler

Modified: mod_parrot/trunk/docs/handler-architecture.txt
==============================================================================
--- mod_parrot/trunk/docs/handler-architecture.txt	(original)
+++ mod_parrot/trunk/docs/handler-architecture.txt	Sun Sep 21 12:23:18 2008
@@ -1,5 +1,8 @@
 # $Id$
 
+NOTE: Due to a redesign, this document may not reflect the current state of
+mod_parrot and should be updated.
+
 mod_parrot Handler Architecture
 ===============================
 

Modified: mod_parrot/trunk/include/mod_parrot.h
==============================================================================
--- mod_parrot/trunk/include/mod_parrot.h	(original)
+++ mod_parrot/trunk/include/mod_parrot.h	Sun Sep 21 12:23:18 2008
@@ -56,8 +56,7 @@
     server_rec *s;
     conn_rec *c;
     void *csd;
-    modparrot_dir_config *dircfg; /* used by HLL directives */
-    modparrot_srv_config *srvcfg; /* used by HLL directives */
+    int module_index;
 };
 typedef struct modparrot_context modparrot_context;
 
@@ -68,6 +67,7 @@
 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);
@@ -80,8 +80,8 @@
 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);
+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);
 
 #endif /* _MODPARROT_H */

Modified: mod_parrot/trunk/include/modparrot_config.h
==============================================================================
--- mod_parrot/trunk/include/modparrot_config.h	(original)
+++ mod_parrot/trunk/include/modparrot_config.h	Sun Sep 21 12:23:18 2008
@@ -19,6 +19,7 @@
 #define _MODPARROT_CONFIG_H
 
 #include "apr_tables.h"
+#include "apr_hash.h"
 
 /* per-server options */
 #define MP_OPT_ENABLE 1
@@ -53,86 +54,79 @@
 #  define MP_INIT_CMD_FLAG(c) (c.func = modparrot_module_cmd_flag)
 #endif /* (AP_HAVE_DESIGNATED_INITIALIZER) || defined(DOXYGEN) */
 
-/* configuration */
-struct modparrot_handler_info
-{
-    char *id;  /* identifier of the code to load */
-    char *hll; /* HLL of the code */
-};
-typedef struct modparrot_handler_info modparrot_handler_info; 
-
-struct modparrot_srv_config
-{
-    apr_pool_t *pool;
-    apr_array_header_t *ctx_pool;
-    char *init_path;
-    int trace_flags;
-    int enable_option_flags;
-    int disable_option_flags;
-    int option_flags;
-    char *include_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;
-
 /* hook types */
 enum modparrot_hooks {
     /* server scope */
     MP_HOOK_OPEN_LOGS,
-    MP_HOOK_CHILD_INIT,
-    MP_HOOK_CHILD_EXIT,
     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,
-    MP_HOOK_POST_READ_REQUEST,
 
     /* directory scope */
     MP_HOOK_INPUT_FILTER,
-    MP_HOOK_OUTPUT_FILTER,
     MP_HOOK_HEADER_PARSER,
-    MP_HOOK_RESPONSE,
     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,
-    MP_HOOK_CLEANUP
+    MP_HOOK_CLEANUP,
+    MP_HOOK_LAST
 };
 
+struct modparrot_module_info
+{
+    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 *name;
+    modparrot_module_info *minfo;
+    Parrot_PMC cfg;
+};
+typedef struct modparrot_module_config modparrot_module_config;
+
+struct modparrot_srv_config
+{
+    apr_pool_t *pool;
+    apr_array_header_t *ctx_pool;
+    char *init_path;
+    int trace_flags;
+    int enable_option_flags;
+    int disable_option_flags;
+    int option_flags;
+    char *include_path;
+    apr_array_header_t *preload;
+    apr_array_header_t *module_array;
+    apr_hash_t *module_hash;
+};
+typedef struct modparrot_srv_config modparrot_srv_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 */
 };
@@ -145,29 +139,7 @@
 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_language(cmd_parms *, void *, const char *);
@@ -178,24 +150,24 @@
 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*);
-const char *modparrot_module_cmd_raw_args(cmd_parms *, void *, const char *);
-const char *modparrot_module_cmd_flag(cmd_parms *, void *, int);
-const char *modparrot_module_cmd_iterate(cmd_parms *, void *, const char *);
-const char *modparrot_module_cmd_iterate2(cmd_parms *, void *, const char *,
-    const char *);
-const char *modparrot_module_cmd_no_args(cmd_parms *, void *);
+/* 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/trunk/languages/perl6/lib/mod_perl6.pm
==============================================================================
--- mod_parrot/trunk/languages/perl6/lib/mod_perl6.pm	(original)
+++ mod_parrot/trunk/languages/perl6/lib/mod_perl6.pm	Sun Sep 21 12:23:18 2008
@@ -21,7 +21,6 @@
 our @preloaded_modules = ();
 our @postconfig_requires = ();
 our %loaded_modules;
-
 sub load($handler)
 {
     unless (%loaded_modules{$handler}) {
@@ -30,10 +29,34 @@
     }
 }
 
-sub handler($ctx, $handler)
+sub server_create()
+{
+    my %cfg;
+    return %cfg;
+}
+
+sub dir_create()
+{
+    my %cfg;
+    return %cfg;
+}
+
+sub response_handler($ctx)
 {
     my $r = $ctx.request_rec();
+
+    unless ($r.handler() ~~ any(<modperl6 perl6-script>)) {
+        return -1; # DECLINED
+    }
+
+    my %cfg = Apache::Module::get_config("modparrot_perl6_module");
+    my %dircfg = Apache::Module::get_config("modparrot_perl6_module",
+        $r.per_dir_config());
+
+    my $handler = %dircfg{'response_handler'};
     load($handler);
+
+    $r.content_type('text/html');
     my $status = ::($handler)::handler($r);
     return $status;
 }
@@ -64,3 +87,32 @@
     my $status = ::($handler)::handler();
     return $status;
 }
+
+sub cmd_perl6responsehandler(%dircfg, @args)
+{
+    %dircfg{'response_handler'} = @args[0];
+}
+
+# register configuration directives
+my $TAKE1 = 1;
+my $OR_AUTHCFG = 8;
+my @cmds = (
+    {
+        'name' => 'Perl6ResponseHandler',
+        'args_how' => $TAKE1,
+        'func' => &cmd_perl6responsehandler,
+        'req_override' => $OR_AUTHCFG,
+        'errmsg' => 'usage: Perl6ResponseHandler handler-name'
+    }
+);
+
+# register hooks
+# XXX would be nice to use the enum strings here
+my @hooks = (13);
+
+Apache::Module::add(
+    'modparrot_perl6_module',
+    'perl6',
+    @cmds,
+    @hooks
+);

Modified: mod_parrot/trunk/lib/Apache/Module.pir
==============================================================================
--- mod_parrot/trunk/lib/Apache/Module.pir	(original)
+++ mod_parrot/trunk/lib/Apache/Module.pir	Sun Sep 21 12:23:18 2008
@@ -33,14 +33,11 @@
 
     null nul
 
-    dlfunc func, nul, "mpnci_add_apache_module", "pJtP"
+    dlfunc func, nul, "mpnci_add_apache_module", "pJttPP"
     set_root_global [ '_modparrot'; 'NCI' ], "add_apache_module", func
 
-    dlfunc func, nul, "mpnci_dircfg_handler", "PJitti"
-    set_root_global [ '_modparrot'; 'NCI' ], "dircfg_handler", func
-
-    dlfunc func, nul, "mpnci_srvcfg_handler", "PJitti"
-    set_root_global [ '_modparrot'; 'NCI' ], "srvcfg_handler", func
+    dlfunc func, nul, "mpnci_get_module_config", "PJtpi"
+    set_root_global [ '_modparrot'; 'NCI' ], "get_module_config", func
 
     newclass module_class, [ 'Apache'; 'Module' ]
     addattribute module_class, 'module'
@@ -50,7 +47,7 @@
 
 =over 4
 
-=item C<add(STRING name, ARRAY cmds)>
+=item C<add(STRING name, STRING namespace, ARRAY cmds)>
 
 =over 4
 
@@ -59,9 +56,12 @@
 an early interpreter startup.
 
 C<name> is the name of your module.  It should be unique.  HLLs should prepend
-mdoule names with the name of the HLL to avoid conflicts.  C<cmds> is an array
-of hashes.  Each element of the array defines a configuration directive.  The
-directive hash is defined as follows:
+mdoule names with the name of the HLL to avoid conflicts.
+
+C<namespace> is the namespace of your module under ModParrot;HLL.
+
+C<cmds> is an array of hashes.  Each element of the array defines a
+configuration directive.  The directive hash is defined as follows:
 
 =over 4
 
@@ -131,75 +131,41 @@
 
 .sub add
     .param string name
+    .param string namespace
     .param pmc cmds
+    .param pmc hooks
     .local pmc add_module
 
     add_module = get_root_global ['_modparrot'; 'NCI' ], "add_apache_module"
-    add_module(name, cmds)
+    add_module(name, namespace, cmds, hooks)
 .end
 
 =back
 
 =over 4
 
-=item C<modparrot_dircfg_handler(INT hook, STRING hll, STRING id)>
+=item C<get_config(STRING name, PMC per_dir_config)>
 
 =over 4
 
-Get or set a mod_parrot handler.
+Get the server or directory configuration PMC.
 
 =cut
 
-.sub modparrot_dircfg_handler
-    .param int hook
-    .param pmc hll :optional
-    .param pmc id :optional
-    .param int update :opt_flag
-    .local pmc func, res
-
-    func = get_root_global ['_modparrot'; 'NCI' ], "dircfg_handler"
-
-    if update goto do_update
-    hll = new 'String'
-    id = new 'String'
-  do_update:
-    res = func(hook, hll, id, update)
+.sub get_config
+    .param string name
+    .param pmc per_dir_config :optional
+    .param int is_directory :opt_flag
+    .local pmc config, get_conf
 
-    .return(res)
+    get_conf = get_root_global ['_modparrot'; 'NCI' ], "get_module_config"
+    config = get_conf(name, per_dir_config, is_directory)
+    
+    .return(config)
 .end
 
 =back
 
-=over 4 
-
-=item C<modparrot_srvcfg_handler(INT hook, STRING hll, STRING id)>
-
-=over 4
-
-Get or set a mod_parrot handler.
-
-=cut
-
-.sub modparrot_srvcfg_handler
-    .param int hook
-    .param pmc hll :optional
-    .param pmc id :optional
-    .param int update :opt_flag
-    .local pmc func, res
-
-    func = get_root_global ['_modparrot'; 'NCI' ], "srvcfg_handler"
-
-    if update goto do_update
-    hll = new 'String'
-    id = new 'String'
-  do_update:
-    res = func(hook, hll, id, update)
-   
-    .return(res)
-.end 
-    
-=back
-
 =head1 AUTHOR
 
 Jeff Horwitz

Modified: mod_parrot/trunk/lib/Apache/RequestRec.pir
==============================================================================
--- mod_parrot/trunk/lib/Apache/RequestRec.pir	(original)
+++ mod_parrot/trunk/lib/Apache/RequestRec.pir	Sun Sep 21 12:23:18 2008
@@ -489,6 +489,31 @@
     .return(val)
 .end
 
+=back
+
+=item C<PMC per_dir_config()>
+
+=over 4
+
+Retrieve the per-directory configuration vector for this request.  This PMC
+is opaque and should only be passed to other methods.
+
+=back
+
+=cut
+
+.sub per_dir_config :method
+    .local pmc dircfg
+    .local pmc get_config
+    .local pmc r
+
+    get_config = get_root_global ['_modparrot'; 'NCI'], 'request_rec_per_dir_config'
+    getattribute r, self, 'r'
+    dircfg = get_config(r)
+
+    .return(dircfg)
+.end
+
 =head1 AUTHOR
 
 Jeff Horwitz

Modified: mod_parrot/trunk/lib/ModParrot/HLL/perl6.pir
==============================================================================
--- mod_parrot/trunk/lib/ModParrot/HLL/perl6.pir	(original)
+++ mod_parrot/trunk/lib/ModParrot/HLL/perl6.pir	Sun Sep 21 12:23:18 2008
@@ -19,6 +19,8 @@
     .local pmc find_file_in_path
 
     load_bytecode 'languages/perl6/perl6.pbc'
+    load_bytecode 'Apache/Module.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
 
     $P0 = new 'Env'
     $S0 = $P0['PERL6LIB']
@@ -38,78 +40,8 @@
     $P0.'register'($P1)
     $P1 = get_class ['ModParrot'; 'Context']
     $P0.'register'($P1)
-
-    # register apache directives
-    .local pmc add_module, cmds, ap_const
-
-    ap_const = get_root_global ['Apache'; 'Constants'], 'ap_constants'
-
-    load_bytecode 'Apache/Module.pbc'
-    load_bytecode 'ModParrot/Constants.pbc'
-
-    cmds = new 'Array'
-    cmds = 2
-
-    $P0 = new 'Hash'
-    $P1 = new 'String'
-    $P1 = 'Perl6ResponseHandler'
-    $P0['name'] = $P1
-    $P1 = new 'Integer'
-    $P1 = ap_const['TAKE1']
-    $P0['args_how'] = $P1
-    $P1 = get_hll_global [ 'ModParrot'; 'HLL'; 'perl6' ], 'cmd_perl6responsehandler'
-    $P0['func'] = $P1
-    $P1 = new 'Integer'
-    $P1 = ap_const['OR_AUTHCFG']
-    $P0['req_override'] = $P1
-    $P1 = new 'String'
-    $P1 = "usage: Perl6ResponseHandler handler-name"
-    $P0['errmsg'] = $P1
-    cmds[0] = $P0
-
-    $P0 = new 'Hash'
-    $P1 = new 'String'
-    $P1 = 'Perl6Module'
-    $P0['name'] = $P1
-    $P1 = new 'Integer'
-    $P1 = ap_const['TAKE1']
-    $P0['args_how'] = $P1
-    $P1 = get_hll_global [ 'ModParrot'; 'HLL'; 'perl6' ], 'cmd_perl6module'
-    $P0['func'] = $P1
-    $P1 = new 'Integer'
-    $P1 = ap_const['RSRC_CONF']
-    $P0['req_override'] = $P1
-    $P1 = new 'String'
-    $P1 = "usage: Perl6Module module"
-    $P0['errmsg'] = $P1
-    cmds[1] = $P0
-
-    add_module = get_hll_global [ 'Apache'; 'Module' ], 'add'
-    $P1 = add_module("modparrot_perl6_module", cmds)
 .end
 
 # declare namespace AFTER loading compiler
 # otherwise we get method resolution errors
 .namespace [ 'ModParrot'; 'HLL'; 'perl6' ]
-
-# helper functions go here
-
-.sub cmd_perl6responsehandler
-    .param pmc args
-    .local string handler
-    .local pmc mp_const
-
-    mp_const = get_root_global ['ModParrot'; 'Constants'], 'mp_constants'
-    handler = args[0]
-    $P0 = get_hll_global ['Apache'; 'Module'], 'modparrot_dircfg_handler'
-    $I0 = mp_const['MP_HOOK_RESPONSE']
-    $P1 = $P0($I0, 'perl6', handler)
-.end
-
-.sub cmd_perl6module
-    .param pmc args
-    $P0 = get_hll_global [ 'ModParrot'; 'HLL'; 'perl6' ], '@preloaded_modules'
-    $P1 = new 'Perl6Str'
-    $P1 = args[0]
-    $P0.push($P1)
-.end

Modified: mod_parrot/trunk/lib/ModParrot/HLL/pir.pir
==============================================================================
--- mod_parrot/trunk/lib/ModParrot/HLL/pir.pir	(original)
+++ mod_parrot/trunk/lib/ModParrot/HLL/pir.pir	Sun Sep 21 12:23:18 2008
@@ -14,47 +14,231 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+.sub __onload :anon :load
+    load_bytecode 'Apache/Module.pbc'
+    load_bytecode 'ModParrot/Constants.pbc'
+
+    # register apache directives
+    .local pmc add_module, cmds, hooks
+
+    cmds = new 'ResizablePMCArray'
+
+    $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)
+    $P0 = new_cmd('ParrotCleanupHandler', 'TAKE1', 'cmd_parrotcleanuphandler', 'OR_AUTHCFG', 'usage: ParrotCleanupHandler handler-name')
+    cmds.push($P0)
+
+    # XXX shouldn't have to hardcode the size of this array
+    hooks = new 'ResizablePMCArray'
+    $I0 = 0
+  loop_start:
+    $P0 = new 'Integer'
+    $P0 = $I0
+    hooks[$I0] = $P0
+    inc $I0
+    if $I0 < 19 goto loop_start
+    
+    add_module = get_hll_global [ '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 ['Apache'; 'Constants'], 'ap_constants'
+    
+    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['OR_AUTHCFG']
+    cmd['req_override'] = $P0
+    $P0 = new 'String'
+    $P0 = errmsg
+    cmd['errmsg'] = $P0
+
+    .return(cmd)
+.end
+    
 .namespace [ 'ModParrot'; 'HLL'; 'PIR' ]
 
+.sub server_create
+     $P0 = new 'Hash'
+     .return($P0)
+.end
+
+.sub dir_create
+     $P0 = new 'Hash'
+     .return($P0)
+.end
+
+# XXX implement merging
+
+#.sub server_merge
+#.end
+
+#.sub dir_merge
+#.end
+
+.sub cmd_parrothandler
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['response_handler'] = $S0
+.end
+
+.sub cmd_parrotauthenhandler
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['authen_handler'] = $S0
+.end
+
+.sub cmd_parrotauthzhandler
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['authz_handler'] = $S0
+.end
+
+.sub cmd_parrotaccesshandler
+    .param pmc dircfg
+    .param pmc args
+
+    $S0 = args[0]
+    dircfg['access_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 ['Apache'; 'Constants'], 'ap_constants'
+
     # 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 ['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'
+    find_global handler, $S0, '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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -64,16 +248,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -83,16 +286,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -102,29 +324,40 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
+    # get configs
+    get_config = get_hll_global ['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
+    find_global handler, $S0, '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()
+    # XXX need access to these from the context!
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'conf_pool'
+    pconf = $P0()
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'log_pool'
+    plog = $P0()
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'temp_pool'
+    ptemp = $P0()
 
     # 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 +367,39 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
+    # get configs
+    get_config = get_hll_global ['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
+    find_global handler, $S0, '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()
+    # XXX need access to these from the context!
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'conf_pool'
+    pconf = $P0()
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'log_pool'
+    plog = $P0()
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'temp_pool'
+    ptemp = $P0()
 
     # 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 +409,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
 
-    # get the server_rec object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'server_rec'
-    s = func()
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
+
+    # get the pool objects
+    # XXX need access to these from the context!
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'child_pool'
+    pchild = $P0()
+
+    # get the server_rec object
+    $P0 = get_root_global [ '_modparrot'; 'NCI' ], 'server_rec'
+    s = $P0()
+
     status = handler(pchild, s)
 
     # return status code
@@ -192,23 +447,33 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
 
-    # get the csd object
-    func = get_root_global [ '_modparrot'; 'NCI' ], 'csd'
-    csd = func()
+    # get configs
+    get_config = get_hll_global ['Apache'; 'Module'], 'get_config'
+    cfg = get_config('modparrot_pir_module')
 
+    # 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'
+    find_global handler, $S0, '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 +483,70 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, '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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -259,17 +556,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -279,17 +594,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -299,17 +632,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -319,17 +670,35 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -339,36 +708,74 @@
 # 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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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'
+    find_global handler, $S0, '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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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['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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code
@@ -378,16 +785,35 @@
 # cleanup handler
 .sub cleanup_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 ['Apache'; 'Constants'], 'ap_constants'
+
     # get the request_rec object
     r = ctx.'request_rec'()
 
+    # get configs
+    get_config = get_hll_global ['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['cleanup_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'
+    find_global handler, $S0, 'handler'
     status = handler(r)
 
     # return status code

Modified: mod_parrot/trunk/lib/mod_parrot.pir
==============================================================================
--- mod_parrot/trunk/lib/mod_parrot.pir	(original)
+++ mod_parrot/trunk/lib/mod_parrot.pir	Sun Sep 21 12:23:18 2008
@@ -51,6 +51,9 @@
     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, nul, "mpnci_request_rec_per_dir_config", "pJp"
+    set_root_global [ '_modparrot'; 'NCI' ], "request_rec_per_dir_config", func
+
     dlfunc func, nul, "mpnci_rwrite", "iJPip"
     set_root_global [ '_modparrot'; 'NCI' ], "rwrite", func
 
@@ -85,7 +88,6 @@
     load_bytecode 'Apache/Constants.pbc'
     load_bytecode 'Apache/RequestRec.pbc'
     load_bytecode 'APR/Table.pbc'
-    load_bytecode 'ModParrot/HLL/pir.pbc'
 .end
 
 .sub modparrot_set_include_path

Modified: mod_parrot/trunk/src/mod_parrot.c
==============================================================================
--- mod_parrot/trunk/src/mod_parrot.c	(original)
+++ mod_parrot/trunk/src/mod_parrot.c	Sun Sep 21 12:23:18 2008
@@ -38,16 +38,9 @@
 
 #define MODPARROT_VERSION "0.4"
 
-#define DEFAULT_HANDLER "handler"
-#define SHOULD_HANDLE(x) (x->handler ? \
- (strncmp(x->handler, MODPARROT_MAGIC, strlen(MODPARROT_MAGIC)) ? 0 : 1) : 0)
-
 /* 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.
@@ -57,23 +50,18 @@
 /* have we started?  this can be global since it's written to at startup */
 int mp_is_started = 0;
 
-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_meta_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 +72,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);
     }
 }
 
@@ -148,6 +136,9 @@
         else {
             interp = ctxp->interp;
         }
+
+        /* usually set s in a hook, but need it here for the config phase */
+        ctxp->s = s;
     }
     else {
         MPLOG_ERROR(s, "init_ctx: no free contexts");
@@ -217,131 +208,55 @@
     return res ? 1 : 0;
 }
 
-static char *get_request_hll(request_rec *r, const char *handler,
-    const char *content_type)
+static int modparrot_call_meta_handler(Parrot_Interp interp, char *hll,
+    char *hook, int *ret)
 {
-    modparrot_srv_config *cfg;
-    char *hll;
-
-    cfg = ap_get_module_config(r->server->module_config, &parrot_module);
+    Parrot_PMC ctx_class;
+    Parrot_PMC ctx_pmc;
+    Parrot_PMC namespace;
+    Parrot_Int typenum;
+    int res;
 
-    /* check handler name */
-    hll = (char *)apr_table_get(cfg->handler_map, handler);
-    if (hll) return hll;
+    typenum = Parrot_PMC_typenum(interp, "ResizableStringArray");
+    namespace = (Parrot_PMC)Parrot_PMC_new(interp, typenum);
+    Parrot_register_pmc(interp, namespace);
+    Parrot_PMC_set_intval(interp, namespace, 2);
+    Parrot_PMC_set_cstring_intkey(interp, namespace, 0, "ModParrot");
+    Parrot_PMC_set_cstring_intkey(interp, namespace, 1, "Context");
+    ctx_class = Parrot_oo_get_class(interp, namespace);
+    Parrot_unregister_pmc(interp, namespace);
 
-    /* check mime type */
-    if (content_type) {
-        hll = (char *)apr_table_get(cfg->type_map, content_type);
-        if (hll) return hll;
-    }
+    ctx_pmc = Parrot_Class_instantiate(interp, ctx_class, PMCNULL);
+    Parrot_register_pmc(interp, ctx_pmc);
 
-    return NULL;
+    if (!hll) hll = MODPARROT_DEFAULT_HLL;
+    res = modparrot_call_sub_IP(interp, hll, hook, ret, ctx_pmc);
+    Parrot_unregister_pmc(interp, ctx_pmc);
+    return res ? 1 : 0;
 }
 
-/* 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)
+static int modparrot_request_phase_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;
-    }
 
     /* initialize context */
     if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for handler '%s'",
-            dircfg->handler->id);
+        MPLOG_ERROR(r->server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "handler";
-    if (!modparrot_meta_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);
 
-    /* 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;
-    }
 
     /* initialize context */
     if (!(ctxp = init_ctx(c->base_server))) {
@@ -349,45 +264,25 @@
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->c = c;
-    ctxp->csd = csd;
-
-    /* call HLL handler */
-    sub = "pre_connection_handler";
-    hll = cfg->pre_connection_handler->hll ?
-        cfg->pre_connection_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_meta_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;
-    }
+    /* we're REALLY_FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
     /* clean up */
     release_ctx(ctxp);
 
-    /* tell apache we're done */
-    return handler_status;
+    /* we only do setup */
+    return DECLINED;
 }
 
-static int modparrot_map_to_storage_handler(request_rec *r)
+/* not a true handler since it has no hook */
+static int modparrot_meta_cleanup_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);
-
-    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;
-    }
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status, m;
 
     /* initialize context */
     if (!(ctxp = init_ctx(r->server))) {
@@ -395,127 +290,115 @@
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
-
-    /* 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_meta_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;
-    }
-
-    /* clean up */
-    release_ctx(ctxp);
+    /* get next module in line -- count backwards since cleanups are LIFO */
+    m = ctxp->module_index--;
+    if (m < 0) return HTTP_INTERNAL_SERVER_ERROR;
 
-    /* tell apache we're done */
-    return handler_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);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(header_parser_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(r->server->module_config, &parrot_module);
+    if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
 
     ctxp->r = r;
 
-    /* call HLL handler */
-    sub = "header_parser_handler";
-    if (!modparrot_meta_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 */
+    modp = ((module **)mpcfg->module_array->elts)[m];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    if (!modparrot_call_meta_handler(ctxp->interp, minfo->namespace,
+       "cleanup_handler", &status)) {
+        MPLOG_ERRORF(r->server, "no cleanup 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_post_read_request_handler(request_rec *r)
+static apr_status_t modparrot_meta_request_cleanup(void *data)
 {
-    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;
-    }
-
-    /* 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 = "post_read_request_handler";
-    hll = cfg->post_read_request_handler->hll ?
-        cfg->post_read_request_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_meta_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;
-    }
-
-    /* tell apache we're done */
-    return handler_status;
+    request_rec *r = (request_rec *)data;
+    modparrot_meta_cleanup_handler(r);
+    return APR_SUCCESS;
 }
 
-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(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;
-    }
+#define MP_REQUEST_METAHANDLER(hname, register_cleanup) \
+    int modparrot_meta_##hname(request_rec *r) \
+    { \
+        modparrot_context *ctxp; \
+        modparrot_module_config *dircfg; \
+        modparrot_srv_config *mpcfg; \
+        module *modp; \
+        modparrot_module_info *minfo; \
+        Parrot_PMC sub; \
+        int status; \
+        /* initialize context */ \
+        if (!(ctxp = init_ctx(r->server))) { \
+            MPLOG_ERROR(r->server, "context initialization failed"); \
+            return HTTP_INTERNAL_SERVER_ERROR; \
+        } \
+        /* get next module in line */ \
+        ctxp->module_index++; \
+        /* decline if mod_parrot isn't enabled */ \
+        mpcfg = ap_get_module_config(r->server->module_config, \
+            &parrot_module); \
+        if (!(mpcfg->option_flags & MP_OPT_ENABLE)) return DECLINED; \
+        /* take this opportunity to register the mod_parrot cleanup handler \
+         * here, as we may not handle any other part of the request until
+         * then. \
+         */ \
+        if (register_cleanup) { \
+            apr_pool_cleanup_register(r->pool, r, \
+                modparrot_meta_request_cleanup, apr_pool_cleanup_null); \
+        } \
+        ctxp->r = r; \
+        /* XXX register cleanup handler here or in the meta handler? */ \
+        /* XXX does header_only check belong in the meta handler? */ \
+        if (r->header_only) { \
+            return OK; \
+        } \
+        /* get HLL config */ \
+        modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index]; \
+        minfo = (modparrot_module_info *)modp->dynamic_load_handle; \
+        dircfg = (modparrot_module_config *)ap_get_module_config( \
+            r->per_dir_config, modp); \
+        /* call meta handler */ \
+        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; \
+        } \
+        /* clean up */ \
+        release_ctx(ctxp); \
+        /* tell apache we're done */ \
+        return status; \
+    }
+
+MP_REQUEST_METAHANDLER(post_read_request_handler, 1)
+MP_REQUEST_METAHANDLER(map_to_storage_handler, 0)
+MP_REQUEST_METAHANDLER(trans_handler, 0)
+MP_REQUEST_METAHANDLER(header_parser_handler, 0)
+MP_REQUEST_METAHANDLER(access_handler, 0)
+MP_REQUEST_METAHANDLER(authen_handler, 0)
+MP_REQUEST_METAHANDLER(authz_handler, 0)
+MP_REQUEST_METAHANDLER(response_handler, 0)
+MP_REQUEST_METAHANDLER(type_handler, 0)
+MP_REQUEST_METAHANDLER(fixup_handler, 0)
+MP_REQUEST_METAHANDLER(log_handler, 0)
+
+int modparrot_meta_pre_connection_handler(conn_rec *c, void *csd)
+{
+    modparrot_context *ctxp;
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
     /* initialize context */
     if (!(ctxp = init_ctx(c->base_server))) {
@@ -523,387 +406,185 @@
         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_meta_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);
-        release_ctx(ctxp);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_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;
-    }
+    /* get next module in line */
+    ctxp->module_index++;
 
-    /* initialize context */
-    if (!(ctxp = init_ctx(s))) {
-        MPLOG_ERROR(s, "context initialization failed");
-        return;
-    }
+    /* 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;
 
-    ctxp->pchild = p;
-    ctxp->s = s;
+    ctxp->c = c;
+    ctxp->csd = csd;
 
-    /* call HLL handler */
-    sub = "child_init_handler";
-    hll = cfg->child_init_handler->hll ?
-        cfg->child_init_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_meta_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;
+    /* get HLL config */
+    modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    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;
     }
 
     /* clean up */
     release_ctx(ctxp);
 
     /* tell apache we're done */
-    return;
+    return status;
 }
 
-static int modparrot_trans_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);
-
-    /* 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");
+    if (!(ctxp = init_ctx(c->base_server))) {
+        MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "trans_handler";
-    hll = cfg->trans_handler->hll ? 
-        cfg->trans_handler->hll : MODPARROT_DEFAULT_HLL;
-
-    if (!modparrot_meta_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;
-    }
+    /* we're REALLY_FIRST, so reset the module index */
+    ctxp->module_index = -1;
 
     /* clean up */
     release_ctx(ctxp);
 
-    /* tell apache we're done */
-    return handler_status;
+    /* we only do setup */
+    return DECLINED;
 }
 
-static int modparrot_fixup_handler(request_rec *r)
+int modparrot_meta_process_connection_handler(conn_rec *c)
 {
-    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(fixup_handler);
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
     /* 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_meta_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
-        MPLOG_ERRORF(r->server, "no subroutine found for handler '%s'",
-            hll_handler);
-        release_ctx(ctxp);
+    if (!(ctxp = init_ctx(c->base_server))) {
+        MPLOG_ERROR(c->base_server, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    /* 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;
+    /* get next module in line */
+    ctxp->module_index++;
 
-    SET_HLL_HANDLER(type_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;
 
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERROR(r->server, "context initialization failed");
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    ctxp->r = r;
+    ctxp->c = c;
 
-    /* call HLL handler */
-    sub = "type_handler";
-    if (!modparrot_meta_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 */
+    modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    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;
     }
 
     /* clean up */
     release_ctx(ctxp);
 
     /* tell apache we're done */
-    return handler_status;
+    return status;
 }
 
-static int modparrot_log_handler(request_rec *r)
+static void modparrot_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;
-
-    /* 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;
+    if (!(ctxp = init_ctx(s))) {
+        MPLOG_ERROR(s, "context initialization failed");
+        return;
     }
 
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "log_handler";
-    if (!modparrot_meta_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);
-
-    /* tell apache we're done */
-    return handler_status;
 }
 
-static int modparrot_access_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);
-
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(access_handler);
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for access handler '%s'",
-            dircfg->access_handler->id);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-    ctxp->r = r;
-
-    /* call HLL handler */
-    sub = "access_handler";
-    if (!modparrot_meta_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))) {
+        MPLOG_ERROR(s, "context initialization failed");
+        return;
     }
 
-    /* clean up */
-    release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
-}
-
-static int modparrot_authen_handler(request_rec *r)
-{
-    modparrot_dir_config *dircfg;
-    modparrot_srv_config *cfg;
-    modparrot_context *ctxp;
-    int handler_status;
-    char *sub, *hll, *hll_handler;
+    /* get next module in line */
+    ctxp->module_index++;
 
-    /* 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);
+    /* 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;
 
-    if (!(cfg->option_flags & MP_OPT_ENABLE)) return DECLINED;
-
-    SET_HLL_HANDLER(authen_handler);
-
-    /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for authen handler '%s'",
-            dircfg->authen_handler->id);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-    ctxp->r = r;
+    ctxp->pchild = p;
+    ctxp->s = s;
 
-    /* call HLL handler */
-    sub = "authen_handler";
-    if (!modparrot_meta_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 */
+    modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    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);
+        return;
     }
 
     /* clean up */
     release_ctx(ctxp);
-
-    /* tell apache we're done */
-    return handler_status;
 }
 
-static int modparrot_authz_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;
-
-    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);
+    if (!(ctxp = init_ctx(s))) {
+        MPLOG_ERROR(s, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-    ctxp->r = r;
 
-    /* call HLL handler */
-    sub = "authz_handler";
-    if (!modparrot_meta_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);
 
-    /* tell apache we're done */
-    return handler_status;
+    /* we only do setup */
+    return DECLINED;
 }
 
-static int modparrot_post_config_handler(apr_pool_t *pconf, apr_pool_t *plog,
-    apr_pool_t *ptemp, server_rec *s)
+int modparrot_meta_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;
-    }
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
     /* initialize context */
     if (!(ctxp = init_ctx(s))) {
@@ -911,56 +592,62 @@
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
+    /* get next module in line */
+    ctxp->module_index++;
+
+    /* 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;
+
     ctxp->pconf = pconf;
     ctxp->plog = plog;
     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_meta_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 */
+    modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    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;
 
     /* 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 (mpcfg->option_flags & MP_OPT_ENABLE) {
         if (!(ctxp = modparrot_startup(pconf, s, NULL))) {
             return HTTP_INTERNAL_SERVER_ERROR;
         }
         parent_interp = ctxp->interp;
 
+        /* we're FIRST, so reset the module index */
+        ctxp->module_index = -1;
+
         /* 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);
         }
     }
 
@@ -988,90 +675,66 @@
         }
         else {
             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) {
-        release_ctx(ctxp);
-        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_meta_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;
-    }
-
     /* clean up */
     release_ctx(ctxp);
 
-    /* tell apache we're done */
-    return handler_status;
+    /* tell apache we're done -- open_logs handler must return OK */
+    return OK;
 }
 
-static int modparrot_cleanup_handler(request_rec *r)
+int modparrot_meta_open_logs_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);
-
-    SET_HLL_HANDLER(cleanup_handler);
+    modparrot_srv_config *mpcfg;
+    module *modp;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
+    int status;
 
     /* initialize context */
-    if (!(ctxp = init_ctx(r->server))) {
-        MPLOG_ERRORF(r->server,
-            "context initialization failed for cleanup handler '%s'",
-            dircfg->cleanup_handler->id);
+    if (!(ctxp = init_ctx(s))) {
+        MPLOG_ERROR(s, "context initialization failed");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-    ctxp->r = r;
 
-    /* call HLL handler */
-    sub = "cleanup_handler";
-    if (!modparrot_meta_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 next module in line */
+    ctxp->module_index++;
+
+    /* 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;
+
+    /* get HLL config */
+    modp = ((module **)mpcfg->module_array->elts)[ctxp->module_index];
+    minfo = (modparrot_module_info *)modp->dynamic_load_handle;
+    /* call meta handler */
+    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);
 
     /* tell apache we're done */
-    return handler_status;
-}
-
-static apr_status_t modparrot_request_cleanup(void *data)
-{
-    request_rec *r = (request_rec *)data;
-    modparrot_cleanup_handler(r);
-    return APR_SUCCESS;
+    return status;
 }
 
 static void register_hooks(apr_pool_t *p)
@@ -1080,23 +743,41 @@
     *(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[] =
@@ -1115,139 +796,6 @@
         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,
-        NULL,
-        RSRC_CONF,
-        "set the Parrot child exit handler"
-    ),
-    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,
-        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"
-    ),
     AP_INIT_ITERATE(
         "ParrotLoad",
         modparrot_cmd_load,
@@ -1269,20 +817,6 @@
         RSRC_CONF,
         "set the Parrot include path"
     ),
-    AP_INIT_ITERATE2(
-        "ParrotAddType",
-        modparrot_cmd_add_type,
-        NULL,
-        RSRC_CONF,
-        "associate a MIME type with a mod_parrot HLL"
-    ),
-    AP_INIT_ITERATE2(
-        "ParrotAddHandler",
-        modparrot_cmd_add_handler,
-        NULL,
-        RSRC_CONF,
-        "associate a handler string with a mod_parrot HLL"
-    ),
     AP_INIT_ITERATE(
         "ParrotOptions",
         modparrot_cmd_options,
@@ -1296,8 +830,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/trunk/src/modparrot_config.c
==============================================================================
--- mod_parrot/trunk/src/modparrot_config.c	(original)
+++ mod_parrot/trunk/src/modparrot_config.c	Sun Sep 21 12:23:18 2008
@@ -42,12 +42,21 @@
 {
     modparrot_srv_config *cfg;
     server_rec *s = (server_rec *)data;
+    int i;
 
     cfg = ap_get_module_config(s->module_config, &parrot_module);
+
+    /* destroy context pools and interpreters */
     mp_ctx_pool_destroy(cfg->ctx_pool);
     cfg->ctx_pool = NULL;
     mp_is_started = 0;
 
+    /* reset module configs so we recreate them on restart */
+    for (i = 0; i < cfg->module_array->nelts; i++) {
+        modparrot_module_config *modcfg;
+        modcfg = ((modparrot_module_config **)cfg->module_array->elts)[i];
+        modcfg->cfg = NULL;
+    }
     return APR_SUCCESS;
 }
 
@@ -62,17 +71,14 @@
     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->module_array = apr_array_make(p, 2, sizeof(module *));
+    cfg->module_hash = apr_hash_make(p);
 
     /* 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);
-
     return (void *)cfg;
 }
 
@@ -101,13 +107,10 @@
         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);
+    /* modules hash and array are only set in main server, so just copy */
+    /* XXX need to enforce this
+    newcfg->modules = apr_hash_copy(p, basecfg->modules);
+    newcfg->module_array = apr_array_copy(p, basecfg->module_array);
 
     /* merges specific to the Parent option */
     if (newcfg->option_flags & MP_OPT_PARENT) {
@@ -132,104 +135,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)
 {
@@ -276,35 +181,28 @@
 }
 
 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)
 {
     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);
-    }
+    /* this will start the interpreter if necessary and return a context */
+    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);
+    modparrot_load_file(ctxp->interp, cmd->server, path);
 
     /* clean up */
     release_ctx(ctxp);
@@ -312,195 +210,6 @@
     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