2024-10-24 21:32:28 +01:00
|
|
|
#ifndef BLUELIB_COMMAND_H_
|
|
|
|
|
#define BLUELIB_COMMAND_H_
|
|
|
|
|
|
|
|
|
|
#include <blue/core/btree.h>
|
|
|
|
|
#include <blue/core/init.h>
|
|
|
|
|
#include <blue/core/iterator.h>
|
|
|
|
|
#include <blue/core/queue.h>
|
|
|
|
|
#include <blue/object/array.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
|
|
#define b_arglist_foreach(it, q) \
|
|
|
|
|
for (int z__b_unique_name() = b_arglist_iterator_begin( \
|
|
|
|
|
q, B_COMMAND_INVALID_ID, B_COMMAND_INVALID_ID, (it)); \
|
|
|
|
|
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
|
|
|
|
|
|
|
|
|
|
#define b_arglist_foreach_filtered(it, q, opt_id, arg_id) \
|
|
|
|
|
for (int z__b_unique_name() \
|
|
|
|
|
= b_arglist_iterator_begin(q, opt_id, arg_id, (it)); \
|
|
|
|
|
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND(id, parent_id) \
|
|
|
|
|
static b_command *command_##id = NULL; \
|
|
|
|
|
static void __init_##id( \
|
|
|
|
|
b_command *, b_command_option *, b_command_arg *, \
|
|
|
|
|
b_command_usage *); \
|
|
|
|
|
B_INIT(init_##id) \
|
|
|
|
|
{ \
|
|
|
|
|
command_##id = b_command_create(id); \
|
|
|
|
|
if ((parent_id) != B_COMMAND_INVALID_ID) { \
|
|
|
|
|
b_command_set_parent(command_##id, parent_id); \
|
|
|
|
|
} \
|
|
|
|
|
__init_##id(command_##id, NULL, NULL, NULL); \
|
|
|
|
|
b_command_register(command_##id); \
|
|
|
|
|
} \
|
|
|
|
|
static void __init_##id( \
|
|
|
|
|
b_command *this_cmd, b_command_option *this_opt, \
|
|
|
|
|
b_command_arg *this_arg, b_command_usage *this_usage)
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_NAME(name) b_command_set_name(this_cmd, (name))
|
|
|
|
|
#define B_COMMAND_LONG_NAME(name) b_command_set_long_name(this_cmd, (name))
|
|
|
|
|
#define B_COMMAND_SHORT_NAME(name) b_command_set_short_name(this_cmd, (name))
|
|
|
|
|
#define B_COMMAND_DESC(desc) b_command_set_description(this_cmd, (desc))
|
|
|
|
|
#define B_COMMAND_FLAGS(flags) b_command_set_flags(this_cmd, (flags))
|
|
|
|
|
#define B_COMMAND_FUNCTION(fn) b_command_set_callback(this_cmd, (fn))
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_OPTION(id) \
|
|
|
|
|
b_command_option *opt_##id = b_command_add_option(this_cmd, (id)); \
|
|
|
|
|
this_opt = opt_##id; \
|
|
|
|
|
if (this_opt)
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_HELP_OPTION() \
|
|
|
|
|
do { \
|
|
|
|
|
b_command_option *opt \
|
|
|
|
|
= b_command_add_option(this_cmd, B_COMMAND_OPTION_HELP); \
|
|
|
|
|
b_command_option_set_description(opt, "Show this help message"); \
|
|
|
|
|
b_command_option_set_short_name(opt, 'h'); \
|
|
|
|
|
b_command_option_set_long_name(opt, "help"); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define B_OPTION_LONG_NAME(name) \
|
|
|
|
|
b_command_option_set_long_name(this_opt, (name))
|
|
|
|
|
|
|
|
|
|
#define B_OPTION_SHORT_NAME(name) \
|
|
|
|
|
b_command_option_set_short_name(this_opt, (name))
|
|
|
|
|
|
|
|
|
|
#define B_OPTION_DESC(desc) b_command_option_set_description(this_opt, (desc))
|
|
|
|
|
|
|
|
|
|
#define B_OPTION_ARG(id) \
|
|
|
|
|
b_command_arg *arg_##id = b_command_option_add_arg(this_opt, (id)); \
|
|
|
|
|
this_arg = arg_##id; \
|
|
|
|
|
if (this_arg)
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_ARG(id) \
|
|
|
|
|
b_command_arg *arg_##id = b_command_add_arg(this_cmd, (id)); \
|
|
|
|
|
this_arg = arg_##id; \
|
|
|
|
|
if (this_arg)
|
|
|
|
|
|
|
|
|
|
#define B_ARG_NAME(name) b_command_arg_set_name(this_arg, (name))
|
|
|
|
|
|
|
|
|
|
#define B_ARG_DESC(desc) b_command_arg_set_description(this_arg, (desc))
|
|
|
|
|
|
|
|
|
|
#define B_ARG_NR_VALUES(nr_values) \
|
|
|
|
|
b_command_arg_set_nr_values(this_arg, (nr_values))
|
|
|
|
|
|
|
|
|
|
#define B_ARG_ALLOWED_VALUES(...) \
|
|
|
|
|
static const char *allowed_values[] = { \
|
|
|
|
|
__VA_ARGS__, \
|
|
|
|
|
NULL, \
|
|
|
|
|
}; \
|
|
|
|
|
b_command_arg_set_allowed_values(this_arg, allowed_values)
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_USAGE() \
|
2024-10-27 14:21:05 +00:00
|
|
|
b_command_usage *z__b_unique_name() = b_command_add_usage(this_cmd); \
|
|
|
|
|
this_usage = z__b_unique_name(); \
|
2024-10-24 21:32:28 +01:00
|
|
|
if (this_usage)
|
|
|
|
|
|
2024-10-31 19:33:48 +00:00
|
|
|
#define B_COMMAND_USAGE_COMMAND(cmd_id) \
|
|
|
|
|
b_command_usage_add_command(this_usage, cmd_id)
|
|
|
|
|
|
|
|
|
|
#define B_COMMAND_USAGE_COMMAND_PLACEHOLDER() \
|
|
|
|
|
b_command_usage_add_command(this_usage, B_COMMAND_INVALID_ID)
|
|
|
|
|
|
2024-10-24 21:32:28 +01:00
|
|
|
#define B_COMMAND_USAGE_OPT(opt_id) \
|
|
|
|
|
b_command_usage_add_option(this_usage, opt_##opt_id)
|
|
|
|
|
|
2024-10-31 19:33:48 +00:00
|
|
|
#define B_COMMAND_USAGE_OPT_PLACEHOLDER() \
|
|
|
|
|
b_command_usage_add_option( \
|
|
|
|
|
this_usage, (struct b_command_option *)B_COMMAND_INVALID_ID)
|
|
|
|
|
|
2024-10-24 21:32:28 +01:00
|
|
|
#define B_COMMAND_USAGE_ARG(opt_id) \
|
|
|
|
|
b_command_usage_add_arg(this_usage, arg_##opt_id)
|
|
|
|
|
|
2024-10-31 19:33:48 +00:00
|
|
|
#define B_COMMAND_USAGE_ARG_PLACEHOLDER() \
|
|
|
|
|
b_command_usage_add_arg( \
|
|
|
|
|
this_usage, (struct b_command_arg *)B_COMMAND_INVALID_ID)
|
|
|
|
|
|
2024-10-24 21:32:28 +01:00
|
|
|
#define B_COMMAND_OPTION_HELP ((unsigned int)0xF0000001)
|
|
|
|
|
#define B_COMMAND_INVALID_ID ((unsigned int)0xFFFFFFFF)
|
|
|
|
|
|
|
|
|
|
typedef enum b_command_arg_value_count {
|
|
|
|
|
B_ARG_0_OR_1_VALUES = -1,
|
|
|
|
|
B_ARG_0_OR_MORE_VALUES = -2,
|
|
|
|
|
B_ARG_1_OR_MORE_VALUES = -3,
|
|
|
|
|
} b_command_arg_value_count;
|
|
|
|
|
|
|
|
|
|
typedef enum b_command_arg_type {
|
|
|
|
|
B_COMMAND_ARG_NONE = 0,
|
|
|
|
|
B_COMMAND_ARG_STRING,
|
|
|
|
|
B_COMMAND_ARG_SIGNED_INT,
|
|
|
|
|
B_COMMAND_ARG_UNSIGNED_INT,
|
|
|
|
|
|
|
|
|
|
B_COMMAND_ARG_INT = B_COMMAND_ARG_SIGNED_INT,
|
|
|
|
|
} b_command_arg_type;
|
|
|
|
|
|
|
|
|
|
typedef enum b_command_flags {
|
|
|
|
|
B_COMMAND_SHOW_HELP_BY_DEFAULT = 0x01u,
|
|
|
|
|
} b_command_flags;
|
|
|
|
|
|
|
|
|
|
typedef enum b_command_usage_flags {
|
|
|
|
|
B_COMMAND_USAGE_SHOW_OPTIONS = 0x01u,
|
|
|
|
|
} b_command_usage_flags;
|
|
|
|
|
|
|
|
|
|
typedef struct b_arglist_value {
|
|
|
|
|
unsigned int val_id;
|
|
|
|
|
b_command_arg_type val_type;
|
|
|
|
|
struct b_btree_node val_node;
|
|
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
char *val_str;
|
|
|
|
|
long long val_int;
|
|
|
|
|
unsigned long long val_uint;
|
|
|
|
|
};
|
|
|
|
|
} b_arglist_value;
|
|
|
|
|
|
|
|
|
|
typedef struct b_arglist_iterator {
|
|
|
|
|
b_iterator _base;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
unsigned int opt_id;
|
|
|
|
|
struct b_arglist_value *value;
|
|
|
|
|
|
|
|
|
|
b_btree_iterator _opt_it, _arg_it;
|
|
|
|
|
unsigned int _opt_filter, _arg_filter;
|
|
|
|
|
} b_arglist_iterator;
|
|
|
|
|
|
|
|
|
|
typedef struct b_command b_command;
|
|
|
|
|
typedef struct b_command_option b_command_option;
|
|
|
|
|
typedef struct b_command_arg b_command_arg;
|
|
|
|
|
typedef struct b_command_usage b_command_usage;
|
|
|
|
|
typedef struct b_arglist b_arglist;
|
|
|
|
|
|
|
|
|
|
typedef int (*b_command_callback)(
|
|
|
|
|
const b_command *, const b_arglist *, const b_array *);
|
|
|
|
|
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_command *b_command_create(unsigned int id);
|
|
|
|
|
BLUE_API void b_command_destroy(b_command *cmd);
|
|
|
|
|
BLUE_API b_status b_command_register(b_command *cmd);
|
|
|
|
|
BLUE_API int b_command_dispatch(unsigned int cmd_id, int argc, const char **argv);
|
|
|
|
|
|
|
|
|
|
BLUE_API b_status b_command_set_name(b_command *cmd, const char *name);
|
|
|
|
|
BLUE_API b_status b_command_set_long_name(b_command *cmd, const char *name);
|
|
|
|
|
BLUE_API b_status b_command_set_short_name(b_command *cmd, char name);
|
|
|
|
|
BLUE_API b_status b_command_set_flags(b_command *cmd, b_command_flags flags);
|
|
|
|
|
BLUE_API b_status b_command_set_description(b_command *cmd, const char *description);
|
|
|
|
|
BLUE_API b_status b_command_set_callback(b_command *cmd, b_command_callback callback);
|
|
|
|
|
BLUE_API b_status b_command_set_parent(b_command *cmd, unsigned int parent_id);
|
|
|
|
|
BLUE_API b_command_option *b_command_add_option(b_command *cmd, int id);
|
|
|
|
|
BLUE_API b_command_arg *b_command_add_arg(b_command *cmd, int id);
|
|
|
|
|
BLUE_API b_command_usage *b_command_add_usage(b_command *cmd);
|
|
|
|
|
|
|
|
|
|
BLUE_API b_status b_command_option_set_long_name(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_option *opt, const char *name);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_option_set_short_name(b_command_option *opt, char name);
|
|
|
|
|
BLUE_API b_status b_command_option_set_description(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_option *opt, const char *description);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_command_arg *b_command_option_add_arg(b_command_option *opt, int id);
|
2024-10-24 21:32:28 +01:00
|
|
|
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_arg_set_name(b_command_arg *arg, const char *name);
|
|
|
|
|
BLUE_API b_status b_command_arg_set_description(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_arg *arg, const char *description);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_arg_set_nr_values(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_arg *arg, b_command_arg_value_count nr_values);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_arg_set_allowed_values(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_arg *arg, const char **allowed_values);
|
|
|
|
|
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_usage_add_option(
|
2024-10-24 21:32:28 +01:00
|
|
|
b_command_usage *usage, b_command_option *opt);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_command_usage_add_arg(b_command_usage *usage, b_command_arg *opt);
|
|
|
|
|
BLUE_API b_status b_command_usage_add_command(
|
2024-10-31 19:33:48 +00:00
|
|
|
b_command_usage *usage, unsigned int cmd_id);
|
2024-10-24 21:32:28 +01:00
|
|
|
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_arglist_get_string(
|
2024-10-24 21:32:28 +01:00
|
|
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
|
|
|
|
unsigned int index, const char **out);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_arglist_get_int(
|
2024-10-24 21:32:28 +01:00
|
|
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
|
|
|
|
unsigned int index, long long *out);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API b_status b_arglist_get_uint(
|
2024-10-24 21:32:28 +01:00
|
|
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
|
|
|
|
unsigned int index, unsigned long long *out);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API size_t b_arglist_get_count(
|
2024-10-24 21:32:28 +01:00
|
|
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id);
|
|
|
|
|
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API int b_arglist_iterator_begin(
|
2024-10-24 21:32:28 +01:00
|
|
|
const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter,
|
|
|
|
|
b_arglist_iterator *it);
|
2024-11-14 16:56:12 +00:00
|
|
|
BLUE_API bool b_arglist_iterator_next(b_arglist_iterator *it);
|
|
|
|
|
BLUE_API bool b_arglist_iterator_is_valid(const b_arglist_iterator *it);
|
2024-10-24 21:32:28 +01:00
|
|
|
|
|
|
|
|
#endif
|