yuffie_proc_macros/
lib.rs1use proc_macro::TokenStream;
7use syn::spanned::Spanned;
8
9#[proc_macro_attribute]
36pub fn entry(args: TokenStream, stream: TokenStream) -> TokenStream {
37 let input = syn::parse_macro_input!(stream as syn::ItemFn);
38
39 if !args.is_empty() {
40 return syn::Error::new(input.span(), "attribute does not take any arguments")
41 .to_compile_error()
42 .into();
43 }
44
45 let attrs = &input.attrs;
46 let sig = &input.sig;
47 let ident = &sig.ident;
48 let block = &input.block;
49
50 if sig.constness.is_some() {
52 return syn::Error::new(sig.constness.span(), "entry point must not be `const`")
53 .to_compile_error()
54 .into();
55 }
56 if sig.asyncness.is_some() {
57 return syn::Error::new(sig.asyncness.span(), "entry point must not be `async`")
58 .to_compile_error()
59 .into();
60 }
61 if sig.unsafety.is_some() {
62 return syn::Error::new(sig.unsafety.span(), "entry point must not be `unsafe`")
63 .to_compile_error()
64 .into();
65 }
66 if sig.abi.is_some() {
67 return syn::Error::new(sig.abi.span(), "entry point must not declare an ABI")
68 .to_compile_error()
69 .into();
70 }
71 if !sig.generics.params.is_empty() {
72 return syn::Error::new(sig.span(), "entry point must not use generics")
73 .to_compile_error()
74 .into();
75 }
76 if sig.variadic.is_some() {
77 return syn::Error::new(sig.span(), "entry point must not be variadic")
78 .to_compile_error()
79 .into();
80 }
81
82 #[rustfmt::skip]
83 let tok = TokenStream::from(quote::quote! {
84 #(#attrs)*
85 #[export_name = "efi_main"]
86 extern "efiapi" #sig
87 #block
88
89 const _: ::yuffie::ImageEntryFn = #ident;
91 });
92
93 tok
94}