This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
If the downstream caller wants block mode, and we're in line mode,
[perl5.git] / pp_ctl.c
index 5288c66..7ea62e5 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3067,7 +3067,6 @@ PP(pp_require)
     const I32 gimme = GIMME_V;
     int filter_has_file = 0;
     PerlIO *tryrsfp = NULL;
-    GV *filter_child_proc = NULL;
     SV *filter_state = NULL;
     SV *filter_sub = NULL;
     SV *hook_sv = NULL;
@@ -3186,23 +3185,11 @@ PP(pp_require)
 
                            if (io) {
                                tryrsfp = IoIFP(io);
-                               if (IoTYPE(io) == IoTYPE_PIPE) {
-                                   /* reading from a child process doesn't
-                                      nest -- when returning from reading
-                                      the inner module, the outer one is
-                                      unreadable (closed?)  I've tried to
-                                      save the gv to manage the lifespan of
-                                      the pipe, but this didn't help. XXX */
-                                   filter_child_proc = (GV *)arg;
-                                   SvREFCNT_inc_simple_void(filter_child_proc);
-                               }
-                               else {
-                                   if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
-                                       PerlIO_close(IoOFP(io));
-                                   }
-                                   IoIFP(io) = NULL;
-                                   IoOFP(io) = NULL;
+                               if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
+                                   PerlIO_close(IoOFP(io));
                                }
+                               IoIFP(io) = NULL;
+                               IoOFP(io) = NULL;
                            }
 
                            if (i < count) {
@@ -3220,7 +3207,8 @@ PP(pp_require)
                            }
 
                            if (!tryrsfp) {
-                               tryrsfp = PerlIO_open("/dev/null", PERL_SCRIPT_MODE);
+                               tryrsfp = PerlIO_open(BIT_BUCKET,
+                                                     PERL_SCRIPT_MODE);
                            }
                        }
                        SP--;
@@ -3236,10 +3224,6 @@ PP(pp_require)
                    }
 
                    filter_has_file = 0;
-                   if (filter_child_proc) {
-                       SvREFCNT_dec(filter_child_proc);
-                       filter_child_proc = NULL;
-                   }
                    if (filter_state) {
                        SvREFCNT_dec(filter_state);
                        filter_state = NULL;
@@ -3363,7 +3347,7 @@ PP(pp_require)
     PL_rsfp = tryrsfp;
     SAVEHINTS();
     PL_hints = 0;
-    SAVECOPWARNINGS(&PL_compiling);
+    SAVECOMPILEWARNINGS();
     if (PL_dowarn & G_WARN_ALL_ON)
         PL_compiling.cop_warnings = pWARN_ALL ;
     else if (PL_dowarn & G_WARN_ALL_OFF)
@@ -3377,10 +3361,9 @@ PP(pp_require)
     SAVESPTR(PL_compiling.cop_io);
     PL_compiling.cop_io = NULL;
 
-    if (filter_sub || filter_child_proc) {
+    if (filter_sub) {
        SV * const datasv = filter_add(S_run_user_filter, NULL);
        IoLINES(datasv) = filter_has_file;
-       IoFMT_GV(datasv) = (GV *)filter_child_proc;
        IoTOP_GV(datasv) = (GV *)filter_state;
        IoBOTTOM_GV(datasv) = (GV *)filter_sub;
     }
@@ -3463,7 +3446,7 @@ PP(pp_entereval)
     PL_hints = PL_op->op_targ;
     if (saved_hh)
        GvHV(PL_hintgv) = saved_hh;
-    SAVECOPWARNINGS(&PL_compiling);
+    SAVECOMPILEWARNINGS();
     PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
     SAVESPTR(PL_compiling.cop_io);
     if (specialCopIO(PL_curcop->cop_io))
@@ -4533,18 +4516,46 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
     dVAR;
     SV * const datasv = FILTER_DATA(idx);
     const int filter_has_file = IoLINES(datasv);
-    GV * const filter_child_proc = (GV *)IoFMT_GV(datasv);
     SV * const filter_state = (SV *)IoTOP_GV(datasv);
     SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv);
     int len = 0;
-
+    /* Filter API says that the filter appends to the contents of the buffer.
+       Usually the buffer is "", so the details don't matter. But if it's not,
+       then clearly what it contains is already filtered by this filter, so we
+       don't want to pass it in a second time.
+       I'm going to use a mortal in case the upstream filter croaks.  */
+    SV *const upstream
+       = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv))
+       ? sv_newmortal() : buf_sv;
+
+    SvUPGRADE(upstream, SVt_PV);
     /* I was having segfault trouble under Linux 2.2.5 after a
        parse error occured.  (Had to hack around it with a test
        for PL_error_count == 0.)  Solaris doesn't segfault --
        not sure where the trouble is yet.  XXX */
 
