6
6
#include <stdlib.h>
7
7
#include <string.h>
8
8
9
- // todo: parser --flag=value
10
- // todo: find way to retrieve remaining args outside of flags
11
-
12
9
struct flag_flag {
13
10
bstr name ;
14
11
bstr usage ;
@@ -41,6 +38,7 @@ flag_Parser flag_new(int argc, char *argv[]) {
41
38
.argc = argc ,
42
39
.argv = argv ,
43
40
.flags = vec_new (sizeof (struct flag_flag * )),
41
+ .remaining = vec_new (sizeof (char * )),
44
42
.parsed = false,
45
43
};
46
44
}
@@ -53,6 +51,18 @@ void flag_free(flag_Parser *p) {
53
51
}
54
52
55
53
vec_free (p -> flags );
54
+ vec_free (p -> remaining );
55
+ }
56
+
57
+ size_t flag_nargs (flag_Parser * p ) { return vec_len (p -> remaining ); }
58
+
59
+ char * flag_arg (flag_Parser * p , size_t idx ) {
60
+ char * arg ;
61
+ if (!vec_get (p -> remaining , idx , & arg )) {
62
+ return NULL ;
63
+ }
64
+
65
+ return arg ;
56
66
}
57
67
58
68
#define CREATE_FLAG (T , flag_type ) \
@@ -90,6 +100,42 @@ CREATE_FLAG(ulong, FLAG_ULONG)
90
100
typedef unsigned long long ulonglong ;
91
101
CREATE_FLAG (ulonglong , FLAG_ULONGLONG )
92
102
103
+ void flag_print_flags (flag_Parser * p ) {
104
+ for (size_t i = 0 ; i < vec_len (p -> flags ); i ++ ) {
105
+ struct flag_flag * curr_flag ;
106
+ vec_get (p -> flags , i , & curr_flag );
107
+ printf ("--%s\n\t%s" , curr_flag -> name .cstr , curr_flag -> usage .cstr );
108
+ printf (" (default: " );
109
+ switch (curr_flag -> type ) {
110
+ case FLAG_BOOL :
111
+ printf (curr_flag -> bool_flag ? "true" : "false" );
112
+ break ;
113
+ case FLAG_DOUBLE :
114
+ printf ("%lf" , curr_flag -> double_flag );
115
+ break ;
116
+ case FLAG_FLOAT :
117
+ printf ("%f" , curr_flag -> float_flag );
118
+ break ;
119
+ case FLAG_LONG :
120
+ printf ("%ld" , curr_flag -> long_flag );
121
+ break ;
122
+ case FLAG_LONGLONG :
123
+ printf ("%lld" , curr_flag -> longlong_flag );
124
+ break ;
125
+ case FLAG_ULONGLONG :
126
+ printf ("%llu" , curr_flag -> ulonglong_flag );
127
+ break ;
128
+ case FLAG_STR :
129
+ printf ("%s" , curr_flag -> str_flag );
130
+ break ;
131
+ case FLAG_ULONG :
132
+ printf ("%lu" , curr_flag -> ulong_flag );
133
+ break ;
134
+ }
135
+ puts (")" );
136
+ }
137
+ }
138
+
93
139
size_t flag_nflags (flag_Parser * p ) { return vec_len (p -> flags ); }
94
140
95
141
static bool arg_is_flag (bstr * arg ) {
@@ -116,6 +162,7 @@ void flag_parse(flag_Parser *p) {
116
162
bstr arg = bstr_new (p -> argv [curr_arg_idx ]);
117
163
118
164
if (!arg_is_flag (& arg )) {
165
+ vec_push (p -> remaining , & arg .cstr );
119
166
continue ;
120
167
}
121
168
@@ -134,61 +181,67 @@ void flag_parse(flag_Parser *p) {
134
181
struct flag_flag * curr_flag = NULL ;
135
182
for (size_t j = 0 ; j < vec_len (p -> flags ); j ++ ) {
136
183
vec_get (p -> flags , j , & curr_flag );
184
+ if (!bstr_equal (flag_name , curr_flag -> name )) {
185
+ continue ;
186
+ }
137
187
138
- if (bstr_equal (flag_name , curr_flag -> name )) {
139
- char * flag_val = NULL ;
140
-
141
- if (flag_value .len == 0 && curr_flag -> type != FLAG_BOOL ) {
142
- if (++ curr_arg_idx >= p -> argc ) {
143
- break ;
144
- }
188
+ char * flag_val = NULL ;
145
189
146
- flag_val = p -> argv [ curr_arg_idx ];
147
- } else {
148
- flag_val = flag_value . cstr ;
190
+ if ( flag_value . len == 0 && curr_flag -> type != FLAG_BOOL ) {
191
+ if ( ++ curr_arg_idx >= p -> argc ) {
192
+ break ;
149
193
}
150
194
151
- switch (curr_flag -> type ) {
152
- case FLAG_BOOL :
153
- if (flag_value .len == 0 ) {
154
- curr_flag -> bool_flag = !curr_flag -> bool_flag ;
155
- } else if (bstr_equal (flag_value , bstr_new ("true" ))) {
156
- curr_flag -> bool_flag = true;
157
- } else if (bstr_equal (flag_value , bstr_new ("false" ))) {
158
- curr_flag -> bool_flag = false;
159
- }
160
- break ;
195
+ flag_val = p -> argv [curr_arg_idx ];
196
+ } else {
197
+ flag_val = flag_value .cstr ;
198
+ }
161
199
162
- case FLAG_STR :
163
- curr_flag -> str_flag = flag_val ;
164
- break ;
200
+ switch (curr_flag -> type ) {
201
+ case FLAG_BOOL :
202
+ if (flag_value .len == 0 ) {
203
+ curr_flag -> bool_flag = !curr_flag -> bool_flag ;
204
+ } else if (bstr_equal (flag_value , bstr_new ("true" ))) {
205
+ curr_flag -> bool_flag = true;
206
+ } else if (bstr_equal (flag_value , bstr_new ("false" ))) {
207
+ curr_flag -> bool_flag = false;
208
+ }
209
+ break ;
165
210
166
- case FLAG_LONG :
167
- curr_flag -> long_flag = strtol ( flag_val , NULL , 10 ) ;
168
- break ;
211
+ case FLAG_STR :
212
+ curr_flag -> str_flag = flag_val ;
213
+ break ;
169
214
170
- case FLAG_ULONG :
171
- curr_flag -> ulong_flag = strtoul (flag_val , NULL , 10 );
172
- break ;
215
+ case FLAG_LONG :
216
+ curr_flag -> long_flag = strtol (flag_val , NULL , 10 );
217
+ break ;
173
218
174
- case FLAG_LONGLONG :
175
- curr_flag -> longlong_flag = strtoll (flag_val , NULL , 10 );
176
- break ;
219
+ case FLAG_ULONG :
220
+ curr_flag -> ulong_flag = strtoul (flag_val , NULL , 10 );
221
+ break ;
177
222
178
- case FLAG_ULONGLONG :
179
- curr_flag -> ulonglong_flag = strtoull (flag_val , NULL , 10 );
180
- break ;
223
+ case FLAG_LONGLONG :
224
+ curr_flag -> longlong_flag = strtoll (flag_val , NULL , 10 );
225
+ break ;
181
226
182
- case FLAG_DOUBLE :
183
- curr_flag -> double_flag = strtod (flag_val , NULL );
184
- break ;
227
+ case FLAG_ULONGLONG :
228
+ curr_flag -> ulonglong_flag = strtoull (flag_val , NULL , 10 );
229
+ break ;
185
230
186
- case FLAG_FLOAT :
187
- curr_flag -> float_flag = strtof (flag_val , NULL );
188
- break ;
189
- }
231
+ case FLAG_DOUBLE :
232
+ curr_flag -> double_flag = strtod (flag_val , NULL );
233
+ break ;
234
+
235
+ case FLAG_FLOAT :
236
+ curr_flag -> float_flag = strtof (flag_val , NULL );
237
+ break ;
190
238
}
239
+
240
+ goto next_arg ;
191
241
}
242
+
243
+ next_arg :
244
+ continue ;
192
245
}
193
246
194
247
p -> parsed = true;
0 commit comments