summaryrefslogtreecommitdiffstats
path: root/rust/syn/mac.rs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-24 08:46:03 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-24 08:46:03 -0700
commitcf9610f9116d55c5a66ef9f1faecacabd93a9322 (patch)
tree757a3d280760c654767631cab5ad8af2d86d1848 /rust/syn/mac.rs
downloadlinux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.tar.gz
linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.zip
Merge tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrlgrafted
Pull pin control updates from Linus Walleij: "Core changes: - Use the non-blocking mux_state_try_select() in the generic MUX pin control back-end - Free pin maps on pinctrl_generic_to_map() failure in the core helpers New hardware pin control: - Qualcomm Maili TLMM SoC, PMG1110 PMIC, and Eliza LPASS LPI TLMM SoC (this is for the low power audio, LPASS = Low Power Audio SubSystem portions) - Upboard support on top of the Intel pin controller - Apple T6030 and T6031 support (just compatible strings) - Samsung Exynos 8855 SoC - Mediatek MT6858 SoC - Rockchip RK3308B and RV1106 SoCs - Airoha EN7523 and AN7563 SoCs Improvements: - Qualcomm TLMM GPIOs are unconditionally marked as wakeup capable - Qualcomm improvements on top of the Qualcomm PDC (power domain controller) irqchip improvements from tglx:s tree - Qualcomm IPQ806x and IPQ9650 non-urgent pin grop fixups - The NPCM8xx driver has been put into shape fixing many pin and group definitions - Some non-urgent Tegra 264 pin assignments are fixed up - Some non-urgent fixups to Airoha AN7581 and AN7583 registers and pin assignments, missing features etc" * tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (130 commits) dt-bindings: pinctrl: Convert TI DA850 pupd to DT schema pinctrl: meson: sync some modify from A4 pinctrl: meson: a4: Add input enable pin configuration pinctrl: realtek: rtd1625: remove unused group name spdif_sel pinctrl: realtek: rtd1625: fix base_bit for VE4 GPIO 13 dt-bindings: pinctrl: microchip,pic32mzda-pinctrl: Convert to DT schema Revert "Merge branch 'ib-rsk7204' into devel" pinctrl: rockchip: Add RV1106 pinctrl support dt-bindings: pinctrl: rockchip: Add RV1106 compatible pinctrl: rockchip: Decode drive strength in the get function pinctrl: fix PINCTRL_GENERIC_MUX not always being selectable pinctrl: airoha: add support of an7563 SoC dt-bindings: pinctrl: airoha: add support of an7563 pin controller pinctrl: airoha: try to find chip scu node by phandle first pinctrl: airoha: add support of en7523 SoC dt-bindings: pinctrl: airoha: add support of en7523 pin controller pinctrl: airoha: an7583: add support for olt pinmux pinctrl: airoha: an7583: add support for pon_alt pinmux pinctrl: airoha: an7583: add support for npu_uart pinmux dt-bindings: pinctrl: airoha: an7583: add missed features ...
Diffstat (limited to 'rust/syn/mac.rs')
-rw-r--r--rust/syn/mac.rs227
1 files changed, 227 insertions, 0 deletions
diff --git a/rust/syn/mac.rs b/rust/syn/mac.rs
new file mode 100644
index 000000000..ce4b022b4
--- /dev/null
+++ b/rust/syn/mac.rs
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#[cfg(feature = "parsing")]
+use crate::error::Result;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, ParseStream, Parser};
+use crate::path::Path;
+use crate::token::{Brace, Bracket, Paren};
+use proc_macro2::extra::DelimSpan;
+#[cfg(feature = "parsing")]
+use proc_macro2::Delimiter;
+use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use proc_macro2::TokenTree;
+
+ast_struct! {
+ /// A macro invocation: `println!("{}", mac)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Macro {
+ pub path: Path,
+ pub bang_token: Token![!],
+ pub delimiter: MacroDelimiter,
+ pub tokens: TokenStream,
+ }
+}
+
+ast_enum! {
+ /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum MacroDelimiter {
+ Paren(Paren),
+ Brace(Brace),
+ Bracket(Bracket),
+ }
+}
+
+impl MacroDelimiter {
+ pub fn span(&self) -> &DelimSpan {
+ match self {
+ MacroDelimiter::Paren(token) => &token.span,
+ MacroDelimiter::Brace(token) => &token.span,
+ MacroDelimiter::Bracket(token) => &token.span,
+ }
+ }
+
+ #[cfg(all(feature = "full", any(feature = "parsing", feature = "printing")))]
+ pub(crate) fn is_brace(&self) -> bool {
+ match self {
+ MacroDelimiter::Brace(_) => true,
+ MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
+ }
+ }
+}
+
+impl Macro {
+ /// Parse the tokens within the macro invocation's delimiters into a syntax
+ /// tree.
+ ///
+ /// This is equivalent to `syn::parse2::<T>(mac.tokens)` except that it
+ /// produces a more useful span when `tokens` is empty.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token};
+ /// use syn::ext::IdentExt;
+ /// use syn::parse::{Error, Parse, ParseStream, Result};
+ /// use syn::punctuated::Punctuated;
+ ///
+ /// // The arguments expected by libcore's format_args macro, and as a
+ /// // result most other formatting and printing macros like println.
+ /// //
+ /// // println!("{} is {number:.prec$}", "x", prec=5, number=0.01)
+ /// struct FormatArgs {
+ /// format_string: Expr,
+ /// positional_args: Vec<Expr>,
+ /// named_args: Vec<(Ident, Expr)>,
+ /// }
+ ///
+ /// impl Parse for FormatArgs {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let format_string: Expr;
+ /// let mut positional_args = Vec::new();
+ /// let mut named_args = Vec::new();
+ ///
+ /// format_string = input.parse()?;
+ /// while !input.is_empty() {
+ /// input.parse::<Token![,]>()?;
+ /// if input.is_empty() {
+ /// break;
+ /// }
+ /// if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
+ /// while !input.is_empty() {
+ /// let name: Ident = input.call(Ident::parse_any)?;
+ /// input.parse::<Token![=]>()?;
+ /// let value: Expr = input.parse()?;
+ /// named_args.push((name, value));
+ /// if input.is_empty() {
+ /// break;
+ /// }
+ /// input.parse::<Token![,]>()?;
+ /// }
+ /// break;
+ /// }
+ /// positional_args.push(input.parse()?);
+ /// }
+ ///
+ /// Ok(FormatArgs {
+ /// format_string,
+ /// positional_args,
+ /// named_args,
+ /// })
+ /// }
+ /// }
+ ///
+ /// // Extract the first argument, the format string literal, from an
+ /// // invocation of a formatting or printing macro.
+ /// fn get_format_string(m: &Macro) -> Result<LitStr> {
+ /// let args: FormatArgs = m.parse_body()?;
+ /// match args.format_string {
+ /// Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit),
+ /// other => {
+ /// // First argument was not a string literal expression.
+ /// // Maybe something like: println!(concat!(...), ...)
+ /// Err(Error::new_spanned(other, "format string must be a string literal"))
+ /// }
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let invocation = parse_quote! {
+ /// println!("{:?}", Instant::now())
+ /// };
+ /// let lit = get_format_string(&invocation).unwrap();
+ /// assert_eq!(lit.value(), "{:?}");
+ /// }
+ /// ```
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_body<T: Parse>(&self) -> Result<T> {
+ self.parse_body_with(T::parse)
+ }
+
+ /// Parse the tokens within the macro invocation's delimiters using the
+ /// given parser.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_body_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
+ let scope = self.delimiter.span().close();
+ crate::parse::parse_scoped(parser, scope, self.tokens.clone())
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
+ input.step(|cursor| {
+ if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
+ let span = g.delim_span();
+ let delimiter = match g.delimiter() {
+ Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
+ Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
+ Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
+ Delimiter::None => {
+ return Err(cursor.error("expected delimiter"));
+ }
+ };
+ Ok(((delimiter, g.stream()), rest))
+ } else {
+ Err(cursor.error("expected delimiter"))
+ }
+ })
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::mac::{parse_delimiter, Macro};
+ use crate::parse::{Parse, ParseStream};
+ use crate::path::Path;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Macro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let tokens;
+ Ok(Macro {
+ path: input.call(Path::parse_mod_style)?,
+ bang_token: input.parse()?,
+ delimiter: {
+ let (delimiter, content) = parse_delimiter(input)?;
+ tokens = content;
+ delimiter
+ },
+ tokens,
+ })
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::mac::{Macro, MacroDelimiter};
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::token;
+ use proc_macro2::{Delimiter, TokenStream};
+ use quote::ToTokens;
+
+ impl MacroDelimiter {
+ pub(crate) fn surround(&self, tokens: &mut TokenStream, inner: TokenStream) {
+ let (delim, span) = match self {
+ MacroDelimiter::Paren(paren) => (Delimiter::Parenthesis, paren.span),
+ MacroDelimiter::Brace(brace) => (Delimiter::Brace, brace.span),
+ MacroDelimiter::Bracket(bracket) => (Delimiter::Bracket, bracket.span),
+ };
+ token::printing::delim(delim, span.join(), tokens, inner);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Macro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ path::printing::print_path(tokens, &self.path, PathStyle::Mod);
+ self.bang_token.to_tokens(tokens);
+ self.delimiter.surround(tokens, self.tokens.clone());
+ }
+ }
+}