X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=utils%2Frunghc%2Frunghc.hs;h=aadafd9a7125ef28785770e74294187b4badc429;hp=e2cea312317001411e1efe272ccb19b93cf1bb84;hb=34cc75e1a62638f2833815746ebce0a9114dc26b;hpb=1a3efdd6b616f3a101e182f715df5a0e306eb348 diff --git a/utils/runghc/runghc.hs b/utils/runghc/runghc.hs index e2cea31..aadafd9 100644 --- a/utils/runghc/runghc.hs +++ b/utils/runghc/runghc.hs @@ -1,4 +1,4 @@ -{-# OPTIONS -cpp -fffi #-} +{-# LANGUAGE CPP, ForeignFunctionInterface #-} #if __GLASGOW_HASKELL__ < 603 #include "config.h" #else @@ -11,7 +11,7 @@ -- runghc program, for invoking from a #! line in a script. For example: -- -- script.lhs: --- #! /usr/bin/runghc +-- #!/usr/bin/env /usr/bin/runghc -- > main = putStrLn "hello!" -- -- runghc accepts one flag: @@ -22,54 +22,109 @@ module Main (main) where -import System.Environment -import System.IO +import Control.Exception +import Data.Char import Data.List +import Data.Monoid +import Data.Version +import System.Cmd +import System.Directory +import System.Environment import System.Exit -import Data.Char -import System.Directory ( removeFile ) -import Control.Exception ( bracket ) -import System.Directory ( findExecutable, getTemporaryDirectory ) -import System.Cmd ( rawSystem ) +import System.FilePath +import System.IO + +#if defined(mingw32_HOST_OS) +import Control.Monad +import Foreign +import Foreign.C.String +#endif main :: IO () main = do args <- getArgs - case getGhcLoc args of - (Just ghc, args') -> doIt ghc args' - (Nothing, args') -> do - mb_ghc <- findExecutable "ghc" - case mb_ghc of + case parseRunGhcFlags args of + (Help, _) -> printUsage + (ShowVersion, _) -> printVersion + (RunGhcFlags (Just ghc), args') -> doIt ghc args' + (RunGhcFlags Nothing, args') -> do + mbPath <- getExecPath + case mbPath of Nothing -> dieProg ("cannot find ghc") - Just ghc -> doIt ghc args' + Just path -> + let ghc = takeDirectory (normalise path) "ghc" + in doIt ghc args' -getGhcLoc :: [String] -> (Maybe FilePath, [String]) -getGhcLoc ("-f" : ghc : args) = (Just ghc, args) -getGhcLoc (('-' : 'f' : ghc) : args) = (Just ghc, args) --- If you need the first GHC flag to be a -f flag then you can pass -- --- first -getGhcLoc ("--" : args) = (Nothing, args) -getGhcLoc args = (Nothing, args) +data RunGhcFlags = RunGhcFlags (Maybe FilePath) -- GHC location + | Help -- Print help text + | ShowVersion -- Print version info + +instance Monoid RunGhcFlags where + mempty = RunGhcFlags Nothing + Help `mappend` _ = Help + _ `mappend` Help = Help + ShowVersion `mappend` _ = ShowVersion + _ `mappend` ShowVersion = ShowVersion + RunGhcFlags _ `mappend` right@(RunGhcFlags (Just _)) = right + left@(RunGhcFlags _) `mappend` RunGhcFlags Nothing = left + +parseRunGhcFlags :: [String] -> (RunGhcFlags, [String]) +parseRunGhcFlags = f mempty + where f flags ("-f" : ghc : args) + = f (flags `mappend` RunGhcFlags (Just ghc)) args + f flags (('-' : 'f' : ghc) : args) + = f (flags `mappend` RunGhcFlags (Just ghc)) args + f flags ("--help" : args) = f (flags `mappend` Help) args + f flags ("--version" : args) = f (flags `mappend` ShowVersion) args + -- If you need the first GHC flag to be a -f flag then + -- you can pass -- first + f flags ("--" : args) = (flags, args) + f flags args = (flags, args) + +printVersion :: IO () +printVersion = do + putStrLn ("runghc " ++ VERSION) + +printUsage :: IO () +printUsage = do + putStrLn "Usage: runghc [runghc flags] [GHC flags] module [program args]" + putStrLn "" + putStrLn "The runghc flags are" + putStrLn " -f /path/to/ghc Tell runghc where GHC is" + putStrLn " --help Print this usage information" + putStrLn " --version Print version number" doIt :: String -> [String] -> IO () doIt ghc args = do let (ghc_args, rest) = getGhcArgs args case rest of [] -> do - -- behave like typical perl, python, ruby interpreters: + -- behave like typical perl, python, ruby interpreters: -- read from stdin tmpdir <- getTemporaryDirectory bracket (openTempFile tmpdir "runghcXXXX.hs") - (\(filename,_) -> removeFile filename) + (\(filename,h) -> do hClose h; removeFile filename) $ \(filename,h) -> do getContents >>= hPutStr h hClose h doIt ghc (ghc_args ++ [filename]) filename : prog_args -> do - let c1 = ":set prog " ++ show filename + -- If the file exists, and is not a .lhs file, then we + -- want to treat it as a .hs file. + -- + -- If the file doesn't exist then GHC is going to look for + -- filename.hs and filename.lhs, and use the appropriate + -- type. + exists <- doesFileExist filename + let xflag = if exists && (takeExtension filename /= ".lhs") + then ["-x", "hs"] + else [] + c1 = ":set prog " ++ show filename c2 = ":main " ++ show prog_args - res <- rawSystem ghc (["-ignore-dot-ghci"] ++ ghc_args ++ + res <- rawSystem ghc (["-ignore-dot-ghci"] ++ + xflag ++ + ghc_args ++ [ "-e", c1, "-e", c2, filename]) exitWith res @@ -99,3 +154,18 @@ dieProg msg = do -- usage :: String -- usage = "syntax: runghc [-f GHC-PATH | --] [GHC-ARGS] [--] FILE ARG..." +getExecPath :: IO (Maybe String) +#if defined(mingw32_HOST_OS) +getExecPath = + allocaArray len $ \buf -> do + ret <- getModuleFileName nullPtr buf len + if ret == 0 then return Nothing + else liftM Just $ peekCString buf + where len = 2048 -- Plenty, PATH_MAX is 512 under Win32. + +foreign import stdcall unsafe "GetModuleFileNameA" + getModuleFileName :: Ptr () -> CString -> Int -> IO Int32 +#else +getExecPath = return Nothing +#endif +