[project @ 2001-05-28 03:31:19 by sof]
[ghc-hetmet.git] / ghc / compiler / main / DriverUtil.hs
index 9a92b83..8ddc416 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: DriverUtil.hs,v 1.5 2000/10/27 13:50:25 sewardj Exp $
+-- $Id: DriverUtil.hs,v 1.22 2001/05/28 03:31:19 sof Exp $
 --
 -- Utils for the driver
 --
@@ -9,27 +9,31 @@
 
 module DriverUtil where
 
+#include "../includes/config.h"
 #include "HsVersions.h"
 
-import Config
 import Util
+import Panic
 
 import IOExts
 import Exception
 import Dynamic
 import RegexString
 
+import Directory       ( getDirectoryContents )
 import IO
 import System
 import List
 import Char
 import Monad
 
+#ifndef mingw32_TARGET_OS
+import Posix
+#endif
+
 -----------------------------------------------------------------------------
 -- Errors
 
-short_usage = "Usage: For basic information, try the `--help' option."
-   
 GLOBAL_VAR(v_Path_usage,  "",  String)
 
 long_usage = do
@@ -39,39 +43,12 @@ long_usage = do
   exitWith ExitSuccess
   where
      dump "" = return ()
-     dump ('$':'$':s) = hPutStr stderr get_prog_name >> dump s
+     dump ('$':'$':s) = hPutStr stderr progName >> dump s
      dump (c:s) = hPutChar stderr c >> dump s
 
-version_str = cProjectVersion
-
-data BarfKind
-  = PhaseFailed String ExitCode
-  | Interrupted
-  | UsageError String                  -- prints the short usage msg after the error
-  | OtherError String                  -- just prints the error message
-  deriving Eq
-
-GLOBAL_VAR(v_Prog_name, "ghc", String)
-
-get_prog_name = unsafePerformIO (readIORef v_Prog_name) -- urk!
-
-instance Show BarfKind where
-  showsPrec _ e = showString get_prog_name . showString ": " . showBarf e
-
-showBarf (UsageError str) = showString str . showChar '\n' . showString short_usage
-showBarf (OtherError str) = showString str
-showBarf (PhaseFailed phase code) = 
-       showString phase . showString " failed, code = " . shows code
-showBarf (Interrupted) = showString "interrupted"
-
-unknownFlagErr f = throwDyn (UsageError ("unrecognised flag: " ++ f))
-
-barfKindTc = mkTyCon "BarfKind"
-instance Typeable BarfKind where
-  typeOf _ = mkAppTy barfKindTc []
-
 -----------------------------------------------------------------------------
 -- Reading OPTIONS pragmas
+
 getOptionsFromSource 
        :: String               -- input file
        -> IO [String]          -- options, if any
@@ -87,14 +64,29 @@ getOptionsFromSource file
                   | prefixMatch "#" l -> look h
                   | prefixMatch "{-# LINE" l -> look h   -- -}
                   | Just (opts:_) <- matchRegex optionRegex l
-                       -> return (words opts)
+                       -> do rest <- look h
+                              return (words opts ++ rest)
                   | otherwise -> return []
 
 optionRegex = mkRegex "\\{-#[ \t]+OPTIONS[ \t]+(.*)#-\\}"   -- -}
 
 -----------------------------------------------------------------------------
+-- A version of getDirectoryContents that is non-fatal if the
+-- directory doesn't exist.
+
+softGetDirectoryContents d
+   = IO.catch (getDirectoryContents d)
+         (\_ -> do hPutStr stderr 
+                         ("WARNING: error while reading directory " ++ d)
+                   return []
+         )
+
+-----------------------------------------------------------------------------
 -- Utils
 
+unknownFlagErr :: String -> a
+unknownFlagErr f = throwDyn (UsageError ("unrecognised flag: " ++ f))
+
 my_partition :: (a -> Maybe b) -> [a] -> ([(a,b)],[a])
 my_partition _ [] = ([],[])
 my_partition p (a:as)
@@ -115,6 +107,9 @@ later = flip finally
 handleDyn :: Typeable ex => (ex -> IO a) -> IO a -> IO a
 handleDyn = flip catchDyn
 
