Hello,

currently there is no (simple) way to open a file on an other layer
than the default layer. But this is necessary if we want to take
advantage from the layered approach.

So i added two new functions: pio_open_with_layer and
pio_fdopen_with_layer which create IO-Objects on different layers. I'm
not keen on the names, but I didn't find better ones.

So to test this I need another layer on which I can open files: stdio
should be available on all systems. So far so good, now I can open
files on with stdio and fdopen existing handles.

But there are some issues:
* During layer initialisation the layers want to register the handles
  for stdin, stdout and stderr. I went around this by conditionally
  only compiling the handle init if stdio is the base IO systems.
  Is this a good solution?
* I needed many casts from PIOHANDLE to FILE * and vice versa. I'm not
  sure if this one fits all approach of PIOHANDLE is the right way.
  Maybe its better to make PIOHANDLE a union. But what to do then
  with the fdopen and getfd ops. It is not guaranteed that a union
  can be casted to an INTVAL and back.
* Modifying the same file through different layers might lead to very
  unpredictable results. But thats already a problem with
  unix-handles/stdio-handles.
* PIO_isatty and PIO_getblksize are macros which are coded at
  compile-time to some layer, and not as read, write etc go through a
  LayerAPI.

Comments
bö

? icu/source/test
? languages/befunge/befunge.pbc
? t/src/headers.t
Index: include/parrot/io.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/io.h,v
retrieving revision 1.49
diff -u -r1.49 io.h
--- include/parrot/io.h	25 Oct 2003 05:40:08 -0000	1.49
+++ include/parrot/io.h	4 Nov 2003 14:15:32 -0000
@@ -261,7 +261,11 @@
 
 extern INTVAL PIO_parse_open_flags(const char *flagstr);
 extern PMC *PIO_open(theINTERP, const char *, const char *);
+extern PMC *PIO_open_with_layer(theINTERP, ParrotIOLayer *,
+                                const char *, const char *);
 extern PMC *PIO_fdopen(theINTERP, PIOHANDLE, const char *);
+extern PMC *PIO_fdopen_with_layer(theINTERP, ParrotIOLayer *, PIOHANDLE,
+                                  const char *);
 extern INTVAL PIO_close(theINTERP, PMC *);
 extern void PIO_flush(theINTERP, PMC *);
 extern INTVAL PIO_read(theINTERP, PMC *, void *, size_t);
Index: io/io.c
===================================================================
RCS file: /cvs/public/parrot/io/io.c,v
retrieving revision 1.70
diff -u -r1.70 io.c
--- io/io.c	30 Oct 2003 08:49:14 -0000	1.70
+++ io/io.c	4 Nov 2003 14:15:32 -0000
@@ -574,6 +574,25 @@
     return new_io_pmc(interpreter, io);
 }
 
