All of lore.kernel.org
 help / color / mirror / Atom feed
From: Timur Tabi <ttabi@nvidia.com>
To: Miguel Ojeda <ojeda@kernel.org>, Benno Lossin <lossin@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	Danilo Krummrich <dakr@kernel.org>,
	<rust-for-linux@vger.kernel.org>
Subject: [PATCH v5] rust: introduce sfile macro for succinct code tracing
Date: Thu, 26 Jun 2025 15:35:35 -0500	[thread overview]
Message-ID: <20250626203535.331219-1-ttabi@nvidia.com> (raw)

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 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.

The macro also uses some unsafe functions in order to avoid indexing
into a str, which is necessary to fully support const contexts.

Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
 rust/kernel/print.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++
 rust/kernel/str.rs   | 28 ++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 9783d960a97a..40f1ff0342af 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -423,3 +423,66 @@ macro_rules! pr_cont (
         $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
     )
 );
+
+/// Returns just the base filename of the current file.
+///
+/// This differs from the built-in [`file!()`] macro, which returns the full
+/// path of the current file.
+///
+/// # Examples
+///
+/// Useful for succinct logging purposes.
+///
+/// ```
+/// # use kernel::sfile;
+/// // Output: `example:42`.
+/// pr_err!("{}:{}\n", sfile!(), line!());
+/// ```
+///
+/// The value is a constant expression, so it can be used in const
+/// contexts, e.g.:
+///
+/// ```
+/// # use kernel::sfile;
+/// // Contains: `example`.
+/// const SFILE: &'static str = sfile!();
+/// ```
+#[macro_export]
+macro_rules! sfile {
+    () => {{
+        const fn shortname() -> Option<&'static str> {
+            const FILE: &str = core::file!();
+
+            let start = ::kernel::str::rfind_const(FILE, '/').unwrap() + 1;
+            let end = ::kernel::str::rfind_const(FILE, '.').unwrap();
+
+            // Make sure that there actually is something to return.  This also
+            // covers a lot of corner cases, such as eliminating filenames that
+            // end in a slash (not possible) or don't have an extension,
+            // and making sure that `start` < `FILE.len()` and `end` - `start` > 0.
+            if end <= start {
+                return None;
+            }
+
+            // The following code is the equivalent of &FILE[start..start+len],
+            // except that it is allowed in const contexts.
+
+            let base_ptr: *const u8 = FILE.as_ptr();
+
+            // SAFETY: The above assertion ensures that `start` points to inside
+            // the string.
+            let p = unsafe { <*const ::core::primitive::u8>::add(base_ptr, start) };
+            // SAFETY: Based on all constraints on `start` and `end`, this slice
+            // will never extend beyond the string.
+            let p = unsafe { core::slice::from_raw_parts(p, end - start) };
+            // SAFETY: We know that the slice is valid UTF-8, because we checked
+            // that `FILE` is ASCII (via `is_ascii()` above).
+            match core::str::from_utf8(p) {
+                Ok(slice) => Some(slice),
+                Err(_) => None,
+            }
+        }
+
+        shortname().unwrap()
+    }};
+}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index a927db8e079c..d74b94a406c4 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -936,3 +936,31 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 macro_rules! fmt {
     ($($f:tt)*) => ( ::core::format_args!($($f)*) )
 }
+
+/// Returns the index of the last occurrence of `needle` in `haystack`, or [`None`].
+///
+/// Similar to [`str::rfind()`], except this one is const.  It also only supports
+/// ASCII strings.
+///
+/// # Examples
+///
+/// ```
+/// # use ::kernel::str::rfind_const;
+/// let l = rfind_const("when will then be now?", 'l');
+/// assert!(l == Some(8));
+///
+/// let q = rfind_const("when will then be now?", 'q');
+/// assert!(q == None);
+/// ```
+#[inline]
+pub const fn rfind_const(haystack: &str, needle: char) -> Option<usize> {
+    let haystack = haystack.as_bytes();
+    let mut i = haystack.len();
+    while i > 0 {
+        i -= 1;
+        if haystack[i] == needle as u8 {
+            return Some(i);
+        }
+    }
+    None
+}

base-commit: c4dce0c094a89b1bc8fde1163342bd6fe29c0370
-- 
2.48.1


             reply	other threads:[~2025-06-26 20:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-26 20:35 Timur Tabi [this message]
2025-06-29 13:41 ` [PATCH v5] rust: introduce sfile macro for succinct code tracing 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=20250626203535.331219-1-ttabi@nvidia.com \
    --to=ttabi@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=dakr@kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.