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.
 
 
 
 
 

204 lines
4.7 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "cmd.h"
#define MAX_HISTORY (4)
#define CMDBUF_SIZE (256)
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 */
};
extern struct cmd_tbl_s __cmdline_cmd_start, __cmdline_cmd_end;
static int maxargs = 4;
static char cmdbuf[CMDBUF_SIZE];
static int bufidx;
static int do_help(cmd_tbl_t s, int argc, char *argv[])
{
cmd_tbl_t it = &__cmdline_cmd_start;
printf("support commands:\r\n\r\n");
while (it < &__cmdline_cmd_end) {
printf("%s\t%s\r\n", it->name, it->help);
++it;
}
return 0;
}
int cmd_init()
{
cmd_tbl_t it = &__cmdline_cmd_start;
while (it < &__cmdline_cmd_end) {
if (it->maxargs > maxargs)
maxargs = it->maxargs + 1;
++it;
}
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
return 0;
}
static int32_t parse_line(char *cmd, uint32_t len, char *argv[], int _maxargs)
{
uint32_t argc;
char *p;
uint32_t position;
/* Init params */
p = cmd;
position = 0;
argc = 0;
while ((position < len) && (argc < _maxargs)) {
/* Skip all blanks */
while (((char)(*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 (((char)*p != ' ') && ((char)*p != '\t') && (position < len)) {
p++;
position++;
}
}
}
return argc;
}
int cmd_process(char *line)
{
cmd_tbl_t it = &__cmdline_cmd_start;
int size = strlen(line);
int i, argc;
char *argv[maxargs];
/* split line */
for (i = 0; i < maxargs; ++i) {
argv[i] = NULL;
}
argc = parse_line(line, size, argv, maxargs);
if (argc <= 0)
goto recovery;
while (it < &__cmdline_cmd_end) {
if (strcasecmp(argv[0], it->name) == 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;
}
CON_CMD(help, 0, "commands help", do_help)
void cmd_loop()
{
char c;
int n;
do {
n = read(STDIN_FILENO, &c, sizeof c);
if (n <= 0)
break;
if (bufidx >= CMDBUF_SIZE) {
printf("too long\r\n");
bufidx = 0;
write(STDOUT_FILENO, "\r\n> ", 4);
}
switch (c) {
case CTRL_C:
bufidx = 0;
write(STDOUT_FILENO, "\r\n> ", 4);
return;
case BACKSPACE:
case CTRL_H:
if (bufidx > 0) {
write(STDOUT_FILENO, "\b \b", 3);
bufidx--;
cmdbuf[bufidx] = '\0';
}
return;
case CTRL_L:
write(STDOUT_FILENO,"\x1b[H\x1b[2J",7);
write(STDOUT_FILENO, "> ", 2);
if (bufidx > 0)
write(STDOUT_FILENO, cmdbuf, bufidx);
return;
}
/* end of line */
if (c == '\r' || c == '\n') {
write(STDOUT_FILENO, "\r\n", 2);
if (bufidx > 0) {
cmdbuf[bufidx] = '\0';
cmd_process(cmdbuf);
write(STDOUT_FILENO, "\r\n", 2);
bufidx = 0;
}
write(STDOUT_FILENO, "> ", 2);
continue;
}
if (isprint(c)) {
cmdbuf[bufidx++] = c;
write(STDOUT_FILENO, &c, 1);
}
} while (1) ;
}