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 <s...@chromium.org>
---

 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 f5d1cb03433..62d419bb36a 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 1bc1ab8035c..bbc53276435 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.42.0.459.ge4e396fd5e-goog

Reply via email to