module System.Environment.Executable.MacOSX
( getExecutablePath
, getApplicationBundlePath
)
where
import Data.Bits
import Data.Word
import Data.Int
import Control.Monad
import Foreign
import Foreign.C
type UInt8 = Word8
type UInt16 = Word16
type UInt32 = Word32
type UInt64 = Word64
type SInt8 = Int8
type SInt16 = Int16
type SInt32 = Int32
type SInt64 = Int64
type OSErr = SInt16
type OSStatus = SInt32
type Boolean = Bool
type Float32 = Float
type Float64 = Double
type UniChar = Char
type CFIndex = SInt32
type ItemCount = UInt32
type ByteCount = UInt32
data CFData
data CFString
data CFAllocator
type CFDataRef = Ptr CFData
type CFStringRef = Ptr CFString
type CFAllocatorRef = Ptr CFAllocator
kCFAllocatorDefault :: CFAllocatorRef
kCFAllocatorDefault = nullPtr
osStatusString :: OSStatus -> String
osStatusString osstatus = "OSStatus = " ++ show osstatus
osStatusError :: OSStatus -> IO a
osStatusError osstatus = fail $ osStatusString osstatus
foreign import ccall unsafe "CFBase.h CFRelease"
c_CFRelease :: Ptr a -> IO ()
foreign import ccall unsafe "CFString.h CFStringGetLength"
c_CFStringGetLength :: CFStringRef -> IO CFIndex
foreign import ccall unsafe "CFString.h CFStringGetCharactersPtr"
c_CFStringGetCharactersPtr :: CFStringRef -> IO (Ptr UniChar)
foreign import ccall unsafe "CFString.h CFStringGetCharacterAtIndex"
c_CFStringGetCharacterAtIndex :: CFStringRef -> CFIndex -> IO UniChar
foreign import ccall unsafe "CFString.h CFStringCreateWithCharacters"
c_CFStringCreateWithCharacters :: CFAllocatorRef -> Ptr UniChar -> CFIndex -> IO CFStringRef
releaseCFString :: CFStringRef -> IO ()
releaseCFString = c_CFRelease
peekCFString :: CFStringRef -> IO String
peekCFString cfstring = do
n <- c_CFStringGetLength cfstring
p <- c_CFStringGetCharactersPtr cfstring
if p /= nullPtr
then forM [0..n1] $ \i -> peekElemOff p (fromIntegral i)
else forM [0..n1] $ \i -> c_CFStringGetCharacterAtIndex cfstring i
newCFString :: String -> IO CFStringRef
newCFString string =
let n = length string in allocaArray n $ \p ->
c_CFStringCreateWithCharacters kCFAllocatorDefault p (fromIntegral n)
withCFString :: String -> (CFStringRef -> IO a) -> IO a
withCFString string action = do
cfstring <- newCFString string
x <- action cfstring
releaseCFString cfstring
return x
data CFBundle
type CFBundleRef = Ptr CFBundle
data CFURL
type CFURLRef = Ptr CFURL
type OSXEnum = CInt
type CFURLPathStyle = OSXEnum
foreign import ccall unsafe "CFBundle.h CFBundleGetMainBundle"
c_CFBundleGetMainBundle :: IO CFBundleRef
foreign import ccall unsafe "CFBundle.h CFBundleCopyBundleURL"
c_CFBundleCopyBundleURL :: CFBundleRef -> IO CFURLRef
foreign import ccall unsafe "CFBundle.h CFBundleCopyExecutableURL"
c_CFBundleCopyExecutableURL :: CFBundleRef -> IO CFURLRef
foreign import ccall unsafe "CFURL.h CFURLCopyFileSystemPath"
c_CFURLCopyFileSystemPath :: CFURLRef -> CFURLPathStyle -> IO CFStringRef
kCFURLPOSIXPathStyle = 0 :: CFURLPathStyle
kCFURLHFSPathStyle = 1 :: CFURLPathStyle
kCFURLWindowsPathStyle = 2 :: CFURLPathStyle
getApplicationBundlePath :: IO FilePath
getApplicationBundlePath = do
bundle <- c_CFBundleGetMainBundle
url <- c_CFBundleCopyBundleURL bundle
cfpath <- c_CFURLCopyFileSystemPath url kCFURLPOSIXPathStyle
peekCFString cfpath
getExecutablePath :: IO FilePath
getExecutablePath = do
bundle <- c_CFBundleGetMainBundle
url <- c_CFBundleCopyExecutableURL bundle
cfpath <- c_CFURLCopyFileSystemPath url kCFURLPOSIXPathStyle
fname <- peekCFString cfpath
return fname