9 * Standard getopt global variables. optreset starts as non-zero in order to
10 * trigger initialization behaviour.
12 const char * optarg
= NULL
;
18 * Quasi-internal global variables -- these are used via GETOPT macros.
20 const char * getopt_dummy
= "(dummy)";
21 int getopt_initialized
= 0;
26 static const char * cmdname
= NULL
;
33 static size_t opt_missing
;
34 static size_t opt_default
;
35 static size_t opt_found
;
36 static const char * packedopts
;
38 static int atexit_registered
= 0;
40 /* Print a message. */
41 #define PRINTMSG(...) do { \
42 if (cmdname != NULL) \
43 fprintf(stderr, "%s: ", cmdname); \
44 fprintf(stderr, __VA_ARGS__); \
45 fprintf(stderr, "\n"); \
48 /* Print an error message and die. */
49 #define DIE(...) do { \
50 PRINTMSG(__VA_ARGS__); \
54 /* Print a warning, if warnings are enabled. */
55 #define WARN(...) do { \
58 if (opt_missing != opt_default) \
60 PRINTMSG(__VA_ARGS__); \
63 /* Free allocated options array. */
72 /* Reset internal state. */
74 reset(int argc
, char * const argv
[])
78 /* If we have arguments, stash argv[0] for error messages. */
80 /* Find the basename, without leading directories. */
81 for (p
= cmdname
= argv
[0]; *p
!= '\0'; p
++) {
87 /* Discard any registered command-line options. */
91 /* Register atexit handler if we haven't done so already. */
92 if (!atexit_registered
) {
93 atexit(atexit_handler
);
94 atexit_registered
= 1;
97 /* We will start scanning from the first option. */
100 /* We're not in the middle of any packed options. */
103 /* We haven't found any option yet. */
104 opt_found
= (size_t)(-1);
106 /* We're not initialized yet. */
107 getopt_initialized
= 0;
109 /* Finished resetting state. */
113 /* Search for an option string. */
115 searchopt(const char * os
)
119 /* Scan the array of options. */
120 for (i
= 0; i
< nopts
; i
++) {
121 /* Is there an option in this slot? */
122 if (opts
[i
].os
== NULL
)
125 /* Does this match up to the length of the option string? */
126 if (strncmp(opts
[i
].os
, os
, opts
[i
].olen
))
129 /* Do we have <option>\0 or <option>= ? */
130 if ((os
[opts
[i
].olen
] == '\0') || (os
[opts
[i
].olen
] == '='))
135 return (opt_default
);
139 getopt(int argc
, char * const argv
[])
141 const char * os
= NULL
;
142 const char * canonical_os
= NULL
;
144 /* No argument yet. */
147 /* Reset the getopt state if needed. */
151 /* If not initialized, return dummy option. */
152 if (!getopt_initialized
)
153 return (GETOPT_DUMMY
);
155 /* If we've run out of arguments, we're done. */
160 * If we're not already in the middle of a packed single-character
161 * options, see if we should start.
163 if ((packedopts
== NULL
) && (argv
[optind
][0] == '-') &&
164 (argv
[optind
][1] != '-') && (argv
[optind
][1] != '\0')) {
165 /* We have one or more single-character options. */
166 packedopts
= &argv
[optind
][1];
169 /* If we're processing single-character options, fish one out. */
170 if (packedopts
!= NULL
) {
171 /* Construct the option string. */
173 popt
[1] = *packedopts
;
177 /* We've done this character. */
180 /* Are we done with this string? */
181 if (*packedopts
== '\0') {
187 /* If we don't have an option yet, do we have dash-dash? */
188 if ((os
== NULL
) && (argv
[optind
][0] == '-') &&
189 (argv
[optind
][1] == '-')) {
190 /* If this is not "--\0", it's an option. */
191 if (argv
[optind
][2] != '\0')
194 /* Either way, we want to eat the string. */
198 /* If we have found nothing which looks like an option, we're done. */
202 /* Search for the potential option. */
203 opt_found
= searchopt(os
);
205 /* If the option is not registered, give up now. */
206 if (opt_found
== opt_default
) {
207 WARN("unknown option: %s", os
);
211 /* The canonical option string is the one registered. */
212 canonical_os
= opts
[opt_found
].os
;
214 /* Does the option take an argument? */
215 if (opts
[opt_found
].hasarg
) {
217 * If we're processing packed single-character options, the
218 * rest of the string is the argument to this option.
220 if (packedopts
!= NULL
) {
227 * If the option string is <option>=<value>, extract that
228 * value as the option argument.
230 if (os
[opts
[opt_found
].olen
] == '=')
231 optarg
= &os
[opts
[opt_found
].olen
+ 1];
234 * If we don't have an argument yet, take one from the
235 * remaining command line.
237 if ((optarg
== NULL
) && (optind
< argc
))
238 optarg
= argv
[optind
++];
240 /* If we still have no option, declare it MIA. */
241 if (optarg
== NULL
) {
242 WARN("option requires an argument: %s",
244 opt_found
= opt_missing
;
247 /* If we have --foo=bar, something went wrong. */
248 if (os
[opts
[opt_found
].olen
] == '=') {
249 WARN("option doesn't take an argument: %s",
251 opt_found
= opt_default
;
255 /* Return the canonical option string. */
256 return (canonical_os
);
260 getopt_lookup(const char * os
)
263 /* Can't reset here. */
265 DIE("Can't reset in the middle of getopt loop");
267 /* We should only be called after initialization is complete. */
268 assert(getopt_initialized
);
270 /* GETOPT_DUMMY should never get passed back to us. */
271 assert(os
!= GETOPT_DUMMY
);
274 * Make sure the option passed back to us corresponds to the one we
277 assert((opt_found
== opt_missing
) || (opt_found
== opt_default
) ||
278 ((opt_found
< nopts
) && (strcmp(os
, opts
[opt_found
].os
) == 0)));
280 /* Return the option number we identified earlier. */
285 getopt_register_opt(const char * os
, size_t ln
, int hasarg
)
288 /* Can't reset here. */
290 DIE("Can't reset in the middle of getopt loop");
292 /* We should only be called during initialization. */
293 assert(!getopt_initialized
);
295 /* We should have space allocated for registering options. */
296 assert(opts
!= NULL
);
298 /* We should not have registered an option here yet. */
299 assert(opts
[ln
].os
== NULL
);
301 /* Options should be "-X" or "--foo". */
302 if ((os
[0] != '-') || (os
[1] == '\0') ||
303 ((os
[1] == '-') && (os
[2] == '\0')) ||
304 ((os
[1] != '-') && (os
[2] != '\0')))
305 DIE("Not a valid command-line option: %s", os
);
307 /* Make sure we haven't already registered this option. */
308 if (searchopt(os
) != opt_default
)
309 DIE("Command-line option registered twice: %s", os
);
313 opts
[ln
].olen
= strlen(os
);
314 opts
[ln
].hasarg
= hasarg
;
318 getopt_register_missing(size_t ln
)
321 /* Can't reset here. */
323 DIE("Can't reset in the middle of getopt loop");
325 /* We should only be called during initialization. */
326 assert(!getopt_initialized
);
328 /* Record missing-argument value. */
333 getopt_setrange(size_t ln
)
337 /* Can't reset here. */
339 DIE("Can't reset in the middle of getopt loop");
341 /* We should only be called during initialization. */
342 assert(!getopt_initialized
);
344 /* Allocate space for options. */
345 opts
= malloc(ln
* sizeof(struct opt
));
346 if ((ln
> 0) && (opts
== NULL
))
347 DIE("Failed to allocate memory in getopt");
349 /* Initialize options. */
350 for (i
= 0; i
< ln
; i
++)
353 /* Record the number of (potential) options. */
356 /* Record default missing-argument and no-such-option values. */
357 opt_missing
= opt_default
= ln
+ 1;
This page took 0.031391 seconds and 4 git commands to generate.