File: MacOSX.hs

package info (click to toggle)
haskell-executable-path 0.0.3.1-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 88 kB
  • sloc: haskell: 421; makefile: 2
file content (152 lines) | stat: -rw-r--r-- 4,354 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}

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
 
--import System.FilePath
  
--------------------------------------------------------------------------------

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

-- | Manually releasing a CFString.
releaseCFString :: CFStringRef -> IO ()
releaseCFString = c_CFRelease

-- | Peeks a CFString.
peekCFString :: CFStringRef -> IO String
peekCFString cfstring = do
  n <- c_CFStringGetLength cfstring
  p <- c_CFStringGetCharactersPtr cfstring
  if p /= nullPtr 
    then forM [0..n-1] $ \i -> peekElemOff p (fromIntegral i)
    else forM [0..n-1] $ \i -> c_CFStringGetCharacterAtIndex cfstring i
 
-- | Creates a new CFString. You have to release it manually.
newCFString :: String -> IO CFStringRef
newCFString string = 
  let n = length string in allocaArray n $ \p ->
  c_CFStringCreateWithCharacters kCFAllocatorDefault p (fromIntegral n)
 
-- | Safe passing of a CFString to the OS (releases it afterwards).
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

-- | Mac OS X only.
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
--  let (path,exename) = splitFileName fname
--  return path
  return fname


--------------------------------------------------------------------------------