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