Created
September 22, 2023 20:28
-
-
Save pommicket/78c4332deac145a2f92a695b009f7c64 to your computer and use it in GitHub Desktop.
tiny C argument parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
tiny argument parser | |
accepts both - and -- prefixes (they are treated the same) | |
usage: | |
ArgParser parser = {.argc = argc, .argv = argv, .options_with_value = "output,foo"}; | |
while (arg_parser_next(&parser)) { | |
if (!parser.option) { | |
printf("standalone argument %s\n", parser.value); | |
} else if (strcmp(parser.option, "output") == 0) { | |
printf("outputting to %s...\n", parser.value); | |
} else if (strcmp(parser.option, "foo") == 0) { | |
printf("your foo is %s\n", parser.value); | |
} else if (strcmp(parser.option, "bar") == 0) { | |
// parser.value will be NULL | |
printf("you passed in the bar flag!\n"); | |
} else if (parser.option) { | |
printf("unrecognized option: %s\n", parser.option); | |
exit(EXIT_FAILURE); | |
} | |
} | |
wow its so simple! | |
license: 0BSD | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
typedef struct { | |
int argc; | |
char **argv; | |
const char *options_with_value; | |
const char *option; | |
const char *value; | |
int i; | |
unsigned char no_option; | |
} ArgParser; | |
static int arg_parser_next(ArgParser *parser) { | |
top: | |
if (parser->i <= 0) | |
parser->i = 1; | |
if (parser->i >= parser->argc) | |
return 0; | |
const char *const arg = parser->argv[parser->i++]; | |
if (parser->no_option) | |
goto no_option; | |
if (arg[0] == '-') { | |
const char *option = arg + 1; | |
if (option[0] == '-') { | |
option += 1; | |
} | |
if (option[0] == '\0') { | |
parser->no_option = 1; | |
goto top; | |
} | |
int requires_arg = 0; | |
const char *p = parser->options_with_value; | |
while (p && *p) { | |
size_t n = strcspn(p, ","); | |
if (strncmp(p, option, n) == 0) { | |
requires_arg = 1; | |
break; | |
} | |
p += n; | |
while (*p == ',') | |
p += 1; | |
} | |
if (requires_arg) { | |
parser->option = option; | |
if (parser->i >= parser->argc) { | |
fprintf(stderr, "Error: no value provided for option %s\n", option); | |
exit(EXIT_FAILURE); | |
} | |
parser->value = parser->argv[parser->i++]; | |
} else { | |
parser->option = option; | |
parser->value = 0; | |
} | |
return 1; | |
} | |
no_option: | |
parser->option = 0; | |
parser->value = arg; | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment