cspmchecker-0.1: src/Checker/Main.hs
{-# LANGUAGE DoAndIfThenElse #-}
module Main where
import Control.Monad
import Control.Monad.Trans
import Data.List
import System.Console.GetOpt
import System.Directory
import System.Environment
import System.FilePath
import System.Exit
import System.IO
import CSPM
import CSPM.PrettyPrinter
import Monad
import Util.Annotated
import Util.Exception
import Util.PrettyPrint
countSuccesses :: [Sfdr Bool] -> Sfdr ()
countSuccesses tasks = do
results <- sequence tasks
let
failed = length $ filter id results
succeeded = length $ filter id results
total = length tasks
if failed+succeeded > 1 then do
liftIO $ putStrLn $ show succeeded++" files succeeded out of "++show total
else return ()
getFilesFromDir :: FilePath -> IO [FilePath]
getFilesFromDir path = do
all <- getDirectoryContents path
let all' = [path++"/"++f | f <- all]
files <- filterM doesFileExist all'
dirs <- filterM doesDirectoryExist all'
let
dirs' = filter (\f -> not $ (isSuffixOf "." f)
|| (isSuffixOf ".." f)) dirs
files' = filter (isSuffixOf ".csp") files
fss <- mapM getFilesFromDir [dir | dir <- dirs']
return $ files'++concat fss
doFile :: FilePath -> Sfdr Bool
doFile fp = do
liftIO $ putStr $ "Checking "++fp++"....."
res <- tryM $ do
ms <- parseFile fp
typeCheckFile ms
return ()
ws <- getState lastWarnings
resetCSPM
case res of
Left e -> do
printError ("\n"++show e)
return False
Right _ -> do
liftIO $ putStrLn $ "Ok"
if ws /= [] then printError (show (prettyPrint ws))
else return ()
return True
printError :: String -> Sfdr ()
printError s = liftIO $ putStrLn $ "\ESC[1;31m\STX"++s++"\ESC[0m\STX"
data Options = Options {
recursive :: Bool,
help :: Bool
}
defaultOptions = Options {
recursive = False,
help = False
}
options :: [OptDescr (Options -> Options)]
options = [
Option ['r'] ["recursive"]
(NoArg (\o -> o { recursive = True }))
"If the input file is a directory, check all files contained in all subdirectories",
Option ['h'] ["help"]
(NoArg (\o -> o { help = True }))
"Display usage message"
]
header :: String
header = "Usage: cspmchecker [OPTION...] files..."
main :: IO ()
main = do
args <- getArgs
st <- initSfdrState
runSfdr st $
case getOpt RequireOrder options args of
(_,_,e:es) -> liftIO $ putStr $ concat (e:es) ++ usageInfo header options
(o,files, []) -> do
let opts = foldl (flip id) defaultOptions o
case (opts, files) of
(_, []) ->
liftIO $ putStr $ usageInfo header options
(Options { help = True }, files) ->
liftIO $ putStr $ usageInfo header options
(Options { recursive = True }, dirs) -> do
tasks <- mapM (liftIO . getFilesFromDir) dirs
countSuccesses (map doFile (concat tasks))
(_, files) ->
countSuccesses (map doFile files)