Commit 39867fec authored by Asahi Lina's avatar Asahi Lina Committed by Miguel Ojeda

rust: macros: Allow specifying multiple module aliases

Modules can (and usually do) have multiple alias tags, in order to
specify multiple possible device matches for autoloading. Allow this by
changing the alias ModuleInfo field to an Option<Vec<String>>.

Note: For normal device IDs this is autogenerated by modpost (which is
not properly integrated with Rust support yet), so it is useful to be
able to manually add device match aliases for now, and should still be
useful in the future for corner cases that modpost does not handle.

This pulls in the expect_group() helper from the rfl/rust branch
(with credit to authors).
Co-developed-by: default avatarMiguel Ojeda <ojeda@kernel.org>
Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
Co-developed-by: default avatarFinn Behrens <me@kloenk.dev>
Signed-off-by: default avatarFinn Behrens <me@kloenk.dev>
Co-developed-by: default avatarSumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: default avatarSumera Priyadarsini <sylphrenadin@gmail.com>
Reviewed-by: default avatarVincenzo Palazzo <vincenzopalazzodev@gmail.com>
Signed-off-by: default avatarAsahi Lina <lina@asahilina.net>
Link: https://lore.kernel.org/r/20230224-rust-macros-v2-1-7396e8b7018d@asahilina.netSigned-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent 318c3cc8
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
use proc_macro::{token_stream, TokenTree}; use proc_macro::{token_stream, Group, TokenTree};
pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> { pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
if let Some(TokenTree::Ident(ident)) = it.next() { if let Some(TokenTree::Ident(ident)) = it.next() {
...@@ -56,6 +56,14 @@ pub(crate) fn expect_string_ascii(it: &mut token_stream::IntoIter) -> String { ...@@ -56,6 +56,14 @@ pub(crate) fn expect_string_ascii(it: &mut token_stream::IntoIter) -> String {
string string
} }
pub(crate) fn expect_group(it: &mut token_stream::IntoIter) -> Group {
if let TokenTree::Group(group) = it.next().expect("Reached end of token stream for Group") {
group
} else {
panic!("Expected Group");
}
}
pub(crate) fn expect_end(it: &mut token_stream::IntoIter) { pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
if it.next().is_some() { if it.next().is_some() {
panic!("Expected end"); panic!("Expected end");
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
use crate::helpers::*; use crate::helpers::*;
use proc_macro::{token_stream, Literal, TokenStream, TokenTree}; use proc_macro::{token_stream, Delimiter, Literal, TokenStream, TokenTree};
use std::fmt::Write; use std::fmt::Write;
fn expect_string_array(it: &mut token_stream::IntoIter) -> Vec<String> {
let group = expect_group(it);
assert_eq!(group.delimiter(), Delimiter::Bracket);
let mut values = Vec::new();
let mut it = group.stream().into_iter();
while let Some(val) = try_string(&mut it) {
assert!(val.is_ascii(), "Expected ASCII string");
values.push(val);
match it.next() {
Some(TokenTree::Punct(punct)) => assert_eq!(punct.as_char(), ','),
None => break,
_ => panic!("Expected ',' or end of array"),
}
}
values
}
struct ModInfoBuilder<'a> { struct ModInfoBuilder<'a> {
module: &'a str, module: &'a str,
counter: usize, counter: usize,
...@@ -78,7 +96,7 @@ struct ModuleInfo { ...@@ -78,7 +96,7 @@ struct ModuleInfo {
name: String, name: String,
author: Option<String>, author: Option<String>,
description: Option<String>, description: Option<String>,
alias: Option<String>, alias: Option<Vec<String>>,
} }
impl ModuleInfo { impl ModuleInfo {
...@@ -112,7 +130,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self { ...@@ -112,7 +130,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
"author" => info.author = Some(expect_string(it)), "author" => info.author = Some(expect_string(it)),
"description" => info.description = Some(expect_string(it)), "description" => info.description = Some(expect_string(it)),
"license" => info.license = expect_string_ascii(it), "license" => info.license = expect_string_ascii(it),
"alias" => info.alias = Some(expect_string_ascii(it)), "alias" => info.alias = Some(expect_string_array(it)),
_ => panic!( _ => panic!(
"Unknown key \"{}\". Valid keys are: {:?}.", "Unknown key \"{}\". Valid keys are: {:?}.",
key, EXPECTED_KEYS key, EXPECTED_KEYS
...@@ -163,8 +181,10 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { ...@@ -163,8 +181,10 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
modinfo.emit("description", &description); modinfo.emit("description", &description);
} }
modinfo.emit("license", &info.license); modinfo.emit("license", &info.license);
if let Some(alias) = info.alias { if let Some(aliases) = info.alias {
modinfo.emit("alias", &alias); for alias in aliases {
modinfo.emit("alias", &alias);
}
} }
// Built-in modules also export the `file` modinfo string. // Built-in modules also export the `file` modinfo string.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment