Oops. The patch helps.
-Melvin
diff -urN tmp/parrot/MANIFEST parrot/MANIFEST
--- tmp/parrot/MANIFEST Tue Jan 1 11:58:13 2002
+++ parrot/MANIFEST Tue Jan 1 16:40:01 2002
@@ -79,6 +79,8 @@
include/parrot/trace.h
include/parrot/unicode.h
interpreter.c
+io/io.c
+io/io_os.c
jit/i386/core.jit
jit/i386/lib.jit
jit/i386/string.jit
diff -urN tmp/parrot/Makefile.in parrot/Makefile.in
--- tmp/parrot/Makefile.in Tue Jan 1 15:11:57 2002
+++ parrot/Makefile.in Tue Jan 1 15:19:24 2002
@@ -73,12 +73,14 @@
CHARTYPE_O_FILES = chartypes/unicode$(O) chartypes/usascii$(O)
+IO_O_FILES = io/io$(O) io/io_os$(O)
+
INTERP_O_FILES = global_setup$(O) interpreter$(O) parrot$(O) register$(O) \
core_ops$(O) core_ops_prederef$(O) memory$(O) packfile$(O) stacks$(O) \
string$(O) encoding$(O) chartype$(O) runops_cores$(O) trace$(O) pmc$(O) key$(O) \
platform$(O) ${jit_o} resources$(O)
-O_FILES = $(INTERP_O_FILES) $(CLASS_O_FILES) $(ENCODING_O_FILES) $(CHARTYPE_O_FILES)
+O_FILES = $(INTERP_O_FILES) $(IO_O_FILES) $(CLASS_O_FILES) $(ENCODING_O_FILES)
+$(CHARTYPE_O_FILES)
###############################################################################
diff -urN tmp/parrot/core.ops parrot/core.ops
--- tmp/parrot/core.ops Tue Jan 1 12:22:54 2002
+++ parrot/core.ops Tue Jan 1 16:22:35 2002
@@ -73,12 +73,21 @@
########################################
+=item B<close>(p)
+
+Close IO stream $1.
+
=item B<close>(i|ic)
Close file opened on file descriptor $1.
=cut
+inline op close(p) {
+ PIO_close(interpreter, (ParrotIO*)($1->data));
+ goto NEXT();
+}
+
inline op close(i|ic) {
fclose((FILE *)$1);
goto NEXT();
@@ -111,6 +120,10 @@
########################################
+=item B<open>(p, s|sc, s|sc)
+
+Open file named $2 with Perl style mode string specified in $3, and
+create the IO stream PMC into $1.
=item B<open>(i, s|sc)
@@ -124,6 +137,18 @@
=cut
+inline op open(p, s|sc, s|sc) {
+ ParrotIO * io;
+ STRING *path = $2;
+ STRING *mode = $3;
+ io = PIO_open(interpreter, path->bufstart, mode->bufstart);
+ if(!io) {
+ /* FIXME: Handle error */
+ }
+ $1 = new_io_pmc(interpreter, io);
+ goto NEXT();
+}
+
inline op open(i, s|sc) {
if (! ($1 = (INTVAL)fopen(($2)->bufstart, "r+"))) {
perror("Can't open");
@@ -222,6 +247,8 @@
=item B<print>(i|ic, p)
+=item B<print>(p, s|sc)
+
Print $2 to the file on $1. (0, 1, and 2 correspond to stdin, stdout,
and stderr)
@@ -247,6 +274,16 @@
goto NEXT();
}
+op print(p, s|sc) {
+ ParrotIO * io;
+ STRING *s = $2;
+ io = (ParrotIO*)($1->data);
+ if (s && string_length(s) && io) {
+ PIO_puts(interpreter, io, (const char *)s->bufstart);
+ }
+ goto NEXT();
+}
+
op print(p) {
PMC *p = $1;
STRING *s = (p->vtable->get_string(interpreter, p));
@@ -325,6 +362,21 @@
}
goto NEXT();
}
+
+
+########################################
+
+=item B<puts>(s|sc)
+
+Print $1 to standard output stream
+
+op puts(s|sc) {
+ STRING *s = $1;
+ if (s && string_length(s)) {
+ PIO_puts(interpreter, pio_stdout, (const char *) s->bufstart);
+ }
+ goto NEXT();
+}
########################################
diff -urN tmp/parrot/include/parrot/io.h parrot/include/parrot/io.h
--- tmp/parrot/include/parrot/io.h Mon Sep 17 21:16:59 2001
+++ parrot/include/parrot/io.h Tue Jan 1 16:38:23 2002
@@ -3,17 +3,221 @@
* CVS Info
* $Id: io.h,v 1.1 2001/09/18 01:16:59 gregor Exp $
* Overview:
- * IO operations header
+ * Parrot IO subsystem
* Data Structure and Algorithms:
* History:
+ * Originally written by Melvin Smith
* Notes:
* References:
+ * Some ideas and goals from Perl5.7 and Nick Ing-Simmons' work
*/
#if !defined(PARROT_IO_H_GUARD)
#define PARROT_IO_H_GUARD
-#define Init_IO(x)
+#include "parrot/parrot.h"
+
+#ifndef SSIZE_MAX
+#define SSIZE_MAX 8192
+#endif
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+
+/* Average block size of most systems (usually varies from 2k-8k),
+ * later we can add some config to query it from the system at
+ * build time (struct stat.st_blksize maybe).
+ */
+#define PIO_BLKSIZE 4096
+#define PIO_LINEBUFSIZE 256
+
+
+enum {
+ PIO_TYPE_FILE,
+ PIO_TYPE_PIPE,
+ PIO_TYPE_SOCKET,
+ PIO_TYPE_MAX
+};
+
+enum {
+ PIO_BUFTYPE_NONE = 0,
+ PIO_BUFTYPE_FULL,
+ PIO_BUFTYPE_LINE,
+ PIO_BUFTYPE_MAX
+};
+
+
+typedef struct _ParrotIOLayerAPI ParrotIOLayerAPI;
+typedef struct _ParrotIOLayer ParrotIOLayer;
+typedef struct _ParrotIOFilter ParrotIOFilter;
+typedef struct _ParrotIOBuf ParrotIOBuf;
+typedef struct _ParrotIO ParrotIO;
+
+/* This is temporary until subs/code refs are done..*/
+typedef void * DummyCodeRef;
+
+
+struct _ParrotIOBuf {
+ size_t bufsize;
+ unsigned char * buf;
+ unsigned char * head;
+};
+
+struct _ParrotIO {
+ INTVAL fd; /* Low level OS descriptor */
+ INTVAL mode; /* Read/Write/etc. */
+ INTVAL flags;
+ INTVAL iotype; /* Type of stream is this */
+ off_t filepos; /* Current real file pointer */
+ INTVAL buftype;
+ ParrotIOBuf in;
+ ParrotIOBuf out;
+ ParrotIOLayer * stack;
+ /* ParrotIOFilter * filters; */
+};
+
+struct _ParrotIOLayer {
+ void * this; /* Instance specific data */
+ const char * name;
+ INTVAL flags;
+ ParrotIOLayerAPI * api;
+ ParrotIOLayer * up;
+ ParrotIOLayer * down;
+};
+
+#define PIO_DOWNLAYER(x) x->down
+#define PIO_UPLAYER(x) x->up
+
+/*
+ * Terminal layer can't be pushed on top of other layers;
+ * vice-versa, non-terminal layers be pushed on an empty io stack
+ * An OS layer would be a terminal layer, non-terminals might be
+ * buffering, translation, compression or encryption layers.
+ */
+#define PIO_L_TERMINAL 0x0001
+#define PIO_L_FASTGETS 0x0002
+
+
+/* Others to come */
+extern ParrotIOLayer pio_os_layer;
+#ifdef WIN32
+/*extern ParrotIOLayer pio_win32_layer; */
+#endif
+
+/* This is list of valid layers */
+extern ParrotIOLayer * pio_registered_layers;
+
+/* This is the actual (default) layer stack which is used for IO */
+extern ParrotIOLayer * pio_default_stack;
+
+
+#ifndef theINTERP
+# define theINTERP struct Parrot_Interp * interpreter
+#endif
+
+
+/*
+ * By default, any layer not implementing an interface (ie. leaving
+ * null value for a function) implicitly passes calls to the
+ * next layer. To override or shadow an API the layer must implement
+ * the specific call.
+ */
+struct _ParrotIOLayerAPI {
+ INTVAL (*Init)(theINTERP, ParrotIOLayer * l);
+ ParrotIOLayer * (*New)(ParrotIOLayer * proto);
+ void (*Delete)(ParrotIOLayer * l);
+ INTVAL (*Pushed)(ParrotIOLayer * l, ParrotIO * io);
+ INTVAL (*Popped)(ParrotIOLayer * l, ParrotIO * io);
+ ParrotIO * (*Open)(theINTERP, ParrotIOLayer * l,
+ const char * name, const char * mode);
+ ParrotIO * (*Open2)(theINTERP, ParrotIOLayer * l,
+ const char * name, const char * mode,
+ int perm);
+ ParrotIO * (*Open3)(theINTERP, ParrotIOLayer * l,
+ const char * name, const char * mode,
+ int perm, ParrotIO * io);
+ ParrotIO * (*Open_ASync)(theINTERP, ParrotIOLayer * l,
+ const char * name, const char * mode,
+ DummyCodeRef *);
+ ParrotIO * (*FDOpen)(theINTERP, ParrotIOLayer * l,
+ INTVAL fd, const char * name);
+ INTVAL (*Close)(theINTERP, ParrotIOLayer * l,
+ ParrotIO * io);
+ size_t (*Write)(theINTERP, ParrotIOLayer * l,
+ ParrotIO * io, const void * buf,
+ size_t len);
+ size_t (*Write_ASync)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, void * buf, size_t len,
+ DummyCodeRef *);
+ size_t (*Read)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, void * buf, size_t len);
+ size_t (*Read_ASync)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, void * buf, size_t len,
+ DummyCodeRef *);
+ INTVAL (*Flush)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io);
+ INTVAL (*Seek)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, off_t offset,
+ INTVAL whence);
+ off_t (*Tell)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io);
+ INTVAL (*SetBuf)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, INTVAL bufsize);
+ INTVAL (*SetLineBuf)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io);
+ INTVAL (*GetCount)(theINTERP, ParrotIOLayer * layer);
+ INTVAL (*Fill)(theINTERP, ParrotIOLayer * layer);
+ INTVAL (*PutS)(theINTERP, ParrotIOLayer * l,
+ ParrotIO * io, const char * s);
+ INTVAL (*GetS)(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, char * s, INTVAL maxlen);
+};
+
+
+/* io.c - If you add new layers, register them in init_layers() */
+extern void PIO_init(theINTERP);
+extern INTVAL PIO_init_stacks(theINTERP);
+extern INTVAL PIO_push_layer(ParrotIOLayer *, ParrotIO *);
+extern ParrotIOLayer * PIO_pop_layer(ParrotIO *);
+extern ParrotIOLayer * PIO_copy_stack(ParrotIOLayer *);
+
+
+extern ParrotIO * new_io_header(struct Parrot_Interp *, INTVAL,
+ INTVAL, INTVAL);
+extern struct PMC * new_io_pmc(struct Parrot_Interp *, ParrotIO *);
+extern void free_io_header(ParrotIO *);
+
+extern INTVAL PIO_base_init(theINTERP, ParrotIOLayer * proto);
+extern ParrotIOLayer * PIO_base_new_layer(ParrotIOLayer * proto);
+extern void PIO_base_delete_layer(ParrotIOLayer * proto);
+
+extern ParrotIO * PIO_open(theINTERP, const char *, const char *);
+extern ParrotIO * PIO_fdopen(theINTERP, INTVAL, const char *);
+extern INTVAL PIO_close(theINTERP, ParrotIO *);
+extern void PIO_flush(theINTERP, ParrotIO *);
+extern INTVAL PIO_read(theINTERP, ParrotIO *, void *, size_t);
+extern INTVAL PIO_write(theINTERP, ParrotIO *, void *, size_t);
+extern INTVAL PIO_setbuf(theINTERP, ParrotIO *, INTVAL);
+extern INTVAL PIO_puts(theINTERP, ParrotIO *, const char *);
+
+#define Init_IO(x) PIO_init(x)
+
+
+
+extern ParrotIO * pio_stdin;
+extern ParrotIO * pio_stdout;
+extern ParrotIO * pio_stderr;
+
#endif
diff -urN tmp/parrot/io/io.c parrot/io/io.c
--- tmp/parrot/io/io.c Wed Dec 31 19:00:00 1969
+++ parrot/io/io.c Tue Jan 1 16:34:40 2002
@@ -0,0 +1,408 @@
+/* io.c
+ * Copyright: (When this is determined...it will go here)
+ * CVS Info
+ * Overview:
+ * This is the Parrot IO subsystem API. Generic IO stuff
+ * goes here, each specific layer goes in its own file...
+ * (io_os, io_buf, io_utf8, etc.)
+ * Data Structure and Algorithms:
+ * Uses the IO PMC defined in io.h
+ * Uses ParrotIO structs in io.h
+ * History:
+ * Initially written by Melvin Smith
+ * Notes:
+ * 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
+ * References:
+ * Some ideas and goals from Perl5.7 and Nick Ing-Simmons' work
+ */
+
+#include "parrot/parrot.h"
+
+
+/* This is list of valid layers */
+ParrotIOLayer * pio_registered_layers;
+
+/* This is the default stack used for IO */
+ParrotIOLayer * pio_default_stack;
+
+/* The standard streams */
+ParrotIO * pio_stdin;
+ParrotIO * pio_stdout;
+ParrotIO * pio_stderr;
+
+
+PMC * new_io_pmc(theINTERP, ParrotIO * io) {
+ PMC * new_pmc;
+ new_pmc = new_pmc_header(interpreter);
+ new_pmc->data = io;
+ new_pmc->vtable = YOU_LOSE_VTABLE;
+ return new_pmc;
+}
+
+ParrotIO * new_io_header(theINTERP, INTVAL iotype, INTVAL flags,
+ INTVAL mode) {
+ ParrotIO * new_io;
+ new_io = (ParrotIO *)malloc(sizeof(ParrotIO));
+ new_io->flags = flags;
+ new_io->mode = mode;
+ new_io->iotype = iotype;
+ new_io->stack = pio_default_stack;
+ /*new_io->buftype = PIO_BUFTYPE_FULL; */
+ /*new_io->filepos = -1; */
+ new_io->in.buf = NULL;
+ new_io->in.head = NULL;
+ new_io->out.buf = NULL;
+ new_io->out.head = NULL;
+ return new_io;
+}
+
+void free_io_header(ParrotIO *io) {
+ if( io->in.buf )
+ free(io->in.buf);
+ if( io->out.buf )
+ free(io->out.buf);
+ free(io);
+}
+
+
+/*
+ * Initialize some stuff.
+ */
+void PIO_init(theINTERP) {
+ int err;
+
+ /* Init IO stacks before creating any handles */
+ if((err = PIO_init_stacks(interpreter)) != 0) {
+ abort();
+ }
+
+ /*
+ * Create our STDIN, STDOUT and STDERR handles
+ */
+ pio_stdin = PIO_fdopen(interpreter, STDIN_FILENO, "<");
+ pio_stdout = PIO_fdopen(interpreter, STDOUT_FILENO, ">");
+ pio_stderr = PIO_fdopen(interpreter, STDERR_FILENO, ">");
+
+ if( !pio_stdin || !pio_stderr || !pio_stdout ) {
+ abort();
+ }
+
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+ PIO_puts(interpreter, pio_stderr,
+ "PIO: IO system initialized.\n");
+ }
+}
+
+
+/*
+ * Initialize the default IO stack(s)
+ */
+INTVAL PIO_init_stacks(theINTERP) {
+ ParrotIOLayer * p;
+ PIO_push_layer(&pio_os_layer, NULL);
+ /*PIO_push_layer(&pio_stdio_layer, NULL);*/
+
+ for(p=pio_default_stack; p; p=p->down) {
+ if( p->api->Init ) {
+ if((*p->api->Init)(interpreter, p) != 0) {
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+#if 0
+ fprintf(stderr,
+ "Parrot IO: Failed init layer(%s).\n",
+p->name);
+#endif
+ /* abort(); */
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Init routine called once for each layer at interpreter creation
+ * time. This is similar to a Perl module INIT {} block.
+ */
+INTVAL PIO_base_init(theINTERP, ParrotIOLayer * proto) {
+ return 0;
+}
+
+/*
+ * ParrotIOLayer constructor with optional copy
+ */
+ParrotIOLayer * PIO_base_new_layer(ParrotIOLayer * proto) {
+ ParrotIOLayer * new_layer;
+
+ new_layer = mem_sys_allocate(sizeof(ParrotIOLayer));
+ if( proto ) {
+ /* FIXME: Flag here to indicate whether to free strings */
+ new_layer->name = proto->name;
+ new_layer->flags = proto->flags;
+ new_layer->api = proto->api;
+ } else {
+ new_layer->name = NULL;
+ new_layer->flags = 0;
+ new_layer->api = NULL;
+ }
+ new_layer->this = 0;
+ new_layer->up = NULL;
+ new_layer->down = NULL;
+ return new_layer;
+}
+
+
+/*
+ * ParrotIOLayer object destructor
+ */
+void PIO_base_delete_layer(ParrotIOLayer * layer) {
+ if( layer != NULL )
+ free(layer);
+}
+
+
+/*
+ * Push a layer onto an IO object or the default stack
+ */
+INTVAL PIO_push_layer(ParrotIOLayer * layer, ParrotIO * io) {
+ if( !layer )
+ return -1;
+ if( io ) {
+ if( !io->stack
+ && (layer->flags & PIO_L_TERMINAL) == 0 ) {
+ /* Error( 1st layer must be terminal) */
+ return -1;
+ }
+ layer->down = io->stack;
+ if( io->stack )
+ io->stack->up = layer;
+ io->stack = layer;
+ if( layer->api->Pushed )
+ (*layer->api->Pushed)(layer, io);
+ } else {
+ if( !pio_default_stack
+ && (layer->flags & PIO_L_TERMINAL) == 0 ) {
+ /* Error( 1st layer must be terminal) */
+ return -1;
+ }
+ layer->down = pio_default_stack;
+ if( pio_default_stack )
+ pio_default_stack->up = layer;
+ pio_default_stack = layer;
+ return 0;
+ }
+ return -1;
+}
+
+
+/*
+ * Pop a layer from an IO object or the default stack
+ */
+ParrotIOLayer * PIO_pop_layer(ParrotIO * io) {
+ ParrotIOLayer * layer;
+ if( io ) {
+ layer = io->stack;
+ if( layer ) {
+ io->stack = layer->down;
+ io->stack->up = 0;
+ layer->up = 0;
+ layer->down = 0;
+ if( layer->api->Popped )
+ (*layer->api->Popped)(layer, io);
+ return layer;
+ }
+ return layer;
+ }
+ /* Null io object - use default stack */
+ else {
+ layer = pio_default_stack;
+ if( layer ) {
+ pio_default_stack = layer->down;
+ pio_default_stack->up = NULL;
+ layer->up = 0;
+ layer->down = 0;
+ return layer;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Primarily used to copy the default IO stack for a new
+ * IO object. Later we will do some funky copy-on-write stuff.
+ */
+ParrotIOLayer * PIO_copy_stack( ParrotIOLayer * stack ) {
+ ParrotIOLayer * new_stack;
+ ParrotIOLayer ** ptr_new;
+ ParrotIOLayer * ptr_proto;
+ ParrotIOLayer * ptr_last = NULL;
+ ptr_new = &new_stack;
+ ptr_proto = stack;
+ while( ptr_proto ) {
+ *ptr_new = PIO_base_new_layer( ptr_proto );
+ (*ptr_new)->up = ptr_last;
+ ptr_proto = ptr_proto->down;
+ ptr_last = *ptr_new;
+ ptr_new = &((*ptr_new)->down);
+ }
+
+ return new_stack;
+}
+
+
+/*
+ * Generic top level ParrotIO interface.
+ */
+
+
+/*
+ * API for controlling buffering specifics on an IO stream
+ */
+INTVAL PIO_setbuf(theINTERP, ParrotIO * io, INTVAL bufsize) {
+ ParrotIOLayer * l = io->stack;
+ PIO_flush(interpreter, io);
+ while(l) {
+ if(l->api->SetBuf) {
+ return (*l->api->SetBuf)(interpreter, l,
+ io, bufsize);
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+
+ return 0;
+}
+
+
+ParrotIO * PIO_open(theINTERP, const char * spath, const char * smode) {
+ ParrotIO * io;
+ ParrotIOLayer * l = pio_default_stack;
+ while(l) {
+ if(l->api->Open) {
+ io = (*l->api->Open)(interpreter, l, spath,
+ smode);
+ io->stack = pio_default_stack;
+ return io;
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ return NULL;
+}
+
+
+/*
+ * Create an IO object on an existing, open file descriptor.
+ * This is particularly used to init Parrot Standard IO onto
+ * the OS IO handles (0,1,2).
+ */
+ParrotIO * PIO_fdopen(theINTERP, INTVAL fd, const char * smode) {
+ ParrotIO * io;
+ ParrotIOLayer * l = pio_default_stack;
+ while(l) {
+ if(l->api->FDOpen) {
+ io = (*l->api->FDOpen)(interpreter, l, fd,
+ smode);
+ io->stack = pio_default_stack;
+ return io;
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ return NULL;
+}
+
+
+INTVAL PIO_close(theINTERP, ParrotIO * io) {
+ if( io ) {
+ ParrotIOLayer * l = io->stack;
+ while(l) {
+ if(l->api->Close) {
+ PIO_flush(interpreter, io);
+ (*l->api->Close)(interpreter, l, io);
+ return;
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ }
+ return 0;
+}
+
+
+void PIO_flush(theINTERP, ParrotIO * io) {
+ if( io ) {
+ ParrotIOLayer * l = io->stack;
+ while(l) {
+ if( l->api->Flush ) {
+ (*l->api->Flush)(interpreter, l, io);
+ return;
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ }
+}
+
+
+/*
+ * Iterate down the stack to the first layer implementing "Read" API
+ */
+INTVAL PIO_read(theINTERP, ParrotIO * io, void * buffer, size_t len) {
+ if( io ) {
+ ParrotIOLayer * l = io->stack;
+ while(l) {
+ if( l->api->Read ) {
+ return (*l->api->Read)(interpreter,
+ l, io, buffer, len);
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Iterate down the stack to the first layer implementing "Write" API
+ */
+INTVAL PIO_write(theINTERP, ParrotIO * io, void * buffer, size_t len) {
+ if( io ) {
+ ParrotIOLayer * l = io->stack;
+ while(l) {
+ if( l->api->Write ) {
+ return (*l->api->Write)(interpreter,
+ l, io, buffer, len);
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ }
+
+ return 0;
+}
+
+
+INTVAL PIO_puts(theINTERP, ParrotIO * io, const char * s) {
+ if( io ) {
+ ParrotIOLayer * l = io->stack;
+ while(l) {
+ if( l->api->PutS ) {
+ return (*l->api->PutS)(interpreter,
+ l, io, s);
+ }
+ l = PIO_DOWNLAYER(l);
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/
diff -urN tmp/parrot/io/io_os.c parrot/io/io_os.c
--- tmp/parrot/io/io_os.c Wed Dec 31 19:00:00 1969
+++ parrot/io/io_os.c Tue Jan 1 16:36:55 2002
@@ -0,0 +1,282 @@
+/* io_os.c
+ * Copyright: (When this is determined...it will go here)
+ * CVS Info
+ * Overview:
+ * This is the Parrot IO UNIX layer. May be changed to be
+ * the "generic OS" layer when we see how much we can share
+ * between platforms without smudging...
+ * For UNIX systems (and some others) this is the low level
+ * OS layer (unbuffered).
+ * Data Structure and Algorithms:
+ * History:
+ * Initially written by Melvin Smith
+ * Notes:
+ * References:
+ */
+
+#include "parrot/parrot.h"
+
+/* Defined at bottom */
+extern ParrotIOLayerAPI pio_os_layer_api;
+
+ParrotIOLayer pio_os_layer = {
+ NULL,
+ "os",
+ PIO_L_TERMINAL,
+ &pio_os_layer_api,
+ 0, 0
+};
+
+
+/*
+ * Currently keeping layer prototypes local to each layer
+ * file.
+ */
+
+ParrotIO * PIO_os_open(theINTERP, ParrotIOLayer * layer,
+ const char * spath, const char * smode);
+ParrotIO * PIO_os_fdopen(theINTERP, ParrotIOLayer * layer,
+ INTVAL fd, const char * smode);
+INTVAL PIO_os_close(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io);
+void PIO_os_flush(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io);
+size_t PIO_os_read(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, void * buffer, size_t len);
+size_t PIO_os_write(theINTERP, ParrotIOLayer * layer,
+ ParrotIO * io, const void * buffer, size_t len);
+INTVAL PIO_os_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+ const char * s);
+
+
+
+
+/*
+ * Open modes (read, write, append, etc.) are done in pseudo-Perl
+ * style using <, >, etc.
+ */
+ParrotIO * PIO_os_open(theINTERP, ParrotIOLayer * layer,
+ const char * spath, const char * smode) {
+ ParrotIO * io;
+ int flags, type, mode, fd;
+ const char * modeptr;
+ type = PIO_TYPE_FILE;
+ flags = 0;
+ mode = DEFAULT_OPEN_MODE;
+ modeptr = smode;
+#if 0
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+ fprintf(stderr, "PIO_os_open: %s, %s\n",
+ spath, modeptr);
+ }
+#endif
+ /* Set mode flags - <, >, >>, +<, +> */
+ /* add ? and ! for block/non-block */
+ switch(*modeptr) {
+ case '+':
+ flags = O_RDWR;
+ break;
+ case '<':
+ flags = O_RDONLY;
+ break;
+ case '>':
+ flags = O_WRONLY | O_CREAT;
+ if( *(++modeptr) == '>')
+ flags |= O_APPEND;
+ else if(*modeptr != 0)
+ return 0;
+ else flags |= O_TRUNC;
+ break;
+ default:
+ return 0;
+ }
+
+ if((fd = open((const char *)spath, flags, mode)) != -1 ){
+ io = new_io_header(interpreter, type, flags, mode);
+ io->fd = fd;
+ return io;
+ } else {
+ /* Error.. */
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+ char * errstr = strerror( errno );
+#if 0
+ fprintf(stderr, "PIO_os_open: %s",
+ errstr );
+#endif
+ }
+ return 0;
+ }
+
+ return 0;
+}
+
+
+ParrotIO * PIO_os_fdopen(theINTERP, ParrotIOLayer * layer,
+ INTVAL fd, const char * smode) {
+ ParrotIO * io;
+ INTVAL flags, mode;
+ flags = 0;
+ mode = 0;
+
+ /* FIXME - Check file handle specifics, validity */
+ /* Need to make this portable, I haven't checked this
+ * on non-UNIX.
+ */
+#if 1
+ /* Get descriptor flags */
+ if((flags = fcntl(fd, F_GETFL, 0)) >= 0) {
+ /*int accmode = flags & O_ACCMODE;*/
+ /* Check other flags (APPEND, ASYNC, etc) */
+ } else {
+ /* Probably invalid descriptor */
+ return NULL;
+ }
+#endif
+ io = new_io_header(interpreter, PIO_TYPE_FILE, flags, mode);
+ io->fd = fd;
+ io->buftype = PIO_BUFTYPE_NONE;
+ return io;
+}
+
+
+INTVAL PIO_os_close(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+#if 0
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+ fprintf(stderr, "PIO_os_close: %d\n", (int)io->fd );
+ }
+#endif
+ close( io->fd );
+ io->fd = -1;
+ return 0;
+}
+
+
+/* At lowest layer all we can do for flush is ask kernel to sync().
+ * How portable is fsync() ? It is POSIX at least.
+ * Can also be accomplished by O_SYNC on file handle.
+ */
+void PIO_os_flush(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+#if 0
+ /* UNIX and VMS have fsync, does win32? */
+ fsync(io->fd);
+#endif
+}
+
+
+size_t PIO_os_read(theINTERP, ParrotIOLayer * layer, ParrotIO * io,
+ void * buffer, size_t len) {
+ int bytes;
+ for(;;) {
+ bytes = read(io->fd, buffer, len);
+ if( bytes > 0 )
+ return bytes;
+ else if( bytes < 0 ) {
+ switch(errno) {
+ case EINTR: continue;
+ default: return bytes;
+ }
+ } else {
+ /* Set EOF flag */
+ return bytes;
+ }
+ }
+ return bytes;
+}
+
+
+size_t PIO_os_write(theINTERP, ParrotIOLayer * layer, ParrotIO * io,
+ const void * buffer, size_t len) {
+ int err;
+ int bytes;
+ size_t to_write;
+ const char * ptr;
+#if 0
+ if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+ fprintf(stderr, "ParrotIO_os_write(fd=%d): %d bytes\n",
+ io->fd, len );
+ }
+#endif
+ ptr = buffer;
+ to_write = len;
+ bytes = 0;
+
+ write_through:
+ while(to_write > 0) {
+ if((err = write(io->fd, ptr, to_write)) >= 0 ) {
+ ptr += err;
+ to_write -= err;
+ bytes += err;
+#if 0
+ fprintf(stderr, "ParrotIO_os_write: wrote %d
+bytes\n", err );
+#endif
+ } else {
+ switch(errno) {
+ case EINTR: goto write_through;
+#ifdef EAGAIN
+ case EAGAIN: return bytes;
+#endif
+ }
+ }
+ }
+ return bytes;
+}
+
+
+INTVAL PIO_os_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+ const char * s) {
+ size_t len;
+ len = strlen(s);
+ if( len > 0 ) {
+ size_t sz;
+ sz = PIO_os_write(interpreter, l, io, s, len);
+ if( sz < len ) {
+ return -1;
+ } else {
+ return len;
+ }
+ }
+
+ return -1;
+}
+
+
+
+ParrotIOLayerAPI pio_os_layer_api = {
+ PIO_base_init,
+ PIO_base_new_layer,
+ PIO_base_delete_layer,
+ NULL,
+ NULL,
+ PIO_os_open,
+ NULL,
+ NULL,
+ NULL,
+ PIO_os_fdopen,
+ PIO_os_close,
+ PIO_os_write,
+ NULL,
+ PIO_os_read,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ PIO_os_puts,
+ NULL
+};
+
+
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/
+