This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add Configure probe for strerror_l()
[perl5.git] / ext / PerlIO-encoding / encoding.xs
... / ...
CommitLineData
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
40typedef 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
52static const MGVTBL PerlIOEncode_tag = { 0, 0, 0, 0, 0, 0, 0, 0 };
53
54static SV *
55PerlIOEncode_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
90static IV
91PerlIOEncode_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
175static IV
176PerlIOEncode_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
198static STDCHAR *
199PerlIOEncode_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 sv_setpvn(e->bufsv, "", 0);
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
235static IV
236PerlIOEncode_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 /* something left over from last time - create a normal
312 SV with new data appended
313 */
314 if (use + SvCUR(e->dataSV) > e->base.bufsiz) {
315 if (e->flags & NEEDS_LINES) {
316 /* Have to grow buffer */
317 e->base.bufsiz = use + SvCUR(e->dataSV);
318 PerlIOEncode_get_base(aTHX_ f);
319 }
320 else {
321 use = e->base.bufsiz - SvCUR(e->dataSV);
322 }
323 }
324 sv_catpvn(e->dataSV,(char*)ptr,use);
325 }
326 else {
327 /* Create a "dummy" SV to represent the available data from layer below */
328 if (SvLEN(e->dataSV) && SvPVX_const(e->dataSV)) {
329 Safefree(SvPVX_mutable(e->dataSV));
330 }
331 if (use > (SSize_t)e->base.bufsiz) {
332 if (e->flags & NEEDS_LINES) {
333 /* Have to grow buffer */
334 e->base.bufsiz = use;
335 PerlIOEncode_get_base(aTHX_ f);
336 }
337 else {
338 use = e->base.bufsiz;
339 }
340 }
341 SvPV_set(e->dataSV, (char *) ptr);
342 SvLEN_set(e->dataSV, 0); /* Hands off sv.c - it isn't yours */
343 SvCUR_set(e->dataSV,use);
344 SvPOK_only(e->dataSV);
345 }
346 SvUTF8_off(e->dataSV);
347 PUSHMARK(sp);
348 XPUSHs(e->enc);
349 XPUSHs(e->dataSV);
350 XPUSHs(e->chk);
351 PUTBACK;
352 if (call_method("decode", G_SCALAR) != 1) {
353 Perl_die(aTHX_ "panic: decode did not return a value");
354 }
355 SPAGAIN;
356 uni = POPs;
357 PUTBACK;
358 /* No cows allowed. */
359 if (SvTHINKFIRST(e->dataSV)) SvPV_force_nolen(e->dataSV);
360 /* Now get translated string (forced to UTF-8) and use as buffer */
361 if (SvPOK(uni)) {
362 s = SvPVutf8(uni, len);
363#ifdef PARANOID_ENCODE_CHECKS
364 if (len && !is_utf8_string((U8*)s,len)) {
365 Perl_warn(aTHX_ "panic: decode did not return UTF-8 '%.*s'",(int) len,s);
366 }
367#endif
368 }
369 if (len > 0) {
370 /* Got _something */
371 /* if decode gave us back dataSV then data may vanish when
372 we do ptrcnt adjust - so take our copy now.
373 (The copy is a pain - need a put-it-here option for decode.)
374 */
375 sv_setpvn(e->bufsv,s,len);
376 e->base.ptr = e->base.buf = (STDCHAR*)SvPVX(e->bufsv);
377 e->base.end = e->base.ptr + SvCUR(e->bufsv);
378 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
379 SvUTF8_on(e->bufsv);
380
381 /* Adjust ptr/cnt not taking anything which
382 did not translate - not clear this is a win */
383 /* compute amount we took */
384 if (!SvPOKp(e->dataSV)) (void)SvPV_force_nolen(e->dataSV);
385 use -= SvCUR(e->dataSV);
386 PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
387 /* and as we did not take it it isn't pending */
388 SvCUR_set(e->dataSV,0);
389 } else {
390 /* Got nothing - assume partial character so we need some more */
391 /* Make sure e->dataSV is a normal SV before re-filling as
392 buffer alias will change under us
393 */
394 s = SvPV(e->dataSV,len);
395 sv_setpvn(e->dataSV,s,len);
396 PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
397 goto retry;
398 }
399 }
400 else {
401 end_of_file:
402 code = -1;
403 if (avail == 0)
404 PerlIOBase(f)->flags |= PERLIO_F_EOF;
405 else
406 {
407 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
408 Perl_PerlIO_save_errno(aTHX_ f);
409 }
410 }
411 FREETMPS;
412 LEAVE;
413 POPSTACK;
414 return code;
415}
416
417static IV
418PerlIOEncode_flush(pTHX_ PerlIO * f)
419{
420 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
421 IV code = 0;
422
423 if (e->bufsv) {
424 dSP;
425 SV *str;
426 char *s;
427 STRLEN len;
428 SSize_t count = 0;
429 if ((PerlIOBase(f)->flags & PERLIO_F_WRBUF) && (e->base.ptr > e->base.buf)) {
430 if (e->inEncodeCall) return 0;
431 /* Write case - encode the buffer and write() to layer below */
432 PUSHSTACKi(PERLSI_MAGIC);
433 ENTER;
434 SAVETMPS;
435 PUSHMARK(sp);
436 XPUSHs(e->enc);
437 SvCUR_set(e->bufsv, e->base.ptr - e->base.buf);
438 SvUTF8_on(e->bufsv);
439 XPUSHs(e->bufsv);
440 XPUSHs(e->chk);
441 PUTBACK;
442 e->inEncodeCall = 1;
443 if (call_method("encode", G_SCALAR) != 1) {
444 e->inEncodeCall = 0;
445 Perl_die(aTHX_ "panic: encode did not return a value");
446 }
447 e->inEncodeCall = 0;
448 SPAGAIN;
449 str = POPs;
450 PUTBACK;
451 s = SvPV(str, len);
452 count = PerlIO_write(PerlIONext(f),s,len);
453 if ((STRLEN)count != len) {
454 code = -1;
455 }
456 FREETMPS;
457 LEAVE;
458 POPSTACK;
459 if (PerlIO_flush(PerlIONext(f)) != 0) {
460 code = -1;
461 }
462 if (!SvPOKp(e->bufsv) || SvTHINKFIRST(e->bufsv))
463 (void)SvPV_force_nolen(e->bufsv);
464 if ((STDCHAR *)SvPVX(e->bufsv) != e->base.buf) {
465 e->base.ptr = (STDCHAR *)SvEND(e->bufsv);
466 e->base.end = (STDCHAR *)SvPVX(e->bufsv) + (e->base.end-e->base.buf);
467 e->base.buf = (STDCHAR *)SvPVX(e->bufsv);
468 }
469 (void)PerlIOEncode_get_base(aTHX_ f);
470 if (SvCUR(e->bufsv)) {
471 /* Did not all translate */
472 e->base.ptr = e->base.buf+SvCUR(e->bufsv);
473 return code;
474 }
475 }
476 else if ((PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
477 /* read case */
478 /* if we have any untranslated stuff then unread that first */
479 /* FIXME - unread is fragile is there a better way ? */
480 if (e->dataSV && SvCUR(e->dataSV)) {
481 s = SvPV(e->dataSV, len);
482 count = PerlIO_unread(PerlIONext(f),s,len);
483 if ((STRLEN)count != len) {
484 code = -1;
485 }
486 SvCUR_set(e->dataSV,0);
487 }
488 /* See if there is anything left in the buffer */
489 if (e->base.ptr < e->base.end) {
490 if (e->inEncodeCall) return 0;
491 /* Bother - have unread data.
492 re-encode and unread() to layer below
493 */
494 PUSHSTACKi(PERLSI_MAGIC);
495 ENTER;
496 SAVETMPS;
497 str = sv_newmortal();
498 sv_upgrade(str, SVt_PV);
499 SvPV_set(str, (char*)e->base.ptr);
500 SvLEN_set(str, 0);
501 SvCUR_set(str, e->base.end - e->base.ptr);
502 SvPOK_only(str);
503 SvUTF8_on(str);
504 PUSHMARK(sp);
505 XPUSHs(e->enc);
506 XPUSHs(str);
507 XPUSHs(e->chk);
508 PUTBACK;
509 e->inEncodeCall = 1;
510 if (call_method("encode", G_SCALAR) != 1) {
511 e->inEncodeCall = 0;
512 Perl_die(aTHX_ "panic: encode did not return a value");
513 }
514 e->inEncodeCall = 0;
515 SPAGAIN;
516 str = POPs;
517 PUTBACK;
518 s = SvPV(str, len);
519 count = PerlIO_unread(PerlIONext(f),s,len);
520 if ((STRLEN)count != len) {
521 code = -1;
522 }
523 FREETMPS;
524 LEAVE;
525 POPSTACK;
526 }
527 }
528 e->base.ptr = e->base.end = e->base.buf;
529 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
530 }
531 return code;
532}
533
534static IV
535PerlIOEncode_close(pTHX_ PerlIO * f)
536{
537 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
538 IV code;
539 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
540 /* Discard partial character */
541 if (e->dataSV) {
542 SvCUR_set(e->dataSV,0);
543 }
544 /* Don't back decode and unread any pending data */
545 e->base.ptr = e->base.end = e->base.buf;
546 }
547 code = PerlIOBase_close(aTHX_ f);
548 if (e->bufsv) {
549 /* This should only fire for write case */
550 if (e->base.buf && e->base.ptr > e->base.buf) {
551 Perl_croak(aTHX_ "Close with partial character");
552 }
553 SvREFCNT_dec(e->bufsv);
554 e->bufsv = Nullsv;
555 }
556 e->base.buf = NULL;
557 e->base.ptr = NULL;
558 e->base.end = NULL;
559 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
560 return code;
561}
562
563static Off_t
564PerlIOEncode_tell(pTHX_ PerlIO * f)
565{
566 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
567 /* Unfortunately the only way to get a position is to (re-)translate,
568 the UTF8 we have in buffer and then ask layer below
569 */
570 PerlIO_flush(f);
571 if (b->buf && b->ptr > b->buf) {
572 Perl_croak(aTHX_ "Cannot tell at partial character");
573 }
574 return PerlIO_tell(PerlIONext(f));
575}
576
577static PerlIO *
578PerlIOEncode_dup(pTHX_ PerlIO * f, PerlIO * o,
579 CLONE_PARAMS * params, int flags)
580{
581 if ((f = PerlIOBase_dup(aTHX_ f, o, params, flags))) {
582 PerlIOEncode *fe = PerlIOSelf(f, PerlIOEncode);
583 PerlIOEncode *oe = PerlIOSelf(o, PerlIOEncode);
584 if (oe->enc) {
585 fe->enc = PerlIO_sv_dup(aTHX_ oe->enc, params);
586 }
587 if (oe->chk) {
588 fe->chk = PerlIO_sv_dup(aTHX_ oe->chk, params);
589 }
590 }
591 return f;
592}
593
594static SSize_t
595PerlIOEncode_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
596{
597 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
598 if (e->flags & NEEDS_LINES) {
599 SSize_t done = 0;
600 const char *ptr = (const char *) vbuf;
601 const char *end = ptr+count;
602 while (ptr < end) {
603 const char *nl = ptr;
604 while (nl < end && *nl++ != '\n') /* empty body */;
605 done = PerlIOBuf_write(aTHX_ f, ptr, nl-ptr);
606 if (done != nl-ptr) {
607 if (done > 0) {
608 ptr += done;
609 }
610 break;
611 }
612 ptr += done;
613 if (ptr[-1] == '\n') {
614 if (PerlIOEncode_flush(aTHX_ f) != 0) {
615 break;
616 }
617 }
618 }
619 return (SSize_t) (ptr - (const char *) vbuf);
620 }
621 else {
622 return PerlIOBuf_write(aTHX_ f, vbuf, count);
623 }
624}
625
626static PERLIO_FUNCS_DECL(PerlIO_encode) = {
627 sizeof(PerlIO_funcs),
628 "encoding",
629 sizeof(PerlIOEncode),
630 PERLIO_K_BUFFERED|PERLIO_K_DESTRUCT,
631 PerlIOEncode_pushed,
632 PerlIOEncode_popped,
633 PerlIOBuf_open,
634 NULL, /* binmode - always pop */
635 PerlIOEncode_getarg,
636 PerlIOBase_fileno,
637 PerlIOEncode_dup,
638 PerlIOBuf_read,
639 PerlIOBuf_unread,
640 PerlIOEncode_write,
641 PerlIOBuf_seek,
642 PerlIOEncode_tell,
643 PerlIOEncode_close,
644 PerlIOEncode_flush,
645 PerlIOEncode_fill,
646 PerlIOBase_eof,
647 PerlIOBase_error,
648 PerlIOBase_clearerr,
649 PerlIOBase_setlinebuf,
650 PerlIOEncode_get_base,
651 PerlIOBuf_bufsiz,
652 PerlIOBuf_get_ptr,
653 PerlIOBuf_get_cnt,
654 PerlIOBuf_set_ptrcnt,
655};
656#endif /* encode layer */
657
658MODULE = PerlIO::encoding PACKAGE = PerlIO::encoding
659
660PROTOTYPES: ENABLE
661
662BOOT:
663{
664 SV *chk = get_sv("PerlIO::encoding::fallback", GV_ADD|GV_ADDMULTI);
665 /*
666 * we now "use Encode ()" here instead of
667 * PerlIO/encoding.pm. This avoids SEGV when ":encoding()"
668 * is invoked without prior "use Encode". -- dankogai
669 */
670 PUSHSTACKi(PERLSI_MAGIC);
671 if (!get_cvs(OUR_DEFAULT_FB, 0)) {
672#if 0
673 /* This would just be an irritant now loading works */
674 Perl_warner(aTHX_ packWARN(WARN_IO), ":encoding without 'use Encode'");
675#endif
676 /* The SV is magically freed by load_module */
677 load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("Encode"), Nullsv, Nullsv);
678 assert(sp == PL_stack_sp);
679 }
680 PUSHMARK(sp);
681 PUTBACK;
682 if (call_pv(OUR_DEFAULT_FB, G_SCALAR) != 1) {
683 /* should never happen */
684 Perl_die(aTHX_ "%s did not return a value",OUR_DEFAULT_FB);
685 }
686 SPAGAIN;
687 sv_setsv(chk, POPs);
688 PUTBACK;
689#ifdef PERLIO_LAYERS
690 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_encode));
691#endif
692 POPSTACK;
693}