@@ -22,6 +22,7 @@ main = do
2222 Left msg -> SI. hPutStrLn SI. stderr msg
2323 Right registry -> do
2424 printTokens api registry
25+ printGroups api registry
2526 let sigMap = signatureMap registry
2627 printForeign sigMap
2728 printFunctions api registry sigMap
@@ -86,11 +87,65 @@ printTokens api registry = do
8687 , e <- es
8788 , api `matches` enumAPI e ]
8889
90+ printGroups :: API -> Registry -> IO ()
91+ printGroups api registry = do
92+ let comment =
93+ [" All enumeration groups from the" ,
94+ " <http://www.opengl.org/registry/ OpenGL registry>." ]
95+ startModule [" Groups" ] Nothing comment $ \ moduleName h -> do
96+ SI. hPutStrLn h $ " module " ++ moduleName ++ " ("
97+ SI. hPutStrLn h $ " -- $EnumerantGroups"
98+ SI. hPutStrLn h $ " ) where"
99+ SI. hPutStrLn h " "
100+ SI. hPutStrLn h $ " -- $EnumerantGroups"
101+ SI. hPutStrLn h $ " -- Note that the actual set of valid values depend on the OpenGL version, the"
102+ SI. hPutStrLn h $ " -- chosen profile and the supported extensions. Therefore, the groups mentioned"
103+ SI. hPutStrLn h $ " -- here should only be considered a rough guideline, for details see the OpenGL"
104+ SI. hPutStrLn h $ " -- specification."
105+ CM. forM_ (M. assocs (groups registry)) $ \ (gn, g) -> do
106+ let ugn = unGroupName gn
107+ es = getGroupEnums api registry g
108+ SI. hPutStrLn h $ " --"
109+ SI. hPutStrLn h $ " -- === #" ++ ugn ++ " # " ++ ugn
110+ SI. hPutStrLn h $ " -- " ++ groupHeader es
111+ SI. hPutStrLn h $ " --"
112+ -- TODO: Improve the alias computation below. It takes quadratic time and
113+ -- is very naive about what is the canonical name and what is an alias.
114+ CM. forM_ es $ \ e -> do
115+ let same = L. sort [ f | f <- es, enumValue e == enumValue f ]
116+ CM. when (e == head same) $ do
117+ SI. hPutStrLn h $ " -- * " ++ linkToToken e ++
118+ (case tail same of
119+ [] -> " "
120+ aliases -> " (" ++ al ++ " : " ++ L. intercalate " , " (map linkToToken aliases) ++ " )"
121+ where al | length aliases == 1 = " alias"
122+ | otherwise = " aliases" )
123+
124+ linkToToken :: Enum' -> String
125+ linkToToken e = " '" ++ moduleNameFor [" Tokens" ] ++ " ." ++ (unEnumName . enumName) e ++ " '"
126+
127+ -- There are several enums which are mentioned in groups, but commented out in
128+ -- enums (12 GL_*_ICC_SGIX enumerants). These are implicitly filtered out below.
129+ getGroupEnums :: API -> Registry -> Group -> [Enum' ]
130+ getGroupEnums api registry g =
131+ [ e | name <- groupEnums g
132+ , Just es <- [ M. lookup name (enums registry) ]
133+ , e <- es
134+ , api `matches` enumAPI e ]
135+
136+ groupHeader :: [Enum' ] -> String
137+ groupHeader es = case sortUnique (map enumType es) of
138+ -- There are 2 empty groups: DataType and FfdMaskSGIX.
139+ [] -> " There are no values defined for this enumeration group."
140+ [t] | isMask t -> " A bitwise combination of several of the following values:"
141+ | otherwise -> " One of the following values:"
142+ types -> error $ " Contradicting enumerant types " ++ show types
143+
89144-- Calulate a map from compact signature to short names.
90145signatureMap :: Registry -> M. Map String String
91146signatureMap registry = fst $ M. foldl' step (M. empty, 0 ) (commands registry)
92147 where step (m,n) command = memberAndInsert (n+ 1 ) n (sig command) (dyn n) m
93- sig = flip showSignatureFromCommand False
148+ sig = flip ( showSignatureFromCommand registry) False
94149 dyn n = " dyn" ++ show n
95150 memberAndInsert notFound found key value map =
96151 (newMap, maybe notFound (const found) maybeValue)
@@ -124,7 +179,7 @@ printFunctions api registry sigMap = do
124179 SI. hPutStrLn h " import System.IO.Unsafe ( unsafePerformIO )"
125180 SI. hPutStrLn h " "
126181 SI. hPutStrLn h $ " import " ++ moduleNameFor [" Foreign" ]
127- SI. hPutStrLn h $ " import " ++ moduleNameFor [" GetProcAddress" ] ++ " ( getProcAddress )"
182+ SI. hPutStrLn h $ " import " ++ moduleNameFor [" GetProcAddress" ] ++ " ( getProcAddress )"
128183 SI. hPutStrLn h $ " import " ++ moduleNameFor [" Types" ]
129184 SI. hPutStrLn h " "
130185 SI. hPutStrLn h " getCommand :: String -> IO (FunPtr a)"
@@ -134,7 +189,7 @@ printFunctions api registry sigMap = do
134189 SI. hPutStrLn h " throwIfNullFunPtr :: String -> IO (FunPtr a) -> IO (FunPtr a)"
135190 SI. hPutStrLn h " throwIfNullFunPtr = throwIf (== nullFunPtr) . const"
136191 SI. hPutStrLn h " "
137- mapM_ (SI. hPutStrLn h . showCommand api sigMap) (M. elems (commands registry))
192+ mapM_ (SI. hPutStrLn h . showCommand api registry sigMap) (M. elems (commands registry))
138193
139194printExtensionModule :: (ExtensionName , ExtensionName , ([TypeName ], [Enum' ], [Command ])) -> IO ()
140195printExtensionModule (extName, mangledExtName, extensionParts) =
@@ -441,8 +496,8 @@ convertEnum e =
441496 , n ++ " = " ++ unEnumValue (enumValue e) ]
442497 where n = unEnumName . enumName $ e
443498
444- showCommand :: API -> M. Map String String -> Command -> String
445- showCommand api sigMap c =
499+ showCommand :: API -> Registry -> M. Map String String -> Command -> String
500+ showCommand api registry sigMap c =
446501 showString (take 80 (" -- " ++ name ++ " " ++ repeat ' -' ) ++ " \n\n " ) .
447502
448503 showString man .
@@ -463,7 +518,7 @@ showCommand api sigMap c =
463518 ptr_name = " ptr_" ++ name
464519 str_name = show name
465520 compactSignature = signature False
466- signature withComment = showSignatureFromCommand c withComment
521+ signature withComment = showSignatureFromCommand registry c withComment
467522 urls = M. findWithDefault [] (api, CommandName name) manPageURLs
468523 links = L. intercalate " or " (map renderURL urls) ++ " \n "
469524 man = case urls of
@@ -479,34 +534,42 @@ makeImportDynamic compactSignature dyn_name =
479534 " :: FunPtr (" ++ compactSignature ++ " )\n " ++
480535 " -> " ++ compactSignature ++ " \n "
481536
482- showSignatureFromCommand :: Command -> Bool -> String
483- showSignatureFromCommand c withComment =
537+ showSignatureFromCommand :: Registry -> Command -> Bool -> String
538+ showSignatureFromCommand registry c withComment =
484539 L. intercalate ((if withComment then " " else " " ) ++ " -> " )
485- ([showSignatureElement withComment False t | t <- paramTypes c] ++
486- [showSignatureElement withComment True (resultType c)])
540+ ([showSignatureElement registry withComment False t | t <- paramTypes c] ++
541+ [showSignatureElement registry withComment True (resultType c)])
487542
488- showSignatureElement :: Bool -> Bool -> SignatureElement -> String
489- showSignatureElement withComment isResult sigElem = el ++ comment
543+ showSignatureElement :: Registry -> Bool -> Bool -> SignatureElement -> String
544+ showSignatureElement registry withComment isResult sigElem = el ++ comment
490545 where el | isResult = monad ++ " " ++ showsPrec 11 sigElem " "
491546 | otherwise = show sigElem
492547 monad | withComment = " m"
493548 | otherwise = " IO"
494- comment | withComment = showComment name sigElem
549+ comment | withComment = showComment registry name sigElem
495550 | otherwise = " "
496551 name | isResult = " "
497552 | otherwise = signatureElementName sigElem
498553
499- showComment :: String -> SignatureElement -> String
500- showComment name sigElem
554+ showComment :: Registry -> String -> SignatureElement -> String
555+ showComment registry name sigElem
501556 | null name' && null info = " \n "
502557 | otherwise = " -- ^" ++ name' ++ info ++ " .\n "
503558
504559 where name' | null name = " "
505560 | otherwise = " " ++ inlineCode name
506561
507- info | isInteresting = elms ++ " of type " ++ inlineCode ( show (base sigElem))
562+ info | isInteresting = elms ++ " of type " ++ hurz
508563 | otherwise = " "
509564
565+ -- Alas, there are tons of group names which are referenced, but never
566+ -- defined, so we have to leave them without a link.
567+ -- TODO: Do not use Show instance for SignatureElement.
568+ hurz = case belongsToGroup sigElem of
569+ Just gn | numPointer sigElem <= 1 &&
570+ gn `M.member` groups registry -> linkToGroup gn
571+ _ -> inlineCode (show (base sigElem))
572+
510573 isInteresting = DM. isJust (arrayLength sigElem) || DM. isJust (belongsToGroup sigElem)
511574
512575 elms | numPointer sigElem > 0 = " pointing to" ++ len ++ " " ++ elements
@@ -522,6 +585,15 @@ showComment name sigElem
522585 | otherwise = e
523586 maybeSetBaseType e = maybe e (\ g -> e{baseType = TypeName (unGroupName g)}) (belongsToGroup e)
524587
588+ -- TODO: This is very fragile, but currently there is no clean way to specify
589+ -- link texts when referencing anchors in Haddock.
590+ linkToGroup :: GroupName -> String
591+ linkToGroup g = " [" ++ n ++ " ](" ++ htmlFilenameFor [" Groups" ] ++ " #" ++ n ++ " )"
592+ where n = unGroupName g
593+
594+ htmlFilenameFor :: [String ] -> String
595+ htmlFilenameFor = (++ " .html" ) . L. intercalate " -" . moduleNameParts
596+
525597inlineCode :: String -> String
526598inlineCode s = " @" ++ s ++ " @"
527599
@@ -556,3 +628,6 @@ toEnumType eNamespace eGroup eType suffix = TypeName $
556628 (Just " GL" , _, Nothing , Nothing ) -> " GLenum"
557629
558630 (_, _, _, _) -> error " can't determine enum type"
631+
632+ isMask :: TypeName -> Bool
633+ isMask = (== TypeName " GLbitfield" )
0 commit comments