cli.c

来自「基于ARM和uC/OS-II实现的串口控制台」· C语言 代码 · 共 1,153 行 · 第 1/3 页

C
1,153
字号
        pParaBuf[i] = CurBuf[offset + i];
    }

    pParaBuf[i] = '\0';
    
    return TRUE;
}

/*******************************************************************************
* Function:     SearchCmd()
* Description:  在当前命令集中查找输入的命令字串
* Calls:        
* Called By:    
* Input:        CurBuf      要查找的命令字串
*               CmdID       用于存放返回的命令ID号的地址
*               err         错误码返回地址
* Return:       ERR_CLI_SEARCHOK    命令搜索成功
*               ERR_CLI_SEARCHERR   命令搜索失败
*******************************************************************************/
int SearchCmd(char *CurBuf, uint8 *CmdID, uint8 *err)
{
    uint8 i, len, index, index2, offset, cnt = 0;
    CmdInfo *CurCmdDB = NULL;
    
    /* 计算字符串长度,以0或空格键作为结尾。以此计算出输入的主命令长度 */
    for(len = 0; *(CurBuf + len) != '\0'; len++)
    {
        if(*(CurBuf + len) == SPACE) break;
    }
    
    /* 获取当前命令状态,用以决定查找命令的数据库及库中的命令数量 */
    switch(GetCmdStatus())
    {
        case USER:
            CurCmdDB = CmdDBUser;
            break;
            
        case PRIVATE:
            CurCmdDB = CmdDBPrivate;
            break;
            
        case CONFIG:
            CurCmdDB = CmdDBConfig;
            break;
            
        case CONFIG_LINE:
            CurCmdDB = CmdDBLine;
            break;
    }
    
    for(cnt = 0; CurCmdDB[cnt].name[0] != NULL;cnt++);
    
    /* 当有命令字符串输入时,在对应命令数据库中进行查找 */
    for(index = 0; (index < cnt) && (len > 0); index++)
    {
        for(i = 0, offset = 0; i < len; i++)
        {
            /* 输入的命令与数据库中的命令串进行逐字符比较 */
            if(CurBuf[i] == CurCmdDB[index].name[i])
            {
                offset++;
            }
            else
            {
                break;
            }
        }
        
        /* 如果输入的命令字符串在命令数据库中能够全部匹配,则查找成功 */
        if(i == len && offset == len)
        {
            /* 查找是否有相同索引的命令 */
            i = 0;
            offset = 0;
            
            for(index2 = index + 1; (index2 < cnt) && (len > 0); index2++)
            {
                for(i = 0, offset = 0; i < len; i++)
                {
                    if(CurBuf[i] == CurCmdDB[index2].name[i])
                    {
                        offset++;
                    }
                    else
                    {
                        break;
                    }
                }
                
                /* 如果输入的命令字符串在命令数据库中后面部分能够全部匹配,
                    则命令索引在该数据库中不唯一 */
                if(i == len && offset == len)
                {
                    return ERR_CLI_CMD_NOT_UNIQUE;
                }
            }
            
            *CmdID = index;
            
            return ERR_CLI_SEARCHOK;
        }
    }
    
    return ERR_CLI_SEARCHERR;
}

/*******************************************************************************
* Function:     SearchPara()
* Description:  
* Calls:        
* Called By:    
* Input:        
* Return:       
*******************************************************************************/
int SearchPara(char *CurBuf, uint8 ParaNum, CmdInfo *CurDB, uint8 *ParaID
                , uint8 *err)
{
    uint8 i, len, index, index2, spcnt = 0, offset = 0, cnt;
    
    while(1)
    {
        /* 计算所要搜索参数在整个输入命令中的偏移量 */
        if(*(CurBuf + offset) == SPACE)
        {
            /* 消除连续空格影响 */
            if(*(CurBuf + offset + 1) == SPACE)
            {
                offset++;
                continue;
            }
            else
            {
                offset++;
                spcnt++;
                if(spcnt == ParaNum)
                {
                    break;
                }
            }
        }
        else
        {
            offset++;
            
            /* 如果已搜索到输入命令的末尾,则结束搜索 */
            if(offset >= strlen(CurBuf))
            {
                return ERR_CLI_SEARCH_PARA_ERR;
            }
        }
    }
    
    /* 计算参数字符串长度,以0或空格键作为结尾 */
    for(len = 0; *(CurBuf + offset + len) != '\0'; len++)
    {
        if(*(CurBuf + offset + len) == SPACE) break;
    }
    
    for(cnt = 0; CurDB[cnt].name[0] != NULL;cnt++);
    
    /* 当有命令字符串输入时,在对应命令数据库中进行查找 */
    for(index = 0; (index < cnt) && (len > 0); index++)
    {
        for(i = 0, spcnt = 0; i < len; i++)
        {
            /* 输入的命令与数据库中的命令串进行逐字符比较 */
            if(CurBuf[i + offset] == CurDB[index].name[i])
            {
                spcnt++;
            }
            else
            {
                break;
            }
        }
        
        /* 如果输入的命令字符串在命令数据库中能够全部匹配,则查找成功 */
        if(i == len && spcnt == len)
        {
            /* 查找是否有相同索引的命令 */
            i = 0;
            spcnt = 0;
            
            for(index2 = index + 1; (index2 < cnt) && (len > 0); index2++)
            {
                for(i = 0, spcnt = 0; i < len; i++)
                {
                    if(CurBuf[i] == CurDB[index2].name[i])
                    {
                        spcnt++;
                    }
                    else
                    {
                        break;
                    }
                }
                
                /* 如果输入的命令字符串在命令数据库中后面部分能够全部匹配,
                    则命令索引在该数据库中不唯一 */
                if(i == len && spcnt == len)
                {
                    return ERR_CLI_CMD_NOT_UNIQUE;
                }
            }

            *ParaID = index;
            
            return ERR_CLI_PARA_OK;
        }
    }
    
    return ERR_CLI_SEARCH_PARA_ERR;
}

