A haskell IRC bot because who doesn't need one
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
1.5KB

  1. {-# LANGUAGE MagicHash #-}
  2. {-# LANGUAGE UnboxedTuples #-}
  3. module IRC.Plugins.Loader ( load ) where
  4. import qualified Data.HashMap.Lazy as M
  5. import IRC.Plugins.Plugin
  6. import Control.Exception ( catch, ErrorCall )
  7. import GHC.Exts ( addrToAny# )
  8. import GHC.Ptr ( Ptr(..) )
  9. import System.Info ( os, arch )
  10. import GHCi.ObjLink
  11. import Encoding
  12. load :: PluginSet -> String -> IO (Either String PluginSet)
  13. load set path = do
  14. initObjLinker RetainCAFs
  15. loadObj "Plugin.o"
  16. _ret <- resolveObjs
  17. ptr <- lookupSymbol (mangleSymbol Nothing "Plugin" "f")
  18. case ptr of
  19. Nothing -> return $ Left "Couldn’t load symbol"
  20. Just (Ptr addr) -> case addrToAny# addr of
  21. (# f #) -> return $ Right f
  22. unload :: PluginSet -> String -> IO PluginSet
  23. unload set plugin = catch unloadPlugin exceptionHandler
  24. where exceptionHandler :: ErrorCall -> IO PluginSet
  25. exceptionHandler _ = return set
  26. unloadPlugin :: IO PluginSet
  27. unloadPlugin = do
  28. unloadObj $ plugin <> ".o"
  29. return $ M.delete plugin set
  30. mangleSymbol :: Maybe String -> String -> String -> String
  31. mangleSymbol pkg module' valsym =
  32. prefixUnderscore <>
  33. maybe "" (\p -> zEncodeString p <> "_") pkg <>
  34. zEncodeString module' <> "_" <> zEncodeString valsym <> "_closure"
  35. prefixUnderscore :: String
  36. prefixUnderscore =
  37. case (os,arch) of
  38. ("mingw32","x86_64") -> ""
  39. ("cygwin","x86_64") -> ""
  40. ("mingw32",_) -> "_"
  41. ("darwin",_) -> "_"
  42. ("cygwin",_) -> "_"
  43. _ -> ""