summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-04-16 15:04:36 +0000
committerNicholas Clark <nick@ccl4.org>2006-04-16 15:04:36 +0000
commit34113e50dc4bebd1212d8cbfbf09a86a40b7a699 (patch)
treed3146dcef80adf0f0d6549f7abfb313b0245e0b1 /pp_ctl.c
parente655f126937737a64491ca38bb28ba229f1eb788 (diff)
downloadperl-34113e50dc4bebd1212d8cbfbf09a86a40b7a699.tar.gz
A scalar reference returned from a coderef in @INC is treated as the
initial "content" of the file. When it is exhausted input is taken from a real file handle, or a generator sub, if either exists. p4raw-id: //depot/perl@27849
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 43db9de319..d783e1f837 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3067,6 +3067,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 +3175,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 +3216,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 +3235,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 +3376,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 */
@@ -4519,15 +4535,11 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
SV * const filter_state = (SV *)IoTOP_GV(datasv);
SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv);
int status = 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 *upstream;
STRLEN got_len;
const char *got_p;
const char *prune_from = NULL;
+ bool read_from_cache = FALSE;
/* I was having segfault trouble under Linux 2.2.5 after a
parse error occured. (Had to hack around it with a test
@@ -4567,9 +4579,15 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int 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);
@@ -4578,8 +4596,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
status = FILTER_READ(idx+1, upstream, 0);
}
- assert(filter_sub);
- if (status >= 0) {
+ if (filter_sub && status >= 0) {
dSP;
int count;
@@ -4650,7 +4667,11 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
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);
}
@@ -4667,6 +4688,12 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
}
filter_del(S_run_user_filter);
}
+ 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;
}