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