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