Skip to content

Commit 783c362

Browse files
committed
Add alias support
- Add `aliases` and `alias_count` fields to the `Flag` struct - Respect the aliases when parsing flags - Print out aliases when printing out options - Update example to feature this
1 parent bc4ce6f commit 783c362

File tree

2 files changed

+59
-18
lines changed

2 files changed

+59
-18
lines changed

example.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ void usage(FILE *stream)
1313

1414
int main(int argc, char **argv)
1515
{
16-
bool *help = flag_bool("help", false, "Print this help to stdout and exit with 0");
17-
char **line = flag_str("line", "Hi!", "Line to output to the file");
18-
size_t *count = flag_size("count", 64, "Amount of lines to generate");
16+
bool *help = flag_bool_aliases("-help", false, "Print this help to stdout and exit with 0", "h");
17+
char **line = flag_str_aliases("-line", "Hi!", "Line to output to the file", "l");
18+
size_t *count = flag_size_aliases("-count", 64, "Amount of lines to generate", "c");
1919

2020
if (!flag_parse(argc, argv)) {
2121
usage(stderr);

flag.h

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stdio.h>
1010
#include <stdlib.h>
1111
#include <stdbool.h>
12+
#include <stdarg.h>
1213
#include <stdint.h>
1314
#include <stddef.h>
1415
#include <inttypes.h>
@@ -24,10 +25,22 @@
2425
// WARNING! *_var functions may break the flag_name() functionality
2526

2627
char *flag_name(void *val);
27-
bool *flag_bool(const char *name, bool def, const char *desc);
28-
uint64_t *flag_uint64(const char *name, uint64_t def, const char *desc);
29-
size_t *flag_size(const char *name, uint64_t def, const char *desc);
30-
char **flag_str(const char *name, const char *def, const char *desc);
28+
bool *flag_bool_null(const char *name, bool def, const char *desc, ...);
29+
#define flag_bool(name, def, desc) flag_bool_null(name, def, desc)
30+
#define flag_bool_aliases(name, def, desc, ...) \
31+
flag_bool_null(name, def, desc, __VA_ARGS__, NULL)
32+
uint64_t *flag_uint64_null(const char *name, uint64_t def, const char *desc, ...);
33+
#define flag_uint64(name, def, desc) flag_uint64_null(name, def, desc, NULL)
34+
#define flag_uint64_aliases(name, def, desc, ...) \
35+
flag_uint64_null(name, def, desc, __VA_ARGS__, NULL)
36+
size_t *flag_size_null(const char *name, uint64_t def, const char *desc, ...);
37+
#define flag_size(name, def, desc) flag_size_null(name, def, desc, NULL)
38+
#define flag_size_aliases(name, def, desc, ...) \
39+
flag_size_null(name, def, desc, __VA_ARGS__, NULL)
40+
char **flag_str_null(const char *name, const char *def, const char *desc, ...);
41+
#define flag_str(name, def, desc) flag_str_null(name, def, desc, NULL)
42+
#define flag_str_aliases(name, def, desc, ...) \
43+
flag_str_null(name, def, desc, __VA_ARGS__, NULL)
3144
bool flag_parse(int argc, char **argv);
3245
int flag_rest_argc(void);
3346
char **flag_rest_argv(void);
@@ -66,9 +79,15 @@ typedef enum {
6679
COUNT_FLAG_ERRORS,
6780
} Flag_Error;
6881

82+
#ifndef ALIAS_CAP
83+
#define ALIAS_CAP 12
84+
#endif // ALIAS_CAP
85+
6986
typedef struct {
7087
Flag_Type type;
7188
char *name;
89+
char *aliases[ALIAS_CAP];
90+
size_t alias_count;
7291
char *desc;
7392
Flag_Value val;
7493
Flag_Value def;
@@ -91,7 +110,7 @@ typedef struct {
91110

92111
static Flag_Context flag_global_context;
93112

94-
Flag *flag_new(Flag_Type type, const char *name, const char *desc)
113+
Flag *flag_new(Flag_Type type, const char *name, const char *desc, va_list aliases)
95114
{
96115
Flag_Context *c = &flag_global_context;
97116

@@ -102,6 +121,11 @@ Flag *flag_new(Flag_Type type, const char *name, const char *desc)
102121
// NOTE: I won't touch them I promise Kappa
103122
flag->name = (char*) name;
104123
flag->desc = (char*) desc;
124+
char *alias = va_arg(aliases, char *);
125+
while (alias != NULL) {
126+
flag->aliases[flag->alias_count++] = alias;
127+
alias = va_arg(aliases, char *);
128+
}
105129
return flag;
106130
}
107131

@@ -111,33 +135,41 @@ char *flag_name(void *val)
111135
return flag->name;
112136
}
113137

114-
bool *flag_bool(const char *name, bool def, const char *desc)
138+
bool *flag_bool_null(const char *name, bool def, const char *desc, ...)
115139
{
116-
Flag *flag = flag_new(FLAG_BOOL, name, desc);
140+
va_list aliases;
141+
va_start(aliases, desc);
142+
Flag *flag = flag_new(FLAG_BOOL, name, desc, aliases);
117143
flag->def.as_bool = def;
118144
flag->val.as_bool = def;
119145
return &flag->val.as_bool;
120146
}
121147

122-
uint64_t *flag_uint64(const char *name, uint64_t def, const char *desc)
148+
uint64_t *flag_uint64_null(const char *name, uint64_t def, const char *desc, ...)
123149
{
124-
Flag *flag = flag_new(FLAG_UINT64, name, desc);
150+
va_list aliases;
151+
va_start(aliases, desc);
152+
Flag *flag = flag_new(FLAG_UINT64, name, desc, aliases);
125153
flag->val.as_uint64 = def;
126154
flag->def.as_uint64 = def;
127155
return &flag->val.as_uint64;
128156
}
129157

130-
size_t *flag_size(const char *name, uint64_t def, const char *desc)
158+
size_t *flag_size_null(const char *name, uint64_t def, const char *desc, ...)
131159
{
132-
Flag *flag = flag_new(FLAG_SIZE, name, desc);
160+
va_list aliases;
161+
va_start(aliases, desc);
162+
Flag *flag = flag_new(FLAG_SIZE, name, desc, aliases);
133163
flag->val.as_size = def;
134164
flag->def.as_size = def;
135165
return &flag->val.as_size;
136166
}
137167

138-
char **flag_str(const char *name, const char *def, const char *desc)
168+
char **flag_str_null(const char *name, const char *def, const char *desc, ...)
139169
{
140-
Flag *flag = flag_new(FLAG_STR, name, desc);
170+
va_list aliases;
171+
va_start(aliases, desc);
172+
Flag *flag = flag_new(FLAG_STR, name, desc, aliases);
141173
flag->val.as_str = (char*) def;
142174
flag->def.as_str = (char*) def;
143175
return &flag->val.as_str;
@@ -190,7 +222,13 @@ bool flag_parse(int argc, char **argv)
190222

191223
bool found = false;
192224
for (size_t i = 0; i < c->flags_count; ++i) {
193-
if (strcmp(c->flags[i].name, flag) == 0) {
225+
bool is_name = strcmp(c->flags[i].name, flag) == 0;
226+
bool is_alias = false;
227+
for (size_t j = 0; !is_alias && j < c->flags[i].alias_count; ++j) {
228+
if (strcmp(c->flags[i].aliases[j], flag) == 0)
229+
is_alias = true;
230+
}
231+
if (is_name || is_alias) {
194232
static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type parsing");
195233
switch (c->flags[i].type) {
196234
case FLAG_BOOL: {
@@ -311,7 +349,10 @@ void flag_print_options(FILE *stream)
311349
for (size_t i = 0; i < c->flags_count; ++i) {
312350
Flag *flag = &c->flags[i];
313351

314-
fprintf(stream, " -%s\n", flag->name);
352+
fprintf(stream, " -%s", flag->name);
353+
for (size_t j = 0; j < flag->alias_count; ++j)
354+
fprintf(stream, ", -%s", flag->aliases[j]);
355+
fprintf(stream, "\n");
315356
fprintf(stream, " %s\n", flag->desc);
316357
static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type defaults printing");
317358
switch (c->flags[i].type) {

0 commit comments

Comments
 (0)