mirror of
https://github.com/NevermindZZT/letter-shell.git
synced 2025-01-01 09:58:41 +08:00
新增 支持自定义类型的函数签名
This commit is contained in:
parent
acd9dceb4e
commit
99b5e6d386
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
|
@ -274,10 +274,39 @@ void systemPassthrough(char *data, unsigned short len)
|
||||
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(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
|
||||
funcSignatureTest, shellFuncSignatureTest, test function signature, .data.cmd.signature = "isc");
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
SHELL_EXPORT_PARAM_PARSER(0, LTestStruct;, testStructParser);
|
||||
|
||||
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);
|
||||
free(data->b);
|
||||
free(data);
|
||||
}
|
||||
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 */
|
||||
|
@ -84,6 +84,19 @@ typedef struct shell_command_cpp_key
|
||||
#endif
|
||||
} ShellCommandCppKey;
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
typedef struct shell_command_cpp_param_parser
|
||||
{
|
||||
int attr; /**< 属性 */
|
||||
const char *type; /**< 参数类型 */
|
||||
int (*function)(char *, void **);; /**< 解析函数 */
|
||||
void *unsed[2]; /**< 未使用成员,需要保持和 ShellCommandCppCmd 大小一致 */
|
||||
#if SHELL_COMMAND_FILL_BYTES != 0
|
||||
char fill[SHELL_COMMAND_FILL_BYTES]; /**< 填充字节 */
|
||||
#endif
|
||||
} ShellCommandCppParamParser;
|
||||
#endif
|
||||
|
||||
#if SHELL_USING_CMD_EXPORT == 1
|
||||
|
||||
#undef SHELL_EXPORT_CMD
|
||||
@ -171,11 +184,28 @@ typedef struct shell_command_cpp_key
|
||||
(void (*)(Shell *))_func, \
|
||||
shellDesc##_value \
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief shell 参数解析器定义
|
||||
*
|
||||
* @param _attr 参数解析器属性
|
||||
* @param _type 参数解析器类型
|
||||
* @param _func 参数解析器函数
|
||||
*/
|
||||
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _func) \
|
||||
const char shellDesc##_func[] = #_type; \
|
||||
extern "C" SHELL_USED const ShellCommandCppParamParser \
|
||||
shellCommand##_func SHELL_SECTION("shellCommand") = \
|
||||
{ \
|
||||
_attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
shellDesc##_func, \
|
||||
(int (*)(char *, void **))_func \
|
||||
}
|
||||
#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], NULL);
|
||||
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,
|
||||
|
85
src/shell.h
85
src/shell.h
@ -143,6 +143,31 @@
|
||||
##__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 代理命令定义
|
||||
*
|
||||
@ -228,6 +253,26 @@
|
||||
#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 _func 参数解析器函数
|
||||
*/
|
||||
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _func) \
|
||||
const char shellDesc##_func[] = #_type; \
|
||||
SHELL_USED const ShellCommand \
|
||||
shellCommand##_func SHELL_SECTION("shellCommand") = \
|
||||
{ \
|
||||
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
.data.paramParser.type = shellDesc##_func, \
|
||||
.data.paramParser.function = (int (*)(char *, void **))_func \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief shell 命令item定义
|
||||
@ -293,12 +338,31 @@
|
||||
.data.key.desc = #_desc \
|
||||
}
|
||||
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
/**
|
||||
* @brief shell 参数解析器item定义
|
||||
*
|
||||
* @param _attr 参数解析器属性
|
||||
* @param _type 参数解析器类型
|
||||
* @param _func 参数解析器函数
|
||||
*/
|
||||
#define SHELL_PARAM_PARSER_ITEM(_attr, _type, _func) \
|
||||
{ \
|
||||
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
|
||||
.data.paramParser.type = #_type, \
|
||||
.data.paramParser.function = (int (*)(char *, void **))_func \
|
||||
}
|
||||
#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 */
|
||||
|
||||
/**
|
||||
@ -316,6 +380,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;
|
||||
|
||||
|
||||
@ -410,28 +477,26 @@ typedef struct shell_command
|
||||
const char *name; /**< 变量名 */
|
||||
void *value; /**< 变量值 */
|
||||
const char *desc; /**< 变量描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
const char *unsued; /**< 未使用成员 */
|
||||
#endif
|
||||
} var; /**< 变量定义 */
|
||||
struct
|
||||
{
|
||||
const char *name; /**< 用户名 */
|
||||
const char *password; /**< 用户密码 */
|
||||
const char *desc; /**< 用户描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
const char *unsued; /**< 未使用成员 */
|
||||
#endif
|
||||
} user; /**< 用户定义 */
|
||||
struct
|
||||
{
|
||||
int value; /**< 按键键值 */
|
||||
void (*function)(Shell *); /**< 按键执行函数 */
|
||||
const char *desc; /**< 按键描述 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
const char *unsued; /**< 未使用成员 */
|
||||
#endif
|
||||
} key; /**< 按键定义 */
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
struct
|
||||
{
|
||||
const char *type; /**< 参数类型 */
|
||||
int (*function)(char *, void **); /**< 解析函数 */
|
||||
} paramParser; /**< 参数解析器 */
|
||||
#endif
|
||||
} data;
|
||||
#if SHELL_COMMAND_FILL_BYTES != 0
|
||||
char fill[SHELL_COMMAND_FILL_BYTES]; /**< 填充字节 */
|
||||
@ -485,5 +550,3 @@ void *shellCompanionGet(Shell *shell, int id);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
123
src/shell_ext.c
123
src/shell_ext.c
@ -30,9 +30,9 @@ extern int shellGetVarValue(Shell *shell, ShellCommand *command);
|
||||
*
|
||||
* @return int 下一个参数在签名中的索引
|
||||
*/
|
||||
static int shellGetNextArgType(const char *signature, int index, char *type)
|
||||
static int shellGetNextParamType(const char *signature, int index, char *type)
|
||||
{
|
||||
char *p = signature + index;
|
||||
const char *p = signature + index;
|
||||
if (*p == 'L')
|
||||
{
|
||||
while (*p != ';' && *p != 0)
|
||||
@ -40,8 +40,10 @@ static int shellGetNextArgType(const char *signature, int index, char *type)
|
||||
*type++ = *p++;
|
||||
index++;
|
||||
}
|
||||
*type++ = *p++;
|
||||
index++;
|
||||
}
|
||||
else
|
||||
else if (*p != 0)
|
||||
{
|
||||
*type++ = *p;
|
||||
index++;
|
||||
@ -49,6 +51,31 @@ static int shellGetNextArgType(const char *signature, int index, char *type)
|
||||
*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
|
||||
|
||||
/**
|
||||
@ -297,47 +324,88 @@ 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, char *type)
|
||||
int shellExtParsePara(Shell *shell, char *string, char *type, unsigned int *result)
|
||||
{
|
||||
if (type == NULL || (*string == '$' && *(string + 1)))
|
||||
{
|
||||
if (*string == '\'' && *(string + 1))
|
||||
{
|
||||
return (unsigned int)shellExtParseChar(string);
|
||||
*result = (unsigned int)shellExtParseChar(string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string == '-' || (*string >= '0' && *string <= '9'))
|
||||
{
|
||||
return (unsigned int)shellExtParseNumber(string);
|
||||
*result = (unsigned int)shellExtParseNumber(string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string == '$' && *(string + 1))
|
||||
{
|
||||
return shellExtParseVar(shell, string);
|
||||
*result = shellExtParseVar(shell, string);
|
||||
return 0;
|
||||
}
|
||||
else if (*string)
|
||||
{
|
||||
return (unsigned int)shellExtParseString(string);
|
||||
*result = (unsigned int)shellExtParseString(string);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
else
|
||||
{
|
||||
if (strcmp("c", type) == 0)
|
||||
{
|
||||
return (unsigned int)shellExtParseChar(string);
|
||||
*result = (unsigned int)shellExtParseChar(string);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("i", type) == 0
|
||||
|| strcmp("f", type) == 0
|
||||
|| strcmp("p", type) == 0)
|
||||
{
|
||||
return (unsigned int)shellExtParseNumber(string);
|
||||
*result = (unsigned int)shellExtParseNumber(string);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("s", type) == 0)
|
||||
{
|
||||
return (unsigned int)shellExtParseString(string);
|
||||
*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.function(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -356,23 +424,38 @@ int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[])
|
||||
int paramNum = command->attr.attrs.paramNum > (argc - 1) ?
|
||||
command->attr.attrs.paramNum : (argc - 1);
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
char type[8];
|
||||
char type[16];
|
||||
int index = 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");
|
||||
shellPrint(shell, "except: %d, actual: %d\r\n", except, argc - 1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < argc - 1; i++)
|
||||
{
|
||||
#if SHELL_USING_FUNC_SIGNATURE == 1
|
||||
if (command->data.cmd.signature != NULL) {
|
||||
index = shellGetNextArgType(command->data.cmd.signature, index, type);
|
||||
params[i] = shellExtParsePara(shell, argv[i + 1], type);
|
||||
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 */
|
||||
{
|
||||
params[i] = shellExtParsePara(shell, argv[i + 1], NULL);
|
||||
if (shellExtParsePara(shell, argv[i + 1], NULL, ¶ms[i]) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
params[i] = shellExtParsePara(shell, argv[i + 1], NULL);
|
||||
#endif
|
||||
}
|
||||
switch (paramNum)
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ typedef enum
|
||||
NUM_TYPE_FLOAT /**< 浮点型 */
|
||||
} ShellNumType;
|
||||
|
||||
unsigned int shellExtParsePara(Shell *shell, char *string, char *type);
|
||||
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