[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / lib / std / cbits / fileLookAhead.lc
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1994
3 %
4 \subsection[fileLookAhead.lc]{hLookAhead Runtime Support}
5
6 \begin{code}
7
8 #include "rtsdefs.h"
9 #include "stgio.h"
10
11 StgInt
12 fileLookAhead(ptr)
13 StgForeignObj 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(ptr,c)
48 StgForeignObj ptr;
49 StgChar c;
50 {
51   IOFileObject* fo = (IOFileObject*)ptr;
52   int rc = 0, sz = 0;
53
54 #if 0
55   fprintf(stderr, "ug: %d %d %c\n",fo->bufRPtr, fo->bufWPtr,(char)c, fo->flags);
56 #endif
57
58   /* Sanity check */
59   if ( !FILEOBJ_READABLE(fo) ) {
60       ghc_errno  = GHC_EINVAL;
61       ghc_errstr = "object not readable";
62       return -1;
63   }
64
65   /* For an unbuffered file object, we lazily
66      allocate a pushback buffer. The sizeof the pushback
67      buffer is (globally) configurable.
68   */
69   sz = getPushbackBufSize();
70   if ( FILEOBJ_UNBUFFERED(fo) && fo->buf==NULL && sz > 0 ) {
71      if ((fo->buf = malloc(sz*sizeof(char))) == NULL ) {
72         return -1;
73      }
74      fo->bufSize = sz;
75      ((unsigned char*)fo->buf)[sz-1]=(unsigned char)c;
76      fo->bufWPtr = sz;    /* Points one past the end of pushback buffer */
77      fo->bufRPtr = sz-1;  /* points to current char. */
78      return 0;
79   }
80
81   if ( fo->bufWPtr > 0 && fo->bufRPtr > 0 ) {
82     fo->bufRPtr -= 1;
83     ((unsigned char*)fo->buf)[fo->bufRPtr]=(unsigned char)c;
84     return 0;
85   } else if ( fo->buf != NULL  && 
86               fo->bufSize > 0  &&
87               fo->bufWPtr == 0 && 
88               fo->bufRPtr==0    ) { /* empty buffer waiting to be filled up */
89      fo->bufRPtr=fo->bufSize-1;
90      ((unsigned char*)fo->buf)[fo->bufRPtr]=(unsigned char)c;
91      fo->bufWPtr=fo->bufSize;
92      return 0;
93   } else {
94     return -1;
95   }
96 }
97 \end{code}