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 <alekratz@gmail.com>
This commit is contained in:
50
src/main.rs
50
src/main.rs
@@ -5,7 +5,7 @@ mod vm;
|
|||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use snafu::Snafu;
|
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;
|
const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
@@ -57,11 +57,28 @@ fn test_bytes_size() {
|
|||||||
struct Options {
|
struct Options {
|
||||||
// maybe some other options:
|
// maybe some other options:
|
||||||
// * debug
|
// * 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))]
|
#[structopt(name = "FILE", parse(from_os_str))]
|
||||||
input: PathBuf,
|
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<usize>,
|
max_mem: Option<usize>,
|
||||||
|
|
||||||
|
/// 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<PathBuf>
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
@@ -74,11 +91,21 @@ fn main() -> Result<()> {
|
|||||||
syn::{lexer, parser},
|
syn::{lexer, parser},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// get the object either from reading it, or from parsing an assembly file
|
||||||
let opt = Options::from_args();
|
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 lexerdef = lexer::lexerdef();
|
||||||
let lexer = lexerdef.lexer(&text);
|
let lexer = lexerdef.lexer(&text);
|
||||||
let (res, errors) = parser::parse(&lexer);
|
let (res, errors) = parser::parse(&lexer);
|
||||||
|
|
||||||
// print errors
|
// print errors
|
||||||
for err in errors.iter() {
|
for err in errors.iter() {
|
||||||
println!("{}", err.pp(&lexer, &parser::token_epp));
|
println!("{}", err.pp(&lexer, &parser::token_epp));
|
||||||
@@ -89,8 +116,25 @@ fn main() -> Result<()> {
|
|||||||
let res = res.unwrap();
|
let res = res.unwrap();
|
||||||
let mut asm = Asm::default();
|
let mut asm = Asm::default();
|
||||||
let object = res.assemble(&mut asm)?;
|
let object = res.assemble(&mut asm)?;
|
||||||
|
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();
|
let mut state = State::new();
|
||||||
state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?;
|
state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?;
|
||||||
let status = state.exec()?;
|
let status = state.exec()?;
|
||||||
process::exit((status & 0xffff_ffff) as i32);
|
process::exit((status & 0xffff_ffff) as i32);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user