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

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