interp/include/utils/getopt.h
2025-08-19 07:49:22 -07:00

85 lines
2.3 KiB
C

/* 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
*/
#ifndef GETOPT_H
#define GETOPT_H
#include <ctype.h>
#include <stdio.h>
#include <string.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);
if (!arg[++optpos]) {
optind++;
optpos = 1;
}
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);
if (!arg[++optpos]) {
optind++;
optpos = 1;
}
return *optstring == ':' ? ':' : '?';
}
} else {
if (!arg[++optpos]) {
optind++;
optpos = 1;
}
return optopt;
}
}
}
#endif