[svn:mod_parrot] r420 - in mod_parrot/branches/hll-modules: . include languages/perl6/lib lib lib/Apache lib/ModParrot/HLL src

[email protected] Tue, 16 Sep 2008 14:15:41 -0700 (PDT)
Newsgroups perl.cvs.mod_parrot
Message-ID <[email protected]>
Author: jhorwitz
Date: Tue Sep 16 14:15:39 2008
New Revision: 420

Modified:
   mod_parrot/branches/hll-modules/call_list.txt
   mod_parrot/branches/hll-modules/include/mod_parrot.h
   mod_parrot/branches/hll-modules/include/modparrot_config.h
   mod_parrot/branches/hll-modules/languages/perl6/lib/mod_perl6.pm
   mod_parrot/branches/hll-modules/lib/Apache/Module.pir
   mod_parrot/branches/hll-modules/lib/Apache/RequestRec.pir
   mod_parrot/branches/hll-modules/lib/ModParrot/HLL/perl6.pir
   mod_parrot/branches/hll-modules/lib/mod_parrot.pir
   mod_parrot/branches/hll-modules/src/mod_parrot.c
   mod_parrot/branches/hll-modules/src/modparrot_config.c
   mod_parrot/branches/hll-modules/src/module.c
   mod_parrot/branches/hll-modules/src/nci.c
   mod_parrot/branches/hll-modules/src/parrot_util.c

Log:
implement first-class HLL apache modules
converted mod_parrot response handler to use the new model
converted mod_perl6 response handler to use the new model
tests will fail until we convert PIR layer to the new model


Modified: mod_parrot/branches/hll-modules/call_list.txt
==============================================================================
--- mod_parrot/branches/hll-modules/call_list.txt	(original)
+++ mod_parrot/branches/hll-modules/call_list.txt	Tue Sep 16 14:15:39 2008
@@ -18,5 +18,6 @@
 v       pit
 v       ptt
 v       Jtiiipt
-p       JtP
+p       JttP
 P	Jitti
+P       Jtpi

Modified: mod_parrot/branches/hll-modules/include/mod_parrot.h
==============================================================================
--- mod_parrot/branches/hll-modules/include/mod_parrot.h	(original)
+++ mod_parrot/branches/hll-modules/include/mod_parrot.h	Tue Sep 16 14:15:39 2008
@@ -56,6 +56,7 @@
     server_rec *s;
     conn_rec *c;
     void *csd;
+    int module_index;
     modparrot_dir_config *dircfg; /* used by HLL directives */
     modparrot_srv_config *srvcfg; /* used by HLL directives */
 };
@@ -68,6 +69,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);
@@ -81,7 +83,7 @@
 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 *,
+module *modparrot_add_module(Parrot_Interp, apr_pool_t *, const char *, char *,
     Parrot_PMC);
 
 #endif /* _MODPARROT_H */

Modified: mod_parrot/branches/hll-modules/include/modparrot_config.h
==============================================================================
--- mod_parrot/branches/hll-modules/include/modparrot_config.h	(original)
+++ mod_parrot/branches/hll-modules/include/modparrot_config.h	Tue Sep 16 14:15:39 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
@@ -61,6 +62,30 @@
 };
 typedef struct modparrot_handler_info modparrot_handler_info; 
 
+/* number of apache hooks we support */
+/* XXX can we obtain this number dynamically? */
+#define MODPARROT_NUM_HOOKS 20
+
+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[MODPARROT_NUM_HOOKS]; /* 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;
@@ -74,6 +99,8 @@
     apr_array_header_t *preload;
     apr_table_t *handler_map;
     apr_table_t *type_map;
+    apr_array_header_t *module_array;
+    apr_hash_t *module_hash;
     modparrot_handler_info *open_logs_handler;
     modparrot_handler_info *child_init_handler;
     modparrot_handler_info *child_exit_handler;
@@ -133,6 +160,7 @@
 
 struct modparrot_module_cmd_data
 {
+    module *modp;
     Parrot_PMC func;     /* parrot callback sub */
     Parrot_PMC cmd_data; /* directive-specific cmd_data */
 };
