Give locations of flag warnings/errors
[ghc-hetmet.git] / compiler / ghci / InteractiveUI.hs
index f88fe44..48033ae 100644 (file)
@@ -42,6 +42,7 @@ import SrcLoc
 
 -- Other random utilities
 import ErrUtils
+import CmdLineParser
 import Digraph
 import BasicTypes hiding (isTopLevel)
 import Panic      hiding (showException)
@@ -68,7 +69,7 @@ import System.Console.Editline.Readline as Readline
 
 --import SystemExts
 
-import Control.Exception as Exception
+import Exception
 -- import Control.Concurrent
 
 import System.FilePath
@@ -321,7 +322,7 @@ interactiveUI session srcs maybe_exprs = do
 
 #ifdef USE_EDITLINE
         is_tty <- hIsTerminalDevice stdin
-        when is_tty $ do
+        when is_tty $ withReadline $ do
             Readline.initialize
 
             withGhcAppData
@@ -337,8 +338,7 @@ interactiveUI session srcs maybe_exprs = do
 #endif
 
    -- initial context is just the Prelude
-   prel_mod <- GHC.findModule session (GHC.mkModuleName "Prelude") 
-                                      (Just basePackageId)
+   prel_mod <- GHC.findModule session (GHC.mkModuleName "Prelude") Nothing
    GHC.setContext session [] [prel_mod]
 
    default_editor <- findEditor
@@ -468,7 +468,7 @@ runGHCi paths maybe_exprs = do
 interactiveLoop :: Bool -> Bool -> GHCi ()
 interactiveLoop is_tty show_prompt =
   -- Ignore ^C exceptions caught here
