Chinaunix首页 | 论坛 | 博客
  • 博客访问: 866203
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: LINUX

2010-05-21 10:31:33

前面已经给出了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;
    }
}


阅读(1279) | 评论(0) | 转发(0) |
0

上一篇:USB驱动

下一篇:VIVI中私有数据的管理

给主人留下些什么吧!~~