@@ -198,4 +226,7 @@
     const char *);
 const char *modparrot_module_cmd_no_args(cmd_parms *, void *);
 
+/* handlers for HLL apache modules */
+int modparrot_meta_response_handler(request_rec *);
+
 #endif /* _MODPARROT_CONFIG_H */

Modified: mod_parrot/branches/hll-modules/languages/perl6/lib/mod_perl6.pm
==============================================================================
--- mod_parrot/branches/hll-modules/languages/perl6/lib/mod_perl6.pm	(original)
+++ mod_parrot/branches/hll-modules/languages/perl6/lib/mod_perl6.pm	Tue Sep 16 14:15:39 2008
@@ -30,10 +30,30 @@
     }
 }
 
-sub handler($ctx, $handler)
+sub server_create()
+{
+    my %cfg =
+        'foo' => 'bar';
+    return %cfg;
+}
+
+sub dir_create()
+{
+    my %cfg;
+    return %cfg;
+}
+
+sub handler($ctx)
 {
     my $r = $ctx.request_rec();
+
+#    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;
 }

Modified: mod_parrot/branches/hll-modules/lib/Apache/Module.pir
==============================================================================
--- mod_parrot/branches/hll-modules/lib/Apache/Module.pir	(original)
+++ mod_parrot/branches/hll-modules/lib/Apache/Module.pir	Tue Sep 16 14:15:39 2008
@@ -33,9 +33,12 @@
 
     null nul
 
-    dlfunc func, nul, "mpnci_add_apache_module", "pJtP"
+    dlfunc func, nul, "mpnci_add_apache_module", "pJttP"
     set_root_global [ '_modparrot'; 'NCI' ], "add_apache_module", func
 
+    dlfunc func, nul, "mpnci_get_module_config", "PJtpi"
+    set_root_global [ '_modparrot'; 'NCI' ], "get_module_config", func
+
     dlfunc func, nul, "mpnci_dircfg_handler", "PJitti"
     set_root_global [ '_modparrot'; 'NCI' ], "dircfg_handler", func
 
@@ -131,11 +134,36 @@
 
 .sub add
     .param string name
+    .param string namespace
     .param pmc cmds
     .local pmc add_module
 
     add_module = get_root_global ['_modparrot'; 'NCI' ], "add_apache_module"
-    add_module(name, cmds)
+    add_module(name, namespace, cmds)
+.end
+
+=back
+
+=over 4
+
+=item C<get_config(STRING name, PMC per_dir_config)>
+
+=over 4
+
+Get the server or directory configuration PMC.
+
+=cut
+
+.sub get_config
+    .param string name
+    .param pmc per_dir_config :optional
+    .param int is_directory :opt_flag
+    .local pmc config, get_conf
+
+    get_conf = get_root_global ['_modparrot'; 'NCI' ], "get_module_config"
+    config = get_conf(name, per_dir_config, is_directory)
+    
+    .return(config)
 .end
 
 =back

Modified: mod_parrot/branches/hll-modules/lib/Apache/RequestRec.pir
==============================================================================
--- mod_parrot/branches/hll-modules/lib/Apache/RequestRec.pir	(original)
+++ mod_parrot/branches/hll-modules/lib/Apache/RequestRec.pir	Tue Sep 16 14:15:39 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/branches/hll-modules/lib/ModParrot/HLL/perl6.pir
==============================================================================
--- mod_parrot/branches/hll-modules/lib/ModParrot/HLL/perl6.pir	(original)
+++ mod_parrot/branches/hll-modules/lib/ModParrot/HLL/perl6.pir	Tue Sep 16 14:15:39 2008
@@ -85,7 +85,7 @@
     cmds[1] = $P0
 
     add_module = get_hll_global [ 'Apache'; 'Module' ], 'add'
-    $P1 = add_module("modparrot_perl6_module", cmds)
+    $P1 = add_module("modparrot_perl6_module", "perl6", cmds)
 .end
 
 # declare namespace AFTER loading compiler
@@ -95,18 +95,17 @@
 # helper functions go here
 
 .sub cmd_perl6responsehandler
+    .param pmc dircfg
     .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)
