[project @ 2002-12-12 13:42:46 by ross]
[haskell-directory.git] / GHC / IO.hs
index 801e683..ab5b319 100644 (file)
--- a/GHC/IO.hs
+++ b/GHC/IO.hs
@@ -1,32 +1,36 @@
-{-# 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
 
@@ -39,7 +43,7 @@ import GHC.Real
 import GHC.Num
 import GHC.Show
 import GHC.List
-import GHC.Exception    ( ioError, catch, throw )
+import GHC.Exception    ( ioError, catch )
 import GHC.Conc
 
 -- ---------------------------------------------------------------------------
@@ -55,7 +59,7 @@ 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
 
@@ -63,11 +67,11 @@ hWaitForInput h msecs = do
        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
 
 -- ---------------------------------------------------------------------------
@@ -100,7 +104,7 @@ hGetChar handle =
        -- 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
@@ -164,10 +168,13 @@ hGetLineBufferedLoop handle_ ref
 #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_)
@@ -175,10 +182,12 @@ hGetLineBufferedLoop handle_ ref
             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)
 
@@ -190,18 +199,18 @@ maybeFillReadBuffer fd is_line is_stream buf
      )
      (\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
@@ -280,7 +289,7 @@ lazyRead' h handle_ = do
        -- 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_ 
@@ -312,14 +321,14 @@ lazyReadHaveBuffer h handle_ fd ref buf = do
 
 
 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
@@ -339,7 +348,7 @@ hPutChar handle c =
        NoBuffering      ->
                withObject (castCharToCChar c) $ \buf ->
                throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
-                  (c_write (fromIntegral fd) buf 1)
+                  (write_off (fromIntegral fd) (haIsStream handle_) buf 0 1)
                   (threadWaitWrite fd)
 
 
@@ -429,7 +438,7 @@ writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
        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
@@ -484,7 +493,7 @@ commitBuffer
        -> 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
 
@@ -499,7 +508,7 @@ commitBuffer hdl raw sz@(I## _) count@(I## _) flush release = do
 --
 -- 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
@@ -603,10 +612,11 @@ hPutBuf :: Handle                 -- handle to write to
        -> 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
@@ -620,7 +630,7 @@ hPutBuf handle ptr count
                    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
@@ -643,7 +653,8 @@ writeChunk fd ptr bytes = loop 0 bytes
 
 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
@@ -665,7 +676,7 @@ hGetBuf handle ptr count
                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
@@ -690,6 +701,7 @@ slurpFile fname = do
     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
@@ -698,13 +710,13 @@ slurpFile fname = do
 -- ---------------------------------------------------------------------------
 -- 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 ())
 
 -----------------------------------------------------------------------------