src/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, Parrot searches the layer stack downwards until it finds a non-NULL function pointer for that particular slot.

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

The ParrotIO PMC provides the class-based interface that is used in Parrot ops. The ParrotIO struct is defined in src/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)

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

  1. Point to a NULL STRING
  2. Point to a real STRING
  3. Point to a fake STRING with (strstart, bufused) holding the *buffer information.
In the third case, the buffer or STRING must be able to hold the required amount of data. For cases 1 and 2, a NULL strstart tells this function to allocate the STRING memory.

ParrotIOTable alloc_pio_array(int numhandles)

Allocates an interpreter's IO handle table with room for numhandles IO handles.

Called from PIO_init().

int realloc_pio_array(ParrotIOTable *table, int numhandles)

Unimplemented; returns -1.

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

Creates 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)

Destroys the IO stream. At the moment, this only frees the memory and removes the pointers from the PMC.

void PIO_init(theINTERP)

Sets up the interpreter's layer stack and creates the STD* handles.

Called when creating an interpreter.

void PIO_finish(theINTERP)

Closes the interpreter's IO resourses. Called during its interpreter destruction.

void PIO_internal_shutdown(theINTERP)

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

INTVAL PIO_init_stacks(theINTERP)

Initializes 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 and 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)

Iterates down the stack to the first layer implementing "Peek" API.

INTVAL PIO_pioctl(theINTERP, PMC *pmc, INTVAL cmd, INTVAL arg)

General purpose interface for manipulating 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 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 copies 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 to *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. Check the returned PMC 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. Returns -1 if it fails.

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

Sends the message *buf to the connected socket *pmc. Returns -1 if it cannot send the message.

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

Connects *pmc to *address. Returns -1 on failure.

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

Binds *pmc's socket to the local address and port specified by *address. Returns -1 on failure.

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

Listens for new connections on socket *pmc. Returns -1 on failure.

INTVAL PIO_accept(theINTERP, PMC *pmc)

Accepts a new connection and returns a newly created ParrotIO socket. Returns NULL on failure.

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 Perl 5.7 and Nick Ing-Simmons' work.


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.