Skip to content

Commit

Permalink
added retrieval for non flags (remaining) arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphGL committed Jul 23, 2024
1 parent bd0de56 commit f065af9
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 51 deletions.
9 changes: 6 additions & 3 deletions flag/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ CFLAGS = -std=c11 -Wall -Wextra -Wpedantic
DEBUGCFLAGS = -fsanitize=address,leak,undefined -g
LIBS = -lm

.PHONY: all
.PHONY: all clean
all: flag maintest

test: all
clean:
rm *.o

test: maintest.c flag.c ../vec/vector.c ../bstr/bstr.c
@rm -f a.out
$(CC) $(DEBUGCFLAGS) $(LIBS) *.o
$(CC) $(DEBUGCFLAGS) $(LIBS) $^
@./a.out

flag: flag.c ../vec/vector.c ../bstr/bstr.c
Expand Down
143 changes: 98 additions & 45 deletions flag/flag.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
#include <stdlib.h>
#include <string.h>

// todo: parser --flag=value
// todo: find way to retrieve remaining args outside of flags

struct flag_flag {
bstr name;
bstr usage;
Expand Down Expand Up @@ -41,6 +38,7 @@ flag_Parser flag_new(int argc, char *argv[]) {
.argc = argc,
.argv = argv,
.flags = vec_new(sizeof(struct flag_flag *)),
.remaining = vec_new(sizeof(char *)),
.parsed = false,
};
}
Expand All @@ -53,6 +51,18 @@ void flag_free(flag_Parser *p) {
}

vec_free(p->flags);
vec_free(p->remaining);
}

size_t flag_nargs(flag_Parser *p) { return vec_len(p->remaining); }

char *flag_arg(flag_Parser *p, size_t idx) {
char *arg;
if (!vec_get(p->remaining, idx, &arg)) {
return NULL;
}

return arg;
}

#define CREATE_FLAG(T, flag_type) \
Expand Down Expand Up @@ -90,6 +100,42 @@ CREATE_FLAG(ulong, FLAG_ULONG)
typedef unsigned long long ulonglong;
CREATE_FLAG(ulonglong, FLAG_ULONGLONG)

void flag_print_flags(flag_Parser *p) {
for (size_t i = 0; i < vec_len(p->flags); i++) {
struct flag_flag *curr_flag;
vec_get(p->flags, i, &curr_flag);
printf("--%s\n\t%s", curr_flag->name.cstr, curr_flag->usage.cstr);
printf(" (default: ");
switch (curr_flag->type) {
case FLAG_BOOL:
printf(curr_flag->bool_flag ? "true" : "false");
break;
case FLAG_DOUBLE:
printf("%lf", curr_flag->double_flag);
break;
case FLAG_FLOAT:
printf("%f", curr_flag->float_flag);
break;
case FLAG_LONG:
printf("%ld", curr_flag->long_flag);
break;
case FLAG_LONGLONG:
printf("%lld", curr_flag->longlong_flag);
break;
case FLAG_ULONGLONG:
printf("%llu", curr_flag->ulonglong_flag);
break;
case FLAG_STR:
printf("%s", curr_flag->str_flag);
break;
case FLAG_ULONG:
printf("%lu", curr_flag->ulong_flag);
break;
}
puts(")");
}
}

size_t flag_nflags(flag_Parser *p) { return vec_len(p->flags); }

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

if (!arg_is_flag(&arg)) {
vec_push(p->remaining, &arg.cstr);
continue;
}

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