+    if (maxlen && IoFMT_GV(datasv)) {
+       SV *const cache = (SV *)IoFMT_GV(datasv);
+       if (SvOK(cache)) {
+           STRLEN cache_len;
+           const char *cache_p = SvPV(cache, cache_len);
+           /* Running in block mode and we have some cached data already.  */
+           if (cache_len >= maxlen) {
+               /* In fact, so much data we don't even need to call
+                  filter_read.  */
+               sv_catpvn(buf_sv, cache_p, maxlen);
+               sv_chop(cache, cache_p + maxlen);
+               /* Definately not EOF  */
+               return 1;
+           }
+           sv_catsv(buf_sv, cache);
+           maxlen -= cache_len;
+           SvOK_off(cache);
+       }
+    }
+       
     if (filter_has_file) {
-       len = FILTER_READ(idx+1, buf_sv, maxlen);
+       len = FILTER_READ(idx+1, upstream, maxlen);
     }
 
     if (filter_sub && len >= 0) {
@@ -4556,7 +4567,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        SAVETMPS;
        EXTEND(SP, 2);
 
-       DEFSV = buf_sv;
+       DEFSV = upstream;
        PUSHMARK(SP);
        PUSHs(sv_2mortal(newSViv(maxlen)));
        if (filter_state) {
@@ -4578,12 +4589,41 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        LEAVE;
     }
 
+    if (maxlen) {
+       /* Running in block mode.  */
+       STRLEN got_len;
+       const char *got_p = SvPV(upstream, got_len);
+
+       if (got_len > maxlen) {
+           /* Oh. Too long. Stuff some in our cache.  */
+           SV *cache = (SV *)IoFMT_GV(datasv);
+
+           if (!cache) {
+               IoFMT_GV(datasv) = (GV*) (cache = newSV(got_len - maxlen));
+           } else if (SvOK(cache)) {
+               /* Cache should be empty.  */
+               assert(!SvCUR(cache));
+           }
+
+           sv_setpvn(cache, got_p + maxlen, got_len - maxlen);
+           /* If you ask for block mode, you may well split UTF-8 characters.
+              "If it breaks, you get to keep both parts"
+              (Your code is broken if you  don't put them back together again
+              before something notices.) */
+           if (SvUTF8(upstream)) {
+               SvUTF8_on(cache);
+           }
+           SvCUR_set(upstream, maxlen);
+       }
+    }
+
+    if (upstream != buf_sv) {
+       sv_catsv(buf_sv, upstream);
+    }
+
     if (len <= 0) {
        IoLINES(datasv) = 0;
-       if (filter_child_proc) {
-           SvREFCNT_dec(filter_child_proc);
-           IoFMT_GV(datasv) = NULL;
-       }
+       SvREFCNT_dec(IoFMT_GV(datasv));
        if (filter_state) {
            SvREFCNT_dec(filter_state);
            IoTOP_GV(datasv) = NULL;
@@ -4594,7 +4634,6 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        }
        filter_del(S_run_user_filter);
     }
-
     return len;
 }