+handle :: (Exception -> IO a) -> IO a -> IO a
+handle = flip Exception.catchAllIO
+
 split :: Char -> String -> [String]
 split c s = case rest of
                []     -> [chunk] 
@@ -132,10 +127,19 @@ addNoDups var x = do
   unless (x `elem` xs) $ writeIORef var (x:xs)
 
 splitFilename :: String -> (String,String)
-splitFilename f = (reverse (stripDot rev_basename), reverse rev_ext)
-  where (rev_ext, rev_basename) = span ('.' /=) (reverse f)
-        stripDot ('.':xs) = xs
-        stripDot xs       = xs
+splitFilename f = split_longest_prefix f '.'
+
+getFileSuffix :: String -> String
+getFileSuffix f = drop_longest_prefix f '.'
+
+-- "foo/bar/xyzzy.ext" -> ("foo/bar", "xyzzy", ".ext")
+splitFilename3 :: String -> (String,String,String)
+splitFilename3 str
+   = let (dir, rest) = split_longest_prefix str '/'
+        (name, ext) = splitFilename rest
+        real_dir | null dir  = "."
+                 | otherwise = dir
+     in  (real_dir, name, ext)
 
 remove_suffix :: Char -> String -> String
 remove_suffix c s
@@ -151,6 +155,16 @@ take_longest_prefix :: String -> Char -> String
 take_longest_prefix s c = reverse pre
   where (_suf,pre) = break (==c) (reverse s)
 
+-- split a string at the last occurence of 'c', returning the two
+-- parts of the string with the 'c' removed.  If the string contains
+-- no 'c's, the entire string is returned in the second component.
+split_longest_prefix :: String -> Char -> (String,String)
+split_longest_prefix s c
+  = case pre of
+       []      -> ([], reverse suf)
+       (_:pre) -> (reverse pre, reverse suf)
+  where (suf,pre) = break (==c) (reverse s)
+
 newsuf :: String -> String -> String
 newsuf suf s = remove_suffix '.' s ++ suf
 
@@ -165,9 +179,56 @@ newdir dir s = dir ++ '/':drop_longest_prefix s '/'
 remove_spaces :: String -> String
 remove_spaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace
 
-booter_version
- = case "\ 
-       \ __GLASGOW_HASKELL__" of
-    ' ':n:ns -> n:'.':ns
-    ' ':m    -> m
 
+ghcToolDir :: String
+prependToolDir :: String -> IO String
+#if defined(mingw32_TARGET_OS) && defined(MINIMAL_UNIX_DEPS)
+ghcToolDir = unsafePerformIO $ do
+               bs <- getEnv "GHC_TOOLDIR" `IO.catch` (\ _ -> return "")
+               case bs of
+                 "" -> return bs
+                 ls -> 
+                   let
+                    term = last ls
+                    bs' 
+                     | term `elem` ['/', '\\'] = bs
+                     | otherwise = bs ++ ['/']
+                   in
+                   return bs'
+
+prependToolDir x = return (dosifyPath (ghcToolDir ++ x))
+#else
+ghcToolDir = ""
+prependToolDir x = return x
+#endif
+
+appendInstallDir :: String -> IO String
+appendInstallDir cmd = 
+  case ghcToolDir of
+    "" -> return cmd
+    _  -> return (unwords [cmd, '-':'B':ghcToolDir])
+
+-- convert filepath into MSDOS form.
+dosifyPath :: String -> String
+#if defined(mingw32_TARGET_OS) && defined(MINIMAL_UNIX_DEPS)
+dosifyPath stuff = subst '/' '\\' real_stuff
+ where
+   -- fully convince myself that /cygdrive/ prefixes cannot
+   -- really appear here.
+  cygdrive_prefix = "/cygdrive/"
+
+  real_stuff
+    | "/cygdrive/" `isPrefixOf` stuff = drop (length cygdrive_prefix) stuff
+    | otherwise = stuff
+   
+  subst a b ls = map (\ x -> if x == a then b else x) ls
+#else
+dosifyPath x = x
+#endif
+
+#ifdef mingw32_TARGET_OS
+foreign import "_getpid" myGetProcessID :: IO Int 
+#else
+myGetProcessID :: IO Int
+myGetProcessID = Posix.getProcessID
+#endif