clang-pure-0.2.0.3: examples/ListStructs.hs
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
import Language.C.Clang
import Language.C.Clang.Cursor.Typed
import Control.Lens
import qualified Data.ByteString.Char8 as BS
import Data.Maybe
import Data.Word
import System.Environment
data CType =
CArrayType { cType :: Type
, cCanonicalType :: Type
, cElementType :: CType
, cArraySize :: Word64, cSize :: Word64} |
CScalarType { cType :: Type
, cCanonicalType :: Type
, cSize :: Word64
} deriving (Show)
data CField = CField
{ cFieldName :: BS.ByteString
, cFieldOffset :: Word64
, cFieldType :: CType
} deriving (Show)
data CStruct = CStruct
{ cStructName :: BS.ByteString
, cStructFields :: [ CField ]
} deriving (Show)
main :: IO ()
main = do
args <- getArgs
case args of
path : clangArgs -> do
idx <- createIndex
tu <- parseTranslationUnit idx path clangArgs
let toCType tp = let canonicalType = typeCanonicalType tp
in case typeKind canonicalType of
ConstantArray -> do
elementType <- toCType . fromJust . typeElementType $ canonicalType
size <- typeSizeOf tp
pure $ CArrayType
{ cType = tp
, cCanonicalType = canonicalType
, cElementType = elementType
, cArraySize = fromJust (typeArraySize canonicalType)
, cSize = size
}
_ -> do
size <- typeSizeOf tp
pure $ CScalarType
{ cType = tp
, cCanonicalType = canonicalType
, cSize = size
}
let toCField fieldDecC = do
fieldOffset <- offsetOfField fieldDecC
fieldType <- toCType (cursorType fieldDecC)
return $ CField
{ cFieldName = cursorSpelling fieldDecC
, cFieldOffset = fieldOffset
, cFieldType = fieldType
}
let toCStruct structDecC = do
let fieldDecs =
structDecC
^.. cursorDescendantsF
. folding (matchKind @'FieldDecl)
cFields <- traverse toCField fieldDecs
return CStruct
{ cStructName = cursorSpelling structDecC
, cStructFields = cFields
}
let cStructs =
translationUnitCursor tu
^.. cursorDescendantsF
. folding (matchKind @'StructDecl)
. to toCStruct
. _Right
print cStructs
_ -> putStrLn "usage: list-structs path [clang opts]"