[project @ 2003-06-12 16:25:31 by simonmar]
[ghc-hetmet.git] / ghc / compiler / main / SysTools.lhs
index 20a8099..505610c 100644 (file)
 module SysTools (
        -- Initialisation
        initSysTools,
-       setPgm,                 -- String -> IO ()
+
+       setPgmL,                -- String -> IO ()
+       setPgmP,
+       setPgmF,
+       setPgmc,
+       setPgmm,
+       setPgms,
+       setPgma,
+       setPgml,
+#ifdef ILX
+       setPgmI,
+       setPgmi,
+#endif
                                -- Command-line override
        setDryRun,
 
@@ -19,6 +31,7 @@ module SysTools (
 
        -- Interface to system tools
        runUnlit, runCpp, runCc, -- [Option] -> IO ()
+       runPp,                   -- [Option] -> IO ()
        runMangle, runSplit,     -- [Option] -> IO ()
        runAs, runLink,          -- [Option] -> IO ()
        runMkDLL,
@@ -29,7 +42,7 @@ module SysTools (
 
        touch,                  -- String -> String -> IO ()
        copy,                   -- String -> String -> String -> IO ()
-       unDosifyPath,           -- String -> String
+       normalisePath,          -- FilePath -> FilePath
        
        -- Temporary-file management
        setTmpDir,
@@ -49,49 +62,54 @@ module SysTools (
 
  ) where
 
+#include "HsVersions.h"
+
 import DriverUtil
 import Config
 import Outputable
 import Panic           ( progName, GhcException(..) )
-import Util            ( global )
+import Util            ( global, notNull )
 import CmdLineOpts     ( dynFlag, verbosity )
 
-import Exception       ( throwDyn, catchAllIO )
-import IO
-import Directory       ( doesFileExist, removeFile )
-import IOExts          ( IORef, readIORef, writeIORef )
+import EXCEPTION       ( throwDyn )
+import DATA_IOREF      ( IORef, readIORef, writeIORef )
+import DATA_INT
+    
 import Monad           ( when, unless )
 import System          ( ExitCode(..), exitWith, getEnv, system )
-import CString
-import Int
-import Addr
-    
+import IO              ( try, catch,
+                         openFile, hPutChar, hPutStrLn, hPutStr, hClose, hFlush, IOMode(..),
+                         stderr )
+import Directory       ( doesFileExist, removeFile )
+import List             ( intersperse )
+
 #include "../includes/config.h"
 
-#ifndef mingw32_TARGET_OS
-import qualified Posix
+-- GHC <= 4.08 didn't have rawSystem, and runs into problems with long command
+-- lines on mingw32, so we disallow it now.
+#if __GLASGOW_HASKELL__ < 500
+#error GHC >= 5.00 is required for bootstrapping GHC
+#endif
+
+#ifndef mingw32_HOST_OS
+#if __GLASGOW_HASKELL__ > 504
+import qualified System.Posix.Internals
 #else
+import qualified Posix
+#endif
+#else /* Must be Win32 */
 import List            ( isPrefixOf )
-import MarshalArray
+import Util            ( dropList )
+import Foreign
+import CString         ( CString, peekCString )
 #endif
 
--- This is a kludge for bootstrapping with 4.08.X.  Given that
--- all distributed compilers >= 5.0 will be compiled with themselves.
--- I don't think this kludge is a problem.  And we have to start
--- building with >= 5.0 on Win32 anyway.
-#if __GLASGOW_HASKELL__ > 408
--- use the line below when we can be sure of compiling with GHC >=
--- 5.02, and remove the implementation of rawSystem at the end of this
--- file
-import PrelIOBase -- this can be removed when SystemExts is used
-import CError     ( throwErrnoIfMinus1 ) -- as can this
--- import SystemExts       ( rawSystem )
+#if __GLASGOW_HASKELL__ < 601
+import Foreign         ( withMany, withArray0, nullPtr, Ptr )
+import CForeign                ( CString, withCString, throwErrnoIfMinus1 )
 #else
-import System          ( system )
+import System.Cmd      ( rawSystem )
 #endif
-
-#include "HsVersions.h"
-
 \end{code}
 
 
@@ -127,9 +145,9 @@ Config.hs contains two sorts of things
   etc          They do *not* include paths
                                
 
-  cUNLIT_DIR   The *path* to the directory containing unlit, split etc
-  cSPLIT_DIR   *relative* to the root of the build tree,
-               for use when running *in-place* in a build tree (only)
+  cUNLIT_DIR_REL   The *path* to the directory containing unlit, split etc
+  cSPLIT_DIR_REL   *relative* to the root of the build tree,
+                  for use when running *in-place* in a build tree (only)
                
 
 
@@ -168,7 +186,8 @@ All these pathnames are maintained IN THE NATIVE FORMAT OF THE HOST MACHINE.
 
 \begin{code}
 GLOBAL_VAR(v_Pgm_L,    error "pgm_L",   String)        -- unlit
-GLOBAL_VAR(v_Pgm_P,    error "pgm_P",   String)        -- cpp
+GLOBAL_VAR(v_Pgm_P,    error "pgm_P",   (String,[Option]))     -- cpp
+GLOBAL_VAR(v_Pgm_F,    error "pgm_F",   String)        -- pp
 GLOBAL_VAR(v_Pgm_c,    error "pgm_c",   String)        -- gcc
 GLOBAL_VAR(v_Pgm_m,    error "pgm_m",   String)        -- asm code mangler
 GLOBAL_VAR(v_Pgm_s,    error "pgm_s",   String)        -- asm code splitter
@@ -221,34 +240,35 @@ initSysTools minusB_args
                -- NB: top_dir is assumed to be in standard Unix format '/' separated
 
        ; let installed, installed_bin :: FilePath -> FilePath
-              installed_bin pgm   =  pgmPath (top_dir `slash` "extra-bin") pgm
+              installed_bin pgm   =  pgmPath top_dir pgm
              installed     file  =  pgmPath top_dir file
-             inplace dir   pgm   =  pgmPath (top_dir `slash` dir) pgm
+             inplace dir   pgm   =  pgmPath (top_dir `slash` 
+                                               cPROJECT_DIR `slash` dir) pgm
 
        ; let pkgconfig_path
                | am_installed = installed "package.conf"
-               | otherwise    = inplace cGHC_DRIVER_DIR "package.conf.inplace"
+               | otherwise    = inplace cGHC_DRIVER_DIR_REL "package.conf.inplace"
 
              ghc_usage_msg_path
                | am_installed = installed "ghc-usage.txt"
-               | otherwise    = inplace cGHC_DRIVER_DIR "ghc-usage.txt"
+               | otherwise    = inplace cGHC_DRIVER_DIR_REL "ghc-usage.txt"
 
                -- For all systems, unlit, split, mangle are GHC utilities
                -- architecture-specific stuff is done when building Config.hs
              unlit_path
-               | am_installed = installed_bin cGHC_UNLIT
-               | otherwise    = inplace cGHC_UNLIT_DIR cGHC_UNLIT
+               | am_installed = installed_bin cGHC_UNLIT_PGM
+               | otherwise    = inplace cGHC_UNLIT_DIR_REL cGHC_UNLIT_PGM
 
                -- split and mangle are Perl scripts
              split_script
-               | am_installed = installed_bin cGHC_SPLIT
-               | otherwise    = inplace cGHC_SPLIT_DIR cGHC_SPLIT
+               | am_installed = installed_bin cGHC_SPLIT_PGM
+               | otherwise    = inplace cGHC_SPLIT_DIR_REL cGHC_SPLIT_PGM
 
              mangle_script
-               | am_installed = installed_bin cGHC_MANGLER
-               | otherwise    = inplace cGHC_MANGLER_DIR cGHC_MANGLER
+               | am_installed = installed_bin cGHC_MANGLER_PGM
+               | otherwise    = inplace cGHC_MANGLER_DIR_REL cGHC_MANGLER_PGM
 
-#ifndef mingw32_TARGET_OS
+#ifndef mingw32_HOST_OS
        -- check whether TMPDIR is set in the environment
        ; IO.try (do dir <- getEnv "TMPDIR" -- fails if not set
                     setTmpDir dir
@@ -266,18 +286,19 @@ initSysTools minusB_args
                tdir <-
                  if ret == 0 then do
                      -- failed, consult TEMP.
-                    destructArray len buf
+                    free buf
                     getEnv "TMP"
                   else do
                     s <- peekCString buf
-                    destructArray len buf
+                    free buf
                     return s
                let
-                 -- strip the trailing slash (awful, but 
+                 -- strip the trailing backslash (awful, but 
                  -- we only do this once).
                  tmpdir =
                    case last tdir of
-                     '/' -> init tdir
+                     '/'  -> init tdir
+                     '\\' -> init tdir
                      _   -> tdir
                setTmpDir tmpdir
                return ())
@@ -289,7 +310,7 @@ initSysTools minusB_args
             throwDyn (InstallationError 
                         ("Can't find package.conf as " ++ pkgconfig_path))
 
-#if defined(mingw32_TARGET_OS)
+#if defined(mingw32_HOST_OS)
        --              WINDOWS-SPECIFIC STUFF
        -- On Windows, gcc and friends are distributed with GHC,
        --      so when "installed" we look in TopDir/bin
@@ -318,22 +339,26 @@ initSysTools minusB_args
                        | otherwise    = cGHC_PERL
 
        -- 'touch' is a GHC util for Windows, and similarly unlit, mangle
-       ; let touch_path  | am_installed = installed_bin cGHC_TOUCHY
-                         | otherwise    = inplace cGHC_TOUCHY_DIR cGHC_TOUCHY
+       ; let touch_path  | am_installed = installed_bin cGHC_TOUCHY_PGM
+                         | otherwise    = inplace cGHC_TOUCHY_DIR_REL cGHC_TOUCHY_PGM
 
        -- On Win32 we don't want to rely on #!/bin/perl, so we prepend 
        -- a call to Perl to get the invocation of split and mangle
        ; let split_path  = perl_path ++ " \"" ++ split_script ++ "\""
              mangle_path = perl_path ++ " \"" ++ mangle_script ++ "\""
 
-       ; let mkdll_path = cMKDLL
+       ; let mkdll_path 
+               | am_installed = pgmPath (installed "gcc-lib/") cMKDLL ++
+                                " --dlltool-name " ++ pgmPath (installed "gcc-lib/") "dlltool" ++
+                                " --driver-name " ++ gcc_path
+               | otherwise    = cMKDLL
 #else
        --              UNIX-SPECIFIC STUFF
        -- On Unix, the "standard" tools are assumed to be
        -- in the same place whether we are running "in-place" or "installed"
        -- That place is wherever the build-time configure script found them.
        ; let   gcc_path   = cGCC
-               touch_path = cGHC_TOUCHY
+               touch_path = "touch"
                mkdll_path = panic "Can't build DLLs on a non-Win32 system"
 
        -- On Unix, scripts are invoked using the '#!' method.  Binary
@@ -345,7 +370,9 @@ initSysTools minusB_args
 #endif
 
        -- cpp is derived from gcc on all platforms
-        ; let cpp_path  = gcc_path ++ " -E " ++ cRAWCPP_FLAGS
+        -- HACK, see setPgmP below. We keep 'words' here to remember to fix
+        -- Config.hs one day.
+        ; let cpp_path  = (gcc_path, (Option "-E"):(map Option (words cRAWCPP_FLAGS)))
 
        -- For all systems, copy and remove are provided by the host
        -- system; architecture-specific stuff is done when building Config.hs
@@ -371,6 +398,7 @@ initSysTools minusB_args
 
        ; writeIORef v_Pgm_L               unlit_path
        ; writeIORef v_Pgm_P               cpp_path
+       ; writeIORef v_Pgm_F               ""
        ; writeIORef v_Pgm_c               gcc_path
        ; writeIORef v_Pgm_m               mangle_path
        ; writeIORef v_Pgm_s               split_path
@@ -387,31 +415,33 @@ initSysTools minusB_args
        ; return ()
        }
 
-#if defined(mingw32_TARGET_OS)
-foreign import stdcall "GetTempPathA" getTempPath :: Int -> CString -> IO Int32
+#if defined(mingw32_HOST_OS)
+foreign import stdcall "GetTempPathA" unsafe getTempPath :: Int -> CString -> IO Int32
 #endif
 \end{code}
 
-setPgm is called when a command-line option like
+The various setPgm functions are called when a command-line option
+like
+
        -pgmLld
+
 is used to override a particular program with a new one
 
 \begin{code}
-setPgm :: String -> IO ()
--- The string is the flag, minus the '-pgm' prefix
--- So the first character says which program to override
-
-setPgm ('P' : pgm) = writeIORef v_Pgm_P pgm
-setPgm ('c' : pgm) = writeIORef v_Pgm_c pgm
-setPgm ('m' : pgm) = writeIORef v_Pgm_m pgm
-setPgm ('s' : pgm) = writeIORef v_Pgm_s pgm
-setPgm ('a' : pgm) = writeIORef v_Pgm_a pgm
-setPgm ('l' : pgm) = writeIORef v_Pgm_l pgm
+setPgmL = writeIORef v_Pgm_L
+-- XXX HACK: Prelude> words "'does not' work" ===> ["'does","not'","work"]
+-- Config.hs should really use Option.
+setPgmP arg = let (pgm:args) = words arg in writeIORef v_Pgm_P (pgm,map Option args)
+setPgmF = writeIORef v_Pgm_F
+setPgmc = writeIORef v_Pgm_c
+setPgmm = writeIORef v_Pgm_m
+setPgms = writeIORef v_Pgm_s
+setPgma = writeIORef v_Pgm_a
+setPgml = writeIORef v_Pgm_l
 #ifdef ILX
-setPgm ('I' : pgm) = writeIORef v_Pgm_I pgm
-setPgm ('i' : pgm) = writeIORef v_Pgm_i pgm
+setPgmI = writeIORef v_Pgm_I
+setPgmi = writeIORef v_Pgm_i
 #endif
-setPgm pgm        = unknownFlagErr ("-pgm" ++ pgm)
 \end{code}
 
 
@@ -448,11 +478,11 @@ findTopDir minusbs
        ; return (am_installed, top_dir)
        }
   where
-    -- get_proto returns a Unix-format path (relying on getExecDir to do so too)
-    get_proto | not (null minusbs)
-             = return (unDosifyPath (drop 2 (last minusbs)))   -- 2 for "-B"
+    -- get_proto returns a Unix-format path (relying on getBaseDir to do so too)
+    get_proto | notNull minusbs
+             = return (normalisePath (drop 2 (last minusbs)))  -- 2 for "-B"
              | otherwise          
-             = do { maybe_exec_dir <- getExecDir -- Get directory of executable
+             = do { maybe_exec_dir <- getBaseDir -- Get directory of executable
                   ; case maybe_exec_dir of       -- (only works on Windows; 
                                                  --  returns Nothing on Unix)
                        Nothing  -> throwDyn (InstallationError "missing -B<dir> option")
@@ -481,18 +511,9 @@ data Option
              String  -- the filepath/filename portion
  | Option     String
  
-showOptions :: [Option] -> String
-showOptions ls = unwords (map (quote.showOpt) ls)
- where
-   showOpt (FileOption pre f) = pre ++ dosifyPath f
-   showOpt (Option s)     = s
-
-#if defined(mingw32_TARGET_OS)
-   quote "" = ""
-   quote s  = "\"" ++ s ++ "\""
-#else
-   quote = id
-#endif
+showOpt (FileOption pre f) = pre ++ platformPath f
+showOpt (Option "") = ""
+showOpt (Option s)  = s
 
 \end{code}
 
@@ -500,7 +521,7 @@ showOptions ls = unwords (map (quote.showOpt) ls)
 %************************************************************************
 %*                                                                     *
 \subsection{Running an external program}
-n%*                                                                    *
+%*                                                                     *
 %************************************************************************
 
 
@@ -510,8 +531,12 @@ runUnlit args = do p <- readIORef v_Pgm_L
                   runSomething "Literate pre-processor" p args
 
 runCpp :: [Option] -> IO ()
-runCpp args =   do p <- readIORef v_Pgm_P
-                  runSomething "C pre-processor" p args
+runCpp args =   do (p,baseArgs) <- readIORef v_Pgm_P
+                  runSomething "C pre-processor" p (baseArgs ++ args)
+
+runPp :: [Option] -> IO ()
+runPp args =   do p <- readIORef v_Pgm_F
+                 runSomething "Haskell pre-processor" p args
 
 runCc :: [Option] -> IO ()
 runCc args =   do p <- readIORef v_Pgm_c
@@ -640,7 +665,7 @@ removeTmpFiles verb fs
             ("Deleting: " ++ unwords fs)
             (mapM_ rm fs)
   where
-    rm f = removeFile f `catchAllIO` 
+    rm f = removeFile f `IO.catch` 
                (\_ignored -> 
                    when (verb >= 2) $
                      hPutStrLn stderr ("Warning: deleting non-existent " ++ f)
@@ -671,27 +696,13 @@ runSomething :: String            -- For -v message
                                --      runSomething will dos-ify them
             -> IO ()
 
-runSomething phase_name pgm args
- = traceCmd phase_name cmd_line $
-   do   {
-#ifndef mingw32_TARGET_OS
-         exit_code <- system cmd_line
-#else
-          exit_code <- rawSystem cmd_line
-#endif
-       ; if exit_code /= ExitSuccess
-         then throwDyn (PhaseFailed phase_name exit_code)
-         else return ()
-       }
-  where
-    cmd_line = pgm ++ ' ':showOptions args -- unwords (pgm : dosifyPaths (map quote args))
-       -- The pgm is already in native format (appropriate dir separators)
-#if defined(mingw32_TARGET_OS)
-    quote "" = ""
-    quote s  = "\"" ++ s ++ "\""
-#else
-    quote = id
-#endif
+runSomething phase_name pgm args = do
+  let real_args = filter notNull (map showOpt args)
+  traceCmd phase_name (concat (intersperse " " (pgm:real_args))) $ do
+  exit_code <- rawSystem pgm real_args
+  if (exit_code /= ExitSuccess)
+       then throwDyn (PhaseFailed phase_name exit_code)
+       else return ()
 
 traceCmd :: String -> String -> IO () -> IO ()
 -- a) trace the command (at two levels of verbosity)
@@ -707,12 +718,60 @@ traceCmd phase_name cmd_line action
        ; unless n $ do {
 
           -- And run it!
-       ; action `catchAllIO` handle_exn verb
+       ; action `IO.catch` handle_exn verb
        }}
   where
     handle_exn verb exn = do { when (verb >= 2) (hPutStr   stderr "\n")
-                            ; when (verb >= 3) (hPutStrLn stderr ("Failed: " ++ cmd_line))
+                            ; when (verb >= 3) (hPutStrLn stderr ("Failed: " ++ cmd_line ++ (show exn)))
                             ; throwDyn (PhaseFailed phase_name (ExitFailure 1)) }
+
+-- -----------------------------------------------------------------------------
+-- rawSystem: run an external command
+
+#if __GLASGOW_HASKELL__ < 601
+
+-- This code is copied from System.Cmd on GHC 6.1.
+
+rawSystem :: FilePath -> [String] -> IO ExitCode
+
+#ifndef mingw32_TARGET_OS
+
+rawSystem cmd args =
+  withCString cmd $ \pcmd ->
+    withMany withCString (cmd:args) $ \cstrs ->
+      withArray0 nullPtr cstrs $ \arr -> do
+       status <- throwErrnoIfMinus1 "rawSystem" (c_rawSystem pcmd arr)
+        case status of
+            0  -> return ExitSuccess
+            n  -> return (ExitFailure n)
+
+foreign import ccall unsafe "rawSystem"
+  c_rawSystem :: CString -> Ptr CString -> IO Int
+
+#else
+
+-- On Windows, the command line is passed to the operating system as
+-- a single string.  Command-line parsing is done by the executable
+-- itself.
+rawSystem cmd args = do
+  let cmdline = {-translate-} cmd ++ concat (map ((' ':) . translate) args)
+  withCString cmdline $ \pcmdline -> do
+    status <- throwErrnoIfMinus1 "rawSystem" (c_rawSystem pcmdline)
+    case status of
+       0  -> return ExitSuccess
+       n  -> return (ExitFailure n)
+
+translate :: String -> String
+translate str = '"' : foldr escape "\"" str
+  where escape '"'  str = '\\' : '"'  : str
+       escape '\\' str = '\\' : '\\' : str
+       escape c    str = c : str
+
+foreign import ccall unsafe "rawSystem"
+  c_rawSystem :: CString -> IO Int
+
+#endif
+#endif
 \end{code}
 
 
@@ -727,20 +786,19 @@ the last moment.  On Windows we dos-ify them just before passing them
 to the Windows command.
 
 The alternative, of using '/' consistently on Unix and '\' on Windows,
-proved quite awkward.  There were a lot more calls to dosifyPath,
+proved quite awkward.  There were a lot more calls to platformPath,
 and even on Windows we might invoke a unix-like utility (eg 'sh'), which
 interpreted a command line 'foo\baz' as 'foobaz'.
 
 \begin{code}
 -----------------------------------------------------------------------------
--- Convert filepath into MSDOS form.
+-- Convert filepath into platform / MSDOS form.
 
-dosifyPaths :: [String] -> [String]
--- dosifyPaths does two things
+-- platformPath does two things
 -- a) change '/' to '\'
 -- b) remove initial '/cygdrive/'
 
-unDosifyPath :: String -> String
+normalisePath :: String -> String
 -- Just change '\' to '/'
 
 pgmPath :: String              -- Directory string in Unix format
@@ -750,37 +808,21 @@ pgmPath :: String         -- Directory string in Unix format
 
 
 
-#if defined(mingw32_TARGET_OS)
-
+#if defined(mingw32_HOST_OS)
 --------------------- Windows version ------------------
-dosifyPaths xs = map dosifyPath xs
-
-unDosifyPath xs = subst '\\' '/' xs
-
-pgmPath dir pgm = dosifyPath dir ++ '\\' : pgm
-
-dosifyPath stuff
-  = subst '/' '\\' real_stuff
- where
-   -- fully convince myself that /cygdrive/ prefixes cannot
-   -- really appear here.
-  cygdrive_prefix = "/cygdrive/"
+normalisePath xs = subst '\\' '/' xs
+platformPath p   = subst '/' '\\' p
+pgmPath dir pgm  = platformPath dir ++ '\\' : pgm
 
-  real_stuff
-    | cygdrive_prefix `isPrefixOf` stuff = drop (length cygdrive_prefix) stuff
-    | otherwise = stuff
-   
+subst a b ls = map (\ x -> if x == a then b else x) ls
 #else
-
---------------------- Unix version ---------------------
-dosifyPaths  ps  = ps
-unDosifyPath xs  = xs
-pgmPath dir pgm  = dir ++ '/' : pgm
-dosifyPath stuff = stuff
+--------------------- Non-Windows version --------------
+normalisePath xs   = xs
+pgmPath dir pgm    = dir ++ '/' : pgm
+platformPath stuff = stuff
 --------------------------------------------------------
 #endif
 
-subst a b ls = map (\ x -> if x == a then b else x) ls
 \end{code}
 
 
@@ -808,45 +850,36 @@ slash s1 s2 = s1 ++ ('/' : s2)
 
 \begin{code}
 -----------------------------------------------------------------------------
--- Define      getExecDir     :: IO (Maybe String)
+-- Define      getBaseDir     :: IO (Maybe String)
 
-#if defined(mingw32_TARGET_OS)
-getExecDir :: IO (Maybe String)
-getExecDir = do let len = (2048::Int) -- plenty, PATH_MAX is 512 under Win32.
+#if defined(mingw32_HOST_OS)
+getBaseDir :: IO (Maybe String)
+-- Assuming we are running ghc, accessed by path  $()/bin/ghc.exe,
+-- return the path $(stuff).  Note that we drop the "bin/" directory too.
+getBaseDir = do let len = (2048::Int) -- plenty, PATH_MAX is 512 under Win32.
                buf <- mallocArray len
-               ret <- getModuleFileName nullAddr buf len
-               if ret == 0 then destructArray len buf >> return Nothing
+               ret <- getModuleFileName nullPtr buf len
+               if ret == 0 then free buf >> return Nothing
                            else do s <- peekCString buf
-                                   destructArray len buf
-                                   return (Just (reverse (drop (length "/bin/ghc.exe") (reverse (unDosifyPath s)))))
-
+                                   free buf
+                                   return (Just (rootDir s))
+  where
+    rootDir s = reverse (dropList "/bin/ghc.exe" (reverse (normalisePath s)))
 
-foreign import stdcall "GetModuleFileNameA" getModuleFileName :: Addr -> CString -> Int -> IO Int32
+foreign import stdcall "GetModuleFileNameA" unsafe
+  getModuleFileName :: Ptr () -> CString -> Int -> IO Int32
 #else
-getExecDir :: IO (Maybe String) = do return Nothing
+getBaseDir :: IO (Maybe String) = do return Nothing
 #endif
 
-#ifdef mingw32_TARGET_OS
-foreign import "_getpid" getProcessID :: IO Int -- relies on Int == Int32 on Windows
+#ifdef mingw32_HOST_OS
+foreign import ccall "_getpid" unsafe getProcessID :: IO Int -- relies on Int == Int32 on Windows
+#elif __GLASGOW_HASKELL__ > 504
+getProcessID :: IO Int
+getProcessID = System.Posix.Internals.c_getpid >>= return . fromIntegral
 #else
 getProcessID :: IO Int
 getProcessID = Posix.getProcessID
 #endif
 
-rawSystem :: String -> IO ExitCode
-#if __GLASGOW_HASKELL__ > 408
-rawSystem "" = ioException (IOError Nothing InvalidArgument "rawSystem" "null command" Nothing)
-rawSystem cmd =
-  withCString cmd $ \s -> do
-    status <- throwErrnoIfMinus1 "rawSystem" (primRawSystem s)
-    case status of
-        0  -> return ExitSuccess
-        n  -> return (ExitFailure n)
-
-foreign import ccall "rawSystemCmd" unsafe primRawSystem :: CString -> IO Int
-#else
-rawSystem = System.system
-#endif
-
-
 \end{code}