Changes:

-Minor layer cleanups
-Win32 layer added (mostly stubs for now) but will be using the
  Win32 API and company rather than the unix-ish fake ones.
-stdin/stdout/stderr Win32 specific code added. Rather than use
  0,1,2, Microsoft says use GetStdHandle(), etc. so that stuff is
  there. Soon we should be able to start using these rather than
  fprintf(stderr, ...) and remove stdio linkage.

New files:

io/io_win32.c

Renamed io_os.c -> io_unix.c

-Melvin
diff -urN tmp/parrot/MANIFEST parrot/MANIFEST
--- tmp/parrot/MANIFEST Mon Jan  7 08:37:51 2002
+++ parrot/MANIFEST     Wed Jan  9 00:06:25 2002
@@ -116,8 +116,9 @@
 include/parrot/unicode.h
 interpreter.c
 io/io.c
-io/io_os.c
 io/io_stdio.c
+io/io_unix.c
+io/io_win32.c
 io/TODO
 jit.c
 jit/i386/core.jit
diff -urN tmp/parrot/Makefile.in parrot/Makefile.in
--- tmp/parrot/Makefile.in      Tue Jan  8 12:24:29 2002
+++ parrot/Makefile.in  Wed Jan  9 00:07:14 2002
@@ -74,7 +74,7 @@
 
 CHARTYPE_O_FILES = chartypes/unicode$(O) chartypes/usascii$(O)
 
-IO_O_FILES = io/io$(O) io/io_os$(O) io/io_stdio$(O)
+IO_O_FILES = io/io$(O) io/io_stdio$(O) io/io_unix$(O) io/io_win32$(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) \
diff -urN tmp/parrot/include/parrot/io.h parrot/include/parrot/io.h
--- tmp/parrot/include/parrot/io.h      Thu Jan  3 17:37:37 2002
+++ parrot/include/parrot/io.h  Wed Jan  9 00:11:55 2002
@@ -57,9 +57,11 @@
 #define PIO_F_READ      0000001
 #define PIO_F_WRITE     0000002
 #define PIO_F_APPEND    0000004
+#define PIO_F_TRUNC     0000010
 #define PIO_F_FILE      0000100
 #define PIO_F_PIPE      0000200
 #define PIO_F_SOCKET    0000400
+#define PIO_F_CONSOLE   0001000         /* A terminal, we can linebuf   */
 #define PIO_F_LINEBUF   0010000
 #define PIO_F_BUF       0020000
 #define PIO_F_MALLOC    0040000         /* Buffer malloced              */
@@ -88,11 +90,21 @@
         unsigned char * next;           /* Current read/write pointer   */
 };
 
