2 % (c) The GRASP/AQUA Project, Glasgow University, 1994
4 \subsection[readFile.lc]{hGetContents Runtime Support}
13 /* Filling up a (block-buffered) buffer, that
14 is completely empty. */
19 IOFileObject* fo = (IOFileObject*)ptr;
23 /* Check if someone hasn't zapped us */
24 if ( fo == NULL || fo->fd == -1 )
29 if ( FILEOBJ_IS_EOF(fo) ) {
30 ghc_errtype = ERR_EOF;
35 /* Weird case: buffering has suddenly been turned off.
36 Return non-std value and deal with this case on the Haskell side.
38 if ( FILEOBJ_UNBUFFERED(fo) ) {
42 /* if input stream is connect to an output stream, flush this one first. */
43 if ( fo->connectedTo != NULL &&
44 fo->connectedTo->fd != -1 &&
45 (fo->connectedTo->flags & FILEOBJ_WRITE)
47 rc = flushFile((StgForeignObj)fo->connectedTo);
49 if (rc < 0) return (rc == FILEOBJ_BLOCKED_WRITE ? FILEOBJ_BLOCKED_CONN_WRITE : rc);
51 /* RW object: flush the (output) buffer first. */
52 if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) && FILEOBJ_NEEDS_FLUSHING(fo) ) {
53 rc = flushBuffer(ptr);
54 if (rc < 0) return rc;
56 fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
58 /* return the unread parts of the file buffer..*/
59 if ( fo->flags & FILEOBJ_READ &&
61 fo->bufWPtr > fo->bufRPtr ) {
62 count = fo->bufWPtr - fo->bufRPtr;
68 fprintf(stderr, "rb: %d %d %d\n", fo->bufRPtr, fo->bufWPtr, fo->bufSize);
71 if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady (ptr,0) != 1 )
72 return FILEOBJ_BLOCKED_READ;
74 while ((count = read(fd, fo->buf, fo->bufSize)) <= 0) {
77 ghc_errtype = ERR_EOF;
80 } else if ( count == -1 && errno == EAGAIN) {
82 return FILEOBJ_BLOCKED_READ;
83 } else if ( count == -1 && errno != EINTR) {
94 /* Filling up a (block-buffered) buffer of length len */
96 readChunk(ptr,buf,len)
101 IOFileObject* fo = (IOFileObject*)ptr;
102 int count=0,rc=0, total_count;
106 /* Check if someone hasn't zapped us */
112 if ( fd == -1 ) /* File has been closed for us */
115 if ( FILEOBJ_IS_EOF(fo) ) {
116 ghc_errtype = ERR_EOF;
121 /* if input stream is connect to an output stream, flush it first */
122 if ( fo->connectedTo != NULL &&
123 fo->connectedTo->fd != -1 &&
124 (fo->connectedTo->flags & FILEOBJ_WRITE)
126 rc = flushFile((StgForeignObj)fo->connectedTo);
128 if (rc < 0) return (rc == FILEOBJ_BLOCKED_WRITE ? FILEOBJ_BLOCKED_CONN_WRITE : rc);
130 /* RW object: flush the (output) buffer first. */
131 if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) && FILEOBJ_NEEDS_FLUSHING(fo) ) {
132 rc = flushBuffer(ptr);
133 if (rc < 0) return rc;
135 fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
137 /* copy the unread parts of the file buffer..*/
138 if ( FILEOBJ_READABLE(fo) &&
140 fo->bufWPtr >= fo->bufRPtr ) {
141 count = ( len < (fo->bufWPtr - fo->bufRPtr)) ? len : (fo->bufWPtr - fo->bufRPtr);
142 memcpy(buf,fo->buf, count);
148 if (len - count <= 0)
156 if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady (ptr,0) != 1 )
157 return FILEOBJ_BLOCKED_READ;
159 while ((count = read(fd, p, len)) < len) {
160 if ( count == 0 ) { /* EOF */
162 } else if ( count == -1 && errno == EAGAIN) {
164 return FILEOBJ_BLOCKED_READ;
165 } else if ( count == -1 && errno != EINTR) {
170 total_count += count;
175 total_count += count;
176 fo->bufWPtr = total_count;
182 readLine() tries to fill the buffer up with a line of chars, returning
183 the length of the resulting line.
185 Users of readLine() should immediately afterwards copy out the line
194 IOFileObject* fo = (IOFileObject*)ptr;
198 /* Check if someone hasn't zapped us */
199 if ( fo == NULL || fo->fd == -1 )
202 if ( FILEOBJ_IS_EOF(fo) ) {
203 ghc_errtype = ERR_EOF;
208 /* Weird case: buffering has been turned off.
209 Return non-std value and deal with this case on the Haskell side.
211 if ( FILEOBJ_UNBUFFERED(fo) ) {
215 /* if input stream is connect to an output stream, flush it first */
216 if ( fo->connectedTo != NULL &&
217 fo->connectedTo->fd != -1 &&
218 (fo->connectedTo->flags & FILEOBJ_WRITE)
220 rc = flushFile((StgForeignObj)fo->connectedTo);
222 if (rc < 0) return (rc == FILEOBJ_BLOCKED_WRITE ? FILEOBJ_BLOCKED_CONN_WRITE : rc);
224 /* RW object: flush the (output) buffer first. */
225 if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) ) {
226 rc = flushBuffer(ptr);
227 if (rc < 0) return rc;
229 fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
231 if ( fo->bufRPtr < 0 || fo->bufRPtr >= fo->bufWPtr ) { /* Buffer is empty */
232 fo->bufRPtr=0; fo->bufWPtr=0;
233 rc = fill_up_line_buffer(fo);
234 if (rc < 0) return rc;
238 unsigned char* s1 = memchr((unsigned char *)fo->buf+fo->bufRPtr, '\n', fo->bufWPtr - fo->bufRPtr);
239 if (s1 != NULL ) { /* Found one */
240 /* Note: we *don't* zero terminate the line */
241 count = s1 - ((unsigned char*)fo->buf + fo->bufRPtr) + 1;
242 fo->bufRPtr += count;
245 /* Just return partial line */
246 count = fo->bufWPtr - fo->bufRPtr;
247 fo->bufRPtr += count;
258 IOFileObject* fo= (IOFileObject*)ptr;
262 /* Check if someone hasn't zapped us */
263 if ( fo == NULL || fo->fd == -1)
266 if ( FILEOBJ_IS_EOF(fo) ) {
267 ghc_errtype = ERR_EOF;
272 /* Buffering has been changed, report back */
273 if ( FILEOBJ_LINEBUFFERED(fo) ) {
275 } else if ( FILEOBJ_BLOCKBUFFERED(fo) ) {
279 /* if input stream is connect to an output stream, flush it first */
280 if ( fo->connectedTo != NULL &&
281 fo->connectedTo->fd != -1 &&
282 (fo->connectedTo->flags & FILEOBJ_WRITE)
284 rc = flushFile((StgForeignObj)fo->connectedTo);
286 if (rc < 0) return (rc == FILEOBJ_BLOCKED_WRITE ? FILEOBJ_BLOCKED_CONN_WRITE : rc);
288 /* RW object: flush the (output) buffer first. */
289 if ( FILEOBJ_WRITEABLE(fo) && FILEOBJ_JUST_WRITTEN(fo) && FILEOBJ_NEEDS_FLUSHING(fo) ) {
290 rc = flushBuffer(ptr);
291 if (rc < 0) return rc;
293 fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
295 if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady (ptr,0) != 1 )
296 return FILEOBJ_BLOCKED_READ;
298 while ( (count = read(fo->fd, &c, 1)) <= 0 ) {
300 ghc_errtype = ERR_EOF;
303 } else if ( count == -1 && errno == EAGAIN) {
305 return FILEOBJ_BLOCKED_READ;
306 } else if ( count == -1 && errno != EINTR) {
313 if ( isatty(fo->fd) && c == EOT ) {