+    dircfg['response_handler'] = handler
 .end
 
 .sub cmd_perl6module
+    .param pmc cfg
     .param pmc args
     $P0 = get_hll_global [ 'ModParrot'; 'HLL'; 'perl6' ], '@preloaded_modules'
     $P1 = new 'Perl6Str'

Modified: mod_parrot/branches/hll-modules/lib/mod_parrot.pir
==============================================================================
--- mod_parrot/branches/hll-modules/lib/mod_parrot.pir	(original)
+++ mod_parrot/branches/hll-modules/lib/mod_parrot.pir	Tue Sep 16 14:15:39 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
 

Modified: mod_parrot/branches/hll-modules/src/mod_parrot.c
==============================================================================
--- mod_parrot/branches/hll-modules/src/mod_parrot.c	(original)
+++ mod_parrot/branches/hll-modules/src/mod_parrot.c	Tue Sep 16 14:15:39 2008
@@ -154,6 +154,9 @@
         ctxp = (modparrot_context *)NULL;
     }
 
+    /* we normally set s in a hook, but we need it here for the config phase */
+    ctxp->s = s;
+
     return(ctxp);
 }
 
@@ -217,6 +220,33 @@
     return res ? 1 : 0;
 }
 
+static int modparrot_call_meta_handler(Parrot_Interp interp, char *hll,
+    char *hook, int *ret)
+{
+    Parrot_PMC ctx_class;
+    Parrot_PMC ctx_pmc;
+    Parrot_PMC namespace;
+    Parrot_Int typenum;
+    int res;
+
+    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);
+
+    ctx_pmc = Parrot_Class_instantiate(interp, ctx_class, PMCNULL);
+    Parrot_register_pmc(interp, ctx_pmc);
+
+    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;
+}
+
 static char *get_request_hll(request_rec *r, const char *handler,
     const char *content_type)
 {
@@ -266,64 +296,72 @@
     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;
-        }
+    /* initialize context */
+    if (!(ctxp = init_ctx(r->server))) {
+        MPLOG_ERROR(r->server, "context initialization failed");
+        return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    hll_handler = dircfg->handler ? dircfg->handler->id : (char *)r->handler;
+    /* we're REALLY_FIRST, so reset the module index */
+    ctxp->module_index = -1;
+
+    /* clean up */
+    release_ctx(ctxp);
 
-    /* set default content type */
-    r->content_type = "text/html";
+    /* we only do setup, no output */
+    return DECLINED;
+}
 
-    /* just headers? */
-    if (r->header_only) {
-        return OK;
-    }
+int modparrot_meta_response_handler(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_ERRORF(r->server,
-            "context initialization failed for handler '%s'",
-            dircfg->handler->id);
+        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;
+
     ctxp->r = r;
 
-    /* call HLL handler */
-    sub = "handler";
-    if (!modparrot_meta_handler(ctxp->interp, hll, sub, hll_handler,
-        &handler_status)) {
+    /* XXX register cleanup handler here or in the meta handler? */
+
+    /* XXX does this 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, "handler",
+        &status)) {
         MPLOG_ERRORF(r->server,
-            "no subroutine found for handler '%s'", hll_handler);
-        release_ctx(ctxp);
-	return HTTP_INTERNAL_SERVER_ERROR;
+            "no response 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_pre_connection_handler(conn_rec *c, void *csd)

Modified: mod_parrot/branches/hll-modules/src/modparrot_config.c
==============================================================================
--- mod_parrot/branches/hll-modules/src/modparrot_config.c	(original)
+++ mod_parrot/branches/hll-modules/src/modparrot_config.c	Tue Sep 16 14:15:39 2008
@@ -42,12 +42,22 @@
 {
     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++) {
+/* *l = &((modparrot_handler_info *)files->elts)[i] */
+        modparrot_module_config *modcfg;
+        modcfg = ((modparrot_module_config **)cfg->module_array->elts)[i];
+        modcfg->cfg = NULL;
+    }
     return APR_SUCCESS;
 }
 
@@ -66,6 +76,8 @@
     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);
@@ -109,6 +121,10 @@
     apr_table_overlap(merged->handler_map, newcfg->handler_map,
         APR_OVERLAP_TABLES_SET);
 
