    {-# LINE 1 "libraries/unix/System/Posix/DynamicLinker/Module.hsc" #-}
    {-# LANGUAGE Safe #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  System.Posix.DynamicLinker.Module
    -- Copyright   :  (c) Volker Stolz <vs@foldr.org> 2003
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  vs@foldr.org
    -- Stability   :  provisional
    -- Portability :  non-portable (requires POSIX)
    --
    -- DLOpen support, old API
    --  Derived from GModule.chs by M.Weber & M.Chakravarty which is part of c2hs
    --  I left the API more or less the same, mostly the flags are different.
    --
    -----------------------------------------------------------------------------

    module System.Posix.DynamicLinker.Module (

    --  Usage:
    --  ******
    --
    --  Let's assume you want to open a local shared library 'foo' (./libfoo.so)
    --  offering a function
    --    char * mogrify (char*,int)
    --  and invoke str = mogrify("test",1):
    --
    --  type Fun = CString -> Int -> IO CString
    --  foreign import dynamic unsafe fun__ :: FunPtr Fun -> Fun
    --
    --  withModule (Just ".") ("libfoo.so") [RTLD_NOW] $ \ mod -> do
    --     funptr <- moduleSymbol mod "mogrify"
    --     let fun = fun__ funptr
    --     withCString "test" $ \ str -> do
    --       strptr <- fun str 1
    --       strstr <- peekCString strptr
    --       ...

          Module
        , moduleOpen             -- :: String -> ModuleFlags -> IO Module
        , moduleSymbol           -- :: Source -> String -> IO (FunPtr a)
        , moduleClose            -- :: Module -> IO Bool
        , moduleError            -- :: IO String
        , withModule             -- :: Maybe String
                                 -- -> String
                                 -- -> [ModuleFlags ]
                                 -- -> (Module -> IO a)
                                 -- -> IO a
        , withModule_            -- :: Maybe String
                                 -- -> String
                                 -- -> [ModuleFlags]
                                 -- -> (Module -> IO a)
                                 -- -> IO ()
        )
    where

    import Prelude hiding (head, tail)
    import System.Posix.DynamicLinker
    import System.Posix.DynamicLinker.Common
    import Foreign.Ptr      ( Ptr, nullPtr, FunPtr )
    import System.Posix.Internals ( withFilePath )

    unModule              :: Module -> (Ptr ())
    unModule :: Module -> Ptr ()
    unModule (Module Ptr ()
    adr)  = Ptr ()
    adr

    -- Opens a module (EXPORTED)
    --

    moduleOpen :: String -> [RTLDFlags] -> IO Module
    moduleOpen :: String -> [RTLDFlags] -> IO Module
    moduleOpen String
    file [RTLDFlags]
    flags = do
      modPtr <- String -> (CString -> IO (Ptr ())) -> IO (Ptr ())
    forall a. String -> (CString -> IO a) -> IO a
    withFilePath String
    file ((CString -> IO (Ptr ())) -> IO (Ptr ()))
    -> (CString -> IO (Ptr ())) -> IO (Ptr ())
    forall a b. (a -> b) -> a -> b
    $ \ CString
    modAddr -> CString -> CInt -> IO (Ptr ())
    c_dlopen CString
    modAddr ([RTLDFlags] -> CInt
    packRTLDFlags [RTLDFlags]
    flags)
      if (modPtr == nullPtr)
          then moduleError >>= \ String
    err -> IOError -> IO Module
    forall a. IOError -> IO a
    ioError (String -> IOError
    userError (String
    "dlopen: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    err))
          else return $ Module modPtr

    -- Gets a symbol pointer from a module (EXPORTED)
    --
    moduleSymbol :: Module -> String -> IO (FunPtr a)
    moduleSymbol :: forall a. Module -> String -> IO (FunPtr a)
    moduleSymbol Module
    file String
    sym = DL -> String -> IO (FunPtr a)
    forall a. DL -> String -> IO (FunPtr a)
    dlsym (Ptr () -> DL
    DLHandle (Module -> Ptr ()
    unModule Module
    file)) String
    sym

    -- Closes a module (EXPORTED)
    --
    moduleClose     :: Module -> IO ()
    moduleClose :: Module -> IO ()
    moduleClose Module
    file  = DL -> IO ()
    dlclose (Ptr () -> DL
    DLHandle (Module -> Ptr ()
    unModule Module
    file))

    -- Gets a string describing the last module error (EXPORTED)
    --
    moduleError :: IO String
    moduleError :: IO String
    moduleError  = IO String
    dlerror

    -- Convenience function, cares for module open- & closing
    -- additionally returns status of `moduleClose' (EXPORTED)
    --
    withModule :: Maybe String
               -> String
               -> [RTLDFlags]
               -> (Module -> IO a)
               -> IO a
    withModule :: forall a.
    Maybe String -> String -> [RTLDFlags] -> (Module -> IO a) -> IO a
    withModule Maybe String
    mdir String
    file [RTLDFlags]
    flags Module -> IO a
    p = do
      let modPath :: String
    modPath = case Maybe String
    mdir of
                      Maybe String
    Nothing -> String
    file
                      Just String
    dir  -> String
    dir String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ case String -> Maybe (String, Char)
    forall a. [a] -> Maybe ([a], a)
    unsnoc String
    dir of
                        Just (String
    _, Char
    '/') -> String
    file
                        Just{}        -> Char
    '/' Char -> String -> String
    forall a. a -> [a] -> [a]
    : String
    file
                        Maybe (String, Char)
    Nothing       -> String -> String
    forall a. HasCallStack => String -> a
    error String
    "System.Posix.DynamicLinker.Module.withModule: directory should not be Just \"\", pass Nothing instead"
      modu <- String -> [RTLDFlags] -> IO Module
    moduleOpen String
    modPath [RTLDFlags]
    flags
      result <- p modu
      moduleClose modu
      return result

    withModule_ :: Maybe String
                -> String
                -> [RTLDFlags]
                -> (Module -> IO a)
                -> IO ()
    withModule_ :: forall a.
    Maybe String -> String -> [RTLDFlags] -> (Module -> IO a) -> IO ()
    withModule_ Maybe String
    dir String
    file [RTLDFlags]
    flags Module -> IO a
    p = Maybe String -> String -> [RTLDFlags] -> (Module -> IO a) -> IO a
    forall a.
    Maybe String -> String -> [RTLDFlags] -> (Module -> IO a) -> IO a
    withModule Maybe String
    dir String
    file [RTLDFlags]
    flags Module -> IO a
    p IO a -> (a -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ a
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    -- Dual to 'Data.List.uncons'.
    unsnoc :: [a] -> Maybe ([a], a)
    unsnoc :: forall a. [a] -> Maybe ([a], a)
    unsnoc = (a -> Maybe ([a], a) -> Maybe ([a], a))
    -> Maybe ([a], a) -> [a] -> Maybe ([a], a)
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr a -> Maybe ([a], a) -> Maybe ([a], a)
    forall {a}. a -> Maybe ([a], a) -> Maybe ([a], a)
    go Maybe ([a], a)
    forall a. Maybe a
    Nothing
      where
        go :: a -> Maybe ([a], a) -> Maybe ([a], a)
    go a
    x Maybe ([a], a)
    Nothing = ([a], a) -> Maybe ([a], a)
    forall a. a -> Maybe a
    Just ([], a
    x)
        go a
    x (Just ([a]
    xs, a
    lst)) = ([a], a) -> Maybe ([a], a)
    forall a. a -> Maybe a
    Just (a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    xs, a
    lst)