{-# LANGUAGE DeriveDataTypeable #-} import System.Console.CmdArgs import System.Exit import System.IO (hPutStrLn, stderr) import qualified DCPU16.Assembly.Parser as P import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import Control.Monad (when, void) import DCPU16.Assembly.Printer import DCPU16.Assembly.Optimizer import DCPU16.Assembler import DCPU16.Disassembler import DCPU16.Hex main = do opts <- cmdArgs options instr <- readInput opts let out = processOutput opts . optimize opts $ instr case output opts of -- absolutely do not do 'putStrLn', to not break binary input: "" -> B.putStr out f -> B.writeFile f out where packNlEof s = B.snoc (B.pack s) '\n' readInput opts = do instr <- case runMode opts of Disassemble -> do s <- B.readFile (inputFile opts) return . Just . disassemble $ s _ -> do let po = P.defaults { P.roundedBrackets = parseSmoothBrackets opts } P.parseFile po (inputFile opts) case instr of Just is -> return is Nothing -> exitFailure -- parser already printed messages optimize opts is = if noOptimization opts then is else sizeVariant is processOutput opts instr = case runMode opts of Assemble -> binEncoding . assemble $ instr _ -> packNlEof $ pprint instr where binEncoding = if hexdump opts then packNlEof . dumpBytes else id -- | Print a message to stderr and exit. errorExit :: String -> IO () errorExit msg = hPutStrLn stderr msg >> exitFailure data RunMode = Assemble | Disassemble | PrettyPrint deriving (Eq,Show,Read,Data,Typeable) data Options = Options { runMode :: RunMode , inputFile :: String , noOptimization :: Bool , output :: String , hexdump :: Bool , parseSmoothBrackets :: Bool } deriving (Eq,Show,Read,Data,Typeable) options = Options { runMode = enum [ PrettyPrint&= help "Assembly -> consistently formatted assembly" , Assemble &= help "Assembly -> machine code" , Disassemble&= help "Machine code -> assembly" ] &= groupname "Mode of operation" , inputFile = "" &= argPos 0 &= typ "" , noOptimization = False &= explicit &= name "no-optimize" &= help "Disable short literal/label optimization" &= groupname "Optimization" , output = def &= typ "" &= help "Write to file instead of stdout" &= groupname "General" , hexdump = False &= help "Encode binary data in a 16-bit hexdump" , parseSmoothBrackets = False &= explicit &= name "smooth-brackets" &= help "Parse (a) instead of [a] for indirect mode" } &= program "soyuz" &= summary "soyuz 0.0.0, amtal " &= details [ "Documentation and source at https://github.com/amtal/soyuz or on Hackage." ]