X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FEnvironment.hs;h=245a9db41900c5a1b488189e7cdd1a2860118323;hb=deab48c5498f00001e37273a02471bbdd7696e6b;hp=d85a52dd2d1ae61a87c387b336d8ca625bebef1c;hpb=1e1907fb42b74de4feb5ac8af10846db31e56edb;p=ghc-base.git diff --git a/System/Environment.hs b/System/Environment.hs index d85a52d..245a9db 100644 --- a/System/Environment.hs +++ b/System/Environment.hs @@ -1,42 +1,58 @@ ----------------------------------------------------------------------------- --- +-- | -- Module : System.Environment -- Copyright : (c) The University of Glasgow 2001 --- License : BSD-style (see the file libraries/core/LICENSE) +-- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : provisional -- Portability : portable -- --- $Id: Environment.hs,v 1.4 2002/01/02 14:40:11 simonmar Exp $ --- -- Miscellaneous information about the system environment. -- ----------------------------------------------------------------------------- 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 ) where import Prelude +#ifdef __GLASGOW_HASKELL__ import Foreign import Foreign.C +import Control.Exception ( bracket ) import Control.Monad - -#ifdef __GLASGOW_HASKELL__ import GHC.IOBase +#include "config.h" +#endif + +#ifdef __HUGS__ +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). +#ifdef __GLASGOW_HASKELL__ getArgs :: IO [String] getArgs = alloca $ \ p_argc -> @@ -47,12 +63,19 @@ getArgs = peekArray (p - 1) (advancePtr argv 1) >>= mapM peekCString -foreign import "getProgArgv" unsafe +foreign import ccall unsafe "getProgArgv" getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO () --- Computation `getProgName' returns the name of the program --- as it was invoked. +{-| +Computation 'getProgName' returns the name of the program as it was +invoked. +However, this is hard-to-impossible to implement on some non-Unix +OSes, so instead, for maximum portability, we just return the leafname +of the program as invoked. Even then there are some differences +between platforms: on Windows, for example, a program invoked as foo +is probably really @FOO.EXE@, and that is what 'getProgName' will return. +-} getProgName :: IO String getProgName = alloca $ \ p_argc -> @@ -82,11 +105,13 @@ unpackProgName argv = do 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 = @@ -97,5 +122,50 @@ getEnv name = else ioException (IOError Nothing NoSuchThing "getEnv" "no environment variable" (Just name)) -foreign import ccall "getenv" unsafe +foreign import ccall unsafe "getenv" c_getenv :: CString -> IO (Ptr CChar) + +{-| +'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 (length argv) vs + return vs + +foreign import ccall unsafe "setProgArgv" + setArgsPrim :: Int -> Ptr CString -> IO () +#endif /* __GLASGOW_HASKELL__ */