1 -----------------------------------------------------------------------------
2 -- $Id: InteractiveUI.hs,v 1.87 2001/08/15 14:41:49 simonmar Exp $
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2000
8 -----------------------------------------------------------------------------
10 {-# OPTIONS -#include "Linker.h" #-}
11 {-# OPTIONS -#include "SchedAPI.h" #-}
12 module InteractiveUI ( interactiveUI, ghciWelcomeMsg ) where
14 #include "../includes/config.h"
15 #include "HsVersions.h"
19 import HscTypes ( GhciMode(..), TyThing(..) )
20 import MkIface ( ifaceTyCls )
26 import Finder ( flushPackageCache )
28 import Id ( isDataConWrapId, idName )
29 import Class ( className )
30 import TyCon ( tyConName )
31 import SrcLoc ( isGoodSrcLoc )
32 import Name ( Name, isHomePackageName, nameSrcLoc )
34 import CmdLineOpts ( DynFlag(..), getDynFlags, saveDynFlags, restoreDynFlags, dopt_unset )
35 import Panic ( GhcException(..) )
38 #ifndef mingw32_TARGET_OS
44 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
58 import PrelGHC ( unsafeCoerce# )
59 import Foreign ( nullPtr )
60 import CString ( peekCString )
62 -----------------------------------------------------------------------------
66 \ / _ \\ /\\ /\\/ __(_)\n\
67 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
68 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
69 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
71 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
73 builtin_commands :: [(String, String -> GHCi Bool)]
75 ("add", keepGoing addModule),
76 ("cd", keepGoing changeDirectory),
77 ("def", keepGoing defineMacro),
78 ("help", keepGoing help),
79 ("?", keepGoing help),
80 ("info", keepGoing info),
81 ("load", keepGoing loadModule),
82 ("module", keepGoing setContext),
83 ("reload", keepGoing reloadModule),
84 ("set", keepGoing setOptions),
85 ("type", keepGoing typeOfExpr),
86 ("unset", keepGoing unsetOptions),
87 ("undef", keepGoing undefineMacro),
91 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
92 keepGoing a str = a str >> return False
94 shortHelpText = "use :? for help.\n"
97 \ Commands available from the prompt:\n\
99 \ <stmt> evaluate/run <stmt>\n\
100 \ :add <filename> ... add module(s) to the current target set\n\
101 \ :cd <dir> change directory to <dir>\n\
102 \ :def <cmd> <expr> define a command :<cmd>\n\
103 \ :help, :? display this list of commands\n\
104 \ :info [<name> ...] display information about the given names\n\
105 \ :load <filename> ... load module(s) and their dependents\n\
106 \ :module <mod> set the context for expression evaluation to <mod>\n\
107 \ :reload reload the current module set\n\
108 \ :set <option> ... set options\n\
109 \ :undef <cmd> undefine user-defined command :<cmd>\n\
110 \ :type <expr> show the type of <expr>\n\
111 \ :unset <option> ... unset options\n\
113 \ :!<command> run the shell command <command>\n\
115 \ Options for `:set' and `:unset':\n\
117 \ +r revert top-level expressions after each evaluation\n\
118 \ +s print timing/memory stats after each evaluation\n\
119 \ +t print type after evaluation\n\
120 \ -<flags> most GHC command line flags can also be set here\n\
121 \ (eg. -v2, -fglasgow-exts, etc.)\n\
124 interactiveUI :: CmState -> [FilePath] -> [LibrarySpec] -> IO ()
125 interactiveUI cmstate paths cmdline_libs = do
127 hSetBuffering stdout NoBuffering
129 -- link in the available packages
130 pkgs <- getPackageInfo
132 linkPackages cmdline_libs pkgs
134 (cmstate, ok, mods) <-
136 [] -> return (cmstate, True, [])
137 _ -> cmLoadModule cmstate paths
139 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
143 dflags <- getDynFlags
145 (cmstate, maybe_hval)
146 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stderr"
148 Just hval -> writeIORef flush_stderr (unsafeCoerce# hval :: IO ())
149 _ -> panic "interactiveUI:stderr"
151 (cmstate, maybe_hval)
152 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stdout"
154 Just hval -> writeIORef flush_stdout (unsafeCoerce# hval :: IO ())
155 _ -> panic "interactiveUI:stdout"
157 startGHCi runGHCi GHCiState{ targets = paths,
161 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
162 Readline.resetTerminal Nothing
170 read_dot_files <- io (readIORef v_Read_DotGHCi)
172 when (read_dot_files) $ do
175 exists <- io (doesFileExist file)
177 dir_ok <- io (checkPerms ".")
178 file_ok <- io (checkPerms file)
179 when (dir_ok && file_ok) $ do
180 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
183 Right hdl -> fileLoop hdl False
185 when (read_dot_files) $ do
186 -- Read in $HOME/.ghci
187 either_dir <- io (IO.try (getEnv "HOME"))
191 cwd <- io (getCurrentDirectory)
192 when (dir /= cwd) $ do
193 let file = dir ++ "/.ghci"
194 ok <- io (checkPerms file)
196 either_hdl <- io (IO.try (openFile file ReadMode))
199 Right hdl -> fileLoop hdl False
201 -- read commands from stdin
202 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
209 io $ do putStrLn "Leaving GHCi."
212 -- NOTE: We only read .ghci files if they are owned by the current user,
213 -- and aren't world writable. Otherwise, we could be accidentally
214 -- running code planted by a malicious third party.
216 -- Furthermore, We only read ./.ghci if . is owned by the current user
217 -- and isn't writable by anyone else. I think this is sufficient: we
218 -- don't need to check .. and ../.. etc. because "." always refers to
219 -- the same directory while a process is running.
221 checkPerms :: String -> IO Bool
223 handle (\_ -> return False) $ do
224 #ifdef mingw32_TARGET_OS
227 st <- getFileStatus name
229 if fileOwner st /= me then do
230 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
233 let mode = fileMode st
234 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
235 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
237 putStrLn $ "*** WARNING: " ++ name ++
238 " is writable by someone else, IGNORING!"
243 fileLoop :: Handle -> Bool -> GHCi ()
244 fileLoop hdl prompt = do
246 mod <- io (cmGetContext (cmstate st))
247 when prompt (io (putStr (mod ++ "> ")))
248 l <- io (IO.try (hGetLine hdl))
250 Left e | isEOFError e -> return ()
251 | otherwise -> throw e
253 case remove_spaces l of
254 "" -> fileLoop hdl prompt
255 l -> do quit <- runCommand l
256 if quit then return () else fileLoop hdl prompt
258 stringLoop :: [String] -> GHCi ()
259 stringLoop [] = return ()
260 stringLoop (s:ss) = do
262 case remove_spaces s of
264 l -> do quit <- runCommand l
265 if quit then return () else stringLoop ss
267 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
268 readlineLoop :: GHCi ()
271 mod <- io (cmGetContext (cmstate st))
272 l <- io (readline (mod ++ "> "))
276 case remove_spaces l of
281 if quit then return () else readlineLoop
284 -- Top level exception handler, just prints out the exception
286 runCommand :: String -> GHCi Bool
288 ghciHandle ( \exception -> do
290 showException exception
295 showException (DynException dyn) =
296 case fromDynamic dyn of
298 io (putStrLn ("*** Exception: (unknown)"))
299 Just (PhaseFailed phase code) ->
300 io (putStrLn ("Phase " ++ phase ++ " failed (code "
301 ++ show code ++ ")"))
303 io (putStrLn "Interrupted.")
304 Just (CmdLineError s) ->
305 io (putStrLn s) -- omit the location for CmdLineError
307 io (putStrLn (show other_ghc_ex))
308 showException other_exception
309 = io (putStrLn ("*** Exception: " ++ show other_exception))
311 doCommand (':' : command) = specialCommand command
313 = do timeIt (do stuff <- runStmt stmt; finishEvalExpr stuff)
316 -- Returns True if the expr was successfully parsed, renamed and
318 runStmt :: String -> GHCi (Maybe [Name])
320 | null (filter (not.isSpace) stmt)
323 = do st <- getGHCiState
324 dflags <- io getDynFlags
325 let dflags' = dopt_unset dflags Opt_WarnUnusedBinds
326 (new_cmstate, names) <- io (cmRunStmt (cmstate st) dflags' stmt)
327 setGHCiState st{cmstate = new_cmstate}
330 -- possibly print the type and revert CAFs after evaluating an expression
331 finishEvalExpr Nothing = return False
332 finishEvalExpr (Just names)
333 = do b <- isOptionSet ShowType
335 when b (mapM_ (showTypeOfName (cmstate st)) names)
337 b <- isOptionSet RevertCAFs
338 io (when b revertCAFs)
342 showTypeOfName :: CmState -> Name -> GHCi ()
343 showTypeOfName cmstate n
344 = do maybe_str <- io (cmTypeOfName cmstate n)
347 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
349 flushEverything :: GHCi ()
351 = io $ do flush_so <- readIORef flush_stdout
353 flush_se <- readIORef flush_stdout
357 specialCommand :: String -> GHCi Bool
358 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
359 specialCommand str = do
360 let (cmd,rest) = break isSpace str
361 cmds <- io (readIORef commands)
362 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
363 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
364 ++ shortHelpText) >> return False)
365 [(_,f)] -> f (dropWhile isSpace rest)
366 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
367 " matches multiple commands (" ++
368 foldr1 (\a b -> a ++ ',':b) (map fst cs)
369 ++ ")") >> return False)
371 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
373 -----------------------------------------------------------------------------
376 help :: String -> GHCi ()
377 help _ = io (putStr helpText)
379 info :: String -> GHCi ()
380 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
383 state <- getGHCiState
384 dflags <- io getDynFlags
386 infoThings cms [] = return cms
387 infoThings cms (name:names) = do
388 (cms, unqual, ty_things) <- io (cmInfoThing cms dflags name)
389 io (putStrLn (showSDocForUser unqual (
390 vcat (intersperse (text "") (map showThing ty_things))))
394 showThing ty_thing = vcat [ text "-- " <> showTyThing ty_thing,
395 ppr (ifaceTyCls ty_thing) ]
397 showTyThing (AClass cl)
398 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
399 showTyThing (ATyCon ty)
400 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
401 showTyThing (AnId id)
403 = hcat [ppr id, text " is a data constructor", showSrcLoc (idName id)]
405 = hcat [ppr id, text " is a variable", showSrcLoc (idName id)]
407 -- also print out the source location for home things
409 | isHomePackageName name && isGoodSrcLoc loc
410 = hsep [ text ", defined at", ppr loc ]
413 where loc = nameSrcLoc name
415 cms <- infoThings (cmstate state) names
416 setGHCiState state{ cmstate = cms }
420 addModule :: String -> GHCi ()
422 let files = words str
423 state <- getGHCiState
424 dflags <- io (getDynFlags)
425 io (revertCAFs) -- always revert CAFs on load/add.
426 let new_targets = files ++ targets state
427 (cmstate1, ok, mods) <- io (cmLoadModule (cmstate state) new_targets)
428 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
429 modulesLoadedMsg ok mods
431 setContext :: String -> GHCi ()
433 = throwDyn (CmdLineError "syntax: `:m <module>'")
434 setContext m | not (isUpper (head m)) || not (all isAlphaNumEx (tail m))
435 = throwDyn (CmdLineError ("strange looking module name: `" ++ m ++ "'"))
437 isAlphaNumEx c = isAlphaNum c || c == '_'
439 = do st <- getGHCiState
440 new_cmstate <- io (cmSetContext (cmstate st) str)
441 setGHCiState st{cmstate=new_cmstate}
443 changeDirectory :: String -> GHCi ()
444 changeDirectory ('~':d) = do
445 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
446 io (setCurrentDirectory (tilde ++ '/':d))
447 changeDirectory d = io (setCurrentDirectory d)
449 defineMacro :: String -> GHCi ()
451 let (macro_name, definition) = break isSpace s
452 cmds <- io (readIORef commands)
454 then throwDyn (CmdLineError "invalid macro name")
456 if (macro_name `elem` map fst cmds)
457 then throwDyn (CmdLineError
458 ("command `" ++ macro_name ++ "' is already defined"))
461 -- give the expression a type signature, so we can be sure we're getting
462 -- something of the right type.
463 let new_expr = '(' : definition ++ ") :: String -> IO String"
465 -- compile the expression
467 dflags <- io getDynFlags
468 (new_cmstate, maybe_hv) <- io (cmCompileExpr (cmstate st) dflags new_expr)
469 setGHCiState st{cmstate = new_cmstate}
472 Just hv -> io (writeIORef commands --
473 ((macro_name, keepGoing (runMacro hv)) : cmds))
475 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
477 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
478 stringLoop (lines str)
480 undefineMacro :: String -> GHCi ()
481 undefineMacro macro_name = do
482 cmds <- io (readIORef commands)
483 if (macro_name `elem` map fst builtin_commands)
484 then throwDyn (CmdLineError
485 ("command `" ++ macro_name ++ "' cannot be undefined"))
487 if (macro_name `notElem` map fst cmds)
488 then throwDyn (CmdLineError
489 ("command `" ++ macro_name ++ "' not defined"))
491 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
493 loadModule :: String -> GHCi ()
494 loadModule str = timeIt (loadModule' str)
497 let files = words str
498 state <- getGHCiState
499 dflags <- io getDynFlags
500 cmstate1 <- io (cmUnload (cmstate state) dflags)
501 setGHCiState state{ cmstate = cmstate1, targets = [] }
502 io (revertCAFs) -- always revert CAFs on load.
503 (cmstate2, ok, mods) <- io (cmLoadModule cmstate1 files)
504 setGHCiState state{ cmstate = cmstate2, targets = files }
505 modulesLoadedMsg ok mods
507 reloadModule :: String -> GHCi ()
509 state <- getGHCiState
510 case targets state of
511 [] -> io (putStr "no current target\n")
513 -> do io (revertCAFs) -- always revert CAFs on reload.
514 (new_cmstate, ok, mods) <- io (cmLoadModule (cmstate state) paths)
515 setGHCiState state{ cmstate=new_cmstate }
516 modulesLoadedMsg ok mods
518 reloadModule _ = noArgs ":reload"
521 modulesLoadedMsg ok mods = do
523 | null mods = text "none."
525 punctuate comma (map text mods)) <> text "."
528 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
530 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
533 typeOfExpr :: String -> GHCi ()
535 = do st <- getGHCiState
536 dflags <- io getDynFlags
537 (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr (cmstate st) dflags str)
538 setGHCiState st{cmstate = new_cmstate}
541 Just tystr -> io (putStrLn tystr)
543 quit :: String -> GHCi Bool
546 shellEscape :: String -> GHCi Bool
547 shellEscape str = io (system str >> return False)
549 ----------------------------------------------------------------------------
552 -- set options in the interpreter. Syntax is exactly the same as the
553 -- ghc command line, except that certain options aren't available (-C,
556 -- This is pretty fragile: most options won't work as expected. ToDo:
557 -- figure out which ones & disallow them.
559 setOptions :: String -> GHCi ()
561 = do st <- getGHCiState
562 let opts = options st
563 io $ putStrLn (showSDoc (
564 text "options currently set: " <>
567 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
570 = do -- first, deal with the GHCi opts (+s, +t, etc.)
571 let (plus_opts, minus_opts) = partition isPlus (words str)
572 mapM setOpt plus_opts
574 -- now, the GHC flags
575 pkgs_before <- io (readIORef v_Packages)
576 leftovers <- io (processArgs static_flags minus_opts [])
577 pkgs_after <- io (readIORef v_Packages)
579 -- update things if the users wants more packages
580 when (pkgs_before /= pkgs_after) $
581 newPackages (pkgs_after \\ pkgs_before)
583 -- then, dynamic flags
586 leftovers <- processArgs dynamic_flags leftovers []
589 if (not (null leftovers))
590 then throwDyn (CmdLineError ("unrecognised flags: " ++
595 unsetOptions :: String -> GHCi ()
597 = do -- first, deal with the GHCi opts (+s, +t, etc.)
599 (minus_opts, rest1) = partition isMinus opts
600 (plus_opts, rest2) = partition isPlus rest1
602 if (not (null rest2))
603 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
606 mapM unsetOpt plus_opts
608 -- can't do GHC flags for now
609 if (not (null minus_opts))
610 then throwDyn (CmdLineError "can't unset GHC command-line flags")
613 isMinus ('-':s) = True
616 isPlus ('+':s) = True
620 = case strToGHCiOpt str of
621 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
622 Just o -> setOption o
625 = case strToGHCiOpt str of
626 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
627 Just o -> unsetOption o
629 strToGHCiOpt :: String -> (Maybe GHCiOption)
630 strToGHCiOpt "s" = Just ShowTiming
631 strToGHCiOpt "t" = Just ShowType
632 strToGHCiOpt "r" = Just RevertCAFs
633 strToGHCiOpt _ = Nothing
635 optToStr :: GHCiOption -> String
636 optToStr ShowTiming = "s"
637 optToStr ShowType = "t"
638 optToStr RevertCAFs = "r"
640 newPackages new_pkgs = do
641 state <- getGHCiState
642 dflags <- io getDynFlags
643 cmstate1 <- io (cmUnload (cmstate state) dflags)
644 setGHCiState state{ cmstate = cmstate1, targets = [] }
647 pkgs <- getPackageInfo
648 flushPackageCache pkgs
650 new_pkg_info <- getPackageDetails new_pkgs
651 mapM_ (linkPackage False) (reverse new_pkg_info)
653 -----------------------------------------------------------------------------
656 data GHCiState = GHCiState
658 targets :: [FilePath],
660 options :: [GHCiOption]
664 = ShowTiming -- show time/allocs after evaluation
665 | ShowType -- show the type of expressions
666 | RevertCAFs -- revert CAFs after every evaluation
669 GLOBAL_VAR(flush_stdout, error "no flush_stdout", IO ())
670 GLOBAL_VAR(flush_stderr, error "no flush_stdout", IO ())
672 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
674 startGHCi :: GHCi a -> GHCiState -> IO a
675 startGHCi g state = do ref <- newIORef state; unGHCi g ref
677 instance Monad GHCi where
678 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
679 return a = GHCi $ \s -> return a
681 getGHCiState = GHCi $ \r -> readIORef r
682 setGHCiState s = GHCi $ \r -> writeIORef r s
684 isOptionSet :: GHCiOption -> GHCi Bool
686 = do st <- getGHCiState
687 return (opt `elem` options st)
689 setOption :: GHCiOption -> GHCi ()
691 = do st <- getGHCiState
692 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
694 unsetOption :: GHCiOption -> GHCi ()
696 = do st <- getGHCiState
697 setGHCiState (st{ options = filter (/= opt) (options st) })
700 io m = GHCi { unGHCi = \s -> m >>= return }
702 -----------------------------------------------------------------------------
703 -- recursive exception handlers
705 -- Don't forget to unblock async exceptions in the handler, or if we're
706 -- in an exception loop (eg. let a = error a in a) the ^C exception
707 -- may never be delivered. Thanks to Marcin for pointing out the bug.
709 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
710 ghciHandle h (GHCi m) = GHCi $ \s ->
711 Exception.catch (m s)
712 (\e -> unGHCi (ghciHandle h (ghciUnblock (h e))) s)
714 ghciUnblock :: GHCi a -> GHCi a
715 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
717 -----------------------------------------------------------------------------
720 -- Left: full path name of a .o file, including trailing .o
721 -- Right: "unadorned" name of a .DLL/.so
722 -- e.g. On unix "qt" denotes "libqt.so"
723 -- On WinDoze "burble" denotes "burble.DLL"
724 -- addDLL is platform-specific and adds the lib/.so/.DLL
725 -- suffixes platform-dependently; we don't do that here.
727 -- For dynamic objects only, try to find the object file in all the
728 -- directories specified in v_Library_Paths before giving up.
731 = Either FilePath String
733 showLS (Left nm) = "(static) " ++ nm
734 showLS (Right nm) = "(dynamic) " ++ nm
736 linkPackages :: [LibrarySpec] -> [PackageConfig] -> IO ()
737 linkPackages cmdline_lib_specs pkgs
738 = do sequence_ [ linkPackage (name p `elem` loaded) p | p <- reverse pkgs ]
739 lib_paths <- readIORef v_Library_paths
740 mapM_ (preloadLib lib_paths) cmdline_lib_specs
741 if (null cmdline_lib_specs)
743 else do putStr "final link ... "
745 if ok then putStrLn "done."
746 else throwDyn (InstallationError "linking extra libraries/objects failed")
748 -- Packages that are already linked into GHCi. For mingw32, we only
749 -- skip gmp and rts, since std and after need to load the msvcrt.dll
750 -- library which std depends on.
752 # ifndef mingw32_TARGET_OS
753 = [ "gmp", "rts", "std", "concurrent", "posix", "text", "util" ]
758 preloadLib :: [String] -> LibrarySpec -> IO ()
759 preloadLib lib_paths lib_spec
760 = do putStr ("Loading object " ++ showLS lib_spec ++ " ... ")
763 -> do b <- preload_static lib_paths static_ish
764 putStrLn (if b then "done." else "not found")
766 -> -- We add "" to the set of paths to try, so that
767 -- if none of the real paths match, we force addDLL
768 -- to look in the default dynamic-link search paths.
769 do b <- preload_dynamic (lib_paths++[""]) dll_unadorned
770 when (not b) (cantFind lib_paths lib_spec)
773 cantFind :: [String] -> LibrarySpec -> IO ()
775 = do putStr ("failed.\nCan't find " ++ showLS spec
776 ++ " in directories:\n"
777 ++ unlines (map (" "++) paths) )
780 -- not interested in the paths in the static case.
781 preload_static paths name
782 = do b <- doesFileExist name
783 if not b then return False
784 else loadObj name >> return True
786 preload_dynamic [] name
788 preload_dynamic (path:paths) rootname
789 = do maybe_errmsg <- addDLL path rootname
790 if maybe_errmsg /= nullPtr
791 then preload_dynamic paths rootname
795 = (throwDyn . CmdLineError)
796 "user specified .o/.so/.DLL could not be loaded."
799 linkPackage :: Bool -> PackageConfig -> IO ()
800 -- ignore rts and gmp for now (ToDo; better?)
801 linkPackage loaded_in_ghci pkg
802 | name pkg `elem` ["rts", "gmp"]
805 = do putStr ("Loading package " ++ name pkg ++ " ... ")
806 -- For each obj, try obj.o and if that fails, obj.so.
807 -- Complication: all the .so's must be loaded before any of the .o's.
808 let dirs = library_dirs pkg
809 let objs = hs_libraries pkg ++ extra_libraries pkg
810 classifieds <- mapM (locateOneObj dirs) objs
812 -- Don't load the .so libs if this is a package GHCi is already
813 -- linked against, because we'll already have the .so linked in.
814 let (so_libs, obj_libs) = partition isRight classifieds
815 let sos_first | loaded_in_ghci = obj_libs
816 | otherwise = so_libs ++ obj_libs
818 mapM loadClassified sos_first
819 putStr "linking ... "
821 if ok then putStrLn "done."
822 else panic ("can't load package `" ++ name pkg ++ "'")
824 isRight (Right _) = True
825 isRight (Left _) = False
827 loadClassified :: LibrarySpec -> IO ()
828 loadClassified (Left obj_absolute_filename)
829 = do loadObj obj_absolute_filename
830 loadClassified (Right dll_unadorned)
831 = do maybe_errmsg <- addDLL "" dll_unadorned -- doesn't seem right to me
832 if maybe_errmsg == nullPtr
834 else do str <- peekCString maybe_errmsg
835 throwDyn (CmdLineError ("can't load .so/.DLL for: "
836 ++ dll_unadorned ++ " (" ++ str ++ ")" ))
838 locateOneObj :: [FilePath] -> String -> IO LibrarySpec
840 = return (Right obj) -- we assume
841 locateOneObj (d:ds) obj
842 = do let path = d ++ '/':obj ++ ".o"
843 b <- doesFileExist path
844 if b then return (Left path) else locateOneObj ds obj
846 -----------------------------------------------------------------------------
847 -- timing & statistics
849 timeIt :: GHCi a -> GHCi a
851 = do b <- isOptionSet ShowTiming
854 else do allocs1 <- io $ getAllocations
855 time1 <- io $ getCPUTime
857 allocs2 <- io $ getAllocations
858 time2 <- io $ getCPUTime
859 io $ printTimes (allocs2 - allocs1) (time2 - time1)
862 foreign import "getAllocations" getAllocations :: IO Int
864 printTimes :: Int -> Integer -> IO ()
865 printTimes allocs psecs
866 = do let secs = (fromIntegral psecs / (10^12)) :: Float
867 secs_str = showFFloat (Just 2) secs
869 parens (text (secs_str "") <+> text "secs" <> comma <+>
870 int allocs <+> text "bytes")))
872 -----------------------------------------------------------------------------
875 foreign import revertCAFs :: IO () -- make it "safe", just in case