if (bstr_equal(flag_name, curr_flag->name)) {
char *flag_val = NULL;

if (flag_value.len == 0 && curr_flag->type != FLAG_BOOL) {
if (++curr_arg_idx >= p->argc) {
break;
}
char *flag_val = NULL;

flag_val = p->argv[curr_arg_idx];
} else {
flag_val = flag_value.cstr;
if (flag_value.len == 0 && curr_flag->type != FLAG_BOOL) {
if (++curr_arg_idx >= p->argc) {
break;
}

switch (curr_flag->type) {
case FLAG_BOOL:
if (flag_value.len == 0) {
curr_flag->bool_flag = !curr_flag->bool_flag;
} else if (bstr_equal(flag_value, bstr_new("true"))) {
curr_flag->bool_flag = true;
} else if (bstr_equal(flag_value, bstr_new("false"))) {
curr_flag->bool_flag = false;
}
break;
flag_val = p->argv[curr_arg_idx];
} else {
flag_val = flag_value.cstr;
}

case FLAG_STR:
curr_flag->str_flag = flag_val;
break;
switch (curr_flag->type) {
case FLAG_BOOL:
if (flag_value.len == 0) {
curr_flag->bool_flag = !curr_flag->bool_flag;
} else if (bstr_equal(flag_value, bstr_new("true"))) {
curr_flag->bool_flag = true;
} else if (bstr_equal(flag_value, bstr_new("false"))) {
curr_flag->bool_flag = false;
}
break;

case FLAG_LONG:
curr_flag->long_flag = strtol(flag_val, NULL, 10);
break;
case FLAG_STR:
curr_flag->str_flag = flag_val;
break;

case FLAG_ULONG:
curr_flag->ulong_flag = strtoul(flag_val, NULL, 10);
break;
case FLAG_LONG:
curr_flag->long_flag = strtol(flag_val, NULL, 10);
break;

case FLAG_LONGLONG:
curr_flag->longlong_flag = strtoll(flag_val, NULL, 10);
break;
case FLAG_ULONG:
curr_flag->ulong_flag = strtoul(flag_val, NULL, 10);
break;

case FLAG_ULONGLONG:
curr_flag->ulonglong_flag = strtoull(flag_val, NULL, 10);
break;
case FLAG_LONGLONG:
curr_flag->longlong_flag = strtoll(flag_val, NULL, 10);
break;

case FLAG_DOUBLE:
curr_flag->double_flag = strtod(flag_val, NULL);
break;
case FLAG_ULONGLONG:
curr_flag->ulonglong_flag = strtoull(flag_val, NULL, 10);
break;

case FLAG_FLOAT:
curr_flag->float_flag = strtof(flag_val, NULL);
break;
}
case FLAG_DOUBLE:
curr_flag->double_flag = strtod(flag_val, NULL);
break;

case FLAG_FLOAT:
curr_flag->float_flag = strtof(flag_val, NULL);
break;
}

goto next_arg;
}

next_arg:
continue;
}

p->parsed = true;
Expand Down
12 changes: 11 additions & 1 deletion flag/flag.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
#include <stddef.h>
#include <stdbool.h>

// todo: create doc comments

typedef struct flag_parser {
int argc;
char **argv;
bool parsed;
struct vec_vector *flags;
struct vec_vector *remaining;
} flag_Parser;

flag_Parser flag_new(int argc, char *argv[]);
void flag_free(flag_Parser *p);
size_t flag_nflags(flag_Parser *p);

void flag_parse(flag_Parser *p);
bool flag_parsed(flag_Parser *p);
size_t flag_nflags(flag_Parser *p);
void flag_print_flags(flag_Parser *p);


size_t flag_nargs(flag_Parser *p);
char *flag_arg(flag_Parser *p, size_t idx);


long *flag_long(flag_Parser *p, char *name, long default_val, char *usage);
float *flag_float(flag_Parser *p, char *name, float default_val, char *usage);
Expand Down
8 changes: 6 additions & 2 deletions flag/maintest.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#include <string.h>

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

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

assert(flag_nargs(&p) == 2);
assert(strcmp(flag_arg(&p, 0), "first_remaining") == 0);
assert(strcmp(flag_arg(&p, 1), "second remaining") == 0);

assert(*funny_num == 69420);
assert(strcmp(*hello, "world") == 0);
assert(*pi == 3.14159265359);
Expand Down

0 comments on commit f065af9

Please sign in to comment.