55extern crate proc_macro;
66use self :: proc_macro:: TokenStream ;
77use quote:: quote;
8+ use std:: collections:: HashSet ;
89use syn:: parse_macro_input;
910
1011/// `input` contains a single identifier, corresponding to a user-defined macro.
@@ -13,22 +14,26 @@ use syn::parse_macro_input;
1314/// See tests/analyze or below for the API.
1415#[ proc_macro]
1516pub fn for_each_api ( input : TokenStream ) -> TokenStream {
17+ let input = parse_macro_input ! ( input as Input ) ;
1618 let files = get_libm_files ( ) ;
17- let functions = get_functions ( & files) ;
18- let input = parse_macro_input ! ( input as syn:: Ident ) ;
19+ let functions = get_functions ( & files, & input. ignored ) ;
1920 let mut tokens = proc_macro2:: TokenStream :: new ( ) ;
21+ let input_macro = input. macro_id ;
2022 for function in functions {
2123 let id = function. ident ;
24+ let api_kind = function. api_kind ;
2225 let ret_ty = function. ret_ty ;
2326 let arg_tys = function. arg_tys ;
2427 let arg_ids = get_arg_ids ( arg_tys. len ( ) ) ;
2528 let t = quote ! {
26- #input ! {
29+ #input_macro ! {
2730 id: #id;
31+ api_kind: #api_kind;
2832 arg_tys: #( #arg_tys) , * ;
2933 arg_ids: #( #arg_ids) , * ;
3034 ret_ty: #ret_ty;
3135 }
36+
3237 } ;
3338 tokens. extend ( t) ;
3439 }
@@ -78,6 +83,7 @@ fn get_libm_files() -> Vec<syn::File> {
7883/// Function signature that will be expanded for the user macro.
7984struct FnSig {
8085 ident : syn:: Ident ,
86+ api_kind : syn:: Ident ,
8187 c_abi : bool ,
8288 ret_ty : Option < syn:: Type > ,
8389 arg_tys : Vec < syn:: Type > ,
@@ -101,7 +107,7 @@ macro_rules! syn_to_str {
101107
102108/// Extracts all public functions from the libm files while
103109/// doing some sanity checks on the function signatures.
104- fn get_functions ( files : & [ syn:: File ] ) -> Vec < FnSig > {
110+ fn get_functions ( files : & [ syn:: File ] , ignored : & Option < HashSet < String > > ) -> Vec < FnSig > {
105111 let mut error = false ;
106112 let mut functions = Vec :: new ( ) ;
107113 // Traverse all files matching function items
@@ -122,10 +128,17 @@ fn get_functions(files: &[syn::File]) -> Vec<FnSig> {
122128 // Build a function signature while doing some sanity checks
123129 let mut fn_sig = FnSig {
124130 ident : ident. clone ( ) ,
131+ api_kind : to_api_kind ( ident. clone ( ) ) ,
125132 c_abi : false ,
126133 arg_tys : Vec :: new ( ) ,
127134 ret_ty : None ,
128135 } ;
136+ // Skip ignored functions:
137+ if let Some ( ignored) = ignored {
138+ if ignored. contains ( & fn_sig. name ( ) ) {
139+ continue ;
140+ }
141+ }
129142 macro_rules! err {
130143 ( $msg: expr) => { {
131144 #[ cfg( feature = "analyze" ) ]
@@ -300,3 +313,48 @@ fn get_arg_ids(len: usize) -> Vec<syn::Ident> {
300313 }
301314 ids
302315}
316+
317+ /// Returns the ApiKind enum variant for this function
318+ fn to_api_kind ( id : syn:: Ident ) -> syn:: Ident {
319+ let name = syn_to_str ! ( id) ;
320+ let first = name. chars ( ) . nth ( 0 ) . unwrap ( ) ;
321+ let first_upper = first. to_uppercase ( ) . nth ( 0 ) . unwrap ( ) ;
322+ let name = name. replacen ( first, & first_upper. to_string ( ) , 1 ) ;
323+ syn:: Ident :: new ( & name, proc_macro2:: Span :: call_site ( ) )
324+ }
325+
326+ #[ derive( Debug ) ]
327+ struct Input {
328+ macro_id : syn:: Ident ,
329+ ignored : Option < HashSet < String > > ,
330+ }
331+
332+ impl syn:: parse:: Parse for Input {
333+ fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
334+ let content;
335+ let macro_id: syn:: Ident = input. parse ( ) ?;
336+ let lookahead = input. lookahead1 ( ) ;
337+ if lookahead. peek ( syn:: token:: Paren ) {
338+ let _paren_token = syn:: parenthesized!( content in input) ;
339+ let ignored: syn:: Lit = content. parse :: < syn:: Lit > ( ) ?;
340+ if let syn:: Lit :: Str ( c) = ignored {
341+ let s = c. value ( ) ;
342+ let mut hash_set = HashSet :: < String > :: new ( ) ;
343+ for i in s. split ( "," ) {
344+ hash_set. insert ( i. to_string ( ) ) ;
345+ }
346+ Ok ( Input {
347+ macro_id : macro_id,
348+ ignored : Some ( hash_set) ,
349+ } )
350+ } else {
351+ Err ( lookahead. error ( ) )
352+ }
353+ } else {
354+ Ok ( Input {
355+ macro_id : macro_id,
356+ ignored : None ,
357+ } )
358+ }
359+ }
360+ }
0 commit comments