rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Benno Lossin" <lossin@kernel.org>
To: "Timur Tabi" <ttabi@nvidia.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Danilo Krummrich" <dakr@kernel.org>,
	<rust-for-linux@vger.kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>
Subject: Re: [PATCH] rust: introduce sfile macro for easier code tracing
Date: Thu, 29 May 2025 22:14:44 +0200	[thread overview]
Message-ID: <DA8X4RXQKX5J.N4S9TWX90OU9@kernel.org> (raw)
In-Reply-To: <20250529184547.1447995-1-ttabi@nvidia.com>

On Thu May 29, 2025 at 8:45 PM CEST, Timur Tabi wrote:
> Introduce the sfile (short file) macro that returns the stem of
> the current source file filename.
>
> Rust provides a file!() macro that is similar to C's __FILE__ predefined
> macro.  Unlike __FILE__, however, file!() returns a full path, which is
> klunky when used for debug traces such as
>
> 	pr_info!("{}:{}\n", file!(), line!());
>
> sfile!() can be used in situations instead, to provide a more compact
> print.  For example, if file!() returns "rust/kernel/print.rs", sfile!()
> returns just "print".
>
> The macro goes avoids str::rfind() because currently, that function is not
> const.  The compiler emits a call to memrchr, even when called on string
> literals.  Instead, the macro implements its own versions of rfind(),
> allowing the compiler to generate the slice at compile time.
>
> Unfortunately, Rust does not consider the .. operator to be const either,
> so sfind!() cannot be assigned to consts.  For example, the following will
> not compile:

This is not the `..` operator, but rather the index operation of a str
(`&FILE[start..]`). It can be made const by using `from_utf8` [1] and
manually creating the correct byte slice using `unsafe` [2] instead.

[1]: https://doc.rust-lang.org/std/str/fn.from_utf8.html
[2]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html

> 	const SFILE: &'static str = sfile!();
>
> Signed-off-by: Timur Tabi <ttabi@nvidia.com>
> ---
>  rust/kernel/print.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
>
> diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
> index cf4714242e14..3c7b0c74bfb9 100644
> --- a/rust/kernel/print.rs
> +++ b/rust/kernel/print.rs
> @@ -414,3 +414,51 @@ macro_rules! pr_cont (
>          $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
>      )
>  );
> +
> +/// Returns just the base filename of the current file.
> +/// file!() returns the full path of the current file, which is often too long.
> +/// Use this macro to trace your code:
> +/// pr_err!("{}:{}\n", sfile!(), line!());
> +/// Note: Avoiding rfind() allows this macro to be evaluated at compile time
> +/// in most situations, such as the above pr_err!() example.  However,
> +/// because .. is apparently a non-const operator, the following will not work:
> +///     const SFILE: &'static str = sfile!();
> +#[macro_export]
> +macro_rules! sfile {
> +    () => {{
> +        const FILE: &str = file!();
> +
> +        /// Return the index of the last occurrence of @needle in @haystack,
> +        /// or zero if not found.  We can't use rfind() because it's not const (yet).
> +        const fn find_last_or_zero(haystack: &str, needle: char) -> usize {
> +            let bytes = haystack.as_bytes();

Using bytes doesn't consider non-ascii filenames (which I think we don't
have), but we could enforce that by checking `is_ascii` and panicking
otherwise.

---
Cheers,
Benno

> +            let mut i = haystack.len();
> +            while i > 0 {
> +                i -= 1;
> +                if bytes[i] == needle as u8 {
> +                    return i;
> +                }
> +            }
> +            0
> +        }
> +
> +        /// Return the index of the last occurrence of @needle in @haystack,
> +        /// or the length of the string if not found.
> +        const fn find_last_or_len(haystack: &str, needle: char) -> usize {
> +            let len = haystack.len();
> +            let bytes = haystack.as_bytes();
> +            let mut i = len;
> +            while i > 0 {
> +                i -= 1;
> +                if bytes[i] == needle as u8 {
> +                    return i;
> +                }
> +            }
> +            len
> +        }
> +
> +        let start = find_last_or_zero(FILE, '/') + 1;
> +        let len = find_last_or_len(&FILE[start..], '.');
> +        &FILE[start..start+len]
> +    }};
> +}


  reply	other threads:[~2025-05-29 20:14 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-29 18:45 [PATCH] rust: introduce sfile macro for easier code tracing Timur Tabi
2025-05-29 20:14 ` Benno Lossin [this message]
2025-06-03 17:15   ` Timur Tabi
2025-06-03 21:54     ` Benno Lossin
2025-05-29 20:21 ` Miguel Ojeda
2025-06-03 18:15   ` Timur Tabi
2025-06-03 21:58     ` Benno Lossin
2025-06-03 22:05       ` Timur Tabi
2025-06-03 22:15         ` Miguel Ojeda
2025-06-04 23:12           ` Timur Tabi
2025-06-05  3:20             ` Miguel Ojeda
2025-06-03 22:15     ` Miguel Ojeda
2025-06-03 23:29       ` Timur Tabi
2025-06-04 10:28         ` Miguel Ojeda
2025-06-04 15:16           ` Benno Lossin
2025-06-04 15:41             ` Miguel Ojeda
2025-06-05  6:05             ` Greg KH
2025-06-04 20:38           ` Timur Tabi
2025-06-05  6:07             ` Greg KH
2025-06-05 15:02               ` Timur Tabi
2025-06-05 15:21                 ` gregkh
2025-06-05 15:38                   ` Miguel Ojeda
2025-06-05 16:42                     ` gregkh
2025-06-05 17:39                       ` Miguel Ojeda
2025-06-06 15:50                 ` Miguel Ojeda
2025-05-30  3:47 ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DA8X4RXQKX5J.N4S9TWX90OU9@kernel.org \
    --to=lossin@kernel.org \
    --cc=aliceryhl@google.com \
    --cc=dakr@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=ttabi@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).