[project @ 2001-02-22 16:10:12 by rrt]
[ghc-hetmet.git] / ghc / lib / std / PrelCError.lhs
1 % -----------------------------------------------------------------------------
2 % $Id: PrelCError.lhs,v 1.6 2001/01/27 07:46:27 qrczak Exp $
3 %
4 % (c) The FFI task force, 2000
5 %
6
7 C-specific Marshalling support: Handling of C "errno" error codes
8
9 \begin{code}
10 {-# OPTIONS -fno-implicit-prelude -#include "cbits/ghc_errno.h" #-}
11
12 -- this is were we get the CCONST_XXX definitions from that configure
13 -- calculated for us
14 --
15 #include "config.h"
16
17 module PrelCError (
18
19   -- Haskell representation for "errno" values
20   --
21   Errno(..),            -- instance: Eq
22   eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
23   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
24   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
25   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
26   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
27   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
28   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
29   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
30   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
31   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
32   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
33   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
34   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
35   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
36                         -- :: Errno
37   isValidErrno,         -- :: Errno -> Bool
38
39   -- access to the current thread's "errno" value
40   --
41   getErrno,             -- :: IO Errno
42   resetErrno,           -- :: IO ()
43
44   -- conversion of an "errno" value into IO error
45   --
46   errnoToIOError,       -- :: String       -- location
47                         -- -> Errno        -- errno
48                         -- -> Maybe Handle -- handle
49                         -- -> Maybe String -- filename
50                         -- -> IOError
51
52   -- throw current "errno" value
53   --
54   throwErrno,           -- ::                String               -> IO a
55
56   -- guards for IO operations that may fail
57   --
58   throwErrnoIf,         -- :: (a -> Bool) -> String -> IO a       -> IO a
59   throwErrnoIf_,        -- :: (a -> Bool) -> String -> IO a       -> IO ()
60   throwErrnoIfRetry,    -- :: (a -> Bool) -> String -> IO a       -> IO a
61   throwErrnoIfRetry_,   -- :: (a -> Bool) -> String -> IO a       -> IO ()
62   throwErrnoIfMinus1,   -- :: Num a 
63                         -- =>                String -> IO a       -> IO a
64   throwErrnoIfMinus1_,  -- :: Num a 
65                         -- =>                String -> IO a       -> IO ()
66   throwErrnoIfMinus1Retry,  
67                         -- :: Num a 
68                         -- =>                String -> IO a       -> IO a
69   throwErrnoIfMinus1Retry_,  
70                         -- :: Num a 
71                         -- =>                String -> IO a       -> IO ()
72   throwErrnoIfNull,     -- ::                String -> IO (Ptr a) -> IO (Ptr a)
73   throwErrnoIfNullRetry -- ::                String -> IO (Ptr a) -> IO (Ptr a)
74 ) where
75
76
77 -- system dependent imports
78 -- ------------------------
79
80 -- GHC allows us to get at the guts inside IO errors/exceptions
81 --
82 #if __GLASGOW_HASKELL__
83 #if __GLASGOW_HASKELL__ < 409
84 import PrelIOBase (IOError(..), IOErrorType(..))
85 #else
86 import PrelIOBase (Exception(..), IOException(..), IOErrorType(..))
87 #endif
88 #endif /* __GLASGOW_HASKELL__ */
89
90
91 -- regular imports
92 -- ---------------
93
94 import Monad        (liftM)
95
96 #if __GLASGOW_HASKELL__
97 import PrelStorable
98 import PrelMarshalError
99 import PrelCTypes
100 import PrelIOBase
101 import PrelPtr
102 import PrelNum
103 import PrelShow
104 import PrelMaybe
105 import PrelBase
106 #else
107 import Ptr          (Ptr, nullPtr)
108 import CTypes       (CInt)
109 import MarshalError (void)
110
111 import IO           (IOError, Handle, ioError)
112 #endif
113
114 -- system dependent re-definitions
115 -- -------------------------------
116
117 -- we bring GHC's `IOErrorType' in scope in other compilers to simplify the
118 -- routine `errnoToIOError' below
119 --
120 #if !__GLASGOW_HASKELL__
121 data IOErrorType
122   = AlreadyExists        | HardwareFault
123   | IllegalOperation     | InappropriateType
124   | Interrupted          | InvalidArgument
125   | NoSuchThing          | OtherError
126   | PermissionDenied     | ProtocolError
127   | ResourceBusy         | ResourceExhausted
128   | ResourceVanished     | SystemError
129   | TimeExpired          | UnsatisfiedConstraints
130   | UnsupportedOperation
131   | EOF
132 #endif
133
134
135 -- "errno" type
136 -- ------------
137
138 -- import of C function that gives address of errno
139 --
140 foreign import "ghcErrno" unsafe _errno :: Ptr CInt
141
142 -- Haskell representation for "errno" values
143 --
144 newtype Errno = Errno CInt
145
146 instance Eq Errno where
147   errno1@(Errno no1) == errno2@(Errno no2) 
148     | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
149     | otherwise                                  = False
150
151 -- common "errno" symbols
152 --
153 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
154   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
155   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
156   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
157   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
158   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
159   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
160   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
161   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
162   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
163   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
164   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
165   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
166   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV                    :: Errno
167 --
168 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
169 -- configure 
170 --
171 eOK             = Errno 0
172 e2BIG           = Errno (CCONST_E2BIG)
173 eACCES          = Errno (CCONST_EACCES)
174 eADDRINUSE      = Errno (CCONST_EADDRINUSE)
175 eADDRNOTAVAIL   = Errno (CCONST_EADDRNOTAVAIL)
176 eADV            = Errno (CCONST_EADV)
177 eAFNOSUPPORT    = Errno (CCONST_EAFNOSUPPORT)
178 eAGAIN          = Errno (CCONST_EAGAIN)
179 eALREADY        = Errno (CCONST_EALREADY)
180 eBADF           = Errno (CCONST_EBADF)
181 eBADMSG         = Errno (CCONST_EBADMSG)
182 eBADRPC         = Errno (CCONST_EBADRPC)
183 eBUSY           = Errno (CCONST_EBUSY)
184 eCHILD          = Errno (CCONST_ECHILD)
185 eCOMM           = Errno (CCONST_ECOMM)
186 eCONNABORTED    = Errno (CCONST_ECONNABORTED)
187 eCONNREFUSED    = Errno (CCONST_ECONNREFUSED)
188 eCONNRESET      = Errno (CCONST_ECONNRESET)
189 eDEADLK         = Errno (CCONST_EDEADLK)
190 eDESTADDRREQ    = Errno (CCONST_EDESTADDRREQ)
191 eDIRTY          = Errno (CCONST_EDIRTY)
192 eDOM            = Errno (CCONST_EDOM)
193 eDQUOT          = Errno (CCONST_EDQUOT)
194 eEXIST          = Errno (CCONST_EEXIST)
195 eFAULT          = Errno (CCONST_EFAULT)
196 eFBIG           = Errno (CCONST_EFBIG)
197 eFTYPE          = Errno (CCONST_EFTYPE)
198 eHOSTDOWN       = Errno (CCONST_EHOSTDOWN)
199 eHOSTUNREACH    = Errno (CCONST_EHOSTUNREACH)
200 eIDRM           = Errno (CCONST_EIDRM)
201 eILSEQ          = Errno (CCONST_EILSEQ)
202 eINPROGRESS     = Errno (CCONST_EINPROGRESS)
203 eINTR           = Errno (CCONST_EINTR)
204 eINVAL          = Errno (CCONST_EINVAL)
205 eIO             = Errno (CCONST_EIO)
206 eISCONN         = Errno (CCONST_EISCONN)
207 eISDIR          = Errno (CCONST_EISDIR)
208 eLOOP           = Errno (CCONST_ELOOP)
209 eMFILE          = Errno (CCONST_EMFILE)
210 eMLINK          = Errno (CCONST_EMLINK)
211 eMSGSIZE        = Errno (CCONST_EMSGSIZE)
212 eMULTIHOP       = Errno (CCONST_EMULTIHOP)
213 eNAMETOOLONG    = Errno (CCONST_ENAMETOOLONG)
214 eNETDOWN        = Errno (CCONST_ENETDOWN)
215 eNETRESET       = Errno (CCONST_ENETRESET)
216 eNETUNREACH     = Errno (CCONST_ENETUNREACH)
217 eNFILE          = Errno (CCONST_ENFILE)
218 eNOBUFS         = Errno (CCONST_ENOBUFS)
219 eNODATA         = Errno (CCONST_ENODATA)
220 eNODEV          = Errno (CCONST_ENODEV)
221 eNOENT          = Errno (CCONST_ENOENT)
222 eNOEXEC         = Errno (CCONST_ENOEXEC)
223 eNOLCK          = Errno (CCONST_ENOLCK)
224 eNOLINK         = Errno (CCONST_ENOLINK)
225 eNOMEM          = Errno (CCONST_ENOMEM)
226 eNOMSG          = Errno (CCONST_ENOMSG)
227 eNONET          = Errno (CCONST_ENONET)
228 eNOPROTOOPT     = Errno (CCONST_ENOPROTOOPT)
229 eNOSPC          = Errno (CCONST_ENOSPC)
230 eNOSR           = Errno (CCONST_ENOSR)
231 eNOSTR          = Errno (CCONST_ENOSTR)
232 eNOSYS          = Errno (CCONST_ENOSYS)
233 eNOTBLK         = Errno (CCONST_ENOTBLK)
234 eNOTCONN        = Errno (CCONST_ENOTCONN)
235 eNOTDIR         = Errno (CCONST_ENOTDIR)
236 eNOTEMPTY       = Errno (CCONST_ENOTEMPTY)
237 eNOTSOCK        = Errno (CCONST_ENOTSOCK)
238 eNOTTY          = Errno (CCONST_ENOTTY)
239 eNXIO           = Errno (CCONST_ENXIO)
240 eOPNOTSUPP      = Errno (CCONST_EOPNOTSUPP)
241 ePERM           = Errno (CCONST_EPERM)
242 ePFNOSUPPORT    = Errno (CCONST_EPFNOSUPPORT)
243 ePIPE           = Errno (CCONST_EPIPE)
244 ePROCLIM        = Errno (CCONST_EPROCLIM)
245 ePROCUNAVAIL    = Errno (CCONST_EPROCUNAVAIL)
246 ePROGMISMATCH   = Errno (CCONST_EPROGMISMATCH)
247 ePROGUNAVAIL    = Errno (CCONST_EPROGUNAVAIL)
248 ePROTO          = Errno (CCONST_EPROTO)
249 ePROTONOSUPPORT = Errno (CCONST_EPROTONOSUPPORT)
250 ePROTOTYPE      = Errno (CCONST_EPROTOTYPE)
251 eRANGE          = Errno (CCONST_ERANGE)
252 eREMCHG         = Errno (CCONST_EREMCHG)
253 eREMOTE         = Errno (CCONST_EREMOTE)
254 eROFS           = Errno (CCONST_EROFS)
255 eRPCMISMATCH    = Errno (CCONST_ERPCMISMATCH)
256 eRREMOTE        = Errno (CCONST_ERREMOTE)
257 eSHUTDOWN       = Errno (CCONST_ESHUTDOWN)
258 eSOCKTNOSUPPORT = Errno (CCONST_ESOCKTNOSUPPORT)
259 eSPIPE          = Errno (CCONST_ESPIPE)
260 eSRCH           = Errno (CCONST_ESRCH)
261 eSRMNT          = Errno (CCONST_ESRMNT)
262 eSTALE          = Errno (CCONST_ESTALE)
263 eTIME           = Errno (CCONST_ETIME)
264 eTIMEDOUT       = Errno (CCONST_ETIMEDOUT)
265 eTOOMANYREFS    = Errno (CCONST_ETOOMANYREFS)
266 eTXTBSY         = Errno (CCONST_ETXTBSY)
267 eUSERS          = Errno (CCONST_EUSERS)
268 eWOULDBLOCK     = Errno (CCONST_EWOULDBLOCK)
269 eXDEV           = Errno (CCONST_EXDEV)
270
271 -- checks whether the given errno value is supported on the current
272 -- architecture
273 --
274 isValidErrno               :: Errno -> Bool
275 --
276 -- the configure script sets all invalid "errno"s to -1
277 --
278 isValidErrno (Errno errno)  = errno /= -1
279
280
281 -- access to the current thread's "errno" value
282 -- --------------------------------------------
283
284 -- yield the current thread's "errno" value
285 --
286 getErrno :: IO Errno
287 getErrno  = liftM Errno (peek _errno)
288
289
290 -- set the current thread's "errno" value to 0
291 --
292 resetErrno :: IO ()
293 resetErrno  = poke _errno 0
294
295
296 -- throw current "errno" value
297 -- ---------------------------
298
299 -- the common case: throw an IO error based on a textual description
300 -- of the error location and the current thread's "errno" value
301 --
302 throwErrno     :: String -> IO a
303 throwErrno loc  =
304   do
305     errno <- getErrno
306     ioError (errnoToIOError loc errno Nothing Nothing)
307
308
309 -- guards for IO operations that may fail
310 -- --------------------------------------
311
312 -- guard an IO operation and throw an "errno" based exception of the result
313 -- value of the IO operation meets the given predicate
314 --
315 throwErrnoIf            :: (a -> Bool) -> String -> IO a -> IO a
316 throwErrnoIf pred loc f  = 
317   do
318     res <- f
319     if pred res then throwErrno loc else return res
320
321 -- as `throwErrnoIf', but discards the result
322 --
323 throwErrnoIf_            :: (a -> Bool) -> String -> IO a -> IO ()
324 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
325
326 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
327 -- flag `EINTR')
328 --
329 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
330 throwErrnoIfRetry pred loc f  = 
331   do
332     res <- f
333     if pred res
334       then do
335         err <- getErrno
336         if err == eINTR
337           then throwErrnoIfRetry pred loc f
338           else throwErrno loc
339       else return res
340
341 -- as `throwErrnoIfRetry', but discards the result
342 --
343 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
344 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
345
346 -- throws "errno" if a result of "-1" is returned
347 --
348 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
349 throwErrnoIfMinus1  = throwErrnoIf (== -1)
350
351 -- as `throwErrnoIfMinus1', but discards the result
352 --
353 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
354 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
355
356 -- throws "errno" if a result of "-1" is returned, but retries in case of an
357 -- interrupted operation
358 --
359 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
360 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
361
362 -- as `throwErrnoIfMinus1', but discards the result
363 --
364 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
365 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
366
367 -- throws "errno" if a result of a NULL pointer is returned
368 --
369 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
370 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
371
372 -- throws "errno" if a result of a NULL pointer is returned, but retries in
373 -- case of an interrupted operation
374 --
375 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
376 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
377
378
379 -- conversion of an "errno" value into IO error
380 -- --------------------------------------------
381
382 -- convert a location string, an "errno" value, an optional handle,
383 -- and an optional filename into a matching IO error
384 --
385 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
386 errnoToIOError loc errno@(Errno no) maybeHdl maybeName =
387 #if __GLASGOW_HASKELL__
388   IOException (IOError maybeHdl errType loc str maybeName)
389 #else
390   userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName)
391 #endif
392   where
393     (errType, str)
394       | errno == eOK              = (OtherError,
395                                      "no error")
396       | errno == e2BIG            = (ResourceExhausted,
397                                      "argument list too long")
398       | errno == eACCES           = (PermissionDenied,
399                                      "inadequate access permission")
400       | errno == eADDRINUSE       = (ResourceBusy,
401                                      "address already in use")
402       | errno == eADDRNOTAVAIL    = (UnsupportedOperation,
403                                      "address not available")
404       | errno == eADV             = (OtherError,
405                                      "RFS advertise error")
406       | errno == eAFNOSUPPORT     = (UnsupportedOperation,
407                                      "address family not supported by " ++
408                                      "protocol family")
409                                      -- no multiline strings with cpp
410       | errno == eAGAIN           = (ResourceExhausted,
411                                      "insufficient resources")
412       | errno == eALREADY         = (AlreadyExists,
413                                      "operation already in progress")
414       | errno == eBADF            = (OtherError,
415                                      "internal error (EBADF)")
416       | errno == eBADMSG          = (InappropriateType,
417                                      "next message has wrong type")
418       | errno == eBADRPC          = (OtherError,
419                                      "invalid RPC request or response")
420       | errno == eBUSY            = (ResourceBusy,
421                                      "device busy")
422       | errno == eCHILD           = (NoSuchThing,
423                                      "no child processes")
424       | errno == eCOMM            = (ResourceVanished,
425                                      "no virtual circuit could be found")
426       | errno == eCONNABORTED     = (OtherError,
427                                      "aborted connection")
428       | errno == eCONNREFUSED     = (NoSuchThing,
429                                      "no listener on remote host")
430       | errno == eCONNRESET       = (ResourceVanished,
431                                      "connection reset by peer")
432       | errno == eDEADLK          = (ResourceBusy,
433                                      "resource deadlock avoided")
434       | errno == eDESTADDRREQ     = (InvalidArgument,
435                                      "destination address required")
436       | errno == eDIRTY           = (UnsatisfiedConstraints,
437                                      "file system dirty")
438       | errno == eDOM             = (InvalidArgument,
439                                      "argument too large")
440       | errno == eDQUOT           = (PermissionDenied,
441                                      "quota exceeded")
442       | errno == eEXIST           = (AlreadyExists,
443                                      "file already exists")
444       | errno == eFAULT           = (OtherError,
445                                      "internal error (EFAULT)")
446       | errno == eFBIG            = (PermissionDenied,
447                                      "file too large")
448       | errno == eFTYPE           = (InappropriateType,
449                                      "inappropriate NFS file type or format")
450       | errno == eHOSTDOWN        = (NoSuchThing,
451                                      "destination host down")
452       | errno == eHOSTUNREACH     = (NoSuchThing,
453                                      "remote host is unreachable")
454       | errno == eIDRM            = (ResourceVanished,
455                                      "IPC identifier removed")
456       | errno == eILSEQ           = (InvalidArgument,
457                                      "invalid wide character")
458       | errno == eINPROGRESS      = (AlreadyExists,
459                                      "operation now in progress")
460       | errno == eINTR            = (Interrupted,
461                                      "interrupted system call")
462       | errno == eINVAL           = (InvalidArgument,
463                                      "invalid argument")
464       | errno == eIO              = (HardwareFault,
465                                      "unknown I/O fault")
466       | errno == eISCONN          = (AlreadyExists,
467                                      "socket is already connected")
468       | errno == eISDIR           = (InappropriateType,
469                                      "file is a directory")
470       | errno == eLOOP            = (InvalidArgument,
471                                      "too many symbolic links")
472       | errno == eMFILE           = (ResourceExhausted,
473                                      "process file table full")
474       | errno == eMLINK           = (ResourceExhausted,
475                                      "too many links")
476       | errno == eMSGSIZE         = (ResourceExhausted,
477                                      "message too long")
478       | errno == eMULTIHOP        = (UnsupportedOperation,
479                                      "multi-hop RFS request")
480       | errno == eNAMETOOLONG     = (InvalidArgument,
481                                      "filename too long")
482       | errno == eNETDOWN         = (ResourceVanished,
483                                      "network is down")
484       | errno == eNETRESET        = (ResourceVanished,
485                                      "remote host rebooted; connection lost")
486       | errno == eNETUNREACH      = (NoSuchThing,
487                                      "remote network is unreachable")
488       | errno == eNFILE           = (ResourceExhausted,
489                                      "system file table full")
490       | errno == eNOBUFS          = (ResourceExhausted,
491                                      "no buffer space available")
492       | errno == eNODATA          = (NoSuchThing,
493                                      "no message on the stream head read " ++
494                                      "queue")
495                                      -- no multiline strings with cpp
496       | errno == eNODEV           = (NoSuchThing,
497                                      "no such device")
498       | errno == eNOENT           = (NoSuchThing,
499                                      "no such file or directory")
500       | errno == eNOEXEC          = (InvalidArgument,
501                                      "not an executable file")
502       | errno == eNOLCK           = (ResourceExhausted,
503                                      "no file locks available")
504       | errno == eNOLINK          = (ResourceVanished,
505                                      "RFS link has been severed")
506       | errno == eNOMEM           = (ResourceExhausted,
507                                      "not enough virtual memory")
508       | errno == eNOMSG           = (NoSuchThing,
509                                      "no message of desired type")
510       | errno == eNONET           = (NoSuchThing,
511                                      "host is not on a network")
512       | errno == eNOPROTOOPT      = (UnsupportedOperation,
513                                      "operation not supported by protocol")
514       | errno == eNOSPC           = (ResourceExhausted,
515                                      "no space left on device")
516       | errno == eNOSR            = (ResourceExhausted,
517                                      "out of stream resources")
518       | errno == eNOSTR           = (InvalidArgument,
519                                      "not a stream device")
520       | errno == eNOSYS           = (UnsupportedOperation,
521                                      "function not implemented")
522       | errno == eNOTBLK          = (InvalidArgument,
523                                      "not a block device")
524       | errno == eNOTCONN         = (InvalidArgument,
525                                      "socket is not connected")
526       | errno == eNOTDIR          = (InappropriateType,
527                                      "not a directory")
528       | errno == eNOTEMPTY        = (UnsatisfiedConstraints,
529                                      "directory not empty")
530       | errno == eNOTSOCK         = (InvalidArgument,
531                                      "not a socket")
532       | errno == eNOTTY           = (IllegalOperation,
533                                      "inappropriate ioctl for device")
534       | errno == eNXIO            = (NoSuchThing,
535                                      "no such device or address")
536       | errno == eOPNOTSUPP       = (UnsupportedOperation,
537                                      "operation not supported on socket")
538       | errno == ePERM            = (PermissionDenied,
539                                      "privileged operation")
540       | errno == ePFNOSUPPORT     = (UnsupportedOperation,
541                                      "protocol family not supported")
542       | errno == ePIPE            = (ResourceVanished,
543                                      "broken pipe")
544       | errno == ePROCLIM         = (PermissionDenied,
545                                      "too many processes")
546       | errno == ePROCUNAVAIL     = (UnsupportedOperation,
547                                      "unimplemented RPC procedure")
548       | errno == ePROGMISMATCH    = (ProtocolError,
549                                      "unsupported RPC program version")
550       | errno == ePROGUNAVAIL     = (UnsupportedOperation,
551                                      "RPC program unavailable")
552       | errno == ePROTO           = (ProtocolError,
553                                      "error in streams protocol")
554       | errno == ePROTONOSUPPORT  = (ProtocolError,
555                                      "protocol not supported")
556       | errno == ePROTOTYPE       = (ProtocolError,
557                                      "wrong protocol for socket")
558       | errno == eRANGE           = (UnsupportedOperation,
559                                      "result too large")
560       | errno == eREMCHG          = (ResourceVanished,
561                                      "remote address changed")
562       | errno == eREMOTE          = (IllegalOperation,
563                                      "too many levels of remote in path")
564       | errno == eROFS            = (PermissionDenied,
565                                      "read-only file system")
566       | errno == eRPCMISMATCH     = (ProtocolError,
567                                      "RPC version is wrong")
568       | errno == eRREMOTE         = (IllegalOperation,
569                                      "object is remote")
570       | errno == eSHUTDOWN        = (IllegalOperation,
571                                      "can't send after socket shutdown")
572       | errno == eSOCKTNOSUPPORT  = (UnsupportedOperation,
573                                      "socket type not supported")
574       | errno == eSPIPE           = (UnsupportedOperation,
575                                      "can't seek on a pipe")
576       | errno == eSRCH            = (NoSuchThing,
577                                      "no such process")
578       | errno == eSRMNT           = (UnsatisfiedConstraints,
579                                      "RFS resources still mounted by " ++
580                                      "remote host(s)")
581                                      -- no multiline strings with cpp
582       | errno == eSTALE           = (ResourceVanished,
583                                      "stale NFS file handle")
584       | errno == eTIME            = (TimeExpired,
585                                      "timer expired")
586       | errno == eTIMEDOUT        = (TimeExpired,
587                                      "connection timed out")
588       | errno == eTOOMANYREFS     = (ResourceExhausted,
589                                      "too many references; can't splice")
590       | errno == eTXTBSY          = (ResourceBusy,
591                                      "text file in-use")
592       | errno == eUSERS           = (ResourceExhausted,
593                                      "quota table full")
594       | errno == eWOULDBLOCK      = (OtherError,
595                                      "operation would block")
596       | errno == eXDEV            = (UnsupportedOperation,
597                                      "can't make a cross-device link")
598       | otherwise                 = (OtherError, 
599                                      "unexpected error (error code: " 
600                                      ++ show no ++")")
601 \end{code}