Browse Source

update lib/cmd.*

Signed-off-by: surenyi <surenyi82@163.com>
master
surenyi 5 years ago
parent
commit
865ced5f3d
  1. 588
      lib/cmd.c
  2. 2
      lib/cmd.h
  3. 4
      lib/config.h
  4. 8
      targets/fk407/main.c
  5. 7
      targets/stm32f429-disc/main.c
  6. 7
      targets/vocoder/main.c
  7. 2
      targets/xc_ppf1901/retarget.c

588
lib/cmd.c

@ -8,14 +8,6 @@
#include "cmd.h"
#include "config.h"
struct cmd_handler {
char buffer[TARGET_CMD_BUFSIZE + 2];
int recved;
void *priv;
void (*putstring)(struct cmd_handler *, const char *s, int len);
int (*getchar)(struct cmd_handler *);
};
enum KEY_ACTION {
KEY_NULL = 0, /* NULL */
CTRL_A = 1, /* Ctrl+a */
@ -38,68 +30,80 @@ enum KEY_ACTION {
BACKSPACE = 127 /* Backspace */
};
struct terminal {
char buf[TARGET_CMD_BUFSIZE]; /* edited line buffer */
int buflen; /* edited line buffer size */
int len; /* current edited line length */
const char *prompt; /* prompt to display */
uint16_t plen; /* prompt length */
uint16_t pos; /* current cursor poistion */
uint16_t oldpos; /* previouse refresh cursor position */
uint16_t cols; /* number of columns in terminal */
int16_t hindex; /* the history index we are currently editing */
};
static struct terminal G;
static char *history[TARGET_CMD_HISTORY];
static int history_len = 0;
#if defined(__CC_ARM)
extern struct cmd_tbl_s Image$$CMDLINE$$Base, Image$$CMDLINE$$Limit;
#else
extern struct cmd_tbl_s __cmdline_cmd_start, __cmdline_cmd_end;
#endif
static struct cmd_handler _G;
#define G_BUF (_G.buffer)
#define G_N (_G.recved)
#define G_GETCH() _G.getchar(&_G)
#ifdef __CC_ARM /* for keil */
static void do_puts(struct cmd_handler *hc, const char *s, int len)
static int tputs(const char *s, int len)
{
if (len < 0) {
len = strlen(s);
}
fwrite(s, len, 1, stdout);
fflush(stdout);
}
static int do_getch(struct cmd_handler *hc)
{
return fgetc(stdin);
}
#else
static void do_puts(struct cmd_handler *hc, const char *s, int len)
static int tgets(char *buf, int len, int blocking /* in millis */)
{
char *buf_save = buf;
int n;
if (len < 0) {
len = strlen(s);
if (blocking <= 0) {
return fread(buf, 1, n, stdin);
}
while (len > 0) {
n = write(STDOUT_FILENO, s, len);
n = fread(buf, 1, n, stdin);
if (n > 0) {
buf += n;
len -= n;
s += n;
}
}
return (buf - buf_save);
}
#else
static int tputs(const char *s, int len)
{
write(STDOUT_FILENO, s, len);
return (len);
}
static int do_getch(struct cmd_handler *hc)
static int tgets(char *buf, int len, int blocking /* in millis */)
{
char c = 0;
char *buf_save = buf;
int n;
if (read(STDIN_FILENO, &c, 1) == 1) {
return (c);
if (blocking <= 0) {
return read(STDIN_FILENO, buf, len);
}
return -1;
}
#endif
static void do_writen(const char *s, int len)
{
_G.putstring(&_G, s, len);
}
while (len > 0) {
n = read(STDIN_FILENO, buf, len);
if (n > 0) {
buf += n;
len -= n;
}
}
static void do_printf(const char *s)
{
do_writen(s, -1);
return (buf - buf_save);
}
#endif
static int do_help(cmd_tbl_t s, int argc, char *argv[])
{
@ -108,34 +112,20 @@ static int do_help(cmd_tbl_t s, int argc, char *argv[])
#else
cmd_tbl_t it = &__cmdline_cmd_start;
#endif
do_printf("support commands:\r\n\r\n");
printf("support commands:\r\n");
#if defined(__CC_ARM)
while (it < &Image$$CMDLINE$$Limit) {
#else
while (it < &__cmdline_cmd_end) {
while (it < &__cmdline_cmd_end) {
#endif
do_printf(it->name);
do_printf("\t");
do_printf(it->help);
do_printf("\r\n");
++it;
}
return 0;
printf("%s\t%s\r\n", it->name, it->help);
++it;
}
return 0;
}
CON_CMD(help, "commands help", NULL, do_help)
int cmd_init()
{
G_N = 0 ;
_G.putstring = do_puts;
_G.getchar = do_getch;
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
return 0;
}
static int parse_line(char *cmd, int len, char *argv[], int _maxargs)
{
int argc;
@ -183,16 +173,16 @@ static int parse_line(char *cmd, int len, char *argv[], int _maxargs)
int cmd_process(char *line)
{
int i, argc, namelen;
int size = strlen(line);
char *argv[TARGET_CMD_MAXARGS + 1];
#if defined(__CC_ARM)
cmd_tbl_t it = &Image$$CMDLINE$$Base;
#else
cmd_tbl_t it = &__cmdline_cmd_start;
#endif
int i, argc, namelen;
int size = strlen(line);
char *argv[TARGET_CMD_MAXARGS + 1];
/* split line */
for (i = 0; i < TARGET_CMD_MAXARGS + 1; ++i) {
argv[i] = NULL;
@ -226,59 +216,433 @@ recovery:
return 0;
}
void cmd_loop()
/*
* Use the ESC [6n escape sequence to query the horizontal cursor position
* and return it. On error -1 is returned, on success the position of the
* cursor.
*/
static int get_cursor_position()
{
int c;
char buf[32];
int cols, rows;
unsigned int i = 0;
/* Report cursor location */
if (tputs("\x1b[6n", 4) != 4) return -1;
/* Read the response: ESC [ rows ; cols R */
while (i < sizeof(buf)-1) {
if (tgets(buf + i, 1, 1000) != 1) break;
if (buf[i] == 'R') break;
i++;
}
buf[i] = '\0';
do {
c = G_GETCH();
if (c <= 0)
break;
if (G_N >= TARGET_CMD_BUFSIZE) {
do_printf("too long\r\n");
G_N = 0;
do_writen("\r\n> ", 4);
}
/* Parse it. */
if (buf[0] != ESC || buf[1] != '[') return -1;
if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
return cols;
}
switch (c) {
case CTRL_C:
G_N = 0;
do_writen("\r\n> ", 4);
return;
case BACKSPACE:
case CTRL_H:
if (G_N > 0) {
do_writen("\b \b", 3);
G_N--;
G_BUF[G_N] = '\0';
}
return;
case CTRL_L:
do_writen("\x1b[H\x1b[2J",7);
do_writen("> ", 2);
if (G_N > 0)
do_writen(G_BUF, G_N);
return;
/*
* Single line low level line refresh.
*
* Rewrite the currently edited line accordingly to the buffer content,
* cursor position, and number of columns of the terminal.
*/
static void refresh_line()
{
char seq[64];
size_t plen = G.plen;
char *buf = G.buf;
size_t len = G.len;
size_t pos = G.pos;
while((plen + pos) >= G.cols) {
buf++;
len--;
pos--;
}
while (plen+len > G.cols) {
len--;
}
/* Cursor to left edge */
tputs("\r", 1);
tputs(G.prompt, G.plen);
tputs(buf, len);
/* Erase to right */
tputs("\x1b[0K", 4);
/* Move cursor to original position. */
snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
tputs(seq, strlen(seq));
}
/*
* Try to get the number of columns in the current terminal, or assume 80
* if it fails.
*/
static int get_columns()
{
char seq[32];
int start, cols;
/* Get the initial position so we can restore it later. */
start = get_cursor_position();
if (start == -1) goto failed;
/* Go to right margin and get position. */
if (tputs("\x1b[999C", 6) != 6) goto failed;
cols = get_cursor_position();
if (cols == -1) goto failed;
/* Restore position. */
if (cols > start) {
snprintf(seq,32,"\x1b[%dD",cols-start);
if (tputs(seq, strlen(seq)) == -1) {
/* Can't recover... */
}
}
return cols;
failed:
return 80;
}
/*
* Delete the character at the right of the cursor without altering the cursor
* position. Basically this is what happens with the "Delete" keyboard key.
*/
static void edit_delete()
{
if (G.len > 0 && G.pos < G.len) {
memmove(G.buf + G.pos, G.buf + G.pos + 1, G.len - G.pos - 1);
G.len--;
G.buf[G.len] = '\0';
refresh_line();
}
}
/* Backspace implementation. */
static void edit_backspace()
{
if (G.pos > 0 && G.len > 0) {
memmove(G.buf + G.pos - 1, G.buf + G.pos, G.len - G.pos);
G.pos--;
G.len--;
G.buf[G.len] = '\0';
refresh_line();
}
}
/* end of line */
if (c == '\r' || c == '\n') {
do_writen("\r\n", 2);
if (G_N > 0) {
G_BUF[G_N] = '\0';
cmd_process(G_BUF);
do_writen("\r\n", 2);
G_N = 0;
/*
* Delete the previosu word, maintaining the cursor at the start of the
* current word.
*/
static void edit_delete_prev()
{
size_t old_pos = G.pos;
size_t diff;
while (G.pos > 0 && G.buf[G.pos - 1] == ' ')
G.pos--;
while (G.pos > 0 && G.buf[G.pos - 1] != ' ')
G.pos--;
diff = old_pos - G.pos;
memmove(G.buf + G.pos, G.buf + old_pos, G.len - old_pos + 1);
G.len -= diff;
refresh_line();
}
/*
* Insert the character 'c' at cursor current position.
*
* On error writing to the terminal -1 is returned, otherwise 0.
*/
static void edit_insert(char c)
{
if (G.len < G.buflen) {
if (G.len == G.pos) {
G.buf[G.pos] = c;
G.pos++;
G.len++;
G.buf[G.len] = '\0';
if (G.plen + G.len < G.cols) {
/* Avoid a full update of the line in the
* trivial case. */
tputs(&c, 1);
}
do_writen("> ", 2);
continue;
} else {
memmove(G.buf + G.pos + 1, G.buf + G.pos, G.len - G.pos);
G.buf[G.pos] = c;
G.len++;
G.pos++;
G.buf[G.len] = '\0';
refresh_line();
}
}
}
static void move_right()
{
if (G.pos != G.len) {
++G.pos;
refresh_line();
}
}
if (isprint(c)) {
G_BUF[G_N] = c;
G_N++;
do_writen((char *)&c, 1);
static void move_left()
{
if (G.pos > 0) {
G.pos--;
refresh_line();
}
}
static void move_home()
{
if (G.pos != 0) {
G.pos = 0;
refresh_line();
}
}
static void move_end()
{
if (G.pos != G.len) {
G.pos = G.len;
refresh_line();
}
}
static int history_add(const char *line)
{
char *copy;
if (history_len && !strcmp(history[history_len - 1], line))
return 0;
copy = strdup(line);
if (!copy)
return 0;
if (history_len == TARGET_CMD_HISTORY) {
free(history[0]);
memmove(history, history + 1, sizeof (char *) * (history_len - 1));
--history_len;
}
history[history_len++] = copy;
return 1;
}
/*
* Substitute the currently edited line with the next or previous history
* entry as specified by 'dir'
*/
static void edit_history(int dir)
{
if (history_len > 0) {
G.hindex += dir;
if (G.hindex < 0) {
G.hindex = history_len - 1;
} else if (G.hindex >= history_len) {
G.hindex = 0;
}
} while (1) ;
strncpy(G.buf, history[G.hindex], G.buflen);
G.buf[G.buflen - 1] = '\0';
G.len = G.pos = strlen(G.buf);
refresh_line();
}
}
static void history_prev()
{
edit_history(-1);
}
static void history_next()
{
edit_history(1);
}
static void reset_linestate()
{
G.cols = get_columns();
G.oldpos = 0;
G.pos = 0;
G.len = 0;
G.hindex = history_len;
tputs(G.prompt, G.plen);
}
static int do_clear(cmd_tbl_t s, int argc, char *argv[])
{
tputs("\x1b[H\x1b[2J",7);
return 0;
}
CON_CMD(clear, "clear the screen", NULL, do_clear);
int cmd_init(const char *prompt)
{
#if defined(__CC_ARM)
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#endif
G.buflen = TARGET_CMD_BUFSIZE;
G.prompt = prompt;
G.plen = strlen(G.prompt);
G.buf[0] = '\0';
G.buflen--; /* make sure there is always space hold `NUL' */
reset_linestate();
return 0;
}
void cmd_loop()
{
char c;
int nread;
char seq[3];
nread = tgets(&c, 1, -1);
if (nread <= 0)
return;
/* if c == TAB, do completion? */
switch (c) {
case ENTER:
case '\n':
tputs("\r\n", 2);
if (G.len > 0) {
G.buf[G.len] = '\0';
history_add(G.buf);
cmd_process(G.buf);
}
reset_linestate();
break;
case CTRL_C: /* ctrl-c */
reset_linestate();
break;
case BACKSPACE: /* backspace */
case CTRL_H:
edit_backspace();
break;
case CTRL_D: /* ctrl-d, remove the right of cursor. */
if (G.len > 0) {
edit_delete();
} else {
reset_linestate();
}
break;
case CTRL_T: /* ctrl-t, swaps current char with previous */
if (G.pos > 0 && G.pos < G.len) {
int aux = G.buf[G.pos - 1];
G.buf[G.pos-1] = G.buf[G.pos];
G.buf[G.pos] = aux;
if (G.pos != G.len - 1) G.pos++;
refresh_line();
}
break;
case CTRL_B: /* ctrl -b */
move_left();
break;
case CTRL_F: /* ctrl-f */
move_right();
break;
case CTRL_L:
tputs("\x1b[H\x1b[2J",7);
refresh_line();
break;
case CTRL_U: /* ctrl-u, delete the whole line */
G.buf[0] = '\0';
G.pos = G.len = 0;
refresh_line();
break;
case CTRL_K: /* ctrl-k, delete from current to end of line */
G.buf[G.pos] = '\0';
G.len = G.pos;
refresh_line();
break;
case CTRL_A: /* ctrl-a, goto start of the line */
move_home();
break;
case CTRL_E: /* ctrl-e, goto end of the line */
move_end();
break;
case CTRL_W:
edit_delete_prev();
break;
case CTRL_P:
history_prev();
break;
case CTRL_N:
history_next();
break;
case ESC: /* escape sequence */
/* Read the next two bytes representing the escape sequence.
* Use two calls to handle slow terminals returning the two
* chars at different times. */
if (tgets(seq, 1, 1000) == -1) break;
if (tgets(seq + 1 ,1, 1000) == -1) break;
/* ESC [ sequences. */
if (seq[0] == '[') {
if (seq[1] >= '0' && seq[1] <= '9') {
/* Extended escape, read additional byte. */
if (tgets(seq + 2, 1, 1000) == -1) break;
if (seq[2] == '~') {
switch(seq[1]) {
case '3': /* Delete key. */
edit_delete();
break;
}
}
} else {
switch(seq[1]) {
case 'A': /* Up */
history_prev();
break;
case 'B': /* Down */
history_next();
break;
case 'C': /* Right */
move_right();
break;
case 'D': /* Left */
move_left();
break;
case 'H': /* Home */
move_home();
break;
case 'F': /* End*/
move_end();
break;
}
}
}
/* ESC O sequences. */
else if (seq[0] == 'O') {
switch(seq[1]) {
case 'H': /* Home */
move_home();
break;
case 'F': /* End*/
move_end();
break;
}
}
break;
default:
edit_insert(c);
break;
}
}

2
lib/cmd.h

@ -19,7 +19,7 @@ typedef struct cmd_tbl_s *cmd_tbl_t;
/* initialize command */
int cmd_init(void);
int cmd_init(const char *prompt);
/* process debug console input */
void cmd_loop(void);

4
lib/config.h

@ -99,6 +99,10 @@ extern "C" {
#define TARGET_CMD_BUFSIZE (256)
#endif
#ifndef TARGET_CMD_HISTORY
#define TARGET_CMD_HISTORY (8)
#endif
#ifndef TARGET_CMD_MAXARGS
#define TARGET_CMD_MAXARGS (8)
#endif

8
targets/fk407/main.c

@ -97,14 +97,11 @@ int main()
timer_setup(TIM_80MS, 80, __on_80ms, NULL);
timer_start(TIM_80MS);
cmd_init();
/* debug console */
serial_setup(&serial0, CONSOLE_BAUDRATE, 8, SERIAL_STOPBITS_1);
printf("\r\n");
bkp_sram_init();
bkp_sram_write(MAGIC_POS, MAGIC_APP);
i2c = i2c_new(PC2, PC1, 100000);
wm8978_init_with_i2c(i2c);
@ -113,8 +110,9 @@ int main()
// wm8978_init_with_iic(&i2c0);
printf("build: %s (%s)\r\n", __DATE__, __TIME__);
printf("running\r\n...............................\r\n> ");
printf("running\r\n...............................\r\n");
cmd_init("m407> ");
bkp_sram_write(MAGIC_POS, MAGIC_APP);
while (1) {
cmd_loop();
iwdg_reset();

7
targets/stm32f429-disc/main.c

@ -120,8 +120,6 @@ int main()
timer_setup(TIM_80MS, 80, __on_80ms, NULL);
// timer_start(TIM_80MS);
cmd_init();
bkp_sram_init();
/* debug console */
@ -141,9 +139,10 @@ int main()
efs_mount();
bkp_sram_write(MAGIC_POS, MAGIC_APP);
printf("build: %s (%s)\r\n", __DATE__, __TIME__);
printf("running\r\n...............................\r\n> ");
printf("running\r\n...............................\r\n");
cmd_init("disc> ");
bkp_sram_write(MAGIC_POS, MAGIC_APP);
while (1) {
cmd_loop();
iwdg_reset();

7
targets/vocoder/main.c

@ -460,8 +460,6 @@ int main()
iwdg_set_period_ms(1000);
iwdg_start();
cmd_init();
bkp_sram_init();
/* debug console */
@ -521,9 +519,10 @@ int main()
timer_setup(LED1_TIMER, 100, flashing, (void *)Y1_OUT);
timer_setup(LED2_TIMER, 100, flashing, (void *)Y2_OUT);
bkp_sram_write(MAGIC_POS, MAGIC_APP);
printf("running\r\n...............................\r\n> ");
printf("running\r\n...............................\r\n");
cmd_init("vo> ");
bkp_sram_write(MAGIC_POS, MAGIC_APP);
while (1) {
cmd_loop();
/*

2
targets/xc_ppf1901/retarget.c

@ -27,7 +27,7 @@ static void init_board(void)
dwt_init();
cmd_init();
cmd_init("xc> ");
/* debug console */
serial_setup(&serial0, CONSOLE_BAUDRATE, 8, SERIAL_STOPBITS_1);

Loading…
Cancel
Save