Well I'm working really slow, barely able to get in 50 lines tonight, work is crushing me.
Patch Comments: Implemented a few more calls in the Win32 layer (write/read/seek/tell) A few other minor tweaks. -Melvin Index: include/parrot/io.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/io.h,v retrieving revision 1.6 diff -u -r1.6 io.h --- include/parrot/io.h 14 Jan 2002 20:04:29 -0000 1.6 +++ include/parrot/io.h 18 Jan 2002 06:54:38 -0000 @@ -9,6 +9,7 @@ * Originally written by Melvin Smith * Notes: * References: + * Perl6 RFCs (14,30,47,60,186,239,321,345,350) * Some ideas and goals from Perl5.7 and Nick Ing-Simmons' work * Some ideas from AT&T SFIO */ @@ -38,11 +39,11 @@ # define O_ACCMODE 0003 #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 +#ifdef BLKSIZE +# define PIO_BLKSIZE BLKSIZE +#else +# define PIO_BLKSIZE 8192 +#endif #define PIO_BUFSIZE 4096 #define PIO_LINEBUFSIZE 256 @@ -93,18 +94,21 @@ #ifdef WIN32 typedef HANDLE PIOHANDLE; +typedef LARGE_INTEGER PIOOFF_T; #else typedef int PIOHANDLE; +typedef off_t PIOOFF_T; #endif +extern PIOOFF_T piooffsetzero; struct _ParrotIO { 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 */ + PIOOFF_T fsize; /* Current file size */ + PIOOFF_T fpos; /* Current real file pointer */ + PIOOFF_T lpos; /* Last file position */ ParrotIOBuf b; /* Buffer structure */ ParrotIOLayer * stack; /* ParrotIOFilter * filters; */ @@ -192,10 +196,9 @@ 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, + PIOOFF_T (*Seek)(theINTERP, ParrotIOLayer * layer, + ParrotIO * io, PIOOFF_T offset, INTVAL whence); + PIOOFF_T (*Tell)(theINTERP, ParrotIOLayer * layer, ParrotIO * io); INTVAL (*SetBuf)(theINTERP, ParrotIOLayer * layer, ParrotIO * io, size_t bufsize); @@ -246,9 +249,13 @@ #ifdef WIN32 extern INTVAL PIO_win32_isatty(PIOHANDLE fd); # define PIO_isatty(x) PIO_win32_isatty(x) +extern INTVAL PIO_win32_getblksize(PIOHANDLE fd); +# define PIO_getblksize(x) PIO_win32_getblksize(x) #else extern INTVAL PIO_unix_isatty(PIOHANDLE fd); # define PIO_isatty(x) PIO_unix_isatty(x) +extern INTVAL PIO_unix_getblksize(PIOHANDLE fd); +# define PIO_getblksize(x) PIO_unix_getblksize(x) #endif extern ParrotIO * pio_stdin; Index: io/TODO =================================================================== RCS file: /cvs/public/parrot/io/TODO,v retrieving revision 1.1 diff -u -r1.1 TODO --- io/TODO 4 Jan 2002 03:57:38 -0000 1.1 +++ io/TODO 18 Jan 2002 06:54:38 -0000 @@ -1,6 +1,6 @@ Add IO tables, right now IO's just float around. -Finish pmc +Finish PMC for IO object The "stdio" layer -buffering @@ -23,5 +23,9 @@ UTF layers (or should we not bother and do as a filter?) Sample programs and test suite + +AIO - On many platforms we must fake async IO, are we doing a background + thread/interp or an inline event queue function that is called + every N ops? Documentation! :) Index: io/io.c =================================================================== RCS file: /cvs/public/parrot/io/io.c,v retrieving revision 1.6 diff -u -r1.6 io.c --- io/io.c 12 Jan 2002 15:34:27 -0000 1.6 +++ io/io.c 18 Jan 2002 06:54:39 -0000 @@ -32,6 +32,7 @@ ParrotIO * pio_stdout; ParrotIO * pio_stderr; +PIOOFF_T piooffsetzero; PMC * new_io_pmc(theINTERP, ParrotIO * io) { PMC * new_pmc; @@ -62,7 +63,7 @@ /* FIXME: Reuse old IO */ } new_io = (ParrotIO *)malloc(sizeof(ParrotIO)); - new_io->fpos = new_io->lpos = (off_t)-1; + new_io->fpos = new_io->lpos = piooffsetzero; new_io->flags = flags; new_io->mode = mode; new_io->stack = pio_default_stack; Index: io/io_stdio.c =================================================================== RCS file: /cvs/public/parrot/io/io_stdio.c,v retrieving revision 1.6 diff -u -r1.6 io_stdio.c --- io/io_stdio.c 14 Jan 2002 20:04:31 -0000 1.6 +++ io/io_stdio.c 18 Jan 2002 06:54:39 -0000 @@ -31,6 +31,7 @@ * file. */ +INTVAL PIO_stdio_init(theINTERP, ParrotIOLayer * layer); ParrotIO * PIO_stdio_open(theINTERP, ParrotIOLayer * layer, const char * path, UINTVAL flags); INTVAL PIO_stdio_setbuf(theINTERP, ParrotIOLayer * layer, @@ -49,12 +50,22 @@ 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, +PIOOFF_T PIO_stdio_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_T offset, INTVAL whence); +PIOOFF_T PIO_stdio_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io); +INTVAL PIO_stdio_init(theINTERP, ParrotIOLayer * layer) { + if(pio_stdout) + PIO_stdio_setlinebuf(interpreter, layer, pio_stdout); + if(pio_stderr) + PIO_stdio_setbuf(interpreter, layer, pio_stderr, PIO_UNBOUND); + if(pio_stdin) + PIO_stdio_setbuf(interpreter, layer, pio_stdin, PIO_UNBOUND); + return 0; +} + ParrotIO * PIO_stdio_open(theINTERP, ParrotIOLayer * layer, const char * path, UINTVAL flags) { @@ -67,7 +78,7 @@ * We have an IO stream now setup stuff * for our layer before returning it. */ - PIO_stdio_setbuf(interpreter, l, io, PIO_BUFSIZE); + PIO_stdio_setbuf(interpreter, l, io, PIO_UNBOUND); return io; } l = PIO_DOWNLAYER(l); @@ -94,7 +105,7 @@ /* Choose an appropriate buffer size for caller */ if( bufsize == PIO_UNBOUND ) { - b->size = PIO_BUFSIZE; + b->size = PIO_getblksize(io->fd); } else { b->size = bufsize; @@ -144,7 +155,7 @@ PIO_stdio_setlinebuf(interpreter, l, io); else PIO_stdio_setbuf(interpreter, l, io, - PIO_BUFSIZE); + PIO_UNBOUND); return io; } l = PIO_DOWNLAYER(l); @@ -230,8 +241,8 @@ } -INTVAL PIO_stdio_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, - off_t offset, INTVAL whence) { +PIOOFF_T PIO_stdio_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_T offset, INTVAL whence) { int hardseek = 0; if( io->flags&PIO_F_SHARED || @@ -243,22 +254,19 @@ * Try to satisfy seek request in buffer if possible, * else make IO request. */ - - io->fpos = lseek(io->fd, offset, whence); + internal_exception(IO_NOT_IMPLEMENTED, "Seek not implemented"); 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; +PIOOFF_T PIO_stdio_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) { + return io->fpos; } ParrotIOLayerAPI pio_stdio_layer_api = { - PIO_base_init, + PIO_stdio_init, PIO_base_new_layer, PIO_base_delete_layer, NULL, Index: io/io_unix.c =================================================================== RCS file: /cvs/public/parrot/io/io_unix.c,v retrieving revision 1.3 diff -u -r1.3 io_unix.c --- io/io_unix.c 12 Jan 2002 15:34:27 -0000 1.3 +++ io/io_unix.c 18 Jan 2002 06:54:40 -0000 @@ -52,9 +52,9 @@ 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); +PIOOFF_T PIO_unix_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_T offset, INTVAL whence); +PIOOFF_T PIO_unix_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io); UINTVAL flags_to_unix(UINTVAL flags) { @@ -236,6 +236,38 @@ return isatty(fd); } +/* + * Various ways of determining block size. If passed a descriptor + * we can use fstat() and the stat buf if available, or the BLKSIZE + * constant if available at compile time. + */ +INTVAL PIO_unix_getblksize(PIOHANDLE fd) { + if(fd >= 0) { + /* Try to get the block size of a regular file */ +#if 0 + /* + * Is it even worth adding non-portable code here + * or should we just estimate a nice buffer size? + * Some systems have st_blksize, some don't. + */ + { + struct stat sbuf; + int err; + err = fstat(fd, &sbuf); + if(err == 0) { + return sbuf.st_blksize; + } + } +#endif + } + /* Try to determine it from general means. */ +#ifdef BLKSIZE + return BLKSIZE; +#else + return PIO_BLKSIZE; +#endif +} + /* At lowest layer all we can do for flush is ask kernel to sync(). */ void PIO_unix_flush(theINTERP, ParrotIOLayer * layer, ParrotIO * io) { @@ -332,16 +364,16 @@ /* * Hard seek */ -INTVAL PIO_unix_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, - off_t offset, INTVAL whence) { +PIOOFF_T PIO_unix_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_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); +PIOOFF_T PIO_unix_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) { + PIOOFF_T p; + p = lseek(io->fd, (PIOOFF_T)0, SEEK_CUR); return p; } Index: io/io_win32.c =================================================================== RCS file: /cvs/public/parrot/io/io_win32.c,v retrieving revision 1.4 diff -u -r1.4 io_win32.c --- io/io_win32.c 14 Jan 2002 20:04:31 -0000 1.4 +++ io/io_win32.c 18 Jan 2002 06:54:41 -0000 @@ -49,9 +49,9 @@ 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); +PIOOFF_T PIO_win32_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_T offset, INTVAL whence); +PIOOFF_T PIO_win32_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io); /* Convert to platform specific bit open flags */ @@ -105,6 +105,12 @@ } +INTVAL PIO_win32_getblksize(PIOHANDLE fd) { + /* Hard coded for now */ + return PIO_BLKSIZE; +} + + ParrotIO * PIO_win32_open(theINTERP, ParrotIOLayer * layer, const char * spath, UINTVAL flags) { int type; @@ -172,38 +178,54 @@ return 0; } + void PIO_win32_flush(theINTERP, ParrotIOLayer * layer, ParrotIO * io) { + /* No op */ } size_t PIO_win32_read(theINTERP, ParrotIOLayer * layer, ParrotIO * io, void * buffer, size_t len) { - return 0; + DWORD countread; + if(ReadFile(io->fd, (LPVOID)buffer, (DWORD)len, &countread, NULL)) + return countread; + else { + if(GetLastError() != NO_ERROR) { + /* FIXME : An error occured */ + } else if(len > 0) { + /* FIXME : Set EOF if bytes were requested */ + } + return 0; + } + return -1; } size_t PIO_win32_write(theINTERP, ParrotIOLayer * layer, ParrotIO * io, const void * buffer, size_t len) { - return 0; + LPCTSTR msg; + DWORD countwrote = 0; + if(WriteFile(io->fd, (LPCSTR)buffer, (DWORD)len, &countwrote, NULL)) + return countwrote; + /* FIXME: Set error flag */ + return -1; } /* - * puts tries WriteConsole first, then WriteFile, whereas - * write calls WriteFile only. + * puts() tries WriteConsole() first, then WriteFile(), whereas + * write() calls WriteFile() only. I've also read that WriteFile + * will call WriteConsole if the handle is the right type (console) so + * I suppose this is saving a function call since puts is probably + * used for consoles a lot. */ 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; - } + DWORD len, countwrote; + len = _tcslen((LPCSTR)s); + if(WriteConsole(io->fd, (LPCSTR)s, len, &countwrote, NULL) + || WriteFile(io->fd, (LPCSTR)s, len, &countwrote, NULL)) + return countwrote; return -1; } @@ -211,23 +233,26 @@ /* * 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; -*/ - internal_exception( IO_NOT_IMPLEMENTED, "Seek not yet implemented on HANDLEs"); - return 0; +PIOOFF_T PIO_win32_seek(theINTERP, ParrotIOLayer * l, ParrotIO * io, + PIOOFF_T offset, INTVAL whence) { + PIOOFF_T p; + p.LowPart = SetFilePointer(io->fd, offset.LowPart, &offset.HighPart, + FILE_CURRENT); + if(p.LowPart == 0xFFFFFFFF && (GetLastError() != NO_ERROR)) { + /* FIXME: Error - exception */ + } + io->fpos = p; + return p; } -off_t PIO_win32_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) { -/* off_t p; - p = lseek(io->fd, (off_t)0, SEEK_CUR); +PIOOFF_T PIO_win32_tell(theINTERP, ParrotIOLayer * l, ParrotIO * io) { + PIOOFF_T p = piooffsetzero; + p.LowPart = SetFilePointer(io->fd, 0, &p.HighPart, FILE_CURRENT); + if(p.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { + /* FIXME: Error - exception */ + } return p; -*/ - internal_exception( IO_NOT_IMPLEMENTED, "Seek not yet implemented on HANDLEs"); - return 0; }