#![doc = include_str!("../README.md")]
use std::io::{self, BufRead};
use argp::{FromArgValue, FromArgs};
use gnuv2_demangle::{demangle, DemangleConfig};
pub mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
#[derive(FromArgs)]
struct Args {
#[argp(positional)]
syms: Vec<String>,
#[argp(option, short = 'm', default = "Mode::default()")]
mode: Mode,
#[argp(switch, short = 'V')]
version: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
enum Mode {
#[default]
G2dem,
Cfilt,
}
impl FromArgValue for Mode {
fn from_arg_value(value: &std::ffi::OsStr) -> Result<Self, String> {
const ERROR: &str = "Valid options are: `g2dem`, `g`, `cfilt` and `c`";
let value = value.to_str().ok_or_else(|| ERROR.to_string())?;
match value {
"g2dem" | "g" => Ok(Self::G2dem),
"cfilt" | "c" => Ok(Self::Cfilt),
_ => Err(ERROR.to_string()),
}
}
}
fn show_version() {
let (dirty, hash_short) = if built_info::GIT_DIRTY == Some(true) {
let hash_short = built_info::GIT_COMMIT_HASH_SHORT.unwrap_or("");
(" (dirty) ", hash_short)
} else {
("", "")
};
println!(
"{} {}{}{}",
built_info::PKG_NAME,
built_info::PKG_VERSION,
dirty,
hash_short
);
println!();
if let (Some(git_version), Some(git_hash_short)) =
(built_info::GIT_VERSION, built_info::GIT_COMMIT_HASH_SHORT)
{
if git_version.ends_with(git_hash_short) {
println!("Untagged git info: {}", git_version);
} else {
}
} else {
println!("No git information?");
}
println!("Built time (UTC): {}", built_info::BUILT_TIME_UTC);
println!("Build profile: {}", built_info::PROFILE);
println!("Repository: {}", built_info::PKG_REPOSITORY);
if let Some(ci) = built_info::CI_PLATFORM {
println!("Built on CI platform: {}", ci);
} else {
println!("Built locally.");
}
}
fn main() {
let args: Args = argp::parse_args_or_exit(argp::DEFAULT);
if args.version {
show_version();
return;
}
let config = match args.mode {
Mode::G2dem => DemangleConfig::new_g2dem(),
Mode::Cfilt => DemangleConfig::new_cfilt(),
};
if args.syms.is_empty() {
for line in io::stdin().lock().lines() {
let line = line.expect("Error reading from stdin");
if let Ok(demangled) = demangle(&line, &config) {
println!("{demangled}");
} else {
println!("{line}");
}
}
} else {
for mangled in args.syms {
if let Ok(demangled) = demangle(&mangled, &config) {
println!("{demangled}");
} else {
println!("{mangled}");
}
}
}
}