use proc_macro::TokenStream;
use syn::spanned::Spanned;
#[proc_macro_attribute]
pub fn entry(args: TokenStream, stream: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(stream as syn::ItemFn);
if !args.is_empty() {
return syn::Error::new(input.span(), "attribute does not take any arguments")
.to_compile_error()
.into();
}
let attrs = &input.attrs;
let sig = &input.sig;
let ident = &sig.ident;
let block = &input.block;
if sig.constness.is_some() {
return syn::Error::new(sig.constness.span(), "entry point must not be `const`")
.to_compile_error()
.into();
}
if sig.asyncness.is_some() {
return syn::Error::new(sig.asyncness.span(), "entry point must not be `async`")
.to_compile_error()
.into();
}
if sig.unsafety.is_some() {
return syn::Error::new(sig.unsafety.span(), "entry point must not be `unsafe`")
.to_compile_error()
.into();
}
if sig.abi.is_some() {
return syn::Error::new(sig.abi.span(), "entry point must not declare an ABI")
.to_compile_error()
.into();
}
if !sig.generics.params.is_empty() {
return syn::Error::new(sig.span(), "entry point must not use generics")
.to_compile_error()
.into();
}
if sig.variadic.is_some() {
return syn::Error::new(sig.span(), "entry point must not be variadic")
.to_compile_error()
.into();
}
#[rustfmt::skip]
let tok = TokenStream::from(quote::quote! {
#(#attrs)*
#[export_name = "efi_main"]
extern "efiapi" #sig
#block
const _: ::yuffie::ImageEntryFn = #ident;
});
tok
}