xref: /openbsd-src/gnu/usr.bin/perl/ext/PerlIO-encoding/encoding.xs (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
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 	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 
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 	    /* 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 
417 static IV
418 PerlIOEncode_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 
534 static IV
535 PerlIOEncode_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 
563 static Off_t
564 PerlIOEncode_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 
577 static PerlIO *
578 PerlIOEncode_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 
594 static SSize_t
595 PerlIOEncode_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 
626 static 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 
658 MODULE = PerlIO::encoding PACKAGE = PerlIO::encoding
659 
660 PROTOTYPES: ENABLE
661 
662 BOOT:
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 }
694