libmish: Reworked to add a 'kind' to commands

Quest to remove any globals from mii

Signed-off-by: Michel Pollet <buserror@gmail.com>
This commit is contained in:
Michel Pollet 2023-10-28 06:28:53 +01:00
parent 2f2cf15576
commit f030ed758e
2 changed files with 71 additions and 11 deletions

View File

@ -44,6 +44,14 @@ void
mish_terminate(
struct mish_t * m);
/* Currently only one flag is used */
typedef union mish_cmd_flags_t {
struct {
unsigned int safe : 1;
};
unsigned int raw;
} mish_cmd_flags_t;
/*
* Register a command; please use the macros, don't call this directly.
*
@ -51,14 +59,35 @@ mish_terminate(
* without having to drag libmish into programs that use it; the commands
* won't register, but if you then link with a program that uses libmish,
* they will.
* Same but allows grouping command by an arbitrary 'kind' value.
*/
void
mish_register_cmd(
mish_register_cmd_kind(
const char ** cmd_names,
const char ** cmd_help,
mish_cmd_handler_p cmd_handler,
void * handler_param,
int safe) __attribute__((weak));
mish_cmd_flags_t flags,
unsigned int kind) __attribute__((weak));
#define mish_register_cmd(__named, __help, __handler, __param, __safe) \
mish_register_cmd_kind(__named, __help, __handler, __param, \
(mish_cmd_flags_t){.safe = __safe}, 0)
/*
* There is some provision for command-specific parameters, but it's not
* used yet. Instead we use a global one. If 'kind' is zero, ALL parameters
* for every command is set to 'param'. If 'kind' is non-zero, only the
* commands that have been registered with MISH_CMD_REGISTER_KIND() and
* the matchinf 'kind' will have their parameter set to 'param'.
*
* This allows grouping commands by 'kind' and have them share a parameter.
*/
void
mish_set_command_parameter(
unsigned int kind,
void * param);
/*!
* Poll the mish threads for pending commands, and call their handlers.
* This is only necessary for 'safe' commands that needs to be run on the
@ -99,15 +128,31 @@ static inline int _gcc_warning_false_pos_workaround(void * func) {
#define MISH_CMD_REGISTER(_d, _handler) \
__attribute__((constructor,used)) \
static void _mish_register_##_d() { \
if (_gcc_warning_false_pos_workaround(mish_register_cmd)) \
mish_register_cmd(_cmd_##_d,_help_##_d,_handler,0,0);\
if (_gcc_warning_false_pos_workaround(mish_register_cmd_kind)) \
mish_register_cmd_kind(_cmd_##_d,_help_##_d,_handler,0,\
(mish_cmd_flags_t){},0);\
}
#ifndef MISH_FCC
// create a four character constant, not necessary, just for convenience
#define MISH_FCC(_a,_b,_c,_d) (((_a)<<24)|((_b)<<16)|((_c)<<8)|(_d))
#endif
#define MISH_CMD_REGISTER_KIND(_d, _handler, _safe, _kind) \
__attribute__((constructor,used)) \
static void _mish_register_##_d() { \
if (_gcc_warning_false_pos_workaround(mish_register_cmd_kind)) \
mish_register_cmd_kind(_cmd_##_d,_help_##_d,\
_handler,0,\
(mish_cmd_flags_t){.safe=_safe},_kind);\
}
//! These are called when the main program calls mish_cmd_poll()
#define MISH_CMD_REGISTER_SAFE(_d, _handler) \
__attribute__((constructor,used)) \
static void _mish_register_##_d() { \
if (_gcc_warning_false_pos_workaround(mish_register_cmd)) \
mish_register_cmd(_cmd_##_d,_help_##_d,_handler,0,1);\
if (_gcc_warning_false_pos_workaround(mish_register_cmd_kind)) \
mish_register_cmd_kind(_cmd_##_d,_help_##_d,_handler,0, \
(mish_cmd_flags_t){.safe=1},0);\
}
#endif /* LIBMISH_SRC_MISH_H_ */

View File

@ -29,7 +29,8 @@ typedef struct mish_cmd_t {
TAILQ_ENTRY(mish_cmd_t) self;
mish_cmd_handler_p cmd_cb;
void * param_cb;
uint32_t safe : 1;
uint32_t kind; // optional, for your own use
mish_cmd_flags_t flags;
const char ** names; // list of aliases for the command
const char ** help;
@ -48,12 +49,13 @@ static TAILQ_HEAD(,mish_cmd_t) _cmd_list = TAILQ_HEAD_INITIALIZER(_cmd_list);
static mish_call_queue_t _cmd_fifo = {0};
void __attribute__((weak))
mish_register_cmd(
mish_register_cmd_kind(
const char ** cmd_names,
const char ** cmd_help,
mish_cmd_handler_p cmd_handler,
void * handler_param,
int safe)
mish_cmd_flags_t flags,
uint32_t kind)
{
if (!cmd_names || !cmd_help || !cmd_handler) {
fprintf(stderr, "%s invalid parameters\n", __func__);
@ -65,7 +67,8 @@ mish_register_cmd(
cmd->help = cmd_help;
cmd->cmd_cb = cmd_handler;
cmd->param_cb = handler_param;
cmd->safe = safe;
cmd->kind = kind;
cmd->flags = flags;
// keep the list roughtly sorted
mish_cmd_p c, s;
@ -78,6 +81,18 @@ mish_register_cmd(
TAILQ_INSERT_TAIL(&_cmd_list, cmd, self);
}
void
mish_set_command_parameter(
unsigned int kind,
void * param)
{
mish_cmd_p cmd;
TAILQ_FOREACH(cmd, &_cmd_list, self) {
if (!kind || cmd->kind == kind)
cmd->param_cb = param;
}
}
/*
* Returns the length of the first word of cmd_line
*/
@ -216,7 +231,7 @@ mish_cmd_call(
int ac = 0;
char ** av = mish_argv_make(cmd_line, &ac);
if (cmd->safe) {
if (cmd->flags.safe) {
if (!mish_call_queue_isfull(&_cmd_fifo)) {
mish_cmd_call_t fe = {
.cmd = cmd,