2 -----------------------------------------------------------------------------
3 -- Standard Library: IO operations, beyond those included in the prelude
5 -- WARNING: The names and semantics of functions defined in this module
6 -- may change as the details of the IO standard are clarified.
8 -- WARNING: extremely kludgey, incomplete and just plain wrong.
9 -----------------------------------------------------------------------------
12 -- Handle, HandlePosn,
14 -- IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
15 IOMode(ReadMode,WriteMode,AppendMode),
16 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
17 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
18 stdin, stdout, stderr,
20 -- hFileSize, hIsEOF, isEOF,
21 -- hSetBuffering, hGetBuffering, hFlush,
24 -- hSeek, hIsSeekable,
25 -- hReady, hGetChar, hLookAhead, hGetContents,
26 hGetChar, hGetLine, hGetContents,
27 hPutChar, hPutStr, hPutStrLn, hPrint,
28 hIsOpen, hIsClosed, hIsReadable, hIsWritable,
29 isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError,
30 isFullError, isEOFError,
31 isIllegalOperation, isPermissionError, isUserError,
32 ioeGetErrorString, ioeGetHandle, ioeGetFileName,
33 try, bracket, bracket_,
35 -- ... and what the Prelude exports
37 FilePath, IOError, ioError, userError, catch,
38 putChar, putStr, putStrLn, print,
39 getChar, getLine, getContents, interact,
40 readFile, writeFile, appendFile, readIO, readLn
46 unimp s = error ("function not implemented: " ++ s)
53 = Handle { name :: FilePath,
54 file :: FILE_STAR, -- C handle
55 state :: HState, -- open/closed/semiclosed
63 instance Eq Handle where
64 h1 == h2 = file h1 == file h2
66 instance Show Handle where
67 showsPrec _ h = showString ("<<handle " ++ name h ++ "=" ++ show (file h) ++ ">>")
74 data IOMode = ReadMode | WriteMode | AppendMode
75 deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
77 data BufferMode = NoBuffering | LineBuffering
79 deriving (Eq, Ord, Read, Show)
81 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
82 deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
84 data HState = HOpen | HSemiClosed | HClosed
87 stdin = Handle "stdin" (primRunST nh_stdin) HOpen ReadMode NoBuffering nULL 0
88 stdout = Handle "stdout" (primRunST nh_stdout) HOpen WriteMode LineBuffering nULL 0
89 stderr = Handle "stderr" (primRunST nh_stderr) HOpen WriteMode NoBuffering nULL 0
91 openFile :: FilePath -> IOMode -> IO Handle
93 = copy_String_to_cstring f >>= \nameptr ->
94 nh_open nameptr (mode2num mode) >>= \fh ->
97 then (ioError.IOError) ("openFile: can't open " ++ f ++ " in " ++ show mode)
98 else return (Handle f fh HOpen mode BlockBuffering nULL 0)
100 mode2num :: IOMode -> Int
101 mode2num ReadMode = 0
102 mode2num WriteMode = 1
103 mode2num AppendMode = 2
105 hClose :: Handle -> IO ()
107 | not (state h == HOpen)
108 = (ioError.IOError) ("hClose on non-open handle " ++ show h)
110 = nh_close (file h) >>
114 else (ioError.IOError) ("hClose: error closing " ++ name h)
116 hFileSize :: Handle -> IO Integer
117 hFileSize = unimp "IO.hFileSize"
118 hIsEOF :: Handle -> IO Bool
119 hIsEOF = unimp "IO.hIsEOF"
123 hSetBuffering :: Handle -> BufferMode -> IO ()
124 hSetBuffering = unimp "IO.hSetBuffering"
125 hGetBuffering :: Handle -> IO BufferMode
126 hGetBuffering = unimp "IO.hGetBuffering"
128 hFlush :: Handle -> IO ()
130 = if state h /= HOpen
131 then (ioError.IOError) ("hFlush on closed/semiclosed file " ++ name h)
132 else nh_flush (file h)
134 hGetPosn :: Handle -> IO HandlePosn
135 hGetPosn = unimp "IO.hGetPosn"
136 hSetPosn :: HandlePosn -> IO ()
137 hSetPosn = unimp "IO.hSetPosn"
138 hSeek :: Handle -> SeekMode -> Integer -> IO ()
139 hSeek = unimp "IO.hSeek"
140 hWaitForInput :: Handle -> Int -> IO Bool
141 hWaitForInput = unimp "hWaitForInput"
142 hReady :: Handle -> IO Bool
143 hReady h = hWaitForInput h 0
145 hGetChar :: Handle -> IO Char
147 = nh_read (file h) >>= \ci ->
148 return (primIntToChar ci)
150 hGetLine :: Handle -> IO String
151 hGetLine h = do c <- hGetChar h
152 if c=='\n' then return ""
153 else do cs <- hGetLine h
156 hLookAhead :: Handle -> IO Char
157 hLookAhead = unimp "IO.hLookAhead"
159 hGetContents :: Handle -> IO String
161 | not (state h == HOpen && mode h == ReadMode)
162 = (ioError.IOError) ("hGetContents on invalid handle " ++ show h)
167 = unsafeInterleaveIO (
170 then hClose h >> return []
171 else read_all f >>= \rest ->
172 return ((primIntToChar ci):rest)
175 hPutStr :: Handle -> String -> IO ()
177 | not (state h == HOpen && mode h /= ReadMode)
178 = (ioError.IOError) ("hPutStr on invalid handle " ++ show h)
180 = write_all (file h) s
185 = nh_write f (primCharToInt c) >>
188 hPutChar :: Handle -> Char -> IO ()
189 hPutChar h c = hPutStr h [c]
191 hPutStrLn :: Handle -> String -> IO ()
192 hPutStrLn h s = do { hPutStr h s; hPutChar h '\n' }
194 hPrint :: Show a => Handle -> a -> IO ()
195 hPrint h = hPutStrLn h . show
197 hIsOpen, hIsClosed, hIsReadable, hIsWritable :: Handle -> IO Bool
198 hIsOpen h = return (state h == HOpen)
199 hIsClosed h = return (state h == HClosed)
200 hIsReadable h = return (mode h == ReadMode)
201 hIsWritable h = return (mode h == WriteMode)
203 hIsSeekable :: Handle -> IO Bool
204 hIsSeekable = unimp "IO.hIsSeekable"
207 isAlreadyExistsError,
213 isUserError :: IOError -> Bool
215 isIllegalOperation = unimp "IO.isIllegalOperation"
216 isAlreadyExistsError = unimp "IO.isAlreadyExistsError"
217 isDoesNotExistError = unimp "IO.isDoesNotExistError"
218 isAlreadyInUseError = unimp "IO.isAlreadyInUseError"
219 isFullError = unimp "IO.isFullError"
220 isEOFError = unimp "IO.isEOFError"
221 isPermissionError = unimp "IO.isPermissionError"
222 isUserError = unimp "IO.isUserError"
225 ioeGetErrorString :: IOError -> String
226 ioeGetErrorString = unimp "ioeGetErrorString"
227 ioeGetHandle :: IOError -> Maybe Handle
228 ioeGetHandle = unimp "ioeGetHandle"
229 ioeGetFileName :: IOError -> Maybe FilePath
230 ioeGetFileName = unimp "ioeGetFileName"
232 try :: IO a -> IO (Either IOError a)
233 try p = catch (p >>= (return . Right)) (return . Left)
235 bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
236 bracket before after m = do
244 -- variant of the above where middle computation doesn't want x
245 bracket_ :: IO a -> (a -> IO b) -> IO c -> IO c
246 bracket_ before after m = do
254 -----------------------------------------------------------------------------