2018-11-27 00:09:56 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "shell_ops.h"
|
|
|
|
#include "shell_help.h"
|
|
|
|
#include "shell_utils.h"
|
|
|
|
|
2019-01-29 18:40:08 +08:00
|
|
|
|
2018-11-27 00:09:56 +08:00
|
|
|
/* Function prints a string on terminal screen with requested margin.
|
|
|
|
* It takes care to not divide words.
|
|
|
|
* shell Pointer to shell instance.
|
|
|
|
* p_str Pointer to string to be printed.
|
|
|
|
* terminal_offset Requested left margin.
|
|
|
|
* offset_first_line Add margin to the first printed line.
|
|
|
|
*/
|
|
|
|
static void formatted_text_print(const struct shell *shell, const char *str,
|
|
|
|
size_t terminal_offset, bool offset_first_line)
|
|
|
|
{
|
|
|
|
size_t offset = 0;
|
|
|
|
size_t length;
|
|
|
|
|
|
|
|
if (str == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset_first_line) {
|
|
|
|
shell_op_cursor_horiz_move(shell, terminal_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Skipping whitespace. */
|
|
|
|
while (isspace((int) *(str + offset))) {
|
|
|
|
++offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
size_t idx = 0;
|
|
|
|
|
|
|
|
length = shell_strlen(str) - offset;
|
|
|
|
|
|
|
|
if (length <=
|
|
|
|
shell->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) {
|
|
|
|
for (idx = 0; idx < length; idx++) {
|
|
|
|
if (*(str + offset + idx) == '\n') {
|
|
|
|
transport_buffer_flush(shell);
|
|
|
|
shell_write(shell, str + offset, idx);
|
|
|
|
offset += idx + 1;
|
|
|
|
cursor_next_line_move(shell);
|
|
|
|
shell_op_cursor_horiz_move(shell,
|
|
|
|
terminal_offset);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* String will fit in one line. */
|
|
|
|
shell_raw_fprintf(shell->fprintf_ctx, str + offset);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* String is longer than terminal line so text needs to
|
|
|
|
* divide in the way to not divide words.
|
|
|
|
*/
|
|
|
|
length = shell->ctx->vt100_ctx.cons.terminal_wid
|
|
|
|
- terminal_offset;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
/* Determining line break. */
|
|
|
|
if (isspace((int) (*(str + offset + idx)))) {
|
|
|
|
length = idx;
|
|
|
|
if (*(str + offset + idx) == '\n') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((idx + terminal_offset) >=
|
|
|
|
shell->ctx->vt100_ctx.cons.terminal_wid) {
|
|
|
|
/* End of line reached. */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Writing one line, fprintf IO buffer must be flushed
|
|
|
|
* before calling shell_write.
|
|
|
|
*/
|
|
|
|
transport_buffer_flush(shell);
|
|
|
|
shell_write(shell, str + offset, length);
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
/* Calculating text offset to ensure that next line will
|
|
|
|
* not begin with a space.
|
|
|
|
*/
|
|
|
|
while (isspace((int) (*(str + offset)))) {
|
|
|
|
++offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
cursor_next_line_move(shell);
|
|
|
|
shell_op_cursor_horiz_move(shell, terminal_offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
cursor_next_line_move(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void help_item_print(const struct shell *shell, const char *item_name,
|
|
|
|
u16_t item_name_width, const char *item_help)
|
|
|
|
{
|
|
|
|
static const u8_t tabulator[] = " ";
|
|
|
|
const u16_t offset = 2 * strlen(tabulator) + item_name_width + 1;
|
|
|
|
|
|
|
|
if (item_name == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) && !IS_ENABLED(CONFIG_ARCH_POSIX)) {
|
|
|
|
/* print option name */
|
shell: allow commands to suspend shell thread
It was possible to deadlock the shell when command
suspended shell's thread and next another thread wanted
to print something on the shell.
To avoid that shell releases mutex before entering command
handler. Due to this change some adapations to shell
internal print functions have been applied.
This change addresses following usecase:
1. A command handler needs to call a (system) function which
communicate results via a callback, and this callback is expected
to print these results. The callback is called by the system from
another thread.
2. To achieve that, the handler needs to pass `struct shell *`
to callbacks, but also some other data specific to callback.
Thus, handles allocates some structure will those fields on
the stack.
3. The handler schedules this callback to be called.
4. As a reference to stack structure is passed to the callback,
the handler can't return immediately (or stack data will go out
of scope and will be overwritten).
5. So, the handler blocks waiting for callback to finish.
Previously, this scenario led to deadlock when the callback
trying or print to shell. With these changes, it just works,
as long as main handler and callback serialize there access
to the shell structure (i.e. when callback prints, the main
handler is blocked waiting for its completion).
Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
2019-02-12 22:38:16 +08:00
|
|
|
shell_internal_fprintf(shell, SHELL_NORMAL, "%s%-*s%s:",
|
|
|
|
tabulator,
|
|
|
|
item_name_width, item_name,
|
|
|
|
tabulator);
|
2018-11-27 00:09:56 +08:00
|
|
|
} else {
|
|
|
|
u16_t tmp = item_name_width - strlen(item_name);
|
|
|
|
char space = ' ';
|
|
|
|
|
shell: allow commands to suspend shell thread
It was possible to deadlock the shell when command
suspended shell's thread and next another thread wanted
to print something on the shell.
To avoid that shell releases mutex before entering command
handler. Due to this change some adapations to shell
internal print functions have been applied.
This change addresses following usecase:
1. A command handler needs to call a (system) function which
communicate results via a callback, and this callback is expected
to print these results. The callback is called by the system from
another thread.
2. To achieve that, the handler needs to pass `struct shell *`
to callbacks, but also some other data specific to callback.
Thus, handles allocates some structure will those fields on
the stack.
3. The handler schedules this callback to be called.
4. As a reference to stack structure is passed to the callback,
the handler can't return immediately (or stack data will go out
of scope and will be overwritten).
5. So, the handler blocks waiting for callback to finish.
Previously, this scenario led to deadlock when the callback
trying or print to shell. With these changes, it just works,
as long as main handler and callback serialize there access
to the shell structure (i.e. when callback prints, the main
handler is blocked waiting for its completion).
Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
2019-02-12 22:38:16 +08:00
|
|
|
shell_internal_fprintf(shell, SHELL_NORMAL, "%s%s", tabulator,
|
|
|
|
item_name);
|
2018-11-27 00:09:56 +08:00
|
|
|
for (u16_t i = 0; i < tmp; i++) {
|
|
|
|
shell_write(shell, &space, 1);
|
|
|
|
}
|
shell: allow commands to suspend shell thread
It was possible to deadlock the shell when command
suspended shell's thread and next another thread wanted
to print something on the shell.
To avoid that shell releases mutex before entering command
handler. Due to this change some adapations to shell
internal print functions have been applied.
This change addresses following usecase:
1. A command handler needs to call a (system) function which
communicate results via a callback, and this callback is expected
to print these results. The callback is called by the system from
another thread.
2. To achieve that, the handler needs to pass `struct shell *`
to callbacks, but also some other data specific to callback.
Thus, handles allocates some structure will those fields on
the stack.
3. The handler schedules this callback to be called.
4. As a reference to stack structure is passed to the callback,
the handler can't return immediately (or stack data will go out
of scope and will be overwritten).
5. So, the handler blocks waiting for callback to finish.
Previously, this scenario led to deadlock when the callback
trying or print to shell. With these changes, it just works,
as long as main handler and callback serialize there access
to the shell structure (i.e. when callback prints, the main
handler is blocked waiting for its completion).
Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
2019-02-12 22:38:16 +08:00
|
|
|
shell_internal_fprintf(shell, SHELL_NORMAL, "%s:", tabulator);
|
2018-11-27 00:09:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (item_help == NULL) {
|
|
|
|
cursor_next_line_move(shell);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* print option help */
|
|
|
|
formatted_text_print(shell, item_help, offset, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function is printing command help, its subcommands name and subcommands
|
|
|
|
* help string.
|
|
|
|
*/
|
|
|
|
void shell_help_subcmd_print(const struct shell *shell)
|
|
|
|
{
|
|
|
|
const struct shell_static_entry *entry = NULL;
|
|
|
|
struct shell_static_entry static_entry;
|
2019-03-27 09:57:45 +08:00
|
|
|
u16_t longest_syntax = 0U;
|
2018-11-27 00:09:56 +08:00
|
|
|
size_t cmd_idx = 0;
|
|
|
|
|
|
|
|
/* Checking if there are any subcommands available. */
|
|
|
|
if (!shell->ctx->active_cmd.subcmd) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Searching for the longest subcommand to print. */
|
|
|
|
do {
|
2019-05-16 17:02:53 +08:00
|
|
|
shell_cmd_get(shell, shell->ctx->active_cmd.subcmd,
|
2018-11-27 00:09:56 +08:00
|
|
|
!SHELL_CMD_ROOT_LVL,
|
|
|
|
cmd_idx++, &entry, &static_entry);
|
|
|
|
|
|
|
|
if (!entry) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16_t len = shell_strlen(entry->syntax);
|
|
|
|
|
|
|
|
longest_syntax = longest_syntax > len ? longest_syntax : len;
|
|
|
|
} while (cmd_idx != 0); /* too many commands */
|
|
|
|
|
|
|
|
if (cmd_idx == 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
shell: allow commands to suspend shell thread
It was possible to deadlock the shell when command
suspended shell's thread and next another thread wanted
to print something on the shell.
To avoid that shell releases mutex before entering command
handler. Due to this change some adapations to shell
internal print functions have been applied.
This change addresses following usecase:
1. A command handler needs to call a (system) function which
communicate results via a callback, and this callback is expected
to print these results. The callback is called by the system from
another thread.
2. To achieve that, the handler needs to pass `struct shell *`
to callbacks, but also some other data specific to callback.
Thus, handles allocates some structure will those fields on
the stack.
3. The handler schedules this callback to be called.
4. As a reference to stack structure is passed to the callback,
the handler can't return immediately (or stack data will go out
of scope and will be overwritten).
5. So, the handler blocks waiting for callback to finish.
Previously, this scenario led to deadlock when the callback
trying or print to shell. With these changes, it just works,
as long as main handler and callback serialize there access
to the shell structure (i.e. when callback prints, the main
handler is blocked waiting for its completion).
Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
2019-02-12 22:38:16 +08:00
|
|
|
shell_internal_fprintf(shell, SHELL_NORMAL, "Subcommands:\n");
|
2018-11-27 00:09:56 +08:00
|
|
|
|
|
|
|
/* Printing subcommands and help string (if exists). */
|
|
|
|
cmd_idx = 0;
|
|
|
|
|
|
|
|
while (true) {
|
2019-05-16 17:02:53 +08:00
|
|
|
shell_cmd_get(shell, shell->ctx->active_cmd.subcmd,
|
2018-11-27 00:09:56 +08:00
|
|
|
!SHELL_CMD_ROOT_LVL,
|
|
|
|
cmd_idx++, &entry, &static_entry);
|
|
|
|
|
|
|
|
if (entry == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
help_item_print(shell, entry->syntax, longest_syntax,
|
|
|
|
entry->help);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void shell_help_cmd_print(const struct shell *shell)
|
|
|
|
{
|
|
|
|
static const char cmd_sep[] = " - "; /* commands separator */
|
|
|
|
|
|
|
|
u16_t field_width = shell_strlen(shell->ctx->active_cmd.syntax) +
|
|
|
|
shell_strlen(cmd_sep);
|
|
|
|
|
shell: allow commands to suspend shell thread
It was possible to deadlock the shell when command
suspended shell's thread and next another thread wanted
to print something on the shell.
To avoid that shell releases mutex before entering command
handler. Due to this change some adapations to shell
internal print functions have been applied.
This change addresses following usecase:
1. A command handler needs to call a (system) function which
communicate results via a callback, and this callback is expected
to print these results. The callback is called by the system from
another thread.
2. To achieve that, the handler needs to pass `struct shell *`
to callbacks, but also some other data specific to callback.
Thus, handles allocates some structure will those fields on
the stack.
3. The handler schedules this callback to be called.
4. As a reference to stack structure is passed to the callback,
the handler can't return immediately (or stack data will go out
of scope and will be overwritten).
5. So, the handler blocks waiting for callback to finish.
Previously, this scenario led to deadlock when the callback
trying or print to shell. With these changes, it just works,
as long as main handler and callback serialize there access
to the shell structure (i.e. when callback prints, the main
handler is blocked waiting for its completion).
Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
2019-02-12 22:38:16 +08:00
|
|
|
shell_internal_fprintf(shell, SHELL_NORMAL, "%s%s",
|
|
|
|
shell->ctx->active_cmd.syntax, cmd_sep);
|
2018-11-27 00:09:56 +08:00
|
|
|
|
|
|
|
formatted_text_print(shell, shell->ctx->active_cmd.help,
|
|
|
|
field_width, false);
|
|
|
|
}
|
|
|
|
|