From patchwork Mon Feb 27 19:42:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Merey X-Patchwork-Id: 65695 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C340F385843A for ; Mon, 27 Feb 2023 19:43:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C340F385843A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1677526992; bh=wH+erM+PXRbgZzjDtSZk97WzWT77dgkoDmnTPI5GUeY=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=QetWSuw9hMG8P8w0QSzfUPt2VN57gbYm+V8npCkecszh8cDQhQL9brKUU0mGfodnU xrn/EY0gQLTBlVA3V5fPnx68HqH4A1L5biTcC1ZGeY04acH+dU0vdXMtQmWOzAZT+q uFp8ZRZrIBICQjnMXolrWzLuxNjFazuqX2EYAj0s= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 169EC3858D3C for ; Mon, 27 Feb 2023 19:42:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 169EC3858D3C Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-215-RyP0l-kFNOmSDyHCX2oxqg-1; Mon, 27 Feb 2023 14:42:15 -0500 X-MC-Unique: RyP0l-kFNOmSDyHCX2oxqg-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 728B885A588 for ; Mon, 27 Feb 2023 19:42:15 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.22.18.122]) by smtp.corp.redhat.com (Postfix) with ESMTP id 41375492C3E; Mon, 27 Feb 2023 19:42:15 +0000 (UTC) To: gdb-patches@sourceware.org Cc: Aaron Merey Subject: [PATCH 4/7] gdb/ui-file: Add newline tracking Date: Mon, 27 Feb 2023 14:42:09 -0500 Message-Id: <20230227194212.348003-4-amerey@redhat.com> In-Reply-To: <20230227194212.348003-1-amerey@redhat.com> References: <20230227194212.348003-1-amerey@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-15.5 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Aaron Merey via Gdb-patches From: Aaron Merey Reply-To: Aaron Merey Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Add a new field line_state to ui_file's that indicates whether the character most recently written to the ui_file's stream is a newline. The purpose of this is to help debuginfod progress messages always print on their own line. Until now they have always done so without any special intervention. But with the addition of deferred debuginfo downloading it is possible for progress messages to occur during the printing of frame information. Without any newline tracking in this case, we can end up with poorly formatted output: (gdb) backtrace [...] #8 0x00007fbe8af7d7cf in pygi_invoke_c_callable (Downloading separate debug info for /lib64/libpython3.11.so.1.0 function_cache=0x561221b224d0, state=... With newline tracking, the progress message writer can detect whether the message should start with a newline. This ensures that all progress messages print on their own line: (gdb) backtrace [...] #8 0x00007fbe8af7d7cf in pygi_invoke_c_callable ( Downloading separate debug info for /lib64/libpython3.11.so.1.0 function_cache=0x561221b224d0, state=... --- gdb/cli-out.c | 18 +++++++++++++++--- gdb/mi/mi-console.c | 4 ++++ gdb/tui/tui-file.c | 4 ++++ gdb/ui-file.c | 31 +++++++++++++++++++++++++++++++ gdb/ui-file.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 3 deletions(-) diff --git a/gdb/cli-out.c b/gdb/cli-out.c index fdfd0f7f0cf..1639f885cb9 100644 --- a/gdb/cli-out.c +++ b/gdb/cli-out.c @@ -307,6 +307,10 @@ cli_ui_out::do_progress_notify (const std::string &msg, if (info.state == progress_update::START) { + /* MSG should print on its own line. */ + if (stream->get_line_state () == ui_file::LINE_NOT_AT_START) + gdb_printf (stream, "\n"); + if (stream->isatty () && current_ui->input_interactive_p () && chars_per_line >= MIN_CHARS_PER_LINE) @@ -410,10 +414,18 @@ void cli_ui_out::do_progress_end () { struct ui_file *stream = m_streams.back (); - m_progress_info.pop_back (); - if (stream->isatty ()) - clear_current_line (); + cli_progress_info &info (m_progress_info.back ()); + + if (info.state != progress_update::START && stream->isatty ()) + { + clear_current_line (); + + if (stream->get_line_state () != ui_file::LINE_UNDEFINED) + stream->set_line_state (ui_file::LINE_AT_START); + } + + m_progress_info.pop_back (); } /* local functions */ diff --git a/gdb/mi/mi-console.c b/gdb/mi/mi-console.c index e0b5648c2df..60f2a823b47 100644 --- a/gdb/mi/mi-console.c +++ b/gdb/mi/mi-console.c @@ -46,6 +46,8 @@ mi_console_file::write (const char *buf, long length_buf) buffer. */ if (strchr (m_buffer.c_str () + prev_size, '\n') != NULL) this->flush (); + + set_line_state_from_buf (m_buffer.c_str () + prev_size, length_buf); } void @@ -63,6 +65,8 @@ mi_console_file::write_async_safe (const char *buf, long length_buf) char nl = '\n'; m_raw->write_async_safe (&nl, 1); + + set_line_state (LINE_AT_START); } void diff --git a/gdb/tui/tui-file.c b/gdb/tui/tui-file.c index c1619d5ace6..c36ce739497 100644 --- a/gdb/tui/tui-file.c +++ b/gdb/tui/tui-file.c @@ -28,6 +28,8 @@ tui_file::puts (const char *linebuffer) tui_puts (linebuffer); if (!m_buffered) tui_refresh_cmd_win (); + + set_line_state_from_buf (linebuffer); } void @@ -36,6 +38,8 @@ tui_file::write (const char *buf, long length_buf) tui_write (buf, length_buf); if (!m_buffered) tui_refresh_cmd_win (); + + set_line_state_from_buf (buf, length_buf); } void diff --git a/gdb/ui-file.c b/gdb/ui-file.c index e0814fe2b2d..3f7a55ed252 100644 --- a/gdb/ui-file.c +++ b/gdb/ui-file.c @@ -31,6 +31,7 @@ null_file null_stream; ui_file::ui_file () + : m_line_state (LINE_UNDEFINED) {} ui_file::~ui_file () @@ -159,6 +160,30 @@ ui_file::printchar (int c, int quoter, bool async_safe) this->write (buf, out); } +/* See ui-file.h. */ + +void +ui_file::set_line_state_from_buf (const char *buf) +{ + const char *last_nl = strrchr (buf, '\n'); + + if (last_nl != nullptr && *++last_nl == '\0') + m_line_state = LINE_AT_START; + else + m_line_state = LINE_NOT_AT_START; +} + +/* See ui-file.h. */ + +void +ui_file::set_line_state_from_buf (const char *buf, long length_buf) +{ + if (buf[length_buf - 1] == '\n') + m_line_state = LINE_AT_START; + else + m_line_state = LINE_NOT_AT_START; +} + void @@ -311,6 +336,8 @@ stdio_file::write (const char *buf, long length_buf) { /* Nothing. */ } + + set_line_state_from_buf (buf, length_buf); } void @@ -323,6 +350,8 @@ stdio_file::write_async_safe (const char *buf, long length_buf) { /* Nothing. */ } + + set_line_state_from_buf (buf, length_buf); } void @@ -339,6 +368,8 @@ stdio_file::puts (const char *linebuffer) { /* Nothing. */ } + + set_line_state_from_buf (linebuffer); } bool diff --git a/gdb/ui-file.h b/gdb/ui-file.h index de24620e247..b85c37d81c7 100644 --- a/gdb/ui-file.h +++ b/gdb/ui-file.h @@ -132,11 +132,40 @@ class ui_file this->puts (str); } + enum line_state + { + /* Line state is not being tracked. */ + LINE_UNDEFINED, + + /* The last character written to this ui_file is not a newline. */ + LINE_NOT_AT_START, + + /* The last character written to this ui_file is a newline. */ + LINE_AT_START + }; + + /* Set this ui_file's line_state to STATE. */ + virtual void set_line_state (line_state state) + { m_line_state = state; } + + /* Return this ui_file's line_state. */ + virtual line_state get_line_state () + { return m_line_state; } + protected: /* The currently applied style. */ ui_file_style m_applied_style; + /* The current line_state. */ + line_state m_line_state; + + /* Set line_state based on whether BUF ends in a newline. */ + void set_line_state_from_buf (const char *buf); + + /* Set line_state based on whether BUF ends in a newline. */ + void set_line_state_from_buf (const char *buf, long length_buf); + private: /* Helper function for putstr and putstrn. Print the character C on @@ -428,6 +457,21 @@ class wrapped_file : public ui_file void write_async_safe (const char *buf, long length_buf) override { return m_stream->write_async_safe (buf, length_buf); } + /* Return the line_state of the underlying stream. */ + line_state get_line_state () override + { + if (m_stream == nullptr) + return ui_file::LINE_UNDEFINED; + return m_stream->get_line_state (); + } + + /* Set the line_state of the underlying stream. */ + void set_line_state (line_state state) override + { + if (m_stream != nullptr) + m_stream->set_line_state (state); + } + protected: /* Note that this class does not assume ownership of the stream.