You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
6.0 KiB
284 lines
6.0 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#if !defined(__CC_ARM)
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <ctype.h>
|
|
#include "cmd.h"
|
|
#include "config.h"
|
|
|
|
struct cmd_handler {
|
|
char buffer[TARGET_CMD_BUFSIZE + 2];
|
|
int recved;
|
|
void *priv;
|
|
void (*puts)(struct cmd_handler *, const char *s, int len);
|
|
int (*getch)(struct cmd_handler *);
|
|
};
|
|
|
|
enum KEY_ACTION {
|
|
KEY_NULL = 0, /* NULL */
|
|
CTRL_A = 1, /* Ctrl+a */
|
|
CTRL_B = 2, /* Ctrl-b */
|
|
CTRL_C = 3, /* Ctrl-c */
|
|
CTRL_D = 4, /* Ctrl-d */
|
|
CTRL_E = 5, /* Ctrl-e */
|
|
CTRL_F = 6, /* Ctrl-f */
|
|
CTRL_H = 8, /* Ctrl-h */
|
|
TAB = 9, /* Tab */
|
|
CTRL_K = 11, /* Ctrl+k */
|
|
CTRL_L = 12, /* Ctrl+l */
|
|
ENTER = 13, /* Enter */
|
|
CTRL_N = 14, /* Ctrl-n */
|
|
CTRL_P = 16, /* Ctrl-p */
|
|
CTRL_T = 20, /* Ctrl-t */
|
|
CTRL_U = 21, /* Ctrl+u */
|
|
CTRL_W = 23, /* Ctrl+w */
|
|
ESC = 27, /* Escape */
|
|
BACKSPACE = 127 /* Backspace */
|
|
};
|
|
|
|
#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.getch(&_G)
|
|
|
|
#ifdef __CC_ARM /* for keil */
|
|
static void do_puts(struct cmd_handler *hc, 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)
|
|
{
|
|
int n;
|
|
|
|
if (len < 0) {
|
|
len = strlen(s);
|
|
}
|
|
while (len > 0) {
|
|
n = write(STDOUT_FILENO, s, len);
|
|
if (n > 0) {
|
|
len -= n;
|
|
s += n;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int do_getch(struct cmd_handler *hc)
|
|
{
|
|
int c;
|
|
|
|
if (read(STDIN_FILENO, &c, 1) == 1) {
|
|
return (c);
|
|
}
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
static void do_writen(const char *s, int len)
|
|
{
|
|
_G.puts(&_G, s, len);
|
|
}
|
|
|
|
static void do_printf(const char *s)
|
|
{
|
|
do_writen(s, -1);
|
|
}
|
|
|
|
static int do_help(cmd_tbl_t s, int argc, char *argv[])
|
|
{
|
|
#if defined(__CC_ARM)
|
|
cmd_tbl_t it = &Image$$CMDLINE$$Base;
|
|
#else
|
|
cmd_tbl_t it = &__cmdline_cmd_start;
|
|
#endif
|
|
do_printf("support commands:\r\n\r\n");
|
|
#if defined(__CC_ARM)
|
|
while (it < &Image$$CMDLINE$$Limit) {
|
|
#else
|
|
while (it < &__cmdline_cmd_end) {
|
|
#endif
|
|
do_printf(it->name);
|
|
do_printf("\t");
|
|
do_printf(it->help);
|
|
do_printf("\r\n");
|
|
++it;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
CON_CMD(help, "commands help", NULL, do_help)
|
|
|
|
int cmd_init()
|
|
{
|
|
G_N = 0 ;
|
|
_G.puts = do_puts;
|
|
_G.getch = 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;
|
|
char *p;
|
|
int position;
|
|
|
|
/* Init params */
|
|
p = cmd;
|
|
position = 0;
|
|
argc = 0;
|
|
|
|
while ((position < len) && (argc < _maxargs)) {
|
|
/* Skip all blanks */
|
|
while (((*p) == ' ') && (position < len)) {
|
|
*p = '\0';
|
|
p++;
|
|
position++;
|
|
}
|
|
/* Process begin of a string */
|
|
if (*p == '"') {
|
|
p++;
|
|
position++;
|
|
argv[argc] = p;
|
|
argc++;
|
|
/* Skip this string */
|
|
while ((*p != '"') && (position < len)) {
|
|
p++;
|
|
position++;
|
|
}
|
|
/* Skip '"' */
|
|
*p = '\0';
|
|
p++;
|
|
position++;
|
|
} else {/* Normal char */
|
|
argv[argc] = p;
|
|
argc++;
|
|
while (((*p) != ' ') && ((*p) != '\t') && (position < len)) {
|
|
p++;
|
|
position++;
|
|
}
|
|
}
|
|
}
|
|
return argc;
|
|
}
|
|
|
|
int cmd_process(char *line)
|
|
{
|
|
#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;
|
|
}
|
|
|
|
argc = parse_line(line, size, argv, TARGET_CMD_MAXARGS + 1);
|
|
|
|
if (argc <= 0)
|
|
goto recovery;
|
|
|
|
#if defined(__CC_ARM)
|
|
while (it < &Image$$CMDLINE$$Limit) {
|
|
#else
|
|
while (it < &__cmdline_cmd_end) {
|
|
#endif
|
|
namelen = strlen(it->name);
|
|
if (strncasecmp(argv[0], it->name, namelen) == 0) {
|
|
it->cmd(it, argc, argv);
|
|
return 1;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
/* recovery line */
|
|
recovery:
|
|
for (i = 0; i < size; ++i) {
|
|
if (line[i] == '\0')
|
|
line[i] = ' ';
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cmd_loop()
|
|
{
|
|
int c;
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
do_writen("> ", 2);
|
|
continue;
|
|
}
|
|
|
|
if (isprint(c)) {
|
|
G_BUF[G_N] = c;
|
|
G_N++;
|
|
do_writen((char *)&c, 1);
|
|
}
|
|
} while (1) ;
|
|
}
|
|
|
|
|