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