aboutsummaryrefslogtreecommitdiff
path: root/crates/readrom
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2025-01-22 15:57:49 +0100
committerMiquel Sabaté Solà <mikisabate@gmail.com>2025-01-22 15:57:49 +0100
commit61ef02df2c128cd86efcddd3fa53870bc8d575c4 (patch)
tree761bb4c9d443f9f61a95744440664cb6501b47df /crates/readrom
parentb4a779f040f18257fde1c357626461ab187490db (diff)
downloadtools.nes-61ef02df2c128cd86efcddd3fa53870bc8d575c4.tar.gz
tools.nes-61ef02df2c128cd86efcddd3fa53870bc8d575c4.zip
Remove the dependency on clap
All three binaries (i.e. readrom, nasm and xa65) used it, and to be honest rolling our own argument parsing was actually pretty easy to achieve. This frees us from a big dependency and it also frees us from inner dependencies such as 'clap_derive' which prevented us from being able to build binaries purely statically. As a side effect, we can now display help/version messages which are more like I'm used to, and certain checks can be moved in the parsing directly instead of having to be done later. As a cherry on top, there is some type masturbation that gets removed along the way. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'crates/readrom')
-rw-r--r--crates/readrom/Cargo.toml1
-rw-r--r--crates/readrom/src/main.rs79
2 files changed, 62 insertions, 18 deletions
diff --git a/crates/readrom/Cargo.toml b/crates/readrom/Cargo.toml
index 93d6134..326ed92 100644
--- a/crates/readrom/Cargo.toml
+++ b/crates/readrom/Cargo.toml
@@ -7,5 +7,4 @@ license.workspace = true
authors.workspace = true
[dependencies]
-clap = "^4"
header.workspace = true
diff --git a/crates/readrom/src/main.rs b/crates/readrom/src/main.rs
index ae2a44c..e37e8c7 100644
--- a/crates/readrom/src/main.rs
+++ b/crates/readrom/src/main.rs
@@ -1,8 +1,65 @@
-use clap::{arg, Arg, Command};
use header::{Header, Kind};
use std::fs::File;
use std::io::{ErrorKind, Read};
+/// Version for this program.
+const VERSION: &str = "0.1.0";
+
+#[derive(Default)]
+struct Args {
+ file: String,
+ header: bool,
+}
+
+fn print_help() {
+ println!("Display information about NES/Famicom ROM files.\n");
+ println!("usage: readrom [OPTIONS] <FILE>\n");
+ println!("Options:");
+ println!(" -H, --header\tJust print the ROM header and quit.");
+ std::process::exit(0);
+}
+
+// Parse the arguments given to the program and returns an Args object with the
+// given information.
+fn parse_arguments() -> Args {
+ let mut args = std::env::args();
+ let mut res = Args::default();
+
+ // Skip command name.
+ args.next();
+
+ for arg in args {
+ match arg.as_str() {
+ "-h" | "--help" => print_help(),
+ "-H" | "--header" => {
+ if res.header {
+ die("do not specify the '-H/--header' flag twice".to_string());
+ }
+ res.header = true;
+ }
+ "-v" | "--version" => {
+ println!("readrom {}", VERSION);
+ std::process::exit(0);
+ }
+ _ => {
+ if arg.starts_with('-') {
+ die(format!("don't know how to handle the '{}' flag", arg));
+ }
+ if !res.file.is_empty() {
+ die("cannot have multiple source files".to_string());
+ }
+ res.file = arg;
+ }
+ }
+ }
+
+ if res.file.is_empty() {
+ die("you need to specify the file to be read".to_string());
+ }
+
+ res
+}
+
fn print_header(header: &Header) {
println!("Header:");
@@ -47,22 +104,10 @@ fn die(message: String) {
}
fn main() {
- let args = Command::new("readrom")
- .version("0.1.0")
- .about("Display information about NES/Famicom ROM files.")
- .arg(Arg::new("FILE").required(true).help("ROM file to be read"))
- .arg(arg!(-H --header "Just print the ROM header and quit"))
- .get_matches();
- let file = match args.get_one::<String>("FILE") {
- Some(file) => file,
- None => {
- die("you have to provide a file".to_string());
- return;
- }
- };
+ let args = parse_arguments();
- let Ok(mut input) = File::open(file) else {
- die(format!("failed to open the given file '{}'", &file));
+ let Ok(mut input) = File::open(&args.file) else {
+ die(format!("failed to open the given file '{}'", &args.file));
return;
};
@@ -85,7 +130,7 @@ fn main() {
};
print_header(&header);
- if *args.get_one::<bool>("header").unwrap() {
+ if args.header {
std::process::exit(0);
}