add IO-1.20; mess with t/lib/io_*.t in an attempt to
[p5sagit/p5-mst-13.2.git] / ext / IO / IO.xs
CommitLineData
cf7fe8a2 1/*
2 * Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
3 * This program is free software; you can redistribute it and/or
4 * modify it under the same terms as Perl itself.
5 */
6
8add82fc 7#include "EXTERN.h"
760ac839 8#define PERLIO_NOT_STDIO 1
8add82fc 9#include "perl.h"
10#include "XSUB.h"
cf7fe8a2 11#include "poll.h"
8add82fc 12#ifdef I_UNISTD
13# include <unistd.h>
14#endif
cf7fe8a2 15#if defined(I_FCNTL) || defined(HAS_FCNTL)
760ac839 16# include <fcntl.h>
17#endif
8add82fc 18
2a0cf753 19#ifdef PerlIO
8add82fc 20typedef int SysRet;
760ac839 21typedef PerlIO * InputStream;
22typedef PerlIO * OutputStream;
2a0cf753 23#else
24#define PERLIO_IS_STDIO 1
25typedef int SysRet;
26typedef FILE * InputStream;
27typedef FILE * OutputStream;
28#endif
8add82fc 29
cf7fe8a2 30#include "patchlevel.h"
31
32#if (PATCHLEVEL < 3) || ((PATCHLEVEL == 3) && (SUBVERSION < 22))
33 /* before 5.003_22 */
34# define MY_start_subparse(fmt,flags) start_subparse()
35#else
36# if (PATCHLEVEL == 3) && (SUBVERSION == 22)
37 /* 5.003_22 */
38# define MY_start_subparse(fmt,flags) start_subparse(flags)
39# else
40 /* 5.003_23 onwards */
41# define MY_start_subparse(fmt,flags) start_subparse(fmt,flags)
42# endif
43#endif
44
45#ifndef gv_stashpvn
46#define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
47#endif
48
8add82fc 49static int
cf7fe8a2 50not_here(s)
51char *s;
8add82fc 52{
53 croak("%s not implemented on this architecture", s);
54 return -1;
55}
56
cf7fe8a2 57#ifndef newCONSTSUB
58/*
59 * Define an XSUB that returns a constant scalar. The resulting structure is
60 * identical to that created by the parser when it parses code like :
61 *
62 * sub xyz () { 123 }
63 *
64 * This allows the constants from the XSUB to be inlined.
65 *
66 * !!! THIS SHOULD BE ADDED INTO THE CORE CODE !!!!
67 *
68 */
69
70static void
71newCONSTSUB(stash,name,sv)
72 HV *stash;
73 char *name;
74 SV *sv;
8add82fc 75{
cf7fe8a2 76#ifdef dTHR
77 dTHR;
8add82fc 78#endif
cf7fe8a2 79 U32 oldhints = hints;
80 HV *old_cop_stash = curcop->cop_stash;
81 HV *old_curstash = curstash;
82 line_t oldline = curcop->cop_line;
83 curcop->cop_line = copline;
84
85 hints &= ~HINT_BLOCK_SCOPE;
86 if(stash)
87 curstash = curcop->cop_stash = stash;
88
89 newSUB(
90 MY_start_subparse(FALSE, 0),
91 newSVOP(OP_CONST, 0, newSVpv(name,0)),
92 newSVOP(OP_CONST, 0, &sv_no), /* SvPV(&sv_no) == "" -- GMB */
93 newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
94 );
95
96 hints = oldhints;
97 curcop->cop_stash = old_cop_stash;
98 curstash = old_curstash;
99 curcop->cop_line = oldline;
100}
8add82fc 101#endif
cf7fe8a2 102
103#ifndef PerlIO
104#define PerlIO_fileno(f) fileno(f)
8add82fc 105#endif
cf7fe8a2 106
107static int
108io_blocking(f,block)
109InputStream f;
110int block;
111{
112 int RETVAL;
113 if(!f) {
114 errno = EBADF;
115 return -1;
116 }
117#if defined(HAS_FCNTL)
118 RETVAL = fcntl(PerlIO_fileno(f), F_GETFL, 0);
119 if (RETVAL >= 0) {
120 int mode = RETVAL;
121#ifdef O_NONBLOCK
122 /* POSIX style */
123#if defined(O_NDELAY) && O_NDELAY != O_NONBLOCK
124 /* Ooops has O_NDELAY too - make sure we don't
125 * get SysV behaviour by mistake
126 */
127 RETVAL = RETVAL & O_NONBLOCK ? 0 : 1;
128
129 if ((mode & O_NDELAY) || ((block == 0) && !(mode & O_NONBLOCK))) {
130 int ret;
131 mode = (mode & ~O_NDELAY) | O_NONBLOCK;
132 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
133 if(ret < 0)
134 RETVAL = ret;
135 }
136 else if ((mode & O_NDELAY) || ((block > 0) && (mode & O_NONBLOCK))) {
137 int ret;
138 mode &= ~(O_NONBLOCK | O_NDELAY);
139 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
140 if(ret < 0)
141 RETVAL = ret;
142 }
8add82fc 143#else
cf7fe8a2 144 /* Standard POSIX */
145 RETVAL = RETVAL & O_NONBLOCK ? 0 : 1;
146
147 if ((block == 0) && !(mode & O_NONBLOCK)) {
148 int ret;
149 mode |= O_NONBLOCK;
150 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
151 if(ret < 0)
152 RETVAL = ret;
153 }
154 else if ((block > 0) && (mode & O_NONBLOCK)) {
155 int ret;
156 mode &= ~O_NONBLOCK;
157 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
158 if(ret < 0)
159 RETVAL = ret;
160 }
161#endif
8add82fc 162#else
cf7fe8a2 163 /* Not POSIX - better have O_NDELAY or we can't cope.
164 * for BSD-ish machines this is an acceptable alternative
165 * for SysV we can't tell "would block" from EOF but that is
166 * the way SysV is...
167 */
168 RETVAL = RETVAL & O_NDELAY ? 0 : 1;
169
170 if ((block == 0) && !(mode & O_NDELAY)) {
171 int ret;
172 mode |= O_NDELAY;
173 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
174 if(ret < 0)
175 RETVAL = ret;
176 }
177 else if ((block > 0) && (mode & O_NDELAY)) {
178 int ret;
179 mode &= ~O_NDELAY;
180 ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
181 if(ret < 0)
182 RETVAL = ret;
183 }
8add82fc 184#endif
cf7fe8a2 185 }
186 return RETVAL;
8add82fc 187#else
cf7fe8a2 188 return -1;
8add82fc 189#endif
8add82fc 190}
191
8add82fc 192MODULE = IO PACKAGE = IO::Seekable PREFIX = f
193
194SV *
195fgetpos(handle)
196 InputStream handle
197 CODE:
8add82fc 198 if (handle) {
199 Fpos_t pos;
2a0cf753 200#ifdef PerlIO
760ac839 201 PerlIO_getpos(handle, &pos);
2a0cf753 202#else
203 fgetpos(handle, &pos);
204#endif
8add82fc 205 ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t)));
206 }
207 else {
cf7fe8a2 208 ST(0) = &sv_undef;
8add82fc 209 errno = EINVAL;
210 }
8add82fc 211
212SysRet
213fsetpos(handle, pos)
214 InputStream handle
215 SV * pos
216 CODE:
cf7fe8a2 217 if (handle)
2a0cf753 218#ifdef PerlIO
cf7fe8a2 219 RETVAL = PerlIO_setpos(handle, (Fpos_t*)SvPVX(pos));
2a0cf753 220#else
cf7fe8a2 221 RETVAL = fsetpos(handle, (Fpos_t*)SvPVX(pos));
2a0cf753 222#endif
8add82fc 223 else {
224 RETVAL = -1;
225 errno = EINVAL;
226 }
8add82fc 227 OUTPUT:
228 RETVAL
229
230MODULE = IO PACKAGE = IO::File PREFIX = f
231
a375a877 232SV *
8add82fc 233new_tmpfile(packname = "IO::File")
234 char * packname
a375a877 235 PREINIT:
236 OutputStream fp;
237 GV *gv;
8add82fc 238 CODE:
2a0cf753 239#ifdef PerlIO
a375a877 240 fp = PerlIO_tmpfile();
2a0cf753 241#else
a375a877 242 fp = tmpfile();
2a0cf753 243#endif
a375a877 244 gv = (GV*)SvREFCNT_inc(newGVgen(packname));
245 hv_delete(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv), G_DISCARD);
246 if (do_open(gv, "+>&", 3, FALSE, 0, 0, fp)) {
6d5cdeed 247 ST(0) = sv_2mortal(newRV((SV*)gv));
a375a877 248 sv_bless(ST(0), gv_stashpv(packname, TRUE));
cf7fe8a2 249 SvREFCNT_dec(gv); /* undo increment in newRV() */
a375a877 250 }
251 else {
cf7fe8a2 252 ST(0) = &sv_undef;
a375a877 253 SvREFCNT_dec(gv);
254 }
8add82fc 255
cf7fe8a2 256MODULE = IO PACKAGE = IO::Poll
257
258void
259_poll(timeout,...)
260 int timeout;
261PPCODE:
262{
263#ifdef HAS_POLL
264 int nfd = (items - 1) / 2;
265 SV *tmpsv = NEWSV(999,nfd * sizeof(struct pollfd));
266 struct pollfd *fds = (struct pollfd *)SvPVX(tmpsv);
267 int i,j,ret;
268 for(i=1, j=0 ; j < nfd ; j++) {
269 fds[j].fd = SvIV(ST(i));
270 i++;
271 fds[j].events = SvIV(ST(i));
272 i++;
273 fds[j].revents = 0;
274 }
275 if((ret = poll(fds,nfd,timeout)) >= 0) {
276 for(i=1, j=0 ; j < nfd ; j++) {
277 sv_setiv(ST(i), fds[j].fd); i++;
278 sv_setiv(ST(i), fds[j].revents); i++;
279 }
280 }
281 SvREFCNT_dec(tmpsv);
282 XSRETURN_IV(ret);
283#else
284 not_here("IO::Poll::poll");
285#endif
286}
287
288MODULE = IO PACKAGE = IO::Handle PREFIX = io_
289
290void
291io_blocking(handle,blk=-1)
292 InputStream handle
293 int blk
294PROTOTYPE: $;$
295CODE:
296{
297 int ret = io_blocking(handle, items == 1 ? -1 : blk ? 1 : 0);
298 if(ret >= 0)
299 XSRETURN_IV(ret);
300 else
301 XSRETURN_UNDEF;
302}
303
8add82fc 304MODULE = IO PACKAGE = IO::Handle PREFIX = f
305
8add82fc 306
307int
308ungetc(handle, c)
309 InputStream handle
310 int c
311 CODE:
312 if (handle)
2a0cf753 313#ifdef PerlIO
760ac839 314 RETVAL = PerlIO_ungetc(handle, c);
2a0cf753 315#else
316 RETVAL = ungetc(c, handle);
317#endif
8add82fc 318 else {
319 RETVAL = -1;
320 errno = EINVAL;
321 }
322 OUTPUT:
323 RETVAL
324
325int
326ferror(handle)
327 InputStream handle
328 CODE:
329 if (handle)
2a0cf753 330#ifdef PerlIO
760ac839 331 RETVAL = PerlIO_error(handle);
2a0cf753 332#else
333 RETVAL = ferror(handle);
334#endif
335 else {
336 RETVAL = -1;
337 errno = EINVAL;
338 }
339 OUTPUT:
340 RETVAL
341
342int
343clearerr(handle)
344 InputStream handle
345 CODE:
346 if (handle) {
347#ifdef PerlIO
348 PerlIO_clearerr(handle);
349#else
350 clearerr(handle);
351#endif
352 RETVAL = 0;
353 }
8add82fc 354 else {
355 RETVAL = -1;
59629a13 356 errno = EINVAL;
357 }
358 OUTPUT:
359 RETVAL
360
361int
362untaint(handle)
363 SV * handle
364 CODE:
7a4c00b4 365#ifdef IOf_UNTAINT
59629a13 366 IO * io;
367 io = sv_2io(handle);
368 if (io) {
369 IoFLAGS(io) |= IOf_UNTAINT;
370 RETVAL = 0;
371 }
372 else {
7a4c00b4 373#endif
59629a13 374 RETVAL = -1;
8add82fc 375 errno = EINVAL;
7a4c00b4 376#ifdef IOf_UNTAINT
8add82fc 377 }
7a4c00b4 378#endif
8add82fc 379 OUTPUT:
380 RETVAL
381
382SysRet
383fflush(handle)
384 OutputStream handle
385 CODE:
386 if (handle)
2a0cf753 387#ifdef PerlIO
760ac839 388 RETVAL = PerlIO_flush(handle);
2a0cf753 389#else
390 RETVAL = Fflush(handle);
391#endif
8add82fc 392 else {
393 RETVAL = -1;
394 errno = EINVAL;
395 }
396 OUTPUT:
397 RETVAL
398
399void
400setbuf(handle, buf)
401 OutputStream handle
402 char * buf = SvPOK(ST(1)) ? sv_grow(ST(1), BUFSIZ) : 0;
403 CODE:
404 if (handle)
760ac839 405#ifdef PERLIO_IS_STDIO
8add82fc 406 setbuf(handle, buf);
760ac839 407#else
408 not_here("IO::Handle::setbuf");
409#endif
8add82fc 410
411SysRet
412setvbuf(handle, buf, type, size)
413 OutputStream handle
414 char * buf = SvPOK(ST(1)) ? sv_grow(ST(1), SvIV(ST(3))) : 0;
415 int type
416 int size
417 CODE:
61839fa9 418/* Should check HAS_SETVBUF once Configure tests for that */
419#if defined(PERLIO_IS_STDIO) && defined(_IOFBF)
d924de76 420 if (!handle) /* Try input stream. */
421 handle = IoIFP(sv_2io(ST(0)));
8add82fc 422 if (handle)
423 RETVAL = setvbuf(handle, buf, type, size);
424 else {
425 RETVAL = -1;
426 errno = EINVAL;
427 }
428#else
61839fa9 429 RETVAL = (SysRet) not_here("IO::Handle::setvbuf");
760ac839 430#endif
8add82fc 431 OUTPUT:
432 RETVAL
433
434
cf7fe8a2 435SysRet
436fsync(handle)
437 OutputStream handle
438 CODE:
439#ifdef HAS_FSYNC
440 if(handle)
441 RETVAL = fsync(PerlIO_fileno(handle));
442 else {
443 RETVAL = -1;
444 errno = EINVAL;
445 }
446#else
447 RETVAL = (SysRet) not_here("IO::Handle::sync");
448#endif
449 OUTPUT:
450 RETVAL
451
452
453BOOT:
454{
455 HV *stash;
456 /*
457 * constant subs for IO::Poll
458 */
459 stash = gv_stashpvn("IO::Poll", 8, TRUE);
460#ifdef POLLIN
461 newCONSTSUB(stash,"POLLIN",newSViv(POLLIN));
462#endif
463#ifdef POLLPRI
464 newCONSTSUB(stash,"POLLPRI", newSViv(POLLPRI));
465#endif
466#ifdef POLLOUT
467 newCONSTSUB(stash,"POLLOUT", newSViv(POLLOUT));
468#endif
469#ifdef POLLRDNORM
470 newCONSTSUB(stash,"POLLRDNORM", newSViv(POLLRDNORM));
471#endif
472#ifdef POLLWRNORM
473 newCONSTSUB(stash,"POLLWRNORM", newSViv(POLLWRNORM));
474#endif
475#ifdef POLLRDBAND
476 newCONSTSUB(stash,"POLLRDBAND", newSViv(POLLRDBAND));
477#endif
478#ifdef POLLWRBAND
479 newCONSTSUB(stash,"POLLWRBAND", newSViv(POLLWRBAND));
480#endif
481#ifdef POLLNORM
482 newCONSTSUB(stash,"POLLNORM", newSViv(POLLNORM));
483#endif
484#ifdef POLLERR
485 newCONSTSUB(stash,"POLLERR", newSViv(POLLERR));
486#endif
487#ifdef POLLHUP
488 newCONSTSUB(stash,"POLLHUP", newSViv(POLLHUP));
489#endif
490#ifdef POLLNVAL
491 newCONSTSUB(stash,"POLLNVAL", newSViv(POLLNVAL));
492#endif
493 /*
494 * constant subs for IO::Handle
495 */
496 stash = gv_stashpvn("IO::Handle", 10, TRUE);
497#ifdef _IOFBF
498 newCONSTSUB(stash,"_IOFBF", newSViv(_IOFBF));
499#endif
500#ifdef _IOLBF
501 newCONSTSUB(stash,"_IOLBF", newSViv(_IOLBF));
502#endif
503#ifdef _IONBF
504 newCONSTSUB(stash,"_IONBF", newSViv(_IONBF));
505#endif
506#ifdef SEEK_SET
507 newCONSTSUB(stash,"SEEK_SET", newSViv(SEEK_SET));
508#endif
509#ifdef SEEK_CUR
510 newCONSTSUB(stash,"SEEK_CUR", newSViv(SEEK_CUR));
511#endif
512#ifdef SEEK_END
513 newCONSTSUB(stash,"SEEK_END", newSViv(SEEK_END));
514#endif
515 /*
516 * constant subs for IO
517 */
518 stash = gv_stashpvn("IO", 2, TRUE);
519#ifdef EINPROGRESS
520 newCONSTSUB(stash,"EINPROGRESS", newSViv(EINPROGRESS));
521#endif
522}