Skip to content

Commit f065af9

Browse files
committed
added retrieval for non flags (remaining) arguments
1 parent bd0de56 commit f065af9

File tree

4 files changed

+121
-51
lines changed

4 files changed

+121
-51
lines changed

flag/Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ CFLAGS = -std=c11 -Wall -Wextra -Wpedantic
33
DEBUGCFLAGS = -fsanitize=address,leak,undefined -g
44
LIBS = -lm
55

6-
.PHONY: all
6+
.PHONY: all clean
77
all: flag maintest
88

9-
test: all
9+
clean:
10+
rm *.o
11+
12+
test: maintest.c flag.c ../vec/vector.c ../bstr/bstr.c
1013
@rm -f a.out
11-
$(CC) $(DEBUGCFLAGS) $(LIBS) *.o
14+
$(CC) $(DEBUGCFLAGS) $(LIBS) $^
1215
@./a.out
1316

1417
flag: flag.c ../vec/vector.c ../bstr/bstr.c

flag/flag.c

Lines changed: 98 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
#include <stdlib.h>
77
#include <string.h>
88

9-
// todo: parser --flag=value
10-
// todo: find way to retrieve remaining args outside of flags
11-
129
struct flag_flag {
1310
bstr name;
1411
bstr usage;
@@ -41,6 +38,7 @@ flag_Parser flag_new(int argc, char *argv[]) {
4138
.argc = argc,
4239
.argv = argv,
4340
.flags = vec_new(sizeof(struct flag_flag *)),
41+
.remaining = vec_new(sizeof(char *)),
4442
.parsed = false,
4543
};
4644
}
@@ -53,6 +51,18 @@ void flag_free(flag_Parser *p) {
5351
}
5452

5553
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;
5666
}
5767

5868
#define CREATE_FLAG(T, flag_type) \
@@ -90,6 +100,42 @@ CREATE_FLAG(ulong, FLAG_ULONG)
90100
typedef unsigned long long ulonglong;
91101
CREATE_FLAG(ulonglong, FLAG_ULONGLONG)
92102

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+
93139
size_t flag_nflags(flag_Parser *p) { return vec_len(p->flags); }
94140

95141
static bool arg_is_flag(bstr *arg) {
@@ -116,6 +162,7 @@ void flag_parse(flag_Parser *p) {
116162
bstr arg = bstr_new(p->argv[curr_arg_idx]);
117163

118164
if (!arg_is_flag(&arg)) {
165+
vec_push(p->remaining, &arg.cstr);
119166
continue;
120167
}
121168

@@ -134,61 +181,67 @@ void flag_parse(flag_Parser *p) {
134181
struct flag_flag *curr_flag = NULL;
135182
for (size_t j = 0; j < vec_len(p->flags); j++) {
136183
vec_get(p->flags, j, &curr_flag);
184+
if (!bstr_equal(flag_name, curr_flag->name)) {
185+
continue;
186+
}
137187

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;
145189

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;
149193
}
150194

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+
}
161199

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;
165210

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;
169214

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;
173218

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;
177222

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;
181226

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;
185230

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;
190238
}
239+
240+
goto next_arg;
191241
}
242+
243+
next_arg:
244+
continue;
192245
}
193246

194247
p->parsed = true;

flag/flag.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
#include <stddef.h>
22
#include <stdbool.h>
33

4+
// todo: create doc comments
5+
46
typedef struct flag_parser {
57
int argc;
68
char **argv;
79
bool parsed;
810
struct vec_vector *flags;
11+
struct vec_vector *remaining;
912
} flag_Parser;
1013

1114
flag_Parser flag_new(int argc, char *argv[]);
1215
void flag_free(flag_Parser *p);
13-
size_t flag_nflags(flag_Parser *p);
16+
1417
void flag_parse(flag_Parser *p);
1518
bool flag_parsed(flag_Parser *p);
19+
size_t flag_nflags(flag_Parser *p);
20+
void flag_print_flags(flag_Parser *p);
21+
22+
23+
size_t flag_nargs(flag_Parser *p);
24+
char *flag_arg(flag_Parser *p, size_t idx);
25+
1626

1727
long *flag_long(flag_Parser *p, char *name, long default_val, char *usage);
1828
float *flag_float(flag_Parser *p, char *name, float default_val, char *usage);

flag/maintest.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
#include <string.h>
55

66
int main(void) {
7-
char *argv[] = {"--test=77", "--funnyno", "69420", "--is-true", "-pi", "3.14159265359", "--hello:world"};
7+
char *argv[] = {"--test=77", "--funnyno", "69420", "first_remaining", "--is-true", "-pi", "3.14159265359", "--hello:world", "second remaining"};
88
int argc = sizeof(argv) / sizeof(argv[0]);
99

1010
flag_Parser p = flag_new(argc, argv);
1111
assert(flag_nflags(&p) == 0);
1212
long *funny_num = flag_long(&p, "funnyno", 0, "the funny number");
1313
char **hello = flag_str(&p, "hello", "test", "says hello");
14-
double *pi = flag_double(&p, "pi", 0, "the number for pi");
14+
double *pi = flag_double(&p, "pi", 9.3, "the number for pi");
1515
long *test = flag_long(&p, "test", 99, "get number 99 or something else");
1616
bool *is_true = flag_bool(&p, "is-true", false, "returns true when used");
1717
assert(flag_nflags(&p) == 5);
@@ -20,6 +20,10 @@ int main(void) {
2020
flag_parse(&p);
2121
assert(flag_parsed(&p) == true);
2222

23+
assert(flag_nargs(&p) == 2);
24+
assert(strcmp(flag_arg(&p, 0), "first_remaining") == 0);
25+
assert(strcmp(flag_arg(&p, 1), "second remaining") == 0);
26+
2327
assert(*funny_num == 69420);
2428
assert(strcmp(*hello, "world") == 0);
2529
assert(*pi == 3.14159265359);

0 commit comments

Comments
 (0)