diff options
author | Simon Glass <sjg@chromium.org> | 2023-01-06 08:52:20 -0600 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-01-16 14:14:11 -0500 |
commit | b08e9d4b6632a72b91306690d552c125b071441e (patch) | |
tree | 948f27c1423537f8e46e78fc12352b51ec0a0294 /include/cli.h | |
parent | 7d850f85aad74ae907290ba6f911d362a0478e61 (diff) | |
download | u-boot-b08e9d4b6632a72b91306690d552c125b071441e.zip u-boot-b08e9d4b6632a72b91306690d552c125b071441e.tar.gz u-boot-b08e9d4b6632a72b91306690d552c125b071441e.tar.bz2 |
cli: Move readline character-processing to a state machine
The current cread_line() function is very long. It handles the escape
processing inline. The menu command does similar processing but at the
character level, so there is some duplication.
Split the character processing into a new function cli_ch_process() which
processes individual characters and returns the resulting input character,
taking account of escape sequences. It requires the caller to set up and
maintain its state.
Update cread_line() to use this new function.
The only intended functional change is that an invalid escape sequence
does not add invalid/control characters into the input buffer, but instead
discards these.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'include/cli.h')
-rw-r--r-- | include/cli.h | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/include/cli.h b/include/cli.h index ba5b8eb..863519e 100644 --- a/include/cli.h +++ b/include/cli.h @@ -7,6 +7,21 @@ #ifndef __CLI_H #define __CLI_H +#include <stdbool.h> + +/** + * struct cli_ch_state - state information for reading cmdline characters + * + * @esc_len: Number of escape characters read so far + * @esc_save: Escape characters collected so far + * @emit_upto: Next character to emit from esc_save (0 if not emitting) + */ +struct cli_ch_state { + int esc_len; + char esc_save[8]; + int emit_upto; +}; + /** * Go into the command loop * @@ -154,5 +169,62 @@ void cli_loop(void); void cli_init(void); #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) +#define CTL_CH(c) ((c) - 'a' + 1) + +/** + * cli_ch_init() - Set up the initial state to process input characters + * + * @cch: State to set up + */ +void cli_ch_init(struct cli_ch_state *cch); + +/** + * cli_ch_process() - Process an input character + * + * When @ichar is 0, this function returns any characters from an invalid escape + * sequence which are still pending in the buffer + * + * Otherwise it processes the input character. If it is an escape character, + * then an escape sequence is started and the function returns 0. If we are in + * the middle of an escape sequence, the character is processed and may result + * in returning 0 (if more characters are needed) or a valid character (if + * @ichar finishes the sequence). + * + * If @ichar is a valid character and there is no escape sequence in progress, + * then it is returned as is. + * + * If the Enter key is pressed, '\n' is returned. + * + * Usage should be like this:: + * + * struct cli_ch_state cch; + * + * cli_ch_init(cch); + * do + * { + * int ichar, ch; + * + * ichar = cli_ch_process(cch, 0); + * if (!ichar) { + * ch = getchar(); + * ichar = cli_ch_process(cch, ch); + * } + * (handle the ichar character) + * } while (!done) + * + * If tstc() is used to look for keypresses, this function can be called with + * @ichar set to -ETIMEDOUT if there is no character after 5-10ms. This allows + * the ambgiuity between the Escape key and the arrow keys (which generate an + * escape character followed by other characters) to be resolved. + * + * @cch: Current state + * @ichar: Input character to process, or 0 if none, or -ETIMEDOUT if no + * character has been received within a small number of milliseconds (this + * cancels any existing escape sequence and allows pressing the Escape key to + * work) + * Returns: Resulting input character after processing, 0 if none, '\e' if + * an existing escape sequence was cancelled + */ +int cli_ch_process(struct cli_ch_state *cch, int ichar); #endif |