summaryrefslogtreecommitdiff
path: root/src/user/lib/vendor/getopt/getopt.c
blob: 63c9b512451253adf777f0b50fc7b103806e1379 (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
65
66
67
68
69
70
71
72
73
74
75
/* Adapted from https://github.com/skeeto/getopt by Chris Wellons */

/* A minimal POSIX getopt() implementation in ANSI C
 *
 * This is free and unencumbered software released into the public domain.
 *
 * This implementation supports the convention of resetting the option
 * parser by assigning optind to 0. This resets the internal state
 * appropriately.
 *
 * Ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
 */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "getopt.h"

int optind;
int opterr = 1;
int optopt;
char *optarg;

int
getopt(int argc, char * const argv[], const char *optstring)
{
	static int optpos = 1;
	const char *arg;

	/* Reset? */
	if (optind == 0) {
		optind = !!argc;
		optpos = 1;
	}

	arg = argv[optind];
	if (arg && strcmp(arg, "--") == 0) {
		optind++;
		return -1;
	} else if (!arg || arg[0] != '-' || !isalnum(arg[1])) {
		return -1;
	} else {
		const char *opt = strchr(optstring, arg[optpos]);
		optopt = arg[optpos];
		if (!opt) {
			if (opterr && *optstring != ':')
				fprintf(stderr, "%s: illegal option: %c\n", argv[0], optopt);
			return '?';
		} else if (opt[1] == ':') {
			if (arg[optpos + 1]) {
				optarg = (char *)arg + optpos + 1;
				optind++;
				optpos = 1;
				return optopt;
			} else if (argv[optind + 1]) {
				optarg = (char *)argv[optind + 1];
				optind += 2;
				optpos = 1;
				return optopt;
			} else {
				if (opterr && *optstring != ':')
					fprintf(stderr,
					        "%s: option requires an argument: %c\n",
					        argv[0], optopt);
				return *optstring == ':' ? ':' : '?';
			}
		} else {
			if (!arg[++optpos]) {
				optind++;
				optpos = 1;
			}
			return optopt;
		}
	}
}