+PMC *
+PIO_open_with_layer(theINTERP, ParrotIOLayer *layer,
+                    const char *spath, const char *sflags)
+{
+    ParrotIO *io;
+    INTVAL flags = PIO_parse_open_flags(sflags);
+
+    io = PIO_open_down(interpreter, layer, spath, flags);
+    /* io could be null here but we still have to
+     * to create a PMC for the caller, no PMCNULL here
+     * as that would cause an exception upon access.
+     */
+    if (io) {
+        io->stack = layer;
+    }
+
+    return new_io_pmc(interpreter, io);
+}
+
 
 /*
  * Create an IO object on an existing, open file descriptor.
@@ -595,6 +614,26 @@
      */
     if (io) {
         io->stack = l;
+    }
+
+    return new_io_pmc(interpreter, io);
+}
+
+
+PMC *
+PIO_fdopen_with_layer(theINTERP, ParrotIOLayer *layer, PIOHANDLE fd,
+                      const char *sflags)
+{
+    ParrotIO *io;
+    INTVAL flags = PIO_parse_open_flags(sflags);
+
+    io = PIO_fdopen_down(interpreter, layer, fd, flags);
+    /* io could be null here but we still have to
+     * to create a PMC for the caller, no PMCNULL here
+     * as that would cause an exception upon access.
+     */
+    if (io) {
+        io->stack = layer;
     }
 
     return new_io_pmc(interpreter, io);
Index: io/io_stdio.c
===================================================================
RCS file: /cvs/public/parrot/io/io_stdio.c,v
retrieving revision 1.33
diff -u -r1.33 io_stdio.c
--- io/io_stdio.c	11 Oct 2003 13:15:30 -0000	1.33
+++ io/io_stdio.c	4 Nov 2003 14:15:32 -0000
@@ -19,7 +19,8 @@
 #include "parrot/parrot.h"
 #include "io_private.h"
 
-#ifdef PIO_OS_STDIO
+extern INTVAL           PIO_stdio_isatty(PIOHANDLE fd);
+extern INTVAL           PIO_stdio_getblksize(PIOHANDLE fd);
 
 /* Defined at bottom */
 extern ParrotIOLayerAPI pio_stdio_layer_api;
@@ -93,6 +94,8 @@
 static INTVAL
 PIO_stdio_init(theINTERP, ParrotIOLayer *layer)
 {
+#ifdef PIO_OS_STDIO
+    /* Only set standard handles if stdio is the OS IO */
     PIO_STDIN(interpreter)
         = new_io_pmc(interpreter,
                      PIO_stdio_fdopen(interpreter, layer, stdin, PIO_F_READ));
@@ -104,7 +107,7 @@
     PIO_STDERR(interpreter)
         = new_io_pmc(interpreter,
                      PIO_stdio_fdopen(interpreter, layer, stderr, PIO_F_WRITE));
-
+#endif /* PIO_OS_STDIO */
     return 0;
 }
 
@@ -140,10 +143,10 @@
 
     /* File open */
     if (fptr != NULL) {
-        if (PIO_isatty(fptr))
+        if (PIO_stdio_isatty((PIOHANDLE)fptr))
             flags |= PIO_F_CONSOLE;
         io = PIO_new(interpreter, type, flags, 0);
-        io->fd = fptr;
+        io->fd = (PIOHANDLE)fptr;
         return io;
     }
     return NULL;
@@ -172,9 +175,10 @@
 static INTVAL
 PIO_stdio_close(theINTERP, ParrotIOLayer *layer, ParrotIO *io)
 {
-    if (io->fd != NULL)
-        fclose(io->fd);
-    io->fd = NULL;
+    FILE *fptr = (FILE*)io->fd;
+    if (fptr != NULL)
+        fclose(fptr);
+    io->fd = (PIOHANDLE)NULL;
     return 0;
 }
 
@@ -198,7 +202,7 @@
 static INTVAL
 PIO_stdio_flush(theINTERP, ParrotIOLayer *layer, ParrotIO *io)
 {
-    return fflush(io->fd);
+    return fflush((FILE*)io->fd);
 }
 
 
@@ -207,14 +211,15 @@
               void *buffer, size_t len)
 {
     size_t bytes;
+    FILE *fptr = (FILE *)io->fd;
 
     UNUSED(interpreter);
     UNUSED(layer);
 
-    bytes = fread(buffer, 1, len, io->fd);
+    bytes = fread(buffer, 1, len, fptr);
 
     if (bytes != len) {
-        if (feof(io->fd)) {
+        if (feof(fptr)) {
             io->flags |= PIO_F_EOF;
         } 
     }
@@ -230,7 +235,7 @@
     UNUSED(interpreter);
     UNUSED(layer);
 
-    return(fwrite(buffer, 1, len, io->fd));
+    return(fwrite(buffer, 1, len, (FILE*)io->fd));
 }
 
 
@@ -244,7 +249,7 @@
     PIOOFF_T pos;
     errno = 0;
 
-    if ((pos = fseek(io->fd, offset, whence)) >= 0) {
+    if ((pos = fseek((FILE*)io->fd, offset, whence)) >= 0) {
         io->lpos = io->fpos;
         io->fpos = pos;
     }
@@ -258,7 +263,7 @@
 static PIOOFF_T
 PIO_stdio_tell(theINTERP, ParrotIOLayer *l, ParrotIO *io)
 {
-    return(ftell(io->fd));
+    return(ftell((FILE*)io->fd));
 }
 
 
@@ -294,8 +299,6 @@
     0 /* no recv */
 };
 
-#endif /* PIO_OS_STDIO */
-
 /*
  * Local variables:
  * c-indentation-style: bsd
@@ -304,4 +307,4 @@
  * End:
  *
  * vim: expandtab shiftwidth=4:
-*/
+ */
Index: t/src/io.t
===================================================================
RCS file: /cvs/public/parrot/t/src/io.t,v
retrieving revision 1.5
diff -u -r1.5 io.t
--- t/src/io.t	30 Oct 2003 06:02:30 -0000	1.5
+++ t/src/io.t	4 Nov 2003 14:15:36 -0000
@@ -1,6 +1,6 @@
 #! perl -w
 
-use Parrot::Test tests => 16;
+use Parrot::Test tests => 17;
 use Test::More;
 
 $/=undef; # slurp mode
@@ -607,3 +607,30 @@
 }
 
 ###############################################################################
+
+c_output_is(<<'CODE', <<'OUTPUT', 'stdio-layer');
+#include "parrot/parrot.h"
+
+extern ParrotIOLayer pio_stdio_layer;
+
+int main()
+{
+    Interp *interpreter;
+    PMC *io;
+
+    interpreter = Parrot_new();
+    
+    if ( interpreter == NULL ) return 1;
+    
+    Parrot_init(interpreter);
+
+    io = PIO_fdopen_with_layer(interpreter, &pio_stdio_layer,
+			       (PIOHANDLE)stdout, ">");
+    PIO_puts(interpreter, io, "Hello, World\n");
+    PIO_flush(interpreter, io);
+
+    return 0;
+}
+CODE
+Hello, World
+OUTPUT

Reply via email to