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>
2425// WARNING! *_var functions may break the flag_name() functionality
2526
2627char * 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)
3144bool flag_parse (int argc , char * * argv );
3245int flag_rest_argc (void );
3346char * * 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+
6986typedef 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
92111static 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