mod default;
mod dylibs;
mod fat;
mod handler;
mod headers;
mod rpaths;
mod segs;
mod syms;
mod rel;
mod lc;
mod data;
mod common;
use self::common::help_string_builder::HelpStringBuilder;
use self::common::options::{AddToOptions, OptionItem};
use super::output::Printer;
use super::result::*;
use colored::Colorize;
use default::*;
use dylibs::*;
use fat::*;
use getopts::Options;
use handler::*;
use headers::*;
use rpaths::*;
use segs::*;
use syms::*;
use rel::*;
use lc::*;
use data::*;
use std::process::exit;
pub fn handle_with_args() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
eprintln!("{}", help_string(None));
exit(1);
}
let handler = matched_handler(&args[1]);
let (command_name, description, mut option_items) = match &handler {
Some(h) => (Some(h.command_name()), h.description(), h.accepted_option_items()),
None => (None, "".to_string(), handler::default_option_items()),
};
let mut opts = Options::new();
option_items.add_to_opts(&mut opts);
let help_request = match command_name {
Some(command_name) => Some(HelpStringRequest(command_name.clone(), description, &mut option_items)),
None => None,
};
if requires_help(handler::default_options(), args.clone()) {
println!("{}", help_string(help_request));
exit(0);
}
let args = match &handler {
Some(_) => match args.get(2..) {
Some(args) => args,
None => {
eprintln!("{}", help_string(help_request));
exit(1);
}
},
None => match args.get(1..) {
Some(args) => args,
None => {
eprintln!("{}", help_string(None));
exit(1);
}
},
};
if args.len() == 0 {
eprintln!("{}", help_string(None));
exit(1);
}
let path = match opts.parse(args.clone()) {
Ok(m) => match m.opt_defined(common::PATH_OPT_SHORT) {
true => match m.opt_str(common::PATH_OPT_SHORT) {
Some(path) => path,
None => args[0].clone(),
},
false => args[0].clone(),
},
Err(f) => {
eprintln!("{f}\n\n{}", help_string(help_request));
exit(1);
}
};
let args = Vec::from(args);
let object_type = match common::helpers::load_object_type_with(&path) {
Ok(obj) => obj,
Err(err) => {
eprint!("\"{}\":\n{:#?}\n\n", path.bright_white(), err);
exit(1);
}
};
match handler {
Some(handler) => handler.handle_object(object_type, args),
None => DefaultHandler::new(Printer {}).handle_object(object_type, args),
}
}
struct HelpStringRequest<'a>(String, String, &'a mut Vec<OptionItem>);
fn help_string(request: Option<HelpStringRequest>) -> String {
match request {
Some(request) => {
let mut help_string_builder =
HelpStringBuilder::new(request.0.clone());
help_string_builder.description = Some(request.1);
help_string_builder.show_usage_title = true;
help_string_builder.add_option_items(request.2);
help_string_builder.build_string()
}
None => {
let mut result = "".to_string();
for handler in available_handlers() {
let mut help_string_builder = HelpStringBuilder::new(handler.command_name());
help_string_builder.add_option_items(&mut handler.accepted_option_items());
result += &help_string_builder.build_string();
result += "\n";
}
result
}
}
}
fn requires_help(opts: Options, args: Vec<String>) -> bool {
match opts.parse(args) {
Ok(m) => m.opt_present(common::HELP_FLAG_SHORT),
Err(_) => false,
}
}
fn matched_handler(name: &str) -> Option<Box<dyn Handler>> {
for handler in available_handlers() {
if handler.can_handle_with_name(name) {
return Some(handler);
}
}
None
}
fn available_handlers() -> Vec<Box<dyn Handler>> {
let printer = Printer {};
vec![
Box::new(SymsHandler::new(printer.clone())),
Box::new(RpathsHandler::new(printer.clone())),
Box::new(DylibsHandler::new(printer.clone())),
Box::new(SegsHandler::new(printer.clone())),
Box::new(ArchsHandler::new(printer.clone())),
Box::new(HeadersHandler::new(printer.clone())),
Box::new(RelHandler::new(printer.clone())),
Box::new(LcHandler::new(printer.clone())),
Box::new(DataHandler::new(printer.clone())),
]
}