xref: /linux/tools/include/nolibc/getopt.h (revision 015a99fa76650e7d6efa3e36f20c0f5b346fe9ce)
1bae3cd70SThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2bae3cd70SThomas Weißschuh /*
3bae3cd70SThomas Weißschuh  * getopt function definitions for NOLIBC, adapted from musl libc
4bae3cd70SThomas Weißschuh  * Copyright (C) 2005-2020 Rich Felker, et al.
5bae3cd70SThomas Weißschuh  * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
6bae3cd70SThomas Weißschuh  */
7bae3cd70SThomas Weißschuh 
8*3785289fSThomas Weißschuh /* make sure to include all global symbols */
9*3785289fSThomas Weißschuh #include "nolibc.h"
10*3785289fSThomas Weißschuh 
11bae3cd70SThomas Weißschuh #ifndef _NOLIBC_GETOPT_H
12bae3cd70SThomas Weißschuh #define _NOLIBC_GETOPT_H
13bae3cd70SThomas Weißschuh 
14bae3cd70SThomas Weißschuh struct FILE;
15bae3cd70SThomas Weißschuh static struct FILE *const stderr;
16bae3cd70SThomas Weißschuh static int fprintf(struct FILE *stream, const char *fmt, ...);
17bae3cd70SThomas Weißschuh 
18bae3cd70SThomas Weißschuh __attribute__((weak,unused,section(".data.nolibc_getopt")))
19bae3cd70SThomas Weißschuh char *optarg;
20bae3cd70SThomas Weißschuh 
21bae3cd70SThomas Weißschuh __attribute__((weak,unused,section(".data.nolibc_getopt")))
22bae3cd70SThomas Weißschuh int optind = 1, opterr = 1, optopt;
23bae3cd70SThomas Weißschuh 
24bae3cd70SThomas Weißschuh static __attribute__((unused))
getopt(int argc,char * const argv[],const char * optstring)25bae3cd70SThomas Weißschuh int getopt(int argc, char * const argv[], const char *optstring)
26bae3cd70SThomas Weißschuh {
27bae3cd70SThomas Weißschuh 	static int __optpos;
28bae3cd70SThomas Weißschuh 	int i;
29bae3cd70SThomas Weißschuh 	char c, d;
30bae3cd70SThomas Weißschuh 	char *optchar;
31bae3cd70SThomas Weißschuh 
32bae3cd70SThomas Weißschuh 	if (!optind) {
33bae3cd70SThomas Weißschuh 		__optpos = 0;
34bae3cd70SThomas Weißschuh 		optind = 1;
35bae3cd70SThomas Weißschuh 	}
36bae3cd70SThomas Weißschuh 
37bae3cd70SThomas Weißschuh 	if (optind >= argc || !argv[optind])
38bae3cd70SThomas Weißschuh 		return -1;
39bae3cd70SThomas Weißschuh 
40bae3cd70SThomas Weißschuh 	if (argv[optind][0] != '-') {
41bae3cd70SThomas Weißschuh 		if (optstring[0] == '-') {
42bae3cd70SThomas Weißschuh 			optarg = argv[optind++];
43bae3cd70SThomas Weißschuh 			return 1;
44bae3cd70SThomas Weißschuh 		}
45bae3cd70SThomas Weißschuh 		return -1;
46bae3cd70SThomas Weißschuh 	}
47bae3cd70SThomas Weißschuh 
48bae3cd70SThomas Weißschuh 	if (!argv[optind][1])
49bae3cd70SThomas Weißschuh 		return -1;
50bae3cd70SThomas Weißschuh 
51bae3cd70SThomas Weißschuh 	if (argv[optind][1] == '-' && !argv[optind][2])
52bae3cd70SThomas Weißschuh 		return optind++, -1;
53bae3cd70SThomas Weißschuh 
54bae3cd70SThomas Weißschuh 	if (!__optpos)
55bae3cd70SThomas Weißschuh 		__optpos++;
56bae3cd70SThomas Weißschuh 	c = argv[optind][__optpos];
57bae3cd70SThomas Weißschuh 	optchar = argv[optind] + __optpos;
58bae3cd70SThomas Weißschuh 	__optpos++;
59bae3cd70SThomas Weißschuh 
60bae3cd70SThomas Weißschuh 	if (!argv[optind][__optpos]) {
61bae3cd70SThomas Weißschuh 		optind++;
62bae3cd70SThomas Weißschuh 		__optpos = 0;
63bae3cd70SThomas Weißschuh 	}
64bae3cd70SThomas Weißschuh 
65bae3cd70SThomas Weißschuh 	if (optstring[0] == '-' || optstring[0] == '+')
66bae3cd70SThomas Weißschuh 		optstring++;
67bae3cd70SThomas Weißschuh 
68bae3cd70SThomas Weißschuh 	i = 0;
69bae3cd70SThomas Weißschuh 	d = 0;
70bae3cd70SThomas Weißschuh 	do {
71bae3cd70SThomas Weißschuh 		d = optstring[i++];
72bae3cd70SThomas Weißschuh 	} while (d && d != c);
73bae3cd70SThomas Weißschuh 
74bae3cd70SThomas Weißschuh 	if (d != c || c == ':') {
75bae3cd70SThomas Weißschuh 		optopt = c;
76bae3cd70SThomas Weißschuh 		if (optstring[0] != ':' && opterr)
77bae3cd70SThomas Weißschuh 			fprintf(stderr, "%s: unrecognized option: %c\n", argv[0], *optchar);
78bae3cd70SThomas Weißschuh 		return '?';
79bae3cd70SThomas Weißschuh 	}
80bae3cd70SThomas Weißschuh 	if (optstring[i] == ':') {
81bae3cd70SThomas Weißschuh 		optarg = 0;
82bae3cd70SThomas Weißschuh 		if (optstring[i + 1] != ':' || __optpos) {
83bae3cd70SThomas Weißschuh 			optarg = argv[optind++];
84bae3cd70SThomas Weißschuh 			if (__optpos)
85bae3cd70SThomas Weißschuh 				optarg += __optpos;
86bae3cd70SThomas Weißschuh 			__optpos = 0;
87bae3cd70SThomas Weißschuh 		}
88bae3cd70SThomas Weißschuh 		if (optind > argc) {
89bae3cd70SThomas Weißschuh 			optopt = c;
90bae3cd70SThomas Weißschuh 			if (optstring[0] == ':')
91bae3cd70SThomas Weißschuh 				return ':';
92bae3cd70SThomas Weißschuh 			if (opterr)
93bae3cd70SThomas Weißschuh 				fprintf(stderr, "%s: option requires argument: %c\n",
94bae3cd70SThomas Weißschuh 					argv[0], *optchar);
95bae3cd70SThomas Weißschuh 			return '?';
96bae3cd70SThomas Weißschuh 		}
97bae3cd70SThomas Weißschuh 	}
98bae3cd70SThomas Weißschuh 	return c;
99bae3cd70SThomas Weißschuh }
100bae3cd70SThomas Weißschuh 
101bae3cd70SThomas Weißschuh #endif /* _NOLIBC_GETOPT_H */
102