前面已经给出了vivi中命令的实现那篇文章
下面给出这篇源代码,这篇源代码实现了一个完整的流程。包括从键盘键入命令,然后解析命令,最后是执行命令!
相信看完这个代码会有所收获:)
/*
* vivi/lib/command.c:
* - to support user commands on the boot loader
*
* Copyright (C) 2001 MIZI Research, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Author: Janghoon Lyu
* Date : $Date: 2004/02/04 06:22:25 $
*
* $Revision: 1.1.1.1 $
*
*
* History
*
* 2001-12-23: Janghoon Lyu
* - Initial code
* - Base on bootldr/bootldr.c
*
* 2002-02-23: Janghoon Lyu
* - Add flash commands
*
* 2002-07-13: Janghoon Lyu
*
*/
#include <string.h>
#include "serial.h"
#include "UART_printf.h"
#include "load_file.h"
#include "boot_interface.h"
enum ParseState {
PS_WHITESPACE,
PS_TOKEN,
PS_STRING,
PS_ESCAPE
};
#define MAX_CMDBUF_SIZE 80
#define CTL_CH(c) ((c) - 'a' + 1)
void getcmd(char *cmd_buf, unsigned int len);
void exec_string(char *buf);
void execcmd(int argc, char **argv);
void jump(int argc, char **argv)
{
unsigned int jump_addr;
int ret;
switch( argc )
{
case 0: jump_addr = RAM_BASE;
break;
case 1: jump_addr = strtoul(argv[0], NULL, 0, &ret);
if (ret)
{
UART_printf("Can't parsing argumets.\n");
return ;
}
if( (jump_addr & 0x11) != 0 )
{
UART_printf("Address must be aligned 4.\n");
return ;
}
break;
default:UART_printf("invalid 'jump' command: too many arguments\n");
return ;
}
jump_to( jump_addr );
}
void serial_term(void)
{
char cmd_buf[MAX_CMDBUF_SIZE];
UART_printf("Now command shell is starting.\n");
for (;;) {
UART_printf("Input command >>");
getcmd(cmd_buf, MAX_CMDBUF_SIZE);
/* execute a user command */
if( strcmp( cmd_buf, "quit" ) == 0 )
{
UART_printf("Now quit command shell.\n");
break;
}
if (cmd_buf[0])
exec_string(cmd_buf);
}
}
void getcmd(char *cmd_buf, unsigned int len)
{
char curpos = 0; /* current position - index into cmd_buf */
char c;
int cmd_echo = 1;
/* Clear out the buffer */
memset(cmd_buf, 0, MAX_CMDBUF_SIZE);
for (;;) {
c = UART_getchar();
switch (c) {
case 0x08:
case 0x06:
case 0x07:
case 0x7E:
case 0x7F: /* backspace or delete */
/* we're not at the beginning of the line */
if (curpos) {
curpos--;
UART_putchar(0x08); /* go backwards */
UART_putchar(' '); /* overwrite the char */
UART_putchar(0x08); /* go back again */
}
cmd_buf[curpos] = '\0';
break;
case '\r':
case '\n':
case '\0':
UART_putchar('\r');
UART_putchar('\n');
goto end_cmd;
case CTL_CH('x'):
curpos = 0;
break;
default:
if (curpos < MAX_CMDBUF_SIZE) {
cmd_buf[curpos] = c;
/* echo it back out to the screen */
if (cmd_echo)
UART_putchar(c);
curpos++;
}
break;
}
}
end_cmd:
UART_printf("COMMAND: %s\n\r", cmd_buf);
}
/*
* Parse user command line
*/
void parseargs(char *argstr, int *argc_p, char **argv, char** resid)
{
int argc = 0;
char c;
enum ParseState stackedState;
enum ParseState lastState = PS_WHITESPACE;
/* tokenize the argstr */
while ((c = *argstr) != 0) {
enum ParseState newState;
if (c == ';' && lastState != PS_STRING && lastState != PS_ESCAPE)
break;
if (lastState == PS_ESCAPE) {
newState = stackedState;
} else if (lastState == PS_STRING) {
if (c == '"') {
newState = PS_WHITESPACE;
*argstr = 0;
} else {
newState = PS_STRING;
}
} else if ((c == ' ') || (c == '\t')) {
/* whitespace character */
*argstr = 0;
newState = PS_WHITESPACE;
} else if (c == '"') {
newState = PS_STRING;
*argstr++ = 0;
argv[argc++] = argstr;
} else if (c == '\\') {
stackedState = lastState;
newState = PS_ESCAPE;
} else {
/* token */
if (lastState == PS_WHITESPACE) {
argv[argc++] = argstr;
}
newState = PS_TOKEN;
}
lastState = newState;
argstr++;
}
argv[argc] = NULL;
if (argc_p != NULL)
*argc_p = argc;
if (*argstr == ';') {
*argstr++ = '\0';
}
*resid = argstr;
}
void execcmd(int argc, char **argv)
{
if( strcmp( argv[0], "load" ) == 0 )
{
if( strcmp( argv[1], "ram" ) == 0)
load_ram( argc-1, argv+1 );
else if( strcmp( argv[1], "flash" ) == 0 )
load_flash( argc-1, argv+1 );
else
{
UART_printf("Could not found '%s' sub-command\n", argv[0]);
UART_printf("If you want to konw available commands, type 'help'\n");
}
}
else if( strcmp( argv[0], "jump" ) == 0 )
jump( argc-1, argv+1 );
else if( strcmp( argv[0], "help" ) == 0 )
{
UART_printf( "\nload |- flash "> \t--Load a file to Flash\n"
" |- ram [addr [length]] \t-- Load a file to RAM \n"
"\njump [addr] \t-- jump to addr(default value:RAM_BASE) and execute .\n"
"\nquit \t--quit command shell .\n"
"\nhelp \t--about help .\n" );
}
else
{
UART_printf("The '%s' command is an invilid command.\n"
"If you want to konw available commands, type 'help'\n");
}
}
/* parse and execute a string */
void exec_string(char *buf)
{
int argc;
char *argv[10];
char *resid;
while (*buf) {
memset(argv, 0, sizeof(argv));
parseargs(buf, &argc, argv, &resid);
if (argc > 0)
execcmd(argc, (char **)argv);
buf = resid;
}
}
|