refactor(cli): use X-macro pattern for CLI options definition

Extract CLI options into a reusable macro (CLI_OPTIONS_LIST) in cli_opt.h
and refactor handler_map.c to eliminate manual option array duplication.
Calculate g_has_len automatically from option definitions.
This commit is contained in:
lohhiiccc 2026-03-03 08:03:55 +01:00
parent 37a4085cfc
commit a6cdef89ca
3 changed files with 113 additions and 44 deletions

View file

@ -33,6 +33,7 @@ typedef struct s_option_descriptor
extern const t_option_descriptor g_options[]; extern const t_option_descriptor g_options[];
extern const size_t g_options_len; extern const size_t g_options_len;
extern const size_t g_opt_str_len;
int cli_handle_count(const char *arg, t_ping_config *config); int cli_handle_count(const char *arg, t_ping_config *config);
int cli_handle_flood(const char *arg, t_ping_config *config); int cli_handle_flood(const char *arg, t_ping_config *config);

94
includes/cli_opt.h Normal file
View file

@ -0,0 +1,94 @@
#ifndef PING_CLI_OPT_H
#define PING_CLI_OPT_H
#define CLI_OPTIONS_LIST \
X( \
'h', \
"help", \
no_argument, \
cli_handle_help, \
OPT_ARG_NONE, \
"Display this help and exit" \
) \
X( \
'V', \
"version", \
no_argument, \
cli_handle_version, \
OPT_ARG_NONE, \
"Display version information and exit" \
) \
X( \
'v', \
"verbose", \
no_argument, \
cli_handle_verbose, \
OPT_ARG_NONE, \
"Verbose output" \
) \
X( \
'q', \
"quiet", \
no_argument, \
cli_handle_quiet, \
OPT_ARG_NONE, \
"Quiet mode (only show summary)" \
) \
X( \
'c', \
"count", \
required_argument, \
cli_handle_count, \
OPT_ARG_UINT, \
"Stop after sending N packets" \
) \
X( \
'i', \
"interval", \
required_argument, \
cli_handle_interval, \
OPT_ARG_SECONDS, \
"Wait N seconds between packets" \
) \
X( \
't', \
"ttl", \
required_argument, \
cli_handle_ttl, \
OPT_ARG_TTL, \
"Set Time To Live" \
) \
X( \
's', \
"size", \
required_argument, \
cli_handle_size, \
OPT_ARG_BYTES, \
"Packet size in bytes" \
) \
X( \
'W', \
"timeout", \
required_argument, \
cli_handle_timeout, \
OPT_ARG_SECONDS, \
"Timeout for replies in seconds" \
) \
X( \
'f', \
"flood", \
no_argument, \
cli_handle_flood, \
OPT_ARG_NONE, \
"Flood mode" \
)
#undef X
#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \
+ (1 * (has_arg == no_argument) \
+ (2 * (has_arg == required_argument) \
+ (3 * (has_arg == optional_argument))))
#define CLI_OPT_STR_LEN (0 CLI_OPTIONS_LIST)
#endif

View file

@ -1,52 +1,26 @@
#include <getopt.h> #include <getopt.h>
#include <stddef.h>
#include "cli.h" #include "cli.h"
#include "cli_opt.h"
#undef X
#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \
{ short_opt, long_opt, has_arg, handler, arg_type, desc },
const t_option_descriptor g_options[] = { const t_option_descriptor g_options[] = {
{ CLI_OPTIONS_LIST
'h', "help", no_argument, cli_handle_help, OPT_ARG_NONE, {0, NULL, 0, NULL, OPT_ARG_NONE, NULL }
"Display this help and exit"
},
{
'V', "version", no_argument, cli_handle_version, OPT_ARG_NONE,
"Display version information and exit"
},
{
'v', "verbose", no_argument, cli_handle_verbose, OPT_ARG_NONE,
"Verbose output"
},
{
'q', "quiet", no_argument, cli_handle_quiet, OPT_ARG_NONE,
"Quiet mode (only show summary)"
},
{
'c', "count", required_argument, cli_handle_count, OPT_ARG_UINT,
"Stop after sending N packets"
},
{
'i', "interval", required_argument, cli_handle_interval, OPT_ARG_SECONDS,
"Wait N seconds between packets"
},
{
't', "ttl", required_argument, cli_handle_ttl, OPT_ARG_TTL,
"Set Time To Live"
},
{
's', "size", required_argument, cli_handle_size, OPT_ARG_BYTES,
"Packet size in bytes"
},
{
'W', "timeout", required_argument, cli_handle_timeout, OPT_ARG_SECONDS,
"Timeout for replies in seconds"
},
{
'f', "flood", no_argument, cli_handle_flood, OPT_ARG_NONE,
"Flood mode"
},
{
0, NULL, 0, NULL, OPT_ARG_NONE,
NULL
}
}; };
const size_t g_options_len = ((sizeof(g_options) / sizeof(*g_options)) - 1); const size_t g_options_len = ((sizeof(g_options) / sizeof(*g_options)) - 1);
#undef X
#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \
+ (1 * (has_arg == no_argument) \
+ (2 * (has_arg == required_argument) \
+ (3 * (has_arg == optional_argument))))
const size_t g_opt_str_len = CLI_OPT_STR_LEN;
#undef X