Commit 6493ccc7cf2357081267effffa7d345e50d68d00

Authored by Simon Glass
Committed by Tom Rini
1 parent 18d66533ac

Split out simple parser and readline into separate files

It doesn't make sense to have the simple parser and the readline code
all in main. Split them out into separate files.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 5 changed files with 1026 additions and 1013 deletions Side-by-side Diff

... ... @@ -11,7 +11,14 @@
11 11 obj-y += command.o
12 12 obj-y += exports.o
13 13 obj-y += hash.o
14   -obj-$(CONFIG_SYS_HUSH_PARSER) += cli_hush.o
  14 +ifdef CONFIG_SYS_HUSH_PARSER
  15 +obj-y += cli_hush.o
  16 +endif
  17 +
  18 +# We always have this since drivers/ddr/fs/interactive.c needs it
  19 +obj-y += cli_simple.o
  20 +
  21 +obj-y += cli_readline.o
15 22 obj-y += s_record.o
16 23 obj-y += xyzModem.o
17 24 obj-y += cmd_disk.o
common/cli_readline.c
  1 +/*
  2 + * (C) Copyright 2000
  3 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4 + *
  5 + * Add to readline cmdline-editing by
  6 + * (C) Copyright 2005
  7 + * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
  8 + *
  9 + * SPDX-License-Identifier: GPL-2.0+
  10 + */
  11 +
  12 +#include <common.h>
  13 +#include <cli.h>
  14 +#include <watchdog.h>
  15 +
  16 +DECLARE_GLOBAL_DATA_PTR;
  17 +
  18 +static const char erase_seq[] = "\b \b"; /* erase sequence */
  19 +static const char tab_seq[] = " "; /* used to expand TABs */
  20 +
  21 +#ifdef CONFIG_BOOT_RETRY_TIME
  22 +static uint64_t endtime; /* must be set, default is instant timeout */
  23 +static int retry_time = -1; /* -1 so can call readline before main_loop */
  24 +#endif
  25 +
  26 +char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */
  27 +
  28 +#ifndef CONFIG_BOOT_RETRY_MIN
  29 +#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
  30 +#endif
  31 +
  32 +static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen)
  33 +{
  34 + char *s;
  35 +
  36 + if (*np == 0)
  37 + return p;
  38 +
  39 + if (*(--p) == '\t') { /* will retype the whole line */
  40 + while (*colp > plen) {
  41 + puts(erase_seq);
  42 + (*colp)--;
  43 + }
  44 + for (s = buffer; s < p; ++s) {
  45 + if (*s == '\t') {
  46 + puts(tab_seq + ((*colp) & 07));
  47 + *colp += 8 - ((*colp) & 07);
  48 + } else {
  49 + ++(*colp);
  50 + putc(*s);
  51 + }
  52 + }
  53 + } else {
  54 + puts(erase_seq);
  55 + (*colp)--;
  56 + }
  57 + (*np)--;
  58 +
  59 + return p;
  60 +}
  61 +
  62 +#ifdef CONFIG_CMDLINE_EDITING
  63 +
  64 +/*
  65 + * cmdline-editing related codes from vivi.
  66 + * Author: Janghoon Lyu <nandy@mizi.com>
  67 + */
  68 +
  69 +#define putnstr(str, n) printf("%.*s", (int)n, str)
  70 +
  71 +#define CTL_CH(c) ((c) - 'a' + 1)
  72 +#define CTL_BACKSPACE ('\b')
  73 +#define DEL ((char)255)
  74 +#define DEL7 ((char)127)
  75 +#define CREAD_HIST_CHAR ('!')
  76 +
  77 +#define getcmd_putch(ch) putc(ch)
  78 +#define getcmd_getch() getc()
  79 +#define getcmd_cbeep() getcmd_putch('\a')
  80 +
  81 +#define HIST_MAX 20
  82 +#define HIST_SIZE CONFIG_SYS_CBSIZE
  83 +
  84 +static int hist_max;
  85 +static int hist_add_idx;
  86 +static int hist_cur = -1;
  87 +static unsigned hist_num;
  88 +
  89 +static char *hist_list[HIST_MAX];
  90 +static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */
  91 +
  92 +#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
  93 +
  94 +static void hist_init(void)
  95 +{
  96 + int i;
  97 +
  98 + hist_max = 0;
  99 + hist_add_idx = 0;
  100 + hist_cur = -1;
  101 + hist_num = 0;
  102 +
  103 + for (i = 0; i < HIST_MAX; i++) {
  104 + hist_list[i] = hist_lines[i];
  105 + hist_list[i][0] = '\0';
  106 + }
  107 +}
  108 +
  109 +static void cread_add_to_hist(char *line)
  110 +{
  111 + strcpy(hist_list[hist_add_idx], line);
  112 +
  113 + if (++hist_add_idx >= HIST_MAX)
  114 + hist_add_idx = 0;
  115 +
  116 + if (hist_add_idx > hist_max)
  117 + hist_max = hist_add_idx;
  118 +
  119 + hist_num++;
  120 +}
  121 +
  122 +static char *hist_prev(void)
  123 +{
  124 + char *ret;
  125 + int old_cur;
  126 +
  127 + if (hist_cur < 0)
  128 + return NULL;
  129 +
  130 + old_cur = hist_cur;
  131 + if (--hist_cur < 0)
  132 + hist_cur = hist_max;
  133 +
  134 + if (hist_cur == hist_add_idx) {
  135 + hist_cur = old_cur;
  136 + ret = NULL;
  137 + } else {
  138 + ret = hist_list[hist_cur];
  139 + }
  140 +
  141 + return ret;
  142 +}
  143 +
  144 +static char *hist_next(void)
  145 +{
  146 + char *ret;
  147 +
  148 + if (hist_cur < 0)
  149 + return NULL;
  150 +
  151 + if (hist_cur == hist_add_idx)
  152 + return NULL;
  153 +
  154 + if (++hist_cur > hist_max)
  155 + hist_cur = 0;
  156 +
  157 + if (hist_cur == hist_add_idx)
  158 + ret = "";
  159 + else
  160 + ret = hist_list[hist_cur];
  161 +
  162 + return ret;
  163 +}
  164 +
  165 +#ifndef CONFIG_CMDLINE_EDITING
  166 +static void cread_print_hist_list(void)
  167 +{
  168 + int i;
  169 + unsigned long n;
  170 +
  171 + n = hist_num - hist_max;
  172 +
  173 + i = hist_add_idx + 1;
  174 + while (1) {
  175 + if (i > hist_max)
  176 + i = 0;
  177 + if (i == hist_add_idx)
  178 + break;
  179 + printf("%s\n", hist_list[i]);
  180 + n++;
  181 + i++;
  182 + }
  183 +}
  184 +#endif /* CONFIG_CMDLINE_EDITING */
  185 +
  186 +#define BEGINNING_OF_LINE() { \
  187 + while (num) { \
  188 + getcmd_putch(CTL_BACKSPACE); \
  189 + num--; \
  190 + } \
  191 +}
  192 +
  193 +#define ERASE_TO_EOL() { \
  194 + if (num < eol_num) { \
  195 + printf("%*s", (int)(eol_num - num), ""); \
  196 + do { \
  197 + getcmd_putch(CTL_BACKSPACE); \
  198 + } while (--eol_num > num); \
  199 + } \
  200 +}
  201 +
  202 +#define REFRESH_TO_EOL() { \
  203 + if (num < eol_num) { \
  204 + wlen = eol_num - num; \
  205 + putnstr(buf + num, wlen); \
  206 + num = eol_num; \
  207 + } \
  208 +}
  209 +
  210 +static void cread_add_char(char ichar, int insert, unsigned long *num,
  211 + unsigned long *eol_num, char *buf, unsigned long len)
  212 +{
  213 + unsigned long wlen;
  214 +
  215 + /* room ??? */
  216 + if (insert || *num == *eol_num) {
  217 + if (*eol_num > len - 1) {
  218 + getcmd_cbeep();
  219 + return;
  220 + }
  221 + (*eol_num)++;
  222 + }
  223 +
  224 + if (insert) {
  225 + wlen = *eol_num - *num;
  226 + if (wlen > 1)
  227 + memmove(&buf[*num+1], &buf[*num], wlen-1);
  228 +
  229 + buf[*num] = ichar;
  230 + putnstr(buf + *num, wlen);
  231 + (*num)++;
  232 + while (--wlen)
  233 + getcmd_putch(CTL_BACKSPACE);
  234 + } else {
  235 + /* echo the character */
  236 + wlen = 1;
  237 + buf[*num] = ichar;
  238 + putnstr(buf + *num, wlen);
  239 + (*num)++;
  240 + }
  241 +}
  242 +
  243 +static void cread_add_str(char *str, int strsize, int insert,
  244 + unsigned long *num, unsigned long *eol_num,
  245 + char *buf, unsigned long len)
  246 +{
  247 + while (strsize--) {
  248 + cread_add_char(*str, insert, num, eol_num, buf, len);
  249 + str++;
  250 + }
  251 +}
  252 +
  253 +static int cread_line(const char *const prompt, char *buf, unsigned int *len,
  254 + int timeout)
  255 +{
  256 + unsigned long num = 0;
  257 + unsigned long eol_num = 0;
  258 + unsigned long wlen;
  259 + char ichar;
  260 + int insert = 1;
  261 + int esc_len = 0;
  262 + char esc_save[8];
  263 + int init_len = strlen(buf);
  264 + int first = 1;
  265 +
  266 + if (init_len)
  267 + cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
  268 +
  269 + while (1) {
  270 +#ifdef CONFIG_BOOT_RETRY_TIME
  271 + while (!tstc()) { /* while no incoming data */
  272 + if (retry_time >= 0 && get_ticks() > endtime)
  273 + return -2; /* timed out */
  274 + WATCHDOG_RESET();
  275 + }
  276 +#endif
  277 + if (first && timeout) {
  278 + uint64_t etime = endtick(timeout);
  279 +
  280 + while (!tstc()) { /* while no incoming data */
  281 + if (get_ticks() >= etime)
  282 + return -2; /* timed out */
  283 + WATCHDOG_RESET();
  284 + }
  285 + first = 0;
  286 + }
  287 +
  288 + ichar = getcmd_getch();
  289 +
  290 + if ((ichar == '\n') || (ichar == '\r')) {
  291 + putc('\n');
  292 + break;
  293 + }
  294 +
  295 + /*
  296 + * handle standard linux xterm esc sequences for arrow key, etc.
  297 + */
  298 + if (esc_len != 0) {
  299 + if (esc_len == 1) {
  300 + if (ichar == '[') {
  301 + esc_save[esc_len] = ichar;
  302 + esc_len = 2;
  303 + } else {
  304 + cread_add_str(esc_save, esc_len,
  305 + insert, &num, &eol_num,
  306 + buf, *len);
  307 + esc_len = 0;
  308 + }
  309 + continue;
  310 + }
  311 +
  312 + switch (ichar) {
  313 + case 'D': /* <- key */
  314 + ichar = CTL_CH('b');
  315 + esc_len = 0;
  316 + break;
  317 + case 'C': /* -> key */
  318 + ichar = CTL_CH('f');
  319 + esc_len = 0;
  320 + break; /* pass off to ^F handler */
  321 + case 'H': /* Home key */
  322 + ichar = CTL_CH('a');
  323 + esc_len = 0;
  324 + break; /* pass off to ^A handler */
  325 + case 'A': /* up arrow */
  326 + ichar = CTL_CH('p');
  327 + esc_len = 0;
  328 + break; /* pass off to ^P handler */
  329 + case 'B': /* down arrow */
  330 + ichar = CTL_CH('n');
  331 + esc_len = 0;
  332 + break; /* pass off to ^N handler */
  333 + default:
  334 + esc_save[esc_len++] = ichar;
  335 + cread_add_str(esc_save, esc_len, insert,
  336 + &num, &eol_num, buf, *len);
  337 + esc_len = 0;
  338 + continue;
  339 + }
  340 + }
  341 +
  342 + switch (ichar) {
  343 + case 0x1b:
  344 + if (esc_len == 0) {
  345 + esc_save[esc_len] = ichar;
  346 + esc_len = 1;
  347 + } else {
  348 + puts("impossible condition #876\n");
  349 + esc_len = 0;
  350 + }
  351 + break;
  352 +
  353 + case CTL_CH('a'):
  354 + BEGINNING_OF_LINE();
  355 + break;
  356 + case CTL_CH('c'): /* ^C - break */
  357 + *buf = '\0'; /* discard input */
  358 + return -1;
  359 + case CTL_CH('f'):
  360 + if (num < eol_num) {
  361 + getcmd_putch(buf[num]);
  362 + num++;
  363 + }
  364 + break;
  365 + case CTL_CH('b'):
  366 + if (num) {
  367 + getcmd_putch(CTL_BACKSPACE);
  368 + num--;
  369 + }
  370 + break;
  371 + case CTL_CH('d'):
  372 + if (num < eol_num) {
  373 + wlen = eol_num - num - 1;
  374 + if (wlen) {
  375 + memmove(&buf[num], &buf[num+1], wlen);
  376 + putnstr(buf + num, wlen);
  377 + }
  378 +
  379 + getcmd_putch(' ');
  380 + do {
  381 + getcmd_putch(CTL_BACKSPACE);
  382 + } while (wlen--);
  383 + eol_num--;
  384 + }
  385 + break;
  386 + case CTL_CH('k'):
  387 + ERASE_TO_EOL();
  388 + break;
  389 + case CTL_CH('e'):
  390 + REFRESH_TO_EOL();
  391 + break;
  392 + case CTL_CH('o'):
  393 + insert = !insert;
  394 + break;
  395 + case CTL_CH('x'):
  396 + case CTL_CH('u'):
  397 + BEGINNING_OF_LINE();
  398 + ERASE_TO_EOL();
  399 + break;
  400 + case DEL:
  401 + case DEL7:
  402 + case 8:
  403 + if (num) {
  404 + wlen = eol_num - num;
  405 + num--;
  406 + memmove(&buf[num], &buf[num+1], wlen);
  407 + getcmd_putch(CTL_BACKSPACE);
  408 + putnstr(buf + num, wlen);
  409 + getcmd_putch(' ');
  410 + do {
  411 + getcmd_putch(CTL_BACKSPACE);
  412 + } while (wlen--);
  413 + eol_num--;
  414 + }
  415 + break;
  416 + case CTL_CH('p'):
  417 + case CTL_CH('n'):
  418 + {
  419 + char *hline;
  420 +
  421 + esc_len = 0;
  422 +
  423 + if (ichar == CTL_CH('p'))
  424 + hline = hist_prev();
  425 + else
  426 + hline = hist_next();
  427 +
  428 + if (!hline) {
  429 + getcmd_cbeep();
  430 + continue;
  431 + }
  432 +
  433 + /* nuke the current line */
  434 + /* first, go home */
  435 + BEGINNING_OF_LINE();
  436 +
  437 + /* erase to end of line */
  438 + ERASE_TO_EOL();
  439 +
  440 + /* copy new line into place and display */
  441 + strcpy(buf, hline);
  442 + eol_num = strlen(buf);
  443 + REFRESH_TO_EOL();
  444 + continue;
  445 + }
  446 +#ifdef CONFIG_AUTO_COMPLETE
  447 + case '\t': {
  448 + int num2, col;
  449 +
  450 + /* do not autocomplete when in the middle */
  451 + if (num < eol_num) {
  452 + getcmd_cbeep();
  453 + break;
  454 + }
  455 +
  456 + buf[num] = '\0';
  457 + col = strlen(prompt) + eol_num;
  458 + num2 = num;
  459 + if (cmd_auto_complete(prompt, buf, &num2, &col)) {
  460 + col = num2 - num;
  461 + num += col;
  462 + eol_num += col;
  463 + }
  464 + break;
  465 + }
  466 +#endif
  467 + default:
  468 + cread_add_char(ichar, insert, &num, &eol_num, buf,
  469 + *len);
  470 + break;
  471 + }
  472 + }
  473 + *len = eol_num;
  474 + buf[eol_num] = '\0'; /* lose the newline */
  475 +
  476 + if (buf[0] && buf[0] != CREAD_HIST_CHAR)
  477 + cread_add_to_hist(buf);
  478 + hist_cur = hist_add_idx;
  479 +
  480 + return 0;
  481 +}
  482 +
  483 +#endif /* CONFIG_CMDLINE_EDITING */
  484 +
  485 +/****************************************************************************/
  486 +
  487 +int readline(const char *const prompt)
  488 +{
  489 + /*
  490 + * If console_buffer isn't 0-length the user will be prompted to modify
  491 + * it instead of entering it from scratch as desired.
  492 + */
  493 + console_buffer[0] = '\0';
  494 +
  495 + return readline_into_buffer(prompt, console_buffer, 0);
  496 +}
  497 +
  498 +
  499 +int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
  500 +{
  501 + char *p = buffer;
  502 +#ifdef CONFIG_CMDLINE_EDITING
  503 + unsigned int len = CONFIG_SYS_CBSIZE;
  504 + int rc;
  505 + static int initted;
  506 +
  507 + /*
  508 + * History uses a global array which is not
  509 + * writable until after relocation to RAM.
  510 + * Revert to non-history version if still
  511 + * running from flash.
  512 + */
  513 + if (gd->flags & GD_FLG_RELOC) {
  514 + if (!initted) {
  515 + hist_init();
  516 + initted = 1;
  517 + }
  518 +
  519 + if (prompt)
  520 + puts(prompt);
  521 +
  522 + rc = cread_line(prompt, p, &len, timeout);
  523 + return rc < 0 ? rc : len;
  524 +
  525 + } else {
  526 +#endif /* CONFIG_CMDLINE_EDITING */
  527 + char *p_buf = p;
  528 + int n = 0; /* buffer index */
  529 + int plen = 0; /* prompt length */
  530 + int col; /* output column cnt */
  531 + char c;
  532 +
  533 + /* print prompt */
  534 + if (prompt) {
  535 + plen = strlen(prompt);
  536 + puts(prompt);
  537 + }
  538 + col = plen;
  539 +
  540 + for (;;) {
  541 +#ifdef CONFIG_BOOT_RETRY_TIME
  542 + while (!tstc()) { /* while no incoming data */
  543 + if (retry_time >= 0 && get_ticks() > endtime)
  544 + return -2; /* timed out */
  545 + WATCHDOG_RESET();
  546 + }
  547 +#endif
  548 + WATCHDOG_RESET(); /* Trigger watchdog, if needed */
  549 +
  550 +#ifdef CONFIG_SHOW_ACTIVITY
  551 + while (!tstc()) {
  552 + show_activity(0);
  553 + WATCHDOG_RESET();
  554 + }
  555 +#endif
  556 + c = getc();
  557 +
  558 + /*
  559 + * Special character handling
  560 + */
  561 + switch (c) {
  562 + case '\r': /* Enter */
  563 + case '\n':
  564 + *p = '\0';
  565 + puts("\r\n");
  566 + return p - p_buf;
  567 +
  568 + case '\0': /* nul */
  569 + continue;
  570 +
  571 + case 0x03: /* ^C - break */
  572 + p_buf[0] = '\0'; /* discard input */
  573 + return -1;
  574 +
  575 + case 0x15: /* ^U - erase line */
  576 + while (col > plen) {
  577 + puts(erase_seq);
  578 + --col;
  579 + }
  580 + p = p_buf;
  581 + n = 0;
  582 + continue;
  583 +
  584 + case 0x17: /* ^W - erase word */
  585 + p = delete_char(p_buf, p, &col, &n, plen);
  586 + while ((n > 0) && (*p != ' '))
  587 + p = delete_char(p_buf, p, &col, &n, plen);
  588 + continue;
  589 +
  590 + case 0x08: /* ^H - backspace */
  591 + case 0x7F: /* DEL - backspace */
  592 + p = delete_char(p_buf, p, &col, &n, plen);
  593 + continue;
  594 +
  595 + default:
  596 + /*
  597 + * Must be a normal character then
  598 + */
  599 + if (n < CONFIG_SYS_CBSIZE-2) {
  600 + if (c == '\t') { /* expand TABs */
  601 +#ifdef CONFIG_AUTO_COMPLETE
  602 + /*
  603 + * if auto completion triggered just
  604 + * continue
  605 + */
  606 + *p = '\0';
  607 + if (cmd_auto_complete(prompt,
  608 + console_buffer,
  609 + &n, &col)) {
  610 + p = p_buf + n; /* reset */
  611 + continue;
  612 + }
  613 +#endif
  614 + puts(tab_seq + (col & 07));
  615 + col += 8 - (col & 07);
  616 + } else {
  617 + char buf[2];
  618 +
  619 + /*
  620 + * Echo input using puts() to force an
  621 + * LCD flush if we are using an LCD
  622 + */
  623 + ++col;
  624 + buf[0] = c;
  625 + buf[1] = '\0';
  626 + puts(buf);
  627 + }
  628 + *p++ = c;
  629 + ++n;
  630 + } else { /* Buffer full */
  631 + putc('\a');
  632 + }
  633 + }
  634 + }
  635 +#ifdef CONFIG_CMDLINE_EDITING
  636 + }
  637 +#endif
  638 +}
  639 +
  640 +#ifdef CONFIG_BOOT_RETRY_TIME
  641 +/***************************************************************************
  642 + * initialize command line timeout
  643 + */
  644 +void init_cmd_timeout(void)
  645 +{
  646 + char *s = getenv("bootretry");
  647 +
  648 + if (s != NULL)
  649 + retry_time = (int)simple_strtol(s, NULL, 10);
  650 + else
  651 + retry_time = CONFIG_BOOT_RETRY_TIME;
  652 +
  653 + if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
  654 + retry_time = CONFIG_BOOT_RETRY_MIN;
  655 +}
  656 +
  657 +/***************************************************************************
  658 + * reset command line timeout to retry_time seconds
  659 + */
  660 +void reset_cmd_timeout(void)
  661 +{
  662 + endtime = endtick(retry_time);
  663 +}
  664 +
  665 +void bootretry_dont_retry(void)
  666 +{
  667 + retry_time = -1;
  668 +}
  669 +
  670 +#endif
  1 +/*
  2 + * (C) Copyright 2000
  3 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4 + *
  5 + * Add to readline cmdline-editing by
  6 + * (C) Copyright 2005
  7 + * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
  8 + *
  9 + * SPDX-License-Identifier: GPL-2.0+
  10 + */
  11 +
  12 +#include <common.h>
  13 +#include <cli.h>
  14 +#include <linux/ctype.h>
  15 +
  16 +#define DEBUG_PARSER 0 /* set to 1 to debug */
  17 +
  18 +#define debug_parser(fmt, args...) \
  19 + debug_cond(DEBUG_PARSER, fmt, ##args)
  20 +
  21 +
  22 +int parse_line(char *line, char *argv[])
  23 +{
  24 + int nargs = 0;
  25 +
  26 + debug_parser("%s: \"%s\"\n", __func__, line);
  27 + while (nargs < CONFIG_SYS_MAXARGS) {
  28 + /* skip any white space */
  29 + while (isblank(*line))
  30 + ++line;
  31 +
  32 + if (*line == '\0') { /* end of line, no more args */
  33 + argv[nargs] = NULL;
  34 + debug_parser("%s: nargs=%d\n", __func__, nargs);
  35 + return nargs;
  36 + }
  37 +
  38 + argv[nargs++] = line; /* begin of argument string */
  39 +
  40 + /* find end of string */
  41 + while (*line && !isblank(*line))
  42 + ++line;
  43 +
  44 + if (*line == '\0') { /* end of line, no more args */
  45 + argv[nargs] = NULL;
  46 + debug_parser("parse_line: nargs=%d\n", nargs);
  47 + return nargs;
  48 + }
  49 +
  50 + *line++ = '\0'; /* terminate current arg */
  51 + }
  52 +
  53 + printf("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);
  54 +
  55 + debug_parser("%s: nargs=%d\n", __func__, nargs);
  56 + return nargs;
  57 +}
  58 +
  59 +static void process_macros(const char *input, char *output)
  60 +{
  61 + char c, prev;
  62 + const char *varname_start = NULL;
  63 + int inputcnt = strlen(input);
  64 + int outputcnt = CONFIG_SYS_CBSIZE;
  65 + int state = 0; /* 0 = waiting for '$' */
  66 +
  67 + /* 1 = waiting for '(' or '{' */
  68 + /* 2 = waiting for ')' or '}' */
  69 + /* 3 = waiting for ''' */
  70 + char *output_start = output;
  71 +
  72 + debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input),
  73 + input);
  74 +
  75 + prev = '\0'; /* previous character */
  76 +
  77 + while (inputcnt && outputcnt) {
  78 + c = *input++;
  79 + inputcnt--;
  80 +
  81 + if (state != 3) {
  82 + /* remove one level of escape characters */
  83 + if ((c == '\\') && (prev != '\\')) {
  84 + if (inputcnt-- == 0)
  85 + break;
  86 + prev = c;
  87 + c = *input++;
  88 + }
  89 + }
  90 +
  91 + switch (state) {
  92 + case 0: /* Waiting for (unescaped) $ */
  93 + if ((c == '\'') && (prev != '\\')) {
  94 + state = 3;
  95 + break;
  96 + }
  97 + if ((c == '$') && (prev != '\\')) {
  98 + state++;
  99 + } else {
  100 + *(output++) = c;
  101 + outputcnt--;
  102 + }
  103 + break;
  104 + case 1: /* Waiting for ( */
  105 + if (c == '(' || c == '{') {
  106 + state++;
  107 + varname_start = input;
  108 + } else {
  109 + state = 0;
  110 + *(output++) = '$';
  111 + outputcnt--;
  112 +
  113 + if (outputcnt) {
  114 + *(output++) = c;
  115 + outputcnt--;
  116 + }
  117 + }
  118 + break;
  119 + case 2: /* Waiting for ) */
  120 + if (c == ')' || c == '}') {
  121 + int i;
  122 + char envname[CONFIG_SYS_CBSIZE], *envval;
  123 + /* Varname # of chars */
  124 + int envcnt = input - varname_start - 1;
  125 +
  126 + /* Get the varname */
  127 + for (i = 0; i < envcnt; i++)
  128 + envname[i] = varname_start[i];
  129 + envname[i] = 0;
  130 +
  131 + /* Get its value */
  132 + envval = getenv(envname);
  133 +
  134 + /* Copy into the line if it exists */
  135 + if (envval != NULL)
  136 + while ((*envval) && outputcnt) {
  137 + *(output++) = *(envval++);
  138 + outputcnt--;
  139 + }
  140 + /* Look for another '$' */
  141 + state = 0;
  142 + }
  143 + break;
  144 + case 3: /* Waiting for ' */
  145 + if ((c == '\'') && (prev != '\\')) {
  146 + state = 0;
  147 + } else {
  148 + *(output++) = c;
  149 + outputcnt--;
  150 + }
  151 + break;
  152 + }
  153 + prev = c;
  154 + }
  155 +
  156 + if (outputcnt)
  157 + *output = 0;
  158 + else
  159 + *(output - 1) = 0;
  160 +
  161 + debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n",
  162 + strlen(output_start), output_start);
  163 +}
  164 +
  165 + /*
  166 + * WARNING:
  167 + *
  168 + * We must create a temporary copy of the command since the command we get
  169 + * may be the result from getenv(), which returns a pointer directly to
  170 + * the environment data, which may change magicly when the command we run
  171 + * creates or modifies environment variables (like "bootp" does).
  172 + */
  173 +int cli_simple_run_command(const char *cmd, int flag)
  174 +{
  175 + char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */
  176 + char *token; /* start of token in cmdbuf */
  177 + char *sep; /* end of token (separator) in cmdbuf */
  178 + char finaltoken[CONFIG_SYS_CBSIZE];
  179 + char *str = cmdbuf;
  180 + char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
  181 + int argc, inquotes;
  182 + int repeatable = 1;
  183 + int rc = 0;
  184 +
  185 + debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd);
  186 + if (DEBUG_PARSER) {
  187 + /* use puts - string may be loooong */
  188 + puts(cmd ? cmd : "NULL");
  189 + puts("\"\n");
  190 + }
  191 + clear_ctrlc(); /* forget any previous Control C */
  192 +
  193 + if (!cmd || !*cmd)
  194 + return -1; /* empty command */
  195 +
  196 + if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
  197 + puts("## Command too long!\n");
  198 + return -1;
  199 + }
  200 +
  201 + strcpy(cmdbuf, cmd);
  202 +
  203 + /* Process separators and check for invalid
  204 + * repeatable commands
  205 + */
  206 +
  207 + debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
  208 + while (*str) {
  209 + /*
  210 + * Find separator, or string end
  211 + * Allow simple escape of ';' by writing "\;"
  212 + */
  213 + for (inquotes = 0, sep = str; *sep; sep++) {
  214 + if ((*sep == '\'') &&
  215 + (*(sep - 1) != '\\'))
  216 + inquotes = !inquotes;
  217 +
  218 + if (!inquotes &&
  219 + (*sep == ';') && /* separator */
  220 + (sep != str) && /* past string start */
  221 + (*(sep - 1) != '\\')) /* and NOT escaped */
  222 + break;
  223 + }
  224 +
  225 + /*
  226 + * Limit the token to data between separators
  227 + */
  228 + token = str;
  229 + if (*sep) {
  230 + str = sep + 1; /* start of command for next pass */
  231 + *sep = '\0';
  232 + } else {
  233 + str = sep; /* no more commands for next pass */
  234 + }
  235 + debug_parser("token: \"%s\"\n", token);
  236 +
  237 + /* find macros in this token and replace them */
  238 + process_macros(token, finaltoken);
  239 +
  240 + /* Extract arguments */
  241 + argc = parse_line(finaltoken, argv);
  242 + if (argc == 0) {
  243 + rc = -1; /* no command at all */
  244 + continue;
  245 + }
  246 +
  247 + if (cmd_process(flag, argc, argv, &repeatable, NULL))
  248 + rc = -1;
  249 +
  250 + /* Did the user stop this? */
  251 + if (had_ctrlc())
  252 + return -1; /* if stopped then not repeatable */
  253 + }
  254 +
  255 + return rc ? rc : repeatable;
  256 +}
  257 +
  258 +void cli_loop(void)
  259 +{
  260 + static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
  261 +
  262 + int len;
  263 + int flag;
  264 + int rc = 1;
  265 +
  266 + for (;;) {
  267 +#ifdef CONFIG_BOOT_RETRY_TIME
  268 + if (rc >= 0) {
  269 + /* Saw enough of a valid command to
  270 + * restart the timeout.
  271 + */
  272 + reset_cmd_timeout();
  273 + }
  274 +#endif
  275 + len = readline(CONFIG_SYS_PROMPT);
  276 +
  277 + flag = 0; /* assume no special flags for now */
  278 + if (len > 0)
  279 + strcpy(lastcommand, console_buffer);
  280 + else if (len == 0)
  281 + flag |= CMD_FLAG_REPEAT;
  282 +#ifdef CONFIG_BOOT_RETRY_TIME
  283 + else if (len == -2) {
  284 + /* -2 means timed out, retry autoboot
  285 + */
  286 + puts("\nTimed out waiting for command\n");
  287 +# ifdef CONFIG_RESET_TO_RETRY
  288 + /* Reinit board to run initialization code again */
  289 + do_reset(NULL, 0, 0, NULL);
  290 +# else
  291 + return; /* retry autoboot */
  292 +# endif
  293 + }
  294 +#endif
  295 +
  296 + if (len == -1)
  297 + puts("<INTERRUPT>\n");
  298 + else
  299 + rc = run_command(lastcommand, flag);
  300 +
  301 + if (rc <= 0) {
  302 + /* invalid command or not repeatable, forget it */
  303 + lastcommand[0] = 0;
  304 + }
  305 + }
  306 +}
  307 +
  308 +int cli_simple_run_command_list(char *cmd, int flag)
  309 +{
  310 + char *line, *next;
  311 + int rcode = 0;
  312 +
  313 + /*
  314 + * Break into individual lines, and execute each line; terminate on
  315 + * error.
  316 + */
  317 + next = cmd;
  318 + line = cmd;
  319 + while (*next) {
  320 + if (*next == '\n') {
  321 + *next = '\0';
  322 + /* run only non-empty commands */
  323 + if (*line) {
  324 + debug("** exec: \"%s\"\n", line);
  325 + if (cli_simple_run_command(line, 0) < 0) {
  326 + rcode = 1;
  327 + break;
  328 + }
  329 + }
  330 + line = next + 1;
  331 + }
  332 + ++next;
  333 + }
  334 + if (rcode == 0 && *line)
  335 + rcode = (cli_simple_run_command(line, 0) >= 0);
  336 +
  337 + return rcode;
  338 +}
