diff --git a/components/shell/drv_shell.c b/components/shell/drv_shell.c deleted file mode 100644 index 2fa64683..00000000 --- a/components/shell/drv_shell.c +++ /dev/null @@ -1,2095 +0,0 @@ -/** - * @file drv_shell.c - * - * Copyright (c) 2021 Bouffalolab team - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "drv_shell.h" -#include "string.h" -#include "stdio.h" -#include "stdarg.h" - - -#if SHELL_USING_CMD_EXPORT == 1 -/** - * @brief 默认用户 - */ -const char shellCmdDefaultUser[] = SHELL_DEFAULT_USER; -const char shellPasswordDefaultUser[] = SHELL_DEFAULT_USER_PASSWORD; -const char shellDesDefaultUser[] = "default user"; -const ShellCommand shellUserDefault SECTION("shellCommand") = -{ - .attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_USER), - .data.user.name = shellCmdDefaultUser, - .data.user.password = shellPasswordDefaultUser, - .data.user.desc = shellDesDefaultUser -}; -#endif - -#if SHELL_USING_CMD_EXPORT == 1 - #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000) - extern const unsigned int shellCommand$$Base; - extern const unsigned int shellCommand$$Limit; - #elif defined(__ICCARM__) || defined(__ICCRX__) - #pragma section="shellCommand" - #elif defined(__GNUC__) - extern const unsigned int _shell_command_start; - extern const unsigned int _shell_command_end; - #endif -#else - extern const ShellCommand shellCommandList[]; - extern const unsigned short shellCommandCount; -#endif - - -/** - * @brief shell 常量文本索引 - */ -enum -{ - SHELL_TEXT_INFO, /**< shell信息 */ - SHELL_TEXT_CMD_TOO_LONG, /**< 命令过长 */ - SHELL_TEXT_CMD_LIST, /**< 可执行命令列表标题 */ - SHELL_TEXT_VAR_LIST, /**< 变量列表标题 */ - SHELL_TEXT_USER_LIST, /**< 用户列表标题 */ - SHELL_TEXT_KEY_LIST, /**< 按键列表标题 */ - SHELL_TEXT_CMD_NOT_FOUND, /**< 命令未找到 */ - SHELL_TEXT_POINT_CANNOT_MODIFY, /**< 指针变量不允许修改 */ - SHELL_TEXT_VAL_CANNOT_MODIFY, /**< 常量不允许修改 */ - SHELL_TEXT_NOT_VAR, /**< 命令不是变量 */ - SHELL_TEXT_VAR_NOT_FOUND, /**< 变量未找到 */ - SHELL_TEXT_HELP_HEADER, /**< help头 */ - SHELL_TEXT_PASSWORD_HINT, /**< 密码输入提示 */ - SHELL_TEXT_PASSWORD_ERROR, /**< 密码错误 */ - SHELL_TEXT_CLEAR_CONSOLE, /**< 清空控制台 */ - SHELL_TEXT_TYPE_CMD, /**< 命令类型 */ - SHELL_TEXT_TYPE_VAR, /**< 变量类型 */ - SHELL_TEXT_TYPE_USER, /**< 用户类型 */ - SHELL_TEXT_TYPE_KEY, /**< 按键类型 */ - SHELL_TEXT_TYPE_NONE, /**< 非法类型 */ -}; - - -static const char *shellText[] = -{ -#if SHELL_SHOW_INFO == 1 - [SHELL_TEXT_INFO] = - "\r\n" - " ____ __ __ _ _ _ \r\n" - " | _ \\ / _|/ _| | | | | | | \r\n" - " | |_) | ___ _ _| |_| |_ __ _| | ___ | | __ _| |__ \r\n" - " | _ < / _ \\| | | | _| _/ _` | |/ _ \\| |/ _` | '_ \\ \r\n" - " | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |\r\n" - " |____/ \\___/ \\__,_|_| |_| \\__,_|_|\\___/|_|\\__,_|_.__/ \r\n" - "\r\n" - "Build: "__DATE__" "__TIME__"\r\n" - "Version: "SHELL_VERSION"\r\n", -#endif - [SHELL_TEXT_CMD_TOO_LONG] = - "\r\nWarning: Command is too long\r\n", - [SHELL_TEXT_CMD_LIST] = - "\r\nCommand List:\r\n", - [SHELL_TEXT_VAR_LIST] = - "\r\nVar List:\r\n", - [SHELL_TEXT_USER_LIST] = - "\r\nUser List:\r\n", - [SHELL_TEXT_KEY_LIST] = - "\r\nKey List:\r\n", - [SHELL_TEXT_CMD_NOT_FOUND] = - "Command not Found\r\n", - [SHELL_TEXT_POINT_CANNOT_MODIFY] = - "can't set pointer\r\n", - [SHELL_TEXT_VAL_CANNOT_MODIFY] = - "can't set val\r\n", - [SHELL_TEXT_NOT_VAR] = - " is not a var\r\n", - [SHELL_TEXT_VAR_NOT_FOUND] = - "Var not Fount\r\n", - [SHELL_TEXT_HELP_HEADER] = - "command help of ", - [SHELL_TEXT_PASSWORD_HINT] = - "\r\nPlease input password:", - [SHELL_TEXT_PASSWORD_ERROR] = - "\r\npassword error\r\n", - [SHELL_TEXT_CLEAR_CONSOLE] = - "\033[2J\033[1H", - [SHELL_TEXT_TYPE_CMD] = - "CMD ", - [SHELL_TEXT_TYPE_VAR] = - "VAR ", - [SHELL_TEXT_TYPE_USER] = - "USER", - [SHELL_TEXT_TYPE_KEY] = - "KEY ", - [SHELL_TEXT_TYPE_NONE] = - "NONE", -}; - - -/** - * @brief shell对象表 - */ -static Shell *shellList[SHELL_MAX_NUMBER] = {NULL}; - - -static void shellAdd(Shell *shell); -static void shellWriteCommandLine(Shell *shell); -static void shellWriteReturnValue(Shell *shell, int value); -static void shellShowVar(Shell *shell, ShellCommand *command); -static void shellSetUser(Shell *shell, const ShellCommand *user); -ShellCommand* shellSeekCommand(Shell *shell, - const char *cmd, - ShellCommand *base, - unsigned short compareLength); - -/** - * @brief shell 初始化 - * - * @param shell shell对象 - */ -void shellInit(Shell *shell, char *buffer, unsigned short size) -{ - shell->parser.length = 0; - shell->parser.cursor = 0; - shell->history.offset = 0; - shell->history.number = 0; - shell->history.record = 0; - shell->info.user = NULL; - shell->status.isChecked = 1; - - shell->parser.buffer = buffer; - shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1); - for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++) - { - shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1); - } - -#if SHELL_USING_CMD_EXPORT == 1 - #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000) - shell->commandList.base = (ShellCommand *)(&shellCommand$$Base); - shell->commandList.count = ((unsigned int)(&shellCommand$$Limit) - - (unsigned int)(&shellCommand$$Base)) - / sizeof(ShellCommand); - - #elif defined(__ICCARM__) || defined(__ICCRX__) - shell->commandList.base = (ShellCommand *)(__section_begin("shellCommand")); - shell->commandList.count = ((unsigned int)(__section_end("shellCommand")) - - (unsigned int)(__section_begin("shellCommand"))) - / sizeof(ShellCommand); - #elif defined(__GNUC__) - shell->commandList.base = (ShellCommand *)(&_shell_command_start); - shell->commandList.count = ((unsigned int)(&_shell_command_end) - - (unsigned int)(&_shell_command_start)) - / sizeof(ShellCommand); - #else - #error not supported compiler, please use command table mode - #endif -#else - shell->commandList.base = (ShellCommand *)shellCommandList; - shell->commandList.count = shellCommandCount; -#endif - - shellAdd(shell); - - shellSetUser(shell, shellSeekCommand(shell, - SHELL_DEFAULT_USER, - shell->commandList.base, - 0)); - shellWriteCommandLine(shell); -} - - -/** - * @brief 添加shell - * - * @param shell shell对象 - */ -static void shellAdd(Shell *shell) -{ - for (short i = 0; i < SHELL_MAX_NUMBER; i++) - { - if (shellList[i] == NULL) - { - shellList[i] = shell; - return; - } - } -} - - -/** - * @brief 获取当前活动shell - * - * @return Shell* 当前活动shell对象 - */ -Shell* shellGetCurrent(void) -{ - for (short i = 0; i < SHELL_MAX_NUMBER; i++) - { - if (shellList[i] && shellList[i]->status.isActive) - { - return shellList[i]; - } - } - return NULL; -} - - -/** - * @brief shell写字符 - * - * @param shell shell对象 - * @param data 字符数据 - */ -static void shellWriteByte(Shell *shell, const char data) -{ - shell->write(data); -} - - -/** - * @brief shell 写字符串 - * - * @param shell shell对象 - * @param string 字符串数据 - * - * @return unsigned short 写入字符的数量 - */ -unsigned short shellWriteString(Shell *shell, const char *string) -{ - unsigned short count = 0; - SHELL_ASSERT(shell->write, return 0); - while(*string) - { - shell->write(*string ++); - count ++; - } - return count; -} - - -/** - * @brief shell 写命令描述字符串 - * - * @param shell shell对象 - * @param string 字符串数据 - * - * @return unsigned short 写入字符的数量 - */ -static unsigned short shellWriteCommandDesc(Shell *shell, const char *string) -{ - unsigned short count = 0; - SHELL_ASSERT(shell->write, return 0); - while(*string - && *string != '\r' - && *string != '\n' - && count < 36) - { - shell->write(*string ++); - count ++; - if (count >= 36 && *(string + 1)) - { - shell->write('.'); - shell->write('.'); - shell->write('.'); - } - } - return count; -} - - -/** - * @brief shell写命令提示符 - * - * @param shell shell对象 - * - */ -static void shellWriteCommandLine(Shell *shell) -{ - if (shell->status.isChecked) - { - shellWriteString(shell, "\r\n"); - shellWriteString(shell, shell->info.user->data.user.name); - #if SHELL_FS == 1 - char path[SHELL_PRINT_BUFFER]; - shell->getcwd(path, SHELL_PRINT_BUFFER); - shellWriteString(shell, ":/"); - shellWriteString(shell, path); - shellWriteString(shell, "$ "); - #else - shellWriteString(shell, "/$ "); - #endif - } - else - { - shellWriteString(shell, shellText[SHELL_TEXT_PASSWORD_HINT]); - } -} - - -#if SHELL_PRINT_BUFFER > 0 -/** - * @brief shell格式化输出 - * - * @param shell shell对象 - * @param fmt 格式化字符串 - * @param ... 参数 - */ -void shellPrint(Shell *shell, char *fmt, ...) -{ - char buffer[SHELL_PRINT_BUFFER]; - va_list vargs; - - SHELL_ASSERT(shell, return); - - va_start(vargs, fmt); - vsnprintf(buffer, SHELL_PRINT_BUFFER - 1, fmt, vargs); - va_end(vargs); - - shellWriteString(shell, buffer); -} -#endif - - -/** - * @brief shell 检查命令权限 - * - * @param shell shell对象 - * @param command ShellCommand - * - * @return signed char 0 当前用户具有该命令权限 - * @return signec char -1 当前用户不具有该命令权限 - */ -signed char shellCheckPermission(Shell *shell, ShellCommand *command) -{ - return ((!command->attr.attrs.permission - || command->attr.attrs.type == SHELL_TYPE_USER - || (command->attr.attrs.permission - & shell->info.user->attr.attrs.permission)) - && (shell->status.isChecked - || command->attr.attrs.enableUnchecked)) - ? 0 : -1; -} - - -/** - * @brief int转16进制字符串 - * - * @param value 数值 - * @param buffer 缓冲 - * - * @return signed char 转换后有效数据长度 - */ -signed char shellToHex(unsigned int value, char *buffer) -{ - char byte; - unsigned char i = 8; - buffer[8] = 0; - while (value) - { - byte = value & 0x0000000F; - buffer[--i] = (byte > 9) ? (byte + 87) : (byte + 48); - value >>= 4; - } - return 8 - i; -} - - -/** -* @brief int转10进制字符串 - * - * @param value 数值 - * @param buffer 缓冲 - * - * @return signed char 转换后有效数据长度 - */ -signed char shellToDec(int value, char *buffer) -{ - unsigned char i = 11; - int v = value; - if (value < 0) - { - v = -value; - } - buffer[11] = 0; - while (v) - { - buffer[--i] = v % 10 + 48; - v /= 10; - } - if (value < 0) - { - buffer[--i] = '-'; - } - if (value == 0) { - buffer[--i] = '0'; - } - return 11 - i; -} - - -/** - * @brief shell字符串复制 - * - * @param dest 目标字符串 - * @param src 源字符串 - * @return unsigned short 字符串长度 - */ -static unsigned short shellStringCopy(char *dest, char* src) -{ - unsigned short count = 0; - while (*(src + count)) - { - *(dest + count) = *(src + count); - count++; - } - *(dest + count) = 0; - return count; -} - - -/** - * @brief shell字符串比较 - * - * @param dest 目标字符串 - * @param src 源字符串 - * @return unsigned short 匹配长度 - */ -static unsigned short shellStringCompare(char* dest, char *src) -{ - unsigned short match = 0; - unsigned short i = 0; - - while (*(dest +i) && *(src + i)) - { - if (*(dest + i) != *(src +i)) - { - break; - } - match ++; - i++; - } - return match; -} - - -/** - * @brief shell获取命令名 - * - * @param command 命令 - * @return const char* 命令名 - */ -static const char* shellGetCommandName(ShellCommand *command) -{ - static char buffer[9]; - for (unsigned char i = 0; i < 9; i++) - { - buffer[i] = '0'; - } - if (command->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) - { - return command->data.cmd.name; - } - else if (command->attr.attrs.type <= SHELL_TYPE_VAL) - { - return command->data.var.name; - } - else if (command->attr.attrs.type <= SHELL_TYPE_USER) - { - return command->data.user.name; - } - else - { - shellToHex(command->data.key.value, buffer); - return buffer; - } -} - - -/** - * @brief shell获取命令描述 - * - * @param command 命令 - * @return const char* 命令描述 - */ -static const char* shellGetCommandDesc(ShellCommand *command) -{ - if (command->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) - { - return command->data.cmd.desc; - } - else if (command->attr.attrs.type <= SHELL_TYPE_VAL) - { - return command->data.var.desc; - } - else if (command->attr.attrs.type <= SHELL_TYPE_USER) - { - return command->data.user.desc; - } - else - { - return command->data.key.desc; - } -} - -/** - * @brief shell 列出命令条目 - * - * @param shell shell对象 - * @param item 命令条目 - */ -void shellListItem(Shell *shell, ShellCommand *item) -{ - short spaceLength; - - spaceLength = 22 - shellWriteString(shell, shellGetCommandName(item)); - spaceLength = (spaceLength > 0) ? spaceLength : 4; - do { - shellWriteByte(shell, ' '); - } while (--spaceLength); - if (item->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) - { - shellWriteString(shell, shellText[SHELL_TEXT_TYPE_CMD]); - } - else if (item->attr.attrs.type <= SHELL_TYPE_VAL) - { - shellWriteString(shell, shellText[SHELL_TEXT_TYPE_VAR]); - } - else if (item->attr.attrs.type <= SHELL_TYPE_USER) - { - shellWriteString(shell, shellText[SHELL_TEXT_TYPE_USER]); - } - else if (item->attr.attrs.type <= SHELL_TYPE_KEY) - { - shellWriteString(shell, shellText[SHELL_TEXT_TYPE_KEY]); - } - else - { - shellWriteString(shell, shellText[SHELL_TEXT_TYPE_NONE]); - } -#if SHELL_HELP_SHOW_PERMISSION == 1 - shellWriteString(shell, " "); - for (signed char i = 7; i >= 0; i--) - { - shellWriteByte(shell, item->attr.attrs.permission & (1 << i) ? 'x' : '-'); - } -#endif - shellWriteString(shell, " "); - shellWriteCommandDesc(shell, shellGetCommandDesc(item)); - shellWriteString(shell, "\r\n"); -} - - -/** - * @brief shell列出可执行命令 - * - * @param shell shell对象 - */ -void shellListCommand(Shell *shell) -{ - ShellCommand *base = (ShellCommand *)shell->commandList.base; - shellWriteString(shell, shellText[SHELL_TEXT_CMD_LIST]); - for (short i = 0; i < shell->commandList.count; i++) - { - if (base[i].attr.attrs.type <= SHELL_TYPE_CMD_FUNC - && shellCheckPermission(shell, &base[i]) == 0) - { - shellListItem(shell, &base[i]); - } - } -} - - -/** - * @brief shell列出变量 - * - * @param shell shell对象 - */ -void shellListVar(Shell *shell) -{ - ShellCommand *base = (ShellCommand *)shell->commandList.base; - shellWriteString(shell, shellText[SHELL_TEXT_VAR_LIST]); - for (short i = 0; i < shell->commandList.count; i++) - { - if (base[i].attr.attrs.type > SHELL_TYPE_CMD_FUNC - && base[i].attr.attrs.type <= SHELL_TYPE_VAL - && shellCheckPermission(shell, &base[i]) == 0) - { - shellListItem(shell, &base[i]); - } - } -} - - -/** - * @brief shell列出用户 - * - * @param shell shell对象 - */ -void shellListUser(Shell *shell) -{ - ShellCommand *base = (ShellCommand *)shell->commandList.base; - shellWriteString(shell, shellText[SHELL_TEXT_USER_LIST]); - for (short i = 0; i < shell->commandList.count; i++) - { - if (base[i].attr.attrs.type > SHELL_TYPE_VAL - && base[i].attr.attrs.type <= SHELL_TYPE_USER - && shellCheckPermission(shell, &base[i]) == 0) - { - shellListItem(shell, &base[i]); - } - } -} - - -/** - * @brief shell列出按键 - * - * @param shell shell对象 - */ -void shellListKey(Shell *shell) -{ - ShellCommand *base = (ShellCommand *)shell->commandList.base; - shellWriteString(shell, shellText[SHELL_TEXT_KEY_LIST]); - for (short i = 0; i < shell->commandList.count; i++) - { - if (base[i].attr.attrs.type > SHELL_TYPE_USER - && base[i].attr.attrs.type <= SHELL_TYPE_KEY - && shellCheckPermission(shell, &base[i]) == 0) - { - shellListItem(shell, &base[i]); - } - } -} - - -/** - * @brief shell列出所有命令 - * - * @param shell shell对象 - */ -void shellListAll(Shell *shell) -{ -#if SHELL_HELP_LIST_USER == 1 - shellListUser(shell); -#endif - shellListCommand(shell); -#if SHELL_HELP_LIST_VAR == 1 - shellListVar(shell); -#endif -#if SHELL_HELP_LIST_KEY == 1 - shellListKey(shell); -#endif -} - - -/** - * @brief shell删除命令行数据 - * - * @param shell shell对象 - * @param length 删除长度 - */ -void shellDeleteCommandLine(Shell *shell, unsigned char length) -{ - while (length--) - { - shellWriteString(shell, "\b \b"); - } -} - - -/** - * @brief shell 清空命令行输入 - * - * @param shell shell对象 - */ -void shellClearCommandLine(Shell *shell) -{ - for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) - { - shellWriteByte(shell, ' '); - } - shellDeleteCommandLine(shell, shell->parser.length); -} - - -/** - * @brief shell插入一个字符到光标位置 - * - * @param shell shell对象 - * @param data 字符数据 - */ -void shellInsertByte(Shell *shell, char data) -{ - /* 判断输入数据是否过长 */ - if (shell->parser.length >= shell->parser.bufferSize - 1) - { - shellWriteString(shell, shellText[SHELL_TEXT_CMD_TOO_LONG]); - shellWriteCommandLine(shell); - shellWriteString(shell, shell->parser.buffer); - return; - } - - /* 插入数据 */ - if (shell->parser.cursor == shell->parser.length) - { - shell->parser.buffer[shell->parser.length++] = data; - shell->parser.buffer[shell->parser.length] = 0; - shell->parser.cursor++; - shellWriteByte(shell, data); - } - else if (shell->parser.cursor < shell->parser.length) - { - for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) - { - shell->parser.buffer[shell->parser.cursor + i] = - shell->parser.buffer[shell->parser.cursor + i - 1]; - } - shell->parser.buffer[shell->parser.cursor++] = data; - shell->parser.buffer[++shell->parser.length] = 0; - for (short i = shell->parser.cursor - 1; i < shell->parser.length; i++) - { - shellWriteByte(shell, shell->parser.buffer[i]); - } - for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) - { - shellWriteByte(shell, '\b'); - } - } -} - - -/** - * @brief shell 删除字节 - * - * @param shell shell对象 - * @param direction 删除方向 {@code 1}删除光标前字符 {@code -1}删除光标处字符 - */ -void shellDeleteByte(Shell *shell, signed char direction) -{ - char offset = (direction == -1) ? 1 : 0; - - if ((shell->parser.cursor == 0 && direction == 1) - || (shell->parser.cursor == shell->parser.length && direction == -1)) - { - return; - } - if (shell->parser.cursor == shell->parser.length && direction == 1) - { - shell->parser.cursor--; - shell->parser.length--; - shell->parser.buffer[shell->parser.length] = 0; - shellDeleteCommandLine(shell, 1); - } - else - { - for (short i = offset; i < shell->parser.length - shell->parser.cursor; i++) - { - shell->parser.buffer[shell->parser.cursor + i - 1] = - shell->parser.buffer[shell->parser.cursor + i]; - } - shell->parser.length--; - if (!offset) - { - shell->parser.cursor--; - shellWriteByte(shell, '\b'); - } - shell->parser.buffer[shell->parser.length] = 0; - for (short i = shell->parser.cursor; i < shell->parser.length; i++) - { - shellWriteByte(shell, shell->parser.buffer[i]); - } - shellWriteByte(shell, ' '); - for (short i = shell->parser.length - shell->parser.cursor + 1; i > 0; i--) - { - shellWriteByte(shell, '\b'); - } - } -} - - -/** - * @brief shell 解析参数 - * - * @param shell shell对象 - */ -static void shellParserParam(Shell *shell) -{ - unsigned char quotes = 0; - unsigned char record = 1; - - shell->parser.paramCount = 0; - for (unsigned short i = 0; i < shell->parser.length; i++) - { - if (quotes != 0 - || (shell->parser.buffer[i] != ' ' - && shell->parser.buffer[i] != 0)) - { - if (shell->parser.buffer[i] == '\"') - { - quotes = quotes ? 0 : 1; - } - if (record == 1) - { - shell->parser.param[shell->parser.paramCount ++] = - &(shell->parser.buffer[i]); - record = 0; - } - if (shell->parser.buffer[i] == '\\' - && shell->parser.buffer[i + 1] != 0) - { - i++; - } - } - else - { - shell->parser.buffer[i] = 0; - record = 1; - } - } -} - - -/** - * @brief shell去除字符串参数头尾的双引号 - * - * @param shell shell对象 - */ -static void shellRemoveParamQuotes(Shell *shell) -{ - unsigned short paramLength; - for (unsigned short i = 0; i < shell->parser.paramCount; i++) - { - if (shell->parser.param[i][0] == '\"') - { - shell->parser.param[i][0] = 0; - shell->parser.param[i] = &shell->parser.param[i][1]; - } - paramLength = strlen(shell->parser.param[i]); - if (shell->parser.param[i][paramLength - 1] == '\"') - { - shell->parser.param[i][paramLength - 1] = 0; - } - } -} - - -/** - * @brief shell匹配命令 - * - * @param shell shell对象 - * @param cmd 命令 - * @param base 匹配命令表基址 - * @param compareLength 匹配字符串长度 - * @return ShellCommand* 匹配到的命令 - */ -ShellCommand* shellSeekCommand(Shell *shell, - const char *cmd, - ShellCommand *base, - unsigned short compareLength) -{ - const char *name; - unsigned short count = shell->commandList.count - - ((int)base - (int)shell->commandList.base) / sizeof(ShellCommand); - for (unsigned short i = 0; i < count; i++) - { - if (base[i].attr.attrs.type == SHELL_TYPE_KEY - || shellCheckPermission(shell, &base[i]) != 0) - { - continue; - } - name = shellGetCommandName(&base[i]); - if (!compareLength) - { - if (strcmp(cmd, name) == 0) - { - return &base[i]; - } - } - else - { - if (strncmp(cmd, name, compareLength) == 0) - { - return &base[i]; - } - } - } - return NULL; -} - - -/** - * @brief shell 获取变量值 - * - * @param shell shell对象 - * @param command 命令 - * @return int 变量值 - */ -int shellGetVarValue(Shell *shell, ShellCommand *command) -{ - int value = 0; - switch (command->attr.attrs.type) - { - case SHELL_TYPE_VAR_INT: - value = *((int *)(command->data.var.value)); - break; - case SHELL_TYPE_VAR_SHORT: - value = *((short *)(command->data.var.value)); - break; - case SHELL_TYPE_VAR_CHAR: - value = *((char *)(command->data.var.value)); - break; - case SHELL_TYPE_VAR_POINT: - case SHELL_TYPE_VAL: - value = (int)(command->data.var.value); - break; - default: - break; - } - return value; -} - - -/** - * @brief shell设置变量值 - * - * @param shell shell对象 - * @param command 命令 - * @param value 值 - */ -void shellSetVarValue(Shell *shell, ShellCommand *command, int value) -{ - switch (command->attr.attrs.type) - { - case SHELL_TYPE_VAR_INT: - *((int *)(command->data.var.value)) = value; - break; - case SHELL_TYPE_VAR_SHORT: - *((short *)(command->data.var.value)) = value; - break; - case SHELL_TYPE_VAR_CHAR: - *((char *)(command->data.var.value)) = value; - break; - case SHELL_TYPE_VAR_POINT: - shellWriteString(shell, shellText[SHELL_TEXT_POINT_CANNOT_MODIFY]); - break; - case SHELL_TYPE_VAL: - shellWriteString(shell, shellText[SHELL_TEXT_VAL_CANNOT_MODIFY]); - break; - default: - break; - } - shellShowVar(shell, command); -} - - -/** - * @brief shell变量输出 - * - * @param shell shell对象 - * @param command 命令 - */ -static void shellShowVar(Shell *shell, ShellCommand *command) -{ - char buffer[12] = "00000000000"; - int value = shellGetVarValue(shell, command); - shellWriteString(shell, command->data.var.name); - shellWriteString(shell, " = "); - shellWriteString(shell, &buffer[11 - shellToDec(value, buffer)]); - shellWriteString(shell, ", 0x"); - for (short i = 0; i < 11; i++) - { - buffer[i] = '0'; - } - shellToHex(value, buffer); - shellWriteString(shell, buffer); - shellWriteString(shell, "\r\n"); -} - - -/** - * @brief shell设置变量 - * - * @param name 变量名 - * @param value 变量值 - * @return int 返回变量值 - */ -int shellSetVar(char *name, int value) -{ - Shell *shell = shellGetCurrent(); - if (shell == NULL) - { - return 0; - } - ShellCommand *command = shellSeekCommand(shell, - name, - shell->commandList.base, - 0); - if (!command) - { - shellWriteString(shell, shellText[SHELL_TEXT_VAR_NOT_FOUND]); - return 0; - } - if (command->attr.attrs.type < SHELL_TYPE_VAR_INT - || command->attr.attrs.type > SHELL_TYPE_VAL) - { - shellWriteString(shell, name); - shellWriteString(shell, shellText[SHELL_TEXT_NOT_VAR]); - return 0; - } - shellSetVarValue(shell, command, value); - return shellGetVarValue(shell, command); -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -setVar, shellSetVar, set var); - - -/** - * @brief shell运行命令 - * - * @param shell shell对象 - * @param command 命令 - */ -static void shellRunCommand(Shell *shell, ShellCommand *command) -{ - int returnValue; - shell->status.isActive = 1; - if (command->attr.attrs.type == SHELL_TYPE_CMD_MAIN) - { - shellRemoveParamQuotes(shell); - returnValue = command->data.cmd.function(shell->parser.paramCount, - shell->parser.param); - if (!command->attr.attrs.disableReturn) - { - shellWriteReturnValue(shell, returnValue); - } - } - else if (command->attr.attrs.type == SHELL_TYPE_CMD_FUNC) - { - returnValue = shellExtRun(shell, - command, - shell->parser.paramCount, - shell->parser.param); - if (!command->attr.attrs.disableReturn) - { - shellWriteReturnValue(shell, returnValue); - } - } - else if (command->attr.attrs.type >= SHELL_TYPE_VAR_INT - && command->attr.attrs.type <= SHELL_TYPE_VAL) - { - shellShowVar(shell, command); - } - else if (command->attr.attrs.type == SHELL_TYPE_USER) - { - shellSetUser(shell, command); - } - shell->status.isActive = 0; -} - - -/** - * @brief shell校验密码 - * - * @param shell shell对象 - */ -static void shellCheckPassword(Shell *shell) -{ - if (strcmp(shell->parser.buffer, shell->info.user->data.user.password) == 0) - { - shell->status.isChecked = 1; - #if SHELL_SHOW_INFO == 1 - shellWriteString(shell, shellText[SHELL_TEXT_INFO]); - #endif - } - else - { - shellWriteString(shell, shellText[SHELL_TEXT_PASSWORD_ERROR]); - } - shell->parser.length = 0; - shell->parser.cursor = 0; -} - - -/** - * @brief shell设置用户 - * - * @param shell shell对象 - * @param user 用户 - */ -static void shellSetUser(Shell *shell, const ShellCommand *user) -{ - shell->info.user = user; - shell->status.isChecked = - ((user->data.user.password && strlen(user->data.user.password) != 0) - && (shell->parser.paramCount == 1 - || strcmp(user->data.user.password, shell->parser.param[1]) != 0)) - ? 0 : 1; - -#if SHELL_CLS_WHEN_LOGIN == 1 - shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_CONSOLE]); -#endif -#if SHELL_SHOW_INFO == 1 - if (shell->status.isChecked) - { - shellWriteString(shell, shellText[SHELL_TEXT_INFO]); - } -#endif -} - - -/** - * @brief shell写返回值 - * - * @param shell shell对象 - * @param value 返回值 - */ -static void shellWriteReturnValue(Shell *shell, int value) -{ - char buffer[12] = "00000000000"; - shellWriteString(shell, "Return: "); - shellWriteString(shell, &buffer[11 - shellToDec(value, buffer)]); - shellWriteString(shell, ", 0x"); - for (short i = 0; i < 11; i++) - { - buffer[i] = '0'; - } - shellToHex(value, buffer); - shellWriteString(shell, buffer); - shellWriteString(shell, "\r\n"); -} - - -/** - * @brief shell历史记录添加 - * - * @param shell shell对象 - */ -static void shellHistoryAdd(Shell *shell) -{ - shell->history.offset = 0; - if (shell->history.number > 0 - && strcmp(shell->history.item[(shell->history.record == 0 ? - SHELL_HISTORY_MAX_NUMBER : shell->history.record) - 1], - shell->parser.buffer) == 0) - { - return; - } - if (shellStringCopy(shell->history.item[shell->history.record], - shell->parser.buffer) != 0) - { - shell->history.record++; - } - if (++shell->history.number > SHELL_HISTORY_MAX_NUMBER) - { - shell->history.number = SHELL_HISTORY_MAX_NUMBER; - } - if (shell->history.record >= SHELL_HISTORY_MAX_NUMBER) - { - shell->history.record = 0; - } -} - - -/** - * @brief shell历史记录查找 - * - * @param shell shell对象 - * @param dir 方向 {@code <0}往上查找 {@code >0}往下查找 - */ -static void shellHistory(Shell *shell, signed char dir) -{ - if (dir > 0) - { - if (shell->history.offset-- <= - -((shell->history.number > shell->history.record) ? - shell->history.number : shell->history.record)) - { - shell->history.offset = -((shell->history.number > shell->history.record) - ? shell->history.number : shell->history.record); - } - } - else if (dir < 0) - { - if (++shell->history.offset > 0) - { - shell->history.offset = 0; - return; - } - } - else - { - return; - } - shellClearCommandLine(shell); - if (shell->history.offset == 0) - { - shell->parser.cursor = shell->parser.length = 0; - } - else - { - if ((shell->parser.length = shellStringCopy(shell->parser.buffer, - shell->history.item[(shell->history.record + SHELL_HISTORY_MAX_NUMBER - + shell->history.offset) % SHELL_HISTORY_MAX_NUMBER])) == 0) - { - return; - } - shell->parser.cursor = shell->parser.length; - shellWriteString(shell, shell->parser.buffer); - } - -} - - -/** - * @brief shell 常规输入 - * - * @param shell shell 对象 - * @param data 输入字符 - */ -void shellNormalInput(Shell *shell, char data) -{ - shell->status.tabFlag = 0; - shellInsertByte(shell, data); -} - - -/** - * @brief shell上方向键输入 - * - * @param shell shell对象 - */ -void shellUp(Shell *shell) -{ - shellHistory(shell, 1); -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4100, shellUp, up); - - -/** - * @brief shell下方向键输入 - * - * @param shell shell对象 - */ -void shellDown(Shell *shell) -{ - shellHistory(shell, -1); -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down); - - -/** - * @brief shell右方向键输入 - * - * @param shell shell对象 - */ -void shellRight(Shell *shell) -{ - if (shell->parser.cursor < shell->parser.length) - { - shellWriteByte(shell, shell->parser.buffer[shell->parser.cursor++]); - } -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x1B5B4300, shellRight, right); - - -/** - * @brief shell左方向键输入 - * - * @param shell shell对象 - */ -void shellLeft(Shell *shell) -{ - if (shell->parser.cursor > 0) - { - shellWriteByte(shell, '\b'); - shell->parser.cursor--; - } -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x1B5B4400, shellLeft, left); - - -/** - * @brief shell Tab按键处理 - * - * @param shell shell对象 - */ -void shellTab(Shell *shell) -{ - unsigned short maxMatch = shell->parser.bufferSize; - unsigned short lastMatchIndex = 0; - unsigned short matchNum = 0; - unsigned short length; - - if (shell->parser.length == 0) - { - shellListAll(shell); - shellWriteCommandLine(shell); - } - else if (shell->parser.length > 0) - { - shell->parser.buffer[shell->parser.length] = 0; - ShellCommand *base = (ShellCommand *)shell->commandList.base; - for (short i = 0; i < shell->commandList.count; i++) - { - if (shellCheckPermission(shell, &base[i]) == 0 - && shellStringCompare(shell->parser.buffer, - (char *)shellGetCommandName(&base[i])) - == shell->parser.length) - { - if (matchNum != 0) - { - if (matchNum == 1) - { - shellWriteString(shell, "\r\n"); - } - shellListItem(shell, &base[lastMatchIndex]); - length = - shellStringCompare((char *)shellGetCommandName(&base[lastMatchIndex]), - (char *)shellGetCommandName(&base[i])); - maxMatch = (maxMatch > length) ? length : maxMatch; - } - lastMatchIndex = i; - matchNum++; - } - } - if (matchNum == 0) - { - return; - } - if (matchNum == 1) - { - shellClearCommandLine(shell); - } - if (matchNum != 0) - { - shell->parser.length = - shellStringCopy(shell->parser.buffer, - (char *)shellGetCommandName(&base[lastMatchIndex])); - } - if (matchNum > 1) - { - shellListItem(shell, &base[lastMatchIndex]); - shellWriteCommandLine(shell); - shell->parser.length = maxMatch; - } - shell->parser.buffer[shell->parser.length] = 0; - shell->parser.cursor = shell->parser.length; - shellWriteString(shell, shell->parser.buffer); - } - - if (SHELL_GET_TICK()) - { - if (matchNum == 1 - && shell->status.tabFlag - && SHELL_GET_TICK() - shell->info.activeTime < SHELL_DOUBLE_CLICK_TIME) - { - shellClearCommandLine(shell); - for (short i = shell->parser.length; i >= 0; i--) - { - shell->parser.buffer[i + 5] = shell->parser.buffer[i]; - } - shellStringCopy(shell->parser.buffer, "help"); - shell->parser.buffer[4] = ' '; - shell->parser.length += 5; - shell->parser.cursor = shell->parser.length; - shellWriteString(shell, shell->parser.buffer); - } - else - { - shell->status.tabFlag = 1; - } - } -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x09000000, shellTab, tab); - - -/** - * @brief shell 退格 - * - * @param shell shell对象 - */ -void shellBackspace(Shell *shell) -{ - shellDeleteByte(shell, 1); -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x08000000, shellBackspace, backspace); - - -/** - * @brief shell 删除 - * - * @param shell shell对象 - */ -void shellDelete(Shell *shell) -{ - shellDeleteByte(shell, -1); -} -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x7F000000, shellDelete, delete); -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x1B5B337E, shellDelete, delete); - -/** - * @brief shell 回车处理 - * - * @param shell shell对象 - */ -void shellEnter(Shell *shell) -{ - if (shell->parser.length == 0) - { - shellWriteCommandLine(shell); - return; - } - - shell->parser.buffer[shell->parser.length] = 0; - - if (shell->status.isChecked) - { - shellHistoryAdd(shell); - shellParserParam(shell); - shell->parser.length = shell->parser.cursor = 0; - if (shell->parser.paramCount == 0) - { - shellWriteCommandLine(shell); - return; - } - shellWriteString(shell, "\r\n"); - - ShellCommand *command = shellSeekCommand(shell, - shell->parser.param[0], - shell->commandList.base, - 0); - if (command != NULL) - { - shellRunCommand(shell, command); - } - else - { - shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]); - } - } - else - { - shellCheckPassword(shell); - } - shellWriteCommandLine(shell); -} -#if SHELL_ENTER_LF == 1 -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x0A000000, shellEnter, enter); -#endif -#if SHELL_ENTER_CR == 1 -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x0D000000, shellEnter, enter); -#endif -#if SHELL_ENTER_CRLF == 1 -SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, -0x0D0A0000, shellEnter, enter); -#endif - - -/** - * @brief shell help - * - * @param argc 参数个数 - * @param argv 参数 - */ -void shellHelp(int argc, char *argv[]) -{ - Shell *shell = shellGetCurrent(); - SHELL_ASSERT(shell, return); - if (argc == 1) - { - shellListAll(shell); - } - else if (argc > 1) - { - ShellCommand *command = shellSeekCommand(shell, - argv[1], - shell->commandList.base, - 0); - shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]); - shellWriteString(shell, shellGetCommandName(command)); - shellWriteString(shell, "\r\n"); - shellWriteString(shell, shellGetCommandDesc(command)); - shellWriteString(shell, "\r\n"); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, -help, shellHelp, show command info\r\nhelp [cmd]); - -/** - * @brief shell 输入处理 - * - * @param shell shell对象 - * @param data 输入数据 - */ -void shellHandler(Shell *shell, char data) -{ - SHELL_ASSERT(data, return); - -#if SHELL_LOCK_TIMEOUT > 0 - if (shell->info.user->data.user.password - && strlen(shell->info.user->data.user.password) != 0 - && SHELL_GET_TICK()) - { - if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT) - { - shell->status.isChecked = 0; - } - } -#endif - - /* 根据记录的按键键值计算当前字节在按键键值中的偏移 */ - char keyByteOffset = 24; - int keyFilter = 0x00000000; - if ((shell->parser.keyValue & 0x0000FF00) != 0x00000000) - { - keyByteOffset = 0; - keyFilter = 0xFFFFFF00; - } - else if ((shell->parser.keyValue & 0x00FF0000) != 0x00000000) - { - keyByteOffset = 8; - keyFilter = 0xFFFF0000; - } - else if ((shell->parser.keyValue & 0xFF000000) != 0x00000000) - { - keyByteOffset = 16; - keyFilter = 0xFF000000; - } - - /* 遍历ShellCommand列表,尝试进行按键键值匹配 */ - ShellCommand *base = (ShellCommand *)shell->commandList.base; - for (short i = 0; i < shell->commandList.count; i++) - { - /* 判断是否是按键定义并验证权限 */ - if (base[i].attr.attrs.type == SHELL_TYPE_KEY - && shellCheckPermission(shell, &(base[i])) == 0) - { - /* 对输入的字节同按键键值进行匹配 */ - if ((base[i].data.key.value & keyFilter) == shell->parser.keyValue - && (base[i].data.key.value & (0xFF << keyByteOffset)) - == (data << keyByteOffset)) - { - shell->parser.keyValue |= data << keyByteOffset; - data = 0x00; - if (keyByteOffset == 0 - || (base[i].data.key.value & (0xFF << (keyByteOffset - 8))) - == 0x00000000) - { - if (base[i].data.key.function) - { - base[i].data.key.function(shell); - } - shell->parser.keyValue = 0x00000000; - break; - } - } - } - } - - if (data != 0x00) - { - shellNormalInput(shell, data); - } - - if (SHELL_GET_TICK()) - { - shell->info.activeTime = SHELL_GET_TICK(); - } -} - - -/** - * @brief shell 任务 - * - * @param param 参数(shell对象) - * - */ -void shellTask(void *param) -{ - Shell *shell = (Shell *)param; - char data; -#if SHELL_TASK_WHILE == 1 - while(1) - { -#endif - if (shell->read && shell->read(&data) == 0) - { - shellHandler(shell, data); - } -#if SHELL_TASK_WHILE == 1 - } -#endif -} - - -/** - * @brief shell 输出用户列表(shell调用) - */ -void shellUsers(void) -{ - Shell *shell = shellGetCurrent(); - if (shell) - { - shellListUser(shell); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -users, shellUsers, list all user); - - -/** - * @brief shell 输出命令列表(shell调用) - */ -void shellCmds(void) -{ - Shell *shell = shellGetCurrent(); - if (shell) - { - shellListCommand(shell); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -cmds, shellCmds, list all cmd); - - -/** - * @brief shell 输出变量列表(shell调用) - */ -void shellVars(void) -{ - Shell *shell = shellGetCurrent(); - if (shell) - { - shellListVar(shell); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -vars, shellVars, list all var); - - -/** - * @brief shell 输出按键列表(shell调用) - */ -void shellKeys(void) -{ - Shell *shell = shellGetCurrent(); - if (shell) - { - shellListKey(shell); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -keys, shellKeys, list all key); - - -/** - * @brief shell 清空控制台(shell调用) - */ -void shellClear(void) -{ - Shell *shell = shellGetCurrent(); - if (shell) - { - shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_CONSOLE]); - } -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, -clear, shellClear, clear console); - - -#if SHELL_EXEC_UNDEF_FUNC == 1 -/** - * @brief shell执行未定义函数 - * - * @param argc 参数个数 - * @param argv 参数 - * @return int 返回值 - */ -int shellExecute(int argc, char *argv[]) -{ - Shell *shell = shellGetCurrent(); - if (shell && argc >= 2) - { - int (*func)() = (int (*)())shellExtParsePara(shell, argv[1]); - shellPrint(shell, "%08x\r\n", func); - ShellCommand command = { - .attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) - |SHELL_CMD_DISABLE_RETURN, - .data.cmd.function = func, - }; - return shellExtRun(shell, &command, argc - 1, &argv[1]); - } - else - { - shellPrint(shell, "%08x\r\n", shellClear); - } - return 0; -} -SHELL_EXPORT_CMD( -SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, -exec, shellExecute, execute function undefined); -#endif - - -/** - * @brief 判断数字进制 - * - * @param string 参数字符串 - * @return NUM_Type 进制 - */ -static NUM_Type shellExtNumType(char *string) -{ - char *p = string; - NUM_Type type = NUM_TYPE_INT; - - if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X'))) - { - type = NUM_TYPE_HEX; - } - else if ((*p == '0') && ((*(p + 1) == 'b') || (*(p + 1) == 'B'))) - { - type = NUM_TYPE_BIN; - } - else if (*p == '0') - { - type = NUM_TYPE_OCT; - } - - while (*p++) - { - if (*p == '.' && *(p + 1) != 0) - { - type = NUM_TYPE_FLOAT; - break; - } - } - - return type; -} - - -/** - * @brief 字符转数字 - * - * @param code 字符 - * @return char 数字 - */ -static char shellExtToNum(char code) -{ - if ((code >= '0') && (code <= '9')) - { - return code -'0'; - } - else if ((code >= 'a') && (code <= 'f')) - { - return code - 'a' + 10; - } - else if ((code >= 'A') && (code <= 'F')) - { - return code - 'A' + 10; - } - else - { - return 0; - } -} - - -/** - * @brief 解析字符参数 - * - * @param string 字符串参数 - * @return char 解析出的字符 - */ -static char shellExtParseChar(char *string) -{ - char *p = string + 1; - char value = 0; - - if (*p == '\\') - { - switch (*(p + 1)) - { - case 'b': - value = '\b'; - break; - case 'r': - value = '\r'; - break; - case 'n': - value = '\n'; - break; - case 't': - value = '\t'; - break; - case '0': - value = 0; - break; - default: - value = *(p + 1); - break; - } - } - else - { - value = *p; - } - return value; -} - - -/** - * @brief 解析字符串参数 - * - * @param string 字符串参数 - * @return char* 解析出的字符串 - */ -static char* shellExtParseString(char *string) -{ - char *p = string; - unsigned short index = 0; - - if (*string == '\"') - { - p = ++string; - } - - while (*p) - { - if (*p == '\\') - { - *(string + index) = shellExtParseChar(p - 1); - p++; - } - else if (*p == '\"') - { - *(string + index) = 0; - } - else - { - *(string + index) = *p; - } - p++; - index ++; - } - *(string + index) = 0; - return string; -} - - -/** - * @brief 解析数字参数 - * - * @param string 字符串参数 - * @return unsigned int 解析出的数字 - */ -static unsigned int shellExtParseNumber(char *string) -{ - NUM_Type type = NUM_TYPE_INT; - char radix = 10; - char *p = string; - char offset = 0; - signed char sign = 1; - unsigned int valueInt = 0; - float valueFloat = 0.0; - unsigned int devide = 0; - - if (*string == '-') - { - sign = -1; - } - - type = shellExtNumType(string + ((sign == -1) ? 1 : 0)); - - switch ((char)type) - { - case NUM_TYPE_HEX: - radix = 16; - offset = 2; - break; - - case NUM_TYPE_OCT: - radix = 8; - offset = 1; - break; - - case NUM_TYPE_BIN: - radix = 2; - offset = 2; - break; - - default: - break; - } - - p = string + offset + ((sign == -1) ? 1 : 0); - - while (*p) - { - if (*p == '.') - { - devide = 1; - p++; - continue; - } - valueInt = valueInt * radix + shellExtToNum(*p); - devide *= 10; - p++; - } - if (type == NUM_TYPE_FLOAT && devide != 0) - { - valueFloat = (float)valueInt / devide * sign; - return (unsigned int)valueFloat; - } - else - { - return valueInt * sign; - } -} - - -/** - * @brief 解析变量参数 - * - * @param shell shell对象 - * @param var 变量 - * @return unsigned int 变量值 - */ -static unsigned int shellExtParseVar(Shell *shell, char *var) -{ - ShellCommand *command = shellSeekCommand(shell, - var + 1, - shell->commandList.base, - 0); - if (command) - { - return shellGetVarValue(shell, command); - } - else - { - return 0; - } -} - - -/** - * @brief 解析参数 - * - * @param shell shell对象 - * @param string 参数 - * @return unsigned int 解析结果 - */ -unsigned int shellExtParsePara(Shell *shell, char *string) -{ - if (*string == '\'' && *(string + 1)) - { - return (unsigned int)shellExtParseChar(string); - } - else if (*string == '-' || (*string >= '0' && *string <= '9')) - { - return (unsigned int)shellExtParseNumber(string); - } - else if (*string == '$' && *(string + 1)) - { - return shellExtParseVar(shell, string); - } - else if (*string) - { - return (unsigned int)shellExtParseString(string); - } - return 0; -} - - -/** - * @brief 执行命令 - * - * @param shell shell对象 - * @param command 命令 - * @param argc 参数个数 - * @param argv 参数 - * @return int 返回值 - */ -int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]) -{ - unsigned int params[8] = {0}; - int paramNum = command->attr.attrs.paramNum > (argc - 1) ? - command->attr.attrs.paramNum : (argc - 1); - for (int i = 0; i < argc - 1; i++) - { - params[i] = shellExtParsePara(shell, argv[i + 1]); - } - switch (paramNum) - { - case 0: - return command->data.cmd.function(); - // break; - case 1: - return command->data.cmd.function(params[0]); - // break; - case 2: - return command->data.cmd.function(params[0], params[1]); - // break; - case 3: - return command->data.cmd.function(params[0], params[1], - params[2]); - // break; - case 4: - return command->data.cmd.function(params[0], params[1], - params[2], params[3]); - // break; - case 5: - return command->data.cmd.function(params[0], params[1], - params[2], params[3], - params[4]); - // break; - case 6: - return command->data.cmd.function(params[0], params[1], - params[2], params[3], - params[4], params[5]); - // break; - case 7: - return command->data.cmd.function(params[0], params[1], - params[2], params[3], - params[4], params[5], - params[6]); - // break; - default: - return -1; - // break; - } -} - - - diff --git a/components/shell/drv_shell.h b/components/shell/drv_shell.h deleted file mode 100644 index 1e7341ce..00000000 --- a/components/shell/drv_shell.h +++ /dev/null @@ -1,394 +0,0 @@ -/** - * @file shell.h - * @author Letter (NevermindZZT@gmail.com) - * @brief letter shell - * @version 3.0.0 - * @date 2019-12-30 - * - * @Copyright (c) 2020 Letter - * - */ - -#ifndef __SHELL_H__ -#define __SHELL_H__ - -#include "shell_cfg.h" - -#define SHELL_VERSION "3.0.2" /**< 版本号 */ - - -/** - * @brief shell 断言 - * - * @param expr 表达式 - * @param action 断言失败操作 - */ -#define SHELL_ASSERT(expr, action) \ - if (!(expr)) { \ - action; \ - } - -/** - * @brief shell 命令权限 - * - * @param permission 权限级别 - */ -#define SHELL_CMD_PERMISSION(permission) \ - (permission & 0x000000FF) - -/** - * @brief shell 命令类型 - * - * @param type 类型 - */ -#define SHELL_CMD_TYPE(type) \ - ((type & 0x0000000F) << 8) - -/** - * @brief 使能命令在未校验密码的情况下使用 - */ -#define SHELL_CMD_ENABLE_UNCHECKED \ - (1 << 12) - -/** - * @brief 禁用返回值打印 - */ -#define SHELL_CMD_DISABLE_RETURN \ - (1 << 13) - -/** - * @brief 命令参数数量 - */ -#define SHELL_CMD_PARAM_NUM(num) \ - ((num & 0x0000000F)) << 16 - -#ifndef SECTION - #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000) - #define SECTION(x) __attribute__((section(x))) - #elif defined(__ICCARM__) || defined(__ICCRX__) - #define SECTION(x) @ x - #elif defined(__GNUC__) - #define SECTION(x) __attribute__((section(x))) - #else - #define SECTION(x) - #endif -#endif - -/** - * @brief shell float型参数转换 - */ -#define SHELL_PARAM_FLOAT(x) (*(float *)(&x)) - -/** - * @brief shell 代理函数名 - */ -#define SHELL_AGENCY_FUNC_NAME(_func) agency##_func - -/** - * @brief shell代理函数定义 - * - * @param _func 被代理的函数 - * @param ... 代理参数 - */ -#define SHELL_AGENCY_FUNC(_func, ...) \ - void SHELL_AGENCY_FUNC_NAME(_func)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) \ - { _func(__VA_ARGS__); } - -#if SHELL_USING_CMD_EXPORT == 1 - - /** - * @brief shell 命令定义 - * - * @param _attr 命令属性 - * @param _name 命令名 - * @param _func 命令函数 - * @param _desc 命令描述 - */ - #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \ - const char shellCmd##_name[] = #_name; \ - const char shellDesc##_name[] = #_desc; \ - const ShellCommand \ - shellCommand##_name SECTION("shellCommand") = \ - { \ - .attr.value = _attr, \ - .data.cmd.name = shellCmd##_name, \ - .data.cmd.function = (int (*)())_func, \ - .data.cmd.desc = shellDesc##_name \ - } - - /** - * @brief shell 代理命令定义 - * - * @param _attr 命令属性 - * @param _name 命令名 - * @param _func 命令函数 - * @param _desc 命令描述 - * @param ... 代理参数 - */ - #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) \ - SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \ - SHELL_EXPORT_CMD(_attr, _name, SHELL_AGENCY_FUNC_NAME(_func), _desc) - - /** - * @brief shell 变量定义 - * - * @param _attr 变量属性 - * @param _name 变量名 - * @param _value 变量值 - * @param _desc 变量描述 - */ - #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \ - const char shellCmd##_name[] = #_name; \ - const char shellDesc##_name[] = #_desc; \ - const ShellCommand \ - shellVar##_name SECTION("shellCommand") = \ - { \ - .attr.value = _attr, \ - .data.var.name = shellCmd##_name, \ - .data.var.value = (void *)_value, \ - .data.var.desc = shellDesc##_name \ - } - - /** - * @brief shell 用户定义 - * - * @param _attr 用户属性 - * @param _name 用户名 - * @param _password 用户密码 - * @param _desc 用户描述 - */ - #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) \ - const char shellCmd##_name[] = #_name; \ - const char shellPassword##_name[] = #_password; \ - const char shellDesc##_name[] = #_desc; \ - const ShellCommand \ - shellUser##_name SECTION("shellCommand") = \ - { \ - .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ - .data.user.name = shellCmd##_name, \ - .data.user.password = shellPassword##_name, \ - .data.user.desc = shellDesc##_name \ - } - - /** - * @brief shell 按键定义 - * - * @param _attr 按键属性 - * @param _value 按键键值 - * @param _func 按键函数 - * @param _desc 按键描述 - */ - #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \ - const char shellDesc##_value[] = #_desc; \ - const ShellCommand \ - shellKey##_value SECTION("shellCommand") = \ - { \ - .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ - .data.key.value = _value, \ - .data.key.function = (void (*)(Shell *))_func, \ - .data.key.desc = shellDesc##_value \ - } -#else - /** - * @brief shell 命令item定义 - * - * @param _attr 命令属性 - * @param _name 命令名 - * @param _func 命令函数 - * @param _desc 命令描述 - */ - #define SHELL_CMD_ITEM(_attr, _name, _func, _desc) \ - { \ - .attr.value = _attr, \ - .data.cmd.name = #_name, \ - .data.cmd.function = (int (*)())_func, \ - .data.cmd.desc = #_desc \ - } - - /** - * @brief shell 变量item定义 - * - * @param _attr 变量属性 - * @param _name 变量名 - * @param _value 变量值 - * @param _desc 变量描述 - */ - #define SHELL_VAR_ITEM(_attr, _name, _value, _desc) \ - { \ - .attr.value = _attr, \ - .data.var.name = #_name, \ - .data.var.value = (void *)_value, \ - .data.var.desc = #_desc \ - } - - /** - * @brief shell 用户item定义 - * - * @param _attr 用户属性 - * @param _name 用户名 - * @param _password 用户密码 - * @param _desc 用户描述 - */ - #define SHELL_USER_ITEM(_attr, _name, _password, _desc) \ - { \ - .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ - .data.user.name = #_name, \ - .data.user.password = #_password, \ - .data.user.desc = #_desc \ - } - - /** - * @brief shell 按键item定义 - * - * @param _attr 按键属性 - * @param _value 按键键值 - * @param _func 按键函数 - * @param _desc 按键描述 - */ - #define SHELL_KEY_ITEM(_attr, _value, _func, _desc) \ - { \ - .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ - .data.key.value = _value, \ - .data.key.function = (void (*)(Shell *))_func, \ - .data.key.desc = #_desc \ - } - - #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) - #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) - #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) - #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) -#endif /** SHELL_USING_CMD_EXPORT == 1 */ - -/** - * @brief shell command类型 - */ -typedef enum -{ - SHELL_TYPE_CMD_MAIN = 0, /**< main形式命令 */ - SHELL_TYPE_CMD_FUNC, /**< C函数形式命令 */ - SHELL_TYPE_VAR_INT, /**< int型变量 */ - SHELL_TYPE_VAR_SHORT, /**< short型变量 */ - SHELL_TYPE_VAR_CHAR, /**< char型变量 */ - SHELL_TYPE_VAR_POINT, /**< 指针型变量 */ - SHELL_TYPE_VAL, /**< 常量 */ - SHELL_TYPE_USER, /**< 用户 */ - SHELL_TYPE_KEY, /**< 按键 */ -} ShellCommandType; - - -/** - * @brief Shell定义 - */ -typedef struct -{ - struct - { - const struct shell_command *user; /**< 当前用户 */ - int activeTime; /**< shell激活时间 */ - } info; - struct - { - unsigned short length; /**< 输入数据长度 */ - unsigned short cursor; /**< 当前光标位置 */ - char *buffer; /**< 输入缓冲 */ - char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< 参数 */ - unsigned short bufferSize; /**< 输入缓冲大小 */ - unsigned short paramCount; /**< 参数数量 */ - int keyValue; /**< 输入按键键值 */ - } parser; - struct - { - char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */ - unsigned short number; /**< 历史记录数 */ - unsigned short record; /**< 当前记录位置 */ - signed short offset; /**< 当前历史记录偏移 */ - } history; - struct - { - void *base; /**< 命令表基址 */ - unsigned short count; /**< 命令数量 */ - } commandList; - struct - { - unsigned char isChecked : 1; /**< 密码校验通过 */ - unsigned char isActive : 1; /**< 当前活动Shell */ - unsigned char tabFlag : 1; /**< tab标志 */ - } status; - signed char (*read)(char *); /**< shell读函数 */ - void (*write)(const char); /**< shell写函数 */ - int (*getcwd)(char *path, unsigned int len); -} Shell; - - -/** - * @brief shell command定义 - */ -typedef struct shell_command -{ - union - { - struct - { - unsigned char permission : 8; /**< command权限 */ - ShellCommandType type : 4; /**< command类型 */ - unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */ - unsigned char disableReturn : 1; /**< 禁用返回值输出 */ - unsigned char reserve : 2; /**< 保留 */ - unsigned char paramNum : 4; /**< 参数数量 */ - } attrs; - int value; - } attr; /**< 属性 */ - union - { - struct - { - const char *name; /**< 命令名 */ - int (*function)(); /**< 命令执行函数 */ - const char *desc; /**< 命令描述 */ - } cmd; /**< 命令定义 */ - struct - { - const char *name; /**< 变量名 */ - void *value; /**< 变量值 */ - const char *desc; /**< 变量描述 */ - } var; /**< 变量定义 */ - struct - { - const char *name; /**< 用户名 */ - const char *password; /**< 用户密码 */ - const char *desc; /**< 用户描述 */ - } user; /**< 用户定义 */ - struct - { - int value; /**< 按键键值 */ - void (*function)(Shell *); /**< 按键执行函数 */ - const char *desc; /**< 按键描述 */ - } key; /**< 按键定义 */ - } data; -} ShellCommand; - - -void shellInit(Shell *shell, char *buffer, unsigned short size); -void shellPrint(Shell *shell, char *fmt, ...); -Shell* shellGetCurrent(void); -void shellHandler(Shell *shell, char data); -void shellTask(void *param); - -/** - * @brief 数字类型 - * - */ -typedef enum -{ - NUM_TYPE_INT, /**< 十进制整型 */ - NUM_TYPE_BIN, /**< 二进制整型 */ - NUM_TYPE_OCT, /**< 八进制整型 */ - NUM_TYPE_HEX, /**< 十六进制整型 */ - NUM_TYPE_FLOAT /**< 浮点型 */ -} NUM_Type; - -unsigned int shellExtParsePara(Shell *shell, char *string); -int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]); - -#endif - diff --git a/components/shell/shell_cfg.h b/components/shell/shell_cfg.h deleted file mode 100644 index 55b516db..00000000 --- a/components/shell/shell_cfg.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file shell_cfg.h - * @author Letter (nevermindzzt@gmail.com) - * @brief shell config - * @version 3.0.0 - * @date 2019-12-31 - * - * @copyright (c) 2019 Letter - * - */ - -#ifndef __SHELL_CFG_H__ -#define __SHELL_CFG_H__ - - -/** - * @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义 - * 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell - * 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()` - */ -#define SHELL_TASK_WHILE 0 - -/** - * @brief 是否使用命令导出方式 - * 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令 - * 定义shell命令,关闭此宏的情况下,需要使用命令表的方式 - */ -#define SHELL_USING_CMD_EXPORT 1 - -/** - * @brief 是否在输出命令列表中列出用户 - */ -#define SHELL_HELP_LIST_USER 0 - -/** - * @brief 是否在输出命令列表中列出变量 - */ -#define SHELL_HELP_LIST_VAR 0 - -/** - * @brief 是否在输出命令列表中列出按键 - */ -#define SHELL_HELP_LIST_KEY 0 - -/** - * @brief 是否在输出命令列表中展示命令权限 - */ -#define SHELL_HELP_SHOW_PERMISSION 0 - -/** - * @brief 使用LF作为命令行回车触发 - * 可以和SHELL_ENTER_CR同时开启 - */ -#define SHELL_ENTER_LF 1 - -/** - * @brief 使用CR作为命令行回车触发 - * 可以和SHELL_ENTER_LF同时开启 - */ -#define SHELL_ENTER_CR 1 - -/** - * @brief 使用CRLF作为命令行回车触发 - * 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启 - */ -#define SHELL_ENTER_CRLF 0 - -/** - * @brief 使用执行未导出函数的功能 - * 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数 - * @attention 如果地址错误,可能会直接引起程序崩溃 - */ -#define SHELL_EXEC_UNDEF_FUNC 0 - -/** - * @brief shell命令参数最大数量 - * 包含命令名在内,超过8个参数并且使用了参数自动转换的情况下,需要修改源码 - */ -#define SHELL_PARAMETER_MAX_NUMBER 8 - -/** - * @brief 历史命令记录数量 - */ -#define SHELL_HISTORY_MAX_NUMBER 5 - -/** - * @brief 双击间隔(ms) - * 使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔 - */ -#define SHELL_DOUBLE_CLICK_TIME 200 - -/** - * @brief 管理的最大shell数量 - */ -#define SHELL_MAX_NUMBER 5 - -/** - * @brief shell格式化输出的缓冲大小 - * 为0时不使用shell格式化输出 - */ -#define SHELL_PRINT_BUFFER 128 - -/** - * @brief 获取系统时间(ms) - * 定义此宏为获取系统Tick,如`HAL_GetTick()` - * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定 - */ -#define SHELL_GET_TICK() 0 - -/** - * @brief 是否显示shell信息 - */ -#define SHELL_SHOW_INFO 0 - -/** - * @brief 是否在登录后清除命令行 - */ -#define SHELL_CLS_WHEN_LOGIN 0 - -/** - * @brief shell默认用户 - */ -#define SHELL_DEFAULT_USER "bouffalolab" - -/** - * @brief shell默认用户密码 - * 若默认用户不需要密码,设为"" - */ -#define SHELL_DEFAULT_USER_PASSWORD "" - -/** - * @brief shell自动锁定超时 - * 使能`SHELL_USING_AUTH`的情况下生效,超时后会自动重新锁定shell - * 设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位 - * @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效 - */ -#define SHELL_LOCK_TIMEOUT 0 * 60 * 1000 - - -/** - * @brief shell是否在命令提示符输出路径,需要引用文件系统 - */ -#define SHELL_FS 0 - -#endif