-  ghciHandleDyn (\e -> case e of 
+  ghciHandleGhcException (\e -> case e of 
                        Interrupted -> do
 #if defined(mingw32_HOST_OS)
                                io (putStrLn "")
@@ -504,7 +504,7 @@ checkPerms _ =
   return True
 #else
 checkPerms name =
-  Util.handle (\_ -> return False) $ do
+  handleIO (\_ -> return False) $ do
      st <- getFileStatus name
      me <- getRealUserID
      if fileOwner st /= me then do
@@ -614,9 +614,7 @@ readlineLoop = do
    io yield
    saveSession -- for use by completion
    prompt <- mkPrompt
-   l <- io (readline prompt `finally` setNonBlockingFD 0)
-                -- readline sometimes puts stdin into blocking mode,
-                -- so we need to put it back for the IO library
+   l <- io $ withReadline (readline prompt)
    splatSavedSession
    case l of
         Nothing -> return Nothing
@@ -625,6 +623,20 @@ readlineLoop = do
                    io (addHistory l)
                    str <- io $ consoleInputToUnicode True l
                    return (Just str)
+
+withReadline :: IO a -> IO a
+withReadline = bracket_ stopTimer (do startTimer; setNonBlockingFD 0)
+     -- Two problems are being worked around here:
+     -- 1. readline sometimes puts stdin into blocking mode,
+     --    so we need to put it back for the IO library
+     -- 2. editline doesn't handle some of its system calls returning
+     --    EINTR, so our timer signal confuses it, hence we turn off
+     --    the timer signal when making calls to editline. (#2277)
+     --    If editline is ever fixed, we can remove this.
+
+-- These come from the RTS
+foreign import ccall unsafe startTimer :: IO ()
+foreign import ccall unsafe stopTimer  :: IO ()
 #endif
 
 queryQueue :: GHCi (Maybe String)
@@ -638,7 +650,7 @@ queryQueue = do
 runCommands :: GHCi (Maybe String) -> GHCi ()
 runCommands = runCommands' handler
 
-runCommands' :: (Exception -> GHCi Bool) -- Exception handler
+runCommands' :: (SomeException -> GHCi Bool) -- Exception handler
              -> GHCi (Maybe String) -> GHCi ()
 runCommands' eh getCmd = do
   mb_cmd <- noSpace queryQueue
@@ -845,7 +857,7 @@ help :: String -> GHCi ()
 help _ = io (putStr helpText)
 
 info :: String -> GHCi ()
-info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
+info "" = ghcError (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
 info s  = do { let names = words s
             ; session <- getSession
             ; dflags <- getDynFlags
@@ -935,7 +947,7 @@ editFile str =
      st <- getGHCiState
      let cmd = editor st
      when (null cmd) 
-       $ throwDyn (CmdLineError "editor not set, use :set editor")
+       $ ghcError (CmdLineError "editor not set, use :set editor")
      io $ system (cmd ++ ' ':file)
      return ()
 
@@ -967,7 +979,7 @@ chooseEditFile =
          do targets <- io (GHC.getTargets session)
             case msum (map fromTarget targets) of
               Just file -> return file
-              Nothing   -> throwDyn (CmdLineError "No files to edit.")
+              Nothing   -> ghcError (CmdLineError "No files to edit.")
           
   where fromTarget (GHC.Target (GHC.TargetFile f _) _) = Just f
         fromTarget _ = Nothing -- when would we get a module target?
@@ -984,7 +996,7 @@ defineMacro overwrite s = do
                                   unlines defined)
        else do
   if (not overwrite && macro_name `elem` defined)
-       then throwDyn (CmdLineError 
+       then ghcError (CmdLineError 
                ("macro '" ++ macro_name ++ "' is already defined"))
        else do
 
@@ -1013,7 +1025,7 @@ undefineMacro str = mapM_ undef (words str)
  where undef macro_name = do
         cmds <- io (readIORef macros_ref)
         if (macro_name `notElem` map cmdName cmds) 
-          then throwDyn (CmdLineError 
+          then ghcError (CmdLineError 
                ("macro '" ++ macro_name ++ "' is not defined"))
           else do
             io (writeIORef macros_ref (filter ((/= macro_name) . cmdName) cmds))
@@ -1042,6 +1054,7 @@ loadModule' files = do
   prev_context <- io $ GHC.getContext session
 
   -- unload first
+  io $ GHC.abandonAll session
   discardActiveBreakPoints
   io (GHC.setTargets session [])
   io (GHC.load session LoadAllTargets)
@@ -1227,8 +1240,8 @@ browseCmd bang m =
         case (as,bs) of
           (as@(_:_), _)   -> browseModule bang (last as) True
           ([],  bs@(_:_)) -> browseModule bang (last bs) True
-          ([],  [])  -> throwDyn (CmdLineError ":browse: no current module")
-    _ -> throwDyn (CmdLineError "syntax:  :browse <module>")
+          ([],  [])  -> ghcError (CmdLineError ":browse: no current module")
+    _ -> ghcError (CmdLineError "syntax:  :browse <module>")
 
 -- without bang, show items in context of their parents and omit children
 -- with bang, show class methods and data constructors separately, and
@@ -1252,7 +1265,7 @@ browseModule bang modl exports_only = do
 
   mb_mod_info <- io $ GHC.getModuleInfo s modl
   case mb_mod_info of
-    Nothing -> throwDyn (CmdLineError ("unknown module: " ++
+    Nothing -> ghcError (CmdLineError ("unknown module: " ++
                                 GHC.moduleNameString (GHC.moduleName modl)))
     Just mod_info -> do
         dflags <- getDynFlags
@@ -1324,7 +1337,7 @@ setContext str
        playCtxtCmd True (cmd, as, bs)
        st <- getGHCiState
        setGHCiState st{ remembered_ctx = remembered_ctx st ++ [(cmd,as,bs)] }
-  | otherwise = throwDyn (CmdLineError "syntax:  :module [+/-] [*]M1 ... [*]Mn")
+  | otherwise = ghcError (CmdLineError "syntax:  :module [+/-] [*]M1 ... [*]Mn")
   where
     (cmd, strs, as, bs) =
         case str of 
@@ -1491,13 +1504,12 @@ newDynFlags :: [String] -> GHCi ()
 newDynFlags minus_opts = do
       dflags <- getDynFlags
       let pkg_flags = packageFlags dflags
-      (dflags', leftovers, warns) <- io $ GHC.parseDynamicFlags dflags minus_opts
+      (dflags', leftovers, warns) <- io $ GHC.parseDynamicFlags dflags $ map noLoc minus_opts
       io $ handleFlagWarnings dflags' warns
 
       if (not (null leftovers))
-               then throwDyn (CmdLineError ("unrecognised flags: " ++ 
-                                               unwords leftovers))
-               else return ()
+        then ghcError $ errorsToGhcException leftovers
+        else return ()
 
       new_pkgs <- setDynFlags dflags'
 
@@ -1529,7 +1541,7 @@ unsetOptions str
        mapM_ unsetOpt plus_opts
  
        let no_flag ('-':'f':rest) = return ("-fno-" ++ rest)
-           no_flag f = throwDyn (ProgramError ("don't know how to reverse " ++ f))
+           no_flag f = ghcError (ProgramError ("don't know how to reverse " ++ f))
 
        no_flags <- mapM no_flag minus_opts
        newDynFlags no_flags
@@ -1584,7 +1596,7 @@ showCmd str = do
         ["context"]  -> showContext
         ["packages"]  -> showPackages
         ["languages"]  -> showLanguages
-       _ -> throwDyn (CmdLineError ("syntax:  :show [ args | prog | prompt | editor | stop | modules | bindings\n"++
+       _ -> ghcError (CmdLineError ("syntax:  :show [ args | prog | prompt | editor | stop | modules | bindings\n"++
                                      "               | breaks | context | packages | languages ]"))
 
 showModules :: GHCi ()
@@ -1810,14 +1822,15 @@ completeHomeModuleOrFile=completeNone
 -- raising another exception.  We therefore don't put the recursive
 -- handler arond the flushing operation, so if stderr is closed
 -- GHCi will just die gracefully rather than going into an infinite loop.
-handler :: Exception -> GHCi Bool
+handler :: SomeException -> GHCi Bool
 
 handler exception = do
   flushInterpBuffers
   io installSignalHandlers
   ghciHandle handler (showException exception >> return False)
 
-showException :: Exception -> GHCi ()
+showException :: SomeException -> GHCi ()
+#if __GLASGOW_HASKELL__ < 609
 showException (DynException dyn) =
   case fromDynamic dyn of
     Nothing               -> io (putStrLn ("*** Exception: (unknown)"))
@@ -1828,6 +1841,17 @@ showException (DynException dyn) =
 
 showException other_exception
   = io (putStrLn ("*** Exception: " ++ show other_exception))
+#else
+showException (SomeException e) =
+  io $ case cast e of
+       Just Interrupted         -> putStrLn "Interrupted."
+       -- omit the location for CmdLineError:
+       Just (CmdLineError s)    -> putStrLn s
+       -- ditto:
+       Just ph@(PhaseFailed {}) -> putStrLn (showGhcException ph "")
+       Just other_ghc_ex        -> print other_ghc_ex
+       Nothing                  -> putStrLn ("*** Exception: " ++ show e)
+#endif
 
 -----------------------------------------------------------------------------
 -- recursive exception handlers
@@ -1836,7 +1860,7 @@ showException other_exception
 -- in an exception loop (eg. let a = error a in a) the ^C exception
 -- may never be delivered.  Thanks to Marcin for pointing out the bug.
 
-ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
+ghciHandle :: (SomeException -> GHCi a) -> GHCi a -> GHCi a
 ghciHandle h (GHCi m) = GHCi $ \s -> 
    Exception.catch (m s) 
        (\e -> unGHCi (ghciUnblock (h e)) s)
@@ -1844,7 +1868,7 @@ ghciHandle h (GHCi m) = GHCi $ \s ->
 ghciUnblock :: GHCi a -> GHCi a
 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
 
-ghciTry :: GHCi a -> GHCi (Either Exception a)
+ghciTry :: GHCi a -> GHCi (Either SomeException a)
 ghciTry (GHCi m) = GHCi $ \s -> Exception.try (m s) 
 
 -- ----------------------------------------------------------------------------
@@ -1868,7 +1892,7 @@ wantInterpretedModule str = do
    modl <- lookupModule str
    is_interpreted <- io (GHC.moduleIsInterpreted session modl)
    when (not is_interpreted) $
-       throwDyn (CmdLineError ("module '" ++ str ++ "' is not interpreted"))
+       ghcError (CmdLineError ("module '" ++ str ++ "' is not interpreted"))
    return modl
 
 wantNameFromInterpretedModule :: (Name -> SDoc -> GHCi ()) -> String
@@ -1927,7 +1951,7 @@ stepModuleCmd  [] = do
     Nothing  -> stepCmd []
     Just _ -> do
        Just span <- getCurrentBreakSpan
-       let f some_span = optSrcSpanFileName span == optSrcSpanFileName some_span
+       let f some_span = srcSpanFileName_maybe span == srcSpanFileName_maybe some_span
        doContinue f GHC.SingleStep
 
 stepModuleCmd expression = stepCmd expression
@@ -2082,7 +2106,7 @@ breakByModuleLine mod line args
    | otherwise = breakSyntax
 
 breakSyntax :: a
-breakSyntax = throwDyn (CmdLineError "Syntax: :break [<mod>] <line> [<column>]")
+breakSyntax = ghcError (CmdLineError "Syntax: :break [<mod>] <line> [<column>]")
 
 findBreakAndSet :: Module -> (TickArray -> Maybe (Int, SrcSpan)) -> GHCi ()
 findBreakAndSet mod lookupTickTree = do 
@@ -2162,7 +2186,7 @@ findBreakByCoord mb_file (line, col) arr
 do_bold :: Bool
 do_bold = (`isPrefixOf` unsafePerformIO mTerm) `any` ["xterm", "linux"]
     where mTerm = System.Environment.getEnv "TERM"
-                  `Exception.catch` \_ -> return "TERM not set"
+                  `catchIO` \_ -> return "TERM not set"
 
 start_bold :: String
 start_bold = "\ESC[1m"
@@ -2237,7 +2261,7 @@ listModuleLine modl line = do
 
 -- | list a section of a source file around a particular SrcSpan.
 -- If the highlight flag is True, also highlight the span using
--- start_bold/end_bold.
+-- start_bold\/end_bold.
 listAround :: SrcSpan -> Bool -> IO ()
 listAround span do_highlight = do
       contents <- BS.readFile (unpackFS file)