//! Used by `rustc` when loading a plugin.

use rustc::session::Session;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use registry::Registry;

use std::borrow::ToOwned;
use std::env;
use std::mem;
use std::path::PathBuf;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};

/// Pointer to a registrar function.
pub type PluginRegistrarFun =
    fn(&mut Registry);

pub struct PluginRegistrar {
    pub fun: PluginRegistrarFun,
    pub args: Vec<ast::NestedMetaItem>,
}

struct PluginLoader<'a> {
    sess: &'a Session,
    reader: CrateLoader<'a>,
    plugins: Vec<PluginRegistrar>,
}

fn call_malformed_plugin_attribute(a: &Session, b: Span) {
    span_err!(a, b, E0498, "malformed plugin attribute");
}

/// Read plugin metadata and dynamically load registrar functions.
pub fn load_plugins(sess: &Session,
                    cstore: &CStore,
                    krate: &ast::Crate,
                    crate_name: &str,
                    addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
    let mut loader = PluginLoader::new(sess, cstore, crate_name);

    // do not report any error now. since crate attributes are
    // not touched by expansion, every use of plugin without
    // the feature enabled will result in an error later...
    if sess.features_untracked().plugin {
        for attr in &krate.attrs {
            if !attr.check_name("plugin") {
                continue;
            }

            let plugins = match attr.meta_item_list() {
                Some(xs) => xs,
                None => {
                    call_malformed_plugin_attribute(sess, attr.span);
                    continue;
                }
            };

            for plugin in plugins {
                // plugins must have a name and can't be key = value
                match plugin.name() {
                    Some(name) if !plugin.is_value_str() => {
                        let args = plugin.meta_item_list().map(ToOwned::to_owned);
                        loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default());
                    },
                    _ => call_malformed_plugin_attribute(sess, attr.span),
                }
            }
        }
    }

    if let Some(plugins) = addl_plugins {
        for plugin in plugins {
            loader.load_plugin(DUMMY_SP, &plugin, vec![]);
        }
    }

    loader.plugins
}

impl<'a> PluginLoader<'a> {
    fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
        PluginLoader {
            sess,
            reader: CrateLoader::new(sess, cstore, crate_name),
            plugins: vec![],
        }
    }

    fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
        let registrar = self.reader.find_plugin_registrar(span, name);

        if let Some((lib, disambiguator)) = registrar {
            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
            let fun = self.dylink_registrar(span, lib, symbol);
            self.plugins.push(PluginRegistrar {
                fun,
                args,
            });
        }
    }

    // Dynamically link a registrar function into the compiler process.
    fn dylink_registrar(&mut self,
                        span: Span,
                        path: PathBuf,
                        symbol: String) -> PluginRegistrarFun {
        use rustc_metadata::dynamic_lib::DynamicLibrary;

        // Make sure the path contains a / or the linker will search for it.
        let path = env::current_dir().unwrap().join(&path);

        let lib = match DynamicLibrary::open(Some(&path)) {
            Ok(lib) => lib,
            // this is fatal: there are almost certainly macros we need
            // inside this crate, so continue would spew "macro undefined"
            // errors
            Err(err) => {
                self.sess.span_fatal(span, &err)
            }
        };

        unsafe {
            let registrar =
                match lib.symbol(&symbol) {
                    Ok(registrar) => {
                        mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
                    }
                    // again fatal if we can't register macros
                    Err(err) => {
                        self.sess.span_fatal(span, &err)
                    }
                };

            // Intentionally leak the dynamic library. We can't ever unload it
            // since the library can make things that will live arbitrarily long
            // (e.g., an @-box cycle or a thread).
            mem::forget(lib);

            registrar
        }
    }
}
