summaryrefslogtreecommitdiff
path: root/argparser.h
blob: 6c97b42561af023ba0d37046b3a8a92445418892 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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;
}