X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Futils%2FStringBuffer.lhs;h=60bca85dbeffd0689926c9b2b03955aafaa78e4f;hb=6e5df3a4551b8d8b83e936b3f7b52edfc778ca8a;hp=eea0af2b655541850fc56861bf07b4f06cd9aaec;hpb=459e7bd4622ea5bb8e90511b5fc6c7d8058dbd5f;p=ghc-hetmet.git diff --git a/ghc/compiler/utils/StringBuffer.lhs b/ghc/compiler/utils/StringBuffer.lhs index eea0af2..60bca85 100644 --- a/ghc/compiler/utils/StringBuffer.lhs +++ b/ghc/compiler/utils/StringBuffer.lhs @@ -6,7 +6,9 @@ Buffers for scanning string input stored in external arrays. \begin{code} -{-# OPTIONS -fno-prune-tydecls #-} + +{-# OPTIONS -optc-DNON_POSIX_SOURCE #-} + module StringBuffer ( StringBuffer, @@ -30,9 +32,9 @@ module StringBuffer lexemeIndex, -- :: StringBuffer -> Int# -- moving the end point of the current lexeme. - setCurrentPos#, -- :: StringBuffer -> Int# -> StringBuffer - incLexeme, -- :: StringBuffer -> StringBuffer - decLexeme, -- :: StringBuffer -> StringBuffer + addToCurrentPos, -- :: StringBuffer -> Int# -> StringBuffer + incCurrentPos, -- :: StringBuffer -> StringBuffer + decCurrentPos, -- :: StringBuffer -> StringBuffer -- move the start and end lexeme pointer on by x units. stepOn, -- :: StringBuffer -> StringBuffer @@ -57,61 +59,53 @@ module StringBuffer -- conversion lexemeToString, -- :: StringBuffer -> String - lexemeToByteArray, -- :: StringBuffer -> _ByteArray Int lexemeToFastString, -- :: StringBuffer -> FastString - lexemeToBuffer, -- :: StringBuffer -> StringBuffer - - FastString, - ByteArray ) where #include "HsVersions.h" -import GlaExts -import PrelAddr ( Addr(..) ) -import Foreign -import Char ( chr ) - --- urk! -#include "../lib/std/cbits/stgerror.h" -#if __GLASGOW_HASKELL__ >= 303 -import IO ( openFile -#if __GLASGOW_HASKELL__ < 407 - , slurpFile -- comes from PrelHandle or IOExts now -#endif - ) -import PrelIOBase -import PrelHandle -import Addr +#if __GLASGOW_HASKELL__ < 502 +import Panic ( panic ) #else -import IO ( openFile, hFileSize, hClose, IOMode(..) ) -import Addr -#endif - -#if __GLASGOW_HASKELL__ < 301 -import IOBase ( Handle, IOError(..), IOErrorType(..), - constructErrorAndFail ) -import IOHandle ( readHandle, writeHandle, filePtr ) -import PackBase ( unpackCStringBA ) +#if __GLASGOW_HASKELL__ < 503 +import Ptr ( Ptr(..) ) #else -# if __GLASGOW_HASKELL__ <= 302 -import PrelIOBase ( Handle, IOError(..), IOErrorType(..), - constructErrorAndFail ) -import PrelHandle ( readHandle, writeHandle, filePtr ) -# endif -import PrelPack ( unpackCStringBA ) +import GHC.Ptr ( Ptr(..) ) +#endif #endif -#if __GLASGOW_HASKELL__ < 402 -import Util ( bracket ) +#if __GLASGOW_HASKELL__ < 501 +import Char ( chr ) +#elif __GLASGOW_HASKELL__ < 503 +import PrelIO ( hGetcBuffered ) #else -import Exception ( bracket ) +import GHC.IO ( hGetcBuffered ) #endif import PrimPacked import FastString -import Char (isDigit) + +import GLAEXTS + +import Foreign + +#if __GLASGOW_HASKELL__ >= 502 +import CString ( newCString ) +#endif + +import IO ( openFile, isEOFError ) +import EXCEPTION ( bracket ) + +#if __GLASGOW_HASKELL__ < 503 +import PrelIOBase +import PrelHandle +#else +import GHC.IOBase +import GHC.Handle +#endif + +import Char ( isDigit ) \end{code} \begin{code} @@ -125,55 +119,26 @@ data StringBuffer \begin{code} instance Show StringBuffer where - showsPrec _ s = showString "" + showsPrec _ s = showString "" \end{code} \begin{code} -hGetStringBuffer :: Bool -> FilePath -> IO StringBuffer -hGetStringBuffer expand_tabs fname = do - (a, read) <- if expand_tabs - then slurpFileExpandTabs fname - else slurpFile fname - - let (A# a#) = a; (I# read#) = read - - -- add sentinel '\NUL' - _casm_ `` ((char *)%0)[(int)%1]=(char)0; '' (A# a#) (I# (read# -# 1#)) - return (StringBuffer a# read# 0# 0#) - -#if __GLASGOW_HASKELL__ < 303 -slurpFile fname = - openFile fname ReadMode >>= \ hndl -> - hFileSize hndl >>= \ len -> - let len_i = fromInteger len in - -- Allocate an array for system call to store its bytes into. - -- ToDo: make it robust --- trace (show ((len_i::Int)+1)) $ - _casm_ `` %r=(char *)malloc(sizeof(char)*(int)%0); '' (len_i::Int) >>= \ arr@(A# a#) -> - if addr2Int# a# ==# 0# then - fail (userError ("hGetStringBuffer: Could not allocate "++show len_i ++ " bytes")) - else - readHandle hndl >>= \ hndl_ -> - writeHandle hndl hndl_ >> - let ptr = filePtr hndl_ in -#if __GLASGOW_HASKELL__ <= 302 - _ccall_ fread arr (1::Int) len_i (ptr::ForeignObj) >>= \ (I# read#) -> -#else - _ccall_ fread arr (1::Int) len_i (ptr::Addr) >>= \ (I# read#) -> -#endif - hClose hndl >> - if read# ==# 0# then -- EOF or some other error - fail (userError ("hGetStringBuffer: failed to slurp in interface file "++fname)) - else - return (arr, I# read#) -#endif - -unsafeWriteBuffer :: StringBuffer -> Int# -> Char# -> StringBuffer -unsafeWriteBuffer s@(StringBuffer a _ _ _) i# ch# = - unsafePerformIO ( - _casm_ `` ((char *)%0)[(int)%1]=(char)%2; '' (A# a) (I# i#) (C# ch#) >>= \ () -> - return s - ) +hGetStringBuffer :: FilePath -> IO StringBuffer +hGetStringBuffer fname = do + (a, read) <- slurpFileExpandTabs fname + + -- urk! slurpFile gives us a buffer that doesn't have room for + -- the sentinel. Assume it has a final newline for now, and overwrite + -- that with the sentinel. slurpFileExpandTabs (below) leaves room + -- for the sentinel. + let (Ptr a#) = a; + (I# read#) = read; + end# = read# -# 1# + + -- add sentinel '\NUL' + writeCharOffPtr a (I# end#) '\0' + + return (StringBuffer a# end# 0# 0#) \end{code} ----------------------------------------------------------------------------- @@ -181,20 +146,20 @@ unsafeWriteBuffer s@(StringBuffer a _ _ _) i# ch# = \begin{code} stringToStringBuffer :: String -> IO StringBuffer -stringToStringBuffer str = - do let sz@(I# sz#) = length str + 1 - (Ptr a@(A# a#)) <- mallocBytes sz - fill_in str a - writeCharOffAddr a (sz-1) '\0' -- sentinel - return (StringBuffer a# sz# 0# 0#) - where - fill_in [] _ = return () - fill_in (c:cs) a = do - writeCharOffAddr a 0 c - fill_in cs (a `plusAddr` 1) - freeStringBuffer :: StringBuffer -> IO () -freeStringBuffer (StringBuffer a# _ _ _) = Foreign.free (Ptr (A# a#)) + +#if __GLASGOW_HASKELL__ >= 502 +stringToStringBuffer str = do + let sz@(I# sz#) = length str + Ptr a# <- newCString str + return (StringBuffer a# sz# 0# 0#) + +freeStringBuffer (StringBuffer a# _ _ _) = Foreign.free (Ptr a#) +#else +stringToStringBuffer = panic "stringToStringBuffer: not implemented" +freeStringBuffer sb = return () +#endif + \end{code} ----------------------------------------------------------------------------- @@ -208,80 +173,90 @@ We guess the size of the buffer required as 20% extra for expanded tabs, and enlarge it if necessary. \begin{code} -#if __GLASGOW_HASKELL__ < 303 -mayBlock fo thing = thing - -writeCharOffAddr :: Addr -> Int -> Char -> IO () -writeCharOffAddr addr off c - = _casm_ ``*((char *)%0+(int)%1)=(char)%2;'' addr off c -#endif - +#if __GLASGOW_HASKELL__ < 501 getErrType :: IO Int -#if __GLASGOW_HASKELL__ < 303 -getErrType = _casm_ ``%r = ghc_errtype;'' -#else getErrType = _ccall_ getErrType__ #endif -slurpFileExpandTabs :: FilePath -> IO (Addr,Int) +slurpFileExpandTabs :: FilePath -> IO (Ptr (),Int) slurpFileExpandTabs fname = do bracket (openFile fname ReadMode) (hClose) (\ handle -> do sz <- hFileSize handle if sz > toInteger (maxBound::Int) - then IOERROR (userError "slurpFile: file too big") + then ioError (userError "slurpFile: file too big") else do let sz_i = fromInteger sz - sz_i' = (sz_i * 12) `div` 10 -- add 20% for tabs - chunk <- allocMem sz_i' - trySlurp handle sz_i' chunk + if sz_i == 0 + -- empty file: just allocate a buffer containing '\0' + then do chunk <- allocMem 1 + writeCharOffPtr chunk 0 '\0' + return (chunk, 0) + else do let sz_i' = (sz_i * 12) `div` 10 -- add 20% for tabs + chunk <- allocMem sz_i' + trySlurp handle sz_i' chunk ) -trySlurp :: Handle -> Int -> Addr -> IO (Addr, Int) +trySlurp :: Handle -> Int -> Ptr () -> IO (Ptr (), Int) trySlurp handle sz_i chunk = -#if __GLASGOW_HASKELL__ == 303 - wantReadableHandle "hGetChar" handle >>= \ handle_ -> - let fo = haFO__ handle_ in -#elif __GLASGOW_HASKELL__ > 303 +#if __GLASGOW_HASKELL__ < 501 wantReadableHandle "hGetChar" handle $ \ handle_ -> let fo = haFO__ handle_ in #else - readHandle handle >>= \ handle_ -> - let fo = filePtr handle_ in + wantReadableHandle "hGetChar" handle $ + \ handle_@Handle__{ haFD=fd, haBuffer=ref, haBufferMode=mode } -> #endif let (I# chunk_sz) = sz_i tAB_SIZE = 8# - slurpFile :: Int# -> Int# -> Addr -> Int# -> Int# -> IO (Addr, Int) + slurpFile :: Int# -> Int# -> Ptr () -> Int# -> Int# -> IO (Ptr (), Int) slurpFile c off chunk chunk_sz max_off = slurp c off where - slurp :: Int# -> Int# -> IO (Addr, Int) + slurp :: Int# -> Int# -> IO (Ptr (), Int) slurp c off | off >=# max_off = do let new_sz = chunk_sz *# 2# chunk' <- reAllocMem chunk (I# new_sz) slurpFile c off chunk' new_sz (new_sz -# (tAB_SIZE +# 1#)) slurp c off = do +#if __GLASGOW_HASKELL__ < 501 intc <- mayBlock fo (_ccall_ fileGetc fo) if intc == ((-1)::Int) then do errtype <- getErrType - if errtype == (ERR_EOF :: Int) + if errtype == (19{-ERR_EOF-} :: Int) then return (chunk, I# off) else constructErrorAndFail "slurpFile" else case chr intc of +#else + buf <- readIORef ref + ch <- (if not (bufferEmpty buf) + then hGetcBuffered fd ref buf + else do +#if __GLASGOW_HASKELL__ >= 503 + new_buf <- fillReadBuffer fd True False buf +#else + new_buf <- fillReadBuffer fd True buf +#endif + hGetcBuffered fd ref new_buf) + `catch` \e -> if isEOFError e + then return '\xFFFF' + else ioError e + case ch of + '\xFFFF' -> return (chunk, I# off) +#endif '\t' -> tabIt c off - ch -> do writeCharOffAddr chunk (I# off) ch + ch -> do writeCharOffPtr chunk (I# off) ch let c' | ch == '\n' = 0# | otherwise = c +# 1# slurp c' (off +# 1#) - tabIt :: Int# -> Int# -> IO (Addr, Int) + tabIt :: Int# -> Int# -> IO (Ptr (), Int) -- can't run out of buffer in here, because we reserved an -- extra tAB_SIZE bytes at the end earlier. tabIt c off = do - writeCharOffAddr chunk (I# off) ' ' + writeCharOffPtr chunk (I# off) ' ' let c' = c +# 1# off' = off +# 1# if c' `remInt#` tAB_SIZE ==# 0# @@ -294,36 +269,42 @@ trySlurp handle sz_i chunk = -- and add 1 to allow room for the final sentinel \NUL at -- the end of the file. (chunk', rc) <- slurpFile 0# 0# chunk chunk_sz (chunk_sz -# (tAB_SIZE +# 1#)) -#if __GLASGOW_HASKELL__ < 404 - writeHandle handle handle_ -#endif - if rc < (0::Int) - then constructErrorAndFail "slurpFile" - else return (chunk', rc+1 {-room for sentinel-}) + return (chunk', rc+1 {- room for sentinel -}) -reAllocMem :: Addr -> Int -> IO Addr +reAllocMem :: Ptr () -> Int -> IO (Ptr ()) reAllocMem ptr sz = do - chunk <- _ccall_ realloc ptr sz - if chunk == nullAddr -#if __GLASGOW_HASKELL__ >= 400 + chunk <- c_realloc ptr sz + if chunk == nullPtr then fail "reAllocMem" -#else - then fail (userError "reAllocMem") -#endif else return chunk -allocMem :: Int -> IO Addr +allocMem :: Int -> IO (Ptr ()) allocMem sz = do - chunk <- _ccall_ malloc sz -#if __GLASGOW_HASKELL__ < 303 - if chunk == nullAddr - then fail (userError "allocMem") - else return chunk -#else - if chunk == nullAddr + chunk <- c_malloc sz + if chunk == nullPtr +#if __GLASGOW_HASKELL__ < 501 then constructErrorAndFail "allocMem" +#else + then ioException (IOError Nothing ResourceExhausted "malloc" + "out of memory" Nothing) +#endif else return chunk + +#if __GLASGOW_HASKELL__ <= 408 +c_malloc sz = do A# a <- c_malloc' sz; return (Ptr a) +foreign import ccall "malloc" unsafe + c_malloc' :: Int -> IO Addr + +c_realloc (Ptr a) sz = do A# a <- c_realloc' (A# a) sz; return (Ptr a) +foreign import ccall "realloc" unsafe + c_realloc' :: Addr -> Int -> IO Addr +#else +foreign import ccall "malloc" unsafe + c_malloc :: Int -> IO (Ptr a) + +foreign import ccall "realloc" unsafe + c_realloc :: Ptr a -> Int -> IO (Ptr a) #endif \end{code} @@ -359,16 +340,16 @@ lexemeIndex (StringBuffer fo# _ c# _) = c# \begin{code} -- moving the end point of the current lexeme. -setCurrentPos# :: StringBuffer -> Int# -> StringBuffer -setCurrentPos# (StringBuffer fo l# s# c#) i# = +addToCurrentPos :: StringBuffer -> Int# -> StringBuffer +addToCurrentPos (StringBuffer fo l# s# c#) i# = StringBuffer fo l# s# (c# +# i#) -- augmenting the current lexeme by one. -incLexeme :: StringBuffer -> StringBuffer -incLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# +# 1#) +incCurrentPos :: StringBuffer -> StringBuffer +incCurrentPos (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# +# 1#) -decLexeme :: StringBuffer -> StringBuffer -decLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# -# 1#) +decCurrentPos :: StringBuffer -> StringBuffer +decCurrentPos (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# -# 1#) \end{code} @@ -519,38 +500,18 @@ stepOnUntilChar# (StringBuffer fo l# s# c#) x# = -- conversion lexemeToString :: StringBuffer -> String -lexemeToString (StringBuffer fo _ start_pos# current#) = +lexemeToString (StringBuffer fo len# start_pos# current#) = if start_pos# ==# current# then "" else - unpackCStringBA (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#))) + unpackCStringBA + (copySubStr fo (I# start_pos#) (I# (current# -# start_pos#))) + (I# len#) -lexemeToByteArray :: StringBuffer -> ByteArray Int -lexemeToByteArray (StringBuffer fo _ start_pos# current#) = - if start_pos# ==# current# then - error "lexemeToByteArray" - else - copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)) - lexemeToFastString :: StringBuffer -> FastString lexemeToFastString (StringBuffer fo l# start_pos# current#) = if start_pos# ==# current# then - mkFastCharString2 (A# fo) (I# 0#) + mkFastString "" else - mkFastSubString (A# fo) (I# start_pos#) (I# (current# -# start_pos#)) - -{- - Create a StringBuffer from the current lexeme, and add a sentinel - at the end. Know What You're Doing before taking this function - into use.. --} -lexemeToBuffer :: StringBuffer -> StringBuffer -lexemeToBuffer (StringBuffer fo l# start_pos# current#) = - if start_pos# ==# current# then - StringBuffer fo 0# start_pos# current# -- an error, really. - else - unsafeWriteBuffer (StringBuffer fo (current# -# start_pos#) start_pos# start_pos#) - (current# -# 1#) - '\NUL'# - + mkFastSubString fo (I# start_pos#) (I# (current# -# start_pos#)) \end{code}