From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neil@brown.name>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH 1/5] xdrgen: Align the error caret under tab-indented source
Date: Sun, 12 Jul 2026 16:34:47 -0400 [thread overview]
Message-ID: <20260712203451.124902-2-cel@kernel.org> (raw)
In-Reply-To: <20260712203451.124902-1-cel@kernel.org>
When xdrgen reports a parse or transform error, it prints the
offending source line followed by a caret marking the column. The
source line is emitted with its tab characters intact, but the caret
offset is computed from a tab-expanded copy of the text ahead of the
column. A terminal expands the line's leading tabs relative to the
four-space output indent, while the caret math expands the same tabs
from column zero, so the two disagree whenever the line is indented
with tabs and the caret lands past the token it should mark.
Render the displayed line with its tabs already expanded so the line
and the caret share one tab origin and the four-space indent cancels.
Fold the now-identical line-and-caret formatting out of both error
handlers into a single helper, so every caller reports the same
aligned output.
Signed-off-by: Chuck Lever <cel@kernel.org>
---
tools/net/sunrpc/xdrgen/xdr_parse.py | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/net/sunrpc/xdrgen/xdr_parse.py b/tools/net/sunrpc/xdrgen/xdr_parse.py
index 241e96c1fdd9..3e76717d2f85 100644
--- a/tools/net/sunrpc/xdrgen/xdr_parse.py
+++ b/tools/net/sunrpc/xdrgen/xdr_parse.py
@@ -63,6 +63,22 @@ def get_xdr_enum_validation() -> bool:
return enum_validation
+def format_source_caret(line_text: str, column: int) -> list[str]:
+ """Render an offending source line with a caret beneath a column.
+
+ Args:
+ line_text: The raw source line containing the error
+ column: 1-based column of the offending token within line_text
+
+ Returns:
+ Output lines for the diagnostic: a blank separator, the source
+ line with tabs expanded, and a caret aligned under the column.
+ """
+ expanded = line_text.expandtabs()
+ caret = len(line_text[: column - 1].expandtabs())
+ return ["", f" {expanded}", f" {' ' * caret}^"]
+
+
def make_error_handler(source: str, filename: str) -> Callable[[UnexpectedInput], bool]:
"""Create an error handler that reports the first parse error and aborts.
@@ -110,10 +126,7 @@ def make_error_handler(source: str, filename: str) -> Callable[[UnexpectedInput]
msg_parts.append(str(e).split("\n")[0])
# Show the offending line with a caret pointing to the error
- msg_parts.append("")
- msg_parts.append(f" {line_text}")
- prefix = line_text[: column - 1].expandtabs()
- msg_parts.append(f" {' ' * len(prefix)}^")
+ msg_parts.extend(format_source_caret(line_text, column))
sys.stderr.write("\n".join(msg_parts) + "\n")
raise XdrParseError()
@@ -151,10 +164,7 @@ def handle_transform_error(e: VisitError, source: str, filename: str) -> None:
# Show the offending line with a caret pointing to the error
if line_text:
- msg_parts.append("")
- msg_parts.append(f" {line_text}")
- prefix = line_text[: column - 1].expandtabs()
- msg_parts.append(f" {' ' * len(prefix)}^")
+ msg_parts.extend(format_source_caret(line_text, column))
sys.stderr.write("\n".join(msg_parts) + "\n")
--
2.54.0
next prev parent reply other threads:[~2026-07-12 20:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-12 20:34 [PATCH 0/5] xdrgen: Improve diagnostic reporting Chuck Lever
2026-07-12 20:34 ` Chuck Lever [this message]
2026-07-12 20:34 ` [PATCH 2/5] xdrgen: Record the source position of each declared identifier Chuck Lever
2026-07-12 20:34 ` [PATCH 3/5] xdrgen: Reject specifications that define a name twice Chuck Lever
2026-07-12 20:34 ` [PATCH 4/5] xdrgen: Enforce RFC 5531 name and number scoping for RPC programs Chuck Lever
2026-07-12 20:34 ` [PATCH 5/5] xdrgen: Reject out-of-range program, version, and procedure numbers Chuck Lever
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=20260712203451.124902-2-cel@kernel.org \
--to=cel@kernel.org \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.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 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.