今天金猪同学说想要一个应用程序的shell 可以用来调试应用程序 (直接在shell 内输入函数的名字和参数就可以调用应用程序内的函数。)
于是下午花了一个多小时, 写了一个简单的demo, 之所以叫demo 是因为, 本来可以通过nm 命令导出的符号表来生成shell 内函数的数组, 而不是手动注册各个函数, 但是本人能力有限, 没有完成, 所以只有自己手动注册相关的函数了(demo 里注册了两个函数 XandY(int x, int y) 和PrintHex(char *bufP)), OK 功能描述至此, 下面粘代码, 希望大侠看了不要笑话~
菜鸟拙码, 希望大家不吝赐教!~
此代码 遵循 GNU General Public License, 在遵守<GNU General Public License>的前提下, 可以自由分发和修改, 作者: Michael Liu michael.liu.point@gmail.com
shell.c
==================================================================================
/*
** Copyright (c) 2009 Michael <michael.liu.point@gmail.com>.
**
** Project: Simple shell
** File: shell.c
** Author: Michael
** Date: 07/22/2009
**
** Purpose:
** A simple Shell for Debug..
*/
/* Include files. */
#include "shell.h"
/* Macro constant definitions. */
#define INPUT_BUF_LENGTH 0x400
#define SHELL_PROMPT "MichaeL ^-^ >"
/* Type definitions. */
/* Local function declarations. */
void GetString(uint8 *buff, sint32 *length);
void* ShellTashMain(void * taskArgP);
void ShellTashMainCreate(void);
void ParseInput(uint8 *inputBufP);
int ParseArgs(int *argsP, uint8 *argBufP);
int XandY(int x, int y);
void PrintHex(uint8 *strP);
/* Macro API definitions. */
#define IsDigit(date) ((((date) >= '0') && ((date) <= '9')) ? 0x01 : 0x00)
/* Global variable declarations. */
static pthread_mutex_t ShellMainLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t ShellMainWait = PTHREAD_COND_INITIALIZER;
pthread_t ShellTaskId;
tSymbolEntry FuncDb[FUNC_DB_ENTRY_MAX] =
{
{"XandY", (funcPtr)XandY},
{"PrintHex", (funcPtr)PrintHex},
};
int
main(int argc, char **argvPP)
{
ShellTashMainCreate();
/* Hold on this. */
pthread_mutex_lock(&ShellMainLock);
pthread_cond_wait(&ShellMainWait, &ShellMainLock);
/* Never reach here. */
return (0);
} /* End of main() */
void*
ShellTashMain(void* taskArgP)
{
uint8 inputBuf[INPUT_BUF_LENGTH];
sint32 inputLen = 0;
while(1)
{
memset(inputBuf, 0, INPUT_BUF_LENGTH);
inputLen = INPUT_BUF_LENGTH;
printf("/n%s", SHELL_PROMPT);
GetString(inputBuf, &inputLen);
if (-1 == inputLen)
{
printf("Too long command./n");
continue;
}
else if ((0 == inputLen) || ('/n' == inputBuf[0]))
{
continue;
}
ParseInput(inputBuf);
}
} /* End of ShellTashMain() */
void
ShellTashMainCreate(void)
{
int ret = 0;
ret = pthread_create(&ShellTaskId, NULL, ShellTashMain, NULL);
if(0 != ret)
{
printf("pthread_create() failed, err: %d./n", ret);
}
return;
} /* End of ShellTashMainCreate() */
void
GetString(uint8 *buff, sint32 *length)
{
sint32 indexI = 0;
char tmpChar;
while((tmpChar = getchar()) != '/n')
{
if (indexI < *length)
{
buff[indexI] = tmpChar;
}
else if (indexI >= *length)
{
*length = -1;
return;
}
indexI++;
}
*length = indexI;
return;
} /* End of GetString() */
void
ParseInput(uint8 *inputBufP)
{
int rc = 0;
int args[ARGS_COUNTER_MAX];
funcPtr functionP = NULL;
uint32 indexI = 0;
uint32 cmdLen = 0;
for (indexI = 0; indexI < FUNC_DB_ENTRY_MAX; indexI++)
{
cmdLen = strlen(FuncDb[indexI].name);
if (strncmp((void*)inputBufP, FuncDb[indexI].name, cmdLen) == 0)
{
functionP = FuncDb[indexI].value;
memset(args, 0, ARGS_COUNTER_MAX);
if(ParseArgs(args, &(inputBufP[cmdLen])) != 0)
{
return;
}
break;
}
}
if (NULL != functionP)
{
rc = functionP(args[0], args[1], args[2], args[3],
args[4], args[5], args[6],args[7], args[8], args[9]);
printf("/nReturn code = 0x%x/n", rc);
}
else
{
printf("No related command.");
}
} /* End of ParseInput() */
int
ParseArgs(int *argsP, uint8 *argBufP)
{
uint32 argsLen = 0;
uint32 argsCounter = 0;
uint32 indexI = 0;
uint8 startPos = 0;
argsLen = strlen((void*)argBufP);
for (; indexI < argsLen; indexI++)
{
if (argsCounter >= ARGS_COUNTER_MAX)
{
printf("Too many arguments!/n");
return (-1);
}
if (0 == startPos)
{
if (' ' == argBufP[indexI])
{
continue;
}
else if ('/n' == argBufP[indexI])
{
break;
}
else if (IsDigit(argBufP[indexI]))
{
argsP[argsCounter] = atoi((void*)&(argBufP[indexI]));
argsCounter++;
}
else if ('"' == argBufP[indexI])
{
startPos = 0x01;
*argsP = (long)&(argBufP[indexI + 1]);
}
}
else if('"' == argBufP[indexI])
{
argBufP[indexI] = 0;
startPos = 0x00;
argsCounter++;
}
} /* End of for() */
return (0);
} /* End of ParseArgs() */
int
XandY(int x, int y)
{
printf("%d + %d = %d./n", x, y, x + y);
return (0);
} /* End of XandY() */
void
PrintHex(uint8 *strP)
{
uint32 len = 0;
uint32 indexI = 0;
len = strlen((void*)strP);
printf("/n");
for (indexI = 0; indexI < len; indexI++)
{
printf("%.2X%c", strP[indexI],
(((indexI + 1) % 16) == 0 ? '/n' : ' '));
}
return;
} /* End of PrintHex() */
shell.h
==================================================================================
/*
** Copyright (c) 2009 Michael <michael.liu.point@gmail.com>.
**
** Project: Simple shell
** File: shell.h
** Author: Michael
** Date: 07/22/2009
**
** Purpose:
** Header file for shell.c.
*/
#ifndef SHELL_H
#define SHELL_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Include files. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
/* Macro constant definitions. */
#define FUNC_NAME_LENGTH_MAX 0x80
#define FUNC_DB_ENTRY_MAX 0x80
#define ARGS_COUNTER_MAX 0x0A
/* Type definitions. */
typedef unsigned char uint8; /* 8-bit unsigned value. */
typedef unsigned short uint16; /* 16-bit unsigned value. */
typedef unsigned int uint32; /* 32-bit unsigned value. */
typedef signed char sint8; /* 8-bit signed value. */
typedef signed short sint16; /* 16-bit signed value. */
typedef signed int sint32; /* 32-bit signed value. */
typedef int (*funcPtr)();
typedef struct
{
char name[FUNC_NAME_LENGTH_MAX];
funcPtr value;
} tSymbolEntry;
/* External function declarations. */
/* Macro API definitions. */
/* Global variable declarations. */
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* SHELL_H */