module Main where import Control.Monad import Data.List -- find, isSuffixOf import qualified Data.Map as Map import System.Environment import System.Exit import System.IO import System.Console.GetOpt import Text.PrettyPrint import Frame import FrameIntel import LexIntel import ParseIntel import StateIntel hiding (print) import Util -- Pretty import Wellformed data Flag = Verbose | Help deriving (Eq, Show) optDescrs :: [OptDescr Flag] optDescrs = [ Option ['?'] ["help"] (NoArg Help) "show usage information" , Option ['v'] ["verbose"] (NoArg Verbose) "be verbose" ] usage :: IO a usage = do putStr $ usageInfo "Usage: risc386 [options] " optDescrs exitFailure -- | Extract the input file name from command line. -- Display usage info for malformed command lines. parseCmdLine :: [String] -> IO String parseCmdLine argv = do let (os, ns, _) = getOpt Permute optDescrs argv unless (length ns == 1) usage let prgFile = head ns when (Verbose `elem` os) $ hPutStrLn stderr $ "Reading program from file: " ++ prgFile when (Help `elem` os) $ ioError (userError "No execution with --help") return prgFile exitOnError :: Either String b -> IO b exitOnError = either crash return where crash a = putStrLn a >> exitFailure {- main: * parse IntelFrame list * search "*main" function * split frames into blocks IBlockFrame * convert frame list into a map * execute main function -} main :: IO () main = do cmdLine <- getArgs prgFile <- parseCmdLine cmdLine input <- readFile prgFile -- hPutStrLn stderr $ "Passing these args to main fct: " ++ (show args) -- input <- getContents -- print (alexScanTokens input) let frames = parse (alexScanTokens input) -- anyting that ends in "main" is considered the main function lmain <- do exitOnError $ maybe (Left "no main function found") Right $ -- find (\ l -> drop (length l - 4) l == "main") $ find ("main" `isSuffixOf`) $ map frameName frames hPutStrLn stderr ("## Input:\n" ++ (render $ ppr frames)) -- check instructions for well-formedness exitOnError $ wellformed frames let bfs = map iBlocksFrame frames hPutStrLn stderr ("## Blocks:\n" ++ (render $ ppr bfs)) let framemap = Map.fromList $ map (\ f@(IBlockFrame l _ _) -> (l,f)) $ bfs let (result, output) = run framemap lmain mapM_ putStr output exitOnError result exitSuccess