X-Git-Url: https://repo.jachan.dev/J-u-boot.git/blobdiff_plain/33eb0b9eef3360396aa0f650f8e1e01baf6dc181..67254214930cd2cb52279b01690c1f820a7f83db:/common/cli_readline.c diff --git a/common/cli_readline.c b/common/cli_readline.c index f3ba76a62ec..2507be22952 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -85,23 +87,35 @@ static int hist_cur = -1; static unsigned hist_num; static char *hist_list[HIST_MAX]; -static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */ #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1) -static void hist_init(void) +static void getcmd_putchars(int count, int ch) { int i; + for (i = 0; i < count; i++) + getcmd_putch(ch); +} + +static int hist_init(void) +{ + unsigned char *hist; + int i; + hist_max = 0; hist_add_idx = 0; hist_cur = -1; hist_num = 0; - for (i = 0; i < HIST_MAX; i++) { - hist_list[i] = hist_lines[i]; - hist_list[i][0] = '\0'; - } + hist = calloc(HIST_MAX, HIST_SIZE + 1); + if (!hist) + return -ENOMEM; + + for (i = 0; i < HIST_MAX; i++) + hist_list[i] = hist + (i * (HIST_SIZE + 1)); + + return 0; } static void cread_add_to_hist(char *line) @@ -163,7 +177,7 @@ static char *hist_next(void) void cread_print_hist_list(void) { int i; - unsigned long n; + uint n; n = hist_num - hist_max; @@ -180,33 +194,33 @@ void cread_print_hist_list(void) } #define BEGINNING_OF_LINE() { \ - while (num) { \ + while (cls->num) { \ getcmd_putch(CTL_BACKSPACE); \ - num--; \ + cls->num--; \ } \ } #define ERASE_TO_EOL() { \ - if (num < eol_num) { \ - printf("%*s", (int)(eol_num - num), ""); \ + if (cls->num < cls->eol_num) { \ + printf("%*s", (int)(cls->eol_num - cls->num), ""); \ do { \ getcmd_putch(CTL_BACKSPACE); \ - } while (--eol_num > num); \ + } while (--cls->eol_num > cls->num); \ } \ } -#define REFRESH_TO_EOL() { \ - if (num < eol_num) { \ - wlen = eol_num - num; \ - putnstr(buf + num, wlen); \ - num = eol_num; \ - } \ +#define REFRESH_TO_EOL() { \ + if (cls->num < cls->eol_num) { \ + uint wlen = cls->eol_num - cls->num; \ + putnstr(buf + cls->num, wlen); \ + cls->num = cls->eol_num; \ + } \ } -static void cread_add_char(char ichar, int insert, unsigned long *num, - unsigned long *eol_num, char *buf, unsigned long len) +static void cread_add_char(char ichar, int insert, uint *num, + uint *eol_num, char *buf, uint len) { - unsigned long wlen; + uint wlen; /* room ??? */ if (insert || *num == *eol_num) { @@ -237,8 +251,7 @@ static void cread_add_char(char ichar, int insert, unsigned long *num, } static void cread_add_str(char *str, int strsize, int insert, - unsigned long *num, unsigned long *eol_num, - char *buf, unsigned long len) + uint *num, uint *eol_num, char *buf, uint len) { while (strsize--) { cread_add_char(*str, insert, num, eol_num, buf, len); @@ -246,121 +259,115 @@ 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; - unsigned long num = 0; - unsigned long eol_num = 0; - unsigned long wlen; - char ichar; - int insert = 1; - int init_len = strlen(buf); - int first = 1; - - cli_ch_init(cch); + char *buf = cls->buf; - if (init_len) - cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); + /* ichar=0x0 when error occurs in U-Boot getc */ + if (!ichar) + return -EAGAIN; - 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; - } + if (ichar == '\n') { + putc('\n'); + buf[cls->eol_num] = '\0'; /* terminate the string */ + return 0; + } - ichar = getcmd_getch(); - ichar = cli_ch_process(cch, ichar); + switch (ichar) { + case CTL_CH('a'): + BEGINNING_OF_LINE(); + break; + case CTL_CH('c'): /* ^C - break */ + *buf = '\0'; /* discard input */ + return -EINTR; + case CTL_CH('f'): + if (cls->num < cls->eol_num) { + getcmd_putch(buf[cls->num]); + cls->num++; } - - /* ichar=0x0 when error occurs in U-Boot getc */ - if (!ichar) - continue; - - if (ichar == '\n') { - putc('\n'); - break; + break; + case CTL_CH('b'): + if (cls->num) { + getcmd_putch(CTL_BACKSPACE); + cls->num--; } - - switch (ichar) { - case CTL_CH('a'): - BEGINNING_OF_LINE(); - break; - case CTL_CH('c'): /* ^C - break */ - *buf = '\0'; /* discard input */ - return -1; - case CTL_CH('f'): - if (num < eol_num) { - getcmd_putch(buf[num]); - num++; - } - break; - case CTL_CH('b'): - if (num) { - getcmd_putch(CTL_BACKSPACE); - num--; + break; + case CTL_CH('d'): + if (cls->num < cls->eol_num) { + uint wlen; + + wlen = cls->eol_num - cls->num - 1; + if (wlen) { + memmove(&buf[cls->num], &buf[cls->num + 1], + wlen); + putnstr(buf + cls->num, wlen); } - break; - case CTL_CH('d'): - if (num < eol_num) { - wlen = eol_num - num - 1; - if (wlen) { - memmove(&buf[num], &buf[num+1], wlen); - putnstr(buf + num, wlen); - } - getcmd_putch(' '); - do { - getcmd_putch(CTL_BACKSPACE); - } while (wlen--); - eol_num--; - } - break; - case CTL_CH('k'): - ERASE_TO_EOL(); - break; - case CTL_CH('e'): - REFRESH_TO_EOL(); - break; - case CTL_CH('o'): - insert = !insert; - break; - case CTL_CH('x'): - case CTL_CH('u'): - BEGINNING_OF_LINE(); - ERASE_TO_EOL(); - break; - case DEL: - case DEL7: - case 8: - if (num) { - wlen = eol_num - num; - num--; - memmove(&buf[num], &buf[num+1], wlen); + getcmd_putch(' '); + do { getcmd_putch(CTL_BACKSPACE); - putnstr(buf + num, wlen); - getcmd_putch(' '); - do { - getcmd_putch(CTL_BACKSPACE); - } while (wlen--); - eol_num--; - } - break; - case CTL_CH('p'): - case CTL_CH('n'): - { + } while (wlen--); + cls->eol_num--; + } + break; + case CTL_CH('k'): + ERASE_TO_EOL(); + break; + case CTL_CH('e'): + REFRESH_TO_EOL(); + break; + case CTL_CH('o'): + cls->insert = !cls->insert; + break; + case CTL_CH('w'): + if (cls->num) { + uint base, wlen; + + for (base = cls->num - 1; + base >= 0 && buf[base] == ' ';) + base--; + for (; base > 0 && buf[base - 1] != ' ';) + base--; + + /* now delete chars from base to cls->num */ + wlen = cls->num - base; + cls->eol_num -= wlen; + memmove(&buf[base], &buf[cls->num], + cls->eol_num - base + 1); + cls->num = base; + getcmd_putchars(wlen, CTL_BACKSPACE); + puts(buf + base); + getcmd_putchars(wlen, ' '); + getcmd_putchars(wlen + cls->eol_num - cls->num, + CTL_BACKSPACE); + } + break; + case CTL_CH('x'): + case CTL_CH('u'): + BEGINNING_OF_LINE(); + ERASE_TO_EOL(); + break; + case DEL: + case DEL7: + case 8: + if (cls->num) { + uint wlen; + + wlen = cls->eol_num - cls->num; + cls->num--; + memmove(&buf[cls->num], &buf[cls->num + 1], wlen); + getcmd_putch(CTL_BACKSPACE); + putnstr(buf + cls->num, wlen); + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (wlen--); + cls->eol_num--; + } + break; + case CTL_CH('p'): + case CTL_CH('n'): + if (cls->history) { char *hline; if (ichar == CTL_CH('p')) @@ -370,7 +377,7 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, if (!hline) { getcmd_cbeep(); - continue; + break; } /* nuke the current line */ @@ -382,39 +389,106 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, /* copy new line into place and display */ strcpy(buf, hline); - eol_num = strlen(buf); + cls->eol_num = strlen(buf); REFRESH_TO_EOL(); - continue; + break; } -#ifdef CONFIG_AUTO_COMPLETE - case '\t': { + break; + case '\t': + if (IS_ENABLED(CONFIG_AUTO_COMPLETE) && cls->cmd_complete) { int num2, col; /* do not autocomplete when in the middle */ - if (num < eol_num) { + if (cls->num < cls->eol_num) { getcmd_cbeep(); break; } - buf[num] = '\0'; - col = strlen(prompt) + eol_num; - num2 = num; - if (cmd_auto_complete(prompt, buf, &num2, &col)) { - col = num2 - num; - num += col; - eol_num += col; + buf[cls->num] = '\0'; + col = strlen(cls->prompt) + cls->eol_num; + num2 = cls->num; + if (cmd_auto_complete(cls->prompt, buf, &num2, &col)) { + col = num2 - cls->num; + cls->num += col; + cls->eol_num += col; } break; } -#endif - default: - cread_add_char(ichar, insert, &num, &eol_num, buf, - *len); - break; + fallthrough; + default: + cread_add_char(ichar, cls->insert, &cls->num, &cls->eol_num, + buf, cls->len); + break; + } + + /* + * keep the string terminated...if we added a char at the end then we + * want a \0 after it + */ + buf[cls->eol_num] = '\0'; + + return -EAGAIN; +} + +void cli_cread_init(struct cli_line_state *cls, char *buf, uint buf_size) +{ + int init_len = strlen(buf); + + memset(cls, '\0', sizeof(struct cli_line_state)); + cls->insert = true; + cls->buf = buf; + cls->len = buf_size; + + if (init_len) + cread_add_str(buf, init_len, 0, &cls->num, &cls->eol_num, buf, + buf_size); +} + +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 first = 1; + + cli_ch_init(cch); + cli_cread_init(cls, buf, *len); + cls->prompt = prompt; + cls->history = true; + cls->cmd_complete = true; + + 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 = eol_num; - buf[eol_num] = '\0'; /* lose the newline */ + *len = cls->eol_num; if (buf[0] && buf[0] != CREAD_HIST_CHAR) cread_add_to_hist(buf); @@ -423,6 +497,19 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, return 0; } +#else /* !CONFIG_CMDLINE_EDITING */ + +static inline int hist_init(void) +{ + return 0; +} + +static int cread_line(const char *const prompt, char *buf, unsigned int *len, + int timeout) +{ + return 0; +} + #endif /* CONFIG_CMDLINE_EDITING */ /****************************************************************************/ @@ -453,7 +540,7 @@ static int cread_line_simple(const char *const prompt, char *p) int n = 0; /* buffer index */ int plen = 0; /* prompt length */ int col; /* output column cnt */ - char c; + int c; /* print prompt */ if (prompt) { @@ -507,14 +594,15 @@ static int cread_line_simple(const char *const prompt, char *p) continue; default: - /* - * Must be a normal character then - */ - if (n < CONFIG_SYS_CBSIZE-2) { - if (c == '\t') { /* expand TABs */ -#ifdef CONFIG_AUTO_COMPLETE + /* Must be a normal character then */ + if (n >= CONFIG_SYS_CBSIZE - 2) { /* Buffer full */ + putc('\a'); + break; + } + if (c == '\t') { /* expand TABs */ + if (IS_ENABLED(CONFIG_AUTO_COMPLETE)) { /* - * if auto completion triggered just + * if auto-completion triggered just * continue */ *p = '\0'; @@ -524,26 +612,24 @@ static int cread_line_simple(const char *const prompt, char *p) p = p_buf + n; /* reset */ continue; } -#endif - puts(tab_seq + (col & 07)); - col += 8 - (col & 07); - } else { - char __maybe_unused buf[2]; - - /* - * Echo input using puts() to force an - * LCD flush if we are using an LCD - */ - ++col; - buf[0] = c; - buf[1] = '\0'; - puts(buf); } - *p++ = c; - ++n; - } else { /* Buffer full */ - putc('\a'); + puts(tab_seq + (col & 07)); + col += 8 - (col & 07); + } else { + char __maybe_unused buf[2]; + + /* + * Echo input using puts() to force an LCD + * flush if we are using an LCD + */ + ++col; + buf[0] = c; + buf[1] = '\0'; + puts(buf); } + *p++ = c; + ++n; + break; } } } @@ -552,8 +638,7 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer, int timeout) { char *p = buffer; -#ifdef CONFIG_CMDLINE_EDITING - unsigned int len = CONFIG_SYS_CBSIZE; + uint len = CONFIG_SYS_CBSIZE; int rc; static int initted; @@ -563,10 +648,11 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer, * Revert to non-history version if still * running from flash. */ - if (gd->flags & GD_FLG_RELOC) { + if (IS_ENABLED(CONFIG_CMDLINE_EDITING) && (gd->flags & GD_FLG_RELOC)) { if (!initted) { - hist_init(); - initted = 1; + rc = hist_init(); + if (rc == 0) + initted = 1; } if (prompt) @@ -576,9 +662,6 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer, return rc < 0 ? rc : len; } else { -#endif /* CONFIG_CMDLINE_EDITING */ return cread_line_simple(prompt, p); -#ifdef CONFIG_CMDLINE_EDITING } -#endif }