From 61094f6909e8a8e863ecb800476be4fad8a6b1db Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 3 Jun 2016 14:56:25 -0700 Subject: [PATCH] Begin a basic command line interface. Add an external dependency to the docopt package and use it for a scaffold command line interface for the cton-util command. I am not too happy about taking external dependencies, and docopt pulls in 13 other packages. However, I really don't want to be writing command line parsers, and as long as the external dependencies are confined to the tools crate, we should be fine. The core cretonne crate should stay free of external dependencies to avoid trouble with embedding it. Implement a basic 'cat' subcommand which currently behaves like unix 'cat'. It will gain parser powers soon. --- cranelift/src/libcretonne/lib.rs | 2 + cranelift/src/tools/Cargo.lock | 101 +++++++++++++++++++++++++++++++ cranelift/src/tools/Cargo.toml | 2 + cranelift/src/tools/cat.rs | 28 +++++++++ cranelift/src/tools/main.rs | 62 ++++++++++++++++++- 5 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 cranelift/src/tools/cat.rs diff --git a/cranelift/src/libcretonne/lib.rs b/cranelift/src/libcretonne/lib.rs index 248c6bb37f..8b92e5dbed 100644 --- a/cranelift/src/libcretonne/lib.rs +++ b/cranelift/src/libcretonne/lib.rs @@ -5,6 +5,8 @@ // // ====------------------------------------------------------------------------------------==== // +pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + pub mod types; pub mod immediates; pub mod entities; diff --git a/cranelift/src/tools/Cargo.lock b/cranelift/src/tools/Cargo.lock index 91e9a5fae4..0b85735d6c 100644 --- a/cranelift/src/tools/Cargo.lock +++ b/cranelift/src/tools/Cargo.lock @@ -4,6 +4,16 @@ version = "0.0.0" dependencies = [ "cretonne 0.0.0", "cretonne-reader 0.0.0", + "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -17,3 +27,94 @@ dependencies = [ "cretonne 0.0.0", ] +[[package]] +name = "docopt" +version = "0.6.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.1.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "thread-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + diff --git a/cranelift/src/tools/Cargo.toml b/cranelift/src/tools/Cargo.toml index 702bd635e6..8059002f40 100644 --- a/cranelift/src/tools/Cargo.toml +++ b/cranelift/src/tools/Cargo.toml @@ -12,3 +12,5 @@ path = "main.rs" [dependencies] cretonne = { path = "../libcretonne" } cretonne-reader = { path = "../libreader" } +docopt = "0.6.80" +rustc-serialize = "0.3.19" diff --git a/cranelift/src/tools/cat.rs b/cranelift/src/tools/cat.rs new file mode 100644 index 0000000000..c8f30d0a99 --- /dev/null +++ b/cranelift/src/tools/cat.rs @@ -0,0 +1,28 @@ +//! The `cat` sub-command. +//! +//! Read a sequence of Cretonne IL files and print them again to stdout. This has the effect of +//! normalizing formatting and removing comments. + +use CommandResult; +use std::fs::File; +use std::io::Read; + +pub fn run(files: Vec) -> CommandResult { + for (i, f) in files.into_iter().enumerate() { + if i != 0 { + println!(""); + } + try!(cat_one(f)) + } + Ok(()) +} + +fn cat_one(filename: String) -> CommandResult { + let mut file = try!(File::open(&filename).map_err(|e| format!("{}: {}", filename, e))); + let mut buffer = String::new(); + try!(file.read_to_string(&mut buffer) + .map_err(|e| format!("Couldn't read {}: {}", filename, e))); + + print!("{}", buffer); + Ok(()) +} diff --git a/cranelift/src/tools/main.rs b/cranelift/src/tools/main.rs index 97b261d22d..1ea40c201c 100644 --- a/cranelift/src/tools/main.rs +++ b/cranelift/src/tools/main.rs @@ -1,5 +1,65 @@ extern crate cretonne; extern crate cton_reader; +extern crate docopt; +extern crate rustc_serialize; -fn main() {} +use cretonne::VERSION; +use docopt::Docopt; +use std::io::{self, Write}; +use std::process; + + +mod cat; + +const USAGE: &'static str = " +Cretonne code generator utility + +Usage: + cton-util cat ... + cton-util --help | --version + +Options: + -h, --help print this help message + --version print the Cretonne version + +"; + +#[derive(RustcDecodable, Debug)] +struct Args { + cmd_cat: bool, + arg_file: Vec, +} + +/// A command either succeeds or fails with an error message. +pub type CommandResult = Result<(), String>; + +/// Parse the command line arguments and run the requested command. +fn cton_util() -> CommandResult { + // Parse comand line arguments. + let args: Args = Docopt::new(USAGE) + .and_then(|d| { + d.help(true) + .version(Some(format!("Cretonne {}", VERSION))) + .decode() + }) + .unwrap_or_else(|e| e.exit()); + + // Find the sub-command to execute. + if args.cmd_cat { + cat::run(args.arg_file) + } else { + // Debugging / shouldn't happen with proper command line handling above. + Err(format!("Unhandled args: {:?}", args)) + } +} + +fn main() { + if let Err(mut msg) = cton_util() { + if !msg.ends_with('\n') { + msg.push('\n'); + } + io::stderr().write(msg.as_bytes()).unwrap(); + process::exit(1); + } +}