命令行解析框架,使用链表将所有注册的信息串联起来,然后每个节点node包含了,keyword,help,数据类型描述,命令执行的回调函数,和参数存储的回调函数。主要的应用点是,
已知函数变量地址,类型,和地址宽度,然后强制转换后对变量读写操作
经过网友的提醒,在关键字匹配的时候采用for循环匹配对整个框架来讲不是最优的,所以嵌入了博主
http://www.cnblogs.com/skywang12345/p/3624177.html
的红黑树的C代码,于是有了新的版本。
源码地址:
https://download.csdn.net/download/seeker_zeroone/10743399
使用红黑树索引关键字的源代码:
https://download.csdn.net/download/seeker_zeroone/10776229
命令节点结构体如下;
typedef struct fun_node
{
struct fun_node *pNext;
const char *pHelp;
const char *pName;
uint8_t paraNum;
FUN_CMD_BK RunFun;
uint8_t EnableState;
}ST_FUN_NODE;
typedef enum
{
emCmdDataType_Dec =1,
emCmdDataType_Hex =2,
emCmdDataType_Str =3,
emCmdDataType_IP =4,
emCmdDataType_MAC =5,
}EM_CMD_DATA_TYPE;
typedef struct cmd_para
{
struct cmd_para *pNext;
const char *pName;
void *pDataAddr;
uint16_t dataLen;
EM_CMD_DATA_TYPE dataType;
uint8_t EnableState;
}ST_CMD_PARA;
typedef struct cmd_node
{
const char *pKeyword;
const char *pHelp;
ST_CMD_PARA *pData;
ST_FUN_NODE *pFuntion;
FUN_STOR_BK StorageFun;
}ST_CMD_NODE;
参数注册配置实例:
void cla_parametersConfig(void)
{
cla_init();
cla_regsister("uuid","uuid <only read>");
cla_addParameter("uuid","uuid ",(void *)&uuid,emCmdDataType_Str, sizeof(uuid));
cla_regsister("wifi","wifi or wifi ssid=xxx password=xxx");
cla_addParameter("wifi","ssid",(void *)ssid,emCmdDataType_Str, sizeof(ssid));
cla_addParameter("wifi","password",(void *)password,emCmdDataType_Str, sizeof(password));
cla_regsister("hex","hex or hex hex8=xx hex16=xx hex32=xx");
cla_addParameter("hex","hex8",(void *)&hex8,emCmdDataType_Hex, sizeof(data8));
cla_addParameter("hex","hex16",(void *)&hex16,emCmdDataType_Hex, sizeof(data16));
cla_addParameter("hex","hex32",(void *)&hex32,emCmdDataType_Hex, sizeof(data32));
cla_regsister("data","data or data data8=xx data16=xx data32=xx");
cla_addParameter("data","data8",(void *)&data8,emCmdDataType_Dec, sizeof(data8));
cla_addParameter("data","data16",(void *)&data16,emCmdDataType_Dec, sizeof(data16));
cla_addParameter("data","data32",(void *)&data32,emCmdDataType_Dec, sizeof(data32));
cla_regsister("ipconfig","ipconfig or ipconfig ipaddr=192.168.1.1");
cla_addParameter("ipconfig","ipaddr",(void *)IPaddr,emCmdDataType_IP, sizeof(IPaddr));
cla_addParameter("ipconfig","mask",(void *)maskIP,emCmdDataType_IP, sizeof(maskIP));
cla_addParameter("ipconfig","dns",(void *)dnsIP,emCmdDataType_IP, sizeof(dnsIP));
cla_addParameter("ipconfig","mac",(void *)Mac,emCmdDataType_MAC, sizeof(Mac));
cla_regsister("run","<funtions>");
cla_addRunFun("run",ptest_3fun_help,"test",test_3fun,3);
cla_addRunFun("run",ptest_2fun_help,"test2",test_2fun,2);
}
参数注册,需要先申请一个Node
BOOLEAN cla_regsister(const char *pKeyword,const char *pHelp)
{
ST_CMD_NODE *pNode=NULL;
pNode =cla_getFreeNode();
if(pNode !=NULL)
{
pNode->pKeyword =pKeyword;
pNode->pHelp =pHelp;
pNode->pData =NULL;
pNode->pFuntion =NULL;
pNode->StorageFun =NULL;
return TRUE;
}
Debug("%s regsiter failed\n",pKeyword);
return FALSE;
}
为Node添加参数描述信息,Node的关键字,参数名称,参数地址,参数类型,参数宽度
BOOLEAN cla_addParameter(const char *pKey,const char *pName,void *pDataAddr,EM_CMD_DATA_TYPE dataType,uint16_t dataLen)
{
ST_CMD_NODE *pNode=NULL;
ST_CMD_PARA *pData=NULL;
pNode =cla_getNodeOfKey(pKey);
if(pNode!=NULL)
{
pData =cla_getFreePara();
if(pData !=NULL)
{
pData->pName =pName;
pData->pDataAddr =pDataAddr;
pData->dataType =dataType;
pData->dataLen =dataLen;
pData->pNext =NULL;
cla_setParamete(pNode,pData);
return TRUE;
}
}
Debug("%s no support\n",pKey);
return FALSE;
}
为node节点添加命令函数描述信息,node的关键字,帮助信息,函数名称,函数回调地址,函数入口参数个数
BOOLEAN cla_addRunFun(const char *pKey,const char *pHelp,const char *pFunName,FUN_CMD_BK funcb,uint8_t paraNum)
{
ST_CMD_NODE *pNode=NULL;
ST_FUN_NODE *pFun=NULL;
pNode =cla_getNodeOfKey(pKey);
if(pNode!=NULL)
{
pFun =cla_getFreeFunNode();
if(pFun !=NULL)
{
pFun->pName =pFunName;
pFun->paraNum =paraNum;
pFun->RunFun =funcb;
pFun->pHelp =pHelp;
pFun->pNext =NULL;
cla_setFuntion(pNode,pFun);
return TRUE;
}
}
Debug("%s no support\n",pKey);
return FALSE;
}
根据命令参数,打印相关的变量
static uint16_t cla_sprintfPara(ST_CMD_PARA *pData,char *pbuff,uint16_t buffLen)
{
uint32_t value=0,tmpLen,totalLen=0,i;
uint32_t ipaddr[4],macAddr[6];
while((pData !=NULL)&&(buffLen > 0))
{
switch(pData->dataType)
{
case emCmdDataType_Dec:
{
value =cla_getValueOfAddrType(pData->pDataAddr,pData->dataLen);
snprintf(pbuff,buffLen,"%s=%d ",pData->pName,value);
}break;
case emCmdDataType_Hex:
{
value =cla_getValueOfAddrType(pData->pDataAddr,pData->dataLen);
snprintf(pbuff,buffLen,"%s=0x%x ",pData->pName,value);
}break;
case emCmdDataType_Str:
{
snprintf(pbuff,buffLen,"%s=%s ",pData->pName,(const char *)pData->pDataAddr);
}break;
case emCmdDataType_IP:
{
if(pData->dataLen >= 4)
{
for(i=0;i<4;i++)
{
ipaddr[i] =cla_getValueOfAddrType((void *)((uint8_t *)(pData->pDataAddr) + i), sizeof(uint8_t));
}
snprintf(pbuff,buffLen,"%s=%d.%d.%d.%d ",pData->pName,
ipaddr[0],ipaddr[1],ipaddr[2],ipaddr[3]);
}
}break;
case emCmdDataType_MAC:
{
if(pData->dataLen >= 6)
{
for(i=0;i<6;i++)
{
macAddr[i] =cla_getValueOfAddrType((void *)((uint8_t *)(pData->pDataAddr) + i), sizeof(uint8_t));
}
snprintf(pbuff,buffLen,"%s=%02X-%02X-%02X-%02X-%02X-%02X ",pData->pName,
macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5]);
}
}break;
default:
break;
}
pData =pData->pNext;
tmpLen =strlen((const char *)pbuff);
pbuff +=tmpLen;
totalLen +=tmpLen;
buffLen -=tmpLen;
}
strcpy(pbuff,"\r\n");
return (totalLen + 3);
}
查找命令,为变量赋值
static BOOLEAN cla_scanfPara(ST_CMD_PARA *pData,ST_CMD_STR *pParaIn)
{
BOOLEAN res;
uint16_t i,k;
uint32_t value;
static uint8_t nmeBuff[32],dataBuff[32],Offset=0,pos=0;
ST_CMD_PARA *pStorData;
for(i=pParaIn->argPos;i<pParaIn->argCount;i++)
{
memset(nmeBuff,0,sizeof(nmeBuff));
memset(dataBuff,0,sizeof(dataBuff));
res =cla_takeNameData(pParaIn->pArgValue[i],nmeBuff,dataBuff);
if(res)
{
Debug("name->%s data->%s\n",nmeBuff,dataBuff);
pStorData =cla_getParaOfName(pData,(const char *)nmeBuff);
if(pStorData)
{
switch(pStorData->dataType)
{
case emCmdDataType_Dec:
{
value =cla_atoi(dataBuff,&Offset);
cla_setValueOfAddrType(pStorData->pDataAddr,pStorData->dataLen,value);
}break;
case emCmdDataType_Hex:
{
value =cla_atohex(dataBuff,&Offset);
//Debug("hex-->0x%02x",value);
cla_setValueOfAddrType(pStorData->pDataAddr,pStorData->dataLen,value);
}break;
case emCmdDataType_Str:
{
strncpy((char *)pStorData->pDataAddr,(const char *)dataBuff,pStorData->dataLen);
}break;
case emCmdDataType_IP:
{
if(pStorData->dataLen >=4)
{
for(pos=0,Offset=0,k=0;k<4;k++)
{
pos +=Offset;
value =cla_atoi(dataBuff + pos,&Offset);
cla_setValueOfAddrType(((uint8_t *)(pStorData->pDataAddr) + k),1,value);
}
}
}break;
case emCmdDataType_MAC:
{
if(pStorData->dataLen >=6)
{
for(pos=0,Offset=0,k=0;k<6;k++)
{
pos +=Offset;
value =cla_atohex(dataBuff + pos,&Offset);
//Debug("mac%d-->%02x",k,value);
cla_setValueOfAddrType(((uint8_t *)(pStorData->pDataAddr) + k),1,value);
}
}
}break;
default:
break;
}
}
else
{
Debug("no support %s\n",nmeBuff);
}
}
else
{
Debug("parameter err\n");
}
}
return TRUE;
}
void cla_precess(uint8_t *pCmd,uint16_t cmdLen,FUN_PRINT_OUT printFun)
{
uint16_t i,outlen;
FUN_STOR_BK storageFun=NULL;
BOOLEAN res;
static ST_CMD_STR cmdStr;
static char outBuff[OUT_BUFF_MAX_LEN];
if((pCmd !=NULL)&&(cmdLen > 2))
{
cla_cmdMake(&cmdStr,pCmd,cmdLen);
if((cla_CheckIn(&cmdStr,printFun))&&(cmdStr.argCount >= 1))
{
for(i=0;i<CMD_NODE_TOTAL;i++)
{
if(CmdNodeGroup[i].pKeyword != NULL)
{
if(strcmp((const char *)CmdNodeGroup[i].pKeyword,cmdStr.pArgValue[0]) == 0)
{
if(cmdStr.argCount == 1)//查询参数
{
outlen =cla_sprintfPara(CmdNodeGroup[i].pData,outBuff,OUT_BUFF_MAX_LEN);
if(printFun !=NULL)
{
printFun(outBuff,outlen);
}
Debug("out done\n");
}
else if(strcmp("run",cmdStr.pArgValue[0]) == 0)
{
cmdStr.argPos =1;
res =cla_runFuntion(CmdNodeGroup[i].pFuntion,&cmdStr);
Debug("run done\n");
}
else
{
cmdStr.argPos =1;
res =cla_scanfPara(CmdNodeGroup[i].pData,&cmdStr);
if(res)
{
Debug("cfg done\n");
storageFun =CmdNodeGroup[i].StorageFun;
if(storageFun !=NULL)
{
storageFun();
}
}
}
return ;
}
else if(strcmp("help",cmdStr.pArgValue[0]) == 0)
{
cla_help(printFun,outBuff,OUT_BUFF_MAX_LEN);
return ;
}
}
}
}
}
}
命令行解析进程
1,cmdMake对输入的命令行,进行格式化匹配,并得到输入命令行参数个数
2,命令行账户校验
3,匹配关键字
4,命令行参数个数为1,表示查询
5,令行参数为多个,表示参数配置
6,run xxFun param1 param2 .. 表示运行xx函数,然后传递参数为param1..