1use proc_macro::TokenStream;
2
3#[macro_use]
4mod errors;
5#[macro_use]
6mod logger;
7
8use quote::{ToTokens};
9
10use logger::{rsmemgen_debug_out,rsmemgen_log_get_timestamp};
11
12
13macro_rules! syn_error_fmt {
14 ($($a:expr),*) => {
15 let cerr = format!($($a),*);
16 eprintln!("{}",cerr);
17 rsmemgen_log_error!("{}",cerr);
18 return cerr.parse().unwrap();
19 }
24}
25
26
27#[allow(unused_assignments)]
28#[proc_macro_attribute]
29pub fn rsmemgen_impl_inline(_args :TokenStream , input :TokenStream) -> TokenStream {
30 let mut implstruct : syn::ItemImpl ;
31
32 match std::env::var("RSMEMCHK_MODE") {
33 Ok(_v) => {},
34 Err(_e) => {
35 rsmemgen_log_trace!("retv\n{}",input.to_string());
37 return input;
38 },
39 }
40
41
42 match syn::parse::<syn::ItemImpl>(input.clone()) {
43 Ok(v) => {
44 implstruct = v.clone();
45 },
46 Err(_e) => {
47 syn_error_fmt!("not parse \n{}",input.to_string());
48 }
49 }
50
51 let mut idx :usize = 0;
52 while idx < implstruct.items.len() {
53 let item = implstruct.items[idx].clone();
54 let mut tk : TokenStream;
55 let mut newfn :Option<syn::ImplItemFn> = None;
56
57 match item {
58 syn::ImplItem::Fn(fnptr) => {
59 tk = fnptr.clone().into_token_stream().into();
60 rsmemgen_log_trace!("fnptr\n{}", tk.to_string());
61 let mut inlinematch :bool = false;
62
63 if fnptr.attrs.len() > 0 {
64 for a in fnptr.attrs.iter() {
65 tk = a.into_token_stream().into();
66 rsmemgen_log_trace!("a\n{}",tk.to_string());
67 match a.meta.clone() {
68 syn::Meta::List(l) => {
69 tk = l.path.into_token_stream().into();
72 rsmemgen_log_trace!("path\n{}",tk.to_string());
73 let pname = tk.to_string();
74 if pname == "inline" {
75 inlinematch = true;
76 }
77 },
78 _ => {
79 },
80 }
81 }
82 }
83 if !inlinematch {
84 newfn = Some(fnptr.clone());
85 let c :&mut syn::ImplItemFn = newfn.as_mut().unwrap();
86 let cp :syn::Attribute = syn::parse_quote! {
87 #[inline(never)]
88 };
89 c.attrs.push(cp.clone());
90 }
91 },
92 _ => {},
93
94 }
95
96 if newfn.is_some() {
97 implstruct.items[idx] = syn::ImplItem::Fn(newfn.as_ref().unwrap().clone());
98 }
99 idx += 1;
100 }
101
102 let retv :TokenStream = implstruct.into_token_stream().into();
103 rsmemgen_log_trace!("retv\n{}",retv.to_string());
104
105 return retv;
106}
107
108#[proc_macro_attribute]
109pub fn rsmemgen_func_inline(_args :TokenStream , input :TokenStream) -> TokenStream {
110 let mut fnstruct : syn::ItemFn ;
111
112 match std::env::var("RSMEMCHK_MODE") {
113 Ok(_v) => {},
114 Err(_e) => {
115 rsmemgen_log_trace!("retv\n{}",input.to_string());
117 return input;
118 },
119 }
120
121
122 match syn::parse::<syn::ItemFn>(input.clone()) {
123 Ok(v) => {
124 fnstruct = v.clone();
125 },
126 Err(_e) => {
127 syn_error_fmt!("not parse \n{}",input.to_string());
128 }
129 }
130
131 let mut matched :bool = false;
132 let mut idx :usize = 0;
133 while idx < fnstruct.attrs.len() {
134 let a :syn::Attribute = fnstruct.attrs[idx].clone();
135 let mut tk : TokenStream;
136 tk = a.clone().into_token_stream().into();
137 rsmemgen_log_trace!("a\n{}",tk.to_string());
138 match a.meta.clone() {
139 syn::Meta::List(l) => {
140 tk = l.path.into_token_stream().into();
143 rsmemgen_log_trace!("path\n{}",tk.to_string());
144 let pname = tk.to_string();
145 if pname == "inline" {
146 matched = true;
147 break;
148 }
149 },
150 _ => {
151 },
152 }
153 idx += 1;
154 }
155
156 if !matched {
157 let cp :syn::Attribute = syn::parse_quote! {
158 #[inline(never)]
159 };
160 fnstruct.attrs.push(cp.clone());
161 }
162
163
164 let retv :TokenStream = fnstruct.into_token_stream().into();
165 rsmemgen_log_trace!("retv\n{}",retv.to_string());
166 return retv;
167}