refactor(cli): simplfy handle_one_option and coding style improvement

- Fix indentation
- Fix import order
- Simplify handle_one_option
- Fix line too long
This commit is contained in:
lohhiiccc 2026-03-05 20:37:48 +01:00
parent de872facd3
commit f59f984a0e
11 changed files with 90 additions and 93 deletions

View file

@ -1,12 +1,14 @@
#ifndef CLI_INTERNAL_MESSAGES #ifndef CLI_INTERNAL_MESSAGES
#define CLI_INTERNAL_MESSAGES #define CLI_INTERNAL_MESSAGES
#include "cli.h"
void print_help(void); void print_help(void);
void print_version(void); void print_version(void);
void error_unknown_opt(const char *current_opt); enum e_cli_code error_unknown_opt(const char *current_opt);
void error_invalid_arg(const char *current_opt); enum e_cli_code error_invalid_arg(const char *current_opt);
void error_invalid_opt(const char *current_opt); enum e_cli_code error_invalid_opt(const char *current_opt);
void error_duplicate_opt(const char *current_opt); enum e_cli_code error_duplicate_opt(const char *current_opt);
#endif #endif

View file

@ -2,18 +2,6 @@
#define PING_CLI_OPT_H #define PING_CLI_OPT_H
#include <getopt.h> #include <getopt.h>
#include "ft_ping_flags.h"
#define TRACK_DUP_OPT(descriptor, tracker, opt_name, opts_array) \
do { \
bitmask_index = (size_t)((descriptor) - (opts_array)); \
if (HAS_FLAG(tracker, (1ULL << bitmask_index))) \
{ \
error_duplicate_opt(opt_name); \
return CLI_ERROR; \
} \
SET_FLAG(tracker, (1ULL << bitmask_index)); \
} while (0)
#define CLI_OPTIONS_LIST \ #define CLI_OPTIONS_LIST \
X( \ X( \

View file

@ -1,9 +1,9 @@
#include <unistd.h>
#include "cli.h" #include "cli.h"
#include "internal/cli/arg_handler.h" #include "internal/cli/arg_handler.h"
#include "internal/cli/parse_utils.h" #include "internal/cli/parse_utils.h"
#include <unistd.h>
int int
cli_handle_interval(const char *arg, t_ping_config *config) cli_handle_interval(const char *arg, t_ping_config *config)
{ {

View file

@ -1,9 +1,9 @@
#include <unistd.h>
#include "cli.h" #include "cli.h"
#include "internal/cli/arg_handler.h" #include "internal/cli/arg_handler.h"
#include "internal/cli/parse_utils.h" #include "internal/cli/parse_utils.h"
#include <unistd.h>
int int
cli_handle_size(const char *arg, t_ping_config *config) cli_handle_size(const char *arg, t_ping_config *config)
{ {

View file

@ -1,9 +1,9 @@
#include <unistd.h>
#include "cli.h" #include "cli.h"
#include "internal/cli/arg_handler.h" #include "internal/cli/arg_handler.h"
#include "internal/cli/parse_utils.h" #include "internal/cli/parse_utils.h"
#include <unistd.h>
int int
cli_handle_timeout(const char *arg, t_ping_config *config) cli_handle_timeout(const char *arg, t_ping_config *config)
{ {

View file

@ -1,9 +1,9 @@
#include <unistd.h>
#include "cli.h" #include "cli.h"
#include "internal/cli/arg_handler.h" #include "internal/cli/arg_handler.h"
#include "internal/cli/parse_utils.h" #include "internal/cli/parse_utils.h"
#include <unistd.h>
int int
cli_handle_ttl(const char *arg, t_ping_config *config) cli_handle_ttl(const char *arg, t_ping_config *config)
{ {

View file

@ -1,5 +1,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include "cli.h"
#include "version_gen.h" #include "version_gen.h"
#define CMD_NAME g_prog_name.name #define CMD_NAME g_prog_name.name
@ -8,36 +10,45 @@
void static inline print_suggest_help(void); void static inline print_suggest_help(void);
/* -------------------- */ /* -------------------- */
void enum e_cli_code
error_unknown_opt(const char *current_opt) error_unknown_opt(const char *current_opt)
{ {
dprintf(STDERR_FILENO, "%s: unknown option -- '%s'\n", CMD_NAME, current_opt); dprintf(STDERR_FILENO, "%s: unknown option -- '%s'\n",
print_suggest_help(); CMD_NAME, current_opt);
print_suggest_help();
return CLI_ERROR;
} }
void enum e_cli_code
error_invalid_arg(const char *current_opt) error_invalid_arg(const char *current_opt)
{ {
dprintf(STDERR_FILENO, "%s: option '%s' requires an argument\n", CMD_NAME, current_opt); dprintf(STDERR_FILENO, "%s: option '%s' requires an argument\n",
print_suggest_help(); CMD_NAME, current_opt);
print_suggest_help();
return CLI_ERROR;
} }
void enum e_cli_code
error_invalid_opt(const char *current_opt) error_invalid_opt(const char *current_opt)
{ {
dprintf(STDERR_FILENO, "%s: invalid option '%s'\n", CMD_NAME, current_opt); dprintf(STDERR_FILENO, "%s: invalid option '%s'\n",
print_suggest_help(); CMD_NAME, current_opt);
print_suggest_help();
return CLI_ERROR;
} }
void enum e_cli_code
error_duplicate_opt(const char *current_opt) error_duplicate_opt(const char *current_opt)
{ {
dprintf(STDERR_FILENO, "%s: duplicate option '%s'\n", CMD_NAME, current_opt); dprintf(STDERR_FILENO, "%s: duplicate option '%s'\n",
print_suggest_help(); CMD_NAME, current_opt);
print_suggest_help();
return CLI_ERROR;
} }
void static inline void static inline
print_suggest_help(void) print_suggest_help(void)
{ {
dprintf(STDERR_FILENO, "Try '%s --help' for more information.\n", CMD_NAME); dprintf(STDERR_FILENO, "Try '%s --help' for more information.\n",
CMD_NAME);
} }

View file

@ -1,6 +1,7 @@
#include "version_gen.h"
#include <stdio.h> #include <stdio.h>
#include "version_gen.h"
void void
print_version(void) print_version(void)
{ {

View file

@ -1,14 +1,12 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include <unistd.h>
#include "cli.h" #include "cli.h"
#include "ft_ping_flags.h"
#include "ft_ping_const.h"
#include "internal/cli/messages.h" #include "internal/cli/messages.h"
#include "internal/cli/options.h" #include "internal/cli/options.h"
#include "internal/cli/arg_handler.h" #include "internal/cli/arg_handler.h"
#include "ft_ping_const.h"
/* Map -? to -h to support help shortcut */ /* Map -? to -h to support help shortcut */
#define HANDLE_QUESTION_MARK(opt) \ #define HANDLE_QUESTION_MARK(opt) \
@ -22,54 +20,51 @@ static void init_config(t_ping_config *config);
static void build_long_options(struct option *long_opts, size_t nb_opts, static void build_long_options(struct option *long_opts, size_t nb_opts,
const t_option_descriptor *src); const t_option_descriptor *src);
static inline const t_option_descriptor *find_option_handler(int opt); static inline const t_option_descriptor *find_option_handler(int opt);
static int handle_one_option(int opt, char **argv, t_ping_config *config, uint64_t *opt_tacker); static int handle_one_option(int opt, char **argv, t_ping_config *config,
uint64_t *opt_tacker);
/* ------------------- */ /* ------------------- */
enum e_cli_code enum e_cli_code
cli_parse_arguments(int argc, char **argv, t_ping_config *config) cli_parse_arguments(int argc, char **argv, t_ping_config *config)
{ {
struct option long_opts[CLI_OPT_LEN + 1]; struct option long_opts[CLI_OPT_LEN + 1];
const char *opt_str = cli_get_optstr();
uint64_t tracker = 0; uint64_t tracker = 0;
int opt; int opt;
int res; int res;
init_config(config); init_config(config);
build_long_options(long_opts, CLI_OPT_LEN, g_options); build_long_options(long_opts, CLI_OPT_LEN, g_options);
while (-1 != (opt = getopt_long(argc, argv, cli_get_optstr(), long_opts, NULL))) while (-1 != (opt = getopt_long(argc, argv, opt_str, long_opts, NULL)))
{ {
HANDLE_QUESTION_MARK(opt); HANDLE_QUESTION_MARK(opt);
res = handle_one_option(opt, argv, config, &tracker); res = handle_one_option(opt, argv, config, &tracker);
if (0 != res) if (CLI_SUCCESS != res)
return res; return res;
} }
return CLI_SUCCESS; return CLI_SUCCESS;
} }
static int static int
handle_one_option(int opt, char **argv, t_ping_config *config, uint64_t *opt_tracker) handle_one_option(int opt, char **argv, t_ping_config *config,
uint64_t *opt_tracker)
{ {
const t_option_descriptor *desc = find_option_handler(opt); const t_option_descriptor *desc = find_option_handler(opt);
const size_t bitmask_index = (size_t)((desc) - (g_options));
const char *current_opt = argv[optind - 1]; const char *current_opt = argv[optind - 1];
int res; int res = CLI_SUCCESS;
size_t bitmask_index;
switch (opt) if ('?' == opt)
{ return error_unknown_opt(current_opt);
case '?': error_unknown_opt(current_opt); return CLI_ERROR; if (':' == opt)
case ':': error_invalid_arg(current_opt); return CLI_ERROR; return error_invalid_opt(current_opt);
default: break; if (HAS_FLAG(*opt_tracker, (1ULL << bitmask_index)))
} return error_duplicate_opt(current_opt);
if (NULL != desc) SET_FLAG(*opt_tracker, (1ULL) << bitmask_index);
{ res = desc->handler(optarg, config);
TRACK_DUP_OPT(desc, *opt_tracker, current_opt, g_options); if (CLI_SUCCESS != res)
res = desc->handler(optarg, config); return error_invalid_opt(current_opt);
if (0 != res)
{
error_invalid_opt(current_opt);
return res;
}
}
return CLI_SUCCESS; return CLI_SUCCESS;
} }

View file

@ -8,33 +8,33 @@ static void init_opt_str(char *str);
const char * const char *
cli_get_optstr(void) cli_get_optstr(void)
{ {
/* Static string to act like a global */ /* Static string to act like a global */
static char opt_str[CLI_OPT_STR_LEN] = ""; static char opt_str[CLI_OPT_STR_LEN] = "";
/* Lazy init */ /* Lazy init */
if ('\0' == *opt_str) if ('\0' == *opt_str)
init_opt_str(opt_str); init_opt_str(opt_str);
return opt_str; return opt_str;
} }
static void static void
init_opt_str(char *dest) init_opt_str(char *dest)
{ {
/* Mute default error messages */ /* Mute default error messages */
dest[0] = ':'; dest[0] = ':';
size_t str_i = 1; size_t str_i = 1;
for (size_t opt_i = 0; opt_i < CLI_OPT_LEN; ++opt_i) for (size_t opt_i = 0; opt_i < CLI_OPT_LEN; ++opt_i)
{ {
dest[str_i++] = g_options[opt_i].short_opt; dest[str_i++] = g_options[opt_i].short_opt;
switch (g_options[opt_i].has_arg) switch (g_options[opt_i].has_arg)
{ {
case optional_argument: dest[str_i++] = ':'; /* fall through */ case optional_argument: dest[str_i++] = ':'; /* fall through */
case required_argument: dest[str_i++] = ':'; break; case required_argument: dest[str_i++] = ':'; break;
default: break; default: break;
} }
} }
dest[str_i] = '\0'; dest[str_i] = '\0';
return; return;
} }

View file

@ -6,17 +6,17 @@
int int
cli_parse_float(const char *s, float *out) cli_parse_float(const char *s, float *out)
{ {
char *end; char *end;
if (NULL == s || '\0' == *s || '-' == *s) if (NULL == s || '\0' == *s || '-' == *s)
return 1; return 1;
errno = 0; errno = 0;
float v = strtof(s, &end); float v = strtof(s, &end);
if (s == end || ERANGE == errno || '\0' != *end || 0 == isfinite(v)) if (s == end || ERANGE == errno || '\0' != *end || 0 == isfinite(v))
return 1; return 1;
*out = v; *out = v;
return 0; return 0;
} }