cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-12-13 Thread stas
stas2002/12/13 02:58:40

  Modified:perl-framework/Apache-Test/lib/Apache TestConfigPerl.pm
   src/modules/perl modperl_module.c
  Log:
  tidy up
  
  Revision  ChangesPath
  1.59  +1 -1  
httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfigPerl.pm
  
  Index: TestConfigPerl.pm
  ===
  RCS file: 
/home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfigPerl.pm,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -r1.58 -r1.59
  --- TestConfigPerl.pm 13 Dec 2002 10:04:28 -  1.58
  +++ TestConfigPerl.pm 13 Dec 2002 10:58:40 -  1.59
  @@ -396,7 +396,7 @@
   
   my $args_hash = list_to_hash_of_lists(\@args);
   $self->postamble($self->$container($module),
  -$args_hash) if @args;
  + $args_hash) if @args;
   
   $self->write_pm_test($module, lc $base, lc $sub);
   }
  
  
  
  1.11  +2 -2  modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- modperl_module.c  13 Dec 2002 04:40:31 -  1.10
  +++ modperl_module.c  13 Dec 2002 10:58:40 -  1.11
  @@ -377,8 +377,8 @@
* temporary link to the base server config's 'modules'
* member. e.g. so Apache::Module->get_config() can be called
* from a custom directive's callback, before the server/vhost
  - * config merge is performed */
  -
  + * config merge is performed
  + */
   if (!scfg->modules) {
   modperl_config_srv_t *base_scfg =
   modperl_config_srv_get(modperl_global_get_server_rec());
  
  
  



cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-12-12 Thread stas
stas2002/12/12 20:40:32

  Modified:src/modules/perl modperl_module.c
  Log:
  make sure that the vars declaration comes before any code, apparently gcc
  3.2's default is to allow the new ansi C extension to allow declarations
  anywhere in the code.
  Submitted by: "Philippe M. Chiasson" <[EMAIL PROTECTED]>
  Reviewed by:  stas
  
  Revision  ChangesPath
  1.10  +27 -19modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- modperl_module.c  12 Dec 2002 10:12:41 -  1.9
  +++ modperl_module.c  13 Dec 2002 04:40:31 -  1.10
  @@ -152,6 +152,15 @@
   *tmp,
   *base = (modperl_module_cfg_t *)basev,
   *add  = (modperl_module_cfg_t *)addv;
  +server_rec *s;
  +int is_startup;
  +PTR_TBL_t *table;
  +SV *mrg_obj = Nullsv, *base_obj, *add_obj;
  +
  +#ifdef USE_ITHREADS
  +modperl_interp_t *interp;
  +dTHX;
  +#endif
   
   /* if the module is loaded in vhost, base==NULL */
   tmp = (base && base->server) ? base : add;
  @@ -161,18 +170,17 @@
   return basev;
   }
   
  -server_rec *s = tmp->server;
  -int is_startup = (p == s->process->pconf);
  +s = tmp->server;
  +is_startup = (p == s->process->pconf);
   
   #ifdef USE_ITHREADS
  -modperl_interp_t *interp = modperl_interp_pool_select(p, s);
  -dTHXa(interp->perl);
  +interp = modperl_interp_pool_select(p, s);
  +aTHX = interp->perl;
   #endif
   
  -PTR_TBL_t *table = modperl_module_config_table_get(aTHX_ TRUE);
  -SV *mrg_obj = Nullsv,
  -*base_obj = modperl_svptr_table_fetch(aTHX_ table, base),
  -*add_obj  = modperl_svptr_table_fetch(aTHX_ table, add);
  +table = modperl_module_config_table_get(aTHX_ TRUE);
  +base_obj = modperl_svptr_table_fetch(aTHX_ table, base);
  +add_obj  = modperl_svptr_table_fetch(aTHX_ table, add);
   
   if (!base_obj || (base_obj == add_obj)) {
   return addv;
  @@ -335,7 +343,17 @@
   modperl_module_info_t *minfo = MP_MODULE_INFO(info->modp);
   modperl_module_cfg_t *srv_cfg;
   
  -   if (s->is_virtual) {
  +#ifdef USE_ITHREADS
  +modperl_interp_t *interp = modperl_interp_pool_select(p, s);
  +dTHXa(interp->perl);
  +#endif
  +
  +int count;
  +PTR_TBL_t *table = modperl_module_config_table_get(aTHX_ TRUE);
  +SV *obj = Nullsv;
  +dSP;
  +
  +if (s->is_virtual) {
   MP_dSCFG(s);
   
   /* if the Perl module is loaded in the base server and a vhost
  @@ -371,16 +389,6 @@
   
   }
   
  -#ifdef USE_ITHREADS
  -modperl_interp_t *interp = modperl_interp_pool_select(p, s);
  -dTHXa(interp->perl);
  -#endif
  -
  -int count;
  -PTR_TBL_t *table = modperl_module_config_table_get(aTHX_ TRUE);
  -SV *obj = Nullsv;
  -dSP;
  -
   errmsg = modperl_module_config_get_obj(aTHX_ p, table, cfg, info,
  minfo->dir_create,
  parms, &obj);
  
  
  



cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-12-12 Thread stas
stas2002/12/12 02:12:41

  Modified:src/modules/perl modperl_module.c
  Log:
  handle correct perlmodules (directives) with vhosts:
  - handle gracefully cases when things are undef/NULL
  - handle the case when scfg==NULL, by stealing the base_servers's config
  
  Revision  ChangesPath
  1.9   +47 -3 modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- modperl_module.c  17 Sep 2002 02:04:00 -  1.8
  +++ modperl_module.c  12 Dec 2002 10:12:41 -  1.9
  @@ -149,10 +149,18 @@
   GV *gv;
   modperl_mgv_t *method;
   modperl_module_cfg_t *mrg = NULL,
  +*tmp,
   *base = (modperl_module_cfg_t *)basev,
  -*add  = (modperl_module_cfg_t *)addv,
  -*tmp = base->server ? base : add;
  -
  +*add  = (modperl_module_cfg_t *)addv;
  +
  +/* if the module is loaded in vhost, base==NULL */
  +tmp = (base && base->server) ? base : add;
  +
  +if (tmp && !tmp->server) {
  +/* no directives for this module were encountered so far */
  +return basev;
  +}
  +
   server_rec *s = tmp->server;
   int is_startup = (p == s->process->pconf);
   
  @@ -327,6 +335,42 @@
   modperl_module_info_t *minfo = MP_MODULE_INFO(info->modp);
   modperl_module_cfg_t *srv_cfg;
   
  +   if (s->is_virtual) {
  +MP_dSCFG(s);
  +
  +/* if the Perl module is loaded in the base server and a vhost
  + * has configuration directives from that module, but no
  + * mod_perl.c directives, scfg == NULL when
  + * modperl_module_cmd_take123 is run. If the directive
  + * callback wants to do something with the mod_perl config
  + * object, it'll segfault, since it doesn't exist yet, because
  + * this happens before server configs are merged. So we create
  + * a temp struct and fill it in with things that might be
  + * needed by the Perl callback.
  + */
  +if (!scfg) {
  +scfg = modperl_config_srv_new(p);
  +modperl_set_module_config(s->module_config, scfg);
  +scfg->server = s;
  +}
  +
  +/* if PerlLoadModule Foo is called from the base server, but
  + * Foo's directives are used inside a vhost, we need to
  + * temporary link to the base server config's 'modules'
  + * member. e.g. so Apache::Module->get_config() can be called
  + * from a custom directive's callback, before the server/vhost
  + * config merge is performed */
  +
  +if (!scfg->modules) {
  +modperl_config_srv_t *base_scfg =
  +modperl_config_srv_get(modperl_global_get_server_rec());
  +if (base_scfg->modules) {
  +scfg->modules = base_scfg->modules;
  +}
  +}
  +
  +}
  +
   #ifdef USE_ITHREADS
   modperl_interp_t *interp = modperl_interp_pool_select(p, s);
   dTHXa(interp->perl);
  
  
  



cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-09-05 Thread dougm

dougm   2002/09/05 11:05:52

  Modified:src/modules/perl modperl_module.c
  Log:
  automate SvREFCNT-ing used with modperl_module_cmd_fetch a bit
  
  Revision  ChangesPath
  1.7   +9 -7  modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- modperl_module.c  4 Sep 2002 17:11:22 -   1.6
  +++ modperl_module.c  5 Sep 2002 18:05:52 -   1.7
  @@ -499,7 +499,10 @@
   {
   const char *errmsg = NULL;
   
  -*retval = Nullsv;
  +if (*retval) {
  +SvREFCNT_dec(*retval);
  +*retval = Nullsv;
  +}
   
   if (sv_isobject(obj)) {
   int count;
  @@ -572,7 +575,7 @@
   cmds = apr_array_make(p, fill+1, sizeof(command_rec));
   
   for (i=0; i<=fill; i++) {
  -SV *val;
  +SV *val = Nullsv;
   STRLEN len;
   SV *obj = AvARRAY(module_cmds)[i];
   modperl_module_cmd_data_t *info = modperl_module_cmd_data_new(p);
  @@ -586,7 +589,6 @@
   }
   
   cmd->name = apr_pstrdup(p, SvPV(val, len));
  -SvREFCNT_dec(val);
   
   if ((errmsg = modperl_module_cmd_fetch(aTHX_ obj, "args_how", &val))) {
   /* XXX default based on $self->func prototype */
  @@ -600,7 +602,6 @@
   cmd->args_how =
   modperl_constants_lookup_apache(SvPV(val, len));
   }
  -SvREFCNT_dec(val);
   }
   
   if (!modperl_module_cmd_lookup(cmd)) {
  @@ -614,7 +615,6 @@
   }
   else {
   info->func_name = apr_pstrdup(p, SvPV(val, len));
  -SvREFCNT_dec(val);
   }
   
   if ((errmsg = modperl_module_cmd_fetch(aTHX_ obj, "req_override", &val))) {
  @@ -628,7 +628,6 @@
   cmd->req_override =
   modperl_constants_lookup_apache(SvPV(val, len));
   }
  -SvREFCNT_dec(val);
   }
   
   if ((errmsg = modperl_module_cmd_fetch(aTHX_ obj, "errmsg", &val))) {
  @@ -638,7 +637,6 @@
   }
   else {
   cmd->errmsg = apr_pstrdup(p, SvPV(val, len));
  -SvREFCNT_dec(val);
   }
   
   cmd->cmd_data = info;
  @@ -646,7 +644,11 @@
   /* no default if undefined */
   if (!(errmsg = modperl_module_cmd_fetch(aTHX_ obj, "data", &val))) {
   info->cmd_data = apr_pstrdup(p, SvPV(val, len));
  +}
  +
  +if (val) {
   SvREFCNT_dec(val);
  +val = Nullsv;
   }
   }
   
  
  
  



cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-08-28 Thread dougm

dougm   2002/08/28 21:32:50

  Modified:src/modules/perl modperl_module.c
  Log:
  lookup {DIR,SERVER}_CREATE methods once per module
  
  Revision  ChangesPath
  1.5   +22 -18modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- modperl_module.c  29 Aug 2002 04:16:27 -  1.4
  +++ modperl_module.c  29 Aug 2002 04:32:50 -  1.5
  @@ -5,12 +5,11 @@
   modperl_mgv_t *dir_merge;
   modperl_mgv_t *srv_create;
   modperl_mgv_t *srv_merge;
  +int namelen;
   } modperl_module_info_t;
   
   typedef struct {
   server_rec *server;
  -const char *name;
  -int namelen;
   modperl_module_info_t *minfo;
   } modperl_module_cfg_t;
   
  @@ -233,11 +232,12 @@
 PTR_TBL_t *table,
 modperl_module_cfg_t *cfg,
 modperl_module_cmd_data_t *info,
  -  const char *method,
  +  modperl_mgv_t *method,
 cmd_parms *parms,
 SV **obj)
   {
  -HV *stash;
  +const char *mname = info->modp->name;
  +modperl_module_info_t *minfo = MP_MODULE_INFO(info->modp);
   GV *gv;
   int is_startup = (p == parms->server->process->pconf);
   
  @@ -253,26 +253,19 @@
   
   MP_TRACE_c(MP_FUNC, "%s cfg=0x%lx for %s.%s\n",
  method, (unsigned long)cfg,
  -   info->modp->name,
  -   parms->cmd->name);
  +   mname, parms->cmd->name);
   
  -cfg->name = info->modp->name;
  -cfg->namelen = strlen(cfg->name);
   /* used by merge functions to get a Perl interp */
   cfg->server = parms->server;
  -cfg->minfo = MP_MODULE_INFO(info->modp);
  +cfg->minfo = minfo;
   
  -stash = gv_stashpvn(cfg->name, cfg->namelen, TRUE);
  -
  -/* return $class->type if $class->can(type) */
  -/* XXX: should do this lookup at startup time */
  -if ((gv = gv_fetchmethod_autoload(stash, method, FALSE)) && isGV(gv)) {
  +if (method && (gv = modperl_mgv_lookup(aTHX_ method))) {
   int count;
   dSP;
   
   ENTER;SAVETMPS;
   PUSHMARK(sp);
  -XPUSHs(sv_2mortal(newSVpv(cfg->name, cfg->namelen)));
  +XPUSHs(sv_2mortal(newSVpv(mname, minfo->namelen)));
   XPUSHs(modperl_bless_cmd_parms(parms));
   
   PUTBACK;
  @@ -291,6 +284,7 @@
   }
   }
   else {
  +HV *stash = gv_stashpvn(mname, minfo->namelen, FALSE);
   /* return bless {}, $class */
   *obj = newRV_noinc((SV*)newHV());
   *obj = sv_bless(*obj, stash);
  @@ -321,6 +315,7 @@
   apr_pool_t *p = parms->pool;
   modperl_module_cmd_data_t *info =
   (modperl_module_cmd_data_t *)cmd->cmd_data;
  +modperl_module_info_t *minfo = MP_MODULE_INFO(info->modp);
   modperl_module_cfg_t *srv_cfg;
   
   #ifdef USE_ITHREADS
  @@ -334,7 +329,8 @@
   dSP;
   
   errmsg = modperl_module_config_get_obj(aTHX_ p, table, cfg, info,
  -   "DIR_CREATE", parms, &obj);
  +   minfo->dir_create,
  +   parms, &obj);
   
   if (errmsg) {
   return errmsg;
  @@ -354,8 +350,8 @@
   if (srv_cfg) {
   SV *srv_obj;
   errmsg = modperl_module_config_get_obj(aTHX_ p, table, srv_cfg, info,
  -   "SERVER_CREATE", parms,
  -   &srv_obj);
  +   minfo->srv_create,
  +   parms, &srv_obj);
   if (errmsg) {
   return errmsg;
   }
  @@ -729,8 +725,16 @@
   modp->create_server_config = modperl_module_config_srv_create;
   modp->merge_server_config  = modperl_module_config_srv_merge;
   
  +minfo->namelen = strlen(name);
  +
  +minfo->dir_create =
  +modperl_module_fetch_method(aTHX_ p, modp, "DIR_CREATE");
  +
   minfo->dir_merge =
   modperl_module_fetch_method(aTHX_ p, modp, "DIR_MERGE");
  +
  +minfo->srv_create =
  +modperl_module_fetch_method(aTHX_ p, modp, "SERVER_CREATE");
   
   minfo->srv_merge =
   modperl_module_fetch_method(aTHX_ p, modp, "SERVER_MERGE");
  
  
  



cvs commit: modperl-2.0/src/modules/perl modperl_module.c

2002-08-27 Thread dougm

dougm   2002/08/27 12:10:08

  Modified:src/modules/perl modperl_module.c
  Log:
  adjustments to compile with -DAP_HAVE_DESIGNATED_INITIALIZER
  
  Revision  ChangesPath
  1.2   +57 -40modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_module.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- modperl_module.c  27 Aug 2002 04:21:20 -  1.1
  +++ modperl_module.c  27 Aug 2002 19:10:08 -  1.2
  @@ -297,12 +297,13 @@
   #define PUSH_STR_ARG(arg) \
   if (arg) XPUSHs(sv_2mortal(newSVpv(arg,0)))
   
  -static const char *modperl_module_cmd_TAKE123(cmd_parms *parms,
  -  modperl_module_cfg_t *cfg,
  +static const char *modperl_module_cmd_take123(cmd_parms *parms,
  +  void *mconfig,
 const char *one,
 const char *two,
 const char *three)
   {
  +modperl_module_cfg_t *cfg = (modperl_module_cfg_t *)mconfig;
   const char *retval = NULL, *errmsg;
   const command_rec *cmd = parms->cmd;
   server_rec *s = parms->server;
  @@ -388,70 +389,86 @@
   return retval;
   }
   
  -static const char *modperl_module_cmd_TAKE1(cmd_parms *parms,
  -modperl_module_cfg_t *cfg,
  +static const char *modperl_module_cmd_take1(cmd_parms *parms,
  +void *mconfig,
   const char *one)
   {
  -return modperl_module_cmd_TAKE123(parms, cfg, one, NULL, NULL);
  +return modperl_module_cmd_take123(parms, mconfig, one, NULL, NULL);
   }
   
  -static const char *modperl_module_cmd_TAKE2(cmd_parms *parms,
  -modperl_module_cfg_t *cfg,
  +static const char *modperl_module_cmd_take2(cmd_parms *parms,
  +void *mconfig,
   const char *one,
   const char *two)
   {
  -return modperl_module_cmd_TAKE123(parms, cfg, one, two, NULL);
  +return modperl_module_cmd_take123(parms, mconfig, one, two, NULL);
   }
   
  -static const char *modperl_module_cmd_FLAG(cmd_parms *parms,
  -   modperl_module_cfg_t *cfg,
  +static const char *modperl_module_cmd_flag(cmd_parms *parms,
  +   void *mconfig,
  int flag)
   {
   char buf[2];
   
   apr_snprintf(buf, sizeof(buf), "%d", flag);
   
  -return modperl_module_cmd_TAKE123(parms, cfg, buf, NULL, NULL);
  +return modperl_module_cmd_take123(parms, mconfig, buf, NULL, NULL);
   }
   
  -#define modperl_module_cmd_RAW_ARGS modperl_module_cmd_TAKE1
  -#define modperl_module_cmd_NO_ARGS  modperl_module_cmd_TAKE1
  -#define modperl_module_cmd_ITERATE  modperl_module_cmd_TAKE1
  -#define modperl_module_cmd_ITERATE2 modperl_module_cmd_TAKE2
  -#define modperl_module_cmd_TAKE12   modperl_module_cmd_TAKE2
  -#define modperl_module_cmd_TAKE23   modperl_module_cmd_TAKE123
  -#define modperl_module_cmd_TAKE3modperl_module_cmd_TAKE123
  -#define modperl_module_cmd_TAKE13   modperl_module_cmd_TAKE123
  +static const char *modperl_module_cmd_no_args(cmd_parms *parms,
  +  void *mconfig)
  +{
  +return modperl_module_cmd_take123(parms, mconfig, NULL, NULL, NULL);
  +}
   
  -static cmd_func modperl_module_cmd_lookup(enum cmd_how args_how) {
  -switch (args_how) {
  -  case RAW_ARGS:
  -return modperl_module_cmd_RAW_ARGS;
  +#define modperl_module_cmd_raw_args modperl_module_cmd_take1
  +#define modperl_module_cmd_iterate  modperl_module_cmd_take1
  +#define modperl_module_cmd_iterate2 modperl_module_cmd_take2
  +#define modperl_module_cmd_take12   modperl_module_cmd_take2
  +#define modperl_module_cmd_take23   modperl_module_cmd_take123
  +#define modperl_module_cmd_take3modperl_module_cmd_take123
  +#define modperl_module_cmd_take13   modperl_module_cmd_take123
  +
  +#if defined(AP_HAVE_DESIGNATED_INITIALIZER)
  +#   define modperl_module_cmd_func_set(cmd, name) \
  +cmd->func.name = modperl_module_cmd_##name
  +#else
  +#   define modperl_module_cmd_func_set(cmd, name) \
  +cmd->func = modperl_module_cmd_##name
  +#endif
  +
  +static int modperl_module_cmd_lookup(command_rec *cmd)
  +{
  +switch (cmd->args_how) {
 case TAKE1:
  -return modperl_module_cmd_TAKE1;
  -  case TAKE2:
  -return modperl_module_cmd_TAKE2;
 case ITERATE:
  -return modperl_module_cmd_ITERATE;
  +mo

cvs commit: modperl-2.0/src/modules/perl modperl_module.c modperl_module.h

2002-08-26 Thread dougm

dougm   2002/08/26 21:21:20

  Added:   src/modules/perl modperl_module.c modperl_module.h
  Log:
  module to create an apache module on the fly to support directive handlers
  
  Revision  ChangesPath
  1.1  modperl-2.0/src/modules/perl/modperl_module.c
  
  Index: modperl_module.c
  ===
  #include "mod_perl.h"
  
  typedef struct {
  server_rec *server;
  const char *name;
  int namelen;
  } modperl_module_cfg_t;
  
  typedef struct {
  module *modp;
  const char *cmd_data;
  const char *func_name;
  } modperl_module_cmd_data_t;
  
  static modperl_module_cfg_t *modperl_module_cfg_new(apr_pool_t *p)
  {
  modperl_module_cfg_t *cfg =
  (modperl_module_cfg_t *)apr_pcalloc(p, sizeof(*cfg));
  
  return cfg;
  }
  
  static modperl_module_cmd_data_t *modperl_module_cmd_data_new(apr_pool_t *p)
  {
  modperl_module_cmd_data_t *cmd_data =
  (modperl_module_cmd_data_t *)apr_pcalloc(p, sizeof(*cmd_data));
  
  return cmd_data;
  }
  
  static void *modperl_module_config_dir_create(apr_pool_t *p, char *dir)
  {
  return modperl_module_cfg_new(p);
  }
  
  static void *modperl_module_config_srv_create(apr_pool_t *p, server_rec *s)
  {
  return modperl_module_cfg_new(p);
  }
  
  static SV **modperl_module_config_hash_get(pTHX_ int create)
  {
  SV **svp;
  
  /* XXX: could make this lookup faster */
  svp = hv_fetch(PL_modglobal,
 "ModPerl::Module::ConfigTable",
 MP_SSTRLEN("ModPerl::Module::ConfigTable"),
 create);
  
  return svp;
  }
  
  void modperl_module_config_table_set(pTHX_ PTR_TBL_t *table)
  {
  SV **svp = modperl_module_config_hash_get(aTHX_ TRUE);
  sv_setiv(*svp, (IV)table);
  }
  
  PTR_TBL_t *modperl_module_config_table_get(pTHX_ int create)
  {
  PTR_TBL_t *table = NULL;
  
  SV *sv, **svp = modperl_module_config_hash_get(aTHX_ create);
  
  if (!svp) {
  return NULL;
  }
  
  sv = *svp;
  if (!SvIOK(sv) && create) {
  table = ptr_table_new();
  sv_setiv(sv, (IV)table);
  }
  else {
  table = (PTR_TBL_t *)SvIV(sv);
  }
  
  return table;
  }
  
  typedef struct {
  PerlInterpreter *perl;
  PTR_TBL_t *table;
  void *ptr;
  } config_obj_cleanup_t;
  
  /*
   * any per-dir CREATE or MERGE that happens at request time
   * needs to be removed from the pointer table.
   */
  static apr_status_t modperl_module_config_obj_cleanup(void *data)
  {
  config_obj_cleanup_t *cleanup =
  (config_obj_cleanup_t *)data;
  dTHXa(cleanup->perl);
  
  modperl_svptr_table_delete(aTHX_ cleanup->table, cleanup->ptr);
  
  MP_TRACE_c(MP_FUNC, "deleting ptr 0x%lx from table 0x%lx\n",
 (unsigned long)cleanup->ptr,
 (unsigned long)cleanup->table);
  
  return APR_SUCCESS;
  }
  
  static void modperl_module_config_obj_cleanup_register(pTHX_
 apr_pool_t *p,
 PTR_TBL_t *table,
 void *ptr)
  {
  config_obj_cleanup_t *cleanup =
  (config_obj_cleanup_t *)apr_palloc(p, sizeof(*cleanup));
  
  cleanup->table = table;
  cleanup->ptr = ptr;
  #ifdef USE_ITHREADS
  cleanup->perl = aTHX;
  #endif
  
  apr_pool_cleanup_register(p, cleanup,
modperl_module_config_obj_cleanup,
apr_pool_cleanup_null);
  }
  
  static void *modperl_module_config_merge(apr_pool_t *p,
   void *basev, void *addv,
   const char *method)
  {
  GV *gv;
  
  modperl_module_cfg_t *mrg = NULL,
  *base = (modperl_module_cfg_t *)basev,
  *add  = (modperl_module_cfg_t *)addv,
  *tmp = base->server ? base : add;
  
  server_rec *s = tmp->server;
  int is_startup = (p == s->process->pconf);
  
  #ifdef USE_ITHREADS
  modperl_interp_t *interp = modperl_interp_pool_select(p, s);
  dTHXa(interp->perl);
  #endif
  
  PTR_TBL_t *table = modperl_module_config_table_get(aTHX_ TRUE);
  SV *mrg_obj = Nullsv,
  *base_obj = ptr_table_fetch(table, base),
  *add_obj  = ptr_table_fetch(table, add);
  
  HV *stash;
  
  if (!base_obj || (base_obj == add_obj)) {
  return add_obj;
  }
  
  stash = SvSTASH(SvRV(base_obj));
  
  MP_TRACE_c(MP_FUNC, "looking for method %s in package `%s'\n", 
 method, SvCLASS(base_obj));
  
  /* XXX: should do this lookup at startup time */
  if ((gv = gv_fetchmethod_autoload(stash, method, FALSE)) && isGV(gv)) {
  int count;
  dSP;
  
  mrg = modperl_module_cfg_new(p);
  memcpy(mrg, tmp,