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:
+*/
+

Reply via email to