From bd34cdad63d58f0db73af9e76b294fe3a354d741 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Tue, 25 Feb 2020 18:12:28 -0500 Subject: [PATCH] Add compile and compile_out options, and extended input/output options * compile flag and compile_out argument to the driver allow the program to be compiled only * if '-' is supplied to compile_out, it will output to STDOUT instead * if '-' is supplied to input, it will read from STDIN instead Signed-off-by: Alek Ratzloff --- src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5509556..a2197f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ mod vm; use structopt::StructOpt; use snafu::Snafu; -use std::{fs, process, path::PathBuf}; +use std::{fs, io::{stdin, stdout, Write, Read}, process, path::PathBuf}; const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024; @@ -57,11 +57,28 @@ fn test_bytes_size() { struct Options { // maybe some other options: // * debug + + /// The input file to work with. + /// + /// By default, the file will be executed. If -c is passed, it will not run and only compile. + /// Supplying - for the path will read from STDIN. #[structopt(name = "FILE", parse(from_os_str))] input: PathBuf, - #[structopt(short, long, parse(try_from_str = from_bytes_size))] + /// The maximum amount of virtual memory allowed. + #[structopt(long, parse(try_from_str = from_bytes_size))] max_mem: Option, + + /// Whether to compile the input file to an object. + #[structopt(short, long)] + compile: bool, + + /// The output file for compiled files. + /// + /// If not supplied, a name will be inferred from the input file. Supplying - for the path will + /// output to STDOUT. + #[structopt(short = "o", long)] + compile_out: Option } type Result = std::result::Result>; @@ -74,11 +91,21 @@ fn main() -> Result<()> { syn::{lexer, parser}, } }; + + // get the object either from reading it, or from parsing an assembly file let opt = Options::from_args(); - let text = fs::read_to_string(&opt.input)?; + let text = if Some("-") == opt.input.to_str() { + let mut text = String::new(); + let stdin = stdin(); + stdin.lock().read_to_string(&mut text)?; + text + } else { + fs::read_to_string(&opt.input)? + }; let lexerdef = lexer::lexerdef(); let lexer = lexerdef.lexer(&text); let (res, errors) = parser::parse(&lexer); + // print errors for err in errors.iter() { println!("{}", err.pp(&lexer, &parser::token_epp)); @@ -89,8 +116,25 @@ fn main() -> Result<()> { let res = res.unwrap(); let mut asm = Asm::default(); let object = res.assemble(&mut asm)?; - let mut state = State::new(); - state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?; - let status = state.exec()?; - process::exit((status & 0xffff_ffff) as i32); + if opt.compile { + let outfile = opt.compile_out.clone().unwrap_or_else(|| { + let mut outfile = opt.input.clone(); + assert!(outfile.set_extension("obj")); + outfile + }); + let bytes = object.to_bytes(); + if Some("-") == outfile.to_str() { + let stdout = stdout(); + stdout.lock().write(&bytes)?; + } else { + // write compiled file here + fs::write(outfile, &bytes)?; + } + Ok(()) + } else { + let mut state = State::new(); + state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?; + let status = state.exec()?; + process::exit((status & 0xffff_ffff) as i32); + } }