Skip to content

Commit 9fe3ffa

Browse files
committed
rust: cleanup modinfo generation in module!
Signed-off-by: Gary Guo <[email protected]>
1 parent 5dd07d5 commit 9fe3ffa

File tree

1 file changed

+85
-109
lines changed

1 file changed

+85
-109
lines changed

rust/macros/module.rs

Lines changed: 85 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3-
use proc_macro::{token_stream, Delimiter, Group, TokenStream, TokenTree};
3+
use proc_macro::{token_stream, Delimiter, Group, Literal, TokenStream, TokenTree};
44

55
fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
66
if let Some(TokenTree::Ident(ident)) = it.next() {
@@ -110,91 +110,77 @@ fn get_byte_string(it: &mut token_stream::IntoIter, expected_name: &str) -> Stri
110110
byte_string
111111
}
112112

113-
fn __build_modinfo_string_base(
114-
module: &str,
115-
field: &str,
116-
content: &str,
117-
variable: &str,
118-
builtin: bool,
119-
) -> String {
120-
let string = if builtin {
121-
// Built-in modules prefix their modinfo strings by `module.`.
122-
format!(
123-
"{module}.{field}={content}",
124-
module = module,
125-
field = field,
126-
content = content
127-
)
128-
} else {
129-
// Loadable modules' modinfo strings go as-is.
130-
format!("{field}={content}", field = field, content = content)
131-
};
113+
struct ModInfoBuilder<'a> {
114+
module: &'a str,
115+
counter: usize,
116+
buffer: String,
117+
}
132118

133-
format!(
134-
"
135-
{cfg}
136-
#[link_section = \".modinfo\"]
137-
#[used]
138-
pub static {variable}: [u8; {length}] = *b\"{string}\\0\";
139-
",
140-
cfg = if builtin {
141-
"#[cfg(not(MODULE))]"
119+
impl<'a> ModInfoBuilder<'a> {
120+
fn new(module: &'a str) -> Self {
121+
ModInfoBuilder {
122+
module,
123+
counter: 0,
124+
buffer: String::new(),
125+
}
126+
}
127+
128+
fn emit_base(&mut self, field: &str, content: &str, builtin: bool) {
129+
use std::fmt::Write;
130+
131+
let string = if builtin {
132+
// Built-in modules prefix their modinfo strings by `module.`.
133+
format!(
134+
"{module}.{field}={content}\0",
135+
module = self.module,
136+
field = field,
137+
content = content
138+
)
142139
} else {
143-
"#[cfg(MODULE)]"
144-
},
145-
variable = variable,
146-
length = string.len() + 1,
147-
string = string,
148-
)
149-
}
140+
// Loadable modules' modinfo strings go as-is.
141+
format!("{field}={content}\0", field = field, content = content)
142+
};
150143

151-
fn __build_modinfo_string_variable(module: &str, field: &str) -> String {
152-
format!("__{module}_{field}", module = module, field = field)
153-
}
144+
write!(
145+
&mut self.buffer,
146+
"
147+
{cfg}
148+
#[link_section = \".modinfo\"]
149+
#[used]
150+
pub static __{module}_{counter}: [u8; {length}] = *{string};
151+
",
152+
cfg = if builtin {
153+
"#[cfg(not(MODULE))]"
154+
} else {
155+
"#[cfg(MODULE)]"
156+
},
157+
module = self.module,
158+
counter = self.counter,
159+
length = string.len(),
160+
string = Literal::byte_string(string.as_bytes()),
161+
)
162+
.unwrap();
154163

155-
fn build_modinfo_string_only_builtin(module: &str, field: &str, content: &str) -> String {
156-
__build_modinfo_string_base(
157-
module,
158-
field,
159-
content,
160-
&__build_modinfo_string_variable(module, field),
161-
true,
162-
)
163-
}
164+
self.counter += 1;
165+
}
164166

165-
fn build_modinfo_string_only_loadable(module: &str, field: &str, content: &str) -> String {
166-
__build_modinfo_string_base(
167-
module,
168-
field,
169-
content,
170-
&__build_modinfo_string_variable(module, field),
171-
false,
172-
)
173-
}
167+
fn emit_only_builtin(&mut self, field: &str, content: &str) {
168+
self.emit_base(field, content, true)
169+
}
174170

175-
fn build_modinfo_string(module: &str, field: &str, content: &str) -> String {
176-
build_modinfo_string_only_builtin(module, field, content)
177-
+ &build_modinfo_string_only_loadable(module, field, content)
178-
}
171+
fn emit_only_loadable(&mut self, field: &str, content: &str) {
172+
self.emit_base(field, content, false)
173+
}
179174

