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

#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) ;
}