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