/*******************************************************************************
* Function:     CmdRun()
* Description:  执行当前命令模式下CmdID对应的命令函数
* Calls:        GetCmdStatus()
* Called By:    TaskCLI()
* Input:        CmdID   命令在命令库中的编号
*******************************************************************************/
void CmdRun(uint8 CmdID)
{
    switch(GetCmdStatus())  // 建立一个状态类,
    {
        case USER:
            CmdDBUser[CmdID].func();
            break;
            
        case PRIVATE:
            CmdDBPrivate[CmdID].func();
            break;
            
        case CONFIG:
            CmdDBConfig[CmdID].func();
            break;
            
        case CONFIG_LINE:
            CmdDBLine[CmdID].func();
            break;
            
        default:
            break;
    }
}

/*******************************************************************************
* Function:     CmdErr()
* Description:  命令错误提示
* Calls:        U0Send()/strlen()/PrintBuf()/CurPrompt()
* Called By:    TaskCLI()/CmdShow()/CmdConf()/CmdHostname()
*******************************************************************************/
void CmdErr(void)
{
    SendStr(BLANKROW);
    PrintBuf();
    SendStr(CMD_ERR_INVALID);
    
    CurPrompt();
    PrintBuf();
}

/*******************************************************************************
* Function:     CmdNotUnique()
* Description:  命令索引不唯一
* Calls:        SendStr()/PrintBuf()/CurPrompt()
* Called By:    TaskCLI()
*******************************************************************************/
void CmdNotUnique(void)
{
    SendStr(BLANKROW);
    PrintBuf();
    SendStr(CMD_ERR_NOT_UNIQUE);
    
    CurPrompt();
    PrintBuf();
}

/*******************************************************************************
* Function:     CmdIncomplate()
* Description:  命令错误提示
* Calls:        U0Send()/strlen()/PrintBuf()/CurPrompt()
* Called By:    
*******************************************************************************/
void CmdIncomplate(void)
{
    SendStr(BLANKROW);
    PrintBuf();
    SendStr(CMD_ERR_INCOMPLETE);
    
    CurPrompt();
    PrintBuf();
}

/*******************************************************************************
* Function:     CLIInit()
* Description:  Command Line Interface Init.
* Calls:        Init_Timer1()
* Called By:    TaskCLI()
*******************************************************************************/
void CLIInit(void)
{
    PINSEL0 |= UART0_RXD;

	/* 初始化EXEC超时定时器 */
	Init_Timer1(EXECTO / 60, EXECTO % 60);
}

/*******************************************************************************
* Function:     RecInHisBuf()
* Description:  Save the history command in HISTORY-COMMAND-BUFFER.
* Calls:        
* Called By:    TaskCLI()
*******************************************************************************/
void RecInHisBuf(char *CurCmdBuf)
{
    uint8 i;
    
    for(i = 0; *(CurCmdBuf + i) != 0; i++)
    {
        CmdHisBuf[CmdHisBufUsage][i] = *(CurCmdBuf + i);
    }
    
    if(CmdHisBufUsage == MAX_HIS_BUF)
    {
        CmdHisBufUsage = 0;
        
        if(CurCmdHisBuf == MAX_HIS_BUF)
        {
            CurCmdHisBuf = 0;
        }
        
        return;
    }
    
    CmdHisBufUsage++;
    CurCmdHisBuf++;
    
    return;
}

/*******************************************************************************
* Function:     TaskCLI()
* Description:  Task of Command Line Interface
* Calls:        CLIInit()/OSSemCreate()/GetCmd()/SearchCmd()/CmdRun()/CmdErr()
* Called By:    main()
*******************************************************************************/
void TaskCLI(void *pdata)
{
    uint8 err, CmdID;
    char CurCmdBuf[256];
    
    CLIInit();

    sem_cmd = OSSemCreate(0);

    while(1)
    {
        OSSemPend(sem_cmd, 0, &err);
        
        GetCmd(CurCmdBuf);
        RecInHisBuf(CurCmdBuf);
        
        switch(SearchCmd(CurCmdBuf, &CmdID, &err))
        {
            case ERR_CLI_SEARCHOK:
                CmdRun(CmdID);
                break;
                
            case ERR_CLI_SEARCHERR:
                CmdErr();
                break;
                
            case ERR_CLI_CMD_NOT_UNIQUE:
                CmdNotUnique();
                break;
                
            default:
                break;
        }
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?