+
+#ifdef WIN32
+typedef HANDLE PIOHANDLE; 
+#else
+typedef int PIOHANDLE;
+#endif
+
+ 
 struct _ParrotIO {
-        INTVAL          fd;             /* Low level OS descriptor      */
-        INTVAL          mode;           /* Read/Write/etc.              */
-        INTVAL          flags;          /* Da flags                     */
-        off_t           filepos;        /* Current real file pointer    */
+        PIOHANDLE       fd;             /* Low level OS descriptor      */
+        UINTVAL         mode;           /* Read/Write/etc.              */
+        UINTVAL         flags;          /* Da flags                     */
+        off_t           fsize;          /* Current file size            */
+        off_t           fpos;           /* Current real file pointer    */
+        off_t           lpos;           /* Last file position           */
         ParrotIOBuf     b;              /* Buffer structure             */
         ParrotIOLayer * stack;
         /* ParrotIOFilter * filters; */
@@ -101,7 +113,7 @@
 struct _ParrotIOLayer {
         void                    * this; /* Instance specific data       */
         const char              * name;
-        INTVAL                    flags;
+        UINTVAL                   flags;
         ParrotIOLayerAPI        * api;
         ParrotIOLayer           * up;
         ParrotIOLayer           * down;
@@ -121,11 +133,12 @@
 
 
 /* Others to come */
-extern ParrotIOLayer    pio_os_layer;
-extern ParrotIOLayer    pio_stdio_layer;
-#ifdef WIN32
-/*extern ParrotIOLayer  pio_win32_layer; */
+#ifndef WIN32
+extern ParrotIOLayer    pio_unix_layer;
+#else
+extern ParrotIOLayer    pio_win32_layer;
 #endif
+extern ParrotIOLayer    pio_stdio_layer;
 
 /* This is list of valid layers */
 extern ParrotIOLayer    * pio_registered_layers;
@@ -152,7 +165,7 @@
         INTVAL          (*Pushed)(ParrotIOLayer * l, ParrotIO * io);
         INTVAL          (*Popped)(ParrotIOLayer * l, ParrotIO * io);
         ParrotIO *      (*Open)(theINTERP, ParrotIOLayer * l,
-                                const char * name, const char * mode);
+                                const char * name, UINTVAL flags);
         ParrotIO *      (*Open2)(theINTERP, ParrotIOLayer * l,
                                 const char * name, const char * mode,
                                         int perm);
@@ -163,7 +176,7 @@
                                 const char * name, const char * mode,
                                         DummyCodeRef *);
         ParrotIO *      (*FDOpen)(theINTERP, ParrotIOLayer * l,
-                                INTVAL fd, const char * name);
+                                PIOHANDLE fd, UINTVAL flags);
         INTVAL          (*Close)(theINTERP, ParrotIOLayer * l,
                                 ParrotIO * io); 
         size_t          (*Write)(theINTERP, ParrotIOLayer * l,
@@ -208,15 +221,16 @@
 
 extern struct PMC *     new_io_pmc(struct Parrot_Interp *, ParrotIO *);
 extern void             free_io_header(ParrotIO *);
-extern ParrotIO *       PIO_new(struct Parrot_Interp *, ParrotIO *, INTVAL,
-                                INTVAL, INTVAL);
+extern ParrotIO *       PIO_new(struct Parrot_Interp *, ParrotIO *,
+                                INTVAL, UINTVAL, UINTVAL);
 
 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 UINTVAL          PIO_parse_open_flags(const char * flagstr);
 extern ParrotIO *       PIO_open(theINTERP, const char *, const char *);
-extern ParrotIO *       PIO_fdopen(theINTERP, INTVAL, const char *);
+extern ParrotIO *       PIO_fdopen(theINTERP, PIOHANDLE, const char *);
 extern INTVAL           PIO_close(theINTERP, ParrotIO *);
 extern void             PIO_flush(theINTERP, ParrotIO *);
 extern INTVAL           PIO_read(theINTERP, ParrotIO *, void *, size_t);
diff -urN tmp/parrot/io/io.c parrot/io/io.c
--- tmp/parrot/io/io.c  Thu Jan  3 17:37:38 2002
+++ parrot/io/io.c      Wed Jan  9 00:11:35 2002
@@ -4,7 +4,7 @@
  *  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.)
+ *      (io_os, io_stdio, io_utf8, etc.)
  *  Data Structure and Algorithms:
  *      Uses the IO PMC defined in io.h
  *      Uses ParrotIO structs in io.h 
@@ -52,13 +52,14 @@
 /*
  * Create a new IO stream, optionally reusing old structure.
  */
