module Text.XkbCommon.ParseDefines
( readHeader, getKeysymDefs, genKeysyms, genKeycodes, genModnames ) where
import Language.Haskell.TH
import Language.Preprocessor.Cpphs
import System.Process
import Data.List
import Data.Maybe (isJust)
import Data.Text (pack, unpack, toLower)
import Control.Arrow
readHeader :: String -> IO (String, String)
readHeader str = do
cpp_out <- readProcess "cpp" [] ("#include<" ++ str ++ ">")
let headerfile = read $ head $ map ((!! 2) . words) (filter (isInfixOf str) $ lines cpp_out)
header <- readFile headerfile
return (headerfile, header)
getKeysymDefs :: IO [(String,Integer)]
getKeysymDefs = do
(headerFilename, keysyms_header) <- readHeader "xkbcommon/xkbcommon-keysyms.h"
(_, defs) <- macroPassReturningSymTab [] defaultBoolOptions [(newfile headerFilename, keysyms_header)]
let exclude_defs = ["XKB_KEY_VoidSymbol", "XKB_KEY_NoSymbol"]
let filtered_defs = filter (\ (name, _) -> isPrefixOf "XKB_KEY" name && notElem name exclude_defs) defs
let parsed_defs = map (drop 8 *** read) filtered_defs
return parsed_defs
genKeysyms :: IO [Dec]
genKeysyms = do
parsed_defs <- getKeysymDefs
return $ map (\ (name, val) -> ValD (VarP $ mkName ("keysym_" ++ name)) (NormalB (AppE (VarE $ mkName "toKeysym") (AppE (ConE $ mkName "CKeysym") $ LitE (IntegerL val)))) []) parsed_defs
genKeycodes :: IO [Dec]
genKeycodes = do
(headerFilename, keysyms_header) <- readHeader "linux/input.h"
preprocessed <- cppIfdef headerFilename [] [] defaultBoolOptions keysyms_header
(_, defs) <- macroPassReturningSymTab [] defaultBoolOptions preprocessed
let exclude_defs = []
let filtered_defs = filter (\ (name, val) -> isPrefixOf "KEY_" name && notElem name exclude_defs && isJust (maybeRead val :: Maybe Int)) defs
let parsed_defs = map (drop 4 *** read) filtered_defs
return $ map (\ (name, val) -> ValD (VarP $ mkName ("keycode_" ++ lowerCase name)) (NormalB (AppE (ConE $ mkName "CKeycode") $ LitE (IntegerL (8 + val)))) []) parsed_defs
genModnames :: IO [Dec]
genModnames = do
(headerFilename, keysyms_header) <- readHeader "xkbcommon/xkbcommon-names.h"
(_, defs) <- macroPassReturningSymTab [] defaultBoolOptions [(newfile headerFilename, keysyms_header)]
let exclude_defs = []
let mod_defs = filter (\ (name, val) -> isPrefixOf "XKB_MOD_" name && notElem name exclude_defs && isJust (maybeRead val :: Maybe String)) defs
let led_defs = filter (\ (name, val) -> isPrefixOf "XKB_LED_" name && notElem name exclude_defs && isJust (maybeRead val :: Maybe String)) defs
let parsed_mods = map ((\ name -> "modname_" ++ lowerCase (drop 13 name)) *** read) mod_defs
let parsed_leds = map ((\ name -> "ledname_" ++ lowerCase (drop 13 name)) *** read) led_defs
return $ map (\ (name, val) -> ValD (VarP $ mkName name) (NormalB (LitE (StringL val))) []) (parsed_mods ++ parsed_leds)
maybeRead :: Read a => String -> Maybe a
maybeRead s = case reads s of
[(x, "")] -> Just x
_ -> Nothing
lowerCase :: String -> String
lowerCase = unpack . toLower . pack