Changes to perlfaq8 "How do I find out if I'm running interactively
[p5sagit/p5-mst-13.2.git] / pp_ctl.c
index 7ea62e5..acefb21 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -113,7 +113,7 @@ PP(pp_regcomp)
        tmpstr = POPs;
 
     if (SvROK(tmpstr)) {
-       SV *sv = SvRV(tmpstr);
+       SV * const sv = SvRV(tmpstr);
        if(SvMAGICAL(sv))
            mg = mg_find(sv, PERL_MAGIC_qr);
     }
@@ -125,14 +125,14 @@ PP(pp_regcomp)
     else {
        STRLEN len;
        const char *t = SvPV_const(tmpstr, len);
+       regexp * const re = PM_GETRE(pm);
 
        /* Check against the last compiled regexp. */
-       if (!PM_GETRE(pm) || !PM_GETRE(pm)->precomp ||
-           PM_GETRE(pm)->prelen != (I32)len ||
-           memNE(PM_GETRE(pm)->precomp, t, len))
+       if (!re || !re->precomp || re->prelen != (I32)len ||
+           memNE(re->precomp, t, len))
        {
-           if (PM_GETRE(pm)) {
-               ReREFCNT_dec(PM_GETRE(pm));
+           if (re) {
+               ReREFCNT_dec(re);
                PM_SETRE(pm, NULL);     /* crucial if regcomp aborts */
            }
            if (PL_op->op_flags & OPf_SPECIAL)
@@ -2898,6 +2898,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     /* set up a scratch pad */
 
     CvPADLIST(PL_compcv) = pad_new(padnew_SAVE);
+    PL_op = NULL; /* avoid PL_op and PL_curpad referring to different CVs */
 
 
     if (!PL_madskills)
@@ -3067,6 +3068,7 @@ PP(pp_require)
     const I32 gimme = GIMME_V;
     int filter_has_file = 0;
     PerlIO *tryrsfp = NULL;
+    SV *filter_cache = NULL;
     SV *filter_state = NULL;
     SV *filter_sub = NULL;
     SV *hook_sv = NULL;
@@ -3174,6 +3176,16 @@ PP(pp_require)
                        SP -= count - 1;
                        arg = SP[i++];
 
+                       if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV)
+                           && !isGV_with_GP(SvRV(arg))) {
+                           filter_cache = SvRV(arg);
+                           SvREFCNT_inc_void_NN(filter_cache);
+
+                           if (i < count) {
+                               arg = SP[i++];
+                           }
+                       }
+
                        if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVGV) {
                            arg = SvRV(arg);
                        }
@@ -3205,11 +3217,11 @@ PP(pp_require)
                                filter_state = SP[i];
                                SvREFCNT_inc_simple_void(filter_state);
                            }
+                       }
 
-                           if (!tryrsfp) {
-                               tryrsfp = PerlIO_open(BIT_BUCKET,
-                                                     PERL_SCRIPT_MODE);
-                           }
+                       if (!tryrsfp && (filter_cache || filter_sub)) {
+                           tryrsfp = PerlIO_open(BIT_BUCKET,
+                                                 PERL_SCRIPT_MODE);
                        }
                        SP--;
                    }
@@ -3224,6 +3236,10 @@ PP(pp_require)
                    }
 
                    filter_has_file = 0;
