use core::fmt;
use std::path::PathBuf;
use crate::elf;
const HELP_TEMPLATE: &str = "{before-help}{about-with-newline}
{usage-heading} {usage}
{all-args}{after-help}
\u{1b}[1m\u{1b}[4mAuthors:\u{1b}[24m\u{1b}[22m
{tab}{author-with-newline}";
#[derive(Debug, clap::Parser)]
#[command(
author,
version,
about,
next_line_help = true,
help_template = HELP_TEMPLATE,
after_help = include_str!("command-line-after-help.txt"),
)]
pub(crate) struct Options {
#[arg(short = 'v', long, global = true, default_value_t = false)]
pub(crate) verbose: bool,
#[arg(short = 'c', long, global = true, value_enum, default_value_t = UseColor::Auto)]
pub(crate) color: UseColor,
#[arg(short = 'l', long, conflicts_with_all = ["sysroot", "libc_spec", "no_libc"])]
pub(crate) libc: Option<PathBuf>,
#[arg(short = 's', long, conflicts_with_all = ["libc", "libc_spec", "no_libc"])]
pub(crate) sysroot: Option<PathBuf>,
#[arg(short = 'i', long, value_enum, conflicts_with_all = ["libc", "sysroot", "no_libc"])]
pub(crate) libc_spec: Option<LibCSpec>,
#[arg(short = 'n', long, default_value_t = false, conflicts_with_all = ["libc", "sysroot", "libc_spec"])]
pub(crate) no_libc: bool,
#[arg(required = true, value_hint = clap::ValueHint::FilePath)]
pub(crate) input_files: Vec<PathBuf>,
}
#[derive(Debug, Copy, Clone, clap::ValueEnum)]
pub(crate) enum UseColor {
Auto,
Always,
Never,
}
impl From<UseColor> for termcolor::ColorChoice {
fn from(other: UseColor) -> Self {
match other {
UseColor::Auto => termcolor::ColorChoice::Auto,
UseColor::Always => termcolor::ColorChoice::Always,
UseColor::Never => termcolor::ColorChoice::Never,
}
}
}
#[derive(Debug, Copy, Clone, clap::ValueEnum)]
pub(crate) enum LibCSpec {
LSB1,
LSB1dot1,
LSB1dot2,
LSB1dot3,
LSB2,
LSB2dot0dot1,
LSB2dot1,
LSB3,
LSB3dot1,
LSB3dot2,
LSB4,
LSB4dot1,
LSB5,
}
impl fmt::Display for LibCSpec {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let spec_name = match *self {
LibCSpec::LSB1
| LibCSpec::LSB1dot1
| LibCSpec::LSB1dot2
| LibCSpec::LSB1dot3
| LibCSpec::LSB2
| LibCSpec::LSB2dot0dot1
| LibCSpec::LSB2dot1
| LibCSpec::LSB3
| LibCSpec::LSB3dot1
| LibCSpec::LSB3dot2
| LibCSpec::LSB4
| LibCSpec::LSB4dot1
| LibCSpec::LSB5 => "Linux Standard Base",
};
let spec_version = match *self {
LibCSpec::LSB1 => "1.0.0",
LibCSpec::LSB1dot1 => "1.1.0",
LibCSpec::LSB1dot2 => "1.2.0",
LibCSpec::LSB1dot3 => "1.3.0",
LibCSpec::LSB2 => "2.0.0",
LibCSpec::LSB2dot0dot1 => "2.0.1",
LibCSpec::LSB2dot1 => "2.1.0",
LibCSpec::LSB3 => "3.0.0",
LibCSpec::LSB3dot1 => "3.1.0",
LibCSpec::LSB3dot2 => "3.2.0",
LibCSpec::LSB4 => "4.0.0",
LibCSpec::LSB4dot1 => "4.1.0",
LibCSpec::LSB5 => "5.0.0",
};
write!(f, "{spec_name} {spec_version}")
}
}
impl LibCSpec {
pub(crate) fn get_functions_with_checked_versions(self) -> &'static [&'static str] {
match self {
LibCSpec::LSB1
| LibCSpec::LSB1dot1
| LibCSpec::LSB1dot2
| LibCSpec::LSB1dot3
| LibCSpec::LSB2
| LibCSpec::LSB2dot0dot1
| LibCSpec::LSB2dot1
| LibCSpec::LSB3
| LibCSpec::LSB3dot1
| LibCSpec::LSB3dot2 => &[],
LibCSpec::LSB4 | LibCSpec::LSB4dot1 | LibCSpec::LSB5 => {
elf::checked_functions::LSB_4_0_0_FUNCTIONS_WITH_CHECKED_VERSIONS
}
}
}
}