stas        2003/08/20 16:20:14

  Modified:    src/modules/perl mod_perl.c mod_perl.h modperl_io.c
                        modperl_io.h
               lib/ModPerl Code.pm
               xs/tables/current/ModPerl FunctionTable.pm
               .        Changes
  Added:       src/modules/perl modperl_io_apache.c modperl_io_apache.h
               t/modperl print_utf8.t
               t/response/TestModperl print_utf8.pm
  Log:
  when perl is built with perlio enabled (5.8+) the new PerlIO Apache
  layer is used, so now one can push layers onto STDIN, STDOUT handles
  e.g. binmode(STDOUT, ':utf8');
  
  Revision  Changes    Path
  1.179     +7 -5      modperl-2.0/src/modules/perl/mod_perl.c
  
  Index: mod_perl.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
  retrieving revision 1.178
  retrieving revision 1.179
  diff -u -r1.178 -r1.179
  --- mod_perl.c        19 Aug 2003 05:01:22 -0000      1.178
  +++ mod_perl.c        20 Aug 2003 23:20:14 -0000      1.179
  @@ -238,6 +238,8 @@
   
       modperl_hash_seed_set(aTHX);
   
  +    modperl_io_apache_init(aTHX);
  +
       PL_perl_destruct_level = 2;
   
       MP_boot_data_set(p, s);
  @@ -909,19 +911,19 @@
           modperl_global_request_set(r);
       }
   
  -    h_stdout = modperl_io_tie_stdout(aTHX_ r);
  -    h_stdin  = modperl_io_tie_stdin(aTHX_ r);
  +    h_stdin  = modperl_io_override_stdin(aTHX_ r);
  +    h_stdout = modperl_io_override_stdout(aTHX_ r);
   
       modperl_env_request_tie(aTHX_ r);
   
       retval = modperl_response_handler_run(r, FALSE);
   
  -    modperl_io_handle_untie(aTHX_ h_stdout);
  -    modperl_io_handle_untie(aTHX_ h_stdin);
  -
       modperl_env_request_untie(aTHX_ r);
   
       modperl_perl_global_request_restore(aTHX_ r);
  +
  +    modperl_io_restore_stdin(aTHX_ h_stdin);
  +    modperl_io_restore_stdout(aTHX_ h_stdout);
   
   #ifdef USE_ITHREADS
       if (MpInterpPUTBACK(interp)) {
  
  
  
  1.60      +1 -0      modperl-2.0/src/modules/perl/mod_perl.h
  
  Index: mod_perl.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.h,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- mod_perl.h        24 Apr 2003 01:51:37 -0000      1.59
  +++ mod_perl.h        20 Aug 2003 23:20:14 -0000      1.60
  @@ -59,6 +59,7 @@
   #include "modperl_options.h"
   #include "modperl_directives.h"
   #include "modperl_io.h"
  +#include "modperl_io_apache.h"
   #include "modperl_filter.h"
   #include "modperl_bucket.h"
   #include "modperl_pcw.h"
  
  
  
  1.10      +154 -40   modperl-2.0/src/modules/perl/modperl_io.c
  
  Index: modperl_io.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- modperl_io.c      22 Jan 2003 03:19:43 -0000      1.9
  +++ modperl_io.c      20 Aug 2003 23:20:14 -0000      1.10
  @@ -6,22 +6,6 @@
   #define TIED(handle) \
   modperl_io_handle_tied(aTHX_ handle, "Apache::RequestRec")
   
  -MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle)
  -{
  -#ifdef MP_TRACE
  -    if (mg_find(TIEHANDLE_SV(handle), 'q')) {
  -        MP_TRACE_g(MP_FUNC, "untie *%s(0x%lx), REFCNT=%d\n",
  -                   GvNAME(handle), (unsigned long)handle,
  -                   SvREFCNT(TIEHANDLE_SV(handle)));
  -    }
  -    else {
  -        return;
  -    }
  -#endif
  -
  -    sv_unmagic(TIEHANDLE_SV(handle), 'q');
  -}
  -
   MP_INLINE void modperl_io_handle_tie(pTHX_ GV *handle,
                                        char *classname, void *ptr)
   {
  @@ -38,29 +22,27 @@
                  SvREFCNT(TIEHANDLE_SV(handle)));
   }
   
  -MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname)
  +MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r)
   {
  -    MAGIC *mg;
  -    SV *sv = TIEHANDLE_SV(handle);
  -
  -    if (SvMAGICAL(sv) && (mg = mg_find(sv, 'q'))) {
  -     char *package = HvNAME(SvSTASH((SV*)SvRV(mg->mg_obj)));
  +#if defined(MP_IO_TIE_SFIO)
  +    /* XXX */
  +#else
  +    dHANDLE("STDIN");
   
  -     if (!strEQ(package, classname)) {
  -         MP_TRACE_g(MP_FUNC, "%s tied to %s\n", GvNAME(handle), package);
  -         return TRUE;
  -     }
  +    if (TIED(handle)) {
  +        return handle;
       }
   
  -    return FALSE;
  +    TIEHANDLE(handle, r);
  +
  +    return handle;
  +#endif
   }
   
   MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r)
   {
   #if defined(MP_IO_TIE_SFIO)
       /* XXX */
  -#elif defined(MP_IO_TIE_PERLIO)
  -    /* XXX */
   #else
       dHANDLE("STDOUT");
   
  @@ -76,21 +58,153 @@
   #endif
   }
   
  -MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r)
  +MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname)
   {
  -#if defined(MP_IO_TIE_SFIO)
  -    /* XXX */
  -#elif defined(MP_IO_TIE_PERLIO)
  -    /* XXX */
  -#else
  -    dHANDLE("STDIN");
  +    MAGIC *mg;
  +    SV *sv = TIEHANDLE_SV(handle);
   
  -    if (TIED(handle)) {
  -        return handle;
  +    if (SvMAGICAL(sv) && (mg = mg_find(sv, 'q'))) {
  +     char *package = HvNAME(SvSTASH((SV*)SvRV(mg->mg_obj)));
  +
  +     if (!strEQ(package, classname)) {
  +         MP_TRACE_g(MP_FUNC, "%s tied to %s\n", GvNAME(handle), package);
  +         return TRUE;
  +     }
       }
   
  -    TIEHANDLE(handle, r);
  +    return FALSE;
  +}
   
  -    return handle;
  +MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle)
  +{
  +#ifdef MP_TRACE
  +    if (mg_find(TIEHANDLE_SV(handle), 'q')) {
  +        MP_TRACE_g(MP_FUNC, "untie *%s(0x%lx), REFCNT=%d\n",
  +                   GvNAME(handle), (unsigned long)handle,
  +                   SvREFCNT(TIEHANDLE_SV(handle)));
  +    }
   #endif
  +
  +    sv_unmagic(TIEHANDLE_SV(handle), 'q');
  +}
  +
  +MP_INLINE GV *modperl_io_perlio_override_stdin(pTHX_ request_rec *r)
  +{
  +    dHANDLE("STDIN");
  +    int status;
  +    GV *handle_save = gv_fetchpv("STDIN_SAVED", TRUE, SVt_PVIO);
  +    SV *sv = sv_newmortal();
  +
  +    sv_setref_pv(sv, "Apache::RequestRec", (void*)r);
  +    MP_TRACE_o(MP_FUNC, "start");
  +
  +    /* open my $oldout, ">&STDIN" or die "Can't dup STDIN: $!"; */
  +    status = Perl_do_open(aTHX_ handle_save, ">&STDIN", 8, FALSE, O_RDONLY,
  +                          0, Nullfp);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to dup STDIN: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    /* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
  +     * have file descriptors, so STDOUT must be closed before it can
  +     * be reopened */
  +    Perl_do_close(aTHX_ handle, TRUE); 
  +    status = Perl_do_open9(aTHX_ handle, "<:Apache", 8, FALSE, O_RDONLY,
  +                           0, Nullfp, sv, 1);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to open STDIN: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    MP_TRACE_o(MP_FUNC, "end\n");
  +
  +    return handle_save;
  +}
  +
  +/* XXX: refactor to merge with the previous function */
  +MP_INLINE GV *modperl_io_perlio_override_stdout(pTHX_ request_rec *r)
  +{
  +    dHANDLE("STDOUT");
  +    int status;
  +    GV *handle_save = gv_fetchpv("STDOUT_SAVED", TRUE, SVt_PVIO);
  +    SV *sv = sv_newmortal();
  +
  +    MP_TRACE_o(MP_FUNC, "start");
  +
  +    sv_setref_pv(sv, "Apache::RequestRec", (void*)r);
  +
  +    /* open my $oldout, ">&STDOUT" or die "Can't dup STDOUT: $!"; */
  +    status = Perl_do_open(aTHX_ handle_save, ">&STDOUT", 8, FALSE, O_RDONLY,
  +                          0, Nullfp);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to dup STDOUT: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    /* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
  +     * have file descriptors, so STDOUT must be closed before it can
  +     * be reopened */
  +    Perl_do_close(aTHX_ handle, TRUE); 
  +    status = Perl_do_open9(aTHX_ handle, ">:Apache", 8, FALSE, O_RDONLY,
  +                           0, Nullfp, sv, 1);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to open STDOUT: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    MP_TRACE_o(MP_FUNC, "end\n");
  +
  +    IoFLUSH_off(handle); /* STDOUT's $|=0 */
  +
  +    return handle_save;
  +    
  +}
  +
  +MP_INLINE void modperl_io_perlio_restore_stdin(pTHX_ GV *handle)
  +{
  +    GV *handle_orig = gv_fetchpv("STDIN", FALSE, SVt_PVIO);
  +    int status;
  +
  +    MP_TRACE_o(MP_FUNC, "start");
  +
  +    /* Perl_do_close(aTHX_ handle_orig, FALSE); */
  +
  +    /* open STDIN, ">&STDIN_SAVED" or die "Can't dup STDIN_SAVED: $!"; */
  +    status = Perl_do_open9(aTHX_ handle_orig, "<&", 2, FALSE, O_RDONLY,
  +                           0, Nullfp, (SV*)handle, 1);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to restore STDIN: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    IoFLUSH_off(handle); /* STDIN's $|=0 */
  +
  +    MP_TRACE_o(MP_FUNC, "end\n");
  +}
  +
  +MP_INLINE void modperl_io_perlio_restore_stdout(pTHX_ GV *handle)
  +{ 
  +    GV *handle_orig = gv_fetchpv("STDOUT", FALSE, SVt_PVIO);
  +    int status;
  +
  +    MP_TRACE_o(MP_FUNC, "start");
  +
  +    /* Perl_do_close(aTHX_ handle_orig, FALSE); */
  +
  +    /* open STDOUT, ">&STDOUT_SAVED" or die "Can't dup STDOUT_SAVED: $!"; */
  +    status = Perl_do_open9(aTHX_ handle_orig, ">&", 2, FALSE, O_RDONLY,
  +                           0, Nullfp, (SV*)handle, 1);
  +    if (status == 0) {
  +        STRLEN n_a;
  +        Perl_croak(aTHX_ "Failed to restore STDOUT: %s",
  +                   SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
  +    }
  +
  +    MP_TRACE_o(MP_FUNC, "end\n");
   }
  
  
  
  1.3       +28 -4     modperl-2.0/src/modules/perl/modperl_io.h
  
  Index: modperl_io.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- modperl_io.h      22 Jan 2003 03:19:43 -0000      1.2
  +++ modperl_io.h      20 Aug 2003 23:20:14 -0000      1.3
  @@ -1,6 +1,8 @@
   #ifndef MODPERL_IO_H
   #define MODPERL_IO_H
   
  +#include "modperl_io_apache.h"
  +
   /*
    * bleedperl change #11639 switch tied handle magic
    * from living in the gv to the GvIOp(gv), so we have to deal
  @@ -23,15 +25,37 @@
   #define IoFLUSH(gv) \
   (IoFLAGS(GvIOp((gv))) & IOf_FLUSH)
   
  -MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle);
  -
   MP_INLINE void modperl_io_handle_tie(pTHX_ GV *handle,
                                        char *classname, void *ptr);
  +MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r);
  +
  +MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r);
   
   MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname);
   
  -MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r);
  +MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle);
  +
  +MP_INLINE GV *modperl_io_perlio_override_stdin(pTHX_ request_rec *r);
  +
  +MP_INLINE GV *modperl_io_perlio_override_stdout(pTHX_ request_rec *r);
  +
  +MP_INLINE void modperl_io_perlio_restore_stdin(pTHX_ GV *handle);
  +
  +MP_INLINE void modperl_io_perlio_restore_stdout(pTHX_ GV *handle);
  +
  +#if defined(MP_IO_TIE_SFIO)
  +    /* XXX */
  +#elif defined(MP_IO_TIE_PERLIO)
  +#define modperl_io_override_stdin  modperl_io_perlio_override_stdin  
  +#define modperl_io_override_stdout modperl_io_perlio_override_stdout  
  +#define modperl_io_restore_stdin   modperl_io_perlio_restore_stdin  
  +#define modperl_io_restore_stdout  modperl_io_perlio_restore_stdout  
  +#else
  +#define modperl_io_override_stdin  modperl_io_tie_stdin  
  +#define modperl_io_override_stdout modperl_io_tie_stdout  
  +#define modperl_io_restore_stdin   modperl_io_handle_untie  
  +#define modperl_io_restore_stdout  modperl_io_handle_untie  
  +#endif
   
  -MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r);
   
   #endif /* MODPERL_IO_H */
  
  
  
  1.1                  modperl-2.0/src/modules/perl/modperl_io_apache.c
  
  Index: modperl_io_apache.c
  ===================================================================
  #include "mod_perl.h"
  
  #ifdef MP_IO_TIE_PERLIO
  
  /***************************
   * The PerlIO Apache layer *
   ***************************/
  
  /* PerlIO ":Apache" layer is used to use the Apache callbacks to read
   * from STDIN and write to STDOUT. The PerlIO API is documented in
   * perliol.pod */
  
  /*
   * XXX: Since we cannot snoop on the internal apr_file_io buffer
   * currently the IO is not buffered on the Perl side so every read
   * requests a char at a time, which is slow. Consider copying the
   * relevant code from PerlIOBuf to implement our own buffer, similar
   * to what PerlIOBuf does or push :perlio layer on top of this layer
   */
  
  typedef struct {
      struct _PerlIO base;
      request_rec *r;
  } PerlIOApache;
  
  /* _open just allocates the layer, _pushed does the real job of
   * filling the data in */
  static PerlIO *
  PerlIOApache_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n,
                  const char *mode, int fd, int imode, int perm,
                  PerlIO *f, int narg, SV **args)
  {
      if (!f) {
          f = PerlIO_allocate(aTHX);
      }
      if ( (f = PerlIO_push(aTHX_ f, self, mode, args[0])) ) {
          PerlIOBase(f)->flags |= PERLIO_F_OPEN;
      }
  
      MP_TRACE_o(MP_FUNC, "mode %s", mode);
  
      return f;
  }
  
  /* this callback is used by pushed() and binmode() to add the layer */
  static IV
  PerlIOApache_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg,
                    PerlIO_funcs *tab)
  {
      IV code;
      PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
  
      if (arg) {
          st->r = modperl_sv2request_rec(aTHX_ arg);
      }
      else {
          Perl_croak(aTHX_ "$r wasn't passed");
          /* XXX: try to get Apache->request? */
      }
      
      /* this method also sets the right flags according to the
       * 'mode' */
      code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
      
      MP_TRACE_o(MP_FUNC, "done");
      
      return code;
  }
  
  static IV
  PerlIOApache_fileno(pTHX_ PerlIO *f)
  {
      /* XXX: we could return STDIN => 0, STDOUT => 2, but that wouldn't
       * be correct, as the IO goes through the socket, may be we should
       * return the filedescriptor of the socket? 
       *
       * -1 in this case indicates that the layer cannot provide fileno
       */
      MP_TRACE_o(MP_FUNC, "did nothing");
      return -1;
  }
  
  
  /* XXX: FIXME */
  static MP_INLINE
  apr_status_t mpxs_setup_client_block(request_rec *r)
  {
      if (!r->read_length) {
          apr_status_t rc;
  
          /* only do this once per-request */
          if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
              ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                           "mod_perl: ap_setup_client_block failed: %d", rc);
              return rc;
          }
      }
  
      return APR_SUCCESS;
  }
  
  #define mpxs_should_client_block(r) \
      (r->read_length || ap_should_client_block(r))
  
  static SSize_t
  PerlIOApache_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
  {
      PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
      request_rec *r = st->r;
      long total = 0;
      int rc;
  
      if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD) ||
          PerlIOBase(f)->flags & (PERLIO_F_EOF|PERLIO_F_ERROR)) {
        return 0;
      }
      
      if ((rc = mpxs_setup_client_block(r)) != APR_SUCCESS) {
          return 0;
      }
  
      if (mpxs_should_client_block(r)) {
          total = ap_get_client_block(r, vbuf, count);
  
          MP_TRACE_o(MP_FUNC, "wanted %db, read %db [%s]",
                     count, total, (char *)vbuf);
  
          if (total < 0) {
              /*
               * XXX: as stated in ap_get_client_block, the real
               * error gets lots, so we only know that there was one
               */
              ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                           "mod_perl: $r->read failed to read");
          }
      }
  
      return total;
  }
  
  static SSize_t
  PerlIOApache_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
  {
      PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
      modperl_config_req_t *rcfg = modperl_config_req_get(st->r);
      apr_size_t bytes = 0;
      apr_status_t rv;
  
      if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
        return 0;
      }
      
      MP_CHECK_WBUCKET_INIT("print");
  
      MP_TRACE_o(MP_FUNC, "%d bytes [%s]", count, (char *)vbuf);
          
      rv = modperl_wbucket_write(aTHX_ rcfg->wbucket, vbuf, &count);
      if (rv != APR_SUCCESS) {
          Perl_croak(aTHX_ modperl_apr_strerror(rv)); 
      }
      bytes += count;
      
      return (SSize_t) bytes;
  }
  
  static IV
  PerlIOApache_flush(pTHX_ PerlIO *f)
  {
      PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
      modperl_config_req_t *rcfg = modperl_config_req_get(st->r);
  
      /* no flush on readonly io handle */
      if (! (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) ) {
          return -1;
      }
  
      MP_CHECK_WBUCKET_INIT("flush");
  
      MP_TRACE_o(MP_FUNC, "%d bytes [%s]", rcfg->wbucket->outcnt,
                 apr_pstrmemdup(rcfg->wbucket->pool, rcfg->wbucket->outbuf,
                                rcfg->wbucket->outcnt));
  
      MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket, FALSE));
  
      return 0;
  }
  
  /* 5.8.0 doesn't export PerlIOBase_noop_fail, so we duplicate it here */
  static IV PerlIOApache_noop_fail(pTHX_ PerlIO *f)
  {
      return -1;
  }
  
  static IV
  PerlIOApache_close(pTHX_ PerlIO *f)
  {
      /* XXX: just temp for tracing */
      MP_TRACE_o(MP_FUNC, "done");
      return PerlIOBase_close(aTHX_ f);
  }
  
  static IV
  PerlIOApache_popped(pTHX_ PerlIO *f)
  {
      /* XXX: just temp for tracing */
      MP_TRACE_o(MP_FUNC, "done");
      return PerlIOBase_popped(aTHX_ f);
  }
  
  
  static PerlIO_funcs PerlIO_Apache = {
      sizeof(PerlIO_funcs),
      "Apache",
      sizeof(PerlIOApache),
      PERLIO_K_MULTIARG,
      PerlIOApache_pushed,
      PerlIOApache_popped,
      PerlIOApache_open,
      PerlIOBase_binmode,
      NULL,                       /* no getarg needed */
      PerlIOApache_fileno,
      PerlIOBase_dup,
      PerlIOApache_read,
      PerlIOBase_unread,
      PerlIOApache_write,
      NULL,                       /* can't seek on STD{IN|OUT}, fail on call*/
      NULL,                       /* can't tell on STD{IN|OUT}, fail on call*/
      PerlIOApache_close,
      PerlIOApache_flush,        
      PerlIOApache_noop_fail,     /* fill */
      PerlIOBase_eof,
      PerlIOBase_error,
      PerlIOBase_clearerr,
      PerlIOBase_setlinebuf,
      NULL,                       /* get_base */
      NULL,                       /* get_bufsiz */
      NULL,                       /* get_ptr */
      NULL,                       /* get_cnt */
      NULL,                       /* set_ptrcnt */
  };
  
  /* ***** End of PerlIOApache tab ***** */
  
  MP_INLINE void modperl_io_apache_init(pTHX)
  {
      PerlIO_define_layer(aTHX_ &PerlIO_Apache);
  }
  
  #endif /* defined MP_IO_TIE_PERLIO */
  
  
  
  
  
  
  
  
  1.1                  modperl-2.0/src/modules/perl/modperl_io_apache.h
  
  Index: modperl_io_apache.h
  ===================================================================
  #ifndef MODPERL_IO_APACHE_H
  #define MODPERL_IO_APACHE_H
  
  #ifdef PERLIO_LAYERS
  
  #include "perliol.h"
  /* XXX: should this be a Makefile.PL config option? */
  #define MP_IO_TIE_PERLIO
  
  #include "apr_portable.h"
  #include "apr_file_io.h"
  #include "apr_errno.h"
  
  typedef enum {
      MODPERL_IO_APACHE_HOOK_READ,
      MODPERL_IO_APACHE_HOOK_WRITE
  } modperl_io_apache_hook_e;
  
  #define PERLIO_Apache_DEBUG
  
  MP_INLINE void modperl_io_apache_init(pTHX);
  
  #else /* #ifdef PERLIO_LAYERS */
  
  #define modperl_io_apache_init(pTHX)
  
  #endif /* #ifdef PERLIO_LAYERS */
      
  #endif /* MODPERL_IO_APACHE_H */
  
  
  
  1.1                  modperl-2.0/t/modperl/print_utf8.t
  
  Index: print_utf8.t
  ===================================================================
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::Test;
  use Apache::TestRequest;
  use Apache::TestUtil;
  
  # utf encode/decode was added only in 5.8.0
  # currently binmode is only available with perlio
  plan tests => 1, have have_min_perl_version(5.008), have_perl('perlio');
  
  #use bytes;
  #use utf8;
  
  my $location = "/TestModperl__print_utf8";
  
  my $received = GET_BODY_ASSERT $location;
  
  # the external stream already include wide-chars, but perl doesn't
  # know about it
  utf8::decode($received);
  
  binmode(STDOUT, ':utf8');
  
  
  my $expected = "Hello Ayhan \x{263A} perlio rules!";
  
  print "$expected\n";
  print "$received\n";
  
  #ok $expected eq $received;
  
  ok t_cmp($expected, $received, 'UTF8 encoding');
  
  
  
  
  1.1                  modperl-2.0/t/response/TestModperl/print_utf8.pm
  
  Index: print_utf8.pm
  ===================================================================
  package TestModperl::print_utf8;
  
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::RequestIO ();
  use Apache::RequestRec ();
  
  use Apache::Const -compile => 'OK';
  
  use utf8;
  
  sub handler {
      my $r = shift;
  
      $r->content_type('text/plain; charset=UTF-8');
  
      #Apache::RequestRec::BINMODE
      binmode(STDOUT, ':utf8');
  
      # must be non-$r->print(), so we go through the tied STDOUT
      print "Hello Ayhan \x{263A} perlio rules!";
  
      Apache::OK;
  }
  
  1;
  __DATA__
  # must test against a tied STDOUT
  SetHandler perl-script
  
  
  
  1.104     +2 -2      modperl-2.0/lib/ModPerl/Code.pm
  
  Index: Code.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v
  retrieving revision 1.103
  retrieving revision 1.104
  diff -u -r1.103 -r1.104
  --- Code.pm   19 Aug 2003 07:26:47 -0000      1.103
  +++ Code.pm   20 Aug 2003 23:20:14 -0000      1.104
  @@ -606,8 +606,8 @@
   );
   
   my @c_src_names = qw(interp tipool log config cmd options callback handler
  -                     gtop util io filter bucket mgv pcw global env cgi
  -                     perl perl_global perl_pp sys module svptr_table
  +                     gtop util io io_apache filter bucket mgv pcw global env
  +                     cgi perl perl_global perl_pp sys module svptr_table
                        const constants apache_compat);
   my @h_src_names = qw(perl_unembed);
   my @g_c_names = map { "modperl_$_" } qw(hooks directives flags xsinit);
  
  
  
  1.119     +81 -0     modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm
  
  Index: FunctionTable.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
  retrieving revision 1.118
  retrieving revision 1.119
  diff -u -r1.118 -r1.119
  --- FunctionTable.pm  11 Aug 2003 20:34:22 -0000      1.118
  +++ FunctionTable.pm  20 Aug 2003 23:20:14 -0000      1.119
  @@ -2783,6 +2783,40 @@
       ]
     },
     {
  +    'return_type' => 'void',
  +    'name' => 'modperl_io_perlio_restore_stdin',
  +    'attr' => [
  +      '__inline__'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
  +      {
  +        'type' => 'GV *',
  +        'name' => 'handle'
  +      }
  +    ]
  +  },
  +  {
  +    'return_type' => 'void',
  +    'name' => 'modperl_io_perlio_restore_stdout',
  +    'attr' => [
  +      '__inline__'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
  +      {
  +        'type' => 'GV *',
  +        'name' => 'handle'
  +      }
  +    ]
  +  },
  +  {
       'return_type' => 'GV *',
       'name' => 'modperl_io_tie_stdin',
       'attr' => [
  @@ -2814,6 +2848,53 @@
           'type' => 'request_rec *',
           'name' => 'r'
         }
  +    ]
  +  },
  +  {
  +    'return_type' => 'GV *',
  +    'name' => 'modperl_io_perlio_override_stdin',
  +    'attr' => [
  +      '__inline__'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
  +      {
  +        'type' => 'request_rec *',
  +        'name' => 'r'
  +      }
  +    ]
  +  },
  +  {
  +    'return_type' => 'GV *',
  +    'name' => 'modperl_io_perlio_override_stdout',
  +    'attr' => [
  +      '__inline__'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
  +      {
  +        'type' => 'request_rec *',
  +        'name' => 'r'
  +      }
  +    ]
  +  },
  +  {
  +    'return_type' => 'void',
  +    'name' => 'modperl_io_apache_init',
  +    'attr' => [
  +      '__inline__'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
       ]
     },
     {
  
  
  
  1.209     +4 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.208
  retrieving revision 1.209
  diff -u -r1.208 -r1.209
  --- Changes   11 Aug 2003 20:34:56 -0000      1.208
  +++ Changes   20 Aug 2003 23:20:14 -0000      1.209
  @@ -12,6 +12,10 @@
   
   =item 1.99_10-dev
   
  +when perl is built with perlio enabled (5.8+) the new PerlIO Apache
  +layer is used, so now one can push layers onto STDIN, STDOUT handles
  +e.g. binmode(STDOUT, ':utf8'); [Stas]
  +
   alter stacked handler interface so that mod_perl follows Apache 
   as closely as possible with respect to VOID/RUN_FIRST/RUN_ALL
   handler types.  now, for phases where OK ends the Apache
  
  
  

Reply via email to