1bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac/* 2bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * getopt.c 3bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * 4bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * getopt_long(), or at least a common subset thereof: 5bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * 6bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * - Option reordering is not supported 7bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * - -W foo is not supported 8bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac * - First optstring character "-" not supported. 9eb078db384e336c1f2338adfdf8f6594660964d6Jens Axboe * 10eb078db384e336c1f2338adfdf8f6594660964d6Jens Axboe * This file was imported from the klibc library from hpa 11bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac */ 12bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 13bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac#include <stdint.h> 14bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac#include <unistd.h> 15bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac#include <string.h> 16eb078db384e336c1f2338adfdf8f6594660964d6Jens Axboe 17eb078db384e336c1f2338adfdf8f6594660964d6Jens Axboe#include "getopt.h" 18bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 195be4c944e83b32c0c6842130df3dc1d46cd6eb1fJens Axboechar *optarg = NULL; 205be4c944e83b32c0c6842130df3dc1d46cd6eb1fJens Axboeint optind = 0, opterr = 0, optopt = 0; 215be4c944e83b32c0c6842130df3dc1d46cd6eb1fJens Axboe 22bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriacstatic struct getopt_private_state { 23bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *optptr; 24bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *last_optstring; 25bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac char *const *last_argv; 26bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac} pvt; 27bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 28bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriacstatic inline const char *option_matches(const char *arg_str, 29eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes const char *opt_name, int smatch) 30bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac{ 31bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac while (*arg_str != '\0' && *arg_str != '=') { 32bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*arg_str++ != *opt_name++) 33bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return NULL; 34bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 35bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 36eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (*opt_name && !smatch) 37bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return NULL; 38bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 39bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return arg_str; 40bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac} 41bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 42bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriacint getopt_long_only(int argc, char *const *argv, const char *optstring, 43bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const struct option *longopts, int *longindex) 44bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac{ 45bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *carg; 46bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *osptr; 47bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac int opt; 48bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 4925c42559e065f5a94a696b7bbefa32426d7b8925Jens Axboe optarg = NULL; 5025c42559e065f5a94a696b7bbefa32426d7b8925Jens Axboe 51bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* getopt() relies on a number of different global state 52bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac variables, which can make this really confusing if there is 53bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac more than one use of getopt() in the same program. This 54bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac attempts to detect that situation by detecting if the 55bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac "optstring" or "argv" argument have changed since last time 56bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac we were called; if so, reinitialize the query state. */ 57bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 58bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (optstring != pvt.last_optstring || argv != pvt.last_argv || 59bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind < 1 || optind > argc) { 60bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* optind doesn't match the current query */ 61bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac pvt.last_optstring = optstring; 62bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac pvt.last_argv = argv; 63bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind = 1; 64bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac pvt.optptr = NULL; 65bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 66bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 67bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac carg = argv[optind]; 68bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 69bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* First, eliminate all non-option cases */ 70bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 71bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!carg || carg[0] != '-' || !carg[1]) 72bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return -1; 73bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 74bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (carg[1] == '-') { 75bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const struct option *lo; 76bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *opt_end = NULL; 77bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 78bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 79bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 80bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Either it's a long option, or it's -- */ 81bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!carg[2]) { 82bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* It's -- */ 83bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return -1; 84bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 85bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 86bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac for (lo = longopts; lo->name; lo++) { 87eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes opt_end = option_matches(carg+2, lo->name, 0); 88eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (opt_end) 89bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac break; 90bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 91eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes /* 92eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes * The GNU getopt_long_only() apparently allows a short match, 93eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes * if it's unique and if we don't have a full match. Let's 94eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes * do the same here, search and see if there is one (and only 95eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes * one) short match. 96eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes */ 97eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (!opt_end) { 98eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes const struct option *lo_match = NULL; 99eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes 100eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes for (lo = longopts; lo->name; lo++) { 101eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes const char *ret; 102eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes 103eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes ret = option_matches(carg+2, lo->name, 1); 104eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (!ret) 105eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes continue; 106eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (!opt_end) { 107eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes opt_end = ret; 108eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes lo_match = lo; 109eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes } else { 110eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes opt_end = NULL; 111eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes break; 112eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes } 113eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes } 114eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes if (!opt_end) 115eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes return '?'; 116eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes lo = lo_match; 117eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes } 118bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 119bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (longindex) 120bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac *longindex = lo-longopts; 121bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 122bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*opt_end == '=') { 123bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (lo->has_arg) 124bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)opt_end+1; 125bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac else 126bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 127bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else if (lo->has_arg == 1) { 128bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!(optarg = argv[optind])) 129bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 130bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 131bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 132bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 133bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (lo->flag) { 134bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac *lo->flag = lo->val; 135bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return 0; 136bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 137bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return lo->val; 138bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 139bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 140bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 141bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { 142bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Someone frobbed optind, change to new opt. */ 143bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac pvt.optptr = carg + 1; 144bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 145bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 146bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac opt = *pvt.optptr++; 147bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 148bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (opt != ':' && (osptr = strchr(optstring, opt))) { 149bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (osptr[1] == ':') { 150bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*pvt.optptr) { 151bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Argument-taking option with attached 152bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac argument */ 153bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)pvt.optptr; 154bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 155bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 156bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Argument-taking option with non-attached 157bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac argument */ 1589f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe if (osptr[2] == ':') { 1599f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe if (argv[optind + 1]) { 1609f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optarg = (char *)argv[optind+1]; 1619f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optind += 2; 1629f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } else { 1639f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optarg = NULL; 1649f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optind++; 1659f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } 1669f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe return opt; 1679f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } else if (argv[optind + 1]) { 168bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)argv[optind+1]; 169bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind += 2; 170bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 171bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Missing argument */ 172bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 173bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return (optstring[0] == ':') 174bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac ? ':' : '?'; 175bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 176bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 177bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return opt; 178bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 179bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Non-argument-taking option */ 180bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* pvt.optptr will remember the exact position to 181bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac resume at */ 182bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!*pvt.optptr) 183bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 184bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return opt; 185bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 186bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 187bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Unknown option */ 188bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optopt = opt; 189bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!*pvt.optptr) 190bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 191bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 192bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 193bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac} 194