1- module Main where
1+ module Main ( main ) where
22
3- import Control.Monad
4- import Data.Char
5- import Data.List
6- import Data.Maybe
3+ import qualified Control.Monad as CM
4+ import qualified Data.Char as C
5+ import qualified Data.List as L
76import qualified Data.Map as M
7+ import qualified Data.Maybe as DM
88import qualified Data.Set as S
9- import System.Console.GetOpt
10- import System.Environment
11- import qualified Registry as R
9+ import qualified System.Console.GetOpt as G
10+ import qualified System.Environment as E
1211import MangledRegistry
1312
1413data Option
15- = PrintXML
16- | PrintRaw
17- | PrintProcessed
18- | PrintCommands
19- | PrintCommandTypes
20- | PrintFeatureCommands
14+ = PrintFeature
15+ | PrintTokens
16+ | PrintFunctions
2117 | UseApi API
2218 | UseVersion Version
2319 | UseProfile ProfileName
2420 deriving Eq
2521
26- options :: [OptDescr Option ]
22+ options :: [G. OptDescr Option ]
2723options =
28- [ Option [' x' ] [" print-xml" ] (NoArg PrintXML ) " print XML"
29- , Option [' r' ] [" print-raw" ] (NoArg PrintRaw ) " print raw registry"
30- , Option [' p' ] [" print-processed" ] (NoArg PrintProcessed ) " print processed registry"
31- , Option [' c' ] [" print-commands" ] (NoArg PrintCommands ) " print commands"
32- , Option [' t' ] [" print-command-types" ] (NoArg PrintCommandTypes ) " print command types"
33- , Option [' C' ] [" print-feature-commands" ] (NoArg PrintFeatureCommands ) " print feature commands"
34- , Option [' a' ] [" api" ] (ReqArg (UseApi . API ) " API" ) " extract features for API (default: gl)"
35- , Option [' v' ] [" version" ] (ReqArg (UseVersion . read ) " VERSION" ) " extract features for version (default: 1.0)"
36- , Option [' P' ] [" profile" ] (ReqArg (UseProfile . ProfileName ) " PROFILE" ) " extract features for profile (default: core)" ]
24+ [ G. Option [' F' ] [" print-feature" ] (G. NoArg PrintFeature ) " print feature"
25+ , G. Option [' t' ] [" print-tokens" ] (G. NoArg PrintTokens ) " print tokens"
26+ , G. Option [' f' ] [" print-functions" ] (G. NoArg PrintFunctions ) " print functions"
27+ , G. Option [' a' ] [" api" ] (G. ReqArg (UseApi . API ) " API" ) " extract features for API (default: gl)"
28+ , G. Option [' v' ] [" version" ] (G. ReqArg (UseVersion . read ) " VERSION" ) " extract features for version (default: 4.5)"
29+ , G. Option [' p' ] [" profile" ] (G. ReqArg (UseProfile . ProfileName ) " PROFILE" ) " extract features for profile (default: compatibility)" ]
3730
3831getPaths :: IO ([Option ], FilePath )
3932getPaths = do
40- args <- getArgs
41- case getOpt Permute options args of
33+ args <- E. getArgs
34+ case G. getOpt G. Permute options args of
4235 (opts, [path], [] ) -> return (opts, path)
4336 (_, _, errs) -> do
44- n <- getProgName
37+ n <- E. getProgName
4538 let header = " Usage: " ++ n ++ " [OPTION]... file"
46- ioError (userError (concat errs ++ usageInfo header options))
39+ ioError (userError (concat errs ++ G. usageInfo header options))
4740
4841main :: IO ()
4942main = do
5043 (opts, path) <- getPaths
5144 let api = head ([ a | UseApi a <- opts ] ++ [ API " gl" ])
52- version = head ([ v | UseVersion v <- opts ] ++ [ read " 1.0" ])
53- profile = head ([ p | UseProfile p <- opts ] ++ [ ProfileName " core" ])
54- str <- readFile path
55- when (PrintXML `elem` opts) $ do
56- putStrLn " ---------------------------------------- XML registry"
57- either putStrLn (putStrLn . R. unparseRegistry) $ R. parseRegistry str
58- when (PrintRaw `elem` opts) $ do
59- putStrLn " ---------------------------------------- raw registry"
60- either putStrLn print $ R. parseRegistry str
61- when (PrintProcessed `elem` opts) $ do
62- putStrLn " ---------------------------------------- processed registry"
63- either putStrLn print $ parseRegistry str
64- when (PrintCommands `elem` opts) $ do
65- putStrLn " ---------------------------------------- commands"
66- either putStrLn (mapM_ print . M. elems . commands) $ parseRegistry str
67- when (PrintCommandTypes `elem` opts) $ do
68- either putStrLn (\ r -> do putStr moduleHeader
69- mapM_ (putStrLn . showCommand) . M. elems . commands $ r) $ parseRegistry str
70- when (PrintFeatureCommands `elem` opts) $ do
71- putStrLn $ " ---------------------------------------- commands for feature " ++ unAPI api ++ " " ++ show version ++ " " ++ unProfileName profile
72- either putStrLn (\ r -> do let tec@ (_ts,es,cs) = getTyEnCo api version profile r
73- putStr " module Foo (\n "
74- putStr (intercalate " ,\n " (exports tec))
75- putStrLn " \n ) where"
76- putStrLn moduleHeader
77- mapM_ (putStrLn . unlines . convertEnum) es
78- mapM_ (putStrLn . showCommand) cs
79- ) $ parseRegistry str
80-
81- exports :: ([TypeName ],[Enum' ],[Command ]) -> [String ]
82- exports (ts,es,cs) =
83- [" -- * Types" ] ++
84- map unTypeName ts ++
85- [" -- * Enums" ] ++
86- map (unEnumName . mangleEnumName . enumName) es ++
87- [" -- * Commands" ] ++
88- map (unCommandName . commandName) cs
45+ version = head ([ v | UseVersion v <- opts ] ++ [ read " 4.5" ])
46+ profile = head ([ p | UseProfile p <- opts ] ++ [ ProfileName " compatibility" ])
47+ res <- fmap parseRegistry $ readFile path
48+ case res of
49+ Left msg -> putStrLn msg
50+ Right registry -> do
51+ CM. when (PrintFeature `elem` opts) $ do
52+ let modName = " Graphics.Rendering.OpenGL.Raw." ++
53+ capitalize (unProfileName profile) ++
54+ show (major version) ++ show (minor version)
55+ putStrLn " --------------------------------------------------------------------------------"
56+ putStrLn " -- |"
57+ putStrLn $ " -- Module : " ++ modName
58+ putStrLn " -- Copyright : (c) Sven Panne 2015"
59+ putStrLn " -- License : BSD3"
60+ putStrLn " --"
61+ putStrLn " -- Maintainer : Sven Panne <[email protected] >" 62+ putStrLn " -- Stability : stable"
63+ putStrLn " -- Portability : portable"
64+ putStrLn " --"
65+ putStrLn " --------------------------------------------------------------------------------"
66+ putStrLn " "
67+ let (ts,es,cs) = getTyEnCo api version profile registry
68+ putStrLn $ " module " ++ modName ++ " ("
69+ CM. unless (null ts) $ do
70+ putStrLn " -- * Types"
71+ putStr $ separate unTypeName ts
72+ putStrLn $ if null es && null cs then " " else " ,"
73+ CM. unless (null es) $ do
74+ putStrLn " -- * Enums"
75+ putStr $ separate (unEnumName . enumName) es
76+ putStrLn $ if null cs then " " else " ,"
77+ CM. unless (null cs) $ do
78+ putStrLn " -- * Functions"
79+ putStr $ separate (unCommandName . commandName) cs
80+ putStrLn " "
81+ putStrLn " ) where"
82+ putStrLn " "
83+ putStrLn " import Graphics.Rendering.OpenGL.Raw.Types"
84+ putStrLn " import Graphics.Rendering.OpenGL.Raw.Tokens"
85+ putStrLn " import Graphics.Rendering.OpenGL.Raw.Functions"
86+ CM. when (PrintTokens `elem` opts) $ do
87+ putStrLn " --------------------------------------------------------------------------------"
88+ putStrLn " -- |"
89+ putStrLn " -- Module : Graphics.Rendering.OpenGL.Raw.Tokens"
90+ putStrLn " -- Copyright : (c) Sven Panne 2015"
91+ putStrLn " -- License : BSD3"
92+ putStrLn " --"
93+ putStrLn " -- Maintainer : Sven Panne <[email protected] >" 94+ putStrLn " -- Stability : stable"
95+ putStrLn " -- Portability : portable"
96+ putStrLn " --"
97+ putStrLn " -- All enumeration tokens from the OpenGL registry, see"
98+ putStrLn " -- <http://www.opengl.org/registry/>."
99+ putStrLn " --"
100+ putStrLn " --------------------------------------------------------------------------------"
101+ putStrLn " "
102+ putStrLn " module Graphics.Rendering.OpenGL.Raw.Tokens where"
103+ putStrLn " "
104+ putStrLn " import Graphics.Rendering.OpenGL.Raw.Types"
105+ putStrLn " "
106+ mapM_ (putStrLn . unlines . convertEnum)
107+ [ e
108+ | es <- M. elems (enums registry)
109+ , e <- es
110+ , api `matches` enumAPI e ]
111+ CM. when (PrintFunctions `elem` opts) $ do
112+ putStrLn " {-# LANGUAGE CPP #-}"
113+ putStrLn " --------------------------------------------------------------------------------"
114+ putStrLn " -- |"
115+ putStrLn " -- Module : Graphics.Rendering.OpenGL.Raw.Functions"
116+ putStrLn " -- Copyright : (c) Sven Panne 2015"
117+ putStrLn " -- License : BSD3"
118+ putStrLn " --"
119+ putStrLn " -- Maintainer : Sven Panne <[email protected] >" 120+ putStrLn " -- Stability : stable"
121+ putStrLn " -- Portability : portable"
122+ putStrLn " --"
123+ putStrLn " -- All raw functions from the OpenGL registry, see"
124+ putStrLn " -- <http://www.opengl.org/registry/>."
125+ putStrLn " --"
126+ putStrLn " --------------------------------------------------------------------------------"
127+ putStrLn " "
128+ putStrLn " module Graphics.Rendering.OpenGL.Raw.Functions ("
129+ putStrLn . separate unCommandName . M. keys . commands $ registry
130+ putStrLn " ) where"
131+ putStrLn " "
132+ putStrLn " import Foreign.C.Types"
133+ putStrLn " import Foreign.Marshal.Error ( throwIf )"
134+ putStrLn " import Foreign.Ptr ( Ptr, FunPtr, nullFunPtr )"
135+ putStrLn " import System.IO.Unsafe ( unsafePerformIO )"
136+ putStrLn " "
137+ putStrLn " import Graphics.Rendering.OpenGL.Raw.GetProcAddress ( getProcAddress )"
138+ putStrLn " import Graphics.Rendering.OpenGL.Raw.Types"
139+ putStrLn " "
140+ putStrLn " getCommand :: String -> IO (FunPtr a)"
141+ putStrLn " getCommand cmd ="
142+ putStrLn " throwIfNullFunPtr (\" unknown OpenGL command \" ++ cmd) $ getProcAddress cmd"
143+ putStrLn " "
144+ putStrLn " throwIfNullFunPtr :: String -> IO (FunPtr a) -> IO (FunPtr a)"
145+ putStrLn " throwIfNullFunPtr = throwIf (== nullFunPtr) . const"
146+ putStrLn " "
147+ mapM_ (putStrLn . showCommand) (M. elems (commands registry))
148+
149+ capitalize :: String -> String
150+ capitalize str = C. toUpper (head str) : tail str
151+
152+ separate :: (a -> String ) -> [a ] -> String
153+ separate f = L. intercalate " ,\n " . map (" " ++ ) . map f
89154
90155getTyEnCo :: API -> Version -> ProfileName -> Registry -> ([TypeName ],[Enum' ],[Command ])
91156getTyEnCo api version profile registry = (ts', es, cs)
@@ -95,8 +160,8 @@ getTyEnCo api version profile registry = (ts', es, cs)
95160 , api `matches` enumAPI e ]
96161 cs = [ lookup' n (commands registry) | CommandElement n <- lst ]
97162 -- Features don't explicitly list the types referenced by commands.
98- ts' = S. toList ( S. unions ( S. fromList ts : map referencedTypes cs))
99- lst = S. toList ( interfaceElementsFor api version profile registry)
163+ ts' = S. toList . S. unions $ S. fromList ts : map referencedTypes cs
164+ lst = S. toList $ interfaceElementsFor api version profile registry
100165
101166-- Here is the heart of the feature construction logic: Chronologically replay
102167-- the whole version history for the given API/version/profile triple.
@@ -105,7 +170,7 @@ interfaceElementsFor api version profile registry =
105170 foldl (flip ($) ) S. empty modificationsFor
106171 where modificationsFor =
107172 [ op (modificationKind m) ie
108- | key <- sort keys
173+ | key <- L. sort keys
109174 , m <- lookup' key (features registry)
110175 , profile `matches` modificationProfile m
111176 , ie <- modificationInterfaceElements m ]
@@ -127,39 +192,7 @@ convertEnum :: Enum' -> [String]
127192convertEnum e =
128193 [ n ++ " :: " ++ unTypeName (enumType e)
129194 , n ++ " = " ++ unEnumValue (enumValue e) ]
130- where n = unEnumName . mangleEnumName . enumName $ e
131-
132- -- TODO: Move to MangledRegistry?
133- mangleEnumName :: EnumName -> EnumName
134- mangleEnumName =
135- EnumName . intercalate [splitChar] . headToLower . splitBy (== splitChar) . unEnumName
136- where splitChar = ' _'
137- headToLower xs = map toLower (head xs) : tail xs
138-
139- splitBy :: (a -> Bool ) -> [a ] -> [[a ]]
140- splitBy _ [] = []
141- splitBy p xs = case break p xs of
142- (ys, [] ) -> [ys]
143- (ys, _: zs) -> ys : splitBy p zs
144-
145- -- TODO: Everything below is currently a cruel hack, clean this up!
146-
147- moduleHeader :: String
148- moduleHeader = unlines [
149- " " ,
150- " import Foreign.C.Types" ,
151- " import Foreign.Ptr" ,
152- " import System.IO.Unsafe" ,
153- " " ,
154- " import Graphics.Rendering.OpenGL.Raw.GetProcAddress" ,
155- " import Graphics.Rendering.OpenGL.Raw.Types" ,
156- " " ,
157- " getExtensionEntry :: String -> String -> IO (FunPtr a)" ,
158- " getExtensionEntry _ = getProcAddress" ,
159- " " ,
160- " extensionNameString :: String" ,
161- " extensionNameString = \" OpenGL 4.5\" " ,
162- " " ]
195+ where n = unEnumName . enumName $ e
163196
164197showCommand :: Command -> String
165198showCommand c =
@@ -169,25 +202,23 @@ showCommand c =
169202 showString (" :: " ++ signature True ) .
170203 showString (name ++ " = " ++ dyn_name ++ " " ++ ptr_name ++ " \n\n " ) .
171204
172- showString (" foreign import" ++ callconv ++ " unsafe \" dynamic\" " ++ dyn_name ++ " \n " ++
205+ showString (" foreign import CALLCONV unsafe \" dynamic\" " ++ dyn_name ++ " \n " ++
173206 " :: FunPtr (" ++ compactSignature ++ " )\n " ++
174207 " -> " ++ compactSignature ++ " \n\n " ) .
175208
176209 showString (" {-# NOINLINE " ++ ptr_name ++ " #-}\n " ) .
177210 showString (ptr_name ++ " :: FunPtr (" ++ compactSignature ++ " )\n " ) .
178- showString (ptr_name ++ " = unsafePerformIO $\n " ++
179- " getExtensionEntry extensionNameString " ++ str_name ++ " \n " ) .
211+ showString (ptr_name ++ " = unsafePerformIO $ getCommand " ++ str_name ++ " \n " ) .
180212
181213 id $ " "
182214
183215 where name = signatureElementName (resultType c)
184216 dyn_name = " dyn_" ++ name
185217 ptr_name = " ptr_" ++ name
186218 str_name = show name
187- callconv = " ccall"
188219 compactSignature = signature False
189220 signature withComment =
190- intercalate ((if withComment then " " else " " ) ++ " -> " )
221+ L. intercalate ((if withComment then " " else " " ) ++ " -> " )
191222 ([showSignatureElement withComment False t | t <- paramTypes c] ++
192223 [showSignatureElement withComment True (resultType c)])
193224
@@ -211,7 +242,7 @@ showComment name sigElem
211242 info | isInteresting = elms ++ " of type " ++ inlineCode (show (base sigElem))
212243 | otherwise = " "
213244
214- isInteresting = isJust (arrayLength sigElem) || isJust (belongsToGroup sigElem)
245+ isInteresting = DM. isJust (arrayLength sigElem) || DM. isJust (belongsToGroup sigElem)
215246
216247 elms | numPointer sigElem > 0 = " pointing to" ++ len ++ " elements"
217248 | otherwise = " "
0 commit comments