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