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) = --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