-{-# OPTIONS -fno-implicit-prelude -#include "HsCore.h" #-}
+{-# OPTIONS -fno-implicit-prelude -#include "HsBase.h" #-}
#undef DEBUG_DUMP
--- -----------------------------------------------------------------------------
--- $Id: IO.hs,v 1.1 2001/12/21 15:07:23 simonmar Exp $
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.IO
+-- Copyright : (c) The University of Glasgow, 1992-2001
+-- License : see libraries/base/LICENSE
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : internal
+-- Portability : non-portable
--
--- (c) The University of Glasgow, 1992-2001
+-- String I\/O functions
--
--- Module GHC.IO
-
--- This module defines all basic IO operations.
--- These are needed for the IO operations exported by Prelude,
--- but as it happens they also do everything required by library
--- module IO.
+-----------------------------------------------------------------------------
module GHC.IO (
- putChar, putStr, putStrLn, print, getChar, getLine, getContents,
- interact, readFile, writeFile, appendFile, readLn, readIO, hReady,
hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
- hPutStrLn, hPrint,
commitBuffer', -- hack, see below
hGetcBuffered, -- needed by ghc/compiler/utils/StringBuffer.lhs
- hGetBuf, hPutBuf, slurpFile
+ hGetBuf, hPutBuf, slurpFile,
+ memcpy_ba_baoff,
+ memcpy_ptr_baoff,
+ memcpy_baoff_ba,
+ memcpy_baoff_ptr,
) where
import Foreign
import Foreign.C
+import System.IO.Error
import Data.Maybe
import Control.Monad
import GHC.Num
import GHC.Show
import GHC.List
-import GHC.Exception ( ioError, catch, throw )
+import GHC.Exception ( ioError, catch )
import GHC.Conc
-- ---------------------------------------------------------------------------
hWaitForInput :: Handle -> Int -> IO Bool
hWaitForInput h msecs = do
- wantReadableHandle "hReady" h $ \ handle_ -> do
+ wantReadableHandle "hWaitForInput" h $ \ handle_ -> do
let ref = haBuffer handle_
buf <- readIORef ref
then return True
else do
- r <- throwErrnoIfMinus1Retry "hReady"
+ r <- throwErrnoIfMinus1Retry "hWaitForInput"
(inputReady (fromIntegral (haFD handle_)) (fromIntegral msecs) (haIsStream handle_))
return (r /= 0)
-foreign import "inputReady" unsafe
+foreign import ccall unsafe "inputReady"
inputReady :: CInt -> CInt -> Bool -> IO CInt
-- ---------------------------------------------------------------------------
-- make use of the minimal buffer we already have
let raw = bufBuf buf
r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
- (read_off (fromIntegral fd) (haIsStream handle_) raw 0 1)
+ (read_off_ba (fromIntegral fd) (haIsStream handle_) raw 0 1)
(threadWaitRead fd)
if r == 0
then ioe_EOF
#endif
xs <- unpack raw r off
+
+ -- if eol == True, then off is the offset of the '\n'
+ -- otherwise off == w and the buffer is now empty.
if eol
- then do if w == off + 1
- then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
- else writeIORef ref buf{ bufRPtr = off + 1 }
+ then do if (w == off + 1)
+ then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ else writeIORef ref buf{ bufRPtr = off + 1 }
return (concat (reverse (xs:xss)))
else do
maybe_buf <- maybeFillReadBuffer (haFD handle_) True (haIsStream handle_)
case maybe_buf of
-- Nothing indicates we caught an EOF, and we may have a
-- partial line to return.
- Nothing -> let str = concat (reverse (xs:xss)) in
- if not (null str)
- then return str
- else ioe_EOF
+ Nothing -> do
+ writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ let str = concat (reverse (xs:xss))
+ if not (null str)
+ then return str
+ else ioe_EOF
Just new_buf ->
hGetLineBufferedLoop handle_ ref new_buf (xs:xss)
)
(\e -> do if isEOFError e
then return Nothing
- else throw e)
+ else ioError e)
unpack :: RawBuffer -> Int -> Int -> IO [Char]
unpack buf r 0 = return ""
-unpack buf (I## r) (I## len) = IO $ \s -> unpack [] (len -## 1##) s
+unpack buf (I# r) (I# len) = IO $ \s -> unpack [] (len -# 1#) s
where
unpack acc i s
- | i <## r = (## s, acc ##)
+ | i <# r = (# s, acc #)
| otherwise =
- case readCharArray## buf i s of
- (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
+ case readCharArray# buf i s of
+ (# s, ch #) -> unpack (C# ch : acc) (i -# 1#) s
hGetLineUnBuffered :: Handle -> IO String
-- make use of the minimal buffer we already have
let raw = bufBuf buf
r <- throwErrnoIfMinus1RetryMayBlock "lazyRead"
- (read_off (fromIntegral fd) (haIsStream handle_) raw 0 1)
+ (read_off_ba (fromIntegral fd) (haIsStream handle_) raw 0 1)
(threadWaitRead fd)
if r == 0
then do handle_ <- hClose_help handle_
unpackAcc :: RawBuffer -> Int -> Int -> [Char] -> IO [Char]
-unpackAcc buf r 0 acc = return ""
-unpackAcc buf (I## r) (I## len) acc = IO $ \s -> unpack acc (len -## 1##) s
+unpackAcc buf r 0 acc = return acc
+unpackAcc buf (I# r) (I# len) acc = IO $ \s -> unpack acc (len -# 1#) s
where
unpack acc i s
- | i <## r = (## s, acc ##)
+ | i <# r = (# s, acc #)
| otherwise =
- case readCharArray## buf i s of
- (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
+ case readCharArray# buf i s of
+ (# s, ch #) -> unpack (C# ch : acc) (i -# 1#) s
-- ---------------------------------------------------------------------------
-- hPutChar
NoBuffering ->
withObject (castCharToCChar c) $ \buf ->
throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
- (c_write (fromIntegral fd) buf 1)
+ (write_off (fromIntegral fd) (haIsStream handle_) buf 0 1)
(threadWaitWrite fd)
return ()
shoveString n (c:cs) = do
n' <- writeCharIntoBuffer raw n c
- if (c == '\n')
+ if (c == '\n')
then do
new_buf <- commitBuffer hdl raw len n' True{-needs flush-} False
writeLines hdl new_buf cs
-> Bool -- release the buffer?
-> IO Buffer
-commitBuffer hdl raw sz@(I## _) count@(I## _) flush release = do
+commitBuffer hdl raw sz@(I# _) count@(I# _) flush release = do
wantWritableHandle "commitAndReleaseBuffer" hdl $
commitBuffer' hdl raw sz count flush release
--
-- This hack is a fairly big win for hPutStr performance. --SDM 18/9/2001
--
-commitBuffer' hdl raw sz@(I## _) count@(I## _) flush release
+commitBuffer' hdl raw sz@(I# _) count@(I# _) flush release
handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } = do
#ifdef DEBUG_DUMP
-> Int -- number of bytes of data in buffer
-> IO ()
hPutBuf handle ptr count
- | count <= 0 = illegalBufferSize handle "hPutBuf" count
+ | count == 0 = return ()
+ | count < 0 = illegalBufferSize handle "hPutBuf" count
| otherwise =
wantWritableHandle "hPutBuf" handle $
- \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
<- readIORef ref
return ()
-- else, we have to flush
- else do flushed_buf <- flushWriteBuffer fd old_buf
+ else do flushed_buf <- flushWriteBuffer fd is_stream old_buf
writeIORef ref flushed_buf
-- ToDo: should just memcpy instead of writing if possible
writeChunk fd ptr count
hGetBuf :: Handle -> Ptr a -> Int -> IO Int
hGetBuf handle ptr count
- | count <= 0 = illegalBufferSize handle "hGetBuf" count
+ | count == 0 = return 0
+ | count < 0 = illegalBufferSize handle "hGetBuf" count
| otherwise =
wantReadableHandle "hGetBuf" handle $
\ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
let remaining = count - copied
if remaining > 0
then do rest <- readChunk fd (ptr `plusPtr` copied) remaining
- return (rest + count)
+ return (rest + copied)
else return count
readChunk :: FD -> Ptr a -> Int -> IO Int
ioError (userError "slurpFile: file too big")
else do
let sz_i = fromIntegral sz
+ if sz_i == 0 then return (nullPtr, 0) else do
chunk <- mallocBytes sz_i
r <- hGetBuf handle chunk sz_i
hClose handle
-- ---------------------------------------------------------------------------
-- memcpy wrappers
-foreign import "__hscore_memcpy_src_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_src_off"
memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
-foreign import "__hscore_memcpy_src_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_src_off"
memcpy_ptr_baoff :: Ptr a -> RawBuffer -> Int -> CSize -> IO (Ptr ())
-foreign import "__hscore_memcpy_dst_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_dst_off"
memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
-foreign import "__hscore_memcpy_dst_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_dst_off"
memcpy_baoff_ptr :: RawBuffer -> Int -> Ptr a -> CSize -> IO (Ptr ())
-----------------------------------------------------------------------------