X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FEnvironment.hs;h=ce972a03b3155d6729f93f99e7a41544e62c2dfa;hb=1a293bde8704156dcc7edd01a67b6b38bf38f5f9;hp=4e9efb6e2a6f0aae285c74614512015928f4cc78;hpb=9812e0a321ec0ed8f9e53eb2febfb14c79564200;p=ghc-base.git diff --git a/System/Environment.hs b/System/Environment.hs index 4e9efb6..ce972a0 100644 --- a/System/Environment.hs +++ b/System/Environment.hs @@ -14,20 +14,26 @@ module System.Environment ( - getArgs -- :: IO [String] - , getProgName -- :: IO String - , getEnv -- :: String -> IO String + getArgs, -- :: IO [String] + getProgName, -- :: IO String + getEnv, -- :: String -> IO String +#ifndef __NHC__ + withArgs, + withProgName, +#endif +#ifdef __GLASGOW_HASKELL__ + getEnvironment, +#endif ) where import Prelude -#ifndef __HUGS__ +#ifdef __GLASGOW_HASKELL__ +import Data.List import Foreign import Foreign.C +import Control.Exception ( bracket ) import Control.Monad -#endif - -#ifdef __GLASGOW_HASKELL__ import GHC.IOBase #endif @@ -35,13 +41,21 @@ import GHC.IOBase import Hugs.System #endif +#ifdef __NHC__ +import System + ( getArgs + , getProgName + , getEnv + ) +#endif + -- --------------------------------------------------------------------------- -- getArgs, getProgName, getEnv --- Computation `getArgs' returns a list of the program's command +-- | Computation 'getArgs' returns a list of the program's command -- line arguments (not including the program name). -#ifndef __HUGS__ +#ifdef __GLASGOW_HASKELL__ getArgs :: IO [String] getArgs = alloca $ \ p_argc -> @@ -88,17 +102,19 @@ unpackProgName argv = do isPathSeparator :: Char -> Bool isPathSeparator '/' = True -#ifdef mingw32_TARGET_OS +#ifdef mingw32_HOST_OS isPathSeparator '\\' = True #endif isPathSeparator _ = False --- Computation `getEnv var' returns the value --- of the environment variable {\em var}. - --- This computation may fail with --- NoSuchThing: The environment variable does not exist. +-- | Computation 'getEnv' @var@ returns the value +-- of the environment variable @var@. +-- +-- This computation may fail with: +-- +-- * 'System.IO.Error.isDoesNotExistError' if the environment variable +-- does not exist. getEnv :: String -> IO String getEnv name = @@ -111,4 +127,70 @@ getEnv name = foreign import ccall unsafe "getenv" c_getenv :: CString -> IO (Ptr CChar) -#endif /* __HUGS__ */ + +{-| +'withArgs' @args act@ - while executing action @act@, have 'getArgs' +return @args@. +-} +withArgs :: [String] -> IO a -> IO a +withArgs xs act = do + p <- System.Environment.getProgName + withArgv (p:xs) act + +{-| +'withProgName' @name act@ - while executing action @act@, +have 'getProgName' return @name@. +-} +withProgName :: String -> IO a -> IO a +withProgName nm act = do + xs <- System.Environment.getArgs + withArgv (nm:xs) act + +-- Worker routine which marshals and replaces an argv vector for +-- the duration of an action. + +withArgv :: [String] -> IO a -> IO a +withArgv new_args act = do + pName <- System.Environment.getProgName + existing_args <- System.Environment.getArgs + bracket (setArgs new_args) + (\argv -> do setArgs (pName:existing_args); freeArgv argv) + (const act) + +freeArgv :: Ptr CString -> IO () +freeArgv argv = do + size <- lengthArray0 nullPtr argv + sequence_ [peek (argv `advancePtr` i) >>= free | i <- [size, size-1 .. 0]] + free argv + +setArgs :: [String] -> IO (Ptr CString) +setArgs argv = do + vs <- mapM newCString argv >>= newArray0 nullPtr + setArgsPrim (genericLength argv) vs + return vs + +foreign import ccall unsafe "setProgArgv" + setArgsPrim :: CInt -> Ptr CString -> IO () + +-- |'getEnvironment' retrieves the entire environment as a +-- list of @(key,value)@ pairs. +-- +-- If an environment entry does not contain an @\'=\'@ character, +-- the @key@ is the whole entry and the @value@ is the empty string. + +getEnvironment :: IO [(String, String)] +getEnvironment = do + pBlock <- getEnvBlock + if pBlock == nullPtr then return [] + else do + stuff <- peekArray0 nullPtr pBlock >>= mapM peekCString + return (map divvy stuff) + where + divvy str = + case break (=='=') str of + (xs,[]) -> (xs,[]) -- don't barf (like Posix.getEnvironment) + (name,_:value) -> (name,value) + +foreign import ccall unsafe "__hscore_environ" + getEnvBlock :: IO (Ptr CString) +#endif /* __GLASGOW_HASKELL__ */