Skip to content

Commit c10abf5

Browse files
committed
rust: cleanup modinfo generation in module!
Signed-off-by: Gary Guo <gary@garyguo.net>
1 parent c677a79 commit c10abf5

File tree

1 file changed

+84
-108
lines changed

1 file changed

+84
-108
lines changed

rust/macros/module.rs

Lines changed: 84 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -113,91 +113,83 @@ fn get_string(it: &mut Cursor<'_>, expected_name: &str) -> String {
113113
byte_string
114114
}
115115

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

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

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

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

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

178-
fn build_modinfo_string(module: &str, field: &str, content: &str) -> String {
179-
build_modinfo_string_only_builtin(module, field, content)
180-
+ &build_modinfo_string_only_loadable(module, field, content)
181-
}
174+
fn emit_only_loadable(&mut self, field: &str, content: &str) {
175+
self.emit_base(field, content, false)
176+
}
182177

183-
fn build_modinfo_string_optional(module: &str, field: &str, content: Option<&str>) -> String {
184-
if let Some(content) = content {
185-
build_modinfo_string(module, field, content)
186-
} else {
187-
"".to_string()
178+
fn emit(&mut self, field: &str, content: &str) {
179+
self.emit_only_builtin(field, content);
180+
self.emit_only_loadable(field, content);
188181
}
189-
}
190182

191-
fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &str) -> String {
192-
let variable = format!(
193-
"__{module}_{field}_{param}",
194-
module = module,
195-
field = field,
196-
param = param
197-
);
198-
let content = format!("{param}:{content}", param = param, content = content);
199-
__build_modinfo_string_base(module, field, &content, &variable, true)
200-
+ &__build_modinfo_string_base(module, field, &content, &variable, false)
183+
fn emit_optional(&mut self, field: &str, content: Option<&str>) {
184+
if let Some(content) = content {
185+
self.emit(field, content);
186+
}
187+
}
188+
189+
fn emit_param(&mut self, field: &str, param: &str, content: &str) {
190+
let content = format!("{param}:{content}", param = param, content = content);
191+
self.emit(field, &content);
192+
}
201193
}
202194

203195
fn permissions_are_readonly(perms: &str) -> bool {
@@ -395,8 +387,18 @@ pub fn module(ts: TokenStream) -> TokenStream {
395387

396388
let name = info.name.clone();
397389

390+
let mut modinfo = ModInfoBuilder::new(&name);
391+
modinfo.emit_optional("author", info.author.as_deref());
392+
modinfo.emit_optional("description", info.description.as_deref());
393+
modinfo.emit("license", &info.license);
394+
modinfo.emit_optional("alias", info.alias.as_deref());
395+
396+
// Built-in modules also export the `file` modinfo string
397+
let file =
398+
std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
399+
modinfo.emit_only_builtin("file", &file);
400+
398401
let mut array_types_to_generate = Vec::new();
399-
let mut params_modinfo = String::new();
400402
if let Some(params) = info.params {
401403
let mut it = params;
402404

@@ -436,18 +438,8 @@ pub fn module(ts: TokenStream) -> TokenStream {
436438
}
437439
};
438440

439-
params_modinfo.push_str(&build_modinfo_string_param(
440-
&name,
441-
"parmtype",
442-
&param_name,
443-
&param_kernel_type,
444-
));
445-
params_modinfo.push_str(&build_modinfo_string_param(
446-
&name,
447-
"parm",
448-
&param_name,
449-
&param_description,
450-
));
441+
modinfo.emit_param("parmtype", &param_name, &param_kernel_type);
442+
modinfo.emit_param("parm", &param_name, &param_description);
451443
let param_type_internal = match param_type {
452444
ParamType::Ident(ref param_type) => match param_type.as_ref() {
453445
"str" => "kernel::module_param::StringParam".to_string(),
@@ -496,7 +488,7 @@ pub fn module(ts: TokenStream) -> TokenStream {
496488
name = name,
497489
param_name = param_name,
498490
);
499-
params_modinfo.push_str(
491+
modinfo.buffer.push_str(
500492
&format!(
501493
"
502494
static mut __{name}_{param_name}_value: {param_type_internal} = {param_default};
@@ -572,9 +564,6 @@ pub fn module(ts: TokenStream) -> TokenStream {
572564
));
573565
}
574566

575-
let file =
576-
std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
577-
578567
format!(
579568
"
580569
/// The module name.
@@ -654,26 +643,13 @@ pub fn module(ts: TokenStream) -> TokenStream {
654643
}}
655644
}}
656645
657-
{author}
658-
{description}
659-
{license}
660-
{alias}
661-
662-
// Built-in modules also export the `file` modinfo string
663-
{file}
664-
665-
{params_modinfo}
646+
{modinfo}
666647
667648
{generated_array_types}
668649
",
669650
type_ = info.type_,
670651
name = info.name,
671-
author = &build_modinfo_string_optional(&name, "author", info.author.as_deref()),
672-
description = &build_modinfo_string_optional(&name, "description", info.description.as_deref()),
673-
license = &build_modinfo_string(&name, "license", &info.license),
674-
alias = &build_modinfo_string_optional(&name, "alias", info.alias.as_deref()),
675-
file = &build_modinfo_string_only_builtin(&name, "file", &file),
676-
params_modinfo = params_modinfo,
652+
modinfo = modinfo.buffer,
677653
generated_array_types = generated_array_types,
678654
initcall_section = ".initcall6.init"
679655
).parse().expect("Error parsing formatted string into token stream.")

0 commit comments

Comments
 (0)