180-
fn build_modinfo_string_optional(module: &str, field: &str, content: Option<&str>) -> String {
181-
if let Some(content) = content {
182-
build_modinfo_string(module, field, content)
183-
} else {
184-
"".to_string()
175+
fn emit(&mut self, field: &str, content: &str) {
176+
self.emit_only_builtin(field, content);
177+
self.emit_only_loadable(field, content);
185178
}
186-
}
187179

188-
fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &str) -> String {
189-
let variable = format!(
190-
"__{module}_{field}_{param}",
191-
module = module,
192-
field = field,
193-
param = param
194-
);
195-
let content = format!("{param}:{content}", param = param, content = content);
196-
__build_modinfo_string_base(module, field, &content, &variable, true)
197-
+ &__build_modinfo_string_base(module, field, &content, &variable, false)
180+
fn emit_param(&mut self, field: &str, param: &str, content: &str) {
181+
let content = format!("{param}:{content}", param = param, content = content);
182+
self.emit(field, &content);
183+
}
198184
}
199185

200186
fn permissions_are_readonly(perms: &str) -> bool {
@@ -397,8 +383,24 @@ pub fn module(ts: TokenStream) -> TokenStream {
397383

398384
let name = info.name.clone();
399385

386+
let mut modinfo = ModInfoBuilder::new(&name);
387+
if let Some(author) = info.author {
388+
modinfo.emit("author", &author);
389+
}
390+
if let Some(description) = info.description {
391+
modinfo.emit("description", &description);
392+
}
393+
modinfo.emit("license", &info.license);
394+
if let Some(alias) = info.alias {
395+
modinfo.emit("alias", &alias);
396+
}
397+
398+
// Built-in modules also export the `file` modinfo string
399+
let file =
400+
std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
401+
modinfo.emit_only_builtin("file", &file);
402+
400403
let mut array_types_to_generate = Vec::new();
401-
let mut params_modinfo = String::new();
402404
if let Some(params) = info.params {
403405
assert_eq!(params.delimiter(), Delimiter::Brace);
404406

@@ -443,18 +445,8 @@ pub fn module(ts: TokenStream) -> TokenStream {
443445
}
444446
};
445447

446-
params_modinfo.push_str(&build_modinfo_string_param(
447-
&name,
448-
"parmtype",
449-
&param_name,
450-
&param_kernel_type,
451-
));
452-
params_modinfo.push_str(&build_modinfo_string_param(
453-
&name,
454-
"parm",
455-
&param_name,
456-
&param_description,
457-
));
448+
modinfo.emit_param("parmtype", &param_name, &param_kernel_type);
449+
modinfo.emit_param("parm", &param_name, &param_description);
458450
let param_type_internal = match param_type {
459451
ParamType::Ident(ref param_type) => match param_type.as_ref() {
460452
"str" => "kernel::module_param::StringParam".to_string(),
@@ -503,7 +495,7 @@ pub fn module(ts: TokenStream) -> TokenStream {
503495
name = name,
504496
param_name = param_name,
505497
);
506-
params_modinfo.push_str(
498+
modinfo.buffer.push_str(
507499
&format!(
508500
"
509501
static mut __{name}_{param_name}_value: {param_type_internal} = {param_default};
@@ -579,9 +571,6 @@ pub fn module(ts: TokenStream) -> TokenStream {
579571
));
580572
}
581573

582-
let file =
583-
std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
584-
585574
format!(
586575
"
587576
/// The module name.
@@ -661,26 +650,13 @@ pub fn module(ts: TokenStream) -> TokenStream {
661650
}}
662651
}}
663652
664-
{author}
665-
{description}
666-
{license}
667-
{alias}
668-
669-
// Built-in modules also export the `file` modinfo string
670-
{file}
671-
672-
{params_modinfo}
653+
{modinfo}
673654
674655
{generated_array_types}
675656
",
676657
type_ = info.type_,
677658
name = info.name,
678-
author = &build_modinfo_string_optional(&name, "author", info.author.as_deref()),
679-
description = &build_modinfo_string_optional(&name, "description", info.description.as_deref()),
680-
license = &build_modinfo_string(&name, "license", &info.license),
681-
alias = &build_modinfo_string_optional(&name, "alias", info.alias.as_deref()),
682-
file = &build_modinfo_string_only_builtin(&name, "file", &file),
683-
params_modinfo = params_modinfo,
659+
modinfo = modinfo.buffer,
684660
generated_array_types = generated_array_types,
685661
initcall_section = ".initcall6.init"
686662
).parse().expect("Error parsing formatted string into token stream.")

0 commit comments

Comments
 (0)