1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::io::Write;
use std::io;
use clap::App;
use clap::AppSettings;
use clap::Arg;
use clap::ArgMatches;
use VERSION;
use decompilation::DecompilationArguments;
use decompiler::Decompiler;
use error::Result;
use error::ResultExt;
use file::File;
use settings::Settings;
fn parse_args<'a>(args: &[String]) -> ArgMatches<'a> {
App::new("decompiler")
.version(VERSION)
.about("Decompiles the given file via retdec.com's API.")
.setting(AppSettings::ColorNever)
.arg(Arg::with_name("FILE")
.required(true)
.help("Input file to be decompiled"))
.arg(Arg::with_name("api_key")
.short("k")
.long("api-key")
.takes_value(true)
.value_name("KEY")
.help("API key to be used."))
.arg(Arg::with_name("api_url")
.short("u")
.long("api-url")
.takes_value(true)
.value_name("URL")
.help("Custom URL to the retdec.com's API."))
.get_matches_from(args)
}
fn print_decompilation_result(output: &str) -> Result<()> {
let mut stdout = io::stdout();
stdout.write(output.as_bytes())
.chain_err(|| "failed to print the result on the standard output")?;
Ok(())
}
fn run(args: &[String]) -> Result<()> {
let args = parse_args(args);
let mut settings = Settings::new();
if let Some(api_key) = args.value_of("api_key") {
settings.set_api_key(api_key);
}
if let Some(api_url) = args.value_of("api_url") {
settings.set_api_url(api_url);
}
let input_file = args.value_of("FILE")
.expect("no FILE - this should never happen");
let decompiler = Decompiler::new(settings);
let args = DecompilationArguments::new()
.with_input_file(File::from_path(&input_file)?);
let mut decompilation = decompiler.start_decompilation(args)?;
decompilation.wait_until_finished()?;
let output_code = decompilation.get_output_hll_code()?;
print_decompilation_result(&output_code)?;
Ok(())
}
generate_main_for_tool!(run);
#[cfg(test)]
mod tests {
use super::*;
macro_rules! args {
($($arg:expr),*) => {
{
let mut args = Vec::new();
args.push("decompiler".to_string());
$(
args.push($arg.to_string());
)*
args
}
}
}
#[test]
fn parse_args_correctly_parses_input_file() {
let args = parse_args(&args!["file.exe"]);
assert_eq!(args.value_of("FILE"), Some("file.exe"));
}
#[test]
fn parse_args_correctly_parses_api_key_short_form() {
let args = parse_args(&args!["-k", "KEY", "file.exe"]);
assert_eq!(args.value_of("api_key"), Some("KEY"));
}
#[test]
fn parse_args_correctly_parses_api_key_long_form() {
let args = parse_args(&args!["--api-key", "KEY", "file.exe"]);
assert_eq!(args.value_of("api_key"), Some("KEY"));
}
#[test]
fn parse_args_correctly_parses_api_url_short_form() {
let args = parse_args(&args!["-u", "URL", "file.exe"]);
assert_eq!(args.value_of("api_url"), Some("URL"));
}
#[test]
fn parse_args_correctly_parses_api_url_long_form() {
let args = parse_args(&args!["--api-url", "URL", "file.exe"]);
assert_eq!(args.value_of("api_url"), Some("URL"));
}
}