From 33a64642f17054fa3b194e40b3819a1846bee24e Mon Sep 17 00:00:00 2001 From: ross Date: Tue, 27 Jul 2004 10:35:55 +0000 Subject: [PATCH] [project @ 2004-07-27 10:35:54 by ross] haddock fodder --- Foreign/C/Error.hs | 115 +++++++++++++++++++++++++++++----------------- Foreign/C/Types.hs | 94 +++++++++++++++++++++++++++++++++---- Foreign/Marshal/Error.hs | 25 +++++----- 3 files changed, 174 insertions(+), 60 deletions(-) diff --git a/Foreign/C/Error.hs b/Foreign/C/Error.hs index d7da52d..7cf294c 100644 --- a/Foreign/C/Error.hs +++ b/Foreign/C/Error.hs @@ -9,15 +9,21 @@ -- Stability : provisional -- Portability : portable -- --- C-specific Marshalling support: Handling of C \"errno\" error codes +-- C-specific Marshalling support: Handling of C \"errno\" error codes. -- ----------------------------------------------------------------------------- module Foreign.C.Error ( - -- Haskell representation for "errno" values - -- + -- * Haskell representations of @errno@ values + Errno(..), -- instance: Eq + + -- ** Common @errno@ symbols + -- | Different operating systems and\/or C libraries often support + -- different values of @errno@. This module defines the common values, + -- but due to the open definition of 'Errno' users may add definitions + -- which are not predefined. eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, @@ -32,6 +38,8 @@ module Foreign.C.Error ( eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV, + + -- ** 'Errno' functions -- :: Errno isValidErrno, -- :: Errno -> Bool @@ -52,8 +60,8 @@ module Foreign.C.Error ( -- throwErrno, -- :: String -> IO a - -- guards for IO operations that may fail - -- + -- ** Guards for IO operations that may fail + throwErrnoIf, -- :: (a -> Bool) -> String -> IO a -> IO a throwErrnoIf_, -- :: (a -> Bool) -> String -> IO a -> IO () throwErrnoIfRetry, -- :: (a -> Bool) -> String -> IO a -> IO a @@ -123,8 +131,10 @@ import System.IO.Unsafe ( unsafePerformIO ) -- "errno" type -- ------------ --- Haskell representation for "errno" values --- +-- | Haskell representation for @errno@ values. +-- The implementation is deliberately exposed, to allow users to add +-- their own definitions of 'Errno' values. + newtype Errno = Errno CInt instance Eq Errno where @@ -256,8 +266,9 @@ eWOULDBLOCK = Errno (CONST_EWOULDBLOCK) eXDEV = Errno (CONST_EXDEV) #endif --- checks whether the given errno value is supported on the current --- architecture +-- | Yield 'True' if the given 'Errno' value is valid on the system. +-- This implies that the 'Eq' instance of 'Errno' is also system dependent +-- as it is only defined for valid values of 'Errno'. -- isValidErrno :: Errno -> Bool -- @@ -269,7 +280,7 @@ isValidErrno (Errno errno) = errno /= -1 -- access to the current thread's "errno" value -- -------------------------------------------- --- yield the current thread's "errno" value +-- | Get the current value of @errno@ in the current thread. -- getErrno :: IO Errno @@ -284,7 +295,7 @@ getErrno = do e <- get_errno; return (Errno e) foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt #endif --- set the current thread's "errno" value to 0 +-- | Reset the current thread\'s @errno@ value to 'eOK'. -- resetErrno :: IO () @@ -299,10 +310,10 @@ foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> I -- throw current "errno" value -- --------------------------- --- the common case: throw an IO error based on a textual description --- of the error location and the current thread's "errno" value +-- | Throw an 'IOError' corresponding to the current value of 'getErrno'. -- -throwErrno :: String -> IO a +throwErrno :: String -- ^ textual description of the error location + -> IO a throwErrno loc = do errno <- getErrno @@ -312,22 +323,28 @@ throwErrno loc = -- guards for IO operations that may fail -- -------------------------------------- --- guard an IO operation and throw an "errno" based exception of the result --- value of the IO operation meets the given predicate +-- | Throw an 'IOError' corresponding to the current value of 'getErrno' +-- if the result value of the 'IO' action meets the given predicate. -- -throwErrnoIf :: (a -> Bool) -> String -> IO a -> IO a +throwErrnoIf :: (a -> Bool) -- ^ predicate to apply to the result value + -- of the 'IO' operation + -> String -- ^ textual description of the location + -> IO a -- ^ the 'IO' operation to be executed + -> IO a throwErrnoIf pred loc f = do res <- f if pred res then throwErrno loc else return res --- as `throwErrnoIf', but discards the result +-- | as 'throwErrnoIf', but discards the result of the 'IO' action after +-- error handling. -- -throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO () +throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO () throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f --- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose --- flag `EINTR') +-- | as 'throwErrnoIf', but retry the 'IO' action when it yields the +-- error code 'eINTR' - this amounts to the standard retry loop for +-- interrupted POSIX system calls. -- throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a throwErrnoIfRetry pred loc f = @@ -341,10 +358,17 @@ throwErrnoIfRetry pred loc f = else throwErrno loc else return res --- as `throwErrnoIfRetry', but checks for operations that would block and --- executes an alternative action in that case. - -throwErrnoIfRetryMayBlock :: (a -> Bool) -> String -> IO a -> IO b -> IO a +-- | as 'throwErrnoIfRetry', but checks for operations that would block and +-- executes an alternative action before retrying in that case. +-- +throwErrnoIfRetryMayBlock + :: (a -> Bool) -- ^ predicate to apply to the result value + -- of the 'IO' operation + -> String -- ^ textual description of the location + -> IO a -- ^ the 'IO' operation to be executed + -> IO b -- ^ action to execute before retrying if + -- an immediate retry would block + -> IO a throwErrnoIfRetryMayBlock pred loc f on_block = do res <- f @@ -358,60 +382,64 @@ throwErrnoIfRetryMayBlock pred loc f on_block = else throwErrno loc else return res --- as `throwErrnoIfRetry', but discards the result +-- | as 'throwErrnoIfRetry', but discards the result. -- throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO () throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f --- as `throwErrnoIfRetryMayBlock', but discards the result +-- | as 'throwErrnoIfRetryMayBlock', but discards the result. -- throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO () throwErrnoIfRetryMayBlock_ pred loc f on_block = void $ throwErrnoIfRetryMayBlock pred loc f on_block --- throws "errno" if a result of "-1" is returned +-- | Throw an 'IOError' corresponding to the current value of 'getErrno' +-- if the 'IO' action returns a result of @-1@. -- throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a throwErrnoIfMinus1 = throwErrnoIf (== -1) --- as `throwErrnoIfMinus1', but discards the result +-- | as 'throwErrnoIfMinus1', but discards the result. -- throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO () throwErrnoIfMinus1_ = throwErrnoIf_ (== -1) --- throws "errno" if a result of "-1" is returned, but retries in case of an --- interrupted operation +-- | Throw an 'IOError' corresponding to the current value of 'getErrno' +-- if the 'IO' action returns a result of @-1@, but retries in case of +-- an interrupted operation. -- throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1) --- as `throwErrnoIfMinus1', but discards the result +-- | as 'throwErrnoIfMinus1', but discards the result. -- throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO () throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1) --- as throwErrnoIfMinus1Retry, but checks for operations that would block +-- | as 'throwErrnoIfMinus1Retry', but checks for operations that would block. -- throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a throwErrnoIfMinus1RetryMayBlock = throwErrnoIfRetryMayBlock (== -1) --- as `throwErrnoIfMinus1RetryMayBlock', but discards the result +-- | as 'throwErrnoIfMinus1RetryMayBlock', but discards the result. -- throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO () throwErrnoIfMinus1RetryMayBlock_ = throwErrnoIfRetryMayBlock_ (== -1) --- throws "errno" if a result of a NULL pointer is returned +-- | Throw an 'IOError' corresponding to the current value of 'getErrno' +-- if the 'IO' action returns 'nullPtr'. -- throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a) throwErrnoIfNull = throwErrnoIf (== nullPtr) --- throws "errno" if a result of a NULL pointer is returned, but retries in --- case of an interrupted operation +-- | Throw an 'IOError' corresponding to the current value of 'getErrno' +-- if the 'IO' action returns 'nullPtr', +-- but retry in case of an interrupted operation. -- throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a) throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr) --- as throwErrnoIfNullRetry, but checks for operations that would block +-- | as 'throwErrnoIfNullRetry', but checks for operations that would block. -- throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a) throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr) @@ -419,10 +447,15 @@ throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr) -- conversion of an "errno" value into IO error -- -------------------------------------------- --- convert a location string, an "errno" value, an optional handle, --- and an optional filename into a matching IO error +-- | Construct a Haskell 98 I\/O error based on the given 'Errno' value. +-- The optional information can be used to improve the accuracy of +-- error messages. -- -errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError +errnoToIOError :: String -- ^ the location where the error occurred + -> Errno -- ^ the error number + -> Maybe Handle -- ^ optional handle associated with the error + -> Maybe String -- ^ optional filename associated with the error + -> IOError errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do str <- strerror errno >>= peekCString #if __GLASGOW_HASKELL__ diff --git a/Foreign/C/Types.hs b/Foreign/C/Types.hs index 0eb64d0..c4be5a7 100644 --- a/Foreign/C/Types.hs +++ b/Foreign/C/Types.hs @@ -14,24 +14,37 @@ ----------------------------------------------------------------------------- module Foreign.C.Types + ( -- * Representations of C types #ifndef __NHC__ - ( -- Integral types, instances of: Eq, Ord, Num, Read, Show, Enum, - -- Typeable, Storable, Bounded, Real, Integral, Bits + -- $ctypes + + -- ** Integral types + -- | These types are are represented as @newtype@s of types in + -- "Data.Int" and "Data.Word", and are instances of + -- 'Eq', 'Ord', 'Num', 'Read', 'Show', 'Enum', 'Typeable', + -- 'Storable', 'Bounded', 'Real', 'Integral' and 'Bits'. CChar, CSChar, CUChar , CShort, CUShort, CInt, CUInt , CLong, CULong , CPtrdiff, CSize, CWchar, CSigAtomic , CLLong, CULLong - -- Numeric types, instances of: Eq, Ord, Num, Read, Show, Enum, - -- Typeable, Storable + + -- ** Numeric types + -- | These types are are represented as @newtype@s of basic + -- foreign types, and are instances of + -- 'Eq', 'Ord', 'Num', 'Read', 'Show', 'Enum', 'Typeable' and + -- 'Storable'. , CClock, CTime - -- Floating types, instances of: Eq, Ord, Num, Read, Show, Enum, - -- Typeable, Storable, Real, Fractional, Floating, RealFrac, - -- RealFloat + -- ** Floating types + -- | These types are are represented as @newtype@s of 'Float' + -- and 'Double', and are instances of + -- 'Eq', 'Ord', 'Num', 'Read', 'Show', 'Enum', 'Typeable', + -- 'Storable', 'Real', 'Fractional', 'Floating', 'RealFrac' + -- and 'RealFloat'. , CFloat, CDouble, CLDouble #else - ( -- Exported non-abstractly in nhc98 to fix an interface file problem. + -- Exported non-abstractly in nhc98 to fix an interface file problem. CChar(..), CSChar(..), CUChar(..) , CShort(..), CUShort(..), CInt(..), CUInt(..) , CLong(..), CULong(..) @@ -40,6 +53,7 @@ module Foreign.C.Types , CClock(..), CTime(..) , CFloat(..), CDouble(..), CLDouble(..) #endif + -- ** Other types -- Instances of: Eq and Storable , CFile, CFpos, CJmpBuf @@ -69,20 +83,31 @@ import Foreign.Ptr #include "Typeable.h" #include "CTypes.h" +-- | Haskell type representing the C @char@ type. INTEGRAL_TYPE(CChar,tyConCChar,"CChar",HTYPE_CHAR) +-- | Haskell type representing the C @signed char@ type. INTEGRAL_TYPE(CSChar,tyConCSChar,"CSChar",HTYPE_SIGNED_CHAR) +-- | Haskell type representing the C @unsigned char@ type. INTEGRAL_TYPE(CUChar,tyConCUChar,"CUChar",HTYPE_UNSIGNED_CHAR) +-- | Haskell type representing the C @short@ type. INTEGRAL_TYPE(CShort,tyConCShort,"CShort",HTYPE_SHORT) +-- | Haskell type representing the C @unsigned short@ type. INTEGRAL_TYPE(CUShort,tyConCUShort,"CUShort",HTYPE_UNSIGNED_SHORT) +-- | Haskell type representing the C @int@ type. INTEGRAL_TYPE(CInt,tyConCInt,"CInt",HTYPE_INT) +-- | Haskell type representing the C @unsigned int@ type. INTEGRAL_TYPE(CUInt,tyConCUInt,"CUInt",HTYPE_UNSIGNED_INT) +-- | Haskell type representing the C @long@ type. INTEGRAL_TYPE(CLong,tyConCLong,"CLong",HTYPE_LONG) +-- | Haskell type representing the C @unsigned long@ type. INTEGRAL_TYPE(CULong,tyConCULong,"CULong",HTYPE_UNSIGNED_LONG) +-- | Haskell type representing the C @long long@ type. INTEGRAL_TYPE(CLLong,tyConCLLong,"CLLong",HTYPE_LONG_LONG) +-- | Haskell type representing the C @unsigned long long@ type. INTEGRAL_TYPE(CULLong,tyConCULLong,"CULLong",HTYPE_UNSIGNED_LONG_LONG) {-# RULES @@ -111,9 +136,12 @@ INTEGRAL_TYPE(CULLong,tyConCULLong,"CULLong",HTYPE_UNSIGNED_LONG_LONG) "fromIntegral/CULLong->a" fromIntegral = \(CULLong x) -> fromIntegral x #-} +-- | Haskell type representing the C @float@ type. FLOATING_TYPE(CFloat,tyConCFloat,"CFloat",HTYPE_FLOAT) +-- | Haskell type representing the C @double@ type. FLOATING_TYPE(CDouble,tyConCDouble,"CDouble",HTYPE_DOUBLE) -- HACK: Currently no long double in the FFI, so we simply re-use double +-- | Haskell type representing the C @long double@ type. FLOATING_TYPE(CLDouble,tyConCLDouble,"CLDouble",HTYPE_DOUBLE) {-# RULES @@ -126,9 +154,13 @@ FLOATING_TYPE(CLDouble,tyConCLDouble,"CLDouble",HTYPE_DOUBLE) "realToFrac/CLDouble->a" realToFrac = \(CLDouble x) -> realToFrac x #-} +-- | Haskell type representing the C @ptrdiff_t@ type. INTEGRAL_TYPE(CPtrdiff,tyConCPtrdiff,"CPtrdiff",HTYPE_PTRDIFF_T) +-- | Haskell type representing the C @size_t@ type. INTEGRAL_TYPE(CSize,tyConCSize,"CSize",HTYPE_SIZE_T) +-- | Haskell type representing the C @wchar_t@ type. INTEGRAL_TYPE(CWchar,tyConCWchar,"CWchar",HTYPE_WCHAR_T) +-- | Haskell type representing the C @sig_atomic_t@ type. INTEGRAL_TYPE(CSigAtomic,tyConCSigAtomic,"CSigAtomic",HTYPE_SIG_ATOMIC_T) {-# RULES @@ -143,17 +175,63 @@ INTEGRAL_TYPE(CSigAtomic,tyConCSigAtomic,"CSigAtomic",HTYPE_SIG_ATOMIC_T) "fromIntegral/CSigAtomic->a" fromIntegral = \(CSigAtomic x) -> fromIntegral x #-} +-- | Haskell type representing the C @clock_t@ type. ARITHMETIC_TYPE(CClock,tyConCClock,"CClock",HTYPE_CLOCK_T) +-- | Haskell type representing the C @time_t@ type. ARITHMETIC_TYPE(CTime,tyConCTime,"CTime",HTYPE_TIME_T) -- FIXME: Implement and provide instances for Eq and Storable +-- | Haskell type representing the C @FILE@ type. data CFile = CFile +-- | Haskell type representing the C @fpos_t@ type. data CFpos = CFpos +-- | Haskell type representing the C @jmp_buf@ type. data CJmpBuf = CJmpBuf -- C99 types which are still missing include: -- intptr_t, uintptr_t, intmax_t, uintmax_t, wint_t, wctrans_t, wctype_t +{- $ctypes + +These types are needed to accurately represent C function prototypes, +in order to access C library interfaces in Haskell. The Haskell system +is not required to represent those types exactly as C does, but the +following guarantees are provided concerning a Haskell type @CT@ +representing a C type @t@: + +* If a C function prototype has @t@ as an argument or result type, + the use of @CT@ in the corresponding position in a foreign declaration + permits the Haskell program to access the full range of values encoded by + the C type; and conversely, any Haskell value for @CT@ has a valid + representation in C. + +* @'sizeOf' ('undefined' :: CT)@ will yield the same value as + @sizeof (t)@ in C. + +* @'alignment' ('undefined' :: CT)@ matches the alignment constraint + enforced by the C implementation for @t@. + +* The members 'peek' and 'poke' of the 'Storable' class map all values of + @CT@ to the corresponding value of @t@ and vice versa. + +* When an instance of 'Bounded' is defined for @CT@, the values of + 'minBound' and 'maxBound' coincide with @t_MIN@ and @t_MAX@ in C. + +* When an instance of 'Eq' or 'Ord' is defined for @CT@, the predicates + defined by the type class implement the same relation as the + corresponding predicate in C on @t@. + +* When an instance of 'Num', 'Read', 'Integral', 'Fractional', 'Floating', + 'RealFrac', or 'RealFloat' is defined for @CT@, the arithmetic + operations defined by the type class implement the same function as + the corresponding arithmetic operations (if available) in C on @t@. + +* When an instance of 'Bits' is defined for @CT@, the bitwise operation + defined by the type class implement the same function as the + corresponding bitwise operation in C on @t@. + +-} + #else /* __NHC__ */ import NHC.FFI diff --git a/Foreign/Marshal/Error.hs b/Foreign/Marshal/Error.hs index 46fa2b7..a88fc19 100644 --- a/Foreign/Marshal/Error.hs +++ b/Foreign/Marshal/Error.hs @@ -9,15 +9,12 @@ -- Stability : provisional -- Portability : portable -- --- Marshalling support: Handling of common error conditions +-- Routines for testing return values and raising a 'userError' exception +-- in case of values indicating an error state. -- ----------------------------------------------------------------------------- module Foreign.Marshal.Error ( - -- * Error utilities - - -- |Throw an exception on specific return values - -- throwIf, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO a throwIf_, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO () throwIfNeg, -- :: (Ord a, Num a) @@ -34,6 +31,10 @@ module Foreign.Marshal.Error ( import Foreign.Ptr #ifdef __GLASGOW_HASKELL__ +#ifdef __HADDOCK__ +import Data.Bool +import System.IO.Error +#endif import GHC.Base import GHC.Num import GHC.IOBase @@ -42,13 +43,15 @@ import GHC.IOBase -- exported functions -- ------------------ --- |Guard an 'IO' operation and throw an exception if the result meets the given --- predicate --- --- * the second argument computes an error message from the result of the 'IO' --- operation +-- |Execute an 'IO' action, throwing a 'userError' if the predicate yields +-- 'True' when applied to the result returned by the 'IO' action. +-- If no exception is raised, return the result of the computation. -- -throwIf :: (a -> Bool) -> (a -> String) -> IO a -> IO a +throwIf :: (a -> Bool) -- ^ error condition on the result of the 'IO' action + -> (a -> String) -- ^ computes an error message from erroneous results + -- of the 'IO' action + -> IO a -- ^ the 'IO' action to be executed + -> IO a throwIf pred msgfct act = do res <- act -- 1.7.10.4