io/io.c - Generic IO


The Parrot IO subsystem uses a per-interpreter stack to provide a layer-based approach to IO. Each layer implements a subset of the ParrotIOLayerAPI vtable. To find an IO function the layer stack is searched downwards until a non-NULL function pointer is found for that particular slot.

This file implements the generic functionality. Specific layers are in separate files: io/io_buf.c, io/io_stdio.c, io/io_unix.c, io/io_win32.c, and io/io_layers.c.

The ParrotIO PMC provides the class-based interface that is used in Parrot ops. The ParrotIO struct is defined in io/io_private.h.

Resource Functions ^

PMC *new_io_pmc(theINTERP, ParrotIO *io)

Creates and returns a new ParrotIO PMC.

STRING *PIO_make_io_string(Interp *, STRING **buf, size_t default_len)

Create a STRING* suitable for returning results from IO read functions. The passed in buf parameter can be either:

  1) Point to a NULL STRING
  2) Point to a real STRING
  3) Point to a fake STRING with (strstart, bufused) holding the *buffer
In case 3) the buffer or STRING must be able to hold the required amount of data. For case 1) or 2) with a NULL strstart the STRING memory gets allocated.

ParrotIOTable alloc_pio_array(int numhandles)

Called in PIO_init() to allocate an interpreter's IO handle table with room for numhandles IO handles.

int realloc_pio_array(ParrotIOTable *table, int numhandles)

Unimplemented. Simply returns -1.

ParrotIO *PIO_new(theINTERP, INTVAL iotype, INTVAL flags, INTVAL mode)

Create a new IO stream.

The values of flags and mode are set in the returned ParrotIO.

Currently iotype is unused.

void PIO_destroy(theINTERP, PMC *pmc)

Destroying the IO stream at the moment only frees the memory and removes the pointers from the PMC.

void PIO_init(theINTERP)

This is called when creating an interpreter to set up its layer stack and creates the STD* handles.

void PIO_finish(theINTERP)

Called when the interpreter is being destroyed to close down its IO resourses.

void PIO_internal_shutdown(theINTERP)

IO system destructor, called on destruction of the last interpreter.

INTVAL PIO_init_stacks(theINTERP)

Initialize the interpreter's default IO stack by pushing on the IO layers (OS-specific first).

INTVAL PIO_base_init(theINTERP, ParrotIOLayer *l)

Init routine called once for each layer at interpreter creation time. This is similar to a Perl module INIT {} block.

This default implementation does nothing. Returns 0.

Generic top-level ParrotIO interface ^

INTVAL PIO_parse_open_flags(const char *flagstr)

Parses *flagstr for Perl-style file open mode flags (<, >, >>, +<, +>) and returns the combined generic bit flags.

The low level OS layers may then interpret the generic bits differently depending on platform.

XXX BD Should this be static?

INTVAL PIO_peek(theINTERP, PMC *pmc, void *buffer)

 Iterate down the stack to the first layer implementing "Peek" API
INTVAL PIO_pioctl(theINTERP, PMC *pmc, INTVAL cmd, INTVAL arg)

General purpose interface for manipulation of IO objects and layer attributes.

Refer to the PIOCTL* values in include/parrot/io.h.

All "set" operations return 0 on success and a negative value on error. "get" operations will use the return value as the value requested, but should always be >= 0. A negative value indicates an error. This may be too limited but we will see. --Melvin

INTVAL PIO_setbuf(theINTERP, PMC *pmc, size_t bufsize)

Sets the buffer size for *pmc to bufsize. Returns 0 if the buffering was enabled.

INTVAL PIO_setlinebuf(theINTERP, PMC *pmc)

Enables line buffering for *pmc. Returns 0 if line buffering was successfully set, or already enabled.

PMC *PIO_open(theINTERP, ParrotIOLayer *layer, const char *spath, const char *sflags)

Creates and returns a ParrotIO PMC for *spath.

PMC *PIO_fdopen(theINTERP, ParrotIOLayer *layer, PIOHANDLE fd, const char *sflags)

Creates and returns a ParrotIO PMC for *spath on an existing, open file descriptor.

This is used particularly to initialize the STD* IO handles onto the OS IO handles (0,1,2).

INTVAL PIO_close(theINTERP, PMC *pmc)

Flushes, closes and destroys the ParrotIO PMC *pmc.

