@@ -21,6 +21,7 @@ use std::collections::HashSet;
2121use syntax:: ast;
2222use syntax:: attr;
2323use syntax:: parse:: token;
24+ use syntax:: ptr:: P ;
2425use syntax:: visit;
2526use syntax:: visit:: Visitor ;
2627use syntax:: attr:: AttrMetaMethods ;
@@ -29,12 +30,17 @@ use syntax::attr::AttrMetaMethods;
2930pub type PluginRegistrarFun =
3031 fn ( & mut Registry ) ;
3132
33+ pub struct PluginRegistrar {
34+ pub fun : PluginRegistrarFun ,
35+ pub args : P < ast:: MetaItem > ,
36+ }
37+
3238/// Information about loaded plugins.
3339pub struct Plugins {
3440 /// Imported macros.
3541 pub macros : Vec < ast:: MacroDef > ,
3642 /// Registrars, as function pointers.
37- pub registrars : Vec < PluginRegistrarFun > ,
43+ pub registrars : Vec < PluginRegistrar > ,
3844}
3945
4046struct PluginLoader < ' a > {
@@ -87,7 +93,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
8793 }
8894
8995 // Parse the attributes relating to macro / plugin loading.
90- let mut load_registrar = false ;
96+ let mut plugin_attr = None ;
9197 let mut macro_selection = Some ( HashSet :: new ( ) ) ; // None => load all
9298 let mut reexport = HashSet :: new ( ) ;
9399 for attr in vi. attrs . iter ( ) {
@@ -97,7 +103,12 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
97103 self . sess . span_err ( attr. span , "#[phase] is deprecated; use \
98104 #[macro_use], #[plugin], and/or #[no_link]") ;
99105 }
100- "plugin" => load_registrar = true ,
106+ "plugin" => {
107+ if plugin_attr. is_some ( ) {
108+ self . sess . span_err ( attr. span , "#[plugin] specified multiple times" ) ;
109+ }
110+ plugin_attr = Some ( attr. node . value . clone ( ) ) ;
111+ }
101112 "macro_use" => {
102113 let names = attr. meta_item_list ( ) ;
103114 if names. is_none ( ) {
@@ -145,6 +156,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
145156 Some ( sel) => sel. len ( ) != 0 || reexport. len ( ) != 0 ,
146157 None => true ,
147158 } ;
159+ let load_registrar = plugin_attr. is_some ( ) ;
148160
149161 if load_macros || load_registrar {
150162 let pmd = self . reader . read_plugin_metadata ( vi) ;
@@ -167,7 +179,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
167179 }
168180
169181 if let Some ( ( lib, symbol) ) = registrar {
170- self . dylink_registrar ( vi, lib, symbol) ;
182+ let fun = self . dylink_registrar ( vi, lib, symbol) ;
183+ self . plugins . registrars . push ( PluginRegistrar {
184+ fun : fun,
185+ args : plugin_attr. unwrap ( ) ,
186+ } ) ;
171187 }
172188 }
173189
@@ -179,7 +195,10 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
179195
180196impl < ' a > PluginLoader < ' a > {
181197 // Dynamically link a registrar function into the compiler process.
182- fn dylink_registrar ( & mut self , vi : & ast:: ViewItem , path : Path , symbol : String ) {
198+ fn dylink_registrar ( & mut self ,
199+ vi : & ast:: ViewItem ,
200+ path : Path ,
201+ symbol : String ) -> PluginRegistrarFun {
183202 // Make sure the path contains a / or the linker will search for it.
184203 let path = os:: make_absolute ( & path) . unwrap ( ) ;
185204
@@ -201,13 +220,12 @@ impl<'a> PluginLoader<'a> {
201220 Err ( err) => self . sess . span_fatal ( vi. span , err[ ] )
202221 } ;
203222
204- self . plugins . registrars . push ( registrar) ;
205-
206223 // Intentionally leak the dynamic library. We can't ever unload it
207224 // since the library can make things that will live arbitrarily long
208225 // (e.g. an @-box cycle or a task).
209226 mem:: forget ( lib) ;
210227
228+ registrar
211229 }
212230 }
213231}
0 commit comments