#include "getopt_compat.h" #include #include char *optarg; int optind = 1; int opterr = 1; int optopt; static const char *short_options; static int option_requires_argument(const char *optstring, int option) { const char *match = strchr(optstring, option); return match != NULL && match[1] == ':'; } static int missing_argument(int option) { optopt = option; optarg = NULL; return '?'; } int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) { const char *arg; optarg = NULL; if (optind >= argc) return -1; arg = argv[optind]; if (arg[0] != '-' || arg[1] == '\0') return -1; if (arg[1] == '-') { const char *name = arg + 2; const char *equals = strchr(name, '='); size_t name_length = equals != NULL ? (size_t)(equals - name) : strlen(name); size_t i; if (name_length == 0) { optind++; return -1; } for (i = 0; longopts[i].name != NULL; i++) { if (strlen(longopts[i].name) != name_length || strncmp(longopts[i].name, name, name_length) != 0) continue; if (longindex != NULL) *longindex = (int)i; if (longopts[i].has_arg == required_argument) { if (equals != NULL) optarg = (char *)(equals + 1); else if (optind + 1 < argc) optarg = argv[++optind]; else return missing_argument(longopts[i].val); } else if (equals != NULL) { return missing_argument(longopts[i].val); } optind++; if (longopts[i].flag != NULL) { *longopts[i].flag = longopts[i].val; return 0; } return longopts[i].val; } optind++; optopt = 0; return '?'; } /* Parse one short option, including clusters such as -vbh. */ if (short_options == NULL || *short_options == '\0') short_options = arg + 1; { int option = (unsigned char)*short_options++; const char *match = strchr(optstring, option); if (match == NULL || option == ':') { optopt = option; if (*short_options == '\0') { short_options = NULL; optind++; } return '?'; } if (option_requires_argument(optstring, option)) { if (*short_options != '\0') { optarg = (char *)short_options; short_options = NULL; optind++; } else if (optind + 1 < argc) { optarg = argv[++optind]; short_options = NULL; optind++; } else { short_options = NULL; optind++; return missing_argument(option); } } else if (*short_options == '\0') { short_options = NULL; optind++; } return option; } }