+    /* modules hash is only set in main server, so just copy */
+    /* XXX need to enforce this
+    newcfg->modules = apr_hash_copy(p, basecfg->modules);
+
     /* merges specific to the Parent option */
     if (newcfg->option_flags & MP_OPT_PARENT) {
         merged->include_path = newcfg->include_path ?
@@ -585,28 +601,68 @@
     return(args);
 }
 
-static void set_mp_config_vectors(modparrot_context *ctxp, cmd_parms *cmd)
+/* use only for setting mod_parrot's config, not HLL module configs */
+static void set_mp_config_vectors(modparrot_context *ctxp, module *modp,
+                                  cmd_parms *cmd)
 {
     modparrot_dir_config *cfg = (modparrot_dir_config *)ap_set_config_vectors(
-        cmd->server, cmd->context, cmd->path, &parrot_module, cmd->pool);
+            cmd->server, cmd->context, cmd->path, modp, cmd->pool);
+
     ctxp->dircfg = cfg;
     ctxp->srvcfg = (modparrot_srv_config *)ap_get_module_config(
-        cmd->server->module_config, &parrot_module);
+        cmd->server->module_config, modp);
 }
 
+#if 0 /* working... */
+static Parrot_PMC modparrot_module_hll_config(Parrot_PMC, int scope)
+#endif
+
 const char *modparrot_module_cmd_take1(cmd_parms *cmd, void *mconfig,
                                        const char *arg)
 {
     modparrot_context *ctxp;
-    Parrot_PMC dircfg;
     Parrot_PMC args;
     modparrot_module_cmd_data *data = cmd->cmd->cmd_data;
+    modparrot_module_info *minfo = data->modp->dynamic_load_handle;
+    modparrot_module_config *srvcfg, *dircfg;
     int ret;
 
+    /* mod_parrot specific stuff */
     ctxp = modparrot_startup(cmd->pool, cmd->server, NULL);
-    set_mp_config_vectors(ctxp, cmd);
+    
+    /* create/fetch module server config */
+    srvcfg = (modparrot_module_config *)ap_get_module_config(
+        cmd->server->module_config, data->modp);
+    if (srvcfg) {
+        if (!srvcfg->cfg) {
+            srvcfg->name = apr_pstrdup(cmd->pool, data->modp->name);
+            if (minfo->server_create_sub) {
+                /* XXX pass in pool and server_rec objects when implemented */
+                srvcfg->cfg = Parrot_call_sub(ctxp->interp,
+                    minfo->server_create_sub, "P");
+            }
+        }
+    }
+
+    /* create/fetch module directory config */
+    dircfg = (modparrot_module_config *)mconfig;
+    if (dircfg) {
+        if (!dircfg->cfg) {
+            srvcfg->name = apr_pstrdup(cmd->pool, data->modp->name);
+            if (minfo->dir_create_sub) {
+                /* XXX pass in pool and server_rec objects when implemented */
+                dircfg->cfg = Parrot_call_sub(ctxp->interp,
+                    minfo->dir_create_sub, "P");
+            }
+        }
+    }
+
     args = make_cmd_args_array(ctxp->interp, cmd->pool, 1, arg);
-    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IP", args);
+
+    /* XXX add cmd_parms to this when it's implemented */
+    ret = Parrot_call_sub_ret_int(ctxp->interp, data->func, "IPP",
+        dircfg->cfg, args);
+
     release_ctx(ctxp);
     return NULL;
 }

Modified: mod_parrot/branches/hll-modules/src/module.c
==============================================================================
--- mod_parrot/branches/hll-modules/src/module.c	(original)
+++ mod_parrot/branches/hll-modules/src/module.c	Tue Sep 16 14:15:39 2008
@@ -35,7 +35,6 @@
 
 extern module AP_MODULE_DECLARE_DATA parrot_module;
 AP_DECLARE_DATA extern module *ap_top_module;
-const char *modparrot_cmd_test(cmd_parms *, void *, const char *);
 
 static apr_status_t modparrot_remove_module(void *data)
 {
@@ -58,17 +57,61 @@
     }
 }
 
