shell: Support output using a va_list

At present it is not possible to write a printf()-like function in
board code which outputs to the shell. Add shell_vfprintf() to permit
this.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2020-04-30 15:25:04 -06:00 committed by Ioannis Glaropoulos
commit fc0e10d064
3 changed files with 59 additions and 9 deletions

View file

@ -726,6 +726,21 @@ int shell_stop(const struct shell *shell);
void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
const char *fmt, ...);
/**
* @brief vprintf-like function which sends formatted data stream to the shell.
*
* This function can be used from the command handler or from threads, but not
* from an interrupt context. It is similar to shell_fprintf() but takes a
* va_list instead of variable arguments.
*
* @param[in] shell Pointer to the shell instance.
* @param[in] color Printed text color.
* @param[in] fmt Format string.
* @param[in] args List of parameters to print.
*/
void shell_vfprintf(const struct shell *shell, enum shell_vt100_color color,
const char *fmt, va_list args);
/**
* @brief Print data in hexadecimal format.
*

View file

@ -1304,8 +1304,8 @@ void shell_process(const struct shell *shell)
/* This function mustn't be used from shell context to avoid deadlock.
* However it can be used in shell command handlers.
*/
void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
const char *fmt, ...)
void shell_vfprintf(const struct shell *shell, enum shell_vt100_color color,
const char *fmt, va_list args)
{
__ASSERT_NO_MSG(shell);
__ASSERT(!k_is_in_isr(), "Thread context required.");
@ -1315,17 +1315,11 @@ void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
__ASSERT_NO_MSG(shell->fprintf_ctx);
__ASSERT_NO_MSG(fmt);
va_list args;
k_mutex_lock(&shell->ctx->wr_mtx, K_FOREVER);
if (!flag_cmd_ctx_get(shell)) {
shell_cmd_line_erase(shell);
}
va_start(args, fmt);
shell_internal_vfprintf(shell, color, fmt, args);
va_end(args);
if (!flag_cmd_ctx_get(shell)) {
shell_print_prompt_and_cmd(shell);
}
@ -1333,6 +1327,19 @@ void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
k_mutex_unlock(&shell->ctx->wr_mtx);
}
/* This function mustn't be used from shell context to avoid deadlock.
* However it can be used in shell command handlers.
*/
void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
shell_vfprintf(shell, color, fmt, args);
va_end(args);
}
static void shell_hexdump_line(const struct shell *shell, unsigned int offset,
const u8_t *data, size_t len)
{

View file

@ -316,6 +316,33 @@ static void test_set_root_cmd(void)
test_shell_execute_cmd("shell colors on", 0);
}
static void test_shell_fprintf(void)
{
static const char expect[] = "testing 1 2 3";
const struct shell *shell;
const char *buf;
size_t size;
shell = shell_backend_dummy_get_ptr();
zassert_not_null(shell, "Failed to get shell");
/* Clear the output buffer */
shell_backend_dummy_get_output(shell, &size);
shell_fprintf(shell, SHELL_VT100_COLOR_DEFAULT, "testing %d %s %c",
1, "2", '3');
buf = shell_backend_dummy_get_output(shell, &size);
zassert_true(size >= sizeof(expect), "Expected size > %u, got %d",
sizeof(expect), size);
/*
* There are prompts and various ANSI characters in the output, so just
* check that the string is in there somewhere.
*/
zassert_true(strstr(buf, expect),
"Expected string to contain '%s', got '%s'", expect, buf);
}
void test_main(void)
{
ztest_test_suite(shell_test_suite,
@ -328,7 +355,8 @@ void test_main(void)
ztest_unit_test(test_cmd_resize),
ztest_unit_test(test_shell_module),
ztest_unit_test(test_shell_wildcards_static),
ztest_unit_test(test_shell_wildcards_dynamic));
ztest_unit_test(test_shell_wildcards_dynamic),
ztest_unit_test(test_shell_fprintf));
ztest_run_test_suite(shell_test_suite);
}