module Tokstyle.C (main) where
import Control.Applicative ((<$>))
import qualified Data.List as List
import Language.C (CError, CTranslUnit,
ErrorInfo (..), InputStream,
errorInfo, initPos, parseC,
posFile, posRow)
import Language.C.Analysis.AstAnalysis (analyseAST)
import Language.C.Analysis.SemRep (GlobalDecls)
import Language.C.Analysis.TravMonad (runTrav_)
import Language.C.System.GCC (newGCC)
import Language.C.System.Preprocess (rawCppArgs, runPreprocessor)
import System.Environment (getArgs)
import qualified Tokstyle.C.Naming
import Tokstyle.Result
phaseCpp :: FilePath -> IO InputStream
phaseCpp file = do
cppArgs <- (["-std=c99", "-U__BLOCKS__", "-D_VA_LIST", "-D_Nonnull=", "-D_Nullable=", "-D__attribute__(x)="] ++) <$> getArgs
result <- runPreprocessor (newGCC "gcc") $ rawCppArgs cppArgs file
case result of
Left err -> fail $ show err
Right ok -> return ok
phaseParse :: FilePath -> InputStream -> Result CTranslUnit
phaseParse file preprocessed =
case parseC preprocessed (initPos file) of
Left err -> fail $ show err
Right tu -> return tu
phaseAnalyse :: CTranslUnit -> Result (CTranslUnit, GlobalDecls, [CError])
phaseAnalyse tu =
case runTrav_ (analyseAST tu) of
Left errs -> fail $ concatMap show errs
Right (decls, cerr) -> return (tu, decls, cerr)
phaseCheck :: (CTranslUnit, GlobalDecls, [CError]) -> [CError]
phaseCheck (tu, decls, _cerr) =
Tokstyle.C.Naming.check tu decls
printError :: ErrorInfo -> IO ()
printError (ErrorInfo _ pos msgs) =
putStrLn $ file ++ ":" ++ show line ++ ": " ++ List.intercalate "\n\t" msgs
where
file = posFile pos
line = posRow pos
showResult :: Result [CError] -> IO ()
showResult (Success cerr) = mapM_ (printError . errorInfo) cerr
showResult (Failure err) = putStr err
process :: FilePath -> IO ()
process path = do
preprocessed <- phaseCpp path
let analysis = phaseParse path preprocessed >>= phaseAnalyse
let results = phaseCheck <$> analysis
showResult results
main :: [String] -> IO ()
main sources = do
putStrLn "[=] preprocessing..."
mapM_ process sources