+static modparrot_module_config *modparrot_create_module_config(apr_pool_t *p)
+{
+    modparrot_module_config *cfg = (modparrot_module_config *)apr_pcalloc(p,
+        sizeof(modparrot_module_config));
+    return(cfg);
+}
+
+void *modparrot_module_srv_create(apr_pool_t *p, server_rec *s)
+{
+    modparrot_module_config *cfg = modparrot_create_module_config(p);
+    return(cfg);
+}
+
+void *modparrot_module_srv_merge(apr_pool_t *p, void *base, void *new)
+{
+    return(NULL);
+}
+
+void *modparrot_module_dir_create(apr_pool_t *p, char *path)
+{
+    modparrot_module_config *cfg = modparrot_create_module_config(p);
+    return(cfg);
+}
+
+void *modparrot_module_dir_merge(apr_pool_t *p, void *base, void *new)
+{
+    return(NULL);
+}
+
+static void register_meta_hooks(apr_pool_t *p)
+{
+    ap_hook_handler(modparrot_meta_response_handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
 /* this is very leaky */
 module *modparrot_add_module(Parrot_Interp interp, apr_pool_t *p,
-                          const char *name, Parrot_PMC cmd_array)
+                             const char *name,
+                             char *namespace,
+                             Parrot_PMC cmd_array)
 {
     int i, num;
+    modparrot_srv_config *mpcfg;
+    modparrot_module_info *minfo;
+    Parrot_PMC sub;
     module *modp = (module *)apr_pcalloc(p, sizeof(*modp));
+    module **modpp;
+    modparrot_context *ctxp = get_interp_ctx(interp);
+    server_rec *s = ctxp->s;
 
     if (!cmd_array) return(NULL);
     num = Parrot_PMC_get_intval(interp, cmd_array);
     if (!num) return(NULL);
 
+    mpcfg = ap_get_module_config(s->module_config, &parrot_module);
+
     command_rec *cmds =
         (command_rec *)apr_pcalloc(p, sizeof(command_rec)*(num+1));
 
@@ -133,6 +176,7 @@
                                         MAKE_PARROT_STRING("errmsg"));
         cmds[i].errmsg = Parrot_PMC_get_cstring(interp, val);
 
+        data->modp = modp;
         data->func = Parrot_PMC_get_pmc_keyed_str(interp, cmd,
                                         MAKE_PARROT_STRING("func"));
         data->cmd_data = Parrot_PMC_get_pmc_keyed_str(interp, cmd,
@@ -146,10 +190,42 @@
     modp->name          = (char *)apr_pstrdup(p, name);
     modp->magic         = MODULE_MAGIC_COOKIE;
 
-    modp->dynamic_load_handle = NULL; /* use for our data */
+    minfo = apr_pcalloc(p, sizeof(modparrot_module_info));
+    minfo->namespace = (char *)apr_pstrdup(p, namespace);
+    modp->dynamic_load_handle = minfo;
+
+    if (sub = get_sub_pmc(interp, namespace, "server_create")) {
+        modp->create_server_config = modparrot_module_srv_create;
+        minfo->server_create_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "server_merge")) {
+        modp->merge_server_config = modparrot_module_srv_merge;
+        minfo->server_merge_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "dir_create")) {
+        modp->create_dir_config = modparrot_module_dir_create;
+        minfo->dir_create_sub = sub;
+    }
+    if (sub = get_sub_pmc(interp, namespace, "dir_merge")) {
+        modp->merge_dir_config = modparrot_module_dir_merge;
+        minfo->dir_merge_sub = sub;
+    }
 
     modp->cmds = cmds; /* our command vector */
 
+    modp->register_hooks = register_meta_hooks;
+
+    /* module_array lets us access modules in sequence */
+#if 0
+    modpp = (module **)apr_array_push(mpcfg->module_array);
+    *modpp = modp; 
+#endif
+    *(module **)apr_array_push(mpcfg->module_array) = modp;
+
+    /* module_hash lets us access modules by name */
+    apr_hash_set(mpcfg->module_hash, (char *)apr_pstrdup(p, modp->name),
+        APR_HASH_KEY_STRING, modp);
+
     modparrot_insert_module(modp);
 
     ap_add_loaded_module(modp, p);

