summaryrefslogtreecommitdiff
path: root/argparser.h
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-02-25 23:14:56 -0500
committerpommicket <pommicket@gmail.com>2025-02-25 23:14:56 -0500
commit61a935b9d204e54d6948ea7b94536e390b6dde71 (patch)
tree140283fa62cb208a40324e2222d6a3381cf1c539 /argparser.h
parent753651a2c21b5e7fc6725560ffdd5d4c01732359 (diff)
command-line arguments
Diffstat (limited to 'argparser.h')
-rw-r--r--argparser.h64
1 files changed, 64 insertions, 0 deletions
diff --git a/argparser.h b/argparser.h
new file mode 100644
index 0000000..6c97b42
--- /dev/null
+++ b/argparser.h
@@ -0,0 +1,64 @@
+#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 && 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;
+}