1 -----------------------------------------------------------------------------
2 -- $Id: InteractiveUI.hs,v 1.93 2001/10/16 13:25:00 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(..) )
26 import Finder ( flushPackageCache )
28 import Id ( isRecordSelector, recordSelectorFieldLabel,
29 isDataConWrapId, idName )
30 import Class ( className )
31 import TyCon ( tyConName, tyConClass_maybe, isPrimTyCon )
32 import FieldLabel ( fieldLabelTyCon )
33 import SrcLoc ( isGoodSrcLoc )
34 import Name ( Name, isHomePackageName, nameSrcLoc, nameOccName,
36 import OccName ( isSymOcc )
37 import BasicTypes ( defaultFixity )
39 import CmdLineOpts ( DynFlag(..), getDynFlags, saveDynFlags, restoreDynFlags, dopt_unset )
40 import Panic ( GhcException(..) )
43 #ifndef mingw32_TARGET_OS
49 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
63 import PrelGHC ( unsafeCoerce# )
64 import Foreign ( nullPtr )
65 import CString ( peekCString )
67 -----------------------------------------------------------------------------
71 \ / _ \\ /\\ /\\/ __(_)\n\
72 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
73 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
74 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
76 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
78 builtin_commands :: [(String, String -> GHCi Bool)]
80 ("add", keepGoing addModule),
81 ("cd", keepGoing changeDirectory),
82 ("def", keepGoing defineMacro),
83 ("help", keepGoing help),
84 ("?", keepGoing help),
85 ("info", keepGoing info),
86 ("load", keepGoing loadModule),
87 ("module", keepGoing setContext),
88 ("reload", keepGoing reloadModule),
89 ("set", keepGoing setOptions),
90 ("type", keepGoing typeOfExpr),
91 ("unset", keepGoing unsetOptions),
92 ("undef", keepGoing undefineMacro),
96 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
97 keepGoing a str = a str >> return False
99 shortHelpText = "use :? for help.\n"
102 \ Commands available from the prompt:\n\
104 \ <stmt> evaluate/run <stmt>\n\
105 \ :add <filename> ... add module(s) to the current target set\n\
106 \ :cd <dir> change directory to <dir>\n\
107 \ :def <cmd> <expr> define a command :<cmd>\n\
108 \ :help, :? display this list of commands\n\
109 \ :info [<name> ...] display information about the given names\n\
110 \ :load <filename> ... load module(s) and their dependents\n\
111 \ :module <mod> set the context for expression evaluation to <mod>\n\
112 \ :reload reload the current module set\n\
113 \ :set <option> ... set options\n\
114 \ :undef <cmd> undefine user-defined command :<cmd>\n\
115 \ :type <expr> show the type of <expr>\n\
116 \ :unset <option> ... unset options\n\
118 \ :!<command> run the shell command <command>\n\
120 \ Options for `:set' and `:unset':\n\
122 \ +r revert top-level expressions after each evaluation\n\
123 \ +s print timing/memory stats after each evaluation\n\
124 \ +t print type after evaluation\n\
125 \ -<flags> most GHC command line flags can also be set here\n\
126 \ (eg. -v2, -fglasgow-exts, etc.)\n\
129 interactiveUI :: CmState -> [FilePath] -> [LibrarySpec] -> IO ()
130 interactiveUI cmstate paths cmdline_libs = do
132 hSetBuffering stdout NoBuffering
134 -- link in the available packages
135 pkgs <- getPackageInfo
137 linkPackages cmdline_libs pkgs
139 (cmstate, ok, mods) <-
141 [] -> return (cmstate, True, [])
142 _ -> cmLoadModule cmstate paths
144 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
148 dflags <- getDynFlags
150 (cmstate, maybe_hval)
151 <- cmCompileExpr cmstate dflags "IO.hSetBuffering IO.stdout IO.NoBuffering >> IO.hSetBuffering IO.stderr IO.NoBuffering"
153 Just hval -> unsafeCoerce# hval :: IO ()
154 _ -> panic "interactiveUI:buffering"
156 (cmstate, maybe_hval)
157 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stderr"
159 Just hval -> writeIORef flush_stderr (unsafeCoerce# hval :: IO ())
160 _ -> panic "interactiveUI:stderr"
162 (cmstate, maybe_hval)
163 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stdout"
165 Just hval -> writeIORef flush_stdout (unsafeCoerce# hval :: IO ())
166 _ -> panic "interactiveUI:stdout"
168 startGHCi runGHCi GHCiState{ targets = paths,
172 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
173 Readline.resetTerminal Nothing
181 read_dot_files <- io (readIORef v_Read_DotGHCi)
183 when (read_dot_files) $ do
186 exists <- io (doesFileExist file)
188 dir_ok <- io (checkPerms ".")
189 file_ok <- io (checkPerms file)
190 when (dir_ok && file_ok) $ do
191 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
194 Right hdl -> fileLoop hdl False
196 when (read_dot_files) $ do
197 -- Read in $HOME/.ghci
198 either_dir <- io (IO.try (getEnv "HOME"))
202 cwd <- io (getCurrentDirectory)
203 when (dir /= cwd) $ do
204 let file = dir ++ "/.ghci"
205 ok <- io (checkPerms file)
207 either_hdl <- io (IO.try (openFile file ReadMode))
210 Right hdl -> fileLoop hdl False
212 -- read commands from stdin
213 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
220 io $ do putStrLn "Leaving GHCi."
223 -- NOTE: We only read .ghci files if they are owned by the current user,
224 -- and aren't world writable. Otherwise, we could be accidentally
225 -- running code planted by a malicious third party.
227 -- Furthermore, We only read ./.ghci if . is owned by the current user
228 -- and isn't writable by anyone else. I think this is sufficient: we
229 -- don't need to check .. and ../.. etc. because "." always refers to
230 -- the same directory while a process is running.
232 checkPerms :: String -> IO Bool
234 handle (\_ -> return False) $ do
235 #ifdef mingw32_TARGET_OS
238 st <- getFileStatus name
240 if fileOwner st /= me then do
241 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
244 let mode = fileMode st
245 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
246 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
248 putStrLn $ "*** WARNING: " ++ name ++
249 " is writable by someone else, IGNORING!"
254 fileLoop :: Handle -> Bool -> GHCi ()
255 fileLoop hdl prompt = do
257 mod <- io (cmGetContext (cmstate st))
258 when prompt (io (putStr (mod ++ "> ")))
259 l <- io (IO.try (hGetLine hdl))
261 Left e | isEOFError e -> return ()
262 | otherwise -> throw e
264 case remove_spaces l of
265 "" -> fileLoop hdl prompt
266 l -> do quit <- runCommand l
267 if quit then return () else fileLoop hdl prompt
269 stringLoop :: [String] -> GHCi ()
270 stringLoop [] = return ()
271 stringLoop (s:ss) = do
273 case remove_spaces s of
275 l -> do quit <- runCommand l
276 if quit then return () else stringLoop ss
278 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
279 readlineLoop :: GHCi ()
282 mod <- io (cmGetContext (cmstate st))
283 l <- io (readline (mod ++ "> "))
287 case remove_spaces l of
292 if quit then return () else readlineLoop
295 -- Top level exception handler, just prints out the exception
297 runCommand :: String -> GHCi Bool
299 ghciHandle ( \exception -> do
301 showException exception
306 showException (DynException dyn) =
307 case fromDynamic dyn of
309 io (putStrLn ("*** Exception: (unknown)"))
310 Just (PhaseFailed phase code) ->
311 io (putStrLn ("Phase " ++ phase ++ " failed (code "
312 ++ show code ++ ")"))
314 io (putStrLn "Interrupted.")
315 Just (CmdLineError s) ->
316 io (putStrLn s) -- omit the location for CmdLineError
318 io (putStrLn (show other_ghc_ex))
319 showException other_exception
320 = io (putStrLn ("*** Exception: " ++ show other_exception))
322 doCommand (':' : command) = specialCommand command
324 = do timeIt (do stuff <- runStmt stmt; finishEvalExpr stuff)
327 -- Returns True if the expr was successfully parsed, renamed and
329 runStmt :: String -> GHCi (Maybe [Name])
331 | null (filter (not.isSpace) stmt)
334 = do st <- getGHCiState
335 dflags <- io getDynFlags
336 let dflags' = dopt_unset dflags Opt_WarnUnusedBinds
337 (new_cmstate, names) <- io (cmRunStmt (cmstate st) dflags' stmt)
338 setGHCiState st{cmstate = new_cmstate}
341 -- possibly print the type and revert CAFs after evaluating an expression
342 finishEvalExpr Nothing = return False
343 finishEvalExpr (Just names)
344 = do b <- isOptionSet ShowType
346 when b (mapM_ (showTypeOfName (cmstate st)) names)
348 b <- isOptionSet RevertCAFs
349 io (when b revertCAFs)
353 showTypeOfName :: CmState -> Name -> GHCi ()
354 showTypeOfName cmstate n
355 = do maybe_str <- io (cmTypeOfName cmstate n)
358 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
360 flushEverything :: GHCi ()
362 = io $ do flush_so <- readIORef flush_stdout
364 flush_se <- readIORef flush_stdout
368 specialCommand :: String -> GHCi Bool
369 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
370 specialCommand str = do
371 let (cmd,rest) = break isSpace str
372 cmds <- io (readIORef commands)
373 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
374 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
375 ++ shortHelpText) >> return False)
376 [(_,f)] -> f (dropWhile isSpace rest)
377 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
378 " matches multiple commands (" ++
379 foldr1 (\a b -> a ++ ',':b) (map fst cs)
380 ++ ")") >> return False)
382 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
384 -----------------------------------------------------------------------------
387 help :: String -> GHCi ()
388 help _ = io (putStr helpText)
390 info :: String -> GHCi ()
391 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
394 state <- getGHCiState
395 dflags <- io getDynFlags
397 infoThings cms [] = return cms
398 infoThings cms (name:names) = do
399 (cms, unqual, stuff) <- io (cmInfoThing cms dflags name)
400 io (putStrLn (showSDocForUser unqual (
401 vcat (intersperse (text "") (map showThing stuff))))
405 showThing (ty_thing, fixity)
406 = vcat [ text "-- " <> showTyThing ty_thing,
407 showFixity fixity (getName ty_thing),
408 ppr (ifaceTyThing ty_thing) ]
411 | fix == defaultFixity = empty
412 | otherwise = ppr fix <+>
413 (if isSymOcc (nameOccName name)
415 else char '`' <> ppr name <> char '`')
417 showTyThing (AClass cl)
418 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
419 showTyThing (ATyCon ty)
421 = hcat [ppr ty, text " is a primitive type constructor"]
423 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
424 showTyThing (AnId id)
425 = hcat [ppr id, text " is a ", idDescr id, showSrcLoc (idName id)]
428 | isRecordSelector id =
429 case tyConClass_maybe (fieldLabelTyCon (
430 recordSelectorFieldLabel id)) of
431 Nothing -> text "record selector"
432 Just c -> text "method in class " <> ppr c
433 | isDataConWrapId id = text "data constructor"
434 | otherwise = text "variable"
436 -- also print out the source location for home things
438 | isHomePackageName name && isGoodSrcLoc loc
439 = hsep [ text ", defined at", ppr loc ]
442 where loc = nameSrcLoc name
444 cms <- infoThings (cmstate state) names
445 setGHCiState state{ cmstate = cms }
449 addModule :: String -> GHCi ()
451 let files = words str
452 state <- getGHCiState
453 dflags <- io (getDynFlags)
454 io (revertCAFs) -- always revert CAFs on load/add.
455 let new_targets = files ++ targets state
456 (cmstate1, ok, mods) <- io (cmLoadModule (cmstate state) new_targets)
457 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
458 modulesLoadedMsg ok mods
460 setContext :: String -> GHCi ()
462 = throwDyn (CmdLineError "syntax: `:m <module>'")
463 setContext m | not (isUpper (head m)) || not (all isAlphaNumEx (tail m))
464 = throwDyn (CmdLineError ("strange looking module name: `" ++ m ++ "'"))
466 isAlphaNumEx c = isAlphaNum c || c == '_'
468 = do st <- getGHCiState
469 new_cmstate <- io (cmSetContext (cmstate st) str)
470 setGHCiState st{cmstate=new_cmstate}
472 changeDirectory :: String -> GHCi ()
473 changeDirectory ('~':d) = do
474 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
475 io (setCurrentDirectory (tilde ++ '/':d))
476 changeDirectory d = io (setCurrentDirectory d)
478 defineMacro :: String -> GHCi ()
480 let (macro_name, definition) = break isSpace s
481 cmds <- io (readIORef commands)
483 then throwDyn (CmdLineError "invalid macro name")
485 if (macro_name `elem` map fst cmds)
486 then throwDyn (CmdLineError
487 ("command `" ++ macro_name ++ "' is already defined"))
490 -- give the expression a type signature, so we can be sure we're getting
491 -- something of the right type.
492 let new_expr = '(' : definition ++ ") :: String -> IO String"
494 -- compile the expression
496 dflags <- io getDynFlags
497 (new_cmstate, maybe_hv) <- io (cmCompileExpr (cmstate st) dflags new_expr)
498 setGHCiState st{cmstate = new_cmstate}
501 Just hv -> io (writeIORef commands --
502 ((macro_name, keepGoing (runMacro hv)) : cmds))
504 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
506 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
507 stringLoop (lines str)
509 undefineMacro :: String -> GHCi ()
510 undefineMacro macro_name = do
511 cmds <- io (readIORef commands)
512 if (macro_name `elem` map fst builtin_commands)
513 then throwDyn (CmdLineError
514 ("command `" ++ macro_name ++ "' cannot be undefined"))
516 if (macro_name `notElem` map fst cmds)
517 then throwDyn (CmdLineError
518 ("command `" ++ macro_name ++ "' not defined"))
520 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
522 loadModule :: String -> GHCi ()
523 loadModule str = timeIt (loadModule' str)
526 let files = words str
527 state <- getGHCiState
528 dflags <- io getDynFlags
529 cmstate1 <- io (cmUnload (cmstate state) dflags)
530 setGHCiState state{ cmstate = cmstate1, targets = [] }
531 io (revertCAFs) -- always revert CAFs on load.
532 (cmstate2, ok, mods) <- io (cmLoadModule cmstate1 files)
533 setGHCiState state{ cmstate = cmstate2, targets = files }
534 modulesLoadedMsg ok mods
536 reloadModule :: String -> GHCi ()
538 state <- getGHCiState
539 case targets state of
540 [] -> io (putStr "no current target\n")
542 -> do io (revertCAFs) -- always revert CAFs on reload.
543 (new_cmstate, ok, mods) <- io (cmLoadModule (cmstate state) paths)
544 setGHCiState state{ cmstate=new_cmstate }
545 modulesLoadedMsg ok mods
547 reloadModule _ = noArgs ":reload"
550 modulesLoadedMsg ok mods = do
552 | null mods = text "none."
554 punctuate comma (map text mods)) <> text "."
557 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
559 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
562 typeOfExpr :: String -> GHCi ()
564 = do st <- getGHCiState
565 dflags <- io getDynFlags
566 (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr (cmstate st) dflags str)
567 setGHCiState st{cmstate = new_cmstate}
570 Just tystr -> io (putStrLn tystr)
572 quit :: String -> GHCi Bool
575 shellEscape :: String -> GHCi Bool
576 shellEscape str = io (system str >> return False)
578 ----------------------------------------------------------------------------
581 -- set options in the interpreter. Syntax is exactly the same as the
582 -- ghc command line, except that certain options aren't available (-C,
585 -- This is pretty fragile: most options won't work as expected. ToDo:
586 -- figure out which ones & disallow them.
588 setOptions :: String -> GHCi ()
590 = do st <- getGHCiState
591 let opts = options st
592 io $ putStrLn (showSDoc (
593 text "options currently set: " <>
596 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
599 = do -- first, deal with the GHCi opts (+s, +t, etc.)
600 let (plus_opts, minus_opts) = partition isPlus (words str)
601 mapM setOpt plus_opts
603 -- now, the GHC flags
604 pkgs_before <- io (readIORef v_Packages)
605 leftovers <- io (processArgs static_flags minus_opts [])
606 pkgs_after <- io (readIORef v_Packages)
608 -- update things if the users wants more packages
609 when (pkgs_before /= pkgs_after) $
610 newPackages (pkgs_after \\ pkgs_before)
612 -- then, dynamic flags
615 leftovers <- processArgs dynamic_flags leftovers []
618 if (not (null leftovers))
619 then throwDyn (CmdLineError ("unrecognised flags: " ++
624 unsetOptions :: String -> GHCi ()
626 = do -- first, deal with the GHCi opts (+s, +t, etc.)
628 (minus_opts, rest1) = partition isMinus opts
629 (plus_opts, rest2) = partition isPlus rest1
631 if (not (null rest2))
632 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
635 mapM unsetOpt plus_opts
637 -- can't do GHC flags for now
638 if (not (null minus_opts))
639 then throwDyn (CmdLineError "can't unset GHC command-line flags")
642 isMinus ('-':s) = True
645 isPlus ('+':s) = True
649 = case strToGHCiOpt str of
650 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
651 Just o -> setOption o
654 = case strToGHCiOpt str of
655 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
656 Just o -> unsetOption o
658 strToGHCiOpt :: String -> (Maybe GHCiOption)
659 strToGHCiOpt "s" = Just ShowTiming
660 strToGHCiOpt "t" = Just ShowType
661 strToGHCiOpt "r" = Just RevertCAFs
662 strToGHCiOpt _ = Nothing
664 optToStr :: GHCiOption -> String
665 optToStr ShowTiming = "s"
666 optToStr ShowType = "t"
667 optToStr RevertCAFs = "r"
669 newPackages new_pkgs = do
670 state <- getGHCiState
671 dflags <- io getDynFlags
672 cmstate1 <- io (cmUnload (cmstate state) dflags)
673 setGHCiState state{ cmstate = cmstate1, targets = [] }
676 pkgs <- getPackageInfo
677 flushPackageCache pkgs
679 new_pkg_info <- getPackageDetails new_pkgs
680 mapM_ linkPackage (reverse new_pkg_info)
682 -----------------------------------------------------------------------------
685 data GHCiState = GHCiState
687 targets :: [FilePath],
689 options :: [GHCiOption]
693 = ShowTiming -- show time/allocs after evaluation
694 | ShowType -- show the type of expressions
695 | RevertCAFs -- revert CAFs after every evaluation
698 GLOBAL_VAR(flush_stdout, error "no flush_stdout", IO ())
699 GLOBAL_VAR(flush_stderr, error "no flush_stdout", IO ())
701 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
703 startGHCi :: GHCi a -> GHCiState -> IO a
704 startGHCi g state = do ref <- newIORef state; unGHCi g ref
706 instance Monad GHCi where
707 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
708 return a = GHCi $ \s -> return a
710 getGHCiState = GHCi $ \r -> readIORef r
711 setGHCiState s = GHCi $ \r -> writeIORef r s
713 isOptionSet :: GHCiOption -> GHCi Bool
715 = do st <- getGHCiState
716 return (opt `elem` options st)
718 setOption :: GHCiOption -> GHCi ()
720 = do st <- getGHCiState
721 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
723 unsetOption :: GHCiOption -> GHCi ()
725 = do st <- getGHCiState
726 setGHCiState (st{ options = filter (/= opt) (options st) })
729 io m = GHCi { unGHCi = \s -> m >>= return }
731 -----------------------------------------------------------------------------
732 -- recursive exception handlers
734 -- Don't forget to unblock async exceptions in the handler, or if we're
735 -- in an exception loop (eg. let a = error a in a) the ^C exception
736 -- may never be delivered. Thanks to Marcin for pointing out the bug.
738 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
739 ghciHandle h (GHCi m) = GHCi $ \s ->
740 Exception.catch (m s)
741 (\e -> unGHCi (ghciHandle h (ghciUnblock (h e))) s)
743 ghciUnblock :: GHCi a -> GHCi a
744 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
746 -----------------------------------------------------------------------------
749 -- Left: full path name of a .o file, including trailing .o
750 -- Right: "unadorned" name of a .DLL/.so
751 -- e.g. On unix "qt" denotes "libqt.so"
752 -- On WinDoze "burble" denotes "burble.DLL"
753 -- addDLL is platform-specific and adds the lib/.so/.DLL
754 -- suffixes platform-dependently; we don't do that here.
756 -- For dynamic objects only, try to find the object file in all the
757 -- directories specified in v_Library_Paths before giving up.
760 = Either FilePath String
762 showLS (Left nm) = "(static) " ++ nm
763 showLS (Right nm) = "(dynamic) " ++ nm
765 linkPackages :: [LibrarySpec] -> [PackageConfig] -> IO ()
766 linkPackages cmdline_lib_specs pkgs
767 = do mapM_ linkPackage (reverse pkgs)
768 lib_paths <- readIORef v_Library_paths
769 mapM_ (preloadLib lib_paths) cmdline_lib_specs
770 if (null cmdline_lib_specs)
772 else do putStr "final link ... "
774 if ok then putStrLn "done."
775 else throwDyn (InstallationError "linking extra libraries/objects failed")
777 preloadLib :: [String] -> LibrarySpec -> IO ()
778 preloadLib lib_paths lib_spec
779 = do putStr ("Loading object " ++ showLS lib_spec ++ " ... ")
782 -> do b <- preload_static lib_paths static_ish
783 putStrLn (if b then "done." else "not found")
785 -> -- We add "" to the set of paths to try, so that
786 -- if none of the real paths match, we force addDLL
787 -- to look in the default dynamic-link search paths.
788 do b <- preload_dynamic (lib_paths++[""]) dll_unadorned
789 when (not b) (cantFind lib_paths lib_spec)
792 cantFind :: [String] -> LibrarySpec -> IO ()
794 = do putStr ("failed.\nCan't find " ++ showLS spec
795 ++ " in directories:\n"
796 ++ unlines (map (" "++) paths) )
799 -- not interested in the paths in the static case.
800 preload_static paths name
801 = do b <- doesFileExist name
802 if not b then return False
803 else loadObj name >> return True
805 preload_dynamic [] name
807 preload_dynamic (path:paths) rootname
808 = do maybe_errmsg <- addDLL path rootname
809 if maybe_errmsg /= nullPtr
810 then preload_dynamic paths rootname
814 = (throwDyn . CmdLineError)
815 "user specified .o/.so/.DLL could not be loaded."
817 -- Packages that are already linked into GHCi. For mingw32, we only
818 -- skip gmp and rts, since std and after need to load the msvcrt.dll
819 -- library which std depends on.
821 # ifndef mingw32_TARGET_OS
822 = [ "gmp", "rts", "std", "concurrent", "posix", "text", "util" ]
827 linkPackage :: PackageConfig -> IO ()
829 = do putStr ("Loading package " ++ name pkg ++ " ... ")
830 -- For each obj, try obj.o and if that fails, obj.so.
831 -- Complication: all the .so's must be loaded before any of the .o's.
832 let dirs = library_dirs pkg
833 let objs = hs_libraries pkg ++ extra_libraries pkg
834 classifieds <- mapM (locateOneObj dirs) objs
836 -- Don't load the .so libs if this is a package GHCi is already
837 -- linked against, because we'll already have the .so linked in.
838 let (so_libs, obj_libs) = partition isRight classifieds
839 let sos_first | name pkg `elem` loaded_in_ghci = obj_libs
840 | otherwise = so_libs ++ obj_libs
842 mapM loadClassified sos_first
843 putStr "linking ... "
845 if ok then putStrLn "done."
846 else panic ("can't load package `" ++ name pkg ++ "'")
848 isRight (Right _) = True
849 isRight (Left _) = False
851 loadClassified :: LibrarySpec -> IO ()
852 loadClassified (Left obj_absolute_filename)
853 = do loadObj obj_absolute_filename
854 loadClassified (Right dll_unadorned)
855 = do maybe_errmsg <- addDLL "" dll_unadorned -- doesn't seem right to me
856 if maybe_errmsg == nullPtr
858 else do str <- peekCString maybe_errmsg
859 throwDyn (CmdLineError ("can't load .so/.DLL for: "
860 ++ dll_unadorned ++ " (" ++ str ++ ")" ))
862 locateOneObj :: [FilePath] -> String -> IO LibrarySpec
864 = return (Right obj) -- we assume
865 locateOneObj (d:ds) obj
866 = do let path = d ++ '/':obj ++ ".o"
867 b <- doesFileExist path
868 if b then return (Left path) else locateOneObj ds obj
870 -----------------------------------------------------------------------------
871 -- timing & statistics
873 timeIt :: GHCi a -> GHCi a
875 = do b <- isOptionSet ShowTiming
878 else do allocs1 <- io $ getAllocations
879 time1 <- io $ getCPUTime
881 allocs2 <- io $ getAllocations
882 time2 <- io $ getCPUTime
883 io $ printTimes (allocs2 - allocs1) (time2 - time1)
886 foreign import "getAllocations" getAllocations :: IO Int
888 printTimes :: Int -> Integer -> IO ()
889 printTimes allocs psecs
890 = do let secs = (fromIntegral psecs / (10^12)) :: Float
891 secs_str = showFFloat (Just 2) secs
893 parens (text (secs_str "") <+> text "secs" <> comma <+>
894 int allocs <+> text "bytes")))
896 -----------------------------------------------------------------------------
899 foreign import revertCAFs :: IO () -- make it "safe", just in case