1 {-# OPTIONS -fno-implicit-prelude #-}
5 -- -----------------------------------------------------------------------------
6 -- $Id: PrelIO.hsc,v 1.12 2001/09/14 14:51:06 simonmar Exp $
8 -- (c) The University of Glasgow, 1992-2001
12 -- This module defines all basic IO operations.
13 -- These are needed for the IO operations exported by Prelude,
14 -- but as it happens they also do everything required by library
20 #include "PrelHandle_hsc.h"
25 import PrelMarshalUtils
33 import PrelHandle -- much of the real stuff is in here
40 import PrelMaybe ( Maybe(..) )
43 import PrelException ( ioError, catch, throw )
46 -- -----------------------------------------------------------------------------
49 putChar :: Char -> IO ()
50 putChar c = hPutChar stdout c
52 putStr :: String -> IO ()
53 putStr s = hPutStr stdout s
55 putStrLn :: String -> IO ()
56 putStrLn s = do putStr s
59 print :: Show a => a -> IO ()
60 print x = putStrLn (show x)
63 getChar = hGetChar stdin
66 getLine = hGetLine stdin
68 getContents :: IO String
69 getContents = hGetContents stdin
71 interact :: (String -> String) -> IO ()
72 interact f = do s <- getContents
75 readFile :: FilePath -> IO String
76 readFile name = openFile name ReadMode >>= hGetContents
78 writeFile :: FilePath -> String -> IO ()
79 writeFile name str = do
80 hdl <- openFile name WriteMode
84 appendFile :: FilePath -> String -> IO ()
85 appendFile name str = do
86 hdl <- openFile name AppendMode
90 readLn :: Read a => IO a
91 readLn = do l <- getLine
95 -- raises an exception instead of an error
96 readIO :: Read a => String -> IO a
97 readIO s = case (do { (x,t) <- reads s ;
100 #ifndef NEW_READS_REP
102 [] -> ioError (userError "Prelude.readIO: no parse")
103 _ -> ioError (userError "Prelude.readIO: ambiguous parse")
106 Nothing -> ioError (userError "Prelude.readIO: no parse")
109 -- ---------------------------------------------------------------------------
110 -- Simple input operations
112 -- Computation "hReady hdl" indicates whether at least
113 -- one item is available for input from handle "hdl".
115 -- If hWaitForInput finds anything in the Handle's buffer, it
116 -- immediately returns. If not, it tries to read from the underlying
117 -- OS handle. Notice that for buffered Handles connected to terminals
118 -- this means waiting until a complete line is available.
120 hReady :: Handle -> IO Bool
121 hReady h = hWaitForInput h 0
123 hWaitForInput :: Handle -> Int -> IO Bool
124 hWaitForInput h msecs = do
125 wantReadableHandle "hReady" h $ \ handle_ -> do
126 let ref = haBuffer handle_
129 if not (bufferEmpty buf)
133 r <- throwErrnoIfMinus1Retry "hReady"
134 (inputReady (fromIntegral (haFD handle_)) (fromIntegral msecs))
137 foreign import "inputReady"
138 inputReady :: CInt -> CInt -> IO CInt
140 -- ---------------------------------------------------------------------------
143 -- hGetChar reads the next character from a handle,
144 -- blocking until a character is available.
146 hGetChar :: Handle -> IO Char
148 wantReadableHandle "hGetChar" handle $ \handle_ -> do
150 let fd = haFD handle_
151 ref = haBuffer handle_
154 if not (bufferEmpty buf)
155 then hGetcBuffered fd ref buf
159 case haBufferMode handle_ of
161 new_buf <- fillReadBuffer fd True buf
162 hGetcBuffered fd ref new_buf
163 BlockBuffering _ -> do
164 new_buf <- fillReadBuffer fd False buf
165 hGetcBuffered fd ref new_buf
167 -- make use of the minimal buffer we already have
169 r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
170 (read_off (fromIntegral fd) raw 0 1)
174 else do (c,_) <- readCharFromBuffer raw 0
177 hGetcBuffered fd ref buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w }
178 = do (c,r) <- readCharFromBuffer b r
179 let new_buf | r == w = buf{ bufRPtr=0, bufWPtr=0 }
180 | otherwise = buf{ bufRPtr=r }
181 writeIORef ref new_buf
184 -- ---------------------------------------------------------------------------
187 -- If EOF is reached before EOL is encountered, ignore the EOF and
188 -- return the partial line. Next attempt at calling hGetLine on the
189 -- handle will yield an EOF IO exception though.
191 -- ToDo: the unbuffered case is wrong: it doesn't lock the handle for
193 hGetLine :: Handle -> IO String
195 m <- wantReadableHandle "hGetLine" h $ \ handle_ -> do
196 case haBufferMode handle_ of
197 NoBuffering -> return Nothing
199 l <- hGetLineBuffered handle_
201 BlockBuffering _ -> do
202 l <- hGetLineBuffered handle_
205 Nothing -> hGetLineUnBuffered h
209 hGetLineBuffered handle_ = do
210 let ref = haBuffer handle_
212 hGetLineBufferedLoop handle_ ref buf []
215 hGetLineBufferedLoop handle_ ref
216 buf@Buffer{ bufRPtr=r, bufWPtr=w, bufBuf=raw } xss =
218 -- find the end-of-line character, if there is one
220 | r == w = return (False, w)
222 (c,r') <- readCharFromBuffer raw r
224 then return (True, r) -- NB. not r': don't include the '\n'
227 (eol, off) <- loop raw r
230 puts ("hGetLineBufferedLoop: r=" ++ show r ++ ", w=" ++ show w ++ ", off=" ++ show off ++ "\n")
233 xs <- unpack raw r off
235 then do if w == off + 1
236 then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
237 else writeIORef ref buf{ bufRPtr = off + 1 }
238 return (concat (reverse (xs:xss)))
240 maybe_buf <- maybeFillReadBuffer (haFD handle_) True
241 buf{ bufWPtr=0, bufRPtr=0 }
243 -- Nothing indicates we caught an EOF, and we may have a
244 -- partial line to return.
245 Nothing -> let str = concat (reverse (xs:xss)) in
250 hGetLineBufferedLoop handle_ ref new_buf (xs:xss)
253 maybeFillReadBuffer fd is_line buf
255 (do buf <- fillReadBuffer fd is_line buf
258 (\e -> do if isEOFError e
263 unpack :: RawBuffer -> Int -> Int -> IO [Char]
264 unpack buf r 0 = return ""
265 unpack buf (I## r) (I## len) = IO $ \s -> unpack [] (len -## 1##) s
268 | i <## r = (## s, acc ##)
270 case readCharArray## buf i s of
271 (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
274 hGetLineUnBuffered :: Handle -> IO String
275 hGetLineUnBuffered h = do
288 if isEOFError err then
298 -- -----------------------------------------------------------------------------
301 -- hGetContents returns the list of characters corresponding to the
302 -- unread portion of the channel or file managed by the handle, which
303 -- is made semi-closed.
305 -- hGetContents on a DuplexHandle only affects the read side: you can
306 -- carry on writing to it afterwards.
308 hGetContents :: Handle -> IO String
309 hGetContents handle =
310 withHandle "hGetContents" handle $ \handle_ ->
311 case haType handle_ of
312 ClosedHandle -> ioe_closedHandle
313 SemiClosedHandle -> ioe_closedHandle
314 AppendHandle -> ioe_notReadable
315 WriteHandle -> ioe_notReadable
316 _ -> do xs <- lazyRead handle
317 return (handle_{ haType=SemiClosedHandle}, xs )
319 -- Note that someone may close the semi-closed handle (or change its
320 -- buffering), so each time these lazy read functions are pulled on,
321 -- they have to check whether the handle has indeed been closed.
323 lazyRead :: Handle -> IO String
326 withHandle "lazyRead" handle $ \ handle_ -> do
327 case haType handle_ of
328 ClosedHandle -> return (handle_, "")
329 SemiClosedHandle -> lazyRead' handle handle_
331 (IOError (Just handle) IllegalOperation "lazyRead"
332 "illegal handle type" Nothing)
334 lazyRead' h handle_ = do
335 let ref = haBuffer handle_
338 -- even a NoBuffering handle can have a char in the buffer...
341 if not (bufferEmpty buf)
342 then lazyReadHaveBuffer h handle_ fd ref buf
345 case haBufferMode handle_ of
347 -- make use of the minimal buffer we already have
350 r <- throwErrnoIfMinus1RetryMayBlock "lazyRead"
351 (read_off (fromIntegral fd) raw 0 1)
354 then do handle_ <- hClose_help handle_
356 else do (c,_) <- readCharFromBuffer raw 0
358 return (handle_, c : rest)
360 LineBuffering -> lazyReadBuffered h handle_ fd ref buf
361 BlockBuffering _ -> lazyReadBuffered h handle_ fd ref buf
363 -- we never want to block during the read, so we call fillReadBuffer with
364 -- is_line==True, which tells it to "just read what there is".
365 lazyReadBuffered h handle_ fd ref buf = do
367 (do buf <- fillReadBuffer fd True{-is_line-} buf
368 lazyReadHaveBuffer h handle_ fd ref buf
370 -- all I/O errors are discarded. Additionally, we close the handle.
371 (\e -> do handle_ <- hClose_help handle_
375 lazyReadHaveBuffer h handle_ fd ref buf = do
377 writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
378 s <- unpackAcc (bufBuf buf) (bufRPtr buf) (bufWPtr buf) more
382 unpackAcc :: RawBuffer -> Int -> Int -> [Char] -> IO [Char]
383 unpackAcc buf r 0 acc = return ""
384 unpackAcc buf (I## r) (I## len) acc = IO $ \s -> unpack acc (len -## 1##) s
387 | i <## r = (## s, acc ##)
389 case readCharArray## buf i s of
390 (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
392 -- ---------------------------------------------------------------------------
395 -- `hPutChar hdl ch' writes the character `ch' to the file or channel
396 -- managed by `hdl'. Characters may be buffered if buffering is
397 -- enabled for `hdl'.
399 hPutChar :: Handle -> Char -> IO ()
401 c `seq` do -- must evaluate c before grabbing the handle lock
402 wantWritableHandle "hPutChar" handle $ \ handle_ -> do
403 let fd = haFD handle_
404 case haBufferMode handle_ of
405 LineBuffering -> hPutcBuffered handle_ True c
406 BlockBuffering _ -> hPutcBuffered handle_ False c
408 withObject (castCharToCChar c) $ \buf ->
409 throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
410 (c_write (fromIntegral fd) buf 1)
414 hPutcBuffered handle_ is_line c = do
415 let ref = haBuffer handle_
418 w' <- writeCharIntoBuffer (bufBuf buf) w c
419 let new_buf = buf{ bufWPtr = w' }
420 if bufferFull new_buf || is_line && c == '\n'
422 flushed_buf <- flushWriteBuffer (haFD handle_) new_buf
423 writeIORef ref flushed_buf
425 writeIORef ref new_buf
428 hPutChars :: Handle -> [Char] -> IO ()
429 hPutChars handle [] = return ()
430 hPutChars handle (c:cs) = hPutChar handle c >> hPutChars handle cs
432 -- ---------------------------------------------------------------------------
435 -- `hPutStr hdl s' writes the string `s' to the file or
436 -- hannel managed by `hdl', buffering the output if needs be.
438 -- We go to some trouble to avoid keeping the handle locked while we're
439 -- evaluating the string argument to hPutStr, in case doing so triggers another
440 -- I/O operation on the same handle which would lead to deadlock. The classic
443 -- putStr (trace "hello" "world")
445 -- so the basic scheme is this:
447 -- * copy the string into a fresh buffer,
448 -- * "commit" the buffer to the handle.
450 -- Committing may involve simply copying the contents of the new
451 -- buffer into the handle's buffer, flushing one or both buffers, or
452 -- maybe just swapping the buffers over (if the handle's buffer was
453 -- empty). See commitBuffer below.
455 hPutStr :: Handle -> String -> IO ()
456 hPutStr handle str = do
457 buffer_mode <- wantWritableHandle "hPutStr" handle
458 (\ handle_ -> do getSpareBuffer handle_)
460 (NoBuffering, _) -> do
461 hPutChars handle str -- v. slow, but we don't care
462 (LineBuffering, buf) -> do
463 writeLines handle buf str
464 (BlockBuffering _, buf) -> do
465 writeBlocks handle buf str
468 getSpareBuffer :: Handle__ -> IO (BufferMode, Buffer)
469 getSpareBuffer Handle__{haBuffer=ref,
474 NoBuffering -> return (mode, error "no buffer!")
476 bufs <- readIORef spare_ref
479 BufferListCons b rest -> do
480 writeIORef spare_ref rest
481 return ( mode, newEmptyBuffer b WriteBuffer (bufSize buf))
483 new_buf <- allocateBuffer (bufSize buf) WriteBuffer
484 return (mode, new_buf)
487 writeLines :: Handle -> Buffer -> String -> IO ()
488 writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
490 shoveString :: Int -> [Char] -> IO ()
491 -- check n == len first, to ensure that shoveString is strict in n.
492 shoveString n cs | n == len = do
493 new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
494 writeBlocks hdl new_buf cs
495 shoveString n [] = do
496 commitBuffer hdl raw len n False{-no flush-} True{-release-}
498 shoveString n (c:cs) = do
499 n' <- writeCharIntoBuffer raw n c
502 new_buf <- commitBuffer hdl raw len n' True{-needs flush-} False
503 writeBlocks hdl new_buf cs
509 writeBlocks :: Handle -> Buffer -> String -> IO ()
510 writeBlocks hdl Buffer{ bufBuf=raw, bufSize=len } s =
512 shoveString :: Int -> [Char] -> IO ()
513 -- check n == len first, to ensure that shoveString is strict in n.
514 shoveString n cs | n == len = do
515 new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
516 writeBlocks hdl new_buf cs
517 shoveString n [] = do
518 commitBuffer hdl raw len n False{-no flush-} True{-release-}
520 shoveString n (c:cs) = do
521 n' <- writeCharIntoBuffer raw n c
526 -- -----------------------------------------------------------------------------
527 -- commitBuffer handle buf sz count flush release
529 -- Write the contents of the buffer 'buf' ('sz' bytes long, containing
530 -- 'count' bytes of data) to handle (handle must be block or line buffered).
534 -- for block/line buffering,
535 -- 1. If there isn't room in the handle buffer, flush the handle
538 -- 2. If the handle buffer is empty,
540 -- then write buf directly to the device.
541 -- else swap the handle buffer with buf.
543 -- 3. If the handle buffer is non-empty, copy buf into the
544 -- handle buffer. Then, if flush != 0, flush
548 :: Handle -- handle to commit to
549 -> RawBuffer -> Int -- address and size (in bytes) of buffer
550 -> Int -- number of bytes of data in buffer
551 -> Bool -- flush the handle afterward?
552 -> Bool -- release the buffer?
555 commitBuffer hdl raw sz count flush release = do
556 wantWritableHandle "commitAndReleaseBuffer" hdl $
557 \ handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } -> do
560 puts ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count
561 ++ ", flush=" ++ show flush ++ ", release=" ++ show release ++"\n")
564 old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
568 -- enough room in handle buffer?
569 if (not flush && (size - w > count))
570 -- The > is to be sure that we never exactly fill
571 -- up the buffer, which would require a flush. So
572 -- if copying the new data into the buffer would
573 -- make the buffer full, we just flush the existing
574 -- buffer and the new data immediately, rather than
575 -- copying before flushing.
577 -- not flushing, and there's enough room in the buffer:
578 -- just copy the data in and update bufWPtr.
579 then do memcpy_off old_raw w raw (fromIntegral count)
580 writeIORef ref old_buf{ bufWPtr = w + count }
581 return (newEmptyBuffer raw WriteBuffer sz)
583 -- else, we have to flush
584 else do flushed_buf <- flushWriteBuffer fd old_buf
587 Buffer{ bufBuf=raw, bufState=WriteBuffer,
588 bufRPtr=0, bufWPtr=count, bufSize=sz }
590 -- if: (a) we don't have to flush, and
591 -- (b) size(new buffer) == size(old buffer), and
592 -- (c) new buffer is not full,
593 -- we can just just swap them over...
594 if (not flush && sz == size && count /= sz)
596 writeIORef ref this_buf
599 -- otherwise, we have to flush the new data too,
600 -- and start with a fresh buffer
602 flushWriteBuffer fd this_buf
603 writeIORef ref flushed_buf
604 -- if the sizes were different, then allocate
605 -- a new buffer of the correct size.
607 then return (newEmptyBuffer raw WriteBuffer sz)
608 else allocateBuffer size WriteBuffer
610 -- release the buffer if necessary
611 if release && bufSize buf_ret == size
613 spare_bufs <- readIORef spare_buf_ref
614 writeIORef spare_buf_ref
615 (BufferListCons (bufBuf buf_ret) spare_bufs)
621 foreign import "memcpy_PrelIO_wrap" unsafe
622 memcpy_off :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
624 void *memcpy_PrelIO_wrap(char *dst, HsInt dst_off, const char *src, size_t sz) \
625 { return memcpy(dst+dst_off, src, sz); }
627 -- ---------------------------------------------------------------------------
630 -- Derived action `hPutStrLn hdl str' writes the string `str' to
631 -- the handle `hdl', adding a newline at the end.
633 hPutStrLn :: Handle -> String -> IO ()
634 hPutStrLn hndl str = do
638 -- ---------------------------------------------------------------------------
641 -- Computation `hPrint hdl t' writes the string representation of `t'
642 -- given by the `shows' function to the file or channel managed by `hdl'.
644 hPrint :: Show a => Handle -> a -> IO ()
645 hPrint hdl = hPutStrLn hdl . show