@@ -22,6 +22,7 @@ main = do
22
22
Left msg -> SI. hPutStrLn SI. stderr msg
23
23
Right registry -> do
24
24
printTokens api registry
25
+ printGroups api registry
25
26
let sigMap = signatureMap registry
26
27
printForeign sigMap
27
28
printFunctions api registry sigMap
@@ -86,11 +87,65 @@ printTokens api registry = do
86
87
, e <- es
87
88
, api `matches` enumAPI e ]
88
89
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
+
89
144
-- Calulate a map from compact signature to short names.
90
145
signatureMap :: Registry -> M. Map String String
91
146
signatureMap registry = fst $ M. foldl' step (M. empty, 0 ) (commands registry)
92
147
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
94
149
dyn n = " dyn" ++ show n
95
150
memberAndInsert notFound found key value map =
96
151
(newMap, maybe notFound (const found) maybeValue)
@@ -124,7 +179,7 @@ printFunctions api registry sigMap = do
124
179
SI. hPutStrLn h " import System.IO.Unsafe ( unsafePerformIO )"
125
180
SI. hPutStrLn h " "
126
181
SI. hPutStrLn h $ " import " ++ moduleNameFor [" Foreign" ]
127
- SI. hPutStrLn h $ " import " ++ moduleNameFor [" GetProcAddress" ] ++ " ( getProcAddress )"
182
+ SI. hPutStrLn h $ " import " ++ moduleNameFor [" GetProcAddress" ] ++ " ( getProcAddress )"
128
183
SI. hPutStrLn h $ " import " ++ moduleNameFor [" Types" ]
129
184
SI. hPutStrLn h " "
130
185
SI. hPutStrLn h " getCommand :: String -> IO (FunPtr a)"
@@ -134,7 +189,7 @@ printFunctions api registry sigMap = do
134
189
SI. hPutStrLn h " throwIfNullFunPtr :: String -> IO (FunPtr a) -> IO (FunPtr a)"
135
190
SI. hPutStrLn h " throwIfNullFunPtr = throwIf (== nullFunPtr) . const"
136
191
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))
138
193
139
194
printExtensionModule :: (ExtensionName , ExtensionName , ([TypeName ], [Enum' ], [Command ])) -> IO ()
140
195
printExtensionModule (extName, mangledExtName, extensionParts) =
@@ -441,8 +496,8 @@ convertEnum e =
441
496
, n ++ " = " ++ unEnumValue (enumValue e) ]
442
497
where n = unEnumName . enumName $ e
443
498
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 =
446
501
showString (take 80 (" -- " ++ name ++ " " ++ repeat ' -' ) ++ " \n\n " ) .
447
502
448
503
showString man .
@@ -463,7 +518,7 @@ showCommand api sigMap c =
463
518
ptr_name = " ptr_" ++ name
464
519
str_name = show name
465
520
compactSignature = signature False
466
- signature withComment = showSignatureFromCommand c withComment
521
+ signature withComment = showSignatureFromCommand registry c withComment
467
522
urls = M. findWithDefault [] (api, CommandName name) manPageURLs
468
523
links = L. intercalate " or " (map renderURL urls) ++ " \n "
469
524
man = case urls of
@@ -479,34 +534,42 @@ makeImportDynamic compactSignature dyn_name =
479
534
" :: FunPtr (" ++ compactSignature ++ " )\n " ++
480
535
" -> " ++ compactSignature ++ " \n "
481
536
482
- showSignatureFromCommand :: Command -> Bool -> String
483
- showSignatureFromCommand c withComment =
537
+ showSignatureFromCommand :: Registry -> Command -> Bool -> String
538
+ showSignatureFromCommand registry c withComment =
484
539
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)])
487
542
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
490
545
where el | isResult = monad ++ " " ++ showsPrec 11 sigElem " "
491
546
| otherwise = show sigElem
492
547
monad | withComment = " m"
493
548
| otherwise = " IO"
494
- comment | withComment = showComment name sigElem
549
+ comment | withComment = showComment registry name sigElem
495
550
| otherwise = " "
496
551
name | isResult = " "
497
552
| otherwise = signatureElementName sigElem
498
553
499
- showComment :: String -> SignatureElement -> String
500
- showComment name sigElem
554
+ showComment :: Registry -> String -> SignatureElement -> String
555
+ showComment registry name sigElem
501
556
| null name' && null info = " \n "
502
557
| otherwise = " -- ^" ++ name' ++ info ++ " .\n "
503
558
504
559
where name' | null name = " "
505
560
| otherwise = " " ++ inlineCode name
506
561
507
- info | isInteresting = elms ++ " of type " ++ inlineCode ( show (base sigElem))
562
+ info | isInteresting = elms ++ " of type " ++ hurz
508
563
| otherwise = " "
509
564
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
+
510
573
isInteresting = DM. isJust (arrayLength sigElem) || DM. isJust (belongsToGroup sigElem)
511
574
512
575
elms | numPointer sigElem > 0 = " pointing to" ++ len ++ " " ++ elements
@@ -522,6 +585,15 @@ showComment name sigElem
522
585
| otherwise = e
523
586
maybeSetBaseType e = maybe e (\ g -> e{baseType = TypeName (unGroupName g)}) (belongsToGroup e)
524
587
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
+
525
597
inlineCode :: String -> String
526
598
inlineCode s = " @" ++ s ++ " @"
527
599
@@ -556,3 +628,6 @@ toEnumType eNamespace eGroup eType suffix = TypeName $
556
628
(Just " GL" , _, Nothing , Nothing ) -> " GLenum"
557
629
558
630
(_, _, _, _) -> error " can't determine enum type"
631
+
632
+ isMask :: TypeName -> Bool
633
+ isMask = (== TypeName " GLbitfield" )
0 commit comments