diff --git a/src/uucore/src/uucore_procs/src/lib.rs b/src/uucore/src/uucore_procs/src/lib.rs index cf675a5ab..9b49314f6 100644 --- a/src/uucore/src/uucore_procs/src/lib.rs +++ b/src/uucore/src/uucore_procs/src/lib.rs @@ -1,9 +1,10 @@ extern crate proc_macro; -// spell-checker:ignore () sigpipe uucore uumain +// spell-checker:ignore () SIGPIPE uucore uumain uutils -// ref: @@ -// ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ +//## rust proc-macro background info +//* ref: @@ +//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ struct Tokens { expr: syn::Expr, @@ -17,30 +18,29 @@ impl syn::parse::Parse for Tokens { } } +// main!( EXPR ) +// generates a `main()` function for utilities within the uutils group +// EXPR == syn::Expr::Lit::String | syn::Expr::Path::Ident ~ EXPR contains the location of the utility `uumain()` function +//* for future use of "eager" macros and more generic use, EXPR may be in either STRING or IDENT form +//* for ease-of-use, the trailing "::uumain" is optional and will be added if needed #[proc_macro] pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream { let Tokens { expr } = syn::parse_macro_input!(stream as Tokens); - // eprintln!("expr={:?}", expr); + // match EXPR as a string literal or an ident path, o/w panic!() let expr = match expr { - syn::Expr::Lit(expr) => { - // eprintln!("found Expr::Lit => {:?}", expr); - match expr.lit { - syn::Lit::Str(ref lit) => { - let mut s = lit.value(); - if !s.ends_with("::uumain") { - s += "::uumain"; - } - syn::LitStr::new(&s, proc_macro2::Span::call_site()) - .parse() - .unwrap() + syn::Expr::Lit(expr) => match expr.lit { + syn::Lit::Str(ref lit) => { + let mut s = lit.value(); + if !s.ends_with("::uumain") { + s += "::uumain"; } - _ => panic!(), + syn::LitStr::new(&s, proc_macro2::Span::call_site()) + .parse() + .unwrap() } - } + _ => panic!(), + }, syn::Expr::Path(expr) => { - // eprintln!("found Expr::Path => {:?}", expr); - // let i = &expr.path.segments.last().unwrap().ident; - // eprintln!("... i => {:?}", i); if &expr.path.segments.last().unwrap().ident.to_string() != "uumain" { syn::parse_quote!( #expr::uumain ) } else { @@ -50,13 +50,13 @@ pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream { _ => panic!(), }; let f = quote::quote! { #expr(uucore::args().collect()) }; - // eprintln!("f = {:?}", f); + // generate a uutils utility `main()` function, tailored for the calling utility let result = quote::quote! { fn main() { use std::io::Write; - uucore::panic::mute_sigpipe_panic(); - let code = #f; - std::io::stdout().flush().expect("could not flush stdout"); + uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics + let code = #f; // execute utility code + std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see std::process::exit(code); } };