X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FIO%2FError.hs;h=83dfd7e5a1b847953cf5ffbecca0c2d5b3620fb2;hb=4b26136ab82fb1ff12e49477c4833a9586d368c5;hp=6874ac9aceea6b1fb67a4a3842f9947c1eab66ec;hpb=9af2914a8114a7858e370392b7704f00957fa5c2;p=haskell-directory.git diff --git a/System/IO/Error.hs b/System/IO/Error.hs index 6874ac9..83dfd7e 100644 --- a/System/IO/Error.hs +++ b/System/IO/Error.hs @@ -1,4 +1,4 @@ -{-# OPTIONS -fno-implicit-prelude #-} +{-# OPTIONS_GHC -fno-implicit-prelude #-} ----------------------------------------------------------------------------- -- | @@ -15,13 +15,10 @@ ----------------------------------------------------------------------------- module System.IO.Error ( - IOError, -- abstract - IOErrorType, -- abstract - catch, -- :: IO a -> (IOError -> IO a) -> IO a - try, -- :: IO a -> IO (Either IOError a) + -- * I\/O errors + IOError, -- = IOException - ioError, -- :: IOError -> IO a userError, -- :: String -> IOError #ifndef __NHC__ @@ -30,10 +27,38 @@ module System.IO.Error ( annotateIOError, -- :: IOError -> String -> Maybe Handle -- -> Maybe FilePath -> IOError +#endif - modifyIOError, -- :: (IOError -> IOError) -> IO a -> IO a + -- ** Classifying I\/O errors + isAlreadyExistsError, -- :: IOError -> Bool + isDoesNotExistError, + isAlreadyInUseError, + isFullError, + isEOFError, + isIllegalOperation, + isPermissionError, + isUserError, + + -- ** Attributes of I\/O errors +#ifndef __NHC__ + ioeGetErrorType, -- :: IOError -> IOErrorType + ioeGetLocation, -- :: IOError -> String +#endif + ioeGetErrorString, -- :: IOError -> String + ioeGetHandle, -- :: IOError -> Maybe Handle + ioeGetFileName, -- :: IOError -> Maybe FilePath + +#ifndef __NHC__ + ioeSetErrorType, -- :: IOError -> IOErrorType -> IOError + ioeSetErrorString, -- :: IOError -> String -> IOError + ioeSetLocation, -- :: IOError -> String -> IOError + ioeSetHandle, -- :: IOError -> Handle -> IOError + ioeSetFileName, -- :: IOError -> FilePath -> IOError #endif + -- * Types of I\/O error + IOErrorType, -- abstract + alreadyExistsErrorType, -- :: IOErrorType doesNotExistErrorType, alreadyInUseErrorType, @@ -43,6 +68,7 @@ module System.IO.Error ( permissionErrorType, userErrorType, + -- ** 'IOErrorType' predicates isAlreadyExistsErrorType, -- :: IOErrorType -> Bool isDoesNotExistErrorType, isAlreadyInUseErrorType, @@ -52,27 +78,15 @@ module System.IO.Error ( isPermissionErrorType, isUserErrorType, - isAlreadyExistsError, -- :: IOError -> Bool - isDoesNotExistError, - isAlreadyInUseError, - isFullError, - isEOFError, - isIllegalOperation, - isPermissionError, - isUserError, + -- * Throwing and catching I\/O errors -#ifndef __NHC__ - ioeGetErrorType, -- :: IOError -> IOErrorType -#endif - ioeGetErrorString, -- :: IOError -> String - ioeGetHandle, -- :: IOError -> Maybe Handle - ioeGetFileName, -- :: IOError -> Maybe FilePath + ioError, -- :: IOError -> IO a + + catch, -- :: IO a -> (IOError -> IO a) -> IO a + try, -- :: IO a -> IO (Either IOError a) #ifndef __NHC__ - ioeSetErrorType, -- :: IOError -> IOErrorType -> IOError - ioeSetErrorString, -- :: IOError -> String -> IOError - ioeSetHandle, -- :: IOError -> Handle -> IOError - ioeSetFileName, -- :: IOError -> FilePath -> IOError + modifyIOError, -- :: (IOError -> IOError) -> IO a -> IO a #endif ) where @@ -112,10 +126,11 @@ import IO --import Control.Monad (MonadPlus(mplus)) #endif --- | The construct @try comp@ exposes IO errors which occur within a +-- | The construct 'try' @comp@ exposes IO errors which occur within a -- computation, and which are not fully handled. --- Other exceptions are not caught by this variant; --- to catch all exceptions, use @try@ from "Control.Exception". +-- +-- Non-I\/O exceptions are not caught by this variant; to catch all +-- exceptions, use 'Control.Exception.try' from "Control.Exception". #ifndef __NHC__ try :: IO a -> IO (Either IOError a) @@ -128,6 +143,10 @@ try f = catch (do r <- f -- ----------------------------------------------------------------------------- -- Constructing an IOError +-- | Construct an 'IOError' of the given type where the second argument +-- describes the error location and the third and fourth argument +-- contain the file handle and file path of the file involved in the +-- error if applicable. mkIOError :: IOErrorType -> String -> Maybe Handle -> Maybe FilePath -> IOError mkIOError t location maybe_hdl maybe_filename = IOError{ ioe_type = t, @@ -157,17 +176,50 @@ mkIOError t location maybe_hdl maybe_filename = -- ----------------------------------------------------------------------------- -- IOErrorType -isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError, - isFullError, isEOFError, isIllegalOperation, isPermissionError, - isUserError :: IOError -> Bool - +-- | An error indicating that an 'IO' operation failed because +-- one of its arguments already exists. +isAlreadyExistsError :: IOError -> Bool isAlreadyExistsError = isAlreadyExistsErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- one of its arguments does not exist. +isDoesNotExistError :: IOError -> Bool isDoesNotExistError = isDoesNotExistErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- one of its arguments is a single-use resource, which is already +-- being used (for example, opening the same file twice for writing +-- might give this error). +isAlreadyInUseError :: IOError -> Bool isAlreadyInUseError = isAlreadyInUseErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- the device is full. +isFullError :: IOError -> Bool isFullError = isFullErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- the end of file has been reached. +isEOFError :: IOError -> Bool isEOFError = isEOFErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- the operation was not possible. +-- Any computation which returns an 'IO' result may fail with +-- 'isIllegalOperation'. In some cases, an implementation will not be +-- able to distinguish between the possible error causes. In this case +-- it should fail with 'isIllegalOperation'. +isIllegalOperation :: IOError -> Bool isIllegalOperation = isIllegalOperationErrorType . ioeGetErrorType + +-- | An error indicating that an 'IO' operation failed because +-- the user does not have sufficient operating system privilege +-- to perform that operation. +isPermissionError :: IOError -> Bool isPermissionError = isPermissionErrorType . ioeGetErrorType + +-- | A programmer-defined error value constructed using 'userError'. +isUserError :: IOError -> Bool isUserError = isUserErrorType . ioeGetErrorType #endif /* __NHC__ */ @@ -180,47 +232,88 @@ data IOErrorType = AlreadyExists | NoSuchThing | ResourceBusy | PermissionDenied | UserError #endif -alreadyExistsErrorType, doesNotExistErrorType, alreadyInUseErrorType, - fullErrorType, eofErrorType, illegalOperationErrorType, - permissionErrorType, userErrorType :: IOErrorType - +-- | I\/O error where the operation failed because one of its arguments +-- already exists. +alreadyExistsErrorType :: IOErrorType alreadyExistsErrorType = AlreadyExists + +-- | I\/O error where the operation failed because one of its arguments +-- does not exist. +doesNotExistErrorType :: IOErrorType doesNotExistErrorType = NoSuchThing + +-- | I\/O error where the operation failed because one of its arguments +-- is a single-use resource, which is already being used. +alreadyInUseErrorType :: IOErrorType alreadyInUseErrorType = ResourceBusy + +-- | I\/O error where the operation failed because the device is full. +fullErrorType :: IOErrorType fullErrorType = ResourceExhausted + +-- | I\/O error where the operation failed because the end of file has +-- been reached. +eofErrorType :: IOErrorType eofErrorType = EOF + +-- | I\/O error where the operation is not possible. +illegalOperationErrorType :: IOErrorType illegalOperationErrorType = IllegalOperation + +-- | I\/O error where the operation failed because the user does not +-- have sufficient operating system privilege to perform that operation. +permissionErrorType :: IOErrorType permissionErrorType = PermissionDenied + +-- | I\/O error that is programmer-defined. +userErrorType :: IOErrorType userErrorType = UserError -- ----------------------------------------------------------------------------- -- IOErrorType predicates -isAlreadyExistsErrorType, isDoesNotExistErrorType, isAlreadyInUseErrorType, - isFullErrorType, isEOFErrorType, isIllegalOperationErrorType, - isPermissionErrorType, isUserErrorType :: IOErrorType -> Bool - +-- | I\/O error where the operation failed because one of its arguments +-- already exists. +isAlreadyExistsErrorType :: IOErrorType -> Bool isAlreadyExistsErrorType AlreadyExists = True isAlreadyExistsErrorType _ = False +-- | I\/O error where the operation failed because one of its arguments +-- does not exist. +isDoesNotExistErrorType :: IOErrorType -> Bool isDoesNotExistErrorType NoSuchThing = True isDoesNotExistErrorType _ = False +-- | I\/O error where the operation failed because one of its arguments +-- is a single-use resource, which is already being used. +isAlreadyInUseErrorType :: IOErrorType -> Bool isAlreadyInUseErrorType ResourceBusy = True isAlreadyInUseErrorType _ = False +-- | I\/O error where the operation failed because the device is full. +isFullErrorType :: IOErrorType -> Bool isFullErrorType ResourceExhausted = True isFullErrorType _ = False +-- | I\/O error where the operation failed because the end of file has +-- been reached. +isEOFErrorType :: IOErrorType -> Bool isEOFErrorType EOF = True isEOFErrorType _ = False +-- | I\/O error where the operation is not possible. +isIllegalOperationErrorType :: IOErrorType -> Bool isIllegalOperationErrorType IllegalOperation = True isIllegalOperationErrorType _ = False +-- | I\/O error where the operation failed because the user does not +-- have sufficient operating system privilege to perform that operation. +isPermissionErrorType :: IOErrorType -> Bool isPermissionErrorType PermissionDenied = True isPermissionErrorType _ = False +-- | I\/O error that is programmer-defined. +isUserErrorType :: IOErrorType -> Bool isUserErrorType UserError = True isUserErrorType _ = False @@ -230,6 +323,7 @@ isUserErrorType _ = False #if defined(__GLASGOW_HASKELL__) || defined(__HUGS__) ioeGetErrorType :: IOError -> IOErrorType ioeGetErrorString :: IOError -> String +ioeGetLocation :: IOError -> String ioeGetHandle :: IOError -> Maybe Handle ioeGetFileName :: IOError -> Maybe FilePath @@ -239,26 +333,35 @@ ioeGetErrorString ioe | isUserErrorType (ioe_type ioe) = ioe_description ioe | otherwise = show (ioe_type ioe) +ioeGetLocation ioe = ioe_location ioe + ioeGetHandle ioe = ioe_handle ioe ioeGetFileName ioe = ioe_filename ioe -ioeSetErrorType :: IOError -> IOErrorType -> IOError -ioeSetErrorString :: IOError -> String -> IOError -ioeSetHandle :: IOError -> Handle -> IOError -ioeSetFileName :: IOError -> FilePath -> IOError +ioeSetErrorType :: IOError -> IOErrorType -> IOError +ioeSetErrorString :: IOError -> String -> IOError +ioeSetLocation :: IOError -> String -> IOError +ioeSetHandle :: IOError -> Handle -> IOError +ioeSetFileName :: IOError -> FilePath -> IOError ioeSetErrorType ioe errtype = ioe{ ioe_type = errtype } ioeSetErrorString ioe str = ioe{ ioe_description = str } +ioeSetLocation ioe str = ioe{ ioe_location = str } ioeSetHandle ioe hdl = ioe{ ioe_handle = Just hdl } ioeSetFileName ioe filename = ioe{ ioe_filename = Just filename } +-- | Catch any 'IOError' that occurs in the computation and throw a +-- modified version. modifyIOError :: (IOError -> IOError) -> IO a -> IO a -modifyIOError f io = GHC.Exception.catch io (\e -> ioError (f e)) +modifyIOError f io = catch io (\e -> ioError (f e)) -- ----------------------------------------------------------------------------- -- annotating an IOError +-- | Adds a location description and maybe a file path and file handle +-- to an 'IOError'. If any of the file handle or file path is not given +-- the corresponding value in the 'IOError' remains unaltered. annotateIOError :: IOError -> String -> Maybe Handle @@ -271,7 +374,7 @@ annotateIOError (IOError ohdl errTy _ str opath) loc hdl path = xs `mplus` _ = xs #endif /* __GLASGOW_HASKELL__ || __HUGS__ */ -#ifdef 0 /*__NHC__*/ +#if 0 /*__NHC__*/ annotateIOError (IOError msg file hdl code) msg' file' hdl' = IOError (msg++'\n':msg') (file`mplus`file') (hdl`mplus`hdl') code annotateIOError (EOFError msg hdl) msg' file' hdl' =