simavr_section_macro/
lib.rs1extern crate proc_macro;
20
21use proc_macro::TokenStream;
22use quote::quote;
23use syn::parse::{self, Parse, ParseStream};
24use syn::{parse_macro_input, Expr, Ident, LitByteStr, Token};
25
26struct StringInput {
27 tag: Ident,
28 string: LitByteStr,
29}
30
31impl Parse for StringInput {
32 fn parse(input: ParseStream) -> parse::Result<StringInput> {
33 let tag = input.parse()?;
34 input.parse::<Token![,]>()?;
35 let string = input.parse()?;
36 Ok(StringInput { tag, string })
37 }
38}
39
40#[proc_macro]
52pub fn avr_mcu_string(input: TokenStream) -> TokenStream {
53 let StringInput { tag, string } = parse_macro_input!(input as StringInput);
54
55 let value = string
56 .value()
57 .into_iter()
58 .chain(std::iter::repeat(0))
59 .take(64)
60 .collect::<Vec<_>>();
61
62 let name = Ident::new(&format!("_{}", tag), tag.span());
63
64 let array = quote! {
65 [
66 #(
67 #value
68 ),*
69 ]
70 };
71
72 quote!(
73 #[used]
74 #[no_mangle]
75 #[link_section = ".mmcu"]
76 pub static #name: ::simavr_section::bindings::avr_mmcu_string_t = ::simavr_section::bindings::avr_mmcu_string_t {
77 tag: ::simavr_section::bindings::#tag as _,
78 len: ::core::mem::size_of::<::simavr_section::bindings::avr_mmcu_string_t>() as u8 - 2,
79 string: #array,
80 };
81 ).into()
82}
83
84struct LongInput {
85 tag: Ident,
86 val: Expr,
87}
88
89impl Parse for LongInput {
90 fn parse(input: ParseStream) -> parse::Result<LongInput> {
91 let tag = input.parse()?;
92 input.parse::<Token![,]>()?;
93 let val = input.parse()?;
94 Ok(LongInput { tag, val })
95 }
96}
97
98#[proc_macro]
110pub fn avr_mcu_long(input: TokenStream) -> TokenStream {
111 let LongInput { tag, val } = parse_macro_input!(input as LongInput);
112
113 let name = Ident::new(&format!("_{}{}", tag, tag.span().start().line), tag.span());
114
115 quote!(
116 #[used]
117 #[no_mangle]
118 #[link_section = ".mmcu"]
119 pub static #name: ::simavr_section::bindings::avr_mmcu_long_t = ::simavr_section::bindings::avr_mmcu_long_t {
120 tag: ::simavr_section::bindings::#tag as _,
121 len: ::core::mem::size_of::<::simavr_section::bindings::avr_mmcu_long_t>() as u8 - 2,
122 val: #val,
123 };
124 ).into()
125}
126
127struct TraceInput {
128 tag: Ident,
129 mask: Expr,
130 what: Expr,
131 name: LitByteStr,
132}
133
134impl Parse for TraceInput {
135 fn parse(input: ParseStream) -> parse::Result<TraceInput> {
136 let tag = input.parse()?;
137 input.parse::<Token![,]>()?;
138 let mask = input.parse()?;
139 input.parse::<Token![,]>()?;
140 let what = input.parse()?;
141 input.parse::<Token![,]>()?;
142 let name = input.parse()?;
143 Ok(TraceInput {
144 tag,
145 mask,
146 what,
147 name,
148 })
149 }
150}
151
152#[proc_macro]
164pub fn avr_mcu_vcd_trace(input: TokenStream) -> TokenStream {
165 let TraceInput {
166 tag,
167 mask,
168 what,
169 name,
170 } = parse_macro_input!(input as TraceInput);
171
172 let id = Ident::new(&format!("_{}{}", tag, tag.span().start().line), tag.span());
173
174 let value = name
175 .value()
176 .into_iter()
177 .chain(std::iter::repeat(0))
178 .take(32)
179 .collect::<Vec<_>>();
180 let array = quote! {
181 [
182 #(
183 #value
184 ),*
185 ]
186 };
187
188 quote!(
189 #[used]
190 #[no_mangle]
191 #[link_section = ".mmcu"]
192 pub static #id: ::simavr_section::bindings::UnsafeVcdTrace = ::simavr_section::bindings::UnsafeVcdTrace(::simavr_section::bindings::avr_mmcu_vcd_trace_t {
193 tag: ::simavr_section::bindings::#tag as _,
194 len: ::core::mem::size_of::<::simavr_section::bindings::avr_mmcu_vcd_trace_t>() as u8 - 2,
195 mask: #mask,
196 what: #what as *mut ::simavr_section::bindings::libc::c_void,
197 name: #array,
198 });
199 ).into()
200}