mirror of
https://github.com/MaJerle/lwshell.git
synced 2025-02-06 13:08:22 +08:00
feat: Move static commands to lwshell instance -> allow multiple shell instances
This commit is contained in:
parent
e7e696420d
commit
b52c41526e
2
TODO.md
2
TODO.md
@ -1,3 +1,5 @@
|
||||
# TODO
|
||||
|
||||
- Add option to decide for delimiter string (`\r\n`)
|
||||
- Improve helper functions for number parsing (do not use math.h to reduce memory footprint)
|
||||
- Add option to statically allocate array of commands and assign them to parser -> use of flash memory on embedded systems
|
@ -82,17 +82,6 @@ typedef int32_t (*lwshell_cmd_fn)(int32_t argc, char** argv);
|
||||
*/
|
||||
typedef void (*lwshell_output_fn)(const char* str, struct lwshell* lwobj);
|
||||
|
||||
/**
|
||||
* \brief LwSHELL main structure
|
||||
*/
|
||||
typedef struct lwshell {
|
||||
lwshell_output_fn out_fn; /*!< Optional output function */
|
||||
char buff[LWSHELL_CFG_MAX_INPUT_LEN + 1]; /*!< Shell command input buffer */
|
||||
size_t buff_ptr; /*!< Buffer pointer for input */
|
||||
int32_t argc; /*!< Number of arguments parsed in command */
|
||||
char* argv[LWSHELL_CFG_MAX_CMD_ARGS]; /*!< Array of all arguments */
|
||||
} lwshell_t;
|
||||
|
||||
/**
|
||||
* \brief Shell command structure
|
||||
*/
|
||||
@ -102,38 +91,86 @@ typedef struct {
|
||||
const char* desc; /*!< Command description for help */
|
||||
} lwshell_cmd_t;
|
||||
|
||||
lwshellr_t lwshell_init(void);
|
||||
lwshellr_t lwshell_set_output_fn(lwshell_output_fn out_fn);
|
||||
lwshellr_t lwshell_register_cmd(const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc);
|
||||
lwshellr_t lwshell_input(const void* in_data, size_t len);
|
||||
/**
|
||||
* \brief LwSHELL main structure
|
||||
*/
|
||||
typedef struct lwshell {
|
||||
lwshell_output_fn out_fn; /*!< Optional output function */
|
||||
char buff[LWSHELL_CFG_MAX_INPUT_LEN + 1]; /*!< Shell command input buffer */
|
||||
size_t buff_ptr; /*!< Buffer pointer for input */
|
||||
int32_t argc; /*!< Number of arguments parsed in command */
|
||||
char* argv[LWSHELL_CFG_MAX_CMD_ARGS]; /*!< Array of all arguments */
|
||||
lwshell_cmd_t cmds[LWSHELL_CFG_MAX_CMDS]; /*!< Shell registered commands */
|
||||
size_t cmds_cnt; /*!< Number of registered commands */
|
||||
} lwshell_t;
|
||||
|
||||
lwshellr_t lwshell_init_ex(lwshell_t* lwobj);
|
||||
lwshellr_t lwshell_set_output_fn_ex(lwshell_t* lwobj, lwshell_output_fn out_fn);
|
||||
lwshellr_t lwshell_register_cmd_ex(lwshell_t* lwobj, const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc);
|
||||
lwshellr_t lwshell_input_ex(lwshell_t* lwobj, const void* in_data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Initialize shell interface
|
||||
* \note It applies to default shell instance
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
#define lwshell_init() lwshell_init_ex(NULL)
|
||||
|
||||
/**
|
||||
* \brief Set output function to use to print data from library to user
|
||||
* \note It applies to default shell instance
|
||||
* \param[in] out_fn: Output function to print library data.
|
||||
* Set to `NULL` to disable the feature
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
#define lwshell_set_output_fn(out_fn) lwshell_set_output_fn_ex(NULL, (out_fn))
|
||||
|
||||
/**
|
||||
* \brief Register new command to shell
|
||||
* \note It applies to default shell instance
|
||||
* \param[in] cmd_name: Command name. This one is used when entering shell command
|
||||
* \param[in] cmd_fn: Function to call on command match
|
||||
* \param[in] desc: Custom command description
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
#define lwshell_register_cmd(cmd_name, cmd_fn, desc) lwshell_register_cmd_ex(NULL, (cmd_name), (cmd_fn), (desc))
|
||||
|
||||
/**
|
||||
* \brief Input data to shell processing
|
||||
* \note It applies to default shell instance
|
||||
* \param[in] in_data: Input data to process
|
||||
* \param[in] len: Length of data for input
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
#define lwshell_input(in_data, len) lwshell_input_ex(NULL, (in_data), (len))
|
||||
|
||||
/**
|
||||
* \brief Parse input string as `integer`
|
||||
* \param[in] str: String to parse
|
||||
* \return String parsed as integer
|
||||
*/
|
||||
#define lwshell_parse_int(str) atoi(str)
|
||||
#define lwshell_parse_int(str) atoi(str)
|
||||
|
||||
/**
|
||||
* \brief Parse input string as `double`
|
||||
* \param[in] str: String to parse
|
||||
* \return String parsed as `double`
|
||||
*/
|
||||
#define lwshell_parse_double(str) atof(str)
|
||||
#define lwshell_parse_double(str) atof(str)
|
||||
|
||||
/**
|
||||
* \brief Parse input string as `long`
|
||||
* \param[in] str: String to parse
|
||||
* \return String parsed as `long`
|
||||
*/
|
||||
#define lwshell_parse_long(str) atol(str)
|
||||
#define lwshell_parse_long(str) atol(str)
|
||||
|
||||
/**
|
||||
* \brief Parse input string as `long long`
|
||||
* \param[in] str: String to parse
|
||||
* \return String parsed as `long long`
|
||||
*/
|
||||
#define lwshell_parse_long_long(str) atoll(str)
|
||||
#define lwshell_parse_long_long(str) atoll(str)
|
||||
|
||||
/**
|
||||
* \}
|
||||
|
@ -59,8 +59,6 @@
|
||||
#endif
|
||||
|
||||
/* Array of all commands */
|
||||
static lwshell_cmd_t cmds[LWSHELL_CFG_MAX_CMDS];
|
||||
static size_t cmds_cnt;
|
||||
static lwshell_t shell;
|
||||
|
||||
/* Get shell instance from input */
|
||||
@ -92,8 +90,6 @@ prv_parse_input(lwshell_t* lwobj) {
|
||||
size_t s_len;
|
||||
char* str;
|
||||
|
||||
lwobj = LWSHELL_GET_LWOBJ(lwobj);
|
||||
|
||||
/* Check string length and compare with buffer pointer */
|
||||
if ((s_len = strlen(lwobj->buff)) != lwobj->buff_ptr) {
|
||||
return;
|
||||
@ -157,14 +153,15 @@ prv_parse_input(lwshell_t* lwobj) {
|
||||
}
|
||||
|
||||
/* Check for command */
|
||||
if (lwobj->argc > 0 && cmds_cnt > 0) {
|
||||
if (lwobj->argc > 0 && lwobj->cmds_cnt > 0) {
|
||||
lwshell_cmd_t* c = NULL;
|
||||
size_t arg_len = strlen(lwobj->argv[0]);
|
||||
|
||||
/* Process all commands */
|
||||
for (size_t i = 0; i < cmds_cnt; ++i) {
|
||||
if (arg_len == strlen(cmds[i].name) && strncmp(cmds[i].name, lwobj->argv[0], arg_len) == 0) {
|
||||
c = &cmds[i];
|
||||
for (size_t i = 0; i < lwobj->cmds_cnt; ++i) {
|
||||
if (arg_len == strlen(lwobj->cmds[i].name)
|
||||
&& strncmp(lwobj->cmds[i].name, lwobj->argv[0], arg_len) == 0) {
|
||||
c = &lwobj->cmds[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -182,10 +179,10 @@ prv_parse_input(lwshell_t* lwobj) {
|
||||
#if LWSHELL_CFG_USE_ENABLE_LIST_CMD
|
||||
} else if (strncmp(lwobj->argv[0], "listcmd", 7) == 0) {
|
||||
LWSHELL_OUTPUT(lwobj, "List of registered commands\r\n");
|
||||
for (size_t i = 0; i < cmds_cnt; ++i) {
|
||||
LWSHELL_OUTPUT(lwobj, cmds[i].name);
|
||||
for (size_t i = 0; i < lwobj->cmds_cnt; ++i) {
|
||||
LWSHELL_OUTPUT(lwobj, lwobj->cmds[i].name);
|
||||
LWSHELL_OUTPUT(lwobj, "\t\t\t");
|
||||
LWSHELL_OUTPUT(lwobj, cmds[i].desc);
|
||||
LWSHELL_OUTPUT(lwobj, lwobj->cmds[i].desc);
|
||||
LWSHELL_OUTPUT(lwobj, "\r\n");
|
||||
}
|
||||
#endif /* LWSHELL_CFG_USE_ENABLE_LIST_CMD */
|
||||
@ -198,11 +195,12 @@ prv_parse_input(lwshell_t* lwobj) {
|
||||
|
||||
/**
|
||||
* \brief Initialize shell interface
|
||||
* \param[in] lwobj: LwSHELL object instance. Set to `NULL` to use default one
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
lwshellr_t
|
||||
lwshell_init(void) {
|
||||
lwshell_t* lwobj = LWSHELL_GET_LWOBJ(NULL);
|
||||
lwshell_init_ex(lwshell_t* lwobj) {
|
||||
lwobj = LWSHELL_GET_LWOBJ(NULL);
|
||||
memset(lwobj, 0x00, sizeof(*lwobj));
|
||||
return lwshellOK;
|
||||
}
|
||||
@ -211,13 +209,14 @@ lwshell_init(void) {
|
||||
|
||||
/**
|
||||
* \brief Set output function to use to print data from library to user
|
||||
* \param[in] lwobj: LwSHELL object instance. Set to `NULL` to use default one
|
||||
* \param[in] out_fn: Output function to print library data.
|
||||
* Set to `NULL` to disable the feature
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
lwshellr_t
|
||||
lwshell_set_output_fn(lwshell_output_fn out_fn) {
|
||||
lwshell_t* lwobj = LWSHELL_GET_LWOBJ(NULL);
|
||||
lwshell_set_output_fn_ex(lwshell_t* lwobj, lwshell_output_fn out_fn) {
|
||||
lwobj = LWSHELL_GET_LWOBJ(lwobj);
|
||||
lwobj->out_fn = out_fn;
|
||||
return lwshellOK;
|
||||
}
|
||||
@ -226,24 +225,27 @@ lwshell_set_output_fn(lwshell_output_fn out_fn) {
|
||||
|
||||
/**
|
||||
* \brief Register new command to shell
|
||||
* \param[in] lwobj: LwSHELL object instance. Set to `NULL` to use default one
|
||||
* \param[in] cmd_name: Command name. This one is used when entering shell command
|
||||
* \param[in] cmd_fn: Function to call on command match
|
||||
* \param[in] desc: Custom command description
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
lwshellr_t
|
||||
lwshell_register_cmd(const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc) {
|
||||
lwshell_register_cmd_ex(lwshell_t* lwobj, const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc) {
|
||||
lwobj = LWSHELL_GET_LWOBJ(lwobj);
|
||||
|
||||
if (cmd_name == NULL || cmd_fn == NULL || strlen(cmd_name) == 0) {
|
||||
return lwshellERRPAR;
|
||||
}
|
||||
|
||||
/* Check for memory available */
|
||||
if (cmds_cnt < LWSHELL_ARRAYSIZE(cmds)) {
|
||||
cmds[cmds_cnt].name = cmd_name;
|
||||
cmds[cmds_cnt].fn = cmd_fn;
|
||||
cmds[cmds_cnt].desc = desc;
|
||||
if (lwobj->cmds_cnt < LWSHELL_ARRAYSIZE(lwobj->cmds)) {
|
||||
lwobj->cmds[lwobj->cmds_cnt].name = cmd_name;
|
||||
lwobj->cmds[lwobj->cmds_cnt].fn = cmd_fn;
|
||||
lwobj->cmds[lwobj->cmds_cnt].desc = desc;
|
||||
|
||||
++cmds_cnt;
|
||||
++lwobj->cmds_cnt;
|
||||
return lwshellOK;
|
||||
}
|
||||
return lwshellERRMEM;
|
||||
@ -251,14 +253,15 @@ lwshell_register_cmd(const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* de
|
||||
|
||||
/**
|
||||
* \brief Input data to shell processing
|
||||
* \param[in] lwobj: LwSHELL object instance. Set to `NULL` to use default one
|
||||
* \param[in] in_data: Input data to process
|
||||
* \param[in] len: Length of data for input
|
||||
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||
*/
|
||||
lwshellr_t
|
||||
lwshell_input(const void* in_data, size_t len) {
|
||||
lwshell_input_ex(lwshell_t* lwobj, const void* in_data, size_t len) {
|
||||
const char* d = in_data;
|
||||
lwshell_t* lwobj = LWSHELL_GET_LWOBJ(NULL);
|
||||
lwobj = LWSHELL_GET_LWOBJ(NULL);
|
||||
|
||||
if (in_data == NULL || len == 0) {
|
||||
return lwshellERRPAR;
|
||||
|
Loading…
x
Reference in New Issue
Block a user