您的位置:首页 > 编程语言

优秀代码赏析(c, 链表, 命令解析框架)

2013-09-06 18:06 344 查看
以下代码摘录自 vivi-20090929

#ifndef _VIVI_COMMAND_H_
#define _VIVI_COMMAND_H_

enum ParseState {
PS_WHITESPACE,
PS_TOKEN,
PS_STRING,
PS_ESCAPE
};

typedef struct user_command {
const char *name;
void (*cmdfunc)(int argc, const char **);
struct user_command *next_cmd;
const char *helpstr;
} user_command_t;

typedef struct user_subcommand {
const char *name;
void (*cmdfunc)(int argc, const char **);
const char *helpstr;
} user_subcommand_t;

/* General interfaces */
extern void add_command(user_command_t *cmd);
void execcmd(int, const char **);
void exec_string(char *);
void execsubcmd(user_subcommand_t *, int, const char **);
void print_usage(char *strhead, user_subcommand_t *);
void invalid_cmd(const char *cmd_name, user_subcommand_t *cmds);
int init_builtin_cmds(void);

#endif /* _VIVI_COMMAND_H_ */


#include "command.h"

enum ParseState stackedState;
static user_command_t *head_cmd = NULL;
static user_command_t *tail_cmd = NULL;

/*
* Parse user command line
*/
void parseargs(char *argstr, int *argc_p, char **argv, char** resid)
{
int argc = 0;
char c;
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 unparseargs(char *argstr, int argc, const char **argv)
{
int i;
for (i = 0; i < argc; i++) {
if (argv[i] != NULL) {
strcat(argstr, " ");
strcat(argstr, argv[i]);
}
}
}

/*
* Genernal interface
*/

/*
* For (main) commands
*/

/* add user command */
void add_command(user_command_t *cmd)
{
if (head_cmd == NULL) {
head_cmd = tail_cmd = cmd;
} else {
tail_cmd->next_cmd = cmd;
tail_cmd = cmd;
}
/*printk("Registered '%s' command\n", cmd->name);*/
}

/* find command */
user_command_t *find_cmd(const char *cmdname)
{
user_command_t *curr;

/* do da string compare for the first offset character of cmdstr
against each number of the cmdlist */
curr = head_cmd;
while(curr != NULL) {
if (strncmp(curr->name, cmdname, strlen(cmdname)) == 0)
return curr;
curr = curr->next_cmd;
}
return NULL;
}

/* execute a function */
void execcmd(int argc, const char **argv)
{
user_command_t *cmd = find_cmd(argv[0]);

if (cmd == NULL) {
printk("Could not found '%s' command\n", argv[0]);
printk("If you want to konw available commands, type 'help'\n");
return;
}
/*printk("execcmd: cmd=%s, argc=%d\n", argv[0], argc);*/

cmd->cmdfunc(argc, argv);
}

/* parse and execute a string */
void exec_string(char *buf)
{
int argc;
char *argv[128];
char *resid;

while (*buf) {
memset(argv, 0, sizeof(argv));
parseargs(buf, &argc, argv, &resid);
if (argc > 0)
execcmd(argc, (const char **)argv);
buf = resid;
}
}

/*
* For sub-commands
*/
void execsubcmd(user_subcommand_t *cmds, int argc, const char **argv)
{

while (cmds->name != NULL) {
if (strncmp(argv[0], cmds->name, strlen(argv[0])) == 0) {
/*printk("subexeccmd: cmd=%s, argc=%d\n", argv[0], argc);*/
cmds->cmdfunc(argc, argv);
return;
}
cmds++;
}
printk("Could not found '%s' sub-command\n", argv[0]);
}

void print_usage(char *strhead, user_subcommand_t *cmds)
{
printk("Usage:\n");
while (cmds->name != NULL) {
if (strhead)
printk("%s ", strhead);
if (*cmds->helpstr)
printk("%s\n", cmds->helpstr);
cmds++;
}
}

void invalid_cmd(const char *cmd_name, user_subcommand_t *cmds)
{
printk("invalid '%s' command: wrong argumets\n", cmd_name);
print_usage("  ", cmds);
}
//测试代码
/* help command */
void command_help(int argc, const char **argv)
{
user_command_t *curr;

/* help <command>. invoke <command> with 'help' as an argument */
if (argc == 2) {
if (strncmp(argv[1], "help", strlen(argv[1])) == 0) {
printk("Are you kidding?\n");
return;
}
argv[0] = argv[1];
argv[1] = "help";
execcmd(argc, argv);
return;
}

printk("Usage:\n");
curr = head_cmd;
while(curr != NULL) {
printk("   %s\n", curr->helpstr);
curr = curr->next_cmd;
}
}

user_command_t help_cmd = {
"help",
command_help,
NULL,
"help [{cmds}] \t\t\t-- Help about help?"
};

/* dump command */
void command_dump(int argc, const char *argv[])
{
size_t num;
unsigned char *p;

if (argc == 3)	/* size spcified */
num = strtoul(argv[2], NULL, 0, NULL);
else
num = 16;

p = (unsigned char *)strtoul(argv[1], NULL, 0, NULL);

hex_dump(p, num);
}

user_command_t dump_cmd = {
"dump",
command_dump,
NULL,
"dump <addr> <length> \t\t-- Display (hex dump) a range of memory."
};

/* Register basic user commands */
int init_builtin_cmds(void)
{
add_command(&dump_cmd);
add_command(&help_cmd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: