[project @ 2002-12-12 13:42:46 by ross]
[haskell-directory.git] / System / IO / Error.hs
1 {-# OPTIONS -fno-implicit-prelude #-}
2
3 -----------------------------------------------------------------------------
4 -- |
5 -- Module      :  System.IO.Error
6 -- Copyright   :  (c) The University of Glasgow 2001
7 -- License     :  BSD-style (see the file libraries/base/LICENSE)
8 -- 
9 -- Maintainer  :  libraries@haskell.org
10 -- Stability   :  provisional
11 -- Portability :  portable
12 --
13 -- Standard IO Errors.
14 --
15 -----------------------------------------------------------------------------
16
17 module System.IO.Error (
18     IOError,                    -- abstract
19 #ifdef __GLASGOW_HASKELL__
20     IOErrorType,                -- abstract
21 #endif
22
23     catch,                      -- :: IO a -> (IOError -> IO a) -> IO a
24     try,                        -- :: IO a -> IO (Either IOError a)
25
26     ioError,                    -- :: IOError -> IO a
27     userError,                  -- :: String  -> IOError
28
29 #ifdef __GLASGOW_HASKELL__
30     mkIOError,                  -- :: IOErrorType -> String -> Maybe Handle
31                                 --    -> Maybe FilePath -> IOError
32
33     annotateIOError,            -- :: IOError -> String -> Maybe FilePath 
34                                 --    -> Maybe Handle -> IOError 
35
36     alreadyExistsErrorType,     -- :: IOErrorType
37     doesNotExistErrorType,
38     alreadyInUseErrorType,
39     fullErrorType,
40     eofErrorType,
41     illegalOperationErrorType, 
42     permissionErrorType,
43     userErrorType,
44
45     isAlreadyExistsErrorType,   -- :: IOErrorType -> Bool
46     isDoesNotExistErrorType,
47     isAlreadyInUseErrorType,
48     isFullErrorType, 
49     isEOFErrorType,
50     isIllegalOperationErrorType, 
51     isPermissionErrorType,
52     isUserErrorType, 
53 #endif  /* __GLASGOW_HASKELL__ */
54
55     isAlreadyExistsError,       -- :: IOError -> Bool
56     isDoesNotExistError,
57     isAlreadyInUseError,
58     isFullError, 
59     isEOFError,
60     isIllegalOperation, 
61     isPermissionError,
62     isUserError,
63
64 #ifdef __GLASGOW_HASKELL__
65     ioeGetErrorType,            -- :: IOError -> IOErrorType
66 #endif
67     ioeGetErrorString,          -- :: IOError -> String
68     ioeGetHandle,               -- :: IOError -> Maybe Handle
69     ioeGetFileName,             -- :: IOError -> Maybe FilePath
70
71   ) where
72
73 import Data.Either
74
75 #ifdef __GLASGOW_HASKELL__
76 import GHC.Base
77 import Data.Maybe
78 import GHC.IOBase
79 import GHC.Exception
80 import Text.Show
81 #endif
82
83 #ifdef __HUGS__
84 import Hugs.IO
85 #endif
86
87 #ifdef __NHC__
88 import IO
89   ( IOError ()
90   , try
91   , ioError
92   , userError
93   , isAlreadyExistsError        -- :: IOError -> Bool
94   , isDoesNotExistError
95   , isAlreadyInUseError
96   , isFullError
97   , isEOFError
98   , isIllegalOperation
99   , isPermissionError
100   , isUserError
101   , ioeGetErrorString           -- :: IOError -> String
102   , ioeGetHandle                -- :: IOError -> Maybe Handle
103   , ioeGetFileName              -- :: IOError -> Maybe FilePath
104   )
105 --import Data.Maybe (fromJust)
106 --import Control.Monad (MonadPlus(mplus))
107 #endif
108
109 -- | The construct @try comp@ exposes IO errors which occur within a
110 -- computation, and which are not fully handled.
111 -- Other exceptions are not caught by this variant;
112 -- to catch all exceptions, use @try@ from "Control.Exception".
113
114 #ifndef __NHC__
115 try            :: IO a -> IO (Either IOError a)
116 try f          =  catch (do r <- f
117                             return (Right r))
118                         (return . Left)
119 #endif
120
121 #ifdef __GLASGOW_HASKELL__
122 -- -----------------------------------------------------------------------------
123 -- Constructing an IOError
124
125 mkIOError :: IOErrorType -> String -> Maybe Handle -> Maybe FilePath -> IOError
126 mkIOError t location maybe_hdl maybe_filename =
127                IOError{ ioe_type = t, 
128                         ioe_location = location,
129                         ioe_descr = "",
130                         ioe_handle = maybe_hdl, 
131                         ioe_filename = maybe_filename
132                         }
133 #ifdef __NHC__
134 mkIOError EOF       location maybe_hdl maybe_filename =
135     EOFError location (fromJust maybe_hdl)
136 mkIOError UserError location maybe_hdl maybe_filename =
137     UserError location ""
138 mkIOError t         location maybe_hdl maybe_filename =
139     NHC.FFI.mkIOError location maybe_filename maybe_handle (ioeTypeToInt t)
140   where
141     ioeTypeToInt AlreadyExists     = fromEnum EEXIST
142     ioeTypeToInt NoSuchThing       = fromEnum ENOENT
143     ioeTypeToInt ResourceBusy      = fromEnum EBUSY
144     ioeTypeToInt ResourceExhausted = fromEnum ENOSPC
145     ioeTypeToInt IllegalOperation  = fromEnum EPERM
146     ioeTypeToInt PermissionDenied  = fromEnum EACCES
147 #endif
148
149 -- -----------------------------------------------------------------------------
150 -- IOErrorType
151
152 isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError,
153  isFullError, isEOFError, isIllegalOperation, isPermissionError,
154  isUserError :: IOError -> Bool
155
156 isAlreadyExistsError = isAlreadyExistsErrorType    . ioeGetErrorType
157 isDoesNotExistError  = isDoesNotExistErrorType     . ioeGetErrorType
158 isAlreadyInUseError  = isAlreadyInUseErrorType     . ioeGetErrorType
159 isFullError          = isFullErrorType             . ioeGetErrorType
160 isEOFError           = isEOFErrorType              . ioeGetErrorType
161 isIllegalOperation   = isIllegalOperationErrorType . ioeGetErrorType
162 isPermissionError    = isPermissionErrorType       . ioeGetErrorType
163 isUserError          = isUserErrorType             . ioeGetErrorType
164 #endif
165
166 -- -----------------------------------------------------------------------------
167 -- IOErrorTypes
168
169 #ifdef __NHC__
170 data IOErrorType = AlreadyExists | NoSuchThing | ResourceBusy
171                  | ResourceExhausted | EOF | IllegalOperation
172                  | PermissionDenied | UserError
173 #endif
174
175 #ifdef __GLASGOW_HASKELL__
176 alreadyExistsErrorType, doesNotExistErrorType, alreadyInUseErrorType,
177  fullErrorType, eofErrorType, illegalOperationErrorType,
178  permissionErrorType, userErrorType :: IOErrorType
179
180 alreadyExistsErrorType    = AlreadyExists
181 doesNotExistErrorType     = NoSuchThing
182 alreadyInUseErrorType     = ResourceBusy
183 fullErrorType             = ResourceExhausted
184 eofErrorType              = EOF
185 illegalOperationErrorType = IllegalOperation
186 permissionErrorType       = PermissionDenied
187 userErrorType             = UserError
188 #endif
189
190 -- -----------------------------------------------------------------------------
191 -- IOErrorType predicates
192
193 #ifdef __GLASGOW_HASKELL__
194 isAlreadyExistsErrorType, isDoesNotExistErrorType, isAlreadyInUseErrorType,
195   isFullErrorType, isEOFErrorType, isIllegalOperationErrorType, 
196   isPermissionErrorType, isUserErrorType :: IOErrorType -> Bool
197 #endif
198
199 #ifdef __GLASGOW_HASKELL__
200 isAlreadyExistsErrorType AlreadyExists = True
201 isAlreadyExistsErrorType _ = False
202
203 isDoesNotExistErrorType NoSuchThing = True
204 isDoesNotExistErrorType _ = False
205
206 isAlreadyInUseErrorType ResourceBusy = True
207 isAlreadyInUseErrorType _ = False
208
209 isFullErrorType ResourceExhausted = True
210 isFullErrorType _ = False
211
212 isEOFErrorType EOF = True
213 isEOFErrorType _ = False
214
215 isIllegalOperationErrorType IllegalOperation = True
216 isIllegalOperationErrorType _ = False
217
218 isPermissionErrorType PermissionDenied = True
219 isPermissionErrorType _ = False
220
221 isUserErrorType UserError = True
222 isUserErrorType _ = False
223 #endif
224
225 -- -----------------------------------------------------------------------------
226 -- Miscellaneous
227
228 #ifdef __GLASGOW_HASKELL__
229 ioeGetErrorType       :: IOError -> IOErrorType
230 ioeGetHandle          :: IOError -> Maybe Handle
231 ioeGetErrorString     :: IOError -> String
232 ioeGetFileName        :: IOError -> Maybe FilePath
233
234 ioeGetErrorType ioe = ioe_type ioe
235
236 ioeGetHandle ioe = ioe_handle ioe
237
238 ioeGetErrorString ioe
239    | isUserErrorType (ioe_type ioe) = ioe_descr ioe
240    | otherwise                      = show (ioe_type ioe)
241
242 ioeGetFileName ioe = ioe_filename ioe
243 #endif
244
245 -- -----------------------------------------------------------------------------
246 -- annotating an IOError
247
248 #ifdef __GLASGOW_HASKELL__
249 annotateIOError :: IOError 
250               -> String 
251               -> Maybe FilePath 
252               -> Maybe Handle 
253               -> IOError 
254 annotateIOError (IOError hdl errTy _ str path) loc opath ohdl = 
255   IOError (hdl `mplus` ohdl) errTy loc str (path `mplus` opath)
256   where
257     Nothing `mplus` ys = ys
258     xs      `mplus` _  = xs
259 #endif
260
261 #ifdef 0 /*__NHC__*/
262 annotateIOError (IOError msg file hdl code) msg' file' hdl' =
263     IOError (msg++'\n':msg') (file`mplus`file') (hdl`mplus`hdl') code
264 annotateIOError (EOFError msg hdl) msg' file' hdl' =
265     EOFError (msg++'\n':msg') (hdl`mplus`hdl')
266 annotateIOError (UserError loc msg) msg' file' hdl' =
267     UserError loc (msg++'\n':msg')
268 annotateIOError (PatternError loc) msg' file' hdl' =
269     PatternError (loc++'\n':msg')
270 #endif