mirror of
https://github.com/NevermindZZT/letter-shell.git
synced 2025-01-21 10:02:54 +08:00
commit
04d9ed7bce
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,5 +3,8 @@ cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
demo/x86-gcc/Makefile
|
||||
demo/x86-gcc/LetterShell
|
||||
demo/x86-gcc/LetterShell.map
|
||||
demo/x86-gcc/compile_commands.json
|
||||
demo/x86-gcc/.cache/
|
||||
.vscode
|
||||
build
|
87
README.md
87
README.md
@ -1,8 +1,8 @@
|
||||
# letter shell 3.x
|
||||
|
||||
![version](https://img.shields.io/badge/version-3.1.2-brightgreen.svg)
|
||||
![version](https://img.shields.io/badge/version-3.2.0-brightgreen.svg)
|
||||
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
|
||||
![build](https://img.shields.io/badge/build-2021.10.17-brightgreen.svg)
|
||||
![build](https://img.shields.io/badge/build-2023.04.15-brightgreen.svg)
|
||||
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
|
||||
|
||||
一个功能强大的嵌入式shell
|
||||
@ -25,6 +25,8 @@
|
||||
- [定义宏说明](#定义宏说明)
|
||||
- [命令属性字段说明](#命令属性字段说明)
|
||||
- [代理函数和代理参数解析](#代理函数和代理参数解析)
|
||||
- [函数签名](#函数签名)
|
||||
- [自定义类型解析](#自定义类型解析)
|
||||
- [权限系统说明](#权限系统说明)
|
||||
- [锁说明](#锁说明)
|
||||
- [伴生对象](#伴生对象)
|
||||
@ -178,6 +180,7 @@
|
||||
| SHELL_DEFAULT_USER | shell默认用户 |
|
||||
| SHELL_DEFAULT_USER_PASSWORD | 默认用户密码 |
|
||||
| SHELL_LOCK_TIMEOUT | shell自动锁定超时 |
|
||||
| SHELL_USING_FUNC_SIGNATURE | 使用函数签名 |
|
||||
|
||||
## 使用方式
|
||||
|
||||
@ -485,6 +488,85 @@ p1, SHELL_PARAM_FLOAT(p2), p3, SHELL_PARAM_FLOAT(p4));
|
||||
|
||||
相比常规的命令导出,代理函数命令导出前4个参数和常规形式的命令导出一致,之后的参数即传递至目标函数的参数,letter shell默认实现的代理函数定义支持最多7个参数,p1~p7,对于不需要代理参数解析的参数,只需要对应写入`px(x为1~7)`即可,比如上方示例的`p1`和`p3`,而需要代理参数解析的参数,则需要使用对应的参数解析器,比如上方示例的`p2`和`p4`
|
||||
|
||||
## 函数签名
|
||||
|
||||
letter shell 3.2.x 之后,引入了函数签名的概念,以便于参数自动解析
|
||||
|
||||
之前的版本里,如果声明的命令是 `SHELL_TYPE_CMD_FUNC`,shell 会自动进行参数的转换,但是参数转换后的类型是猜出来的,无法保证转换后的数据类型是正确的,一旦猜错了,就容易导致程序挂掉
|
||||
|
||||
由此,借鉴 Java 等语言的函数签名,新版也引入了函数签名的概念,在声明命令时,可以给定最终执行命令的函数的签名,shell 根据这个签名进行参数转换,使用此功能时,需要打开宏 `SHELL_USING_FUNC_SIGNATURE`
|
||||
|
||||
函数签名是一个字符串,通过这个字符串声明表达函数的参数类型,返回值不声明,比如一个函数`int func(int a, char *b, char c)`,它的函数签名就是 `isc`
|
||||
|
||||
基本类型的参数签名定义如下:
|
||||
|
||||
| 类型 | 签名 |
|
||||
| -------------------- | ---- |
|
||||
| char(字符) | c |
|
||||
| int/short/char(数字) | i |
|
||||
| char * (字符串) | s |
|
||||
| pointer | p |
|
||||
|
||||
声明命令时,在最后添加一个参数 `.data.cmd.signature = "isc"` 即可,比如:
|
||||
|
||||
```c
|
||||
void shellFuncSignatureTest(int a, char *b, char c)
|
||||
{
|
||||
printf("a = %d, b = %s, c = %c\r\n", a, b, c);
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
|
||||
funcSignatureTest, shellFuncSignatureTest, test function signature, .data.cmd.signature = "isc");
|
||||
```
|
||||
|
||||
### 自定义类型解析
|
||||
|
||||
由于函数签名的引用,我们就可以使用函数签名描述任何参数,对应的,在参数类型已知的情况下,也可以定义对应的参数解析器进行参数解析,自定义的参数类型签名需要以 `L` 开头,以 `;` 结尾,比如说定义一个 `TestStruct` 结构体类型为 `LTestStruct;`,那么接收这个结构体为参数的函数就可以通过这个类型签名定义函数签名,并导出命令
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
int a;
|
||||
char *b;
|
||||
} TestStruct;
|
||||
|
||||
void shellParamParserTest(int a, TestStruct *data, char *c)
|
||||
{
|
||||
printf("a = %d, data->a = %d, data->b = %s, c = %s\r\n", a, data->a, data->b, c);
|
||||
}
|
||||
SHELL_EXPORT_CMD_SIGN(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
|
||||
paramParserTest, shellParamParserTest, test function signature and param parser, iLTestStruct;s);
|
||||
```
|
||||
|
||||
同时,我们需要对自定义的类型定义解析器,使用 `SHELL_EXPORT_PARAM_PARSER` 宏
|
||||
|
||||
```c
|
||||
int testStructParser(char *string, void **param)
|
||||
{
|
||||
TestStruct *data = malloc(sizeof(TestStruct));
|
||||
data->b = malloc(16);
|
||||
if (sscanf(string, "%d %s", &(data->a), data->b) == 2)
|
||||
{
|
||||
*param = (void *)data;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int testStructClener(void *param)
|
||||
{
|
||||
TestStruct *data = (TestStruct *)param;
|
||||
free(data->b);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
SHELL_EXPORT_PARAM_PARSER(0, LTestStruct;, testStructParser, testStructClener);
|
||||
```
|
||||
|
||||
`SHELL_EXPORT_PARAM_PARSER` 接收四个参数,第一个参数表示属性,这里一般填 0 皆可,第二个参数就是解析器对应的类型签名,第三个参数是解析器函数,第四个参数是清理函数,清理函数在参数解析失败或者命令执行完毕后会被调用,一般用于清理解析器分配的内存,如果不需要清理函数,填 `NULL` 即可
|
||||
|
||||
解析器函数接收两个参数,第一个参数是输入的字符串,也就是命令行输入的参数,第二个参数是解析后的参数,解析成功后,需要将解析后的参数赋值给第二个参数,解析成功返回 0,解析失败返回 -1
|
||||
|
||||
清理函数接收一个参数,就是解析器函数解析得到的结果
|
||||
|
||||
## 权限系统说明
|
||||
|
||||
letter shell 3.x的权限管理同用户定义紧密相关,letter shell 3.x使用8个bit位表示命令权限,当用户和命令的权限按位与为真,或者命令权限为0时,表示该用户拥有此命令的权限,可以调用该命令
|
||||
@ -566,7 +648,6 @@ python shellTools.py project
|
||||
letter shell 3.x提供了一个x86的demo,可以直接编译运行,其中包含了一条按键键值测试命令,可以测试按键键值,用于快捷键的定义,编译运行方法如下:
|
||||
|
||||
```sh
|
||||
mv src/shell_cfg.h src/shell_cfg.h.bak
|
||||
cd demo/x86-gcc/
|
||||
cmake .
|
||||
make
|
||||
|
@ -1,10 +1,15 @@
|
||||
add_definitions(-DSHELL_CFG_USER="shell_cfg_user.h")
|
||||
|
||||
idf_component_register(
|
||||
SRCS "src/shell.c"
|
||||
"src/shell_ext.c"
|
||||
"shell_port.c"
|
||||
|
||||
INCLUDE_DIRS "./"
|
||||
"./src"
|
||||
|
||||
REQUIRES
|
||||
driver
|
||||
|
||||
LDFRAGMENTS "shell.lf"
|
||||
)
|
||||
)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -DSHELL_CFG_USER="shell_cfg_user.h")
|
||||
|
@ -11,3 +11,5 @@
|
||||
- `esp-idf` 编译系统会忽略 `__attribute__((used))` 声明,所以仅仅作为命令定义的函数不会被包含在编译出来的固件里面,只有被代码引用的函数会被编译进去
|
||||
|
||||
- 此 demo 包含链接使用的 `.lf` 文件,在使用这个文件的情况下不需要修改 `esp-idf` 中的 `ld` 文件
|
||||
|
||||
- 如果使用 overlay 的方式配置 shell,建议在主 CMakeList.txt 后面添加 `idf_build_set_property(COMPILE_OPTIONS "-DSHELL_CFG_USER=\"shell_cfg_user.h\"" APPEND)`
|
||||
|
@ -34,5 +34,7 @@ target_include_directories(LetterShell PUBLIC
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T shell.lds")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \
|
||||
-T \"${CMAKE_CURRENT_SOURCE_DIR}/shell.lds\" \
|
||||
-Wl,-Map=LetterShell.map")
|
||||
set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11 -pthread")
|
||||
|
@ -77,6 +77,13 @@ SECTIONS
|
||||
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
. = ALIGN(32);
|
||||
.shell_command ALIGN(4) :
|
||||
{
|
||||
_shell_command_start = .;
|
||||
KEEP (*(shellCommand))
|
||||
_shell_command_end = .;
|
||||
}
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
@ -183,12 +190,7 @@ SECTIONS
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||
_shell_command_start = .;
|
||||
KEEP (*(shellCommand))
|
||||
_shell_command_end = .;
|
||||
}
|
||||
{ *(.lrodata .lrodata.* .gnu.linkonce.lr.*) }
|
||||
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||
|
@ -66,4 +66,11 @@ unsigned int userGetTick();
|
||||
*/
|
||||
#define SHELL_FREE(obj) free(obj)
|
||||
|
||||
/**
|
||||
* @brief 使用函数签名
|
||||
* 使能后,可以在声明命令时,指定函数的签名,shell 会根据函数签名进行参数转换,
|
||||
* 而不是自动判断参数的类型,如果参数和函数签名不匹配,会停止执行命令
|
||||
*/
|
||||
#define SHELL_USING_FUNC_SIGNATURE 1
|
||||
|
||||
#endif
|
||||
|
@ -272,3 +272,47 @@ void systemPassthrough(char *data, unsigned short len)
|
||||
system(data);
|
||||
}
|
||||
SHELL_EXPORT_PASSTROUGH(SHELL_CMD_PERMISSION(0), system, system>>\x20, systemPassthrough, passthrough for system command);
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
|
||||
void shellFuncSignatureTest(int a, char *b, char c)
|
||||
{
|
||||
printf("a = %d, b = %s, c = %c\r\n", a, b, c);
|
||||
}
|
||||
SHELL_EXPORT_CMD_SIGN(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
|
||||
funcSignatureTest, shellFuncSignatureTest, test function signature, isc);
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
char *b;
|
||||
} TestStruct;
|
||||
|
||||
int testStructParser(char *string, void **param)
|
||||
{
|
||||
TestStruct *data = malloc(sizeof(TestStruct));
|
||||
data->b = malloc(16);
|
||||
if (sscanf(string, "%d %s", &(data->a), data->b) == 2)
|
||||
{
|
||||
*param = (void *)data;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int testStructClener(void *param)
|
||||
{
|
||||
TestStruct *data = (TestStruct *)param;
|
||||
free(data->b);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
SHELL_EXPORT_PARAM_PARSER(0, LTestStruct;, testStructParser, testStructClener);
|
||||
|
||||
void shellParamParserTest(int a, TestStruct *data, char *c)
|
||||
{
|
||||
printf("a = %d, data->a = %d, data->b = %s, c = %s\r\n", a, data->a, data->b, c);
|
||||
}
|
||||
SHELL_EXPORT_CMD_SIGN(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
|
||||
paramParserTest, shellParamParserTest, test function signature and param parser, iLTestStruct;s);
|
||||
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
|
@ -25,6 +25,9 @@ typedef struct shell_command_cpp_cmd
|
||||
const char *name; /**< 命令名 */
|
||||
int (*function)(); /**< 命令执行函数 */
|
||||
const char *desc; /**< 命令描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
const char *signature; /**< 函数签名 */
|
||||
#endif
|
||||
} ShellCommandCppCmd;
|
||||
|
||||
/**
|
||||
@ -36,6 +39,9 @@ typedef struct shell_command_cpp_var
|
||||
const char *name; /**< 变量名 */
|
||||
void *value; /**< 变量值 */
|
||||
const char *desc; /**< 变量描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
void *unused; /**< 未使用成员,需要保持和 ShellCommandCppCmd 大小一致 */
|
||||
#endif
|
||||
} ShellCommandCppVar;
|
||||
|
||||
/**
|
||||
@ -47,6 +53,9 @@ typedef struct shell_command_cpp_user
|
||||
const char *name; /**< 用户名 */
|
||||
const char *password; /**< 用户密码 */
|
||||
const char *desc; /**< 用户描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
void *unused; /**< 未使用成员,需要保持和 ShellCommandCppCmd 大小一致 */
|
||||
#endif
|
||||
} ShellCommandCppUser;
|
||||
|
||||
/**
|
||||
@ -58,8 +67,22 @@ typedef struct shell_command_cpp_key
|
||||
int value; /**< 按键键值 */
|
||||
void (*function)(Shell *); /**< 按键执行函数 */
|
||||
const char *desc; /**< 按键描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
void *unused; /**< 未使用成员,需要保持和 ShellCommandCppCmd 大小一致 */
|
||||
#endif
|
||||
} ShellCommandCppKey;
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
typedef struct shell_command_cpp_param_parser
|
||||
{
|
||||
int attr; /**< 属性 */
|
||||
const char *type; /**< 参数类型 */
|
||||
int (*parser)(char *, void **);; /**< 解析函数 */
|
||||
int (*cleaner)(void *); /**< 清理函数 */
|
||||
void *unsed; /**< 未使用成员,需要保持和 ShellCommandCppCmd 大小一致 */
|
||||
} ShellCommandCppParamParser;
|
||||
#endif
|
||||
|
||||
#if SHELL_USING_CMD_EXPORT == 1
|
||||
|
||||
#undef SHELL_EXPORT_CMD
|
||||
@ -70,8 +93,9 @@ typedef struct shell_command_cpp_key
|
||||
* @param _name 命令名
|
||||
* @param _func 命令函数
|
||||
* @param _desc 命令描述
|
||||
* @param ... 其他参数
|
||||
*/
|
||||
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
|
||||
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc, ...) \
|
||||
const char shellCmd##_name[] = #_name; \
|
||||
const char shellDesc##_name[] = #_desc; \
|
||||
extern "C" SHELL_USED const ShellCommandCppCmd \
|
||||
@ -80,7 +104,8 @@ typedef struct shell_command_cpp_key
|
||||
_attr, \
|
||||
shellCmd##_name, \
|
||||
(int (*)())_func, \
|
||||
shellDesc##_name \
|
||||
shellDesc##_name, \
|
||||
##__VA_ARGS__ \
|
||||
}
|
||||
|
||||
#undef SHELL_EXPORT_VAR
|
||||
@ -145,11 +170,31 @@ typedef struct shell_command_cpp_key
|
||||
(void (*)(Shell *))_func, \
|
||||
shellDesc##_value \
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
#undef SHELL_EXPORT_PARAM_PARSER
|
||||
/**
|
||||
* @brief shell 参数解析器定义
|
||||
*
|
||||
* @param _attr 参数解析器属性
|
||||
* @param _type 参数解析器类型
|
||||
* @param _parser 参数解析器函数
|
||||
* @param _cleaner 参数清理函数
|
||||
*/
|
||||
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner) \
|
||||
const char shellDesc##_parser[] = #_type; \
|
||||
extern "C" SHELL_USED const ShellCommandCppParamParser \
|
||||
shellCommand##_parser SHELL_SECTION("shellCommand") = \
|
||||
{ \
|
||||
_attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
shellDesc##_parser, \
|
||||
(int (*)(char *, void **))_parser, \
|
||||
(int (*)(void *))_cleaner \
|
||||
}
|
||||
#endif
|
||||
#endif /** SHELL_USING_CMD_EXPORT == 1 */
|
||||
|
||||
}
|
||||
#endif /**< defined __cplusplus */
|
||||
|
||||
#endif /**< __SHELL_CPP_H__ */
|
||||
|
||||
|
||||
|
14
src/shell.c
14
src/shell.c
@ -573,6 +573,12 @@ static const char* shellGetCommandName(ShellCommand *command)
|
||||
{
|
||||
return command->data.user.name;
|
||||
}
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
else if (command->attr.attrs.type == SHELL_TYPE_PARAM_PARSER)
|
||||
{
|
||||
return command->data.paramParser.type;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
shellToHex(command->data.key.value, buffer);
|
||||
@ -1957,7 +1963,13 @@ int shellExecute(int argc, char *argv[])
|
||||
Shell *shell = shellGetCurrent();
|
||||
if (shell && argc >= 2)
|
||||
{
|
||||
int (*func)() = (int (*)())shellExtParsePara(shell, argv[1]);
|
||||
unsigned result;
|
||||
if (shellExtParsePara(shell, argv[1], NULL, &result) != 0)
|
||||
{
|
||||
shellWriteString(shell, shellText[SHELL_TEXT_PARAM_ERROR]);
|
||||
return -1;
|
||||
}
|
||||
int (*func)() = (int (*)())result;
|
||||
ShellCommand command = {
|
||||
.attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)
|
||||
|SHELL_CMD_DISABLE_RETURN,
|
||||
|
100
src/shell.h
100
src/shell.h
@ -14,7 +14,7 @@
|
||||
|
||||
#include "shell_cfg.h"
|
||||
|
||||
#define SHELL_VERSION "3.1.2" /**< 版本号 */
|
||||
#define SHELL_VERSION "3.2.0" /**< 版本号 */
|
||||
|
||||
|
||||
/**
|
||||
@ -77,11 +77,11 @@
|
||||
|
||||
#ifndef SHELL_SECTION
|
||||
#if defined(__CC_ARM) || defined(__CLANG_ARM)
|
||||
#define SHELL_SECTION(x) __attribute__((section(x)))
|
||||
#define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
|
||||
#elif defined (__IAR_SYSTEMS_ICC__)
|
||||
#define SHELL_SECTION(x) @ x
|
||||
#elif defined(__GNUC__)
|
||||
#define SHELL_SECTION(x) __attribute__((section(x)))
|
||||
#define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
|
||||
#else
|
||||
#define SHELL_SECTION(x)
|
||||
#endif
|
||||
@ -128,8 +128,9 @@
|
||||
* @param _name 命令名
|
||||
* @param _func 命令函数
|
||||
* @param _desc 命令描述
|
||||
* @param ... 其他参数
|
||||
*/
|
||||
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
|
||||
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc, ...) \
|
||||
const char shellCmd##_name[] = #_name; \
|
||||
const char shellDesc##_name[] = #_desc; \
|
||||
SHELL_USED const ShellCommand \
|
||||
@ -138,9 +139,35 @@
|
||||
.attr.value = _attr, \
|
||||
.data.cmd.name = shellCmd##_name, \
|
||||
.data.cmd.function = (int (*)())_func, \
|
||||
.data.cmd.desc = shellDesc##_name \
|
||||
.data.cmd.desc = shellDesc##_name, \
|
||||
##__VA_ARGS__ \
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief shell 命令定义
|
||||
*
|
||||
* @param _attr 命令属性
|
||||
* @param _name 命令名
|
||||
* @param _func 命令函数
|
||||
* @param _desc 命令描述
|
||||
* @param _sign 命令签名
|
||||
*/
|
||||
#define SHELL_EXPORT_CMD_SIGN(_attr, _name, _func, _desc, _sign) \
|
||||
const char shellCmd##_name[] = #_name; \
|
||||
const char shellDesc##_name[] = #_desc; \
|
||||
const char shellSign##_name[] = #_sign; \
|
||||
SHELL_USED const ShellCommand \
|
||||
shellCommand##_name SHELL_SECTION("shellCommand") = \
|
||||
{ \
|
||||
.attr.value = _attr, \
|
||||
.data.cmd.name = shellCmd##_name, \
|
||||
.data.cmd.function = (int (*)())_func, \
|
||||
.data.cmd.desc = shellDesc##_name, \
|
||||
.data.cmd.signature = shellSign##_name \
|
||||
}
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
|
||||
/**
|
||||
* @brief shell 代理命令定义
|
||||
*
|
||||
@ -226,6 +253,28 @@
|
||||
#define SHELL_EXPORT_KEY_AGENCY(_attr, _value, _func, _desc, ...) \
|
||||
SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \
|
||||
SHELL_EXPORT_KEY(_attr, _value, SHELL_AGENCY_FUNC_NAME(_func), _desc)
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief shell 参数解析器定义
|
||||
*
|
||||
* @param _attr 参数解析器属性
|
||||
* @param _type 参数解析器类型
|
||||
* @param _parser 参数解析器函数
|
||||
* @param _cleaner 参数清理器
|
||||
*/
|
||||
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner) \
|
||||
const char shellDesc##_parser[] = #_type; \
|
||||
SHELL_USED const ShellCommand \
|
||||
shellCommand##_parser SHELL_SECTION("shellCommand") = \
|
||||
{ \
|
||||
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
.data.paramParser.type = shellDesc##_parser, \
|
||||
.data.paramParser.parser = (int (*)(char *, void **))_parser, \
|
||||
.data.paramParser.cleaner = (int (*)(void *))_cleaner \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief shell 命令item定义
|
||||
@ -291,12 +340,33 @@
|
||||
.data.key.desc = #_desc \
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief shell 参数解析器item定义
|
||||
*
|
||||
* @param _attr 参数解析器属性
|
||||
* @param _type 参数解析器类型
|
||||
* @param _parser 参数解析器函数
|
||||
* @param _cleaner 参数清理器
|
||||
*/
|
||||
#define SHELL_PARAM_PARSER_ITEM(_attr, _type, _parser, _cleaner) \
|
||||
{ \
|
||||
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
.data.paramParser.type = #_type, \
|
||||
.data.paramParser.parser = (int (*)(char *, void **))_parser, \
|
||||
.data.paramParser.cleaner = (int (*)(void *))_cleaner \
|
||||
}
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
|
||||
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc)
|
||||
#define SHELL_EXPORT_CMD_AGENCY(_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)
|
||||
#define SHELL_EXPORT_KEY_AGENCY(_attr, _name, _func, _desc, ...)
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _func)
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
#endif /** SHELL_USING_CMD_EXPORT == 1 */
|
||||
|
||||
/**
|
||||
@ -314,6 +384,9 @@ typedef enum
|
||||
SHELL_TYPE_VAR_NODE, /**< 节点变量 */
|
||||
SHELL_TYPE_USER, /**< 用户 */
|
||||
SHELL_TYPE_KEY, /**< 按键 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
SHELL_TYPE_PARAM_PARSER, /**< 参数解析器 */
|
||||
#endif
|
||||
} ShellCommandType;
|
||||
|
||||
|
||||
@ -386,7 +459,7 @@ typedef struct shell_command
|
||||
ShellCommandType type : 4; /**< command类型 */
|
||||
unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */
|
||||
unsigned char disableReturn : 1; /**< 禁用返回值输出 */
|
||||
unsigned char readOnly : 1; /**< 只读 */
|
||||
unsigned char readOnly : 1; /**< 只读 */
|
||||
unsigned char reserve : 1; /**< 保留 */
|
||||
unsigned char paramNum : 4; /**< 参数数量 */
|
||||
} attrs;
|
||||
@ -399,6 +472,9 @@ typedef struct shell_command
|
||||
const char *name; /**< 命令名 */
|
||||
int (*function)(); /**< 命令执行函数 */
|
||||
const char *desc; /**< 命令描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
const char *signature; /**< 函数签名 */
|
||||
#endif
|
||||
} cmd; /**< 命令定义 */
|
||||
struct
|
||||
{
|
||||
@ -418,7 +494,15 @@ typedef struct shell_command
|
||||
void (*function)(Shell *); /**< 按键执行函数 */
|
||||
const char *desc; /**< 按键描述 */
|
||||
} key; /**< 按键定义 */
|
||||
} data;
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
struct
|
||||
{
|
||||
const char *type; /**< 参数类型 */
|
||||
int (*parser)(char *, void **); /**< 解析函数 */
|
||||
int (*cleaner)(void *); /**< 清理器 */
|
||||
} paramParser; /**< 参数解析器 */
|
||||
#endif
|
||||
} data;
|
||||
} ShellCommand;
|
||||
|
||||
/**
|
||||
@ -468,5 +552,3 @@ void *shellCompanionGet(Shell *shell, int id);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -246,4 +246,13 @@
|
||||
#define SHELL_LOCK_TIMEOUT 0 * 60 * 1000
|
||||
#endif /** SHELL_LOCK_TIMEOUT */
|
||||
|
||||
#ifndef SHELL_USING_FUNC_SIGNATURE
|
||||
/**
|
||||
* @brief 使用函数签名
|
||||
* 使能后,可以在声明命令时,指定函数的签名,shell 会根据函数签名进行参数转换,
|
||||
* 而不是自动判断参数的类型,如果参数和函数签名不匹配,会停止执行命令
|
||||
*/
|
||||
#define SHELL_USING_FUNC_SIGNATURE 0
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE */
|
||||
|
||||
#endif
|
||||
|
300
src/shell_ext.c
300
src/shell_ext.c
@ -12,7 +12,7 @@
|
||||
#include "shell_cfg.h"
|
||||
#include "shell.h"
|
||||
#include "shell_ext.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
extern ShellCommand* shellSeekCommand(Shell *shell,
|
||||
const char *cmd,
|
||||
@ -20,6 +20,64 @@ extern ShellCommand* shellSeekCommand(Shell *shell,
|
||||
unsigned short compareLength);
|
||||
extern int shellGetVarValue(Shell *shell, ShellCommand *command);
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief 获取下一个参数类型
|
||||
*
|
||||
* @param signature 函数签名
|
||||
* @param index 参数遍历在签名中的起始索引
|
||||
* @param type 获取到的参数类型
|
||||
*
|
||||
* @return int 下一个参数在签名中的索引
|
||||
*/
|
||||
static int shellGetNextParamType(const char *signature, int index, char *type)
|
||||
{
|
||||
const char *p = signature + index;
|
||||
if (*p == 'L')
|
||||
{
|
||||
while (*p != ';' && *p != 0)
|
||||
{
|
||||
*type++ = *p++;
|
||||
index++;
|
||||
}
|
||||
*type++ = *p++;
|
||||
index++;
|
||||
}
|
||||
else if (*p != 0)
|
||||
{
|
||||
*type++ = *p;
|
||||
index++;
|
||||
}
|
||||
*type = '\0';
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
static int shellGetParamNumExcept(const char *signature)
|
||||
{
|
||||
int num = 0;
|
||||
const char *p = signature;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (*p == 'L')
|
||||
{
|
||||
while (*p != ';' && *p != 0)
|
||||
{
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
p++;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 判断数字进制
|
||||
*
|
||||
@ -92,7 +150,7 @@ static char shellExtToNum(char code)
|
||||
*/
|
||||
static char shellExtParseChar(char *string)
|
||||
{
|
||||
char *p = string + 1;
|
||||
char *p = (*string == '\'') ? (string + 1) : string;
|
||||
char value = 0;
|
||||
|
||||
if (*p == '\\')
|
||||
@ -266,30 +324,125 @@ static unsigned int shellExtParseVar(Shell *shell, char *var)
|
||||
*
|
||||
* @param shell shell对象
|
||||
* @param string 参数
|
||||
* @return unsigned int 解析结果
|
||||
* @param result 解析结果
|
||||
*
|
||||
* @return int 0 解析成功 --1 解析失败
|
||||
*/
|
||||
unsigned int shellExtParsePara(Shell *shell, char *string)
|
||||
int shellExtParsePara(Shell *shell, char *string, char *type, unsigned int *result)
|
||||
{
|
||||
if (*string == '\'' && *(string + 1))
|
||||
if (type == NULL || (*string == '$' && *(string + 1)))
|
||||
{
|
||||
return (unsigned int)shellExtParseChar(string);
|
||||
if (*string == '\'' && *(string + 1))
|
||||
{
|
||||
*result = (unsigned int)shellExtParseChar(string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string == '-' || (*string >= '0' && *string <= '9'))
|
||||
{
|
||||
*result = (unsigned int)shellExtParseNumber(string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string == '$' && *(string + 1))
|
||||
{
|
||||
*result = shellExtParseVar(shell, string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string)
|
||||
{
|
||||
*result = (unsigned int)shellExtParseString(string);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (*string == '-' || (*string >= '0' && *string <= '9'))
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
else
|
||||
{
|
||||
return (unsigned int)shellExtParseNumber(string);
|
||||
if (strcmp("c", type) == 0)
|
||||
{
|
||||
*result = (unsigned int)shellExtParseChar(string);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("i", type) == 0
|
||||
|| strcmp("f", type) == 0
|
||||
|| strcmp("p", type) == 0)
|
||||
{
|
||||
*result = (unsigned int)shellExtParseNumber(string);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("s", type) == 0)
|
||||
{
|
||||
*result = (unsigned int)shellExtParseString(string);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellCommand *command = shellSeekCommand(shell,
|
||||
type,
|
||||
shell->commandList.base,
|
||||
0);
|
||||
if (command != NULL)
|
||||
{
|
||||
void *param;
|
||||
if (command->data.paramParser.parser(shellExtParseString(string), ¶m) == 0)
|
||||
{
|
||||
*result = (unsigned int)param;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
shellWriteString(shell, "Parse param for type: ");
|
||||
shellWriteString(shell, type);
|
||||
shellWriteString(shell, " failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shellWriteString(shell, "Can't find the param parser for type: ");
|
||||
shellWriteString(shell, type);
|
||||
shellWriteString(shell, "\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*string == '$' && *(string + 1))
|
||||
{
|
||||
return shellExtParseVar(shell, string);
|
||||
}
|
||||
else if (*string)
|
||||
{
|
||||
return (unsigned int)shellExtParseString(string);
|
||||
}
|
||||
return 0;
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
int shellExtCleanerPara(Shell *shell, char *type, unsigned int param)
|
||||
{
|
||||
if (type == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp("c", type) == 0
|
||||
|| strcmp("i", type) == 0
|
||||
|| strcmp("f", type) == 0
|
||||
|| strcmp("p", type) == 0
|
||||
|| strcmp("s", type) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellCommand *command = shellSeekCommand(shell,
|
||||
type,
|
||||
shell->commandList.base,
|
||||
0);
|
||||
if (command != NULL && command->data.paramParser.cleaner != NULL)
|
||||
{
|
||||
return command->data.paramParser.cleaner((void *)param);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
|
||||
|
||||
/**
|
||||
* @brief 执行命令
|
||||
*
|
||||
@ -304,132 +457,162 @@ int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[])
|
||||
unsigned int params[SHELL_PARAMETER_MAX_NUMBER] = {0};
|
||||
int paramNum = command->attr.attrs.paramNum > (argc - 1) ?
|
||||
command->attr.attrs.paramNum : (argc - 1);
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
char type[16];
|
||||
int index = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (command->data.cmd.signature != NULL)
|
||||
{
|
||||
int except = shellGetParamNumExcept(command->data.cmd.signature);
|
||||
if (except != argc - 1)
|
||||
{
|
||||
shellWriteString(shell, "Parameters number incorrect\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < argc - 1; i++)
|
||||
{
|
||||
params[i] = shellExtParsePara(shell, argv[i + 1]);
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
if (command->data.cmd.signature != NULL) {
|
||||
index = shellGetNextParamType(command->data.cmd.signature, index, type);
|
||||
if (shellExtParsePara(shell, argv[i + 1], type, ¶ms[i]) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
{
|
||||
if (shellExtParsePara(shell, argv[i + 1], NULL, ¶ms[i]) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (paramNum)
|
||||
{
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 1
|
||||
case 0:
|
||||
return command->data.cmd.function();
|
||||
// break;
|
||||
ret = command->data.cmd.function();
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 1 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 2
|
||||
case 1:
|
||||
return command->data.cmd.function(params[0]);
|
||||
// break;
|
||||
ret = command->data.cmd.function(params[0]);
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 2 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 3
|
||||
case 2:
|
||||
return command->data.cmd.function(params[0], params[1]);
|
||||
// break;
|
||||
ret = command->data.cmd.function(params[0], params[1]);
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 3 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 4
|
||||
case 3:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 4 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 5
|
||||
case 4:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 5 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 6
|
||||
case 5:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 6 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 7
|
||||
case 6:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 7 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 8
|
||||
case 7:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 8 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 9
|
||||
case 8:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 9 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 10
|
||||
case 9:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 10 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 11
|
||||
case 10:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8], params[9]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 11 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 12
|
||||
case 11:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8], params[9],
|
||||
params[10]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 12 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 13
|
||||
case 12:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8], params[9],
|
||||
params[10], params[11]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 13 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 14
|
||||
case 13:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8], params[9],
|
||||
params[10], params[11],
|
||||
params[12]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 14 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 15
|
||||
case 14:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
params[8], params[9],
|
||||
params[10], params[11],
|
||||
params[12], params[13]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 15 */
|
||||
#if SHELL_PARAMETER_MAX_NUMBER >= 16
|
||||
case 15:
|
||||
return command->data.cmd.function(params[0], params[1],
|
||||
ret = command->data.cmd.function(params[0], params[1],
|
||||
params[2], params[3],
|
||||
params[4], params[5],
|
||||
params[6], params[7],
|
||||
@ -437,11 +620,24 @@ int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[])
|
||||
params[10], params[11],
|
||||
params[12], params[13],
|
||||
params[14]);
|
||||
// break;
|
||||
break;
|
||||
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 16 */
|
||||
default:
|
||||
return -1;
|
||||
// break;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
if (command->data.cmd.signature != NULL) {
|
||||
index = 0;
|
||||
for (int i = 0; i < argc - 1; i++)
|
||||
{
|
||||
index = shellGetNextParamType(command->data.cmd.signature, index, type);
|
||||
shellExtCleanerPara(shell, type, params[i]);
|
||||
}
|
||||
}
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ typedef enum
|
||||
NUM_TYPE_FLOAT /**< 浮点型 */
|
||||
} ShellNumType;
|
||||
|
||||
unsigned int shellExtParsePara(Shell *shell, char *string);
|
||||
int shellExtParsePara(Shell *shell, char *string, char *type, unsigned int *result);
|
||||
int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user