3 IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
4 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
5 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
6 stdin, stdout, stderr, openFile, hClose, hFileSize, hIsEOF, isEOF,
7 hSetBuffering, hGetBuffering, hFlush, hGetPosn, hSetPosn, hSeek,
8 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable, hReady,
9 hGetChar, hLookAhead, hGetContents, hPutChar, hPutStr, hPrint,
10 isAlreadyExistsError, isAlreadyInUseError, isFullError, isEOFError,
11 isIllegalOperation, isPermissionError, isUserError,
12 ioeGetHandle, ioeGetFileName ) where
15 import GHCio -- much of the real stuff is in here
17 import GHCps ( nilPS, packCBytesST, unpackPS )
19 --GHCio:hClose :: Handle -> IO ()
20 --GHCio:hFileSize :: Handle -> IO Integer
21 --GHCio:hFlush :: Handle -> IO ()
22 --GHCio:hGetBuffering :: Handle -> IO BufferMode
23 hGetChar :: Handle -> IO Char
24 hGetContents :: Handle -> IO String
25 --GHCio:hGetPosn :: Handle -> IO HandlePosn
26 --GHCio:hIsClosed :: Handle -> IO Bool
27 --GHCio:hIsEOF :: Handle -> IO Bool
28 --GHCio:hIsOpen :: Handle -> IO Bool
29 --GHCio:hIsReadable :: Handle -> IO Bool
30 --GHCio:hIsSeekable :: Handle -> IO Bool
31 --GHCio:hIsWritable :: Handle -> IO Bool
32 hLookAhead :: Handle -> IO Char
33 hPrint :: Show a => Handle -> a -> IO ()
34 hPutChar :: Handle -> Char -> IO ()
35 hPutStr :: Handle -> String -> IO ()
36 hReady :: Handle -> IO Bool
37 --GHCio:hSeek :: Handle -> SeekMode -> Integer -> IO ()
38 --GHCio:hSetBuffering :: Handle -> BufferMode -> IO ()
39 --GHCio:hSetPosn :: HandlePosn -> IO ()
40 ioeGetFileName :: IOError -> Maybe FilePath
41 ioeGetHandle :: IOError -> Maybe Handle
42 isAlreadyExistsError :: IOError -> Bool
43 isAlreadyInUseError :: IOError -> Bool
44 --GHCio:isEOF :: IO Bool
45 isEOFError :: IOError -> Bool
46 isFullError :: IOError -> Bool
47 isIllegalOperation :: IOError -> Bool
48 isPermissionError :: IOError -> Bool
49 isUserError :: IOError -> Maybe String
50 --GHCio:openFile :: FilePath -> IOMode -> IO Handle
51 --GHCio:stdin, stdout, stderr :: Handle
53 ---------------------------
54 -- Computation $hReady hdl$ indicates whether at least
55 -- one item is available for input from handle {\em hdl}.
57 --hReady :: Handle -> IO Bool
59 readHandle handle >>= \ htype ->
61 ErrorHandle ioError ->
62 writeHandle handle htype >>
65 writeHandle handle htype >>
66 fail (IllegalOperation "handle is closed")
67 SemiClosedHandle _ _ ->
68 writeHandle handle htype >>
69 fail (IllegalOperation "handle is closed")
71 writeHandle handle htype >>
72 fail (IllegalOperation "handle is not open for reading")
74 writeHandle handle htype >>
75 fail (IllegalOperation "handle is not open for reading")
77 _ccall_ inputReady (filePtr other) `stThen` \ rc ->
78 writeHandle handle (markHandle htype) >>
82 _ -> constructErrorAndFail "hReady"
84 ---------------------------
85 --Computation $hGetChar hdl$ reads the next character from handle {\em
86 --hdl}, blocking until a character is available.
88 --hGetChar :: Handle -> IO Char
91 readHandle handle >>= \ htype ->
93 ErrorHandle ioError ->
94 writeHandle handle htype >>
97 writeHandle handle htype >>
98 fail (IllegalOperation "handle is closed")
99 SemiClosedHandle _ _ ->
100 writeHandle handle htype >>
101 fail (IllegalOperation "handle is closed")
102 AppendHandle _ _ _ ->
103 writeHandle handle htype >>
104 fail (IllegalOperation "handle is not open for reading")
106 writeHandle handle htype >>
107 fail (IllegalOperation "handle is not open for reading")
109 _ccall_ fileGetc (filePtr other) `stThen` \ intc ->
110 writeHandle handle (markHandle htype) >>
111 if intc /= ``EOF'' then
114 constructErrorAndFail "hGetChar"
116 -------------------------------
117 -- Computation $hLookahead hdl$ returns the next character from handle
118 --{\em hdl} without removing it from the input buffer, blocking until a
119 -- character is available.
121 --hLookAhead :: Handle -> IO Char
124 readHandle handle >>= \ htype ->
126 ErrorHandle ioError ->
127 writeHandle handle htype >>
130 writeHandle handle htype >>
131 fail (IllegalOperation "handle is closed")
132 SemiClosedHandle _ _ ->
133 writeHandle handle htype >>
134 fail (IllegalOperation "handle is closed")
135 AppendHandle _ _ _ ->
136 writeHandle handle htype >>
137 fail (IllegalOperation "handle is not open for reading")
139 writeHandle handle htype >>
140 fail (IllegalOperation "handle is not open for reading")
142 _ccall_ fileLookAhead (filePtr other) `stThen` \ intc ->
143 writeHandle handle (markHandle htype) >>
144 if intc /= ``EOF'' then
147 constructErrorAndFail "hLookAhead"
149 -----------------------------------
150 -- Computation $hGetContents hdl$ returns the list of characters
151 -- corresponding to the unread portion of the channel or file managed by
152 -- {\em hdl}, which is made semi-closed.
154 --hGetContents :: Handle -> IO String
156 hGetContents handle =
157 readHandle handle >>= \ htype ->
159 ErrorHandle ioError ->
160 writeHandle handle htype >>
163 writeHandle handle htype >>
164 fail (IllegalOperation "handle is closed")
165 SemiClosedHandle _ _ ->
166 writeHandle handle htype >>
167 fail (IllegalOperation "handle is closed")
168 AppendHandle _ _ _ ->
169 writeHandle handle htype >>
170 fail (IllegalOperation "handle is not open for reading")
172 writeHandle handle htype >>
173 fail (IllegalOperation "handle is not open for reading")
176 To avoid introducing an extra layer of buffering here,
177 we provide three lazy read methods, based on character,
178 line, and block buffering.
180 stToIO (getBufferMode other) >>= \ other ->
181 case (bufferMode other) of
182 Just LineBuffering ->
183 allocBuf Nothing >>= \ buf_info ->
184 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
186 unsafeInterleavePrimIO (lazyReadLine handle)
187 `stThen` \ contents ->
190 Just (BlockBuffering size) ->
191 allocBuf size >>= \ buf_info ->
192 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
194 unsafeInterleavePrimIO (lazyReadBlock handle)
195 `stThen` \ contents ->
197 _ -> -- Nothing is treated pessimistically as NoBuffering
198 writeHandle handle (SemiClosedHandle (filePtr other) (``NULL'', 0))
200 unsafeInterleavePrimIO (lazyReadChar handle)
201 `stThen` \ contents ->
204 allocBuf :: Maybe Int -> IO (Addr, Int)
206 _ccall_ malloc size `stThen` \ buf ->
207 if buf /= ``NULL'' then
210 fail (ResourceExhausted "not enough virtual memory")
215 Nothing -> ``BUFSIZ''
218 Note that someone may yank our handle out from under us, and then re-use
219 the same FILE * for something else. Therefore, we have to re-examine the
220 handle every time through.
223 lazyReadBlock :: Handle -> PrimIO String
224 lazyReadLine :: Handle -> PrimIO String
225 lazyReadChar :: Handle -> PrimIO String
227 lazyReadBlock handle =
228 ioToST (readHandle handle) >>= \ htype ->
230 -- There cannae be an ErrorHandle here
232 ioToST (writeHandle handle htype) >>
234 SemiClosedHandle fp (buf, size) ->
235 _ccall_ readBlock buf fp size >>= \ bytes ->
238 else packCBytesST bytes buf) >>= \ some ->
240 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
242 _ccall_ free buf >>= \ () ->
243 _ccall_ closeFile fp >>
244 returnPrimIO (unpackPS some)
246 ioToST (writeHandle handle htype) >>
247 unsafeInterleavePrimIO (lazyReadBlock handle)
249 returnPrimIO (unpackPS some ++ more)
251 lazyReadLine handle =
252 ioToST (readHandle handle) >>= \ htype ->
254 -- There cannae be an ErrorHandle here
256 ioToST (writeHandle handle htype) >>
258 SemiClosedHandle fp (buf, size) ->
259 _ccall_ readLine buf fp size >>= \ bytes ->
262 else packCBytesST bytes buf) >>= \ some ->
264 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
266 _ccall_ free buf >>= \ () ->
267 _ccall_ closeFile fp >>
268 returnPrimIO (unpackPS some)
270 ioToST (writeHandle handle htype) >>
271 unsafeInterleavePrimIO (lazyReadLine handle)
273 returnPrimIO (unpackPS some ++ more)
275 lazyReadChar handle =
276 ioToST (readHandle handle) >>= \ htype ->
278 -- There cannae be an ErrorHandle here
280 ioToST (writeHandle handle htype) >>
282 SemiClosedHandle fp buf_info ->
283 _ccall_ readChar fp >>= \ char ->
284 if char == ``EOF'' then
285 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' buf_info))
287 _ccall_ closeFile fp >>
290 ioToST (writeHandle handle htype) >>
291 unsafeInterleavePrimIO (lazyReadChar handle)
293 returnPrimIO (chr char : more)
295 -----------------------------------
296 -- Computation $hPutChar hdl c$ writes the character {\em c} to the file
297 -- or channel managed by {\em hdl}. Characters may be buffered if
298 -- buffering is enabled for {\em hdl}.
300 --hPutChar :: Handle -> Char -> IO ()
303 readHandle handle >>= \ htype ->
305 ErrorHandle ioError ->
306 writeHandle handle htype >>
309 writeHandle handle htype >>
310 fail (IllegalOperation "handle is closed")
311 SemiClosedHandle _ _ ->
312 writeHandle handle htype >>
313 fail (IllegalOperation "handle is closed")
315 writeHandle handle htype >>
316 fail (IllegalOperation "handle is not open for writing")
318 _ccall_ filePutc (filePtr other) (ord c) `stThen` \ rc ->
319 writeHandle handle (markHandle htype) >>
323 constructErrorAndFail "hPutChar"
325 ------------------------------------
326 -- Computation $hPutStr hdl s$ writes the string {\em s} to the file or
327 -- channel managed by {\em hdl}.
329 --hPutStr :: Handle -> String -> IO ()
332 readHandle handle >>= \ htype ->
334 ErrorHandle ioError ->
335 writeHandle handle htype >>
338 writeHandle handle htype >>
339 fail (IllegalOperation "handle is closed")
340 SemiClosedHandle _ _ ->
341 writeHandle handle htype >>
342 fail (IllegalOperation "handle is closed")
344 writeHandle handle htype >>
345 fail (IllegalOperation "handle is not open for writing")
347 getBufferMode other `stThen` \ other ->
348 (case bufferMode other of
349 Just LineBuffering ->
350 writeLines (filePtr other) str
351 Just (BlockBuffering (Just size)) ->
352 writeBlocks (filePtr other) size str
353 Just (BlockBuffering Nothing) ->
354 writeBlocks (filePtr other) ``BUFSIZ'' str
355 _ -> -- Nothing is treated pessimistically as NoBuffering
356 writeChars (filePtr other) str
357 ) `stThen` \ success ->
358 writeHandle handle (markHandle other) >>
362 constructErrorAndFail "hPutStr"
364 writeLines :: Addr -> String -> PrimIO Bool
365 writeLines = writeChunks ``BUFSIZ'' True
367 writeBlocks :: Addr -> Int -> String -> PrimIO Bool
368 writeBlocks fp size s = writeChunks size False fp s
371 The breaking up of output into lines along \n boundaries
372 works fine as long as there are newlines to split by.
373 Avoid the splitting up into lines alltogether (doesn't work
374 for overly long lines like the stuff that showsPrec instances
375 normally return). Instead, we split them up into fixed size
376 chunks before blasting them off to the Real World.
378 Hacked to avoid multiple passes over the strings - unsightly, but
379 a whole lot quicker. -- SOF 3/96
382 writeChunks :: Int -> Bool -> Addr -> String -> PrimIO Bool
384 writeChunks (I# bufLen) chopOnNewLine fp s =
385 newCharArray (0,I# bufLen) >>= \ arr@(MutableByteArray _ arr#) ->
387 write_char :: MutableByteArray# RealWorld -> Int# -> Char# -> PrimIO ()
388 write_char arr# n x = ST $ \ (S# s#) ->
389 case (writeCharArray# arr# n x s#) of { s1# ->
392 shoveString :: Int# -> [Char] -> PrimIO Bool
396 if n `eqInt#` 0# then
399 _ccall_ writeFile arr fp (I# n) >>= \rc ->
403 write_char arr# n x >>
405 {- Flushing lines - should we bother? -}
406 if n `eqInt#` bufLen {- || (chopOnNewLine && (x `eqChar#` '\n'#)) -} then
407 _ccall_ writeFile arr fp (I# (n `plusInt#` 1#)) >>= \ rc ->
413 shoveString (n `plusInt#` 1#) xs
417 writeChars :: Addr -> String -> PrimIO Bool
418 writeChars fp "" = returnPrimIO True
419 writeChars fp (c:cs) =
420 _ccall_ filePutc fp (ord c) >>= \ rc ->
426 ------------------------------------------
427 -- Computation $hPrint hdl t$ writes the string representation of {\em
428 -- t} given by the $shows$ function to the file or channel managed by
431 --hPrint :: Show a => Handle -> a -> IO ()
432 hPrint hdl = hPutStr hdl . show
434 ------------------------------------------
435 -- almost no effort made on these so far...
437 isAlreadyExistsError (AlreadyExists _) = True
438 isAlreadyExistsError _ = False
440 isAlreadyInUseError (ResourceBusy _) = True
441 isAlreadyInUseError _ = False
443 isFullError (ResourceExhausted _) = True
444 isFullError _ = False
446 isEOFError EOF = True
449 isIllegalOperation (IllegalOperation _) = True
450 isIllegalOperation _ = False
452 isPermissionError (PermissionDenied _) = True
453 isPermissionError _ = False
455 isUserError (UserError s) = Just s
456 isUserError _ = Nothing
458 ioeGetHandle _ = Nothing -- a stub, essentially
460 ioeGetFileName _ = Nothing -- a stub, essentially