{-# LINE 1 "libraries\base\System\Environment\ExecutablePath.hsc" #-}
{-# LANGUAGE Safe #-}
{-# LINE 2 "libraries\base\System\Environment\ExecutablePath.hsc" #-}
{-# LANGUAGE CPP #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  System.Environment.ExecutablePath
-- Copyright   :  (c) The University of Glasgow 2001
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  libraries@haskell.org
-- Stability   :  provisional
-- Portability :  portable
--
-- Function to retrieve the absolute filepath of the current executable.
--
-- @since 4.6.0.0
-----------------------------------------------------------------------------

module System.Environment.ExecutablePath ( getExecutablePath ) where

-- The imports are purposely kept completely disjoint to prevent edits
-- to one OS implementation from breaking another.


{-# LINE 36 "libraries\base\System\Environment\ExecutablePath.hsc" #-}
import Data.Word
import Foreign.C
import Foreign.Marshal.Array
import Foreign.Ptr
import System.Posix.Internals

{-# LINE 48 "libraries\base\System\Environment\ExecutablePath.hsc" #-}

-- The exported function is defined outside any if-guard to make sure
-- every OS implements it with the same type.

-- | Returns the absolute pathname of the current executable.
--
-- Note that for scripts and interactive sessions, this is the path to
-- the interpreter (e.g. ghci.)
--
-- @since 4.6.0.0
getExecutablePath :: IO FilePath

--------------------------------------------------------------------------------
-- Mac OS X


{-# LINE 131 "libraries\base\System\Environment\ExecutablePath.hsc" #-}


{-# LINE 133 "libraries\base\System\Environment\ExecutablePath.hsc" #-}
#  define WINDOWS_CCONV stdcall

{-# LINE 139 "libraries\base\System\Environment\ExecutablePath.hsc" #-}

foreign import WINDOWS_CCONV unsafe "windows.h GetModuleFileNameW"
    c_GetModuleFileName :: Ptr () -> CWString -> Word32 -> IO Word32

getExecutablePath = go 2048  -- plenty, PATH_MAX is 512 under Win32
  where
    go size = allocaArray (fromIntegral size) $ \ buf -> do
        ret <- c_GetModuleFileName nullPtr buf size
        case ret of
            0 -> error "getExecutablePath: GetModuleFileNameW returned an error"
            _ | ret < size -> peekFilePath buf
              | otherwise  -> go (size * 2)

--------------------------------------------------------------------------------
-- Fallback to argv[0]


{-# LINE 176 "libraries\base\System\Environment\ExecutablePath.hsc" #-}