static int API_auto_complete(va_list ap) { char *prompt; char *buf; int *np, *colp; prompt=(char *)va_arg(ap, u_int32_t); buf=(char *)va_arg(ap, u_int32_t); np=(int *)va_arg(ap, u_int32_t); colp=(int *)va_arg(ap, u_int32_t); cmd_auto_complete(prompt, buf, np, colp); return 0; }
int ubreadline_into_buffer(const char *const prompt, char *buffer, int timeout) { char *p = buffer; unsigned int len = CONFIG_SYS_CBSIZE; int rc; static int initted = 0; /* * History uses a global array which is not * writable until after relocation to RAM. * Revert to non-history version if still * running from flash. */ if (0) { if (!initted) { hist_init(); initted = 1; } if (prompt) printf (prompt); rc = cread_line(prompt, p, &len, timeout); return rc < 0 ? rc : len; } else { char * p_buf = p; int n = 0; /* buffer index */ int plen = 0; /* prompt length */ int col; /* output column cnt */ char c; /* print prompt */ if (prompt) { plen = strlen (prompt); printf (prompt); } col = plen; for (;;) { c = serial_getchar(); /* * Special character handling */ switch (c) { case '\r': /* Enter */ case '\n': *p = '\0'; printf ("\r\n"); return p - p_buf; case '\0': /* nul */ continue; case 0x03: /* ^C - break */ p_buf[0] = '\0'; /* discard input */ return -1; case 0x15: /* ^U - erase line */ while (col > plen) { printf (erase_seq); --col; } p = p_buf; n = 0; continue; case 0x17: /* ^W - erase word */ p=delete_char(p_buf, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=delete_char(p_buf, p, &col, &n, plen); } continue; case 0x08: /* ^H - backspace */ case 0x7F: /* DEL - backspace */ p=delete_char(p_buf, p, &col, &n, plen); continue; default: /* * Must be a normal character then */ if (n < CONFIG_SYS_CBSIZE-2) { if (c == '\t') { /* expand TABs */ /* if auto completion triggered just continue */ *p = '\0'; if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { p = p_buf + n; /* reset */ continue; } printf (tab_seq+(col&07)); col += 8 - (col&07); } else { char buf[2]; /* * Echo input using printf() to force an * LCD flush if we are using an LCD */ ++col; buf[0] = c; buf[1] = '\0'; printf(buf); } *p++ = c; ++n; } else { /* Buffer full */ serial_putchar('\a'); } } } } }
static int cread_line(const char *const prompt, char *buf, unsigned int *len, int timeout) { unsigned long num = 0; unsigned long eol_num = 0; unsigned long wlen; char ichar; int insert = 1; int esc_len = 0; char esc_save[8]; int init_len = strlen(buf); //int first = 1; if (init_len) cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); while (1) { #if 0 #ifdef CONFIG_BOOT_RETRY_TIME while (!tstc()) { /* while no incoming data */ if (retry_time >= 0 && get_ticks() > endtime) return (-2); /* timed out */ // WATCHDOG_RESET(); } #endif if (first && timeout) { uint64_t etime = endtick(timeout); while (!tstc()) { /* while no incoming data */ if (get_ticks() >= etime) return -2; /* timed out */ WATCHDOG_RESET(); } first = 0; } #endif ichar = getcmd_getch(); if ((ichar == '\n') || (ichar == '\r')) { serial_putchar('\n'); break; } /* * handle standard linux xterm esc sequences for arrow key, etc. */ if (esc_len != 0) { if (esc_len == 1) { if (ichar == '[') { esc_save[esc_len] = ichar; esc_len = 2; } else { cread_add_str(esc_save, esc_len, insert, &num, &eol_num, buf, *len); esc_len = 0; } continue; } switch (ichar) { case 'D': /* <- key */ ichar = CTL_CH('b'); esc_len = 0; break; case 'C': /* -> key */ ichar = CTL_CH('f'); esc_len = 0; break; /* pass off to ^F handler */ case 'H': /* Home key */ ichar = CTL_CH('a'); esc_len = 0; break; /* pass off to ^A handler */ case 'A': /* up arrow */ ichar = CTL_CH('p'); esc_len = 0; break; /* pass off to ^P handler */ case 'B': /* down arrow */ ichar = CTL_CH('n'); esc_len = 0; break; /* pass off to ^N handler */ default: esc_save[esc_len++] = ichar; cread_add_str(esc_save, esc_len, insert, &num, &eol_num, buf, *len); esc_len = 0; continue; } } switch (ichar) { case 0x1b: if (esc_len == 0) { esc_save[esc_len] = ichar; esc_len = 1; } else { printf("impossible condition #876\n"); esc_len = 0; } break; 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 (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(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'): { char * hline; esc_len = 0; if (ichar == CTL_CH('p')) hline = hist_prev(); else hline = hist_next(); if (!hline) { getcmd_cbeep(); continue; } /* nuke the current line */ /* first, go home */ BEGINNING_OF_LINE(); /* erase to end of line */ ERASE_TO_EOL(); /* copy new line into place and display */ strcpy(buf, hline); eol_num = strlen(buf); REFRESH_TO_EOL(); continue; } #ifdef CONFIG_AUTO_COMPLETE case '\t': { int num2, col; /* do not autocomplete when in the middle */ if (num < 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; } break; } #endif default: cread_add_char(ichar, insert, &num, &eol_num, buf, *len); break; } } *len = eol_num; buf[eol_num] = '\0'; /* lose the newline */ if (buf[0] && buf[0] != CREAD_HIST_CHAR) cread_add_to_hist(buf); hist_cur = hist_add_idx; return 0; }
/*! * @brief read line into buffer */ static int cread_line(const char * const prompt, char * buf, uint8_t * len) { uint8_t num = 0; uint8_t eol_num = 0; uint8_t wlen; char ichar = 0; uint8_t insert = 1; uint8_t esc_len = 0; char esc_save[8]; uint8_t init_len = strlen(buf); if (init_len) { cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); } while (1) { do { ichar = sgetc(); }while(!ichar); if ((ichar == '\n') || (ichar == '\r')) { sputc('\r');sputc('\n'); break; } /* handle standard linux xterm esc sequences for arrow key, etc.*/ if (esc_len != 0) { if (esc_len == 1) { if (ichar == '[') { esc_save[esc_len] = ichar; esc_len = 2; } else { cread_add_str(esc_save, esc_len, insert, &num, &eol_num, buf, *len); esc_len = 0; } continue; } switch (ichar) { case 'D': /* <- key */ ichar = CTL_CH('b'); esc_len = 0; break; case 'C': /* -> key */ ichar = CTL_CH('f'); esc_len = 0; break; /* pass off to ^F handler */ case 'H': /* Home key */ ichar = CTL_CH('a'); esc_len = 0; break; /* pass off to ^A handler */ case 'A': /* up arrow */ ichar = CTL_CH('p'); esc_len = 0; break; /* pass off to ^P handler */ case 'B': /* down arrow */ ichar = CTL_CH('n'); esc_len = 0; break; /* pass off to ^N handler */ default: esc_save[esc_len++] = ichar; cread_add_str(esc_save, esc_len, insert, &num, &eol_num, buf, *len); esc_len = 0; continue; } } switch (ichar) { case 0x1b: if (esc_len == 0) { esc_save[esc_len] = ichar; esc_len = 1; } else { shell_printf("impossible condition #876\n"); esc_len = 0; } break; case CTL_CH('a'): BEGINNING_OF_LINE() break; case CTL_CH('c'): /* ^C - break */ *buf = '\0'; /* discard input */ return (-1); //break; /* have to follow MISRA */ case CTL_CH('f'): if (num < eol_num) { sputc(buf[num]); num++; } break; case CTL_CH('b'): if (num) { sputc(CTL_BACKSPACE); num--; } 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); } sputc(' '); do { sputc(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); sputc(CTL_BACKSPACE); putnstr(buf + num, wlen); sputc(' '); do { sputc(CTL_BACKSPACE); } while (wlen--); eol_num--; } break; case CTL_CH('p'): case CTL_CH('n'): #ifdef SHELL_CONFIG_USE_HIST { char * hline; esc_len = 0; if (ichar == CTL_CH('p')) { hline = hist_prev(); } else { hline = hist_next(); } if (!hline) { shell_beep(); continue; } /* nuke the current line */ /* first, go home */ BEGINNING_OF_LINE() ERASE_TO_EOL() /* copy new line into place and display */ strcpy(buf, hline); eol_num = strlen(buf); REFRESH_TO_EOL() continue; //break; /* have to follow MISRA */ } #else { continue; } #endif /* SHELL_CONFIG_USE_HIST */ case '\t': #ifdef SHELL_CONFIG_AUTO_COMPLETE { uint8_t num2, col; /* do not autocomplete when in the middle */ if (num < eol_num) { shell_beep(); 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; } break; } #else { continue; } #endif /* SHELL_CONFIG_AUTO_COMPLETE */ default: cread_add_char(ichar, insert, &num, &eol_num, buf, *len); break; } } *len = eol_num; buf[eol_num] = '\0'; /* lose the newline */ #ifdef SHELL_CONFIG_USE_HIST if ((buf[0]) && (buf[0] != CREAD_HIST_CHAR)) { cread_add_to_hist(buf); } hist_cur = hist_add_idx; #endif return 0; }