1
0
mirror of https://github.com/NevermindZZT/letter-shell.git synced 2025-01-01 09:58:41 +08:00

新增 支持自定义类型的函数签名

This commit is contained in:
Letter 2023-04-16 17:18:38 +08:00
parent acd9dceb4e
commit 99b5e6d386
7 changed files with 258 additions and 38 deletions

3
.gitignore vendored
View File

@ -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

View File

@ -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 */

View File

@ -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__ */

View File

@ -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,

View File

@ -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

View File

@ -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), &param) == 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, &params[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, &params[i]) != 0)
{
return -1;
}
}
#else
params[i] = shellExtParsePara(shell, argv[i + 1], NULL);
#endif
}
switch (paramNum)
{

View File

@ -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