94 lines
2.2 KiB
C
94 lines
2.2 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <args/args.h>
|
|
#include <string/conv.h>
|
|
#include <string/string.h>
|
|
#include <uprintf.h>
|
|
#include <errors.h>
|
|
|
|
int32_t parse_args(char **argv, size_t argc, Arg *defs) {
|
|
#define CONSUME_TK() i++
|
|
|
|
if (!argv || !defs) {
|
|
return E_INVALIDARGUMENT;
|
|
}
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
char *arg = argv[i];
|
|
if (!arg) {
|
|
continue;
|
|
}
|
|
|
|
if (arg[0] == '-' && arg[1] != '\0') {
|
|
size_t j = 0;
|
|
while (!defs[j].end) {
|
|
Arg *def = &defs[j];
|
|
|
|
if (!def->shortname || !def->ptr) {
|
|
j++;
|
|
continue;
|
|
}
|
|
|
|
if (string_strcmp(def->shortname, arg) == 0) {
|
|
bool have_next = (i + 1) < argc && argv[i + 1] != NULL;
|
|
char *nexttk = have_next ? argv[i + 1] : NULL;
|
|
|
|
if (nexttk && nexttk[0] == '-' && nexttk[1] != '\0') {
|
|
have_next = false;
|
|
nexttk = NULL;
|
|
}
|
|
|
|
switch (def->expected_value) {
|
|
case ARG_STRING:
|
|
if (!have_next) {
|
|
break;
|
|
}
|
|
*((char **)def->ptr) = nexttk;
|
|
CONSUME_TK();
|
|
break;
|
|
case ARG_BOOL:
|
|
if (!have_next) {
|
|
*((bool *)def->ptr) = true;
|
|
} else {
|
|
if (string_strcmp(nexttk, "yes") == 0) {
|
|
*((bool *)def->ptr) = true;
|
|
CONSUME_TK();
|
|
} else if (string_strcmp(nexttk, "no") == 0) {
|
|
*((bool *)def->ptr) = false;
|
|
CONSUME_TK();
|
|
} else {
|
|
*((bool *)def->ptr) = true;
|
|
}
|
|
}
|
|
break;
|
|
case ARG_INT:
|
|
if (!have_next) {
|
|
break;
|
|
}
|
|
char *endptr = NULL;
|
|
long val = string_conv_strtol(nexttk, &endptr, 10);
|
|
if (endptr == NULL) {
|
|
break;
|
|
}
|
|
if (*endptr != '\0') {
|
|
break;
|
|
}
|
|
*((int32_t *)def->ptr) = (int32_t)val;
|
|
CONSUME_TK();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return E_OK;
|
|
}
|