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.
320 lines
6.4 KiB
320 lines
6.4 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 "tick.h"
|
|
#include "terminal.h"
|
|
#include "config.h"
|
|
|
|
#define PROMPT_MAX_LEN (8)
|
|
static char __editline_buf[TARGET_CMD_BUFSIZE + (PROMPT_MAX_LEN + 1)] __attribute__((section(".rxbuf.editline,\"aw\",%nobits@")));
|
|
static struct terminal G;
|
|
|
|
#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
|
|
|
|
#ifdef __CC_ARM /* for keil */
|
|
static int tputs(const char *s, int len)
|
|
{
|
|
fwrite(s, len, 1, stdout);
|
|
return (len);
|
|
}
|
|
|
|
static int tgets(char *buf, int len, int blocking /* in millis */)
|
|
{
|
|
char *buf_save = buf;
|
|
int n;
|
|
|
|
if (blocking <= 0) {
|
|
return fread(buf, 1, len, stdin);
|
|
}
|
|
|
|
while (len > 0) {
|
|
n = fread(buf, 1, len, stdin);
|
|
if (n > 0) {
|
|
buf += n;
|
|
len -= n;
|
|
}
|
|
}
|
|
|
|
return (buf - buf_save);
|
|
}
|
|
#else
|
|
static int tputs(const char *s, int len)
|
|
{
|
|
write(STDOUT_FILENO, s, len);
|
|
return (len);
|
|
}
|
|
|
|
static int tgets(char *buf, int len, int blocking /* in millis */)
|
|
{
|
|
char *buf_save = buf;
|
|
int n;
|
|
uint64_t end;
|
|
|
|
if (blocking <= 0) {
|
|
return read(STDIN_FILENO, buf, len);
|
|
}
|
|
|
|
end = millis() + blocking;
|
|
while ((len > 0) && (end > millis())) {
|
|
n = read(STDIN_FILENO, buf, len);
|
|
if (n > 0) {
|
|
buf += n;
|
|
len -= n;
|
|
}
|
|
}
|
|
|
|
return (buf - buf_save);
|
|
}
|
|
#endif
|
|
|
|
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
|
|
printf("support commands:\r\n");
|
|
#if defined(__CC_ARM)
|
|
while (it < &Image$$CMDLINE$$Limit) {
|
|
#else
|
|
while (it < &__cmdline_cmd_end) {
|
|
#endif
|
|
printf("%s\t%s\r\n", it->name, it->help);
|
|
++it;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
CON_CMD(help, "commands help", NULL, do_help)
|
|
|
|
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)
|
|
{
|
|
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
|
|
|
|
/* 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;
|
|
}
|
|
|
|
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);
|
|
|
|
static int do_mode(cmd_tbl_t s, int argc, char *argv[])
|
|
{
|
|
int mode;
|
|
|
|
if (argc >= 2) {
|
|
mode = atoi(argv[1]);
|
|
G.mlmode = mode > 0 ? 1 : 0;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
CON_CMD(mlmode, "set multi-line cmdline mode (0 or 1)", NULL, do_mode);
|
|
|
|
static int __puts(void *unused, const char *s, int len)
|
|
{
|
|
return tputs(s, len);
|
|
}
|
|
|
|
static int __gets(void *unused, char *s, int len, int blocking)
|
|
{
|
|
return tgets(s, len, blocking);
|
|
}
|
|
|
|
static int get_matched(const char *buf, int len)
|
|
{
|
|
#if defined(__CC_ARM)
|
|
cmd_tbl_t it = &Image$$CMDLINE$$Base;
|
|
#else
|
|
cmd_tbl_t it = &__cmdline_cmd_start;
|
|
#endif
|
|
int n, mached = 0;
|
|
|
|
#if defined(__CC_ARM)
|
|
while (it < &Image$$CMDLINE$$Limit) {
|
|
#else
|
|
while (it < &__cmdline_cmd_end) {
|
|
#endif
|
|
n = strlen(it->name);
|
|
if (n > len)
|
|
n = len;
|
|
if (memcmp(it->name, buf, n) == 0)
|
|
++mached;
|
|
++it;
|
|
}
|
|
|
|
return (mached);
|
|
}
|
|
|
|
static int __matched(void *unused, const char *buf, int len, const char *vec[], int mached)
|
|
{
|
|
#if defined(__CC_ARM)
|
|
cmd_tbl_t it = &Image$$CMDLINE$$Base;
|
|
#else
|
|
cmd_tbl_t it = &__cmdline_cmd_start;
|
|
#endif
|
|
int i = 0, n;
|
|
|
|
if (vec == NULL || mached == 0) {
|
|
return get_matched(buf, len);
|
|
}
|
|
|
|
#if defined(__CC_ARM)
|
|
while (it < &Image$$CMDLINE$$Limit) {
|
|
#else
|
|
while (it < &__cmdline_cmd_end) {
|
|
#endif
|
|
n = strlen(it->name);
|
|
if (n > len)
|
|
n = len;
|
|
if (memcmp(it->name, buf, n) == 0) {
|
|
vec[i++] = it->name;
|
|
if (i >= mached)
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
return (i);
|
|
}
|
|
|
|
static void __dispatch(void *unused, char *s, int len)
|
|
{
|
|
cmd_process(s);
|
|
}
|
|
|
|
int cmd_init(const char *prompt)
|
|
{
|
|
struct terminal *l = &G;
|
|
struct lineop opbase;
|
|
|
|
#if defined(__CC_ARM)
|
|
setvbuf(stdin, NULL, _IONBF, 0);
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
setvbuf(stderr, NULL, _IONBF, 0);
|
|
#endif
|
|
|
|
opbase.puts = __puts;
|
|
opbase.gets = __gets;
|
|
opbase.match = __matched;
|
|
opbase.dispatch = __dispatch;
|
|
opbase.priv = NULL;
|
|
|
|
if (!term_init(l, &opbase, __editline_buf, sizeof __editline_buf, prompt, TARGET_CMD_HISTORY)) {
|
|
term_set_multiline(l, TARGET_CMD_MULTIMODE);
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void cmd_refresh()
|
|
{
|
|
term_refresh(&G);
|
|
}
|
|
|
|
void cmd_loop()
|
|
{
|
|
struct terminal *l = &G;
|
|
|
|
term_dispatch(l);
|
|
}
|
|
|
|
|