9
9
#include <stdio.h>
10
10
#include <stdlib.h>
11
11
#include <stdbool.h>
12
+ #include <stdarg.h>
12
13
#include <stdint.h>
13
14
#include <stddef.h>
14
15
#include <inttypes.h>
24
25
// WARNING! *_var functions may break the flag_name() functionality
25
26
26
27
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)
31
44
bool flag_parse (int argc , char * * argv );
32
45
int flag_rest_argc (void );
33
46
char * * flag_rest_argv (void );
@@ -66,9 +79,15 @@ typedef enum {
66
79
COUNT_FLAG_ERRORS ,
67
80
} Flag_Error ;
68
81
82
+ #ifndef ALIAS_CAP
83
+ #define ALIAS_CAP 12
84
+ #endif // ALIAS_CAP
85
+
69
86
typedef struct {
70
87
Flag_Type type ;
71
88
char * name ;
89
+ char * aliases [ALIAS_CAP ];
90
+ size_t alias_count ;
72
91
char * desc ;
73
92
Flag_Value val ;
74
93
Flag_Value def ;
@@ -91,7 +110,7 @@ typedef struct {
91
110
92
111
static Flag_Context flag_global_context ;
93
112
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 )
95
114
{
96
115
Flag_Context * c = & flag_global_context ;
97
116
@@ -102,6 +121,11 @@ Flag *flag_new(Flag_Type type, const char *name, const char *desc)
102
121
// NOTE: I won't touch them I promise Kappa
103
122
flag -> name = (char * ) name ;
104
123
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
+ }
105
129
return flag ;
106
130
}
107
131
@@ -111,33 +135,41 @@ char *flag_name(void *val)
111
135
return flag -> name ;
112
136
}
113
137
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 , ... )
115
139
{
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 );
117
143
flag -> def .as_bool = def ;
118
144
flag -> val .as_bool = def ;
119
145
return & flag -> val .as_bool ;
120
146
}
121
147
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 , ... )
123
149
{
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 );
125
153
flag -> val .as_uint64 = def ;
126
154
flag -> def .as_uint64 = def ;
127
155
return & flag -> val .as_uint64 ;
128
156
}
129
157
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 , ... )
131
159
{
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 );
133
163
flag -> val .as_size = def ;
134
164
flag -> def .as_size = def ;
135
165
return & flag -> val .as_size ;
136
166
}
137
167
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 , ... )
139
169
{
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 );
141
173
flag -> val .as_str = (char * ) def ;
142
174
flag -> def .as_str = (char * ) def ;
143
175
return & flag -> val .as_str ;
@@ -190,7 +222,13 @@ bool flag_parse(int argc, char **argv)
190
222
191
223
bool found = false;
192
224
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 ) {
194
232
static_assert (COUNT_FLAG_TYPES == 4 , "Exhaustive flag type parsing" );
195
233
switch (c -> flags [i ].type ) {
196
234
case FLAG_BOOL : {
@@ -311,7 +349,10 @@ void flag_print_options(FILE *stream)
311
349
for (size_t i = 0 ; i < c -> flags_count ; ++ i ) {
312
350
Flag * flag = & c -> flags [i ];
313
351
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" );
315
356
fprintf (stream , " %s\n" , flag -> desc );
316
357
static_assert (COUNT_FLAG_TYPES == 4 , "Exhaustive flag type defaults printing" );
317
358
switch (c -> flags [i ].type ) {
0 commit comments