347853576b9243ae5c6f43eac8e1e06f4f1c5db3
[ghc-hetmet.git] / ghc / lib / std / cbits / fileLookAhead.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: fileLookAhead.c,v 1.5 1999/12/08 15:47:07 simonmar Exp $
5  *
6  * hLookAhead Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 StgInt
13 fileLookAhead(StgForeignPtr ptr)
14 {
15     IOFileObject* fo = (IOFileObject*)ptr;
16     int c, rc;
17    
18 #if 0
19     fprintf(stderr, "flh: %d %d %d\n",fo->bufRPtr, fo->bufWPtr, fo->flags);
20 #endif
21
22     /* 
23      * fileLookahead reads the next character (hopefully from the buffer),
24      * before putting it back and returning the char.
25      *
26      */
27
28     if ( FILEOBJ_IS_EOF(fo) ) {
29        ghc_errtype = ERR_EOF;
30        ghc_errstr = "";
31        return -1;
32     }
33
34     if ( (c = fileGetc(ptr)) < 0 ) {
35          return c;
36     }
37
38     rc = ungetChar(ptr,(char)c);
39     if ( rc < 0 ) {
40        return rc;
41     } else {
42        return c;
43     }
44 }
45
46 StgInt
47 ungetChar(StgForeignPtr ptr, StgChar c)
48 {
49   IOFileObject* fo = (IOFileObject*)ptr;
50   int sz = 0;
51
52 #if 0
53   fprintf(stderr, "ug: %d %d %c\n",fo->bufRPtr, fo->bufWPtr,(char)c, fo->flags);
54 #endif
55
56   /* Sanity check */
57   if ( !FILEOBJ_READABLE(fo) ) {
58       ghc_errno  = GHC_EINVAL;
59       ghc_errstr = "object not readable";
60       return -1;
61   }
62
63   /* For an unbuffered file object, we lazily
64      allocate a pushback buffer. The sizeof the pushback
65      buffer is (globally) configurable.
66   */
67   sz = getPushbackBufSize();
68   if ( FILEOBJ_UNBUFFERED(fo) && fo->buf==NULL && sz > 0 ) {
69      if ((fo->buf = malloc(sz*sizeof(char))) == NULL ) {
70         return -1;
71      }
72      fo->bufSize = sz;
73      ((unsigned char*)fo->buf)[sz-1]=(unsigned char)c;
74      fo->bufWPtr = sz;    /* Points one past the end of pushback buffer */
75      fo->bufRPtr = sz-1;  /* points to current char. */
76      return 0;
77   }
78
79   if ( fo->bufWPtr > 0 && fo->bufRPtr > 0 ) {
80     fo->bufRPtr -= 1;
81     ((unsigned char*)fo->buf)[fo->bufRPtr]=(unsigned char)c;
82     return 0;
83   } else if ( fo->buf != NULL  && 
84               fo->bufSize > 0  &&
85               fo->bufWPtr == 0 && 
86               fo->bufRPtr==0    ) { /* empty buffer waiting to be filled up */
87      fo->bufRPtr=fo->bufSize-1;
88      ((unsigned char*)fo->buf)[fo->bufRPtr]=(unsigned char)c;
89      fo->bufWPtr=fo->bufSize;
90      return 0;
91   } else {
92     return -1;
93   }
94 }