+                   if (filter_cache) {
+                       SvREFCNT_dec(filter_cache);
+                       filter_cache = NULL;
+                   }
                    if (filter_state) {
                        SvREFCNT_dec(filter_state);
                        filter_state = NULL;
@@ -3361,11 +3377,12 @@ PP(pp_require)
     SAVESPTR(PL_compiling.cop_io);
     PL_compiling.cop_io = NULL;
 
-    if (filter_sub) {
+    if (filter_sub || filter_cache) {
        SV * const datasv = filter_add(S_run_user_filter, NULL);
        IoLINES(datasv) = filter_has_file;
        IoTOP_GV(datasv) = (GV *)filter_state;
        IoBOTTOM_GV(datasv) = (GV *)filter_sub;
+       IoFMT_GV(datasv) = (GV *)filter_cache;
     }
 
     /* switch to eval mode */
@@ -4518,47 +4535,69 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
     const int filter_has_file = IoLINES(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;
+    int status = 0;
+    SV *upstream;
+    STRLEN got_len;
+    const char *got_p;
+    const char *prune_from = NULL;
+    bool read_from_cache = FALSE;
 
-    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)) {
+    if (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);
+           STRLEN take = 0;
+
+           if (maxlen) {
+               /* 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.  */
+                   take = maxlen;
+               }
+           } else {
+               const char *const first_nl = memchr(cache_p, '\n', cache_len);
+               if (first_nl) {
+                   take = first_nl + 1 - cache_p;
+               }
+           }
+           if (take) {
+               sv_catpvn(buf_sv, cache_p, take);
+               sv_chop(cache, cache_p + take);
                /* Definately not EOF  */
                return 1;
            }
+
            sv_catsv(buf_sv, cache);
-           maxlen -= cache_len;
+           if (maxlen) {
+               maxlen -= cache_len;
+           }
            SvOK_off(cache);
+           read_from_cache = TRUE;
        }
     }
+
+    /* 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.  */
+    upstream = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv))
+       ? sv_newmortal() : buf_sv;
+    SvUPGRADE(upstream, SVt_PV);
        
     if (filter_has_file) {
-       len = FILTER_READ(idx+1, upstream, maxlen);
+       status = FILTER_READ(idx+1, upstream, 0);
     }
 
-    if (filter_sub && len >= 0) {
+    if (filter_sub && status >= 0) {
        dSP;
        int count;
 
@@ -4569,7 +4608,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 
        DEFSV = upstream;
        PUSHMARK(SP);
-       PUSHs(sv_2mortal(newSViv(maxlen)));
+       PUSHs(sv_2mortal(newSViv(0)));
        if (filter_state) {
            PUSHs(filter_state);
        }
@@ -4580,7 +4619,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        if (count > 0) {
            SV *out = POPs;
            if (SvOK(out)) {
-               len = SvIV(out);
+               status = SvIV(out);
            }
        }
 
@@ -4589,39 +4628,55 @@ 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));
+    if(SvOK(upstream)) {
+       got_p = SvPV(upstream, got_len);
+       if (maxlen) {
+           if (got_len > maxlen) {
+               prune_from = got_p + maxlen;
            }
-
-           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);
+       } else {
+           const char *const first_nl = memchr(got_p, '\n', got_len);
+           if (first_nl && first_nl + 1 < got_p + got_len) {
+               /* There's a second line here... */
+               prune_from = first_nl + 1;
            }
-           SvCUR_set(upstream, maxlen);
        }
     }
+    if (prune_from) {
+       /* Oh. Too long. Stuff some in our cache.  */
+       STRLEN cached_len = got_p + got_len - prune_from;
+       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, prune_from, cached_len);
+       /* 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, got_len - cached_len);
+       /* Can't yet be EOF  */
+       if (status == 0)
+           status = 1;
+    }
 
-    if (upstream != buf_sv) {
+    /* If they are at EOF but buf_sv has something in it, then they may never
+       have touched the SV upstream, so it may be undefined.  If we naively
+       concatenate it then we get a warning about use of uninitialised value.
+    */
+    if (upstream != buf_sv && (SvOK(upstream) || SvGMAGICAL(upstream))) {
        sv_catsv(buf_sv, upstream);
     }
 
-    if (len <= 0) {
+    if (status <= 0) {
        IoLINES(datasv) = 0;
        SvREFCNT_dec(IoFMT_GV(datasv));
        if (filter_state) {
@@ -4634,7 +4689,13 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        }
        filter_del(S_run_user_filter);
     }
-    return len;
+    if (status == 0 && read_from_cache) {
+       /* If we read some data from the cache (and by getting here it implies
+          that we emptied the cache) then we aren't yet at EOF, and mustn't
+          report that to our caller.  */
+       return 1;
+    }
+    return status;
 }
 
 /* perhaps someone can come up with a better name for