call pp_glob() even when its being skipped
authorDavid Mitchell <davem@iabyn.com>
Fri, 31 Dec 2010 18:55:36 +0000 (18:55 +0000)
committerDavid Mitchell <davem@iabyn.com>
Sun, 2 Jan 2011 20:00:27 +0000 (20:00 +0000)
Currently when an external Perl glob function is used (which is most of
the time), the OP_GLOB op is removed and replaced with the pair:
    GV("CORE::GLOBAL::glob"), ENTERSUB.

This commit re-adds the OP_GLOB to the op tree, but with OPf_SPECIAL set;
and pp_glob() is updated to just return if OPf_SPECIAL is set.

Thus there's no change in outward functionality with this commit. However,
by always calling pp_glob(), it will allow us (in the next commit) to
handle iterator overloading consistently, regardless of whether the
internal globbing function is used or not.

op.c
op.h
pp_sys.c

diff --git a/op.c b/op.c
index ba9e2e2..a1b11a2 100644 (file)
--- a/op.c
+++ b/op.c
@@ -7663,20 +7663,30 @@ Perl_ck_glob(pTHX_ OP *o)
     }
 #endif /* PERL_EXTERNAL_GLOB */
 
+    assert(!(o->op_flags & OPf_SPECIAL));
     if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) {
+       /* convert
+        *     glob
+        *       \ null - const(wildcard)
+        * into
+        *     null
+        *       \ enter
+        *            \ list
+        *                 \ mark - glob - rv2cv
+        *                             |        \ gv(CORE::GLOBAL::glob)
+        *                             |
+        *                              \ null - const(wildcard) - const(ix)
+        */
+       o->op_flags |= OPf_SPECIAL;
        op_append_elem(OP_GLOB, o,
                    newSVOP(OP_CONST, 0, newSViv(PL_glob_index++)));
-       o->op_type = OP_LIST;
-       o->op_ppaddr = PL_ppaddr[OP_LIST];
-       cLISTOPo->op_first->op_type = OP_PUSHMARK;
-       cLISTOPo->op_first->op_ppaddr = PL_ppaddr[OP_PUSHMARK];
-       cLISTOPo->op_first->op_targ = 0;
+       o = newLISTOP(OP_LIST, 0, o, NULL);
        o = newUNOP(OP_ENTERSUB, OPf_STACKED,
                    op_append_elem(OP_LIST, o,
                                scalar(newUNOP(OP_RV2CV, 0,
                                               newGVOP(OP_GV, 0, gv)))));
        o = newUNOP(OP_NULL, 0, ck_subr(o));
-       o->op_targ = OP_GLOB;           /* hint at what it used to be */
+       o->op_targ = OP_GLOB; /* hint at what it used to be: eg in newWHILEOP */
        return o;
     }
     gv = newGVgen("main");
diff --git a/op.h b/op.h
index a55bb1e..4d6229b 100644 (file)
--- a/op.h
+++ b/op.h
@@ -146,6 +146,7 @@ Deprecated.  Use C<GIMME_V> instead.
                                    that was optimised away, so it should
                                    not be bound via =~ */
                                /*  On OP_CONST, from a constant CV */
+                               /*  On OP_GLOB, use Perl glob function */
 
 /* old names; don't use in new code, but don't break them, either */
 #define OPf_LIST       OPf_WANT_LIST
index 332abbb..7144bc3 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -358,6 +358,16 @@ PP(pp_glob)
 {
     dVAR;
     OP *result;
+
+    if (PL_op->op_flags & OPf_SPECIAL) {
+       /* call Perl-level glob function instead. Stack args are:
+        * MARK, wildcard, csh_glob context index
+        * and following OPs should be: gv(CORE::GLOBAL::glob), entersub
+        * */
+       return NORMAL;
+    }
+    /* stack args are: wildcard, gv(_GEN_n) */
+
     tryAMAGICunTARGET(iter_amg, -1);
 
     /* Note that we only ever get here if File::Glob fails to load