refactor(cli): replace runtime size vars with compile-time enum constants

Replace g_options_len and g_opt_str_len extern variables with
CLI_OPT_LEN and CLI_OPT_STR_LEN enum constants computed via X-macros.

Disables Variable Length Arrays (VLA) by enforcing the use of the -Wvla
flag in strict mode.
This commit is contained in:
lohhiiccc 2026-03-03 09:01:45 +01:00
parent a6cdef89ca
commit 2fc8d92e98
6 changed files with 19 additions and 25 deletions

2
configure vendored
View file

@ -512,7 +512,7 @@ generate_build_mk() {
# Strict flags # Strict flags
if [ "$ENABLE_STRICT" = "yes" ]; then if [ "$ENABLE_STRICT" = "yes" ]; then
strict_flags="-Wpedantic -Wconversion -Wshadow -Wcast-align -Wstrict-prototypes" strict_flags="-Wpedantic -Wconversion -Wshadow -Wcast-align -Wstrict-prototypes -Wvla"
fi fi
# libicmp-specific configuration # libicmp-specific configuration

View file

@ -32,8 +32,6 @@ typedef struct s_option_descriptor
} t_option_descriptor; } t_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_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);

View file

@ -83,12 +83,16 @@
"Flood mode" \ "Flood mode" \
) )
#undef X
#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) + 1
enum { CLI_OPT_LEN = (0 CLI_OPTIONS_LIST) };
#include <getopt.h>
#undef X #undef X
#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \ #define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \
+ (1 * (has_arg == no_argument) \ + (1 * (has_arg == no_argument) \
+ (2 * (has_arg == required_argument) \ + (2 * (has_arg == required_argument) \
+ (3 * (has_arg == optional_argument)))) + (3 * (has_arg == optional_argument))))
enum { CLI_OPT_STR_LEN = (0 CLI_OPTIONS_LIST) };
#define CLI_OPT_STR_LEN (0 CLI_OPTIONS_LIST)
#endif #endif

View file

@ -3,6 +3,7 @@
#include <getopt.h> #include <getopt.h>
#include "cli.h" #include "cli.h"
#include "cli_opt.h"
#include "ft_ping.h" #include "ft_ping.h"
/* Forward declarations */ /* Forward declarations */
@ -19,7 +20,7 @@ cli_handle_help(const char *arg, t_ping_config *config)
printf("Usage: ft_ping [options] <destination>\n\n"); printf("Usage: ft_ping [options] <destination>\n\n");
printf("Options:\n"); printf("Options:\n");
for (size_t i = 0; i < g_options_len; ++i) for (size_t i = 0; i < CLI_OPT_LEN; ++i)
{ {
const t_option_descriptor *opt = &g_options[i]; const t_option_descriptor *opt = &g_options[i];
const char *argstr = option_arg_type_to_str(opt->arg_type); const char *argstr = option_arg_type_to_str(opt->arg_type);

View file

@ -13,14 +13,4 @@ const t_option_descriptor g_options[] = {
{0, NULL, 0, NULL, OPT_ARG_NONE, NULL } {0, NULL, 0, NULL, OPT_ARG_NONE, NULL }
}; };
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 #undef X

View file

@ -3,6 +3,7 @@
#include <getopt.h> #include <getopt.h>
#include "cli.h" #include "cli.h"
#include "cli_opt.h"
#include "ft_ping.h" #include "ft_ping.h"
#include "ft_ping_const.h" #include "ft_ping_const.h"
@ -17,13 +18,13 @@ static int handle_one_option(int opt, char *arg, t_ping_config *config);
int int
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[g_options_len + 1]; struct option long_opts[CLI_OPT_LEN + 1];
const char *opt_str = "hVvq:c:i:t:s:W:f"; const char *opt_str = "hVvqc:i:t:s:W:f";
int opt; int opt;
int res; int res;
init_config(config); init_config(config);
build_long_options(long_opts, g_options_len, g_options); build_long_options(long_opts, CLI_OPT_LEN, g_options);
while (-1 != (opt = getopt_long(argc, argv, opt_str, long_opts, NULL))) while (-1 != (opt = getopt_long(argc, argv, opt_str, long_opts, NULL)))
{ {
res = handle_one_option(opt, optarg, config); res = handle_one_option(opt, optarg, config);
@ -77,7 +78,7 @@ build_long_options(struct option *long_opts, size_t nb_opts,
static const t_option_descriptor static const t_option_descriptor
*find_option_handler(int opt) *find_option_handler(int opt)
{ {
for (size_t i = 0; i < g_options_len; ++i) for (size_t i = 0; i < CLI_OPT_LEN; ++i)
{ {
if (g_options[i].short_opt == opt) if (g_options[i].short_opt == opt)
return &g_options[i]; return &g_options[i];