Add max_mem and size parsing for arg parsing
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
60
src/main.rs
60
src/main.rs
@@ -4,7 +4,54 @@ mod common;
|
|||||||
mod vm;
|
mod vm;
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use std::{fs, io, process, path::{Path, PathBuf}};
|
use snafu::Snafu;
|
||||||
|
use std::{fs, process, path::PathBuf};
|
||||||
|
|
||||||
|
const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
|
#[derive(Snafu, Debug, Clone, PartialEq)]
|
||||||
|
enum ArgParseError<'a> {
|
||||||
|
#[snafu(display("invalid specified size: {} (sizes may end in G, M, or K)", text))]
|
||||||
|
InvalidSize { text: &'a str }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_bytes_size<'a>(mut text: &'a str) -> std::result::Result<usize, ArgParseError<'a>> {
|
||||||
|
if text.is_empty() {
|
||||||
|
return Err(ArgParseError::InvalidSize { text })
|
||||||
|
}
|
||||||
|
let multiplier = match text.chars().last().unwrap() {
|
||||||
|
'k' | 'K' => 1024,
|
||||||
|
'm' | 'M' => 1024 * 1024,
|
||||||
|
'g' | 'G' => 1024 * 1024 * 1024,
|
||||||
|
_ => 1,
|
||||||
|
};
|
||||||
|
// trim the last character
|
||||||
|
if multiplier != 1 {
|
||||||
|
text = &text[0 .. text.len() - 1];
|
||||||
|
}
|
||||||
|
let value = text.parse::<usize>().map_err(|_| ArgParseError::InvalidSize { text })?;
|
||||||
|
Ok(value * multiplier)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bytes_size() {
|
||||||
|
assert_eq!(from_bytes_size("64G"), Ok(64 * 1024 * 1024 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64M"), Ok(64 * 1024 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64K"), Ok(64 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64g"), Ok(64 * 1024 * 1024 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64m"), Ok(64 * 1024 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64k"), Ok(64 * 1024));
|
||||||
|
assert_eq!(from_bytes_size("64"), Ok(64));
|
||||||
|
|
||||||
|
assert!(from_bytes_size("64B").is_err());
|
||||||
|
assert!(from_bytes_size("64MB").is_err());
|
||||||
|
assert!(from_bytes_size("64GB").is_err());
|
||||||
|
assert!(from_bytes_size("64KB").is_err());
|
||||||
|
assert!(from_bytes_size("64b").is_err());
|
||||||
|
assert!(from_bytes_size("64mb").is_err());
|
||||||
|
assert!(from_bytes_size("64gb").is_err());
|
||||||
|
assert!(from_bytes_size("64kb").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug)]
|
||||||
struct Options {
|
struct Options {
|
||||||
@@ -12,14 +59,13 @@ struct Options {
|
|||||||
// * debug
|
// * debug
|
||||||
#[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))]
|
||||||
|
max_mem: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
fn get_input_string(path: impl AsRef<Path>) -> io::Result<String> {
|
|
||||||
fs::read_to_string(path.as_ref())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
use vm::{
|
use vm::{
|
||||||
state::State,
|
state::State,
|
||||||
@@ -29,7 +75,7 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let opt = Options::from_args();
|
let opt = Options::from_args();
|
||||||
let text = get_input_string(&opt.input)?;
|
let text = 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);
|
||||||
@@ -44,7 +90,7 @@ fn main() -> Result<()> {
|
|||||||
let mut asm = Asm::default();
|
let mut asm = Asm::default();
|
||||||
let object = res.assemble(&mut asm)?;
|
let object = res.assemble(&mut asm)?;
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
state.load_object(object, 64 * 1024 * 1024)?;
|
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