winprefs v0.3.2
A registry exporter for programmers.
Loading...
Searching...
No Matches
arg.h
1/* arg.h -- A POSIX compliant argument parser based on plan9's arg(3)
2 * Olaf Bernstein <camel-cdr@protonmail.com>
3 * Distributed under the MIT license, see license at the end of the file.
4 * New versions available at https://github.com/camel-cdr/cauldron
5 */
6
7#ifndef ARG_H_INCLUDED
8
9static int ARG_LONG_func(wchar_t **argv0, char const *name) {
10 wchar_t *argIt = *argv0;
11 while (*argIt == *name && *argIt)
12 argIt++, name++;
13 if (*argIt == *name || (*argIt == '=' && !*name)) {
14 *argv0 = argIt;
15 return 1;
16 }
17 return 0;
18}
19
20#define ARG_BEGIN \
21 do { \
22 for (argv[0] && (--argc, ++argv); argv[0] && argv[0][0] == '-'; \
23 argv[0] && (--argc, ++argv)) { \
24 int isFlag = 1; \
25 wchar_t *arg = argv[0]; \
26 if (arg[1] == '-' && arg[2] == 0 && (--argc, ++argv, 1)) \
27 break; \
28 ARG_BEGIN_REP: \
29 switch ((++arg)[0]) { \
30 case '-': \
31 isFlag = 0; \
32 if (arg[-1] == '-') \
33 ++arg;
34
35#define ARG_LONG(name) ARG_LONG_func(&(arg), (name))
36
37#define ARG_VAL() \
38 (isFlag ? (arg[1] ? ++arg : *(--argc, ++argv)) : (arg[0] == '=' ? ++arg : *(--argc, ++argv)))
39
40#define ARG_FLAG() \
41 if (isFlag && arg[1]) \
42 goto ARG_BEGIN_REP
43
44#define ARG_END \
45 } \
46 } \
47 } \
48 while (0)
49
50#define ARG_H_INCLUDED
51#endif
52
53/*
54 * Example:
55 */
56
57#if defined(ARG_EXAMPLE) || defined(ARG_FUZZ)
58
59// spell-checker: disable
60
61#include <stdio.h>
62#include <stdlib.h>
63
64#ifdef ARG_FUZZ
65#define main argMain
66#undef stderr
67#define stderr stdout
68#endif
69
70int main(int argc, char **argv) {
71 char *argv0 = argv[0];
72 int a = 0, b = 0, c = 0, reverse = 0;
73 char const *input = "default", *output = "default";
74 int readstdin = 0;
75
76 ARG_BEGIN {
77 if (0) {
78 case 'a':
79 a = 1;
80 ARG_FLAG();
81 break;
82 case 'b':
83 b = 1;
84 ARG_FLAG();
85 break;
86 case 'c':
87 c = 1;
88 ARG_FLAG();
89 break;
90 case '\0':
91 readstdin = 1;
92 break;
93 } else if (ARG_LONG("reverse"))
94 case 'r': {
95 reverse = 1;
96 ARG_FLAG();
97 }
98 else if (ARG_LONG("input")) case 'i': {
99 input = ARG_VAL();
100 }
101 else if (ARG_LONG("output")) case 'o': {
102 output = ARG_VAL();
103 }
104 else if (ARG_LONG("help")) case 'h':
105 case '?': {
106 printf("Usage: %s [OPTION...] [STRING...]\n", argv0);
107 puts("Example usage of arg.h\n");
108 puts("Options:");
109 puts(" -a, set a to true");
110 puts(" -b, set b to true");
111 puts(" -c, set c to true");
112 puts(" -r, --reverse set reverse to true");
113 puts(" -i, --input=STR set input string to STR");
114 puts(" -o, --output=STR set output string to STR");
115 puts(" -h, --help display this help and exit");
116 return EXIT_SUCCESS;
117 }
118 else {
119 default:
120 fprintf(stderr,
121 "%s: invalid option '%s'\n"
122 "Try '%s --help' for more information.\n",
123 argv0,
124 *argv,
125 argv0);
126 return EXIT_FAILURE;
127 }
128 }
129 ARG_END;
130
131 printf("a = %s\n", a ? "true" : "false");
132 printf("b = %s\n", b ? "true" : "false");
133 printf("c = %s\n", c ? "true" : "false");
134 printf("reverse = %s\n", reverse ? "true" : "false");
135 printf("readstdin = %s\n", readstdin ? "true" : "false");
136 printf("input = %s\n", input);
137 printf("output = %s\n", output);
138
139 printf("\nargc: %d", argc);
140 puts("\nargv:");
141 while (*argv)
142 printf(" %s\n", *argv++);
143
144 return 0;
145}
146
147#endif /* ARG_EXAMPLE */
148
149/*
150 * Fuzzing:
151 */
152
153#ifdef ARG_FUZZ
154
155#include <stdint.h>
156#include <string.h>
157#define MAX_ARGC 50000
158
159int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
160 if (size < 2)
161 return -1;
162
163 char *buf = malloc(size + 2);
164 memcpy(buf, data, size);
165 buf[size] = buf[size + 1] = 0;
166
167 static char *argv[MAX_ARGC + 1];
168 size_t argc = 0;
169 for (char *ptr = buf; *ptr && argc < MAX_ARGC;) {
170 argv[argc++] = ptr;
171 while (*ptr++)
172 ;
173 }
174 argv[argc] = 0;
175
176 main(argc, argv);
177 free(buf);
178
179 return 0;
180}
181
182#endif
183
184/*
185 * Copyright (c) 2021 Olaf Berstein
186 * Permission is hereby granted, free of charge, to any person obtaining a copy
187 * of this software and associated documentation files (the "Software"), to deal
188 * in the Software without restriction, including without limitation the rights
189 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
190 * copies of the Software, and to permit persons to whom the Software is
191 * furnished to do so, subject to the following conditions:
192 * The above copyright notice and this permission notice shall be included in
193 * all copies or substantial portions of the Software.
194 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
195 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
196 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
197 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
199 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
200 * SOFTWARE.
201 */