Changes suppressed. Click to show
... ... @@ -2,10 +2,6 @@
2 2 * (C) Copyright 2000
3 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 4 *
5   - * Add to readline cmdline-editing by
6   - * (C) Copyright 2005
7   - * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
8   - *
9 5 * SPDX-License-Identifier: GPL-2.0+
10 6 */
11 7  
... ... @@ -20,8 +16,6 @@
20 16 #include <menu.h>
21 17 #include <post.h>
22 18 #include <version.h>
23   -#include <watchdog.h>
24   -#include <linux/ctype.h>
25 19  
26 20 DECLARE_GLOBAL_DATA_PTR;
27 21  
28 22  
... ... @@ -33,34 +27,12 @@
33 27  
34 28 #define MAX_DELAY_STOP_STR 32
35 29  
36   -#define DEBUG_PARSER 0 /* set to 1 to debug */
37   -
38   -#define debug_parser(fmt, args...) \
39   - debug_cond(DEBUG_PARSER, fmt, ##args)
40   -
41 30 #ifndef DEBUG_BOOTKEYS
42 31 #define DEBUG_BOOTKEYS 0
43 32 #endif
44 33 #define debug_bootkeys(fmt, args...) \
45 34 debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
46 35  
47   -char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */
48   -
49   -static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
50   -static const char erase_seq[] = "\b \b"; /* erase sequence */
51   -static const char tab_seq[] = " "; /* used to expand TABs */
52   -
53   -#ifdef CONFIG_BOOT_RETRY_TIME
54   -static uint64_t endtime = 0; /* must be set, default is instant timeout */
55   -static int retry_time = -1; /* -1 so can call readline before main_loop */
56   -#endif
57   -
58   -#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
59   -
60   -#ifndef CONFIG_BOOT_RETRY_MIN
61   -#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
62   -#endif
63   -
64 36 #ifdef CONFIG_MODEM_SUPPORT
65 37 int do_mdm_init = 0;
66 38 extern void mdm_init(void); /* defined in board.c */
... ... @@ -162,7 +134,7 @@
162 134 # ifdef CONFIG_BOOT_RETRY_TIME
163 135 /* don't retry auto boot */
164 136 if (! delaykey[i].retry)
165   - retry_time = -1;
  137 + bootretry_dont_retry();
166 138 # endif
167 139 abort = 1;
168 140 }
... ... @@ -416,12 +388,6 @@
416 388  
417 389 void main_loop(void)
418 390 {
419   -#ifndef CONFIG_SYS_HUSH_PARSER
420   - static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
421   - int len;
422   - int rc = 1;
423   - int flag;
424   -#endif
425 391 #ifdef CONFIG_PREBOOT
426 392 char *p;
427 393 #endif
428 394  
429 395  
... ... @@ -489,943 +455,13 @@
489 455 /* This point is never reached */
490 456 for (;;);
491 457 #else
492   - for (;;) {
493   -#ifdef CONFIG_BOOT_RETRY_TIME
494   - if (rc >= 0) {
495   - /* Saw enough of a valid command to
496   - * restart the timeout.
497   - */
498   - reset_cmd_timeout();
499   - }
500   -#endif
501   - len = readline (CONFIG_SYS_PROMPT);
502   -
503   - flag = 0; /* assume no special flags for now */
504   - if (len > 0)
505   - strcpy (lastcommand, console_buffer);
506   - else if (len == 0)
507   - flag |= CMD_FLAG_REPEAT;
508   -#ifdef CONFIG_BOOT_RETRY_TIME
509   - else if (len == -2) {
510   - /* -2 means timed out, retry autoboot
511   - */
512   - puts ("\nTimed out waiting for command\n");
513   -# ifdef CONFIG_RESET_TO_RETRY
514   - /* Reinit board to run initialization code again */
515   - do_reset (NULL, 0, 0, NULL);
516   -# else
517   - return; /* retry autoboot */
518   -# endif
519   - }
520   -#endif
521   -
522   - if (len == -1)
523   - puts ("<INTERRUPT>\n");
524   - else
525   - rc = run_command(lastcommand, flag);
526   -
527   - if (rc <= 0) {
528   - /* invalid command or not repeatable, forget it */
529   - lastcommand[0] = 0;
530   - }
531   - }
  458 + cli_loop();
532 459 #endif /*CONFIG_SYS_HUSH_PARSER*/
533 460 }
534 461  
535   -#ifdef CONFIG_BOOT_RETRY_TIME
536   -/***************************************************************************
537   - * initialize command line timeout
538   - */
539   -void init_cmd_timeout(void)
540   -{
541   - char *s = getenv ("bootretry");
542   -
543   - if (s != NULL)
544   - retry_time = (int)simple_strtol(s, NULL, 10);
545   - else
546   - retry_time = CONFIG_BOOT_RETRY_TIME;
547   -
548   - if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
549   - retry_time = CONFIG_BOOT_RETRY_MIN;
550   -}
551   -
552   -/***************************************************************************
553   - * reset command line timeout to retry_time seconds
554   - */
555   -void reset_cmd_timeout(void)
556   -{
557   - endtime = endtick(retry_time);
558   -}
559   -#endif
560   -
561   -#ifdef CONFIG_CMDLINE_EDITING
562   -
563   -/*
564   - * cmdline-editing related codes from vivi.
565   - * Author: Janghoon Lyu <nandy@mizi.com>
566   - */
567   -
568   -#define putnstr(str,n) do { \
569   - printf ("%.*s", (int)n, str); \
570   - } while (0)
571   -
572   -#define CTL_CH(c) ((c) - 'a' + 1)
573   -#define CTL_BACKSPACE ('\b')
574   -#define DEL ((char)255)
575   -#define DEL7 ((char)127)
576   -#define CREAD_HIST_CHAR ('!')
577   -
578   -#define getcmd_putch(ch) putc(ch)
579   -#define getcmd_getch() getc()
580   -#define getcmd_cbeep() getcmd_putch('\a')
581   -
582   -#define HIST_MAX 20
583   -#define HIST_SIZE CONFIG_SYS_CBSIZE
584   -
585   -static int hist_max;
586   -static int hist_add_idx;
587   -static int hist_cur = -1;
588   -static unsigned hist_num;
589   -
590   -static char *hist_list[HIST_MAX];
591   -static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */
592   -
593   -#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
594   -
595   -static void hist_init(void)
596   -{
597   - int i;
598   -
599   - hist_max = 0;
600   - hist_add_idx = 0;
601   - hist_cur = -1;
602   - hist_num = 0;
603   -
604   - for (i = 0; i < HIST_MAX; i++) {
605   - hist_list[i] = hist_lines[i];
606   - hist_list[i][0] = '\0';
607   - }
608   -}
609   -
610   -static void cread_add_to_hist(char *line)
611   -{
612   - strcpy(hist_list[hist_add_idx], line);
613   -
614   - if (++hist_add_idx >= HIST_MAX)
615   - hist_add_idx = 0;
616   -
617   - if (hist_add_idx > hist_max)
618   - hist_max = hist_add_idx;
619   -
620   - hist_num++;
621   -}
622   -
623   -static char* hist_prev(void)
624   -{
625   - char *ret;
626   - int old_cur;
627   -
628   - if (hist_cur < 0)
629   - return NULL;
630   -
631   - old_cur = hist_cur;
632   - if (--hist_cur < 0)
633   - hist_cur = hist_max;
634   -
635   - if (hist_cur == hist_add_idx) {
636   - hist_cur = old_cur;
637   - ret = NULL;
638   - } else
639   - ret = hist_list[hist_cur];
640   -
641   - return (ret);
642   -}
643   -
644   -static char* hist_next(void)
645   -{
646   - char *ret;
647   -
648   - if (hist_cur < 0)
649   - return NULL;
650   -
651   - if (hist_cur == hist_add_idx)
652   - return NULL;
653   -
654   - if (++hist_cur > hist_max)
655   - hist_cur = 0;
656   -
657   - if (hist_cur == hist_add_idx) {
658   - ret = "";
659   - } else
660   - ret = hist_list[hist_cur];
661   -
662   - return (ret);
663   -}
664   -
665   -#ifndef CONFIG_CMDLINE_EDITING
666   -static void cread_print_hist_list(void)
667   -{
668   - int i;
669   - unsigned long n;
670   -
671   - n = hist_num - hist_max;
672   -
673   - i = hist_add_idx + 1;
674   - while (1) {
675   - if (i > hist_max)
676   - i = 0;
677   - if (i == hist_add_idx)
678   - break;
679   - printf("%s\n", hist_list[i]);
680   - n++;
681   - i++;
682   - }
683   -}
684   -#endif /* CONFIG_CMDLINE_EDITING */
685   -
686   -#define BEGINNING_OF_LINE() { \
687   - while (num) { \
688   - getcmd_putch(CTL_BACKSPACE); \
689   - num--; \
690   - } \
691   -}
692   -
693   -#define ERASE_TO_EOL() { \
694   - if (num < eol_num) { \
695   - printf("%*s", (int)(eol_num - num), ""); \
696   - do { \
697   - getcmd_putch(CTL_BACKSPACE); \
698   - } while (--eol_num > num); \
699   - } \
700   -}
701   -
702   -#define REFRESH_TO_EOL() { \
703   - if (num < eol_num) { \
704   - wlen = eol_num - num; \
705   - putnstr(buf + num, wlen); \
706   - num = eol_num; \
707   - } \
708   -}
709   -
710   -static void cread_add_char(char ichar, int insert, unsigned long *num,
711   - unsigned long *eol_num, char *buf, unsigned long len)
712   -{
713   - unsigned long wlen;
714   -
715   - /* room ??? */
716   - if (insert || *num == *eol_num) {
717   - if (*eol_num > len - 1) {
718   - getcmd_cbeep();
719   - return;
720   - }
721   - (*eol_num)++;
722   - }
723   -
724   - if (insert) {
725   - wlen = *eol_num - *num;
726   - if (wlen > 1) {
727   - memmove(&buf[*num+1], &buf[*num], wlen-1);
728   - }
729   -
730   - buf[*num] = ichar;
731   - putnstr(buf + *num, wlen);
732   - (*num)++;
733   - while (--wlen) {
734   - getcmd_putch(CTL_BACKSPACE);
735   - }
736   - } else {
737   - /* echo the character */
738   - wlen = 1;
739   - buf[*num] = ichar;
740   - putnstr(buf + *num, wlen);
741   - (*num)++;
742   - }
743   -}
744   -
745   -static void cread_add_str(char *str, int strsize, int insert, unsigned long *num,
746   - unsigned long *eol_num, char *buf, unsigned long len)
747   -{
748   - while (strsize--) {
749   - cread_add_char(*str, insert, num, eol_num, buf, len);
750   - str++;
751   - }
752   -}
753   -
754   -static int cread_line(const char *const prompt, char *buf, unsigned int *len,
755   - int timeout)
756   -{
757   - unsigned long num = 0;
758   - unsigned long eol_num = 0;
759   - unsigned long wlen;
760   - char ichar;
761   - int insert = 1;
762   - int esc_len = 0;
763   - char esc_save[8];
764   - int init_len = strlen(buf);
765   - int first = 1;
766   -
767   - if (init_len)
768   - cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
769   -
770   - while (1) {
771   -#ifdef CONFIG_BOOT_RETRY_TIME
772   - while (!tstc()) { /* while no incoming data */
773   - if (retry_time >= 0 && get_ticks() > endtime)
774   - return (-2); /* timed out */
775   - WATCHDOG_RESET();
776   - }
777   -#endif
778   - if (first && timeout) {
779   - uint64_t etime = endtick(timeout);
780   -
781   - while (!tstc()) { /* while no incoming data */
782   - if (get_ticks() >= etime)
783   - return -2; /* timed out */
784   - WATCHDOG_RESET();
785   - }
786   - first = 0;
787   - }
788   -
789   - ichar = getcmd_getch();
790   -
791   - if ((ichar == '\n') || (ichar == '\r')) {
792   - putc('\n');
793   - break;
794   - }
795   -
796   - /*
797   - * handle standard linux xterm esc sequences for arrow key, etc.
798   - */
799   - if (esc_len != 0) {
800   - if (esc_len == 1) {
801   - if (ichar == '[') {
802   - esc_save[esc_len] = ichar;
803   - esc_len = 2;
804   - } else {
805   - cread_add_str(esc_save, esc_len, insert,
806   - &num, &eol_num, buf, *len);
807   - esc_len = 0;
808   - }
809   - continue;
810   - }
811   -
812   - switch (ichar) {
813   -
814   - case 'D': /* <- key */
815   - ichar = CTL_CH('b');
816   - esc_len = 0;
817   - break;
818   - case 'C': /* -> key */
819   - ichar = CTL_CH('f');
820   - esc_len = 0;
821   - break; /* pass off to ^F handler */
822   - case 'H': /* Home key */
823   - ichar = CTL_CH('a');
824   - esc_len = 0;
825   - break; /* pass off to ^A handler */
826   - case 'A': /* up arrow */
827   - ichar = CTL_CH('p');
828   - esc_len = 0;
829   - break; /* pass off to ^P handler */
830   - case 'B': /* down arrow */
831   - ichar = CTL_CH('n');
832   - esc_len = 0;
833   - break; /* pass off to ^N handler */
834   - default:
835   - esc_save[esc_len++] = ichar;
836   - cread_add_str(esc_save, esc_len, insert,
837   - &num, &eol_num, buf, *len);
838   - esc_len = 0;
839   - continue;
840   - }
841   - }
842   -
843   - switch (ichar) {
844   - case 0x1b:
845   - if (esc_len == 0) {
846   - esc_save[esc_len] = ichar;
847   - esc_len = 1;
848   - } else {
849   - puts("impossible condition #876\n");
850   - esc_len = 0;
851   - }
852   - break;
853   -
854   - case CTL_CH('a'):
855   - BEGINNING_OF_LINE();
856   - break;
857   - case CTL_CH('c'): /* ^C - break */
858   - *buf = '\0'; /* discard input */
859   - return (-1);
860   - case CTL_CH('f'):
861   - if (num < eol_num) {
862   - getcmd_putch(buf[num]);
863   - num++;
864   - }
865   - break;
866   - case CTL_CH('b'):
867   - if (num) {
868   - getcmd_putch(CTL_BACKSPACE);
869   - num--;
870   - }
871   - break;
872   - case CTL_CH('d'):
873   - if (num < eol_num) {
874   - wlen = eol_num - num - 1;
875   - if (wlen) {
876   - memmove(&buf[num], &buf[num+1], wlen);
877   - putnstr(buf + num, wlen);
878   - }
879   -
880   - getcmd_putch(' ');
881   - do {
882   - getcmd_putch(CTL_BACKSPACE);
883   - } while (wlen--);
884   - eol_num--;
885   - }
886   - break;
887   - case CTL_CH('k'):
888   - ERASE_TO_EOL();
889   - break;
890   - case CTL_CH('e'):
891   - REFRESH_TO_EOL();
892   - break;
893   - case CTL_CH('o'):
894   - insert = !insert;
895   - break;
896   - case CTL_CH('x'):
897   - case CTL_CH('u'):
898   - BEGINNING_OF_LINE();
899   - ERASE_TO_EOL();
900   - break;
901   - case DEL:
902   - case DEL7:
903   - case 8:
904   - if (num) {
905   - wlen = eol_num - num;
906   - num--;
907   - memmove(&buf[num], &buf[num+1], wlen);
908   - getcmd_putch(CTL_BACKSPACE);
909   - putnstr(buf + num, wlen);
910   - getcmd_putch(' ');
911   - do {
912   - getcmd_putch(CTL_BACKSPACE);
913   - } while (wlen--);
914   - eol_num--;
915   - }
916   - break;
917   - case CTL_CH('p'):
918   - case CTL_CH('n'):
919   - {
920   - char * hline;
921   -
922   - esc_len = 0;
923   -
924   - if (ichar == CTL_CH('p'))
925   - hline = hist_prev();
926   - else
927   - hline = hist_next();
928   -
929   - if (!hline) {
930   - getcmd_cbeep();
931   - continue;
932   - }
933   -
934   - /* nuke the current line */
935   - /* first, go home */
936   - BEGINNING_OF_LINE();
937   -
938   - /* erase to end of line */
939   - ERASE_TO_EOL();
940   -
941   - /* copy new line into place and display */
942   - strcpy(buf, hline);
943   - eol_num = strlen(buf);
944   - REFRESH_TO_EOL();
945   - continue;
946   - }
947   -#ifdef CONFIG_AUTO_COMPLETE
948   - case '\t': {
949   - int num2, col;
950   -
951   - /* do not autocomplete when in the middle */
952   - if (num < eol_num) {
953   - getcmd_cbeep();
954   - break;
955   - }
956   -
957   - buf[num] = '\0';
958   - col = strlen(prompt) + eol_num;
959   - num2 = num;
960   - if (cmd_auto_complete(prompt, buf, &num2, &col)) {
961   - col = num2 - num;
962   - num += col;
963   - eol_num += col;
964   - }
965   - break;
966   - }
967   -#endif
968   - default:
969   - cread_add_char(ichar, insert, &num, &eol_num, buf, *len);
970   - break;
971   - }
972   - }
973   - *len = eol_num;
974   - buf[eol_num] = '\0'; /* lose the newline */
975   -
976   - if (buf[0] && buf[0] != CREAD_HIST_CHAR)
977   - cread_add_to_hist(buf);
978   - hist_cur = hist_add_idx;
979   -
980   - return 0;
981   -}
982   -
983   -#endif /* CONFIG_CMDLINE_EDITING */
984   -
985 462 /****************************************************************************/
986 463  
987 464 /*
988   - * Prompt for input and read a line.
989   - * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
990   - * time out when time goes past endtime (timebase time in ticks).
991   - * Return: number of read characters
992   - * -1 if break
993   - * -2 if timed out
994   - */
995   -int readline (const char *const prompt)
996   -{
997   - /*
998   - * If console_buffer isn't 0-length the user will be prompted to modify
999   - * it instead of entering it from scratch as desired.
1000   - */
1001   - console_buffer[0] = '\0';
1002   -
1003   - return readline_into_buffer(prompt, console_buffer, 0);
1004   -}
1005   -
1006   -
1007   -int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
1008   -{
1009   - char *p = buffer;
1010   -#ifdef CONFIG_CMDLINE_EDITING
1011   - unsigned int len = CONFIG_SYS_CBSIZE;
1012   - int rc;
1013   - static int initted = 0;
1014   -
1015   - /*
1016   - * History uses a global array which is not
1017   - * writable until after relocation to RAM.
1018   - * Revert to non-history version if still
1019   - * running from flash.
1020   - */
1021   - if (gd->flags & GD_FLG_RELOC) {
1022   - if (!initted) {
1023   - hist_init();
1024   - initted = 1;
1025   - }
1026   -
1027   - if (prompt)
1028   - puts (prompt);
1029   -
1030   - rc = cread_line(prompt, p, &len, timeout);
1031   - return rc < 0 ? rc : len;
1032   -
1033   - } else {
1034   -#endif /* CONFIG_CMDLINE_EDITING */
1035   - char * p_buf = p;
1036   - int n = 0; /* buffer index */
1037   - int plen = 0; /* prompt length */
1038   - int col; /* output column cnt */
1039   - char c;
1040   -
1041   - /* print prompt */
1042   - if (prompt) {
1043   - plen = strlen (prompt);
1044   - puts (prompt);
1045   - }
1046   - col = plen;
1047   -
1048   - for (;;) {
1049   -#ifdef CONFIG_BOOT_RETRY_TIME
1050   - while (!tstc()) { /* while no incoming data */
1051   - if (retry_time >= 0 && get_ticks() > endtime)
1052   - return (-2); /* timed out */
1053   - WATCHDOG_RESET();
1054   - }
1055   -#endif
1056   - WATCHDOG_RESET(); /* Trigger watchdog, if needed */
1057   -
1058   -#ifdef CONFIG_SHOW_ACTIVITY
1059   - while (!tstc()) {
1060   - show_activity(0);
1061   - WATCHDOG_RESET();
1062   - }
1063   -#endif
1064   - c = getc();
1065   -
1066   - /*
1067   - * Special character handling
1068   - */
1069   - switch (c) {
1070   - case '\r': /* Enter */
1071   - case '\n':
1072   - *p = '\0';
1073   - puts ("\r\n");
1074   - return p - p_buf;
1075   -
1076   - case '\0': /* nul */
1077   - continue;
1078   -
1079   - case 0x03: /* ^C - break */
1080   - p_buf[0] = '\0'; /* discard input */
1081   - return -1;
1082   -
1083   - case 0x15: /* ^U - erase line */
1084   - while (col > plen) {
1085   - puts (erase_seq);
1086   - --col;
1087   - }
1088   - p = p_buf;
1089   - n = 0;
1090   - continue;
1091   -
1092   - case 0x17: /* ^W - erase word */
1093   - p=delete_char(p_buf, p, &col, &n, plen);
1094   - while ((n > 0) && (*p != ' ')) {
1095   - p=delete_char(p_buf, p, &col, &n, plen);
1096   - }
1097   - continue;
1098   -
1099   - case 0x08: /* ^H - backspace */
1100   - case 0x7F: /* DEL - backspace */
1101   - p=delete_char(p_buf, p, &col, &n, plen);
1102   - continue;
1103   -
1104   - default:
1105   - /*
1106   - * Must be a normal character then
1107   - */
1108   - if (n < CONFIG_SYS_CBSIZE-2) {
1109   - if (c == '\t') { /* expand TABs */
1110   -#ifdef CONFIG_AUTO_COMPLETE
1111   - /* if auto completion triggered just continue */
1112   - *p = '\0';
1113   - if (cmd_auto_complete(prompt, console_buffer, &n, &col)) {
1114   - p = p_buf + n; /* reset */
1115   - continue;
1116   - }
1117   -#endif
1118   - puts (tab_seq+(col&07));
1119   - col += 8 - (col&07);
1120   - } else {
1121   - char buf[2];
1122   -
1123   - /*
1124   - * Echo input using puts() to force an
1125   - * LCD flush if we are using an LCD
1126   - */
1127   - ++col;
1128   - buf[0] = c;
1129   - buf[1] = '\0';
1130   - puts(buf);
1131   - }
1132   - *p++ = c;
1133   - ++n;
1134   - } else { /* Buffer full */
1135   - putc ('\a');
1136   - }
1137   - }
1138   - }
1139   -#ifdef CONFIG_CMDLINE_EDITING
1140   - }
1141   -#endif
1142   -}
1143   -
1144   -/****************************************************************************/
1145   -
1146   -static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
1147   -{
1148   - char *s;
1149   -
1150   - if (*np == 0) {
1151   - return (p);
1152   - }
1153   -
1154   - if (*(--p) == '\t') { /* will retype the whole line */
1155   - while (*colp > plen) {
1156   - puts (erase_seq);
1157   - (*colp)--;
1158   - }
1159   - for (s=buffer; s<p; ++s) {
1160   - if (*s == '\t') {
1161   - puts (tab_seq+((*colp) & 07));
1162   - *colp += 8 - ((*colp) & 07);
1163   - } else {
1164   - ++(*colp);
1165   - putc (*s);
1166   - }
1167   - }
1168   - } else {
1169   - puts (erase_seq);
1170   - (*colp)--;
1171   - }
1172   - (*np)--;
1173   - return (p);
1174   -}
1175   -
1176   -/****************************************************************************/
1177   -
1178   -int parse_line (char *line, char *argv[])
1179   -{
1180   - int nargs = 0;
1181   -
1182   - debug_parser("parse_line: \"%s\"\n", line);
1183   - while (nargs < CONFIG_SYS_MAXARGS) {
1184   -
1185   - /* skip any white space */
1186   - while (isblank(*line))
1187   - ++line;
1188   -
1189   - if (*line == '\0') { /* end of line, no more args */
1190   - argv[nargs] = NULL;
1191   - debug_parser("parse_line: nargs=%d\n", nargs);
1192   - return nargs;
1193   - }
1194   -
1195   - argv[nargs++] = line; /* begin of argument string */
1196   -
1197   - /* find end of string */
1198   - while (*line && !isblank(*line))
1199   - ++line;
1200   -
1201   - if (*line == '\0') { /* end of line, no more args */
1202   - argv[nargs] = NULL;
1203   - debug_parser("parse_line: nargs=%d\n", nargs);
1204   - return nargs;
1205   - }
1206   -
1207   - *line++ = '\0'; /* terminate current arg */
1208   - }
1209   -
1210   - printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);
1211   -
1212   - debug_parser("parse_line: nargs=%d\n", nargs);
1213   - return (nargs);
1214   -}
1215   -
1216   -/****************************************************************************/
1217   -
1218   -#ifndef CONFIG_SYS_HUSH_PARSER
1219   -static void process_macros (const char *input, char *output)
1220   -{
1221   - char c, prev;
1222   - const char *varname_start = NULL;
1223   - int inputcnt = strlen (input);
1224   - int outputcnt = CONFIG_SYS_CBSIZE;
1225   - int state = 0; /* 0 = waiting for '$' */
1226   -
1227   - /* 1 = waiting for '(' or '{' */
1228   - /* 2 = waiting for ')' or '}' */
1229   - /* 3 = waiting for ''' */
1230   - char *output_start = output;
1231   -
1232   - debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input),
1233   - input);
1234   -
1235   - prev = '\0'; /* previous character */
1236   -
1237   - while (inputcnt && outputcnt) {
1238   - c = *input++;
1239   - inputcnt--;
1240   -
1241   - if (state != 3) {
1242   - /* remove one level of escape characters */
1243   - if ((c == '\\') && (prev != '\\')) {
1244   - if (inputcnt-- == 0)
1245   - break;
1246   - prev = c;
1247   - c = *input++;
1248   - }
1249   - }
1250   -
1251   - switch (state) {
1252   - case 0: /* Waiting for (unescaped) $ */
1253   - if ((c == '\'') && (prev != '\\')) {
1254   - state = 3;
1255   - break;
1256   - }
1257   - if ((c == '$') && (prev != '\\')) {
1258   - state++;
1259   - } else {
1260   - *(output++) = c;
1261   - outputcnt--;
1262   - }
1263   - break;
1264   - case 1: /* Waiting for ( */
1265   - if (c == '(' || c == '{') {
1266   - state++;
1267   - varname_start = input;
1268   - } else {
1269   - state = 0;
1270   - *(output++) = '$';
1271   - outputcnt--;
1272   -
1273   - if (outputcnt) {
1274   - *(output++) = c;
1275   - outputcnt--;
1276   - }
1277   - }
1278   - break;
1279   - case 2: /* Waiting for ) */
1280   - if (c == ')' || c == '}') {
1281   - int i;
1282   - char envname[CONFIG_SYS_CBSIZE], *envval;
1283   - int envcnt = input - varname_start - 1; /* Varname # of chars */
1284   -
1285   - /* Get the varname */
1286   - for (i = 0; i < envcnt; i++) {
1287   - envname[i] = varname_start[i];
1288   - }
1289   - envname[i] = 0;
1290   -
1291   - /* Get its value */
1292   - envval = getenv (envname);
1293   -
1294   - /* Copy into the line if it exists */
1295   - if (envval != NULL)
1296   - while ((*envval) && outputcnt) {
1297   - *(output++) = *(envval++);
1298   - outputcnt--;
1299   - }
1300   - /* Look for another '$' */
1301   - state = 0;
1302   - }
1303   - break;
1304   - case 3: /* Waiting for ' */
1305   - if ((c == '\'') && (prev != '\\')) {
1306   - state = 0;
1307   - } else {
1308   - *(output++) = c;
1309   - outputcnt--;
1310   - }
1311   - break;
1312   - }
1313   - prev = c;
1314   - }
1315   -
1316   - if (outputcnt)
1317   - *output = 0;
1318   - else
1319   - *(output - 1) = 0;
1320   -
1321   - debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n",
1322   - strlen(output_start), output_start);
1323   -}
1324   -
1325   -/****************************************************************************
1326   - * returns:
1327   - * 1 - command executed, repeatable
1328   - * 0 - command executed but not repeatable, interrupted commands are
1329   - * always considered not repeatable
1330   - * -1 - not executed (unrecognized, bootd recursion or too many args)
1331   - * (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
1332   - * considered unrecognized)
1333   - *
1334   - * WARNING:
1335   - *
1336   - * We must create a temporary copy of the command since the command we get
1337   - * may be the result from getenv(), which returns a pointer directly to
1338   - * the environment data, which may change magicly when the command we run
1339   - * creates or modifies environment variables (like "bootp" does).
1340   - */
1341   -static int builtin_run_command(const char *cmd, int flag)
1342   -{
1343   - char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */
1344   - char *token; /* start of token in cmdbuf */
1345   - char *sep; /* end of token (separator) in cmdbuf */
1346   - char finaltoken[CONFIG_SYS_CBSIZE];
1347   - char *str = cmdbuf;
1348   - char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
1349   - int argc, inquotes;
1350   - int repeatable = 1;
1351   - int rc = 0;
1352   -
1353   - debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd);
1354   - if (DEBUG_PARSER) {
1355   - /* use puts - string may be loooong */
1356   - puts(cmd ? cmd : "NULL");
1357   - puts("\"\n");
1358   - }
1359   - clear_ctrlc(); /* forget any previous Control C */
1360   -
1361   - if (!cmd || !*cmd) {
1362   - return -1; /* empty command */
1363   - }
1364   -
1365   - if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
1366   - puts ("## Command too long!\n");
1367   - return -1;
1368   - }
1369   -
1370   - strcpy (cmdbuf, cmd);
1371   -
1372   - /* Process separators and check for invalid
1373   - * repeatable commands
1374   - */
1375   -
1376   - debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
1377   - while (*str) {
1378   -
1379   - /*
1380   - * Find separator, or string end
1381   - * Allow simple escape of ';' by writing "\;"
1382   - */
1383   - for (inquotes = 0, sep = str; *sep; sep++) {
1384   - if ((*sep=='\'') &&
1385   - (*(sep-1) != '\\'))
1386   - inquotes=!inquotes;
1387   -
1388   - if (!inquotes &&
1389   - (*sep == ';') && /* separator */
1390   - ( sep != str) && /* past string start */
1391   - (*(sep-1) != '\\')) /* and NOT escaped */
1392   - break;
1393   - }
1394   -
1395   - /*
1396   - * Limit the token to data between separators
1397   - */
1398   - token = str;
1399   - if (*sep) {
1400   - str = sep + 1; /* start of command for next pass */
1401   - *sep = '\0';
1402   - }
1403   - else
1404   - str = sep; /* no more commands for next pass */
1405   - debug_parser("token: \"%s\"\n", token);
1406   -
1407   - /* find macros in this token and replace them */
1408   - process_macros (token, finaltoken);
1409   -
1410   - /* Extract arguments */
1411   - if ((argc = parse_line (finaltoken, argv)) == 0) {
1412   - rc = -1; /* no command at all */
1413   - continue;
1414   - }
1415   -
1416   - if (cmd_process(flag, argc, argv, &repeatable, NULL))
1417   - rc = -1;
1418   -
1419   - /* Did the user stop this? */
1420   - if (had_ctrlc ())
1421   - return -1; /* if stopped then not repeatable */
1422   - }
1423   -
1424   - return rc ? rc : repeatable;
1425   -}
1426   -#endif
1427   -
1428   -/*
1429 465 * Run a command using the selected parser.
1430 466 *
1431 467 * @param cmd Command to run
1432 468  
... ... @@ -1436,10 +472,10 @@
1436 472 {
1437 473 #ifndef CONFIG_SYS_HUSH_PARSER
1438 474 /*
1439   - * builtin_run_command can return 0 or 1 for success, so clean up
  475 + * cli_run_command can return 0 or 1 for success, so clean up
1440 476 * its result.
1441 477 */
1442   - if (builtin_run_command(cmd, flag) == -1)
  478 + if (cli_simple_run_command(cmd, flag) == -1)
