/*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
*
- * $Id: fileGetc.c,v 1.1 1998/04/10 10:54:22 simonm Exp $
+ * $Id: fileGetc.c,v 1.6 2000/01/18 12:41:03 simonmar Exp $
*
* hGetChar Runtime Support
*/
#include "Rts.h"
#include "stgio.h"
-#include "error.h"
+#define EOT 4
+
+/* Pre-condition: only ever called on a readable fileObject */
StgInt
-fileGetc(StgAddr fp)
+fileGetc(StgForeignPtr ptr)
{
- int c;
+ IOFileObject* fo = (IOFileObject*)ptr;
+ int rc=0;
+ unsigned char c;
+
+#if 0
+ fprintf(stderr, "fgc: %d %d %d\n", fo->bufRPtr, fo->bufWPtr, fo->flags);
+#endif
+ /*
+ fileGetc does the following:
+ - if the input is buffered, try fetch the char from buffer.
+ - failing that,
+
+ - if the input stream is 'connected' to an output stream,
+ flush it before requesting any input.
+ - if unbuffered, read in one character.
+ - if line-buffered, read in one line, returning the first.
+ - if block-buffered, fill up block, returning the first.
+ */
- if (feof((FILE *)fp)) {
- ghc_errtype = ERR_EOF;
- ghc_errstr = "";
- return EOF;
+ if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) && FILEOBJ_NEEDS_FLUSHING(fo) ) {
+ rc = flushBuffer(ptr);
+ if (rc < 0) return rc;
}
- /* Try to read a character */
- while ((c = getc((FILE *)fp)) == EOF && errno == EINTR)
- clearerr((FILE *)fp);
+ fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
- if (feof((FILE *)fp)) {
+ if ( FILEOBJ_IS_EOF(fo) ) {
ghc_errtype = ERR_EOF;
ghc_errstr = "";
- } else if (c == EOF) {
- cvtErrno();
- stdErrno();
+ return -1;
+ }
+
+ if ( FILEOBJ_BUFFER_EMPTY(fo) ) {
+ ;
+ } else if ( FILEOBJ_UNBUFFERED(fo) && !FILEOBJ_HAS_PUSHBACKS(fo) ) {
+ ;
+ } else if ( FILEOBJ_UNBUFFERED(fo) ) { /* Unbuffered stream has pushbacks, retrieve them */
+ c=((unsigned char*)(fo->buf))[fo->bufRPtr++];
+ return (int)c;
+ } else {
+ c=((unsigned char*)(fo->buf))[fo->bufRPtr];
+ fo->bufRPtr++;
+ return (int)c;
+ }
+
+ /* Nothing in the buffer, go out and fetch a byte for our customer,
+ filling up the buffer if needs be.
+ */
+ if ( FILEOBJ_UNBUFFERED(fo) ) {
+ return (readChar(ptr));
+ } else if ( FILEOBJ_LINEBUFFERED(fo) ) {
+
+ /* if input stream is connect to an output stream, flush it first */
+ if ( fo->connectedTo != NULL &&
+ fo->connectedTo->fd != -1 &&
+ (fo->connectedTo->flags & FILEOBJ_WRITE) ) {
+ rc = flushFile((StgForeignPtr)fo->connectedTo);
+ }
+ if (rc < 0) return rc;
+
+ rc = fill_up_line_buffer(fo);
+ if (rc < 0) return rc;
+
+ c=((unsigned char*)(fo->buf))[fo->bufRPtr];
+ fo->bufRPtr++;
+ return (int)c;
+
+ } else { /* Fully-buffered */
+ rc = readBlock(ptr);
+ if (rc < 0) return rc;
+
+ c=((unsigned char*)(fo->buf))[fo->bufRPtr];
+ fo->bufRPtr++;
+ return (int)c;
}
- return c;
}