1#![warn(missing_docs)]
6
7use proc_macro::TokenStream;
8use proc_macro2::TokenTree;
9use quote::{quote, ToTokens};
10
11#[proc_macro_attribute]
23pub fn winmain(a: TokenStream, b: TokenStream) -> TokenStream {
24 if !a.is_empty() {
25 return quote! {
26 compile_error!("winmain attribute does not take any parameters");
27 }.into()
28 };
29
30 let Ok(tokens) = syn::parse::<syn::ItemFn>(b.clone()) else {
31 return b;
32 };
33
34 let rval = tokens.sig.output.into_token_stream();
35 let function_name = &tokens.sig.ident;
36
37 let handle_rval = if !rval.is_empty() && rval.to_string() != "()" {
38 TokenTree::Ident(proc_macro2::Ident::new("_rval", proc_macro2::Span::call_site()))
39 }
40 else {
41 TokenTree::Literal(proc_macro2::Literal::i32_suffixed(0))
42 };
43
44 let inputs = tokens.sig.inputs.to_token_stream();
45 let function_call = if inputs.is_empty() {
46 quote! { super::#function_name () }
47 }
48 else {
49 quote! {
50 super::#function_name (
51 _hInstance as min32::HINSTANCE,
52 _hPrevInstance as min32::HINSTANCE,
53 _commandLine,
54 _nShowCmd
55 )
56 }
57 };
58
59 let winmain: TokenStream = quote! {
60 mod __private_winmain_impl {
61 #[unsafe(no_mangle)]
62 extern "system" fn WinMain(
63 _hInstance: min32::HINSTANCE,
64 _hPrevInstance: min32::HINSTANCE,
65 _commandLine: *const core::ffi::c_char,
66 _nShowCmd: core::ffi::c_int
67 ) -> core::ffi::c_int {
68 let _rval = unsafe { #function_call };
69 #handle_rval as core::ffi::c_int
70 }
71 }
72 }.into();
73
74 TokenStream::from_iter([winmain, b].into_iter())
75}
76
77
78#[proc_macro_attribute]
89pub fn dllmain(a: TokenStream, b: TokenStream) -> TokenStream {
90 if !a.is_empty() {
91 return quote! {
92 compile_error!("dllmain attribute does not take any parameters")
93 }.into()
94 };
95
96 let Ok(tokens) = syn::parse::<syn::ItemFn>(b.clone()) else {
97 return b;
98 };
99
100 let rval = tokens.sig.output.into_token_stream();
101 let function_name = &tokens.sig.ident;
102
103 let inputs = tokens.sig.inputs.to_token_stream();
104 if inputs.is_empty() {
105 return quote! {
106 compile_error!("DllMain functions must take three parameters");
107 }.into()
108 };
109
110 let handle_rval = if !rval.is_empty() && rval.to_string() != "()" {
111 quote! { _rval as i32 }
112 }
113 else {
114 TokenTree::Literal(proc_macro2::Literal::i32_suffixed(1)).to_token_stream()
115 };
116
117 let function_call = quote! {
118 super::#function_name (
119 _hInstance as min32::HINSTANCE,
120 _fdwReason,
121 _lpvReserved
122 )
123 };
124
125 let dllmain: TokenStream = quote! {
126 mod __private_dllmain_impl {
127 #[unsafe(no_mangle)]
128 extern "system" fn DllMain(
129 _hInstance: usize,
130 _fdwReason: u32,
131 _lpvReserved: *mut core::ffi::c_void
132 ) -> core::ffi::c_int {
133 let _rval = unsafe { #function_call };
134 #handle_rval
135 }
136 }
137 }.into();
138
139 TokenStream::from_iter([dllmain, b].into_iter())
140}