1443 479 return 1;
1444 480  
1445 481 return 0;
... ... @@ -1449,49 +485,6 @@
1449 485 #endif
1450 486 }
1451 487  
1452   -#ifndef CONFIG_SYS_HUSH_PARSER
1453   -/**
1454   - * Execute a list of command separated by ; or \n using the built-in parser.
1455   - *
1456   - * This function cannot take a const char * for the command, since if it
1457   - * finds newlines in the string, it replaces them with \0.
1458   - *
1459   - * @param cmd String containing list of commands
1460   - * @param flag Execution flags (CMD_FLAG_...)
1461   - * @return 0 on success, or != 0 on error.
1462   - */
1463   -static int builtin_run_command_list(char *cmd, int flag)
1464   -{
1465   - char *line, *next;
1466   - int rcode = 0;
1467   -
1468   - /*
1469   - * Break into individual lines, and execute each line; terminate on
1470   - * error.
1471   - */
1472   - line = next = cmd;
1473   - while (*next) {
1474   - if (*next == '\n') {
1475   - *next = '\0';
1476   - /* run only non-empty commands */
1477   - if (*line) {
1478   - debug("** exec: \"%s\"\n", line);
1479   - if (builtin_run_command(line, 0) < 0) {
1480   - rcode = 1;
1481   - break;
1482   - }
1483   - }
1484   - line = next + 1;
1485   - }
1486   - ++next;
1487   - }
1488   - if (rcode == 0 && *line)
1489   - rcode = (builtin_run_command(line, 0) >= 0);
1490   -
1491   - return rcode;
1492   -}
1493   -#endif
1494   -
1495 488 int run_command_list(const char *cmd, int len, int flag)
1496 489 {
1497 490 int need_buff = 1;
... ... @@ -1525,7 +518,7 @@
1525 518 * doing a malloc() which is actually required only in a case that
1526 519 * is pretty rare.
1527 520 */
1528   - rcode = builtin_run_command_list(buff, flag);
  521 + rcode = cli_simple_run_command_list(buff, flag);
1529 522 if (need_buff)
1530 523 free(buff);
1531 524 #endif
... ... @@ -99,5 +99,10 @@
99 99 */
100 100 int parse_line(char *line, char *argv[]);
101 101  
  102 +/** bootretry_dont_retry() - Indicate that we should not retry the boot */
  103 +void bootretry_dont_retry(void);
  104 +
  105 +#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
  106 +
102 107 #endif