void PIO_flush(theINTERP, PMC *pmc)

Flushes the ParrotIO PMC *pmc.

STRING *PIO_reads(theINTERP, PMC *pmc, size_t len)

Return a new STRING* holding up to len bytes.

INTVAL PIO_read(theINTERP, PMC *pmc, void *buffer, size_t len)

Reads up to len bytes from *pmc and copys them into *buffer.

INTVAL PIO_write(theINTERP, PMC *pmc, const void *buffer, size_t len)

Writes len bytes from *buffer to *pmc.

PIOOFF_T PIO_seek(theINTERP, PMC *pmc, PIOOFF_T offset, INTVAL w)

Moves the read/write position of *pmc to offset bytes from the position indicated by w. Typically w will be 0 for the start of the file, 1 for the current position, and 2 for the end.

PIOOFF_T PIO_tell(theINTERP, PMC *pmc)

Returns the current read/write position of *pmc.


Returns a boolean value indication whether *pmc's current read/write position is EOF.

INTVAL PIO_puts(theINTERP, PMC *pmc, const char *s)

Writes *s tp *pmc. C string version.

INTVAL PIO_putps(theINTERP, PMC *pmc, STRING *s)

Writes *s tp *pmc. Parrot string version.

INTVAL PIO_fprintf(theINTERP, PMC *pmc, const char *s, ...)

Writes a C string format with varargs to *pmc.

INTVAL PIO_printf(theINTERP, const char *s, ...)

Writes a C string format with varargs to stdout.

INTVAL PIO_eprintf(theINTERP, const char *s, ...)

Writes a C string format with varargs to stderr.


Returns *pmc's file descriptor, or 0 if it is not defined.

PIO_STD* Functions ^

The PIO_STD* functions are defined using the theINTERP macro. The prototype is protected with an identity macro.


Returns the ParrotIO PMC for stdin.


Returns the ParrotIO PMC for stdout.


Returns the ParrotIO PMC for stderr.

DOD-related Functions ^

void Parrot_IOData_mark(theINTERP, ParrotIOData *piodata)

Called from trace_active_PMCs() to mark the IO data live.

Offset Functions ^

These are used to create offsets for the seek op.

PIOOFF_T PIO_make_offset(INTVAL offset)

Returns offset.

PIOOFF_T PIO_make_offset32(INTVAL hi, INTVAL lo)

hi is shifted 32 bytes to the left and ored together with lo. This allows 64-bit seeks with only 32-bit INTVALS.

PIOOFF_T PIO_make_offset_pmc(theINTERP, PMC *pmc)

Returns the return value of the get_integer vtable method on *pmc.

Networking Functions ^

INTVAL PIO_poll(theINTERP, PMC *pmc, INTVAL which, INTVAL sec, INTVAL usec)

Polls *pmc for the events in which every sec seconds + usec microseconds.

PMC *PIO_socket(theINTERP, INTVAL fam, INTVAL type, INTVAL proto)

Creates and returns a socket using the specified address family, socket type and protocol number. The returned PMC has to be checked with a boolean test to see whether the socket was successfully created.

INTVAL PIO_recv(theINTERP, PMC *pmc, STRING **buf)

Receives a message from the connected socket *pmc in *buf.

INTVAL PIO_send(theINTERP, PMC *pmc, STRING *buf)

Send the message *buf to the connected socket *pmc.

INTVAL PIO_connect(theINTERP, PMC *pmc, STRING *address)

Connect *pmc to *address.

INTVAL PIO_bind(theINTERP, PMC *pmc, STRING *address)

Binds *pmc's socket to the local address and port specified by *address.

INTVAL PIO_listen(theINTERP, PMC *pmc, INTVAL backlog)

Listen for new connections on socket *pmc.

INTVAL PIO_accept(theINTERP, PMC *pmc)

Accept a new connection and return a newly created ParrotIO socket.

INTVAL PIO_isatty(theINTERP, PMC *pmc)

Returns a boolean value indicating whether *pmc is a console/tty.


io/io_buf.c, io/io_passdown.c, io/io_stdio.c, io/io_unix.c, io/io_win32.c, io/io_private.h.


Initially written by Melvin Smith.

Some ideas and goals from Perl5.7 and Nick Ing-Simmons' work.


In future rework to use copy-on-write IO stacks rather than creating a new stack for each IO stream.

Add support for loadable layers in Parrot bytecode.