AMdnoP |int |Perl_signbit |NV f
#endif
+XEMop |void |emulate_cop_io |NN const COP *const c|NN SV *const sv
+
END_EXTERN_C
/*
* ex: set ts=8 sts=4 sw=4 noet:
#endif
#if !defined(HAS_SIGNBIT)
#endif
+#if defined(PERL_CORE) || defined(PERL_EXT)
+#endif
#define ck_anoncode(a) Perl_ck_anoncode(aTHX_ a)
#define ck_bitop(a) Perl_ck_bitop(aTHX_ a)
#define ck_chdir(a) Perl_ck_chdir(aTHX_ a)
static SV *
make_cop_io_object(pTHX_ SV *arg, COP *cop)
{
- if (CopHINTS_get(cop) & HINT_LEXICAL_IO) {
- /* I feel you should be able to simply SvREFCNT_inc the return value
- from this, but if you do (and restore the line
- my $ioix = $cop->io->ix;
- in B::COP::bsave in Bytecode.pm, then you get errors about
- "attempt to free temp prematurely ... during global destruction.
- The SV's flags are consistent with the error, but quite how the
- temp escaped from the save stack is not clear. */
- SV *value = Perl_refcounted_he_fetch(aTHX_ cop->cop_hints_hash,
- 0, "open", 4, 0, 0);
+ SV *const value = newSV(0);
+
+ Perl_emulate_cop_io(cop, value);
+
+ if(SvOK(value)) {
return make_temp_object(aTHX_ arg, newSVsv(value));
} else {
+ SvREFCNT_dec(value);
return make_sv_object(aTHX_ arg, NULL);
}
}
@hints{2,512,1024} = ('$', '&', '*');
# integers, locale, bytes, arybase
@hints{1,4,8,16,32} = ('i', 'l', 'b', '[');
-# block scope, localise %^H, $^OPEN
-@hints{256,131072,262144} = ('{','%','<');
+# block scope, localise %^H, $^OPEN (in), $^OPEN (out)
+@hints{256,131072,262144,524288} = ('{','%','<','>');
# overload new integer, float, binary, string, re
@hints{4096,8192,16384,32768,65536} = ('I', 'F', 'B', 'S', 'R');
# taint and eval
# This is a bit of a kludge. Really we need to find a way to encode in the
# golden results that the hints wll differ because ${^OPEN} is set.
-if (((caller 0)[10]||{})->{'open'}) {
+if (((caller 0)[10]||{})->{'open<'}) {
@open_todo = (skip => "\${^OPEN} is set");
}
} \
} STMT_END
+void
+Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv)
+{
+ if (!(CopHINTS_get(c) & (HINT_LEXICAL_IO_IN|HINT_LEXICAL_IO_OUT)))
+ sv_setsv(sv, &PL_sv_undef);
+ else {
+ sv_setpvs(sv, "");
+ SvUTF8_off(sv);
+ if ((CopHINTS_get(c) & HINT_LEXICAL_IO_IN)) {
+ SV *const value = Perl_refcounted_he_fetch(aTHX_
+ c->cop_hints_hash,
+ 0, "open<", 5, 0, 0);
+ assert(value);
+ sv_catsv(sv, value);
+ }
+ sv_catpvs(sv, "\0");
+ if ((CopHINTS_get(c) & HINT_LEXICAL_IO_OUT)) {
+ SV *const value = Perl_refcounted_he_fetch(aTHX_
+ c->cop_hints_hash,
+ 0, "open>", 5, 0, 0);
+ assert(value);
+ sv_catsv(sv, value);
+ }
+ }
+}
+
int
Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
{
SvTAINTED_off(sv);
}
else if (strEQ(remaining, "PEN")) {
- if (!(CopHINTS_get(&PL_compiling) & HINT_LEXICAL_IO))
- sv_setsv(sv, &PL_sv_undef);
- else {
- sv_setsv(sv,
- Perl_refcounted_he_fetch(aTHX_
- PL_compiling.cop_hints_hash,
- 0, "open", 4, 0, 0));
- }
+ Perl_emulate_cop_io(aTHX_ &PL_compiling, sv);
}
break;
case '\020':
}
}
else if (strEQ(mg->mg_ptr, "\017PEN")) {
- PL_compiling.cop_hints |= HINT_LEXICAL_IO;
- PL_hints |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO;
+ STRLEN len;
+ const char *const start = SvPV(sv, len);
+ const char *out = memchr(start, '\0', len);
+ SV *tmp;
+ struct refcounted_he *tmp_he;
+
+
+ PL_compiling.cop_hints |= HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT;
+ PL_hints
+ |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT;
+
+ /* Opening for input is more common than opening for output, so
+ ensure that hints for input are sooner on linked list. */
+ tmp = sv_2mortal(out ? newSVpvn(out + 1, start + len - out - 1)
+ : newSVpvs(""));
+ SvFLAGS(tmp) |= SvUTF8(sv);
+
+ tmp_he
+ = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
+ sv_2mortal(newSVpvs("open>")), tmp);
+
+ /* The UTF-8 setting is carried over */
+ sv_setpvn(tmp, start, out ? (STRLEN)(out - start) : len);
+
PL_compiling.cop_hints_hash
- = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
- sv_2mortal(newSVpvs("open")), sv);
+ = Perl_refcounted_he_new(aTHX_ tmp_he,
+ sv_2mortal(newSVpvs("open<")), tmp);
}
break;
case '\020': /* ^P */
#define HINT_NEW_STRING 0x00008000
#define HINT_NEW_RE 0x00010000
#define HINT_LOCALIZE_HH 0x00020000 /* %^H needs to be copied */
-#define HINT_LEXICAL_IO 0x00040000 /* ${^OPEN} is set */
+#define HINT_LEXICAL_IO_IN 0x00040000 /* ${^OPEN} is set for input */
+#define HINT_LEXICAL_IO_OUT 0x00080000 /* ${^OPEN} is set for output */
#define HINT_RE_TAINT 0x00100000 /* re pragma */
#define HINT_RE_EVAL 0x00200000 /* re pragma */
Perl_PerlIO_context_layers(pTHX_ const char *mode)
{
dVAR;
- const char *type = NULL;
+ const char *direction = NULL;
+ SV *layers;
/*
* Need to supply default layer info from open.pm
*/
- if (PL_curcop && PL_curcop->cop_hints & HINT_LEXICAL_IO) {
- SV * const layers
- = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, 0,
- "open", 4, 0, 0);
- assert(layers);
- if (SvOK(layers)) {
- STRLEN len;
- type = SvPV_const(layers, len);
- if (type && mode && mode[0] != 'r') {
- /*
- * Skip to write part, which is separated by a '\0'
- */
- STRLEN read_len = strlen(type);
- if (read_len < len) {
- type += read_len + 1;
- }
- }
- }
+
+ if (!PL_curcop)
+ return NULL;
+
+ if (mode && mode[0] != 'r') {
+ if (PL_curcop->cop_hints & HINT_LEXICAL_IO_OUT)
+ direction = "open>";
+ } else {
+ if (PL_curcop->cop_hints & HINT_LEXICAL_IO_IN)
+ direction = "open<";
}
- return type;
+ if (!direction)
+ return NULL;
+
+ layers = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
+ 0, direction, 5, 0, 0);
+
+ assert(layers);
+ return SvOK(layers) ? SvPV_nolen_const(layers) : NULL;
}
#endif
+PERL_CALLCONV void Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv)
+ __attribute__nonnull__(pTHX_1)
+ __attribute__nonnull__(pTHX_2);
+
+
END_EXTERN_C
/*
* ex: set ts=8 sts=4 sw=4 noet: