diff options
-rw-r--r-- | perlio.c | 242 | ||||
-rw-r--r-- | pod/perlapio.pod | 37 | ||||
-rw-r--r-- | pod/perlxstut.pod | 39 |
3 files changed, 191 insertions, 127 deletions
@@ -106,7 +106,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode) } #ifndef O_ACCMODE -#define O_ACCMODE 3 /* Assume traditional implementation */ +#define O_ACCMODE 3 /* Assume traditional implementation */ #endif int @@ -190,7 +190,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) return NULL; #else #ifdef PERL_IMPLICIT_SYS - return PerlSIO_fdupopen(f); + return PerlSIO_fdupopen(f); #else #ifdef WIN32 return win32_fdupopen(f); @@ -297,7 +297,7 @@ PerlIO_tmpfile(void) return tmpfile(); } -#else /* PERLIO_IS_STDIO */ +#else /* PERLIO_IS_STDIO */ #ifdef USE_SFIO @@ -355,7 +355,7 @@ PerlIO_findFILE(PerlIO *pio) } -#else /* USE_SFIO */ +#else /* USE_SFIO */ /*======================================================================================*/ /* * Implement all the PerlIO interface ourselves. @@ -403,7 +403,7 @@ PerlIO_debug(const char *fmt, ...) if (!s) s = "(none)"; sprintf(buffer, "%s:%" IVdf " ", s, (IV) CopLINE(PL_curcop)); - len = strlen(buffer); + len = strlen(buffer); vsprintf(buffer+len, fmt, ap); PerlLIO_write(dbg, buffer, strlen(buffer)); #else @@ -470,7 +470,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) PerlIO_funcs *tab = PerlIOBase(f)->tab; PerlIO *new; PerlIO_debug("fdupopen f=%p param=%p\n",(void*)f,(void*)param); - new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags); + new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags); return new; } else { @@ -710,7 +710,7 @@ perlio_mg_free(pTHX_ SV *sv, MAGIC *mg) MGVTBL perlio_vtab = { perlio_mg_get, perlio_mg_set, - NULL, /* len */ + NULL, /* len */ perlio_mg_clear, perlio_mg_free }; @@ -745,7 +745,7 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES) XSRETURN(count); } -#endif /* USE_ATTIBUTES_FOR_PERLIO */ +#endif /* USE_ATTIBUTES_FOR_PERLIO */ SV * PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab) @@ -802,7 +802,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ char q = ((*s == '\'') ? '"' : '\''); if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), + Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: invalid separator character %c%c%c in layer specification list %s", q, *s, q, s); return -1; @@ -837,8 +837,8 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ case '\0': e--; - if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), + if (ckWARN(WARN_LAYER)) + Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: argument list not closed for layer \"%.*s\"", (int) (e - s), s); return -1; @@ -861,7 +861,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) &PL_sv_undef); } else { - if (warn_layer) + if (warn_layer) Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: unknown layer \"%.*s\"", (int) llen, s); return -1; @@ -882,7 +882,7 @@ PerlIO_default_buffer(pTHX_ PerlIO_list_t *av) tab = &PerlIO_crlf; #else if (PerlIO_stdio.Set_ptrcnt) - tab = &PerlIO_stdio; + tab = &PerlIO_stdio; #endif PerlIO_debug("Pushing %s\n", tab->name); PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0), @@ -1689,17 +1689,17 @@ PerlIO_funcs PerlIO_utf8 = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; PerlIO_funcs PerlIO_byte = { @@ -1717,17 +1717,17 @@ PerlIO_funcs PerlIO_byte = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; PerlIO * @@ -1755,17 +1755,17 @@ PerlIO_funcs PerlIO_raw = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; /*--------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------*/ @@ -2107,9 +2107,9 @@ PerlIO_cleanup(pTHX) */ typedef struct { - struct _PerlIO base; /* The generic part */ - int fd; /* UNIX like file descriptor */ - int oflags; /* open/fcntl flags */ + struct _PerlIO base; /* The generic part */ + int fd; /* UNIX like file descriptor */ + int oflags; /* open/fcntl flags */ } PerlIOUnix; int @@ -2232,7 +2232,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, s->fd = fd; s->oflags = imode; PerlIOBase(f)->flags |= PERLIO_F_OPEN; - PerlIOUnix_refcnt_inc(fd); + PerlIOUnix_refcnt_inc(fd); return f; } else { @@ -2326,7 +2326,7 @@ PerlIOUnix_close(pTHX_ PerlIO *f) if (PerlIOUnix_refcnt_dec(fd) > 0) { PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; return 0; - } + } } else { SETERRNO(EBADF,SS$_IVCHAN); @@ -2361,17 +2361,17 @@ PerlIO_funcs PerlIO_unix = { PerlIOUnix_seek, PerlIOUnix_tell, PerlIOUnix_close, - PerlIOBase_noop_ok, /* flush */ - PerlIOBase_noop_fail, /* fill */ + PerlIOBase_noop_ok, /* flush */ + PerlIOBase_noop_fail, /* fill */ PerlIOBase_eof, PerlIOBase_error, PerlIOBase_clearerr, PerlIOBase_setlinebuf, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; /*--------------------------------------------------------------------------------------*/ @@ -2381,7 +2381,7 @@ PerlIO_funcs PerlIO_unix = { typedef struct { struct _PerlIO base; - FILE *stdio; /* The stream */ + FILE *stdio; /* The stream */ } PerlIOStdio; IV @@ -2427,20 +2427,37 @@ PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) return PerlIOBase_pushed(aTHX_ f, mode, arg); } + PerlIO * PerlIO_importFILE(FILE *stdio, int fl) { dTHX; PerlIO *f = NULL; if (stdio) { - int mode = fcntl(fileno(stdio), F_GETFL); - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, - (mode&O_ACCMODE) == O_RDONLY ? "r" - : (mode&O_ACCMODE) == O_WRONLY ? "w" - : "r+", - Nullsv), PerlIOStdio); + /* We need to probe to see how we can open the stream + so start with read/write and then try write and read + we dup() so that we can fclose without loosing the fd. + */ + int fd = PerlLIO_dup(fileno(stdio)); + char *mode = "r+"; + FILE *f2 = fdopen(fd, mode); + PerlIOStdio *s; + if (!f2 && errno == EINVAL) { + mode = "w"; + f2 = fdopen(fd, mode); + } + if (!f2 && errno == EINVAL) { + mode = "r"; + f2 = fdopen(fd, mode); + } + if (!f2) { + /* Don't seem to be able to open */ + return f; + } + fclose(f2); + s = PerlIOSelf(PerlIO_push + (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, + mode, Nullsv), PerlIOStdio); s->stdio = stdio; } return f; @@ -2564,7 +2581,7 @@ PerlIOStdio_close(pTHX_ PerlIO *f) FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) { /* Do not close it but do flush any buffers */ - return PerlIO_flush(f); + return PerlIO_flush(f); } return ( #ifdef SOCKS5_VERSION_NAME @@ -2749,7 +2766,7 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; if (ptr != NULL) { #ifdef STDIO_PTR_LVALUE - PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */ + PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */ #ifdef STDIO_PTR_LVAL_SETS_CNT if (PerlSIO_get_cnt(stdio) != (cnt)) { assert(PerlSIO_get_cnt(stdio) == (cnt)); @@ -2761,24 +2778,24 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) */ return; #endif -#else /* STDIO_PTR_LVALUE */ +#else /* STDIO_PTR_LVALUE */ PerlProc_abort(); -#endif /* STDIO_PTR_LVALUE */ +#endif /* STDIO_PTR_LVALUE */ } /* * Now (or only) set cnt */ #ifdef STDIO_CNT_LVALUE PerlSIO_set_cnt(stdio, cnt); -#else /* STDIO_CNT_LVALUE */ +#else /* STDIO_CNT_LVALUE */ #if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT)) PerlSIO_set_ptr(stdio, PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) - cnt)); -#else /* STDIO_PTR_LVAL_SETS_CNT */ +#else /* STDIO_PTR_LVAL_SETS_CNT */ PerlProc_abort(); -#endif /* STDIO_PTR_LVAL_SETS_CNT */ -#endif /* STDIO_CNT_LVALUE */ +#endif /* STDIO_PTR_LVAL_SETS_CNT */ +#endif /* STDIO_CNT_LVALUE */ } #endif @@ -2817,14 +2834,14 @@ PerlIO_funcs PerlIO_stdio = { PerlIOStdio_get_cnt, #if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT))) PerlIOStdio_set_ptrcnt -#else /* STDIO_PTR_LVALUE */ +#else /* STDIO_PTR_LVALUE */ NULL -#endif /* STDIO_PTR_LVALUE */ -#else /* USE_STDIO_PTR */ +#endif /* STDIO_PTR_LVALUE */ +#else /* USE_STDIO_PTR */ NULL, NULL, NULL -#endif /* USE_STDIO_PTR */ +#endif /* USE_STDIO_PTR */ }; FILE * @@ -2861,6 +2878,19 @@ PerlIO_findFILE(PerlIO *f) void PerlIO_releaseFILE(PerlIO *p, FILE *f) { + PerlIOl *l; + while ((l = *p)) { + if (l->tab == &PerlIO_stdio) { + PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio); + if (s->stdio == f) { + dTHX; + PerlIO_pop(aTHX_ p); + return; + } + } + p = PerlIONext(p); + } + return; } /*--------------------------------------------------------------------------------------*/ @@ -2910,7 +2940,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, f, narg, args); if (f) { - if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { + if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { /* * if push fails during open, open fails. close will pop us. */ @@ -3013,7 +3043,7 @@ PerlIOBuf_fill(pTHX_ PerlIO *f) PerlIOBase_flush_linebuf(aTHX); if (!b->buf) - PerlIO_get_base(f); /* allocate via vtable */ + PerlIO_get_base(f); /* allocate via vtable */ b->ptr = b->end = b->buf; if (PerlIO_fast_gets(n)) { @@ -3447,8 +3477,8 @@ PerlIO_funcs PerlIO_pending = { */ typedef struct { - PerlIOBuf base; /* PerlIOBuf stuff */ - STDCHAR *nl; /* Position of crlf we "lied" about in the + PerlIOBuf base; /* PerlIOBuf stuff */ + STDCHAR *nl; /* Position of crlf we "lied" about in the * buffer */ } PerlIOCrlf; @@ -3559,19 +3589,19 @@ PerlIOCrlf_get_cnt(pTHX_ PerlIO *f) } else { int code; - b->ptr++; /* say we have read it as far as + b->ptr++; /* say we have read it as far as * flush() is concerned */ - b->buf++; /* Leave space in front of buffer */ - b->bufsiz--; /* Buffer is thus smaller */ - code = PerlIO_fill(f); /* Fetch some more */ - b->bufsiz++; /* Restore size for next time */ - b->buf--; /* Point at space */ - b->ptr = nl = b->buf; /* Which is what we hand + b->buf++; /* Leave space in front of buffer */ + b->bufsiz--; /* Buffer is thus smaller */ + code = PerlIO_fill(f); /* Fetch some more */ + b->bufsiz++; /* Restore size for next time */ + b->buf--; /* Point at space */ + b->ptr = nl = b->buf; /* Which is what we hand * off */ - b->posn--; /* Buffer starts here */ - *nl = 0xd; /* Fill in the CR */ + b->posn--; /* Buffer starts here */ + *nl = 0xd; /* Fill in the CR */ if (code == 0) - goto test; /* fill() call worked */ + goto test; /* fill() call worked */ /* * CR at EOF - just fall through */ @@ -3595,11 +3625,11 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) if (!ptr) { if (c->nl) { ptr = c->nl + 1; - if (ptr == b->end && *c->nl == 0xd) { + if (ptr == b->end && *c->nl == 0xd) { /* Defered CR at end of buffer case - we lied about count */ - ptr--; - } - } + ptr--; + } + } else { ptr = b->end; } @@ -3612,10 +3642,10 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) */ IV flags = PerlIOBase(f)->flags; STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end; - if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) { + if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) { /* Defered CR at end of buffer case - we lied about count */ chk--; - } + } chk -= cnt; if (ptr != chk ) { @@ -3665,8 +3695,8 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) break; } else { - *(b->ptr)++ = 0xd; /* CR */ - *(b->ptr)++ = 0xa; /* LF */ + *(b->ptr)++ = 0xd; /* CR */ + *(b->ptr)++ = 0xa; /* LF */ buf++; if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) { PerlIO_flush(f); @@ -3706,15 +3736,15 @@ PerlIO_funcs PerlIO_crlf = { sizeof(PerlIOCrlf), PERLIO_K_BUFFERED | PERLIO_K_CANCRLF, PerlIOCrlf_pushed, - PerlIOBase_noop_ok, /* popped */ + PerlIOBase_noop_ok, /* popped */ PerlIOBuf_open, NULL, PerlIOBase_fileno, PerlIOBuf_dup, - PerlIOBuf_read, /* generic read works with ptr/cnt lies + PerlIOBuf_read, /* generic read works with ptr/cnt lies * ... */ - PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */ - PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */ + PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */ + PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */ PerlIOBuf_seek, PerlIOBuf_tell, PerlIOBuf_close, @@ -3738,10 +3768,10 @@ PerlIO_funcs PerlIO_crlf = { */ typedef struct { - PerlIOBuf base; /* PerlIOBuf stuff */ - Mmap_t mptr; /* Mapped address */ - Size_t len; /* mapped length */ - STDCHAR *bbuf; /* malloced buffer if map fails */ + PerlIOBuf base; /* PerlIOBuf stuff */ + Mmap_t mptr; /* Mapped address */ + Size_t len; /* mapped length */ + STDCHAR *bbuf; /* malloced buffer if map fails */ } PerlIOMmap; static size_t page_size = 0; @@ -3792,7 +3822,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f) page_size = getpagesize(); # else # if defined(I_SYS_PARAM) && defined(PAGESIZE) - page_size = PAGESIZE; /* compiletime, bad */ + page_size = PAGESIZE; /* compiletime, bad */ # endif # endif #endif @@ -3876,11 +3906,11 @@ PerlIOMmap_get_base(pTHX_ PerlIO *f) /* * We have a write buffer or flushed PerlIOBuf read buffer */ - m->bbuf = b->buf; /* save it in case we need it again */ - b->buf = NULL; /* Clear to trigger below */ + m->bbuf = b->buf; /* save it in case we need it again */ + b->buf = NULL; /* Clear to trigger below */ } if (!b->buf) { - PerlIOMmap_map(aTHX_ f); /* Try and map it */ + PerlIOMmap_map(aTHX_ f); /* Try and map it */ if (!b->buf) { /* * Map did not work - recover PerlIOBuf buffer if we have one @@ -4045,7 +4075,7 @@ PerlIO_funcs PerlIO_mmap = { PerlIOBuf_set_ptrcnt, }; -#endif /* HAS_MMAP */ +#endif /* HAS_MMAP */ PerlIO * Perl_PerlIO_stdin(pTHX) @@ -4263,8 +4293,8 @@ PerlIO_tmpfile(void) #undef HAS_FSETPOS #undef HAS_FGETPOS -#endif /* USE_SFIO */ -#endif /* PERLIO_IS_STDIO */ +#endif /* USE_SFIO */ +#endif /* PERLIO_IS_STDIO */ /*======================================================================================*/ /* @@ -4343,7 +4373,7 @@ int vprintf(char *pat, char *args) { _doprnt(pat, args, stdout); - return 0; /* wrong, but perl doesn't use the return + return 0; /* wrong, but perl doesn't use the return * value */ } @@ -4351,7 +4381,7 @@ int vfprintf(FILE *fd, char *pat, char *args) { _doprnt(pat, args, fd); - return 0; /* wrong, but perl doesn't use the return + return 0; /* wrong, but perl doesn't use the return * value */ } diff --git a/pod/perlapio.pod b/pod/perlapio.pod index 22128db978..a0e4ffaf10 100644 --- a/pod/perlapio.pod +++ b/pod/perlapio.pod @@ -305,27 +305,34 @@ changes in this area. =item B<PerlIO_importFILE(f,flags)> -Used to get a PerlIO * from a FILE *. May need additional arguments, -interface under review. +Used to get a PerlIO * from a FILE *. The flags argument was meant to be used for read vs write vs read/write information. In hindsight it would have been better to make -it a char *mode as in fopen/freopen. +it a char *mode as in fopen/freopen. Flags arecurrently ignored, and +code attempts to empirically determine the mode in which I<f> is open. + +Once called the FILE * should I<ONLY> be closed by calling +C<PerlIO_close()> on the returned PerlIO *. + =item B<PerlIO_exportFILE(f,flags)> Given a PerlIO * create a 'native' FILE * suitable for passing to code expecting to be compiled and linked with ANSI C I<stdio.h>. +The flags argument was meant to be used for read vs write vs +read/write information. In hindsight it would have been better to make +it a char *mode as in fopen/freopen. Flags are ignored and the +FILE * is opened in same mode as the PerlIO *. -The fact that such a FILE * has been 'exported' is recorded, and may -affect future PerlIO operations on the original PerlIO *. - -Calling this function repeatedly will create a FILE * on each call. - -=item B<PerlIO_findFILE(f)> +The fact that such a FILE * has been 'exported' is recorded, (normally by +pushing a new :stdio "layer" onto the PerlIO *), which may affect future +PerlIO operations on the original PerlIO *. +You should not call C<fclose()> on the file unless you call +C<PerlIO_releaseFILE()> to disassociate it from the the PerlIO *. -Returns a native FILE * used by a stdio layer. If there is none, it -will create one with PerlIO_exportFILE. +Calling this function repeatedly will create a FILE * on each call +(and will push an :stdio layer each time as well). =item B<PerlIO_releaseFILE(p,f)> @@ -333,7 +340,13 @@ Calling PerlIO_releaseFILE informs PerlIO that all use of FILE * is complete. It is removed from list of 'exported' FILE *s, and associated PerlIO * should revert to original behaviour. -(Currently a noop.) +=item B<PerlIO_findFILE(f)> + +Returns a native FILE * used by a stdio layer. If there is none, it +will create one with PerlIO_exportFILE. In either case the FILE * +should be considered at belonging to PerlIO subsystem and should +only be closed by calling C<PerlIO_close()>. + =back diff --git a/pod/perlxstut.pod b/pod/perlxstut.pod index a697ecb7d1..c7723af887 100644 --- a/pod/perlxstut.pod +++ b/pod/perlxstut.pod @@ -1229,20 +1229,40 @@ The real work is done in the standard typemap. B<But> you loose all the fine stuff done by the perlio layers. This calls the stdio function C<fputs()>, which knows nothing about them. +For PerlIO *'s, there considered to be three kinds in the +standard typemap C<InputStream> (T_IN), C<InOutStream> (T_INOUT) and +C<OutputStream> (T_OUT), a bare C<PerlIO *> is considered a T_INOUT. +If it matters in your code (see below for why it might) #define or typedef +one of the specific names and use that as the type in your XS file. + +For streams coming I<from> perl the main difference is that +C<OutputStream> will get the output PerlIO * - which may make +a difference on a socket. + +For streams being handed I<to> perl a new file handle is created +(i.e. a reference to a new glob) and associated with the PerlIO * +provided. If the read/write state of the PerlIO * is not correct then you +may get errors or warnings from when the file handle is used. +So if you opened the PerlIO * as "w" it should really be an +C<OutputStream> if open as "r" it should be an C<InputStream>. + Now, suppose you want to use perlio layers in your XS. We'll use the perlio C<PerlIO_puts()> function as an example. -For PerlIO *'s, we need a typemap because the standard typemap does -not provide C<PerlIO *>: +In the C part of the XS file (above the first MODULE line) you +have + + #define OutputStream PerlIO * + or + typedef PerlIO * OutputStream; - PerlIO * T_INOUT And this is the XS code: int perlioputs(s, stream) char * s - PerlIO * stream + OutputStream stream CODE: RETVAL = PerlIO_puts(stream, s); OUTPUT: @@ -1270,6 +1290,10 @@ for a stdio C<FILE *>: OUTPUT: RETVAL +(We also using bare PerlIO * as the type - so we get the I<input> +PerlIO * of a socket - if this is undesirable use typedef or #define +as above.) + Note: C<PerlIO_findFILE()> will search the layers for a stdio layer. If it can't find one, it will call C<PerlIO_exportFILE()> to generate a new stdio C<FILE>. Please only call C<PerlIO_exportFILE()> if @@ -1281,10 +1305,6 @@ generated by C<PerlIO_exportFILE()>. This applies to the perlio system only. For versions before 5.7, C<PerlIO_exportFILE()> is equivalent to C<PerlIO_findFILE()>. - - -Getting fd's from filehandles - =head2 Troubleshooting these Examples As mentioned at the top of this document, if you are having problems with @@ -1335,7 +1355,8 @@ Jeff Okamoto <F<okamoto@corp.hp.com>> Reviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig, and Tim Bunce. -PerlIO material contributed by Lupe Christoph. +PerlIO material contributed by Lupe Christoph, with some clarification +by Nick Ing-Simmons. =head2 Last Changed |