From patchwork Fri Aug 22 14:21:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 108 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872546; bh=fjXFZc19++r4pbvJxXGtjoZSIMczHC/wES2wKNQj468=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=jCYNiStp/zdYGuKlkOyxVX4T3bVKpyBqtvV6RSY2cfR1L/4akUtvEyRgbPEuDI0P9 EmSJcO2zVktC5VgmsD6zPVn6k5Ov7Km4bXWPER1Fv4Vd6npVCu4HyZtJJXuXPr4o6j F19jeGr003VpdAoLaoxxzOWuvVHaciZti0IXTChogSMoTbGhkAP4LOE3gDtOIKIMH6 tWtcVcUTGgXMQkBgBEu7nboX3IpBBs9LxD6kqM3dOLd7X1Ttao5QPo4hRSK7M/yXcz F6RXkW/4YSHg+dEzC5fOj5pOaHiIguhKzA0PYjg3NEidRxpeyRycIFFFfQPqiLwcu8 m67qZT9TfydQw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 7C291676DB for ; Fri, 22 Aug 2025 08:22:26 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 3uz9t98B9cdA for ; Fri, 22 Aug 2025 08:22:26 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872545; bh=fjXFZc19++r4pbvJxXGtjoZSIMczHC/wES2wKNQj468=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=HGtf1FWMsxQFSPnav+wdSlnEkHxSfPlCCIvvBKMHsfkVOrGw7cMMg7WoUegwXFTp4 uw2DY5ObdX+PyodVAKEBVUP7CMuXIHH/n/rd/GA6FHMTotZFo3mxhGaTNf17NJV1Ur tTV7hun98iLFts8qbG8PncqNtqHqnA0YhrrpvV0pdvrBEXspsuNT2e/R1RXI2Du1tf x83KfQfWN3ox9KvgAKAEWTmNpxv7HsX7QLnqtRvUR1ool2MWDupQoTggCvd15eo7IJ yxyxS14kuaQs5savkbfe4VLFuG6cMXDhy2Nj7LCV3F4GjOcMRsFV6M2cn/EAHVV0uV FXcoXJzwHH6gQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 60412676C4 for ; Fri, 22 Aug 2025 08:22:25 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872543; bh=XiG1jc49IvXhaoolq6g6DOq+Ago/4LogIE1s/JpqOWo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SlbsttqUreJ1kw5Yo0/UmAuE0LjFnbnq8p6GVpbZezNKmzta2xy1r8i10amP1zOD5 11D4z6A9M2TLhc4ODwp6fDsoBnHTbqSgfgoPXeImOqpXwrZO2D+/p0LoNH17iEIHkW NGLevaibR+cu6HmtDfcxZ5l05/Nn5QyBkMdi7MYQm2swFj2jWfI5QdwE5EbJh9e0/A iGfguaDFwpwIKvYUT3ySwX3jUL4KbZ3Fc2pGJavsA3xxatkBD1dCzDSX3wbRL29TF2 BI6s9M75SMKJdhfuiq3Lpu5b7SWGuBcb7ilNmRLWV+QEBUHenG/kk7HSl7zNVHe8on pE6A9wWG09cEw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 6266E5E45E; Fri, 22 Aug 2025 08:22:23 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id FJwCV4VTAUxR; Fri, 22 Aug 2025 08:22:23 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872542; bh=xS2lKKuSRMHv+hMxeRCAS6FnNnYH7+Pjklun4yxOEn8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J0mO85eNzYQYbuVejAj5Un+1159iYxxTTPVUQjAncqWnYnExSOlj10zvmwTC3nCVW E3DfqZwouF7goqLuDTHASngiuN34m6OTnxUrajEeocHSKcMzp7SY47HqS7IXtDA3Q9 +FDYLApA/ylORcC8Bge/7FYCzk1MdF0GsXlcc+1QJqBm5UmtHXBu27t3JADDatOKPG V/RSP8Rf4IfjUJbYMmpDgEwatWEI3/54mPVMAlA2yKAJMjUIroSV/Du8fOocDEQblg QLTh+/4kYWp613tGi0SOfSkrkASO+P0pomjs11hbnPq//xg8MRlxfw5MhGlU6CIInw HpP7MyrnnjtZg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9470A676C4; Fri, 22 Aug 2025 08:22:22 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 22 Aug 2025 08:21:34 -0600 Message-ID: <20250822142153.3404275-4-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250822142153.3404275-1-sjg@u-boot.org> References: <20250822142153.3404275-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: YYRPQZOYPKYSBPRWTZK5LRBGDYIYQNPG X-Message-ID-Hash: YYRPQZOYPKYSBPRWTZK5LRBGDYIYQNPG X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 03/16] console: Provide a way to output without the pager List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Sometimes output should be sent ignoring the pager, such as when it is a message related to paging. Add a parameter to support this. Co-developed-by: Claude Signed-off-by: Simon Glass --- common/pager.c | 11 ++-- include/pager.h | 15 ++++-- test/common/pager.c | 123 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 112 insertions(+), 37 deletions(-) diff --git a/common/pager.c b/common/pager.c index 084c741989f..20aa8558654 100644 --- a/common/pager.c +++ b/common/pager.c @@ -14,12 +14,12 @@ DECLARE_GLOBAL_DATA_PTR; -const char *pager_post(struct pager *pag, const char *s) +const char *pager_post(struct pager *pag, bool use_pager, const char *s) { struct membuf old; int ret, len; - if (!pag) + if (!pag || !use_pager) return s; len = strlen(s); @@ -44,14 +44,17 @@ const char *pager_post(struct pager *pag, const char *s) pag->mb = old; } - return pager_next(pag, 0); + return pager_next(pag, true, 0); } -const char *pager_next(struct pager *pag, int key) +const char *pager_next(struct pager *pag, bool use_pager, int key) { char *str, *p, *end; int ret; + if (!use_pager) + return NULL; + /* replace the real character we overwrite with nul, if needed */ if (pag->nulch) { *pag->nulch = pag->oldch; diff --git a/include/pager.h b/include/pager.h index 16739d41119..7f7df690d7f 100644 --- a/include/pager.h +++ b/include/pager.h @@ -74,7 +74,7 @@ struct pager { /** * pager_post() - Add text to the input buffer for later handling * - * The text is added to the pager buffer and fed out a screenful + * If @use_pager the text is added to the pager buffer and fed out a screenful * at a time. This function calls pager_post() after storing the text. * * After calling pager_post(), if it returns anything other than NULL, you must @@ -84,10 +84,12 @@ struct pager { * If @pag is NULL, this does nothing but return @s * * @pag: Pager to use, may be NULL + * @use_pager: Whether or not to use the pager functionality * @s: Text to add * Return: text which should be sent to output, or NULL if there is no more. + * If !@use_pager this just returns @s and does not affect the pager state */ -const char *pager_post(struct pager *pag, const char *s); +const char *pager_post(struct pager *pag, bool use_pager, const char *s); /** * pager_next() - Returns the next screenful of text to show @@ -98,12 +100,14 @@ const char *pager_post(struct pager *pag, const char *s); * return PAGER_WAITING until @ch is non-zero. * * @pag: Pager to use + * @use_pager: Whether or not to use the pager functionality * @ch: Key that the user has pressed, or 0 if none * * Return: text which should be sent to output, or PAGER_WAITING if waiting for * the user to press a key, or NULL if there is no more text. + * If !@use_pager this just returns NULL and does not affect the pager state */ -const char *pager_next(struct pager *pag, int ch); +const char *pager_next(struct pager *pag, bool use_pager, int ch); /** * pager_uninit() - Uninit the pager @@ -115,12 +119,13 @@ const char *pager_next(struct pager *pag, int ch); void pager_uninit(struct pager *pag); #else -static inline const char *pager_post(struct pager *pag, const char *s) +static inline const char *pager_post(struct pager *pag, bool use_pager, + const char *s) { return s; } -static inline const char *pager_next(struct pager *pag, int ch) +static inline const char *pager_next(struct pager *pag, bool use_pager, int ch) { return NULL; } diff --git a/test/common/pager.c b/test/common/pager.c index 37796494f79..f72d0f40304 100644 --- a/test/common/pager.c +++ b/test/common/pager.c @@ -50,12 +50,12 @@ static int pager_test_simple_text(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 20, 1024)); /* Post some text and get it back */ - result = pager_post(pag, text); + result = pager_post(pag, true, text); ut_assertnonnull(result); ut_asserteq_str(text, result); /* Should be no more text */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); pager_uninit(pag); @@ -76,28 +76,28 @@ static int pager_test_multiline(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 20, 1024)); /* Post multiple pieces of text */ - result = pager_post(pag, text1); + result = pager_post(pag, true, text1); ut_assertnonnull(result); ut_asserteq_str(text1, result); /* Should be no more text after first post */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); - result = pager_post(pag, text2); + result = pager_post(pag, true, text2); ut_assertnonnull(result); ut_asserteq_str(text2, result); /* Should be no more text after second post */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); - result = pager_post(pag, text3); + result = pager_post(pag, true, text3); ut_assertnonnull(result); ut_asserteq_str(text3, result); /* Should be no more text after third post */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); pager_uninit(pag); @@ -115,10 +115,10 @@ static int pager_test_large_text(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 20, 16)); /* Small buffer */ /* Post large text - should fit in buffer */ - result = pager_post(pag, "this is 16 chars"); + result = pager_post(pag, true, "this is 16 chars"); ut_assertnonnull(result); ut_asserteq_str("this is 16 chars", result); - ut_assertnull(pager_next(pag, 0)); + ut_assertnull(pager_next(pag, true, 0)); pager_uninit(pag); @@ -135,12 +135,12 @@ static int pager_test_overflow(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 20, 4)); /* Small buffer */ /* send some text which is too long for the buffer */ - result = pager_post(pag, "test1"); + result = pager_post(pag, true, "test1"); ut_assertnonnull(result); /* overflow handling should return the text */ ut_asserteq_str("test1", result); - ut_assertnull(pager_next(pag, 0)); + ut_assertnull(pager_next(pag, true, 0)); pager_uninit(pag); @@ -154,7 +154,7 @@ static int pager_test_null_input(struct unit_test_state *uts) const char *result; /* Test pager_post with NULL pager */ - result = pager_post(NULL, "test"); + result = pager_post(NULL, true, "test"); ut_asserteq_str("test", result); return 0; @@ -170,11 +170,11 @@ static int pager_test_empty_strings(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 20, 1024)); /* Post empty string */ - result = pager_post(pag, ""); + result = pager_post(pag, true, ""); ut_assertnull(result); /* Should be no more text */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); pager_uninit(pag); @@ -197,7 +197,7 @@ static int pager_test_buffer_management(struct unit_test_state *uts) ut_asserteq(1024, pag->buf.size); /* Post text and verify buffer state */ - result = pager_post(pag, text); + result = pager_post(pag, true, text); ut_assertnonnull(result); /* Verify the buffer contains our text */ @@ -225,7 +225,7 @@ static int pager_test_long_single_line(struct unit_test_state *uts) long_line[sizeof(long_line) - 1] = '\0'; /* Post the long line */ - result = pager_post(pag, long_line); + result = pager_post(pag, true, long_line); ut_assertnonnull(result); /* Should get our text back */ @@ -248,7 +248,7 @@ static int pager_test_line_counting(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 4, 1024)); /* Post multiline text */ - result = pager_post(pag, multiline_text); + result = pager_post(pag, true, multiline_text); ut_assertnonnull(result); /* Should get first 3 lines (excluding the 3rd newline) */ @@ -257,22 +257,22 @@ static int pager_test_line_counting(struct unit_test_state *uts) ut_asserteq(0, pag->line_count); /* Next call should return pager prompt */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnonnull(result); ut_asserteq_str("\n: Press SPACE to continue", result); /* Press space to continue */ - result = pager_next(pag, ' '); + result = pager_next(pag, true, ' '); ut_assertnonnull(result); ut_asserteq_str("\r \r", result); /* Get remaining lines */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnonnull(result); ut_asserteq_str("Line 4\nLine 5\n", result); /* Should be no more text */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); pager_uninit(pag); @@ -291,30 +291,30 @@ static int pager_test_pager_waiting(struct unit_test_state *uts) ut_assertok(pager_init(&pag, 3, 1024)); /* Post text that fills exactly the page limit */ - result = pager_post(pag, "Line 1\nLine 2\n"); + result = pager_post(pag, true, "Line 1\nLine 2\n"); ut_assertnonnull(result); ut_asserteq_str("Line 1\nLine 2", result); /* Next call should return the prompt */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnonnull(result); ut_asserteq_str("\n: Press SPACE to continue", result); /* Next call without space key should return PAGER_WAITING */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_asserteq_ptr(PAGER_WAITING, result); /* Another call without space should still return PAGER_WAITING */ - result = pager_next(pag, 'x'); /* Wrong key */ + result = pager_next(pag, true, 'x'); /* Wrong key */ ut_asserteq_ptr(PAGER_WAITING, result); /* Pressing space should clear the prompt */ - result = pager_next(pag, ' '); + result = pager_next(pag, true, ' '); ut_assertnonnull(result); ut_asserteq_str("\r \r", result); /* Now should return NULL (no more content) */ - result = pager_next(pag, 0); + result = pager_next(pag, true, 0); ut_assertnull(result); pager_uninit(pag); @@ -322,3 +322,70 @@ static int pager_test_pager_waiting(struct unit_test_state *uts) return 0; } COMMON_TEST(pager_test_pager_waiting, 0); + +/* Test use_pager parameter - output text directly, while buffer is non-empty */ +static int pager_test_use_pager_param(struct unit_test_state *uts) +{ + struct pager *pag; + const char *buffered_text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n"; + const char *direct_text = "This should be written immediately"; + const char *result; + + /* Init with small page length to ensure paging occurs */ + ut_assertok(pager_init(&pag, 3, 1024)); + + /* Post text with use_pager=true - should trigger paging */ + result = pager_post(pag, true, buffered_text); + ut_assertnonnull(result); + /* Should get first 2 lines */ + ut_asserteq_str("Line 1\nLine 2", result); + + /* Now call pager_post with use_pager=false while text is still buffered */ + result = pager_post(pag, false, direct_text); + /* Should get the text immediately, not from buffer */ + ut_asserteq_ptr(direct_text, result); + + /* Call pager_next with use_pager=false - should return NULL */ + result = pager_next(pag, false, 0); + ut_assertnull(result); + + /* Now continue with use_pager=true to get buffered text */ + result = pager_next(pag, true, 0); + ut_assertnonnull(result); + /* Should get the pager prompt */ + ut_asserteq_str("\n: Press SPACE to continue", result); + + /* Press space to continue */ + result = pager_next(pag, true, ' '); + ut_assertnonnull(result); + ut_asserteq_str("\r \r", result); + + /* Get remaining buffered lines - should be next 2 lines due to page limit */ + result = pager_next(pag, true, 0); + ut_assertnonnull(result); + ut_asserteq_str("Line 3\nLine 4", result); + + /* Should get pager prompt again */ + result = pager_next(pag, true, 0); + ut_assertnonnull(result); + ut_asserteq_str("\n: Press SPACE to continue", result); + + /* Press space to continue */ + result = pager_next(pag, true, ' '); + ut_assertnonnull(result); + ut_asserteq_str("\r \r", result); + + /* Get final line */ + result = pager_next(pag, true, 0); + ut_assertnonnull(result); + ut_asserteq_str("Line 5\n", result); + + /* Should be no more text */ + result = pager_next(pag, true, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_use_pager_param, 0);