[project @ 1999-05-05 10:33:13 by sof]
[ghc-hetmet.git] / ghc / lib / std / cbits / fileObject.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: fileObject.c,v 1.3 1999/05/05 10:33:14 sof Exp $
5  *
6  * hPutStr Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11 #include "fileObject.h"
12
13 #include <stdio.h>
14
15 #ifdef HAVE_WINSOCK_H
16 #include <winsock.h>
17 #endif
18
19 void
20 setBufFlags(fo, flg)
21 StgForeignPtr fo;
22 StgInt flg;
23 {
24   ((IOFileObject*)fo)->flags = flg;
25   return;
26 }
27
28 void
29 setBufWPtr(fo, len)
30 StgForeignPtr fo;
31 StgInt len;
32 {
33   ((IOFileObject*)fo)->bufWPtr = len;
34   return;
35 }
36
37 StgInt
38 getBufWPtr(fo)
39 StgForeignPtr fo;
40 {
41   return (((IOFileObject*)fo)->bufWPtr);
42 }
43
44 StgInt
45 getBufSize(fo)
46 StgForeignPtr fo;
47 {
48   return (((IOFileObject*)fo)->bufSize);
49 }
50
51 void
52 setBuf(fo, buf,sz)
53 StgForeignPtr fo;
54 StgAddr buf;
55 StgInt sz;
56 {
57   ((IOFileObject*)fo)->buf     = buf;
58   ((IOFileObject*)fo)->bufSize = sz;
59   return;
60 }
61
62 StgAddr
63 getBuf(fo)
64 StgForeignPtr fo;
65 { return (((IOFileObject*)fo)->buf); }
66
67 StgAddr
68 getWriteableBuf(ptr)
69 StgForeignPtr ptr;
70
71    /* getWriteableBuf() is called prior to starting to pack
72       a Haskell string into the IOFileObject buffer. It takes
73       care of flushing the (input) buffer in the case we're
74       dealing with a RW handle.
75    */
76    IOFileObject* fo = (IOFileObject*)ptr;
77
78    if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
79       flushReadBuffer(ptr);  /* ignoring return code */
80       /* Ahead of time really, but indicate that we're (just about to) write */
81    }
82    fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
83    return (fo->buf);
84 }
85
86 StgAddr
87 getBufStart(fo,count)
88 StgForeignPtr fo;
89 StgInt count;
90 { return ((char*)((IOFileObject*)fo)->buf + (((IOFileObject*)fo)->bufRPtr) - count); }
91
92 StgInt
93 getFileFd(fo)
94 StgForeignPtr fo;
95 { return (((IOFileObject*)fo)->fd); }
96
97 StgInt
98 getConnFileFd(fo)
99 StgForeignPtr fo;
100 { return (((IOFileObject*)fo)->connectedTo->fd); }
101
102
103 void
104 setFd(fo,fp)
105 StgForeignPtr fo;
106 StgInt fp;
107 { ((IOFileObject*)fo)->fd = fp;
108   return;
109 }
110
111 void
112 setConnectedTo(fo, fw, flg)
113 StgForeignPtr fo;
114 StgForeignPtr fw;
115 StgInt flg;
116 {
117   if( flg && (! isatty(((IOFileObject*)fo)->fd) || !isatty(((IOFileObject*)fw)->fd)) ) {
118       return;
119   }
120  ((IOFileObject*)fo)->connectedTo = (IOFileObject*)fw;
121   return;
122 }
123
124 static int __pushback_buf_size__ = 2;
125
126 void
127 setPushbackBufSize(i)
128 StgInt i;
129 { __pushback_buf_size__ = (i > 0 ? i : 0); }
130
131 StgInt
132 getPushbackBufSize()
133 { return (__pushback_buf_size__); }
134
135 void
136 clearNonBlockingIOFlag__ (ptr)
137 StgForeignPtr ptr;
138 { ((IOFileObject*)ptr)->flags &= ~FILEOBJ_NONBLOCKING_IO; }
139
140 void
141 setNonBlockingIOFlag__ (ptr)
142 StgForeignPtr ptr;
143 { ((IOFileObject*)ptr)->flags |= FILEOBJ_NONBLOCKING_IO; }
144
145 void
146 clearConnNonBlockingIOFlag__ (ptr)
147 StgForeignPtr ptr;
148 { ((IOFileObject*)ptr)->connectedTo->flags &= ~FILEOBJ_NONBLOCKING_IO; }
149
150 void
151 setConnNonBlockingIOFlag__ (ptr)
152 StgForeignPtr ptr;
153
154   if ( ((IOFileObject*)ptr)->connectedTo != NULL )  {
155     ((IOFileObject*)ptr)->connectedTo->flags |= FILEOBJ_NONBLOCKING_IO;
156   }
157   return;
158 }
159
160
161 /* Only ever called on line-buffered file objects */
162 StgInt
163 fill_up_line_buffer(fo)
164 IOFileObject* fo;
165 {
166   int count,len, ipos;
167   unsigned char* p;
168
169   /* ToDo: deal with buffer overflow (i.e., realloc buffer if this happens) */
170  
171   if ( fo->bufRPtr == fo->bufWPtr ) { /* There's nothing in the buffer, reset */
172       fo->bufRPtr=0;
173       fo->bufWPtr=0;
174   }
175   ipos = fo->bufWPtr;
176   len = fo->bufSize - fo->bufWPtr + 1;
177   p   = (unsigned char*)fo->buf + fo->bufWPtr;
178
179   if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady ((StgForeignPtr)fo,0) != 1 )
180      return FILEOBJ_BLOCKED_READ;
181
182   if ((count = 
183          (
184 #ifdef HAVE_WINSOCK_H
185            fo->flags & FILEOBJ_WINSOCK ?
186            recv(fo->fd, p, len, 0) :
187            read(fo->fd, p, len))) <= 0 ) {
188 #else
189            read(fo->fd, p, len))) <= 0 ) {
190 #endif    
191       if (count == 0) {
192          ghc_errtype = ERR_EOF;
193          ghc_errstr = "";
194          FILEOBJ_SET_EOF(fo);
195          return -1;
196       } else if ( count == -1 && errno == EAGAIN) {
197          errno = 0;
198          return FILEOBJ_BLOCKED_READ;
199       } else if ( count == -1 && errno != EINTR ) {
200          cvtErrno();
201          stdErrno();
202          return -1;
203       }
204   }
205   fo->bufWPtr += count;
206   return (fo->bufWPtr - ipos);
207 }