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