#ifndef BLUELIB_COMMAND_H_ #define BLUELIB_COMMAND_H_ #include #include #include #include #include #include #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() \ b_command_usage *usage_##__LINE__ = b_command_add_usage(this_cmd); \ this_usage = usage_##__LINE__; \ if (this_usage) #define B_COMMAND_USAGE_OPT(opt_id) \ b_command_usage_add_option(this_usage, opt_##opt_id) #define B_COMMAND_USAGE_ARG(opt_id) \ b_command_usage_add_arg(this_usage, arg_##opt_id) #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 *); extern b_command *b_command_create(unsigned int id); extern void b_command_destroy(b_command *cmd); extern b_status b_command_register(b_command *cmd); extern int b_command_dispatch(unsigned int cmd_id, int argc, const char **argv); extern b_status b_command_set_name(b_command *cmd, const char *name); extern b_status b_command_set_long_name(b_command *cmd, const char *name); extern b_status b_command_set_short_name(b_command *cmd, char name); extern b_status b_command_set_flags(b_command *cmd, b_command_flags flags); extern b_status b_command_set_description(b_command *cmd, const char *description); extern b_status b_command_set_callback(b_command *cmd, b_command_callback callback); extern b_status b_command_set_parent(b_command *cmd, unsigned int parent_id); extern b_command_option *b_command_add_option(b_command *cmd, int id); extern b_command_arg *b_command_add_arg(b_command *cmd, int id); extern b_command_usage *b_command_add_usage(b_command *cmd); extern b_status b_command_option_set_long_name( b_command_option *opt, const char *name); extern b_status b_command_option_set_short_name(b_command_option *opt, char name); extern b_status b_command_option_set_description( b_command_option *opt, const char *description); extern b_command_arg *b_command_option_add_arg(b_command_option *opt, int id); extern b_status b_command_arg_set_name(b_command_arg *arg, const char *name); extern b_status b_command_arg_set_description( b_command_arg *arg, const char *description); extern b_status b_command_arg_set_nr_values( b_command_arg *arg, b_command_arg_value_count nr_values); extern b_status b_command_arg_set_allowed_values( b_command_arg *arg, const char **allowed_values); extern b_status b_command_usage_add_option( b_command_usage *usage, b_command_option *opt); extern b_status b_command_usage_add_arg(b_command_usage *usage, b_command_arg *opt); extern b_status b_arglist_get_string( const b_arglist *args, unsigned int opt_id, unsigned int arg_id, unsigned int index, const char **out); extern b_status b_arglist_get_int( const b_arglist *args, unsigned int opt_id, unsigned int arg_id, unsigned int index, long long *out); extern b_status b_arglist_get_uint( const b_arglist *args, unsigned int opt_id, unsigned int arg_id, unsigned int index, unsigned long long *out); extern size_t b_arglist_get_count( const b_arglist *args, unsigned int opt_id, unsigned int arg_id); extern int b_arglist_iterator_begin( const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter, b_arglist_iterator *it); extern bool b_arglist_iterator_next(b_arglist_iterator *it); extern bool b_arglist_iterator_is_valid(const b_arglist_iterator *it); #endif