Modified: mod_parrot/branches/hll-modules/src/nci.c
==============================================================================
--- mod_parrot/branches/hll-modules/src/nci.c	(original)
+++ mod_parrot/branches/hll-modules/src/nci.c	Tue Sep 16 14:15:39 2008
@@ -23,6 +23,7 @@
 #include "http_protocol.h"
 #include "http_config.h"
 #include "apr_strings.h"
+#include "apr_hash.h"
 
 #include "parrot/parrot.h"
 #include "parrot/embed.h"
@@ -44,6 +45,12 @@
     return(ctxp->r);
 }
 
+struct ap_conf_vector_t *mpnci_request_rec_per_dir_config(Parrot_Interp interp,
+    request_rec *r)
+{
+    return(r->per_dir_config);
+}
+
 apr_pool_t *mpnci_conf_pool(Parrot_Interp interp)
 {
     modparrot_context *ctxp;
@@ -180,18 +187,54 @@
     ap_log_rerror(file, line, level, status, r, "%s", msg);
 }
 
-module *mpnci_add_apache_module(Parrot_Interp interp, char *name,
-    Parrot_PMC cmd_array)
+module *mpnci_add_apache_module(Parrot_Interp interp,
+                                const char *name,
+                                char *namespace,
+                                Parrot_PMC cmd_array)
 {
     modparrot_context *ctxp;
     module *modp;
 
     ctxp = get_interp_ctx(interp);
     if (!ctxp) return NULL;
-    modp = modparrot_add_module(interp, ctxp->pconf, name, cmd_array);
+    modp = modparrot_add_module(interp, ctxp->pconf, name, namespace, 
+        cmd_array);
     return(modp);
 }
 
+Parrot_PMC mpnci_get_module_config(Parrot_Interp interp, char *name,
+    ap_conf_vector_t *per_dir_config, int is_directory)
+{
+    modparrot_context *ctxp;
+    modparrot_srv_config *mpcfg;
+    modparrot_module_config *cfg;
+    module *modp;
+    apr_pool_t *pool;
+
+    ctxp = get_interp_ctx(interp);
+    if (!ctxp) return NULL;
+
+    mpcfg = ap_get_module_config(ctxp->s->module_config, &parrot_module);
+    modp = apr_hash_get(mpcfg->module_hash, name, APR_HASH_KEY_STRING);
+    if (!modp) {
+        return(NULL);
+    }
+
+    /* use request pool if we're in a request so we don't leak */
+    pool = ctxp->r ? ctxp->r->pool : ctxp->pconf;
+
+    if (is_directory) {
+        /* possibly do more here if not in a request */
+        cfg = ap_get_module_config(ctxp->r->per_dir_config, modp);
+    }
+    else {
+        cfg = ap_get_module_config(ctxp->s->module_config, modp);
+    }
+
+    /* return the PMC cfg inside the modparrot_module_config struct */
+    return(cfg->cfg);
+}
+ 
 #define SET_DIRCFG_INFO(x) if (update) { ctxp->dircfg->x = handler_info; } \
                              else { handler_info = ctxp->dircfg->x; }
 

Modified: mod_parrot/branches/hll-modules/src/parrot_util.c
==============================================================================
--- mod_parrot/branches/hll-modules/src/parrot_util.c	(original)
+++ mod_parrot/branches/hll-modules/src/parrot_util.c	Tue Sep 16 14:15:39 2008
@@ -155,6 +155,19 @@
     return(1);
 }
 
+int modparrot_call_sub_IP(Parrot_Interp interp, char *namespace, char *name,
+    int *ret, Parrot_PMC pmc)
+{
+    Parrot_PMC sub;
+
+    sub = get_sub_pmc(interp, namespace, name);
+    if (!sub) {
+        return(0);
+    }
+    *ret = Parrot_call_sub_ret_int(interp, sub, "IP", pmc);
+    return(1);
+}
+
 int modparrot_call_sub_IPS(Parrot_Interp interp, char *namespace, char *name,
     int *ret, Parrot_PMC pmc, char *arg)
 {