更新模板到最新状态

This commit is contained in:
LokLiang
2025-02-13 17:17:07 +08:00
parent 4e259f666c
commit f455349861
40 changed files with 1251 additions and 789 deletions

View File

@@ -21,15 +21,6 @@ void drv_misc_busy_wait(unsigned us);
*/
unsigned *drv_misc_bitband(void *mem);
/**
* @brief 读取 MCU 身份信息的 MD5 值
*
* @param out[out] 输出
* @retval 0 成功
* @retval -1 失败
*/
int drv_misc_read_id_md5(unsigned char out[16]);
/**
* @brief 设置中断向量地址
*
@@ -44,22 +35,6 @@ void drv_misc_set_vector(void *vector);
*/
void *drv_misc_get_vector(void);
/**
* @brief 根据具体平台以尽可能快的速度把内存置0
*
* @param src 内存地址
* @param len 内存长度
*/
void mem_reset(void *src, unsigned len);
/**
* @brief 根据具体平台,以尽可能快的速度复制内存数据
*
* @param dest[out] 目录内存
* @param src 源内存
* @param len 长度
*/
void mem_cpy(void *dest, const void *src, unsigned len);
#ifdef __cplusplus
}

View File

@@ -48,6 +48,7 @@ typedef struct
typedef void (*os_work_fn)(void *arg);
os_state os_work_create_default(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior, os_time_t delay_ms);
os_state os_work_create(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior);
void os_work_delete(os_work_t *work_handle);

File diff suppressed because it is too large Load Diff

View File

@@ -83,8 +83,7 @@ SH_REGISTER_CMD(
### 补全勾子的可用接口
- sh_putstr_quiet()
- sh_cmd_info()
- sh_completion_cmd()
- sh_cmd_test()
- sh_completion_param()
- sh_completion_resource()
- sh_get_cp_result()

View File

@@ -10,6 +10,7 @@
*/
#include "sh.h"
#include "sh_vset.h"
#include <string.h>
#include <stdlib.h>
@@ -127,7 +128,7 @@ static const sh_key_t *_find_key(sh_t *sh_hdl, const char *code)
* 如果当前为模块模式,由优先在模块中查找。
*
* @param dest_reg_struct[out] 保存根命令结构的定义地址
* @param sub_cmd NULL -- 从根命令中遍查找; ! NULL 从已知的父命令节点中查找
* @param sub_cmd NULL -- 从根命令中遍查找; ! NULL 从已知的父命令节点中查找
* @param cmd 单元命令字符串
* @return const sh_cmd_t* NULL -- 没有记录这个命令; ! NULL 找到的命令节点
*/
@@ -399,8 +400,9 @@ static void _insert_str(sh_t *sh_hdl, const char *str)
*/
static void _read_param(int *argc, const char *argv[CONFIG_SH_MAX_PARAM], char *dest, const char *src)
{
bool end = false;
*argc = 0;
while (*argc < CONFIG_SH_MAX_PARAM)
while (end == false && *argc < CONFIG_SH_MAX_PARAM)
{
int len = 0;
@@ -485,6 +487,13 @@ static void _read_param(int *argc, const char *argv[CONFIG_SH_MAX_PARAM], char *
++src;
dest[len] = '\0';
}
else if (dest[len] == '#' && split_char == ' ') /* 注释 */
{
++src;
dest[len] = '\0';
end = true;
}
if (dest[len] == '\0')
{
break;
@@ -719,6 +728,16 @@ int sh_unregister_cmd(const sh_cmd_reg_t *sh_reg)
return -!ret;
}
/**
* @brief 取消所有已注册命令
*/
void sh_unregister_all(sh_t *sh_hdl)
{
sys_pslist_init(&s_cmd_list);
sys_pslist_init(&s_cmd_list_hide);
sys_pslist_init(&sh_hdl->cmd_list);
}
/**
* @brief 注册一组热键
* 适用于动态加载/卸载
@@ -1563,7 +1582,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
while (1)
{
if (sub_cmd == NULL) // 遍根命令链
if (sub_cmd == NULL) // 遍根命令链
{
const sh_cmd_reg_t *sh_reg;
sys_pslist_t *cmd_list[] = {
@@ -1587,7 +1606,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
}
}
}
else // 遍子命令数据
else // 遍子命令数据
{
sub_cmd = sub_cmd->sub_fn.sub_cmd;
for (int i = 0; sub_cmd[i].cmd != NULL; i++)
@@ -1603,7 +1622,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
info->print_count == 0 && // 没有打印任何可选项
err_status != _SH_CMD_STATUS_Incomplete && // 如果正在输出当前模块下的子命令,则只继续补全子命令
print_match == true && // 只打印匹配的备选项
flag_parent == 0 // 目前仅在 _cmd_select_param() 被置起,此时不再遍根命令链
flag_parent == 0 // 目前仅在 _cmd_select_param() 被置起,此时不再遍根命令链
)
{
sub_cmd = NULL; // 使从根命令链重新查找
@@ -1614,7 +1633,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
if (sh_hdl->select_cmd != NULL && // 当前状态为模块模式
info->match_num == 0 && // 没有找到可匹配的命令
err_status != _SH_CMD_STATUS_Incomplete && // 如果正在输出当前模块下的子命令,则只继续补全子命令
sub_cmd != NULL // 未遍过根命令链
sub_cmd != NULL // 未遍过根命令链
)
{
sub_cmd = NULL; // 使从根命令链重新查找
@@ -1739,7 +1758,7 @@ static int _calc_list_algin(sh_cp_info_t *info)
* @param argv 命令字符串指针
* @return sh_cmd_info_t 命令信息
*/
sh_cmd_info_t sh_cmd_info(sh_t *sh_hdl, int argc, const char *argv[])
sh_cmd_info_t sh_cmd_test(sh_t *sh_hdl, int argc, const char *argv[])
{
SYS_ASSERT(sh_hdl != NULL, "");
@@ -1808,12 +1827,12 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
/* 初始化 cmd_info 和 cp_info */
if (_arg_is_end(sh_hdl))
{
cmd_info = sh_cmd_info(sh_hdl, argc, argv);
cmd_info = sh_cmd_test(sh_hdl, argc, argv);
cp_info = _completion_init("");
}
else
{
cmd_info = sh_cmd_info(sh_hdl, --argc, argv);
cmd_info = sh_cmd_test(sh_hdl, --argc, argv);
if (cmd_info.err_status == _SH_CMD_STATUS_Success)
{
cp_info = _completion_init(argv[argc++]);
@@ -1892,7 +1911,7 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
}
else
{
cmd_info = sh_cmd_info(sh_hdl, argc, argv);
cmd_info = sh_cmd_test(sh_hdl, argc, argv);
cp_info = _completion_init(""); // 没有任何命令时直接打印所有根命令
}
@@ -1923,20 +1942,6 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
return sh_hdl->cp_operate;
}
/**
* @brief 根据输入的参数,结合当前命令行的状态,在已注册命令中查找并自执行一次自动补全命令/打印备选命令的全过程
*
* @param argc 命令数量
* @param argv 命令字符串指针
* @return sh_cp_op_t 自动补全命令/打印备选命令的执行结果
*/
sh_cp_op_t sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[])
{
SYS_ASSERT(sh_hdl != NULL, "");
return _sh_completion_cmd(sh_hdl, argc, argv, 0);
}
/**
* @brief 仅在 cp_fn() 中可用,根据当前命令行内容,在给出的参数结构中查找并自动补全参数/打印备选参数的全过程
*
@@ -1998,7 +2003,8 @@ sh_cp_op_t sh_completion_param(sh_t *sh_hdl, const sh_cp_param_t *param)
* 自动补全/打印备行项 将在 cp_fn() 退出后自动执行。
* @ref @c fatfs_shell.c@_scan_files()/@_cmd_df_cp()
*
* @param arg_str 指定已输入的待自动补全的字符串当为NULL时表示按当前命令行自动填充
* @param arg_str 指定已输入的待自动补全的字符串当为NULL时表示按当前命令行自动填充
* 使用场景:在自动补全路径时, arg_str 表示仅关注路径的最后一部分,而不是整个路径,以便于在补全时只显示当前目录下的文件。
* @param res_str 候选字符串
* @param help 帮助描述信息。如果值为 NULL 则不会被打印
*/
@@ -2106,7 +2112,7 @@ void sh_ctrl_tab(sh_t *sh_hdl)
_read_param(&argc, argv, cmd_param, cmd_param);
/* 自动补全命令 */
sh_completion_cmd(sh_hdl, argc, argv);
_sh_completion_cmd(sh_hdl, argc, argv, 0);
}
/**
@@ -2133,7 +2139,7 @@ bool sh_ctrl_enter(sh_t *sh_hdl)
_apply_history(sh_hdl);
/* 根据 argc, argv解析出 info */
sh_cmd_info_t info = sh_cmd_info(sh_hdl, argc, argv);
sh_cmd_info_t info = sh_cmd_test(sh_hdl, argc, argv);
if (info.err_status == _SH_CMD_STATUS_Success)
{
_clear_argv(argc, argv);
@@ -2791,7 +2797,7 @@ SH_CMD_FN(_cmd_select)
{
if (argc)
{
sh_cmd_info_t cmd_info = sh_cmd_info(sh_hdl, argc, argv);
sh_cmd_info_t cmd_info = sh_cmd_test(sh_hdl, argc, argv);
if (cmd_info.err_status == _SH_CMD_STATUS_Incomplete)
{
sh_hdl->select_reg_struct = cmd_info.reg_struct;
@@ -2875,7 +2881,7 @@ SH_CMD_FN(_cmd_exit)
SH_CMD_FN(_cmd_print_help)
{
sh_cmd_info_t info = sh_cmd_info(sh_hdl, argc, argv);
sh_cmd_info_t info = sh_cmd_test(sh_hdl, argc, argv);
if (argc == 0)
{
@@ -2905,7 +2911,7 @@ SH_CMD_FN(_cmd_print_help)
total_len += 3;
for (int i = 1; i <= info.match_count; i++)
{
sh_cmd_info_t tmp = sh_cmd_info(sh_hdl, i, argv);
sh_cmd_info_t tmp = sh_cmd_test(sh_hdl, i, argv);
if (i == 1)
{
@@ -2949,7 +2955,7 @@ SH_CMD_FN(_cmd_print_help)
SH_CMD_CP_FN(_cmd_print_help_param)
{
sh_completion_cmd(sh_hdl, argc, argv);
_sh_completion_cmd(sh_hdl, argc, argv, 0);
}
SH_CMD_FN(_cmd_echo_on)
@@ -3025,6 +3031,13 @@ SH_REGISTER_CMD(
SH_SETUP_CMD("exit", "Exit parent command or disconnect", _cmd_exit, NULL), //
);
static int _vset_init(void)
{
vset_init(&g_uart_handle_vt100, NULL);
return 0;
}
INIT_EXPORT_COMPONENT(_vset_init);
/**
* @brief 用于显式初始化内部函数。
* 当自动初始化函数不适用时,使用此函数可强制初始化内部的一些功能。包含:
@@ -3047,5 +3060,7 @@ void sh_register_external(sh_vprint_fn out)
static uint8_t bank_mem[CONFIG_SH_MAX_LINE_LEN];
sh_config_history_mem(&g_uart_handle_vt100, history_mem, sizeof(history_mem));
sh_config_backup_mem(&g_uart_handle_vt100, bank_mem, sizeof(bank_mem));
_vset_init();
}
}

View File

@@ -244,7 +244,8 @@ typedef struct sh_obj_def // 对象内存结构
* 1. 如果 FUNC 取值为 NULL 时, SUB_NAME 必须指向 SH_DEF_SUB_CMD 定义的子命令列表名;
* 2. 如果 FUNC 取值为函数时:
* 2.1 SUB_NAME 可为 NULL
* 2.1 SUB_NAME 指向 void (*cp_fn)(sh_t *sh_hdl, int argc, const char *argv[]) 表示按 TAB 键时被执行的函数,用于参数补全。
* 2.1 SUB_NAME 指向 void (*cp_fn)(sh_t *sh_hdl, int argc, const char *argv[]) 表示按 TAB 键时被执行的函数,
* 这个函数内部允许执行 cp_fn 应用,用于帮助对 FUNC 命令参数补全。
*
* @verbatim
* @c sh.c
@@ -316,6 +317,7 @@ SH_CMD_CP_FN(_sh_generic_cp_fn) {}
int sh_register_cmd(const sh_cmd_reg_t *sh_reg); // 可用自动初始化宏执行 @ref SH_REGISTER_CMD
int sh_register_cmd_hide(const sh_cmd_reg_t *sh_reg); // 可用自动初始化宏执行 @ref SH_REGISTER_CMD
int sh_unregister_cmd(const sh_cmd_reg_t *sh_reg); // 取消注册一个根命令
void sh_unregister_all(sh_t *sh_hdl); // 取消所有已注册命令
/* 现成终端协议初始化 ----------------------------------------------------------------- */
@@ -337,7 +339,7 @@ void sh_set_prompt(sh_t *sh_hdl, const char *prompt); // 设置提示符
void sh_reset_line(sh_t *sh_hdl); // 清除命令接收缓存
int sh_echo(sh_t *sh_hdl, const char *fmt, ...); // 回显到终端
int sh_echo(sh_t *sh_hdl, const char *fmt, ...); // 回显到终端
sh_parse_t sh_parse_value(const char *str); // 参数工具:解析字符串表示的数值
@@ -347,12 +349,10 @@ int sh_get_cmd_result(sh_t *sh_hdl); // 获取上一条有效命令的返回值
void sh_refresh_line(sh_t *sh_hdl); // 执行刷一次当前命令行显示
sh_cmd_info_t sh_cmd_test(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,完整解析命令并获取命令信息
/* cp_fn 应用 ---------------------------------------------------------------------- */
sh_cmd_info_t sh_cmd_info(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,获取完全匹配的命令信息
sh_cp_op_t sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,在已注册命令中查找并自动补全命令
sh_cp_op_t sh_completion_param(sh_t *sh_hdl, const sh_cp_param_t *param); // 仅在 cp_fn() 中可用,根据当前命令行内容,在给出的参数结构中查找并自动补全参数。参数允许为 NULL
void sh_completion_resource(sh_t *sh_hdl, const char *arg_str, const char *res_str, const char *help); // 仅在 cp_fn() 中可用,根据当前命令行内容,逐个给出可供查找的提示符。内部将根据所提供的数据自动补全

View File

@@ -25,11 +25,11 @@
#define _TYPE_FLAG_FLOAT (1 << 2)
#define _TYPE_FLAG_STRING (1 << 3)
#define _PARAM_CB() \
do \
{ \
if (param->cb) \
param->cb(s_sh_hdl, &value); \
#define _PARAM_CB() \
do \
{ \
if (cb) \
cb(s_sh_hdl, &value); \
} while (0)
static sh_t *s_sh_hdl;
@@ -40,19 +40,19 @@ static const sh_vset_param_t *_find_option(const char *input, const sh_vset_para
static bool _do_completing_option(sh_t *sh_hdl, int argc, const char *argv[], const sh_vset_param_t *p, unsigned size);
static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, unsigned size);
static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, unsigned int low, unsigned int high);
static int _set_dest_integer(const __vset_param_t *param, signed int value, signed int low, signed int high);
static int _set_dest_float(const __vset_param_t *param, float value, float low, float high);
static int _set_dest_string(const __vset_param_t *param, const char *str, unsigned bufsize);
static int _set_dest_enum(const __vset_param_t *param, const char *value, int type_flag);
static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high);
static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high);
static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high);
static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize);
static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag);
static unsigned int _get_unsigned(const __vset_param_t *param);
static signed int _get_integer(const __vset_param_t *param);
static float _get_float(const __vset_param_t *param);
static char *_get_string(const __vset_param_t *param);
static unsigned int _get_unsigned(void *dest, __type_attr_t attr);
static signed int _get_integer(void *dest, __type_attr_t attr);
static float _get_float(void *dest, __type_attr_t attr);
static char *_get_string(void *dest, __type_attr_t attr);
static int _enum_format(char *enum_buf, int buf_len, const char *enum_str);
static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf);
static int _get_enum_by_param(const __vset_param_t *param, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp);
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp);
/**
* @brief s_attr_to_type_tbl
@@ -78,12 +78,12 @@ static int const s_attr_to_type_tbl[] = {
* @brief 初始化设置
*
* @param sh_hdl 设置 shell 的句柄
* @param cb 当任意一个值被修改时回调此函数,可设为 NULL
* @param global_cb 当任意一个值被修改时回调此函数,可设为 NULL
*/
void vset_init(sh_t *sh_hdl, vset_global_cb cb)
void vset_init(sh_t *sh_hdl, vset_global_cb global_cb)
{
s_sh_hdl = sh_hdl;
s_global_cb = cb;
s_global_cb = global_cb;
}
/**
@@ -92,10 +92,10 @@ void vset_init(sh_t *sh_hdl, vset_global_cb cb)
*/
void vset_force_cb(void)
{
vset_global_cb cb = s_global_cb;
if (cb)
vset_global_cb global_cb = s_global_cb;
if (global_cb)
{
cb(s_sh_hdl);
global_cb(s_sh_hdl);
}
}
@@ -147,6 +147,10 @@ int vset_option_set(sh_t *sh_hdl, int *argc, const char *argv[], const sh_vset_p
{
flag = true;
sh_echo(s_sh_hdl, "选项: %s\r\n", pset->option);
if (pset->help)
{
sh_echo(s_sh_hdl, "说明: %s\r\n", pset->help);
}
}
}
@@ -235,22 +239,22 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
}
}
int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int low, unsigned int high)
int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
if (s_sh_hdl == NULL)
{
return -1;
}
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_UNSIGNED)
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_UNSIGNED)
{
sh_echo(s_sh_hdl, "待设置的参数类型不是正整数\r\n");
return -1;
@@ -271,7 +275,7 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
low ^= high;
}
sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
sh_echo(s_sh_hdl, "当前值: %u\r\n", _get_unsigned(param));
sh_echo(s_sh_hdl, "当前值: %u\r\n", _get_unsigned(dest, attr));
return 0;
}
@@ -279,7 +283,7 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
switch (pv.type)
{
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
return _set_dest_unsigned(param, pv.value.val_unsigned, low, high);
return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, low, high);
default:
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入正整数\r\n", argv[0]);
@@ -287,22 +291,22 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
}
}
int vset_integer(const __vset_param_t *param, const char *argv[], signed int low, signed int high)
int vset_integer(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], signed int low, signed int high)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
if (s_sh_hdl == NULL)
{
return -1;
}
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_INTEGER)
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_INTEGER)
{
sh_echo(s_sh_hdl, "待设置的参数类型不是带符号整数\r\n");
return -1;
@@ -323,7 +327,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
low ^= high;
}
sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
sh_echo(s_sh_hdl, "当前值: %d\r\n", _get_integer(param));
sh_echo(s_sh_hdl, "当前值: %d\r\n", _get_integer(dest, attr));
return 0;
}
@@ -331,7 +335,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
switch (pv.type)
{
case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
return _set_dest_integer(param, pv.value.val_integer, low, high);
return _set_dest_integer(dest, attr, cb, pv.value.val_integer, low, high);
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
if (pv.value.val_unsigned > (1u << (sizeof(pv.value.val_unsigned) * 8 - 1)) - 1)
@@ -339,7 +343,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
sh_echo(s_sh_hdl, "参数 %u 溢出\r\n", pv.value.val_unsigned);
return -1;
}
return _set_dest_integer(param, pv.value.val_unsigned, low, high);
return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, low, high);
default:
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入整数\r\n", argv[0]);
@@ -347,22 +351,22 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
}
}
int vset_float(const __vset_param_t *param, const char *argv[], float low, float high)
int vset_float(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], float low, float high)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
if (s_sh_hdl == NULL)
{
return -1;
}
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_FLOAT)
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_FLOAT)
{
sh_echo(s_sh_hdl, "待设置的参数类型不是浮点数\r\n");
return -1;
@@ -383,7 +387,7 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
high = tmp;
}
sh_echo(s_sh_hdl, "有效范围: %f .. %f\r\n", low, high);
sh_echo(s_sh_hdl, "当前值: %f\r\n", _get_float(param));
sh_echo(s_sh_hdl, "当前值: %f\r\n", _get_float(dest, attr));
return 0;
}
@@ -391,13 +395,13 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
switch (pv.type)
{
case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
return _set_dest_float(param, pv.value.val_integer, low, high);
return _set_dest_float(dest, attr, cb, pv.value.val_integer, low, high);
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
return _set_dest_float(param, pv.value.val_unsigned, low, high);
return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, low, high);
case _PARSE_TYPE_FLOAT: // 解析出的参数格式是浮点数
return _set_dest_float(param, pv.value.val_float, low, high);
return _set_dest_float(dest, attr, cb, pv.value.val_float, low, high);
default:
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入数值\r\n", argv[0]);
@@ -405,22 +409,22 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
}
}
int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
int vset_str(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned bufsize)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
if (s_sh_hdl == NULL)
{
return -1;
}
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_STRING)
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_STRING)
{
sh_echo(s_sh_hdl, "待设置的参数类型不是字符串\r\n");
return -1;
@@ -435,7 +439,7 @@ int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
if (strcmp(argv[0], "?") == 0)
{
sh_echo(s_sh_hdl, "最大长度: %d\r\n", bufsize - 1);
sh_echo(s_sh_hdl, "当前值: %s\r\n", _get_string(param));
sh_echo(s_sh_hdl, "当前值: %s\r\n", _get_string(dest, attr));
return 0;
}
@@ -445,21 +449,21 @@ int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
return -1;
}
return _set_dest_string(param, argv[0], bufsize);
return _set_dest_string(dest, attr, cb, argv[0], bufsize);
}
int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_str)
int vset_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], const char *enum_str)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
if (s_sh_hdl == NULL)
{
return -1;
}
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
@@ -484,7 +488,7 @@ int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_
if (strcmp(argv[0], "?") == 0)
{
sh_echo(s_sh_hdl, "可选值:\r\n");
_get_enum_by_param(param, &match_key, &match_value, enum_buf, true, false);
_get_enum_by_param(dest, attr, &match_key, &match_value, enum_buf, true, false);
if (match_value)
{
sh_echo(s_sh_hdl, "当前值:\t%s\r\n", match_key);
@@ -504,7 +508,7 @@ int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_
return -1;
}
return _set_dest_enum(param, match_value, type_flag);
return _set_dest_enum(dest, attr, cb, match_value, type_flag);
}
void vset_cp_enum(int argc, bool flag, const char *enum_str)
@@ -528,15 +532,10 @@ void vset_cp_enum(int argc, bool flag, const char *enum_str)
return;
}
__vset_param_t param = {
.dest = enum_buf,
.attr = __GENERIC_ATTR(enum_buf),
};
/* 分割字符串 str_buf 并穷举匹配到的值,输出 match_key, match_value, type_flag */
char *match_key = NULL;
char *match_value = NULL;
_get_enum_by_param(&param, &match_key, &match_value, enum_buf, false, true);
_get_enum_by_param(enum_buf, __GENERIC_ATTR(enum_buf), &match_key, &match_value, enum_buf, false, true);
}
else
{
@@ -667,11 +666,9 @@ static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, un
return false;
}
static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, unsigned int low, unsigned int high)
static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high)
{
void *dest = param->dest;
__type_attr_t attr = param->attr;
vset_global_cb cb = NULL;
vset_global_cb global_cb = NULL;
int ret = -1;
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
@@ -703,7 +700,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
{
_PARAM_CB();
*((uint8_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -721,7 +718,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
{
_PARAM_CB();
*((uint16_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -733,7 +730,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
{
_PARAM_CB();
*((uint32_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -745,7 +742,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
{
_PARAM_CB();
*((uint64_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -755,23 +752,21 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
return -1;
}
if (cb)
if (global_cb)
{
cb(s_sh_hdl);
global_cb(s_sh_hdl);
}
return ret;
}
static int _set_dest_integer(const __vset_param_t *param, signed int value, signed int low, signed int high)
static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high)
{
#define _MAX_S8 127
#define _MIN_S8 -128
#define _MAX_S16 32767
#define _MIN_S16 -32768
void *dest = param->dest;
__type_attr_t attr = param->attr;
vset_global_cb cb = NULL;
vset_global_cb global_cb = NULL;
int ret = -1;
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
@@ -803,7 +798,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((char *)dest) = data;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -821,7 +816,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((bool *)dest) = data;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -841,7 +836,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((int8_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -861,7 +856,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((int16_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -873,7 +868,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((int32_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -885,7 +880,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
{
_PARAM_CB();
*((int64_t *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -895,18 +890,16 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
return -1;
}
if (cb)
if (global_cb)
{
cb(s_sh_hdl);
global_cb(s_sh_hdl);
}
return ret;
}
static int _set_dest_float(const __vset_param_t *param, float value, float low, float high)
static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high)
{
void *dest = param->dest;
__type_attr_t attr = param->attr;
vset_global_cb cb = NULL;
vset_global_cb global_cb = NULL;
int ret = -1;
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
@@ -932,7 +925,7 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
{
_PARAM_CB();
*((float *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -943,7 +936,7 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
{
_PARAM_CB();
*((double *)dest) = value;
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -953,19 +946,17 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
return -1;
}
if (cb)
if (global_cb)
{
cb(s_sh_hdl);
global_cb(s_sh_hdl);
}
return ret;
}
static int _set_dest_string(const __vset_param_t *param, const char *str, unsigned bufsize)
static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize)
{
void *dest = param->dest;
int str_size = strlen(str) + 1;
__type_attr_t attr = param->attr;
vset_global_cb cb = NULL;
vset_global_cb global_cb = NULL;
int ret = -1;
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
@@ -974,6 +965,7 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
if (str_size > bufsize)
{
sh_echo(s_sh_hdl, "注意: '%s' 大于最大长度 %d\r\n", str, bufsize - 1);
str_size = bufsize;
}
switch (attr)
@@ -982,14 +974,15 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
memset(dest, 0, bufsize);
if (memcmp(dest, str, str_size))
{
if (param->cb)
if (cb)
{
char value[0x100];
memcpy(dest, str, str_size);
char value[str_size + 1];
memset(value, 0, str_size + 1);
memcpy(value, str, str_size);
_PARAM_CB();
}
memcpy(dest, str, str_size);
cb = s_global_cb;
global_cb = s_global_cb;
}
ret = 0;
break;
@@ -998,17 +991,17 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
return -1;
}
if (cb)
if (global_cb)
{
cb(s_sh_hdl);
global_cb(s_sh_hdl);
}
return ret;
}
static int _set_dest_enum(const __vset_param_t *param, const char *value, int type_flag)
static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag)
{
sh_parse_t pv = sh_parse_value(value);
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
{
@@ -1020,7 +1013,7 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
switch (pv.type)
{
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
return _set_dest_unsigned(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
default:
return -1;
@@ -1038,10 +1031,10 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
switch (pv.type)
{
case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
return _set_dest_integer(param, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
return _set_dest_integer(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
return _set_dest_integer(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
default:
return -1;
@@ -1059,13 +1052,13 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
switch (pv.type)
{
case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
return _set_dest_float(param, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
return _set_dest_float(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
return _set_dest_float(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
case _PARSE_TYPE_FLOAT: // 当前匹配的参数格式是浮点数
return _set_dest_float(param, pv.value.val_float, pv.value.val_float, pv.value.val_float);
return _set_dest_float(dest, attr, cb, pv.value.val_float, pv.value.val_float, pv.value.val_float);
default:
return -1;
@@ -1075,96 +1068,96 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
{
return _set_dest_string(param, value, strlen(value) + 1);
return _set_dest_string(dest, attr, cb, value, strlen(value) + 1);
}
break;
default:
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
return -1;
}
static signed int _get_integer(const __vset_param_t *param)
static signed int _get_integer(void *dest, __type_attr_t attr)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
switch (param->attr)
switch (attr)
{
case __TYPE_ATTR_CHR:
return *((char *)param->dest);
return *((char *)dest);
case __TYPE_ATTR_BOOL:
return *((bool *)param->dest);
return *((bool *)dest);
case __TYPE_ATTR_S8:
return *((int8_t *)param->dest);
return *((int8_t *)dest);
case __TYPE_ATTR_S16:
return *((int16_t *)param->dest);
return *((int16_t *)dest);
case __TYPE_ATTR_S32:
return *((int32_t *)param->dest);
return *((int32_t *)dest);
case __TYPE_ATTR_S64:
return *((int64_t *)param->dest);
return *((int64_t *)dest);
default:
return -1;
}
}
static float _get_float(const __vset_param_t *param)
static float _get_float(void *dest, __type_attr_t attr)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
switch (param->attr)
switch (attr)
{
case __TYPE_ATTR_FLOAT:
return *((float *)param->dest);
return *((float *)dest);
case __TYPE_ATTR_DOUBLE:
return *((double *)param->dest);
return *((double *)dest);
default:
return -1;
}
}
static char *_get_string(const __vset_param_t *param)
static char *_get_string(void *dest, __type_attr_t attr)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
return param->dest;
return dest;
}
static unsigned int _get_unsigned(const __vset_param_t *param)
static unsigned int _get_unsigned(void *dest, __type_attr_t attr)
{
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
switch (param->attr)
switch (attr)
{
case __TYPE_ATTR_U8:
return *((uint8_t *)param->dest);
return *((uint8_t *)dest);
case __TYPE_ATTR_U16:
return *((uint16_t *)param->dest);
return *((uint16_t *)dest);
case __TYPE_ATTR_U32:
return *((uint32_t *)param->dest);
return *((uint32_t *)dest);
case __TYPE_ATTR_U64:
return *((uint64_t *)param->dest);
return *((uint64_t *)dest);
default:
return -1;
@@ -1318,37 +1311,37 @@ static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf)
* _TYPE_FLAG_FLOAT 掩码表示在 enum_buf 中包含浮点数
* _TYPE_FLAG_STRING 掩码表示在 enum_buf 中包含字符串
*/
static int _get_enum_by_param(const __vset_param_t *param, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp)
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp)
{
char param_value_str[0x100];
int type_flag = 0; // 在 match_value 中出现过的数据类型
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
{
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%d", _get_integer(param));
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%d", _get_integer(dest, attr));
break;
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%u", _get_unsigned(param));
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%u", _get_unsigned(dest, attr));
break;
case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%f", _get_float(param));
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%f", _get_float(dest, attr));
break;
case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%s", _get_string(param));
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%s", _get_string(dest, attr));
break;
default:
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
return -1;
}
param_value_str[__ARR_SIZE(param_value_str) - 1] = '\0';
@@ -1378,7 +1371,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
type_flag |= _TYPE_FLAG_UNSIGNED;
if (*match_key == NULL)
{
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%u", pv.value.val_unsigned);
@@ -1402,7 +1395,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
type_flag |= _TYPE_FLAG_INTEGER;
if (*match_key == NULL)
{
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%d", pv.value.val_integer);
@@ -1423,7 +1416,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
type_flag |= _TYPE_FLAG_FLOAT;
if (*match_key == NULL)
{
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%f", (float)pv.value.val_float);
@@ -1481,7 +1474,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
token = strtok_r(NULL, ",", &save_token);
}
switch (s_attr_to_type_tbl[param->attr])
switch (s_attr_to_type_tbl[attr])
{
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
{

View File

@@ -27,11 +27,11 @@
* - @b PSET_CP 根据一个已定义的 const sh_vset_param_t* 执行自动补选项
*
* 实例1: 以下这些函数可被 SH_SETUP_CMD 中定义的 FUNC 执行,或者作为 sh_vset_param_t::set_func 的成员
* static int _value_set_u8(const char *argv[]) { SET_VAR(&var_u8, 1, 200); }
* static int _value_set_s16(const char *argv[]) { SET_VAR(&var_s16, -1000, 1000); }
* static int _value_set_float(const char *argv[]) { SET_VAR(&var_float, -1000, var_u8); }
* static int _value_set_str(const char *argv[]) { SET_VAR(&var_str, 0, 0); }
* static int _value_set_enum(const char *argv[]) { SET_ENUM(&var_s32, "enable=1,disable=0"); }
* static int _value_set_u8(const char *argv[]) { return SET_VAR(&var_u8, 1, 200); }
* static int _value_set_s16(const char *argv[]) { return SET_VAR(&var_s16, -1000, 1000); }
* static int _value_set_float(const char *argv[]) { return SET_VAR(&var_float, -1000, var_u8); }
* static int _value_set_str(const char *argv[]) { return SET_VAR(&var_str, 0, 0); }
* static int _value_set_enum(const char *argv[]) { return SET_ENUM(&var_s32, "enable=1,disable=0"); }
*
* 实例2: 实现选项+参数的格式
* static sh_vset_param_t const s_param_template[] = {
@@ -77,14 +77,6 @@ typedef enum
*/
typedef void (*vset_cb)(sh_t *sh_hdl, void *new_value);
/* 待设置变量数据结构 */
typedef struct
{
void *dest;
__type_attr_t attr;
vset_cb cb;
} __vset_param_t;
#define __GENERIC_ATTR(VAR) (__builtin_types_compatible_p(__typeof(VAR), char) ? __TYPE_ATTR_CHR \
: __builtin_types_compatible_p(__typeof(VAR), volatile char) ? __TYPE_ATTR_CHR \
: __builtin_types_compatible_p(__typeof(VAR), bool) ? __TYPE_ATTR_BOOL \
@@ -122,71 +114,41 @@ typedef struct // 用于长选项设置的描述结构
const char *enum_str; // 仅在类型为 vset_enum_fn 时有效,为对应的选项提供可选的补全参数选项,值为 NULL 或 "" 时默认候选参数为 '?'
} sh_vset_param_t;
int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int low, unsigned int high);
int vset_integer(const __vset_param_t *param, const char *argv[], signed int low, signed int high);
int vset_float(const __vset_param_t *param, const char *argv[], float low, float high);
int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize);
int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_str);
int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high);
int vset_integer(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], signed int low, signed int high);
int vset_float(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], float low, float high);
int vset_str(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned bufsize);
int vset_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], const char *enum_str);
void vset_cp_enum(int argc, bool flag, const char *enum_str);
int vset_option_set(sh_t *sh_hdl, int *argc, const char *argv[], const sh_vset_param_t *p, unsigned size);
bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const sh_vset_param_t *p, unsigned size);
/* 自动分析并设置变量的值,带设置回调 */
#define SET_VAR_CB(NAME, LOW, HIGH, CB) \
do \
{ \
static __vset_param_t const param = { \
.dest = NAME, \
.attr = __GENERIC_ATTR(*(NAME)), \
.cb = CB, \
}; \
if ( \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U8 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U16 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U32 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U64) \
{ \
return vset_unsigned(&param, argv, LOW, HIGH); \
} \
else if ( \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_CHR || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_BOOL || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S8 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S16 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S32 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S64) \
{ \
return vset_integer(&param, argv, LOW, HIGH); \
} \
else if ( \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_FLOAT || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_DOUBLE) \
{ \
return vset_float(&param, argv, LOW, HIGH); \
} \
else if ( \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_STR) \
{ \
return vset_str(&param, argv, sizeof(*(NAME))); \
} \
else \
{ \
return -1; \
} \
} while (0)
#define SET_VAR_CB(NAME, LOW, HIGH, CB) \
((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U8 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U16 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U32 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U64) \
? vset_unsigned(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_CHR || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_BOOL || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S8 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S16 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S32 || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S64) \
? vset_integer(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_FLOAT || \
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_DOUBLE) \
? vset_float(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_STR) \
? vset_str(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, sizeof(*(NAME))) \
: -1))))
/* 设置数据类型为 枚举型 的变量,带设置回调 */
#define SET_ENUM_CB(NAME, ENUM_STR, CB) \
do \
{ \
static __vset_param_t const param = { \
.dest = NAME, \
.attr = __GENERIC_ATTR(*(NAME)), \
.cb = CB, \
}; \
return vset_enum(&param, argv, ENUM_STR); \
} while (0)
(vset_enum(NAME, __GENERIC_ATTR(*(NAME)), CB, \
argv, ENUM_STR))
/* 自动分析并设置变量的值 */
#define SET_VAR(NAME, LOW, HIGH) SET_VAR_CB(NAME, LOW, HIGH, NULL)
@@ -194,16 +156,6 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
/* 设置数据类型为 枚举型 的变量 */
#define SET_ENUM(NAME, ENUM_STR) SET_ENUM_CB(NAME, ENUM_STR, NULL)
/* 对应 SET_VAR 所设置的变量的可用自动补全函数 */
#define SET_CP_VAR() \
do \
{ \
if (argc + flag == 1) \
{ \
sh_completion_resource(sh_hdl, NULL, "? ", NULL); \
} \
} while (0)
/* 对应 SET_ENUM 所设置的变量的可用自动补全函数 */
#define SET_CP_ENUM(ENUM_STR) \
do \
@@ -216,8 +168,67 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
typedef void (*vset_global_cb)(sh_t *sh_hdl);
void vset_init(sh_t *sh_hdl, vset_global_cb cb);
void vset_init(sh_t *sh_hdl, vset_global_cb global_cb);
void vset_force_cb(void);
/**
* @note 对本函数的进一步说明。
*
* 在 sh 模块设计完成后,发现除了用于执行某些定义好的的操作外,更多情况下是用于设置变量。
* 为了更好的支持这种需求,本模块应运而生。
* 本模块的设计目标是通过命令行的形式设置变量,同时支持对变量的取值范围限制。
* 本模块的设计思路是通过宏定义,将变量的类型和取值范围传递给 SET_VAR() 或 SET_ENUM() 进行具体的设置。
* 本模块主要使用到的宏定义有:
* - @b SET_VAR()
* - @b SET_ENUM()
* - @b SET_CP_ENUM()
* - @b PSET_FN()
* - @b PSET_CP()
*
* 这些都是根据实际的使用场景定义的。
* 根据 sh 模块的主体功能,分为两个部分(可在使用 SH_SETUP_CMD() 定义命令时的第三和第四个参数来体现):
* - 一个是用于执行某些操作的函数。
* - 另一个是用于像 bash 一样,按 Tab 键自动补全的函数。
* 对于前者,可在实际执行函数中直接使用 SET_VAR() 或 SET_ENUM() 来设置变量。
* 对于后者,可在实际补全函数中直接使用 SET_CP_ENUM() 来提示可选项和可选值。
*
* 为什么设置宏要分两种?
* SET_VAR() 和 SET_ENUM() 的本质区别是, SET_VAR() 用于设置无符号整形、带符号整型、单精度的浮点数和字符串的变量,它们的取值范围是连续的。
* 值得注意的是: SET_VAR() 也支持字符串的设置,但是字符串的取值范围是无法限制的。
* 而 SET_ENUM() 用于设置枚举型的变量,它的取值范围是允许离散的,并且可用一些字符串来表示具体的取值。
*
* 为什么补全函数只有 SET_CP_ENUM()
* 因为 SET_ENUM() 的取值范围是离散的,所以需要一个额外的函数来提供可选的补全参数选项。对于连续的取值范围,不需要这个函数。
*
* 设置宏较为独立,虽然它是为了配合本模块而设计的,但是它的功能是独立的,在传输的参数中的 sh_hdl 主要是为了回显一些错误信息。
* 补全宏则是为了配合 sh 模块的补全功能而设计的,它的功能是为了提供可选的补全参数选项。
*
* 小结:
* - SET_VAR() 和 SET_ENUM() 用于设置变量的值。
* - SET_CP_ENUM() 用于提供可选的补全参数选项。
* - 它们可能在命令执行函数和补全函数中直接使用。
*
* 接着新问题来了,使用 SET_VAR() 或 SET_ENUM() 时,只能设置一个变量,如果这个命令要包含多种设置,该怎么办?
* 为了解决这个问题,本模块引入了 sh_vset_param_t 结构体,它是一个数组,用于描述支待的待设置变量的具体类型。
* 它统一描述了该命令的所有选项,包括选项的名称、选项的描述、选项的设置函数和选项的可选值。
* 在命令执行函数和补全函数中,通过调用 PSET_FN() 和 PSET_CP() 来执行具体的设置。
* 这两个宏的参数就是 sh_vset_param_t 结构体的数组。
* 这个结构体的定义是固定的,它的成员包括:
* - 选项,如 "--value"
* - 对该选项的描述
* - 与 option 对应的,使用宏 SET_VAR() 或 SET_ENUM() 设置变量的函数。如果值为 NULL 表示该选项无参数,同时对应的输入参数被保留
* - 仅在类型为 vset_enum_fn 时有效,为对应的选项提供可选的补全参数选项,值为 NULL 或 "" 时默认候选参数为 '?'
* 通过设置这个结构,便可得到一个完整的命令格式: <命令> [选项 <参数>] [选项 <参数>] ...
*
* 其他一些细节:
* - 这些宏都是以最简约的形式定义的,以便在有大量数据的情况下降低阅读难度。在一些特殊情况下,可根据这些提及到的宏的定义展开理解再灵活使用。
*
* 总结:
* SET_VAR(), SET_ENUM() 和 SET_CP_ENUM() 是用于单个变量的设置和补全,它们可以直接在命令执行函数和补全函数中使用,也可以在 sh_vset_param_t 结构体中对应的函数使用。
* PSET_FN() 和 PSET_CP() 是用于多个变量的设置和补全,它们可以直接在命令执行函数和补全函数中被调用。
* sh_vset_param_t 结构体是用于描述支待的待设置变量的具体类型,它可以直接在命令执行函数和补全函数中被调用。
*
*/
#endif

View File

@@ -43,6 +43,12 @@ static test_single_t const test_tab_ipc[] = {
os_test_pipe,
};
INIT_EXPORT_APP(99)
{
SYS_LOG_INF("success");
os_thread_sleep(200);
}
void os_test_main(void)
{
rand(); // rand() 用到 malloc()