[project @ 2000-04-13 14:11:00 by simonmar]
[ghc-hetmet.git] / ghc / lib / std / cbits / fileGetc.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: fileGetc.c,v 1.6 2000/01/18 12:41:03 simonmar Exp $
5  *
6  * hGetChar Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #define EOT 4
13
14 /* Pre-condition: only ever called on a readable fileObject */
15 StgInt
16 fileGetc(StgForeignPtr ptr)
17 {
18     IOFileObject* fo = (IOFileObject*)ptr;
19     int rc=0;
20     unsigned char c;
21     
22 #if 0
23     fprintf(stderr, "fgc: %d %d %d\n", fo->bufRPtr, fo->bufWPtr, fo->flags);
24 #endif
25     /*
26       fileGetc does the following:
27         - if the input is buffered, try fetch the char from buffer.
28         - failing that,
29     
30           - if the input stream is 'connected' to an output stream,
31             flush it before requesting any input.
32           - if unbuffered, read in one character.
33           - if line-buffered, read in one line, returning the first.
34           - if block-buffered, fill up block, returning the first.
35     */
36
37     if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) && FILEOBJ_NEEDS_FLUSHING(fo) ) {
38         rc = flushBuffer(ptr);
39         if (rc < 0) return rc;
40     }
41
42     fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
43
44     if ( FILEOBJ_IS_EOF(fo) ) {
45         ghc_errtype = ERR_EOF;
46         ghc_errstr = "";
47         return -1;
48     }
49
50     if ( FILEOBJ_BUFFER_EMPTY(fo) ) {
51        ;
52     } else if ( FILEOBJ_UNBUFFERED(fo) && !FILEOBJ_HAS_PUSHBACKS(fo) ) {
53        ;
54     } else if ( FILEOBJ_UNBUFFERED(fo) ) { /* Unbuffered stream has pushbacks, retrieve them */
55           c=((unsigned char*)(fo->buf))[fo->bufRPtr++];
56           return (int)c;
57     } else {
58           c=((unsigned char*)(fo->buf))[fo->bufRPtr];
59           fo->bufRPtr++;
60           return (int)c;
61     }
62     
63     /* Nothing in the buffer, go out and fetch a byte for our customer,
64        filling up the buffer if needs be.
65     */
66     if ( FILEOBJ_UNBUFFERED(fo) ) {
67         return (readChar(ptr));
68     } else if ( FILEOBJ_LINEBUFFERED(fo) ) {
69
70         /* if input stream is connect to an output stream, flush it first */
71         if ( fo->connectedTo != NULL   &&
72              fo->connectedTo->fd != -1 &&
73             (fo->connectedTo->flags & FILEOBJ_WRITE)  ) {
74            rc = flushFile((StgForeignPtr)fo->connectedTo);
75         }
76         if (rc < 0) return rc;
77
78         rc = fill_up_line_buffer(fo);
79         if (rc < 0) return rc;
80
81         c=((unsigned char*)(fo->buf))[fo->bufRPtr];
82         fo->bufRPtr++;
83         return (int)c;
84
85     } else { /* Fully-buffered */
86         rc = readBlock(ptr);
87         if (rc < 0) return rc;
88   
89         c=((unsigned char*)(fo->buf))[fo->bufRPtr];
90         fo->bufRPtr++;
91         return (int)c;
92     }
93 }