//! Parser for the `-l` command-line option, which links the generated crate to
//! a native library.
//!
//! (There is also a similar but separate syntax for `#[link]` attributes,
//! which have their own parser in `rustc_metadata`.)

use rustc_feature::UnstableFeatures;
use rustc_hir::attrs::NativeLibKind;

use crate::EarlyDiagCtxt;
use crate::config::UnstableOptions;
use crate::utils::NativeLib;

#[cfg(test)]
mod tests;

/// Parses all `-l` options.
pub(crate) fn parse_native_libs(
    early_dcx: &EarlyDiagCtxt,
    unstable_opts: &UnstableOptions,
    unstable_features: UnstableFeatures,
    matches: &getopts::Matches,
) -> Vec<NativeLib> {
    let cx = ParseNativeLibCx {
        early_dcx,
        unstable_options_enabled: unstable_opts.unstable_options,
        is_nightly: unstable_features.is_nightly_build(),
    };
    matches.opt_strs("l").into_iter().map(|value| parse_native_lib(&cx, &value)).collect()
}

struct ParseNativeLibCx<'a> {
    early_dcx: &'a EarlyDiagCtxt,
    unstable_options_enabled: bool,
    is_nightly: bool,
}

impl ParseNativeLibCx<'_> {
    /// If unstable values are not permitted, exits with a fatal error made by
    /// combining the given strings.
    fn on_unstable_value(&self, message: &str, if_nightly: &str, if_stable: &str) {
        if self.unstable_options_enabled {
            return;
        }

        let suffix = if self.is_nightly { if_nightly } else { if_stable };
        self.early_dcx.early_fatal(format!("{message}{suffix}"));
    }
}

/// Parses the value of a single `-l` option.
fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib {
    let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value);

    let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind {
        "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
        "dylib" => NativeLibKind::Dylib { as_needed: None },
        "framework" => NativeLibKind::Framework { as_needed: None },
        "link-arg" => {
            cx.on_unstable_value(
                "library kind `link-arg` is unstable",
                ", the `-Z unstable-options` flag must also be passed to use it",
                " and only accepted on the nightly compiler",
            );
            NativeLibKind::LinkArg
        }
        _ => cx.early_dcx.early_fatal(format!(
            "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
        )),
    });

    // Provisionally create the result, so that modifiers can modify it.
    let mut native_lib = NativeLib {
        name: name.to_owned(),
        new_name: new_name.map(str::to_owned),
        kind,
        verbatim: None,
    };

    if let Some(modifiers) = modifiers {
        // If multiple modifiers are present, they are separated by commas.
        for modifier in modifiers.split(',') {
            parse_and_apply_modifier(cx, modifier, &mut native_lib);
        }
    }

    if native_lib.name.is_empty() {
        cx.early_dcx.early_fatal("library name must not be empty");
    }

    native_lib
}

/// Parses one of the comma-separated modifiers (prefixed by `+` or `-`), and
/// modifies `native_lib` appropriately.
///
/// Exits with a fatal error if a malformed/unknown/inappropriate modifier is
/// found.
fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_lib: &mut NativeLib) {
    let early_dcx = cx.early_dcx;

    // Split off the leading `+` or `-` into a boolean value.
    let (modifier, value) = match modifier.split_at_checked(1) {
        Some(("+", m)) => (m, true),
        Some(("-", m)) => (m, false),
        _ => cx.early_dcx.early_fatal(
            "invalid linking modifier syntax, expected '+' or '-' prefix \
             before one of: bundle, verbatim, whole-archive, as-needed",
        ),
    };

    // Assigns the value (from `+` or `-`) to an empty `Option<bool>`, or emits
    // a fatal error if the option has already been set.
    let assign_modifier = |opt_bool: &mut Option<bool>| {
        if opt_bool.is_some() {
            let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
            early_dcx.early_fatal(msg)
        }
        *opt_bool = Some(value);
    };

    // Check that the modifier is applicable to the native lib kind, and apply it.
    match (modifier, &mut native_lib.kind) {
        ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
        ("bundle", _) => early_dcx
            .early_fatal("linking modifier `bundle` is only compatible with `static` linking kind"),

        ("verbatim", _) => assign_modifier(&mut native_lib.verbatim),

        ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
            assign_modifier(whole_archive)
        }
        ("whole-archive", _) => early_dcx.early_fatal(
            "linking modifier `whole-archive` is only compatible with `static` linking kind",
        ),

        ("as-needed", NativeLibKind::Dylib { as_needed })
        | ("as-needed", NativeLibKind::Framework { as_needed }) => {
            cx.on_unstable_value(
                "linking modifier `as-needed` is unstable",
                ", the `-Z unstable-options` flag must also be passed to use it",
                " and only accepted on the nightly compiler",
            );
            assign_modifier(as_needed)
        }
        ("as-needed", _) => early_dcx.early_fatal(
            "linking modifier `as-needed` is only compatible with \
             `dylib` and `framework` linking kinds",
        ),

        _ => early_dcx.early_fatal(format!(
            "unknown linking modifier `{modifier}`, expected one \
             of: bundle, verbatim, whole-archive, as-needed"
        )),
    }
}

#[derive(Debug, PartialEq, Eq)]
struct NativeLibParts<'a> {
    kind: Option<&'a str>,
    modifiers: Option<&'a str>,
    name: &'a str,
    new_name: Option<&'a str>,
}

/// Splits a string of the form `[KIND[:MODIFIERS]=]NAME[:NEW_NAME]` into those
/// individual parts. This cannot fail, but the resulting strings require
/// further validation.
fn split_native_lib_value(value: &str) -> NativeLibParts<'_> {
    // Split the initial value into `[KIND=]NAME`.
    let name = value;
    let (kind, name) = match name.split_once('=') {
        Some((prefix, name)) => (Some(prefix), name),
        None => (None, name),
    };

    // Split the kind part, if present, into `KIND[:MODIFIERS]`.
    let (kind, modifiers) = match kind {
        Some(kind) => match kind.split_once(':') {
            Some((kind, modifiers)) => (Some(kind), Some(modifiers)),
            None => (Some(kind), None),
        },
        None => (None, None),
    };

    // Split the name part into `NAME[:NEW_NAME]`.
    let (name, new_name) = match name.split_once(':') {
        Some((name, new_name)) => (name, Some(new_name)),
        None => (name, None),
    };

    NativeLibParts { kind, modifiers, name, new_name }
}