-ParrotIO * PIO_new(theINTERP, ParrotIO * old, INTVAL iotype, INTVAL flags,
-                                INTVAL mode) {
+ParrotIO * PIO_new(theINTERP, ParrotIO * old, INTVAL iotype,
+                        UINTVAL flags, UINTVAL mode) {
         ParrotIO * new_io;
         if( old ) {
                 /* FIXME: Reuse old IO */
         }
         new_io = (ParrotIO *)malloc(sizeof(ParrotIO));
+        new_io->fpos = new_io->lpos = (off_t)-1;
         new_io->flags = flags;
         new_io->mode = mode;
         new_io->stack = pio_default_stack;
@@ -81,19 +82,15 @@
         if( pio_initialized != 0 )
                 return;
 
-        /* Init IO stacks before creating any handles */
+        /* Init IO stacks.
+         * Side effect of the Init method of the OS stack will
+         * create STDIN, STDOUT, STDERR.
+         */
         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 ) {
+        if(!pio_stdin || !pio_stderr || !pio_stdout) {
                 abort();
         }
 
@@ -121,10 +118,17 @@
 INTVAL PIO_init_stacks(theINTERP) {
         ParrotIOLayer * p;
 
-        PIO_push_layer(&pio_os_layer, NULL);
+        /* First push the platform specific OS layer */
+#ifndef WIN32
+        PIO_push_layer(&pio_unix_layer, NULL);
+#else
+        PIO_push_layer(&pio_win32_layer, NULL);
+#endif
 #if 0
         PIO_push_layer(&pio_stdio_layer, NULL);
 #endif
+
+        /* Note: All layer pushes should be done before init calls */
         for(p=pio_default_stack; p; p=p->down) {
                 if( p->api->Init ) {
                         if((*p->api->Init)(interpreter, p) != 0) {
@@ -274,21 +278,21 @@
  * 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_new;
+        ParrotIOLayer ** ptr_ptr_new;
         ParrotIOLayer * ptr_proto;
         ParrotIOLayer * ptr_last = NULL;
-        ptr_new = &new_stack;
+        ptr_ptr_new = &ptr_new;
         ptr_proto = stack;
         while( ptr_proto ) { 
-                *ptr_new = PIO_base_new_layer( ptr_proto );
-                (*ptr_new)->up = ptr_last;
+                *ptr_ptr_new = PIO_base_new_layer( ptr_proto );
+                (*ptr_ptr_new)->up = ptr_last;
                 ptr_proto = ptr_proto->down;
-                ptr_last = *ptr_new;
-                ptr_new = &((*ptr_new)->down);
+                ptr_last = *ptr_ptr_new;
+                ptr_ptr_new = &((*ptr_ptr_new)->down);
         }
 
-        return new_stack;
+        return ptr_new;
 }
 
 
@@ -296,6 +300,43 @@
  * Generic top level ParrotIO interface.
  */
 
+/*
+ * Parse string for file open mode and return generic
+ * bits. The low level OS layers may then interpret the
+ * generic bits differently depending on platform.
+ */
+UINTVAL PIO_parse_open_flags(const char * flagstr) {
+        UINTVAL flags;
+        const char * s;
+
+        if( !flagstr || !(*flagstr) )
+                return 0;
+        flags = 0;
+        s = flagstr;
+        /* Set mode flags - <, >, >>, +<, +> */
+        /* add ? and ! for block/non-block */
+        switch(*s) {
+                case '+':
+                        flags |= (PIO_F_WRITE|PIO_F_READ);
+                        break;
+                case '<':
+                        flags |= PIO_F_READ;
+                        break;
+                case '>':
+                        flags |= PIO_F_WRITE;
+                        if( *(++s) == '>') {
+                                flags |= PIO_F_APPEND;
+                        }
+                        else if(*s != 0)
+                                return 0;
+                        break;
+                default:
+                        return 0;
+        }
+
+        return flags;
+}
+ 
 
 /*
  * API for controlling buffering specifics on an IO stream
@@ -315,13 +356,13 @@
 }
 
 
-ParrotIO * PIO_open(theINTERP, const char * spath, const char * smode) {
+ParrotIO * PIO_open(theINTERP, const char * spath, const char * sflags) {
         ParrotIO * io;
         ParrotIOLayer * l = pio_default_stack;
+        UINTVAL flags = PIO_parse_open_flags(sflags);
         while(l) {
                 if(l->api->Open) {
-                        io = (*l->api->Open)(interpreter, l, spath,
-                                                smode);
+                        io = (*l->api->Open)(interpreter, l, spath, flags);
                         io->stack = pio_default_stack;
                         return io;
                 }
@@ -336,13 +377,14 @@
  * 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 * PIO_fdopen(theINTERP, PIOHANDLE fd, const char * sflags) {
         ParrotIO * io;
+        UINTVAL flags;
         ParrotIOLayer * l = pio_default_stack;
+        flags = PIO_parse_open_flags(sflags);
         while(l) {
                 if(l->api->FDOpen) {
-                        io = (*l->api->FDOpen)(interpreter, l, fd,
-                                                smode);
+                        io = (*l->api->FDOpen)(interpreter, l, fd, flags);
                         io->stack = pio_default_stack;
                         return io;
                 }
diff -urN tmp/parrot/io/io_os.c parrot/io/io_os.c
--- tmp/parrot/io/io_os.c       Thu Jan  3 17:37:38 2002
+++ parrot/io/io_os.c   Wed Dec 31 19:00:00 1969
@@ -1,342 +0,0 @@
-/* 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, oflags, 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 |= (PIO_F_WRITE|PIO_F_READ);
-                        oflags = O_RDWR;
-                        break;
-                case '<':
-                        flags |= PIO_F_READ;
-                        oflags = O_RDONLY;
-                        break;
-                case '>':
-                        flags |= PIO_F_WRITE;
-                        oflags = O_WRONLY | O_CREAT;
-                        if( *(++modeptr) == '>') {
-                                flags |= PIO_F_APPEND;
-                                oflags |= O_APPEND;
-                        }
-                        else if(*modeptr != 0)
-                                return 0;
-                        else oflags |= O_TRUNC;
-                        break;
-                default:
-                        return 0;
-        }
-
-        /* Only files for now */
-        flags |= PIO_F_FILE;
-
-        /* Try open with no create first */
-        while((fd = open(spath, oflags&(O_WRONLY|O_RDWR), mode)) < 0
-                        && errno == EINTR )
-                errno = 0;
-
-        /* File open */
-        if(fd >= 0){
-                /*
-                 * Now check if we specified O_CREAT|O_EXCL or not.
-                 * If so, we must return NULL, else either use the
-                 * descriptor or create the file.
-                 */
-                if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
-                        close(fd);
-                        return NULL;
-                }
-                /*
-                 * Check for truncate?
-                 */
-                if(oflags&O_TRUNC) {
-                        int tfd;
-                        while((tfd = creat(spath, PIO_DEFAULTMODE)) < 0
-                                        && errno == EINTR)
-                                errno = 0;
-                        close(tfd);
-                }
-        } else if(oflags&O_CREAT) {
-                /* O_CREAT and file doesn't exist. */
-                while((fd = creat(spath, PIO_DEFAULTMODE)) < 0
-                                && errno == EINTR)
-                        errno = 0;
-                if(!(oflags&O_WRONLY)) {
-                        close(fd);
-                        /*
-                         * File created, reopen with read+write
-                         */
-                        while((fd = open(spath, oflags&(O_WRONLY|O_RDWR),
-                                        mode)) < 0 && errno == EINTR )
-                                errno = 0;
-                }
-        } else {
-#if 0
-                if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
-                        char * errstr = strerror( errno );
-                        fprintf(stderr, "PIO_os_open: %s",
-                                errstr );
-                }
-#endif
-        }
-
-        if(fd >= 0) {
-                /*
-                 * Finally we have a descriptor, create an IO stream
-                 */
-                io = PIO_new(interpreter, NULL, type, flags, mode);
-                io->fd = fd;
-                io->flags = flags;
-                return io;
-        }
-        return NULL;
-  }
-
-
-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 0
-        /* 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
-
-#if 0
-        if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
-                fprintf(stderr, "PIO_os_fdopen: %d\n", (int)fd );
-        }
-#endif
-        /* FIXME: Add mode string parser from PIO_os_open() here,
-         * possibly need a seperate function for it.
-         */
-        io = PIO_new(interpreter, NULL, PIO_F_FILE, flags, mode);
-        io->fd = fd;
-        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;
-        size_t 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
-                                default:        return (size_t)-1;
-                        }
-                }
-        }
-       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:
-*/
-
diff -urN tmp/parrot/io/io_stdio.c parrot/io/io_stdio.c
--- tmp/parrot/io/io_stdio.c    Fri Jan  4 11:39:35 2002
+++ parrot/io/io_stdio.c        Wed Jan  9 00:11:04 2002
@@ -1,7 +1,6 @@
 /* io_stdio.c
  *  Copyright: (When this is determined...it will go here)
  *  CVS Info
- *     $Id: io_stdio.c,v 1.2 2002/01/04 16:39:35 dan Exp $
  *  Overview:
  *      The "STDIO" layer of Parrot IO. Buffering and all the fun stuff.
  *
@@ -37,7 +36,7 @@
 INTVAL          PIO_stdio_setbuf(theINTERP, ParrotIOLayer * layer,
                         ParrotIO * io, size_t bufsize);
 ParrotIO *      PIO_stdio_fdopen(theINTERP, ParrotIOLayer * layer,
-                       INTVAL fd, const char * smode);
+                       PIOHANDLE fd, const char * smode);
 INTVAL          PIO_stdio_close(theINTERP, ParrotIOLayer * layer,
                         ParrotIO * io);
 void            PIO_stdio_flush(theINTERP, ParrotIOLayer * layer,
@@ -48,7 +47,10 @@
                         ParrotIO * io, const void * buffer, size_t len);
 INTVAL          PIO_stdio_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
                         const char * s);
-
+INTVAL          PIO_stdio_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence);
+off_t           PIO_stdio_tell(theINTERP, ParrotIOLayer * l,
+                        ParrotIO * io);
 
 
 
@@ -128,7 +130,7 @@
 
 
 ParrotIO * PIO_stdio_fdopen(theINTERP, ParrotIOLayer * layer,
-                       INTVAL fd, const char * smode) {
+                       PIOHANDLE fd, const char * smode) {
         ParrotIO * io;
         ParrotIOLayer * l = PIO_DOWNLAYER(layer);
         while(l) {
@@ -216,6 +218,32 @@
 }
 
 
+INTVAL PIO_stdio_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence) {
+        int hardseek = 0;
+
+        if( io->flags&PIO_F_SHARED ||
+                !(io->flags&(PIO_F_BUF|PIO_F_LINEBUF))) {
+                hardseek = 1;
+        }
+
+        /*
+         * Try to satisfy seek request in buffer if possible,
+         * else make IO request.
+         */
+
+        io->fpos = lseek(io->fd, offset, whence);
+        return io->fpos;
+}
+
+
+off_t PIO_stdio_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) {
+        off_t p;
+        p = lseek(io->fd, (off_t)0, SEEK_CUR);
+        return p;
+}
+
+
 
 ParrotIOLayerAPI        pio_stdio_layer_api = {
         PIO_base_init,
diff -urN tmp/parrot/io/io_unix.c parrot/io/io_unix.c
--- tmp/parrot/io/io_unix.c     Wed Dec 31 19:00:00 1969
+++ parrot/io/io_unix.c Wed Jan  9 00:11:04 2002
@@ -0,0 +1,377 @@
+/* io_unix.c
+ *  Copyright: (When this is determined...it will go here)
+ *  CVS Info
+ *  Overview:
+ *      This is the Parrot IO UNIX layer. May be changed to
+ *      include other platforms if that platform is similar 
+ *      enough to keep from smudging, else implement seperate layer.
+ *      For UNIX systems this is the low level OS layer (unbuffered).
+ *  Data Structure and Algorithms:
+ *  History:
+ *      Initially written by Melvin Smith ([EMAIL PROTECTED])
+ *  Notes:
+ *  References:
+ *      APitUE - W. Richard Stevens, AT&T SFIO, Perl5 (Nick Ing-Simmons)
+ */
+
+#include "parrot/parrot.h"
+
+/* Configure doesn't generate a generic UNIX define yet */
+#ifndef WIN32
+
+/* Defined at bottom */
+extern ParrotIOLayerAPI        pio_unix_layer_api;
+
+ParrotIOLayer           pio_unix_layer = {
+        NULL,
+        "unix",
+        PIO_L_TERMINAL,
+        &pio_unix_layer_api,
+        0, 0
+};
+
+
+/*
+ * Currently keeping layer prototypes local to each layer
+ * file.
+ */
+UINTVAL         flags_to_unix(UINTVAL flags);
+
+INTVAL          PIO_unix_init(theINTERP, ParrotIOLayer * layer);
+ParrotIO *      PIO_unix_open(theINTERP, ParrotIOLayer * layer,
+                       const char * spath, UINTVAL flags);
+ParrotIO *      PIO_unix_fdopen(theINTERP, ParrotIOLayer * layer,
+                       PIOHANDLE fd, UINTVAL flags);
+INTVAL          PIO_unix_close(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io);
+void            PIO_unix_flush(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io);
+size_t          PIO_unix_read(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io, void * buffer, size_t len);
+size_t          PIO_unix_write(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io, const void * buffer, size_t len);
+INTVAL          PIO_unix_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        const char * s);
+INTVAL          PIO_unix_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence);
+off_t           PIO_unix_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io);
+
+
+UINTVAL flags_to_unix(UINTVAL flags) {
+        UINTVAL oflags;
+        oflags = 0;
+        if((flags&(PIO_F_WRITE|PIO_F_READ)) == (PIO_F_WRITE|PIO_F_READ)) {
+                oflags |= O_RDWR|O_CREAT;
+        } else if( flags & PIO_F_WRITE ) {
+                oflags |= O_WRONLY|O_CREAT;
+        } else if( flags & PIO_F_READ ) {
+                oflags |= O_RDONLY;
+        }
+
+        if( flags & PIO_F_APPEND ) {
+                oflags |= O_APPEND;
+        } else if( flags & PIO_F_TRUNC ) {
+                oflags |= O_TRUNC;
+        }
+        return oflags;
+}
+
+
+
+/*
+ * Setup standard streams, etc.
+ */
+INTVAL PIO_unix_init(theINTERP, ParrotIOLayer * layer) {
+        if((pio_stdin=PIO_fdopen(interpreter, STDIN_FILENO, "<"))
+                &&(pio_stdout=PIO_fdopen(interpreter, STDOUT_FILENO, ">"))
+                &&(pio_stderr=PIO_fdopen(interpreter, STDERR_FILENO, ">"))
+                )
+                return 0;
+        return -1;
+}
+
+
+/*
+ * Open modes (read, write, append, etc.) are done in pseudo-Perl
+ * style using <, >, etc.
+ */
+ParrotIO * PIO_unix_open(theINTERP, ParrotIOLayer * layer,
+                       const char * spath, UINTVAL flags) {
+        ParrotIO * io;
+        int oflags, type, mode, fd;
+        const char * modeptr;
+        type = PIO_TYPE_FILE;
+        mode = DEFAULT_OPEN_MODE;
+#if 0
+        if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+                fprintf(stderr, "PIO_unix_open: %s, %s\n",
+                                spath, modeptr);
+        }
+#endif
+        if( (flags & (PIO_F_WRITE|PIO_F_READ)) == 0 )
+                return NULL;
+
+        oflags = flags_to_unix(flags);
+
+        /* Only files for now */
+        flags |= PIO_F_FILE;
+
+        /* Try open with no create first */
+        while((fd = open(spath, oflags&(O_WRONLY|O_RDWR), mode)) < 0
+                        && errno == EINTR )
+                errno = 0;
+
+        /* File open */
+        if(fd >= 0){
+                /*
+                 * Now check if we specified O_CREAT|O_EXCL or not.
+                 * If so, we must return NULL, else either use the
+                 * descriptor or create the file.
+                 */
+                if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
+                        close(fd);
+                        return NULL;
+                }
+                /*
+                 * Check for truncate?
+                 */
+                if(oflags&O_TRUNC) {
+                        int tfd;
+                        while((tfd = creat(spath, PIO_DEFAULTMODE)) < 0
+                                        && errno == EINTR)
+                                errno = 0;
+                        close(tfd);
+                }
+        } else if(oflags&O_CREAT) {
+                /* O_CREAT and file doesn't exist. */
+                while((fd = creat(spath, PIO_DEFAULTMODE)) < 0
+                                && errno == EINTR)
+                        errno = 0;
+                if(!(oflags&O_WRONLY)) {
+                        close(fd);
+                        /*
+                         * File created, reopen with read+write
+                         */
+                        while((fd = open(spath, oflags&(O_WRONLY|O_RDWR),
+                                        mode)) < 0 && errno == EINTR )
+                                errno = 0;
+                }
+        } else {
+#if 0
+                if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+                        char * errstr = strerror( errno );
+                        fprintf(stderr, "PIO_unix_open: %s",
+                                errstr );
+                }
+#endif
+        }
+
+        if(fd >= 0) {
+                /*
+                 * Finally we have a descriptor, create an IO stream
+                 */
+                io = PIO_new(interpreter, NULL, type, flags, mode);
+#if 0
+                /* Set generic flag here if is a terminal then
+                 * higher layers can know how to setup buffering.
+                 * STDIN, STDOUT, STDERR would be in this case
+                 * so we would setup linebuffering.
+                 */
+                if( isatty(fd) )
+                        flags |= PIO_F_CONSOLE;
+#endif
+                io->fd = fd;
+                io->flags = flags;
+                return io;
+        }
+        return NULL;
+}
+
+
+ParrotIO * PIO_unix_fdopen(theINTERP, ParrotIOLayer * layer,
+                       PIOHANDLE fd, UINTVAL flags) {
+        ParrotIO * io;
+        UINTVAL oflags, rflags, mode;
+        mode = 0;
+
+        oflags = flags_to_unix(flags);
+
+        /* FIXME - Check file handle flags, validity */
+#ifdef HAD_HEADER_FCNTL
+        /* Get descriptor flags */
+        if((rflags = fcntl(fd, F_GETFL, 0)) >= 0) {
+                /*int accmode = rflags & O_ACCMODE;*/
+                /* Check other flags (APPEND, ASYNC, etc) */
+        } else {
+                /* Probably invalid descriptor */
+                return NULL;
+        } 
+#endif
+
+#if 0
+        if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+                fprintf(stderr, "PIO_unix_fdopen: %d\n", (int)fd );
+        }
+#endif
+        /* FIXME: Add mode string parser from PIO_unix_open() here,
+         * possibly need a seperate function for it.
+         */
+        io = PIO_new(interpreter, NULL, PIO_F_FILE, flags, mode);
+        io->fd = fd;
+        return io;
+}
+
+
+INTVAL PIO_unix_close(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+        if( io->fd >= 0 )
+                close( io->fd );
+        io->fd = -1;
+       return 0;
+}
+
+
+/* At lowest layer all we can do for flush is ask kernel to sync().
+ */
+void PIO_unix_flush(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+#if 0
+        fsync(io->fd);
+#endif
+}
+
+
+size_t PIO_unix_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_unix_write(theINTERP, ParrotIOLayer * layer, ParrotIO * io,
+                       const void * buffer, size_t len) {
+        int err;
+        size_t bytes;
+        size_t to_write;
+        const char * ptr;
+#if 0
+        if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+                fprintf(stderr, "PIO_unix_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, "PIO_unix_write: wrote %d bytes\n", 
+err );
+#endif
+                } else {
+                        switch(errno) {
+                                case EINTR:     goto write_through;
+#ifdef EAGAIN
+                                case EAGAIN:    return bytes;
+#endif
+                                default:        return (size_t)-1;
+                        }
+                }
+        }
+       return bytes;
+}
+
+
+INTVAL PIO_unix_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                                const char * s) {
+        size_t len;
+        len = strlen(s);
+        if( len > 0 ) {
+                size_t sz;
+                sz = PIO_unix_write(interpreter, l, io, s, len);
+                if( sz < len ) {
+                        return -1;
+                } else {
+                        return len;
+                }
+        }
+       
+        return -1;
+}
+
+
+/*
+ * Hard seek
+ */
+INTVAL PIO_unix_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence) {
+        io->fpos = lseek(io->fd, offset, whence);
+        return io->fpos;
+}
+
+
+off_t PIO_unix_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) {
+        off_t p;
+        p = lseek(io->fd, (off_t)0, SEEK_CUR);
+        return p;
+}
+
+
+
+ParrotIOLayerAPI        pio_unix_layer_api = {
+        PIO_unix_init,
+        PIO_base_new_layer,
+        PIO_base_delete_layer,
+        NULL,
+        NULL,
+        PIO_unix_open,
+        NULL,
+        NULL,
+        NULL,
+        PIO_unix_fdopen,
+        PIO_unix_close,
+        PIO_unix_write,
+        NULL,
+        PIO_unix_read,
+        NULL,
+        NULL,
+        PIO_unix_seek,
+        PIO_unix_tell,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        PIO_unix_puts,
+        NULL 
+};
+
+
+#endif /* WIN32 */
+
+/*
+ * 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_win32.c parrot/io/io_win32.c
--- tmp/parrot/io/io_win32.c    Wed Dec 31 19:00:00 1969
+++ parrot/io/io_win32.c        Wed Jan  9 00:11:04 2002
@@ -0,0 +1,257 @@
+/* io_win32.c
+ *  Copyright: (When this is determined...it will go here)
+ *  CVS Info
+ *  Overview:
+ *      This is the Parrot IO OS layer for Win32 platforms.
+ *  Data Structure and Algorithms:
+ *  History:
+ *      Initially written by Melvin Smith
+ *  Notes:
+ *  References:
+ *      Win32 System Programming, 2nd Edition
+ */
+
+#include "parrot/parrot.h"
+
+#ifdef WIN32
+
+/* Defined at bottom */
+extern ParrotIOLayerAPI        pio_win32_layer_api;
+
+ParrotIOLayer           pio_win32_layer = {
+        NULL,
+        "win32",
+        PIO_L_TERMINAL,
+        &pio_win32_layer_api,
+        0, 0
+};
+
+
+/*
+ * Currently keeping layer prototypes local to each layer
+ * file.
+ */
+
+INTVAL          PIO_win32_init(theINTERP, ParrotIOLayer * layer);
+ParrotIO *      PIO_win32_open(theINTERP, ParrotIOLayer * layer,
+                       const char * spath, UINTVAL flags);
+ParrotIO *      PIO_win32_fdopen(theINTERP, ParrotIOLayer * layer,
+                       PIOHANDLE fd, const char * smode);
+INTVAL          PIO_win32_close(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io);
+void            PIO_win32_flush(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io);
+size_t          PIO_win32_read(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io, void * buffer, size_t len);
+size_t          PIO_win32_write(theINTERP, ParrotIOLayer * layer,
+                        ParrotIO * io, const void * buffer, size_t len);
+INTVAL          PIO_win32_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        const char * s);
+INTVAL          PIO_win32_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence);
+off_t           PIO_win32_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io);
+
+
+/* Convert to platform specific bit open flags */
+UINTVAL flags_to_win32(UINTVAL flags, DWORD * fdwAccess,
+                        DWORD * fdwShareMode, DWORD * fdwCreate) {
+        if((flags&(PIO_F_WRITE|PIO_F_READ)) == (PIO_F_WRITE|PIO_F_READ)) {
+                *fdwAccess = GENERIC_WRITE|GENERIC_READ;
+                *fdwCreate = OPEN_ALWAYS|CREATE_ALWAYS; 
+        } else if( flags & PIO_F_WRITE ) {
+                *fdwAccess = GENERIC_WRITE;
+                *fdwCreate = OPEN_ALWAYS|CREATE_ALWAYS; 
+        } else if( flags & PIO_F_READ ) {
+                *fdwAccess = GENERIC_READ;
+                *fdwCreate = OPEN_ALWAYS|CREATE_ALWAYS; 
+        }
+
+        /* Temporary */
+        *fdwShareMode = 0;
+
+        if( (flags & PIO_F_TRUNC) && (flags & PIO_F_WRITE) )
+                *fdwCreate |= TRUNCATE_EXISTING;
+        else if( flags & PIO_F_APPEND ) {
+                /* FIXME - I don't think Win32 has an O_APPEND
+                 * so just open then seek to end.
+                 */
+        }
+
+        return 1;
+}
+
+
+/*
+ * Setup standard streams.
+ */
+INTVAL PIO_win32_init(theINTERP, ParrotIOLayer * layer) {
+        HANDLE h;
+        if((h = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE) {
+                pio_stdin = PIO_win32_fdopen(interpreter, layer, h, "<");
+        }
+        if((h = GetStdHandle(STD_OUTPUT_HANDLE))
+                                        != INVALID_HANDLE_VALUE){
+                pio_stdout = PIO_win32_fdopen(interpreter, layer, h, ">");
+        }
+        if((h = GetStdHandle(STD_ERROR_HANDLE)) != INVALID_HANDLE_VALUE) {
+                pio_stderr = PIO_win32_fdopen(interpreter, layer, h, ">");
+        }
+
+        if(pio_stdin && pio_stdout && pio_stderr)
+                return 0;
+        return -1;
+}
+
+
+ParrotIO * PIO_win32_open(theINTERP, ParrotIOLayer * layer,
+                       const char * spath, UINTVAL flags) {
+        ParrotIO * io;
+        int type;
+        PIOHANDLE fd;
+        DWORD fAcc, fShare, fCreat;
+        type = PIO_TYPE_FILE;
+#if 0
+        if((interpreter->flags & PARROT_DEBUG_FLAG) != 0) {
+                fprintf(stderr, "PIO_win32_open: %s, %s\n",
+                                spath, modeptr);
+        }
+#endif
+        if( (flags & (PIO_F_WRITE|PIO_F_READ)) == 0 )
+                return (ParrotIO *)NULL;
+
+        /* Set open flags - <, >, >>, +<, +> */
+        /* add ? and ! for block/non-block */
+        if( flags_to_win32(flags, &fAcc, fShare, fCreat) < 0 )
+                return (ParrotIO *)NULL;
+
+        /* Only files for now */
+        flags |= PIO_F_FILE;
+
+        /* Try open with no create first */
+       
+        /* FIXME: Unfinished */ 
+        return (ParrotIO *)NULL;
+}
+
+
+ParrotIO * PIO_win32_fdopen(theINTERP, ParrotIOLayer * layer,
+                       PIOHANDLE fd, const char * smode) {
+        ParrotIO * io;
+        INTVAL flags, mode;
+        flags = 0;
+        mode = 0;
+
+        /* FIXME - Check file handle specifics, validity */
+
+        io = PIO_new(interpreter, NULL, PIO_F_FILE, flags, mode);
+        io->fd = fd;
+        return io;
+}
+
+
+INTVAL PIO_win32_close(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+        if( io && io->fd != INVALID_HANDLE_VALUE ) {
+                CloseHandle( io->fd );
+                io->fd = INVALID_HANDLE_VALUE;
+        }
+       return 0;
+}
+
+
+void PIO_win32_flush(theINTERP, ParrotIOLayer * layer, ParrotIO * io) {
+}
+
+
+size_t PIO_win32_read(theINTERP, ParrotIOLayer * layer, ParrotIO * io,
+                               void * buffer, size_t len) {
+        return 0;
+}
+
+
+size_t PIO_win32_write(theINTERP, ParrotIOLayer * layer, ParrotIO * io,
+                       const void * buffer, size_t len) {
+        return 0;
+}
+
+
+/*
+ * puts tries WriteConsole first, then WriteFile, whereas
+ * write calls WriteFile only.
+ */
+INTVAL PIO_win32_puts(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                                const char * s) {
+        LPCTSTR msg;
+        DWORD len, wrote;
+        if((msg = (LPCTSTR)s) != NULL) {
+                len = _tcslen(msg);
+                if(!WriteConsole(io->fd, msg, len, &wrote, NULL)
+                        && !WriteFile(io->fd, msg, len * sizeof(TCHAR),
+                                &wrote, NULL))
+                        return -1;
+                return wrote;
+
+        } 
+        return -1;
+}
+
+
+/*
+ * Hard seek
+ */
+INTVAL PIO_win32_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io,
+                        off_t offset, INTVAL whence) {
+        io->fpos = lseek(io->fd, offset, whence);
+        return io->fpos;
+}
+
+
+off_t PIO_win32_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) {
+        off_t p;
+        p = lseek(io->fd, (off_t)0, SEEK_CUR);
+        return p;
+}
+
+
+
+ParrotIOLayerAPI        pio_win32_layer_api = {
+        PIO_win32_init,
+        PIO_base_new_layer,
+        PIO_base_delete_layer,
+        NULL,
+        NULL,
+        PIO_win32_open,
+        NULL,
+        NULL,
+        NULL,
+        PIO_win32_fdopen,
+        PIO_win32_close,
+        PIO_win32_write,
+        NULL,
+        PIO_win32_read,
+        NULL,
+        NULL,
+        PIO_win32_seek,
+        PIO_win32_tell,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        PIO_win32_puts,
+        NULL 
+};
+
+
+
+#endif /* WIN32 */
+
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/
+


Reply via email to