From e5509ce87b29f773b045200735bec2903b72eed4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 Oct 2023 19:13:13 -0600 Subject: [PATCH] cli: Create a function to process characters Move most of the inner loop from cread_line() into a new function. This will allow using it from other code. This involves adding a few more members to the state struct. Signed-off-by: Simon Glass --- common/cli_readline.c | 108 ++++++++++++++++++++++++------------------ include/cli.h | 15 ++++++ 2 files changed, 78 insertions(+), 45 deletions(-) diff --git a/common/cli_readline.c b/common/cli_readline.c index f5d1cb0343..62d419bb36 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -253,52 +253,17 @@ static void cread_add_str(char *str, int strsize, int insert, } } -static int cread_line(const char *const prompt, char *buf, unsigned int *len, - int timeout) +int cread_line_process_ch(struct cli_line_state *cls, char ichar) { - struct cli_ch_state s_cch, *cch = &s_cch; - struct cli_line_state s_cls, *cls = &s_cls; - char ichar; - int init_len = strlen(buf); - int first = 1; - - cli_ch_init(cch); - memset(cls, '\0', sizeof(struct cli_line_state)); - cls->insert = true; - - if (init_len) - cread_add_str(buf, init_len, 1, &cls->num, &cls->eol_num, buf, - *len); - - while (1) { - /* Check for saved characters */ - ichar = cli_ch_process(cch, 0); - - if (!ichar) { - if (bootretry_tstc_timeout()) - return -2; /* timed out */ - if (first && timeout) { - u64 etime = endtick(timeout); - - while (!tstc()) { /* while no incoming data */ - if (get_ticks() >= etime) - return -2; /* timed out */ - schedule(); - } - first = 0; - } - - ichar = getcmd_getch(); - ichar = cli_ch_process(cch, ichar); - } + char *buf = cls->buf; /* ichar=0x0 when error occurs in U-Boot getc */ if (!ichar) - continue; + return -EAGAIN; if (ichar == '\n') { putc('\n'); - break; + return 0; } switch (ichar) { @@ -307,7 +272,7 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, break; case CTL_CH('c'): /* ^C - break */ *buf = '\0'; /* discard input */ - return -1; + return -EINTR; case CTL_CH('f'): if (cls->num < cls->eol_num) { getcmd_putch(buf[cls->num]); @@ -405,7 +370,7 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, if (!hline) { getcmd_cbeep(); - continue; + break; } /* nuke the current line */ @@ -419,7 +384,7 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, strcpy(buf, hline); cls->eol_num = strlen(buf); REFRESH_TO_EOL(); - continue; + break; } case '\t': if (IS_ENABLED(CONFIG_AUTO_COMPLETE)) { @@ -432,9 +397,9 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, } buf[cls->num] = '\0'; - col = strlen(prompt) + cls->eol_num; + col = strlen(cls->prompt) + cls->eol_num; num2 = cls->num; - if (cmd_auto_complete(prompt, buf, &num2, &col)) { + if (cmd_auto_complete(cls->prompt, buf, &num2, &col)) { col = num2 - cls->num; cls->num += col; cls->eol_num += col; @@ -444,9 +409,62 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, fallthrough; default: cread_add_char(ichar, cls->insert, &cls->num, &cls->eol_num, - buf, *len); + buf, cls->len); break; } + + return -EAGAIN; +} + +static int cread_line(const char *const prompt, char *buf, unsigned int *len, + int timeout) +{ + struct cli_ch_state s_cch, *cch = &s_cch; + struct cli_line_state s_cls, *cls = &s_cls; + char ichar; + int init_len = strlen(buf); + int first = 1; + + cli_ch_init(cch); + memset(cls, '\0', sizeof(struct cli_line_state)); + cls->insert = true; + cls->len = *len; + cls->prompt = prompt; + cls->buf = buf; + + if (init_len) + cread_add_str(buf, init_len, 1, &cls->num, &cls->eol_num, buf, + *len); + + while (1) { + int ret; + + /* Check for saved characters */ + ichar = cli_ch_process(cch, 0); + + if (!ichar) { + if (bootretry_tstc_timeout()) + return -2; /* timed out */ + if (first && timeout) { + u64 etime = endtick(timeout); + + while (!tstc()) { /* while no incoming data */ + if (get_ticks() >= etime) + return -2; /* timed out */ + schedule(); + } + first = 0; + } + + ichar = getcmd_getch(); + ichar = cli_ch_process(cch, ichar); + } + + ret = cread_line_process_ch(cls, ichar); + if (ret == -EINTR) + return -1; + else if (!ret) + break; } *len = cls->eol_num; buf[cls->eol_num] = '\0'; /* lose the newline */ diff --git a/include/cli.h b/include/cli.h index 1bc1ab8035..bbc5327643 100644 --- a/include/cli.h +++ b/include/cli.h @@ -31,11 +31,16 @@ struct cli_ch_state { * @num: Current cursor position, where 0 is the start * @eol_num: Number of characters in the buffer * @insert: true if in 'insert' mode + * @buf: Buffer containing line + * @prompt: Prompt for the line */ struct cli_line_state { uint num; uint eol_num; + uint len; bool insert; + char *buf; + const char *prompt; }; /** @@ -243,6 +248,16 @@ void cli_ch_init(struct cli_ch_state *cch); */ int cli_ch_process(struct cli_ch_state *cch, int ichar); +/** + * cread_line_process_ch() - Process a character for line input + * + * @cls: CLI line state + * @ichar: Character to process + * Return: 0 if input is complete, with line in cls->buf, -EINTR if input was + * cancelled with Ctrl-C, -EAGAIN if more characters are needed + */ +int cread_line_process_ch(struct cli_line_state *cls, char ichar); + /** cread_print_hist_list() - Print the command-line history list */ void cread_print_hist_list(void); -- 2.39.5