This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
put signature ops in their own subtree.
[perl5.git] / ext / PerlIO-encoding / encoding.xs
1 #define PERL_NO_GET_CONTEXT
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5 #define U8 U8
6
7 #define OUR_DEFAULT_FB  "Encode::PERLQQ"
8
9 #if defined(USE_PERLIO)
10
11 /* Define an encoding "layer" in the perliol.h sense.
12
13    The layer defined here "inherits" in an object-oriented sense from
14    the "perlio" layer with its PerlIOBuf_* "methods".  The
15    implementation is particularly efficient as until Encode settles
16    down there is no point in tryint to tune it.
17
18    The layer works by overloading the "fill" and "flush" methods.
19
20    "fill" calls "SUPER::fill" in perl terms, then calls the encode OO
21    perl API to convert the encoded data to UTF-8 form, then copies it
22    back to the buffer. The "base class's" read methods then see the
23    UTF-8 data.
24
25    "flush" transforms the UTF-8 data deposited by the "base class's
26    write method in the buffer back into the encoded form using the
27    encode OO perl API, then copies data back into the buffer and calls
28    "SUPER::flush.
29
30    Note that "flush" is _also_ called for read mode - we still do the
31    (back)-translate so that the base class's "flush" sees the
32    correct number of encoded chars for positioning the seek
33    pointer. (This double translation is the worst performance issue -
34    particularly with all-perl encode engine.)
35
36 */
37
38 #include "perliol.h"
39
40 typedef struct {
41     PerlIOBuf base;             /* PerlIOBuf stuff */
42     SV *bufsv;                  /* buffer seen by layers above */
43     SV *dataSV;                 /* data we have read from layer below */
44     SV *enc;                    /* the encoding object */
45     SV *chk;                    /* CHECK in Encode methods */
46     int flags;                  /* Flags currently just needs lines */
47     int inEncodeCall;           /* trap recursive encode calls */
48 } PerlIOEncode;
49
50 #define NEEDS_LINES     1
51
52 static const MGVTBL PerlIOEncode_tag = { 0, 0, 0, 0, 0, 0, 0, 0 };
53
54 static SV *
55 PerlIOEncode_getarg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
56 {
57     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
58     SV *sv;
59     PERL_UNUSED_ARG(flags);
60     /* During cloning, return an undef token object so that _pushed() knows
61      * that it should not call methods and wait for _dup() to actually dup the
62      * encoding object. */
63     if (param) {
64         sv = newSV(0);
65         sv_magicext(sv, NULL, PERL_MAGIC_ext, &PerlIOEncode_tag, 0, 0);
66         return sv;
67     }
68     sv = &PL_sv_undef;
69     if (e->enc) {
70         dSP;
71         /* Not 100% sure stack swap is right thing to do during dup ... */
72         PUSHSTACKi(PERLSI_MAGIC);
73         ENTER;
74         SAVETMPS;
75         PUSHMARK(sp);
76         XPUSHs(e->enc);
77         PUTBACK;
78         if (call_method("name", G_SCALAR) == 1) {
79             SPAGAIN;
80             sv = newSVsv(POPs);
81             PUTBACK;
82         }
83         FREETMPS;
84         LEAVE;
85         POPSTACK;
86     }
87     return sv;
88 }
89
90 static IV
91 PerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, PerlIO_funcs *tab)
92 {
93     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
94     dSP;
95     IV  code = PerlIOBuf_pushed(aTHX_ f, mode, Nullsv,tab);
96     SV *result = Nullsv;
97
98     if (SvTYPE(arg) >= SVt_PVMG
99                 && mg_findext(arg, PERL_MAGIC_ext, &PerlIOEncode_tag)) {
100         e->enc = NULL;
101         e->chk = NULL;
102         e->inEncodeCall = 0;
103         return code;
104     }
105
106     PUSHSTACKi(PERLSI_MAGIC);
107     ENTER;
108     SAVETMPS;
109
110     PUSHMARK(sp);
111     XPUSHs(arg);
112     PUTBACK;
113     if (call_pv("Encode::find_encoding", G_SCALAR) != 1) {
114         /* should never happen */
115         Perl_die(aTHX_ "Encode::find_encoding did not return a value");
116         return -1;
117     }
118     SPAGAIN;
119     result = POPs;
120     PUTBACK;
121
122     if (!SvROK(result) || !SvOBJECT(SvRV(result))) {
123         e->enc = Nullsv;
124         if (ckWARN_d(WARN_IO))
125             Perl_warner(aTHX_ packWARN(WARN_IO), "Cannot find encoding \"%" SVf "\"",
126                     arg);
127         errno = EINVAL;
128         code = -1;
129     }
130     else {
131
132        /* $enc->renew */
133         PUSHMARK(sp);
134         XPUSHs(result);
135         PUTBACK;
136         if (call_method("renew",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
137             if (ckWARN_d(WARN_IO))
138                 Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support renew method",
139                         arg);
140         }
141         else {
142             SPAGAIN;
143             result = POPs;
144             PUTBACK;
145         }
146         e->enc = newSVsv(result);
147         PUSHMARK(sp);
148         XPUSHs(e->enc);
149         PUTBACK;
150         if (call_method("needs_lines",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
151             if (ckWARN_d(WARN_IO))
152                 Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support needs_lines",
153                         arg);
154         }
155         else {
156             SPAGAIN;
157             result = POPs;
158             PUTBACK;
159             if (SvTRUE(result)) {
160                 e->flags |= NEEDS_LINES;
161             }
162         }
163         PerlIOBase(f)->flags |= PERLIO_F_UTF8;
164     }
165
166     e->chk = newSVsv(get_sv("PerlIO::encoding::fallback", 0));
167     e->inEncodeCall = 0;
168
169     FREETMPS;
170     LEAVE;
171     POPSTACK;
172     return code;
173 }
174
175 static IV
176 PerlIOEncode_popped(pTHX_ PerlIO * f)
177 {
178     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
179     if (e->enc) {
180         SvREFCNT_dec(e->enc);
181         e->enc = Nullsv;
182     }
183     if (e->bufsv) {
184         SvREFCNT_dec(e->bufsv);
185         e->bufsv = Nullsv;
186     }
187     if (e->dataSV) {
188         SvREFCNT_dec(e->dataSV);
189         e->dataSV = Nullsv;
190     }
191     if (e->chk) {
192         SvREFCNT_dec(e->chk);
193         e->chk = Nullsv;
194     }
195     return 0;
196 }
197
198 static STDCHAR *
199 PerlIOEncode_get_base(pTHX_ PerlIO * f)
200 {
201     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
202     if (!e->base.bufsiz)
203         e->base.bufsiz = 1024;
204     if (!e->bufsv) {
205         e->bufsv = newSV(e->base.bufsiz);
206         SvPVCLEAR(e->bufsv);
207     }
208     e->base.buf = (STDCHAR *) SvPVX(e->bufsv);
209     if (!e->base.ptr)
210         e->base.ptr = e->base.buf;
211     if (!e->base.end)
212         e->base.end = e->base.buf;
213     if (e->base.ptr < e->base.buf
214         || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
215         Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
216                   e->base.buf + SvLEN(e->bufsv));
217         abort();
218     }
219     if (SvLEN(e->bufsv) < e->base.bufsiz) {
220         SSize_t poff = e->base.ptr - e->base.buf;
221         SSize_t eoff = e->base.end - e->base.buf;
222         e->base.buf = (STDCHAR *) SvGROW(e->bufsv, e->base.bufsiz);
223         e->base.ptr = e->base.buf + poff;
224         e->base.end = e->base.buf + eoff;
225     }
226     if (e->base.ptr < e->base.buf
227         || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
228         Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
229                   e->base.buf + SvLEN(e->bufsv));
230         abort();
231     }
232     return e->base.buf;
233 }
234
235 static IV
236 PerlIOEncode_fill(pTHX_ PerlIO * f)
237 {
238     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
239     dSP;
240     IV code = 0;
241     PerlIO *n;
242     SSize_t avail;
243
244     if (PerlIO_flush(f) != 0)
245         return -1;
246     n  = PerlIONext(f);
247     if (!PerlIO_fast_gets(n)) {
248         /* Things get too messy if we don't have a buffer layer
249            push a :perlio to do the job */
250         char mode[8];
251         n  = PerlIO_push(aTHX_ n, &PerlIO_perlio, PerlIO_modestr(f,mode), Nullsv);
252         if (!n) {
253             Perl_die(aTHX_ "panic: cannot push :perlio for %p",f);
254         }
255     }
256     PUSHSTACKi(PERLSI_MAGIC);
257     ENTER;
258     SAVETMPS;
259   retry:
260     avail = PerlIO_get_cnt(n);
261     if (avail <= 0) {
262         avail = PerlIO_fill(n);
263         if (avail == 0) {
264             avail = PerlIO_get_cnt(n);
265         }
266         else {
267             if (!PerlIO_error(n) && PerlIO_eof(n))
268                 avail = 0;
269         }
270     }
271     if (avail > 0 || (e->flags & NEEDS_LINES)) {
272         STDCHAR *ptr = PerlIO_get_ptr(n);
273         SSize_t use  = (avail >= 0) ? avail : 0;
274         SV *uni;
275         char *s = NULL;
276         STRLEN len = 0;
277         e->base.ptr = e->base.end = (STDCHAR *) NULL;
278         (void) PerlIOEncode_get_base(aTHX_ f);
279         if (!e->dataSV)
280             e->dataSV = newSV(0);
281         if (SvTYPE(e->dataSV) < SVt_PV) {
282             sv_upgrade(e->dataSV,SVt_PV);
283         }
284         if (e->flags & NEEDS_LINES) {
285             /* Encoding needs whole lines (e.g. iso-2022-*)
286                search back from end of available data for
287                and line marker
288              */
289             STDCHAR *nl = ptr+use-1;
290             while (nl >= ptr) {
291                 if (*nl == '\n') {
292                     break;
293                 }
294                 nl--;
295             }
296             if (nl >= ptr && *nl == '\n') {
297                 /* found a line - take up to and including that */
298                 use = (nl+1)-ptr;
299             }
300             else if (avail > 0) {
301                 /* No line, but not EOF - append avail to the pending data */
302                 sv_catpvn(e->dataSV, (char*)ptr, use);
303                 PerlIO_set_ptrcnt(n, ptr+use, 0);
304                 goto retry;
305             }
306             else if (!SvCUR(e->dataSV)) {
307                 goto end_of_file;
308             }
309         }
310         if (!SvCUR(e->dataSV))
311             SvPVCLEAR(e->dataSV);
312         if (use + SvCUR(e->dataSV) > e->base.bufsiz) {
313             if (e->flags & NEEDS_LINES) {
314                 /* Have to grow buffer */
315                 e->base.bufsiz = use + SvCUR(e->dataSV);
316                 PerlIOEncode_get_base(aTHX_ f);
317             }
318             else {
319                 use = e->base.bufsiz - SvCUR(e->dataSV);
320             }
321         }
322         sv_catpvn(e->dataSV,(char*)ptr,use);
323         SvUTF8_off(e->dataSV);
324         PUSHMARK(sp);
325         XPUSHs(e->enc);
326         XPUSHs(e->dataSV);
327         XPUSHs(e->chk);
328         PUTBACK;
329         if (call_method("decode", G_SCALAR) != 1) {
330             Perl_die(aTHX_ "panic: decode did not return a value");
331         }
332         SPAGAIN;
333         uni = POPs;
334         PUTBACK;
335         /* No cows allowed. */
336         if (SvTHINKFIRST(e->dataSV)) SvPV_force_nolen(e->dataSV);
337         /* Now get translated string (forced to UTF-8) and use as buffer */
338         if (SvPOK(uni)) {
339             s = SvPVutf8(uni, len);
340 #ifdef PARANOID_ENCODE_CHECKS
341             if (len && !is_utf8_string((U8*)s,len)) {
342                 Perl_warn(aTHX_ "panic: decode did not return UTF-8 '%.*s'",(int) len,s);
343             }
344 #endif
345         }
346         if (len > 0) {
347             /* Got _something */
348             /* if decode gave us back dataSV then data may vanish when
349                we do ptrcnt adjust - so take our copy now.
350                (The copy is a pain - need a put-it-here option for decode.)
351              */
352             sv_setpvn(e->bufsv,s,len);
353             e->base.ptr = e->base.buf = (STDCHAR*)SvPVX(e->bufsv);
354             e->base.end = e->base.ptr + SvCUR(e->bufsv);
355             PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
356             SvUTF8_on(e->bufsv);
357
358             /* Adjust ptr/cnt not taking anything which
359                did not translate - not clear this is a win */
360             /* compute amount we took */
361             if (!SvPOKp(e->dataSV)) (void)SvPV_force_nolen(e->dataSV);
362             use -= SvCUR(e->dataSV);
363             PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
364             /* and as we did not take it, it isn't pending */
365             SvCUR_set(e->dataSV,0);
366         } else {
367             /* Got nothing - assume partial character so we need some more */
368             /* Make sure e->dataSV is a normal SV before re-filling as
369                buffer alias will change under us
370              */
371             s = SvPV(e->dataSV,len);
372             sv_setpvn(e->dataSV,s,len);
373             PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
374             goto retry;
375         }
376     }
377     else {
378     end_of_file:
379         code = -1;
380         if (avail == 0)
381             PerlIOBase(f)->flags |= PERLIO_F_EOF;
382         else
383         {
384             PerlIOBase(f)->flags |= PERLIO_F_ERROR;
385             Perl_PerlIO_save_errno(aTHX_ f);
386         }
387     }
388     FREETMPS;
389     LEAVE;
390     POPSTACK;
391     return code;
392 }
393
394 static IV
395 PerlIOEncode_flush(pTHX_ PerlIO * f)
396 {
397     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
398     IV code = 0;
399
400     if (e->bufsv) {
401         dSP;
402         SV *str;
403         char *s;
404         STRLEN len;
405         SSize_t count = 0;
406         if ((PerlIOBase(f)->flags & PERLIO_F_WRBUF) && (e->base.ptr > e->base.buf)) {
407             if (e->inEncodeCall) return 0;
408             /* Write case - encode the buffer and write() to layer below */
409             PUSHSTACKi(PERLSI_MAGIC);
410             ENTER;
411             SAVETMPS;
412             PUSHMARK(sp);
413             XPUSHs(e->enc);
414             SvCUR_set(e->bufsv, e->base.ptr - e->base.buf);
415             SvUTF8_on(e->bufsv);
416             XPUSHs(e->bufsv);
417             XPUSHs(e->chk);
418             PUTBACK;
419             e->inEncodeCall = 1;
420             if (call_method("encode", G_SCALAR) != 1) {
421                 e->inEncodeCall = 0;
422                 Perl_die(aTHX_ "panic: encode did not return a value");
423             }
424             e->inEncodeCall = 0;
425             SPAGAIN;
426             str = POPs;
427             PUTBACK;
428             s = SvPV(str, len);
429             count = PerlIO_write(PerlIONext(f),s,len);
430             if ((STRLEN)count != len) {
431                 code = -1;
432             }
433             FREETMPS;
434             LEAVE;
435             POPSTACK;
436             if (PerlIO_flush(PerlIONext(f)) != 0) {
437                 code = -1;
438             }
439             if (!SvPOKp(e->bufsv) || SvTHINKFIRST(e->bufsv))
440                 (void)SvPV_force_nolen(e->bufsv);
441             if ((STDCHAR *)SvPVX(e->bufsv) != e->base.buf) {
442                 e->base.ptr = (STDCHAR *)SvEND(e->bufsv);
443                 e->base.end = (STDCHAR *)SvPVX(e->bufsv) + (e->base.end-e->base.buf);
444                 e->base.buf = (STDCHAR *)SvPVX(e->bufsv);
445             }
446             (void)PerlIOEncode_get_base(aTHX_ f);
447             if (SvCUR(e->bufsv)) {
448                 /* Did not all translate */
449                 e->base.ptr = e->base.buf+SvCUR(e->bufsv);
450                 return code;
451             }
452         }
453         else if ((PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
454             /* read case */
455             /* if we have any untranslated stuff then unread that first */
456             /* FIXME - unread is fragile is there a better way ? */
457             if (e->dataSV && SvCUR(e->dataSV)) {
458                 s = SvPV(e->dataSV, len);
459                 count = PerlIO_unread(PerlIONext(f),s,len);
460                 if ((STRLEN)count != len) {
461                     code = -1;
462                 }
463                 SvCUR_set(e->dataSV,0);
464             }
465             /* See if there is anything left in the buffer */
466             if (e->base.ptr < e->base.end) {
467                 if (e->inEncodeCall) return 0;
468                 /* Bother - have unread data.
469                    re-encode and unread() to layer below
470                  */
471                 PUSHSTACKi(PERLSI_MAGIC);
472                 ENTER;
473                 SAVETMPS;
474                 str = sv_newmortal();
475                 sv_upgrade(str, SVt_PV);
476                 SvPV_set(str, (char*)e->base.ptr);
477                 SvLEN_set(str, 0);
478                 SvCUR_set(str, e->base.end - e->base.ptr);
479                 SvPOK_only(str);
480                 SvUTF8_on(str);
481                 PUSHMARK(sp);
482                 XPUSHs(e->enc);
483                 XPUSHs(str);
484                 XPUSHs(e->chk);
485                 PUTBACK;
486                 e->inEncodeCall = 1;
487                 if (call_method("encode", G_SCALAR) != 1) {
488                     e->inEncodeCall = 0;
489                     Perl_die(aTHX_ "panic: encode did not return a value");
490                 }
491                 e->inEncodeCall = 0;
492                 SPAGAIN;
493                 str = POPs;
494                 PUTBACK;
495                 s = SvPV(str, len);
496                 count = PerlIO_unread(PerlIONext(f),s,len);
497                 if ((STRLEN)count != len) {
498                     code = -1;
499                 }
500                 FREETMPS;
501                 LEAVE;
502                 POPSTACK;
503             }
504         }
505         e->base.ptr = e->base.end = e->base.buf;
506         PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
507     }
508     return code;
509 }
510
511 static IV
512 PerlIOEncode_close(pTHX_ PerlIO * f)
513 {
514     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
515     IV code;
516     if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
517         /* Discard partial character */
518         if (e->dataSV) {
519             SvCUR_set(e->dataSV,0);
520         }
521         /* Don't back decode and unread any pending data */
522         e->base.ptr = e->base.end = e->base.buf;
523     }
524     code = PerlIOBase_close(aTHX_ f);
525     if (e->bufsv) {
526         /* This should only fire for write case */
527         if (e->base.buf && e->base.ptr > e->base.buf) {
528             Perl_croak(aTHX_ "Close with partial character");
529         }
530         SvREFCNT_dec(e->bufsv);
531         e->bufsv = Nullsv;
532     }
533     e->base.buf = NULL;
534     e->base.ptr = NULL;
535     e->base.end = NULL;
536     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
537     return code;
538 }
539
540 static Off_t
541 PerlIOEncode_tell(pTHX_ PerlIO * f)
542 {
543     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
544     /* Unfortunately the only way to get a position is to (re-)translate,
545        the UTF8 we have in buffer and then ask layer below
546      */
547     PerlIO_flush(f);
548     if (b->buf && b->ptr > b->buf) {
549         Perl_croak(aTHX_ "Cannot tell at partial character");
550     }
551     return PerlIO_tell(PerlIONext(f));
552 }
553
554 static PerlIO *
555 PerlIOEncode_dup(pTHX_ PerlIO * f, PerlIO * o,
556                  CLONE_PARAMS * params, int flags)
557 {
558     if ((f = PerlIOBase_dup(aTHX_ f, o, params, flags))) {
559         PerlIOEncode *fe = PerlIOSelf(f, PerlIOEncode);
560         PerlIOEncode *oe = PerlIOSelf(o, PerlIOEncode);
561         if (oe->enc) {
562             fe->enc = PerlIO_sv_dup(aTHX_ oe->enc, params);
563         }
564         if (oe->chk) {
565             fe->chk = PerlIO_sv_dup(aTHX_ oe->chk, params);
566         }
567     }
568     return f;
569 }
570
571 static SSize_t
572 PerlIOEncode_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
573 {
574     PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
575     if (e->flags & NEEDS_LINES) {
576         SSize_t done = 0;
577         const char *ptr = (const char *) vbuf;
578         const char *end = ptr+count;
579         while (ptr < end) {
580             const char *nl = ptr;
581             while (nl < end && *nl++ != '\n') /* empty body */;
582             done = PerlIOBuf_write(aTHX_ f, ptr, nl-ptr);
583             if (done != nl-ptr) {
584                 if (done > 0) {
585                     ptr += done;
586                 }
587                 break;
588             }
589             ptr += done;
590             if (ptr[-1] == '\n') {
591                 if (PerlIOEncode_flush(aTHX_ f) != 0) {
592                     break;
593                 }
594             }
595         }
596         return (SSize_t) (ptr - (const char *) vbuf);
597     }
598     else {
599         return PerlIOBuf_write(aTHX_ f, vbuf, count);
600     }
601 }
602
603 static PERLIO_FUNCS_DECL(PerlIO_encode) = {
604     sizeof(PerlIO_funcs),
605     "encoding",
606     sizeof(PerlIOEncode),
607     PERLIO_K_BUFFERED|PERLIO_K_DESTRUCT,
608     PerlIOEncode_pushed,
609     PerlIOEncode_popped,
610     PerlIOBuf_open,
611     NULL, /* binmode - always pop */
612     PerlIOEncode_getarg,
613     PerlIOBase_fileno,
614     PerlIOEncode_dup,
615     PerlIOBuf_read,
616     PerlIOBuf_unread,
617     PerlIOEncode_write,
618     PerlIOBuf_seek,
619     PerlIOEncode_tell,
620     PerlIOEncode_close,
621     PerlIOEncode_flush,
622     PerlIOEncode_fill,
623     PerlIOBase_eof,
624     PerlIOBase_error,
625     PerlIOBase_clearerr,
626     PerlIOBase_setlinebuf,
627     PerlIOEncode_get_base,
628     PerlIOBuf_bufsiz,
629     PerlIOBuf_get_ptr,
630     PerlIOBuf_get_cnt,
631     PerlIOBuf_set_ptrcnt,
632 };
633 #endif                          /* encode layer */
634
635 MODULE = PerlIO::encoding PACKAGE = PerlIO::encoding
636
637 PROTOTYPES: ENABLE
638
639 BOOT:
640 {
641     SV *chk = get_sv("PerlIO::encoding::fallback", GV_ADD|GV_ADDMULTI);
642     /*
643      * we now "use Encode ()" here instead of
644      * PerlIO/encoding.pm.  This avoids SEGV when ":encoding()"
645      * is invoked without prior "use Encode". -- dankogai
646      */
647     PUSHSTACKi(PERLSI_MAGIC);
648     if (!get_cvs(OUR_DEFAULT_FB, 0)) {
649 #if 0
650         /* This would just be an irritant now loading works */
651         Perl_warner(aTHX_ packWARN(WARN_IO), ":encoding without 'use Encode'");
652 #endif
653         /* The SV is magically freed by load_module */
654         load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("Encode"), Nullsv, Nullsv);
655         assert(sp == PL_stack_sp);
656     }
657     PUSHMARK(sp);
658     PUTBACK;
659     if (call_pv(OUR_DEFAULT_FB, G_SCALAR) != 1) {
660             /* should never happen */
661             Perl_die(aTHX_ "%s did not return a value",OUR_DEFAULT_FB);
662     }
663     SPAGAIN;
664     sv_setsv(chk, POPs);
665     PUTBACK;
666 #ifdef PERLIO_LAYERS
667     PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_encode));
668 #endif
669     POPSTACK;
670 }