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, 29bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac const char *opt_name) 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 36bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*opt_name) 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++) { 87bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if ((opt_end = option_matches(carg+2, lo->name))) 88bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac break; 89bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 90bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!opt_end) 91bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 92bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 93bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (longindex) 94bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac *longindex = lo-longopts; 95bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 96bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*opt_end == '=') { 97bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (lo->has_arg) 98bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)opt_end+1; 99bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac else 100bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 101bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else if (lo->has_arg == 1) { 102bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!(optarg = argv[optind])) 103bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 104bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 105bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 106bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 107bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (lo->flag) { 108bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac *lo->flag = lo->val; 109bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return 0; 110bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 111bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return lo->val; 112bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 113bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 114bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 115bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { 116bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Someone frobbed optind, change to new opt. */ 117bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac pvt.optptr = carg + 1; 118bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 119bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 120bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac opt = *pvt.optptr++; 121bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac 122bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (opt != ':' && (osptr = strchr(optstring, opt))) { 123bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (osptr[1] == ':') { 124bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (*pvt.optptr) { 125bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Argument-taking option with attached 126bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac argument */ 127bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)pvt.optptr; 128bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 129bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 130bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Argument-taking option with non-attached 131bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac argument */ 1329f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe if (osptr[2] == ':') { 1339f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe if (argv[optind + 1]) { 1349f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optarg = (char *)argv[optind+1]; 1359f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optind += 2; 1369f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } else { 1379f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optarg = NULL; 1389f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe optind++; 1399f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } 1409f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe return opt; 1419f170691560bacdcd8cef6296d14fc0a8467a9ddJens Axboe } else if (argv[optind + 1]) { 142bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optarg = (char *)argv[optind+1]; 143bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind += 2; 144bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 145bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Missing argument */ 146bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 147bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return (optstring[0] == ':') 148bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac ? ':' : '?'; 149bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 150bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 151bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return opt; 152bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 153bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Non-argument-taking option */ 154bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* pvt.optptr will remember the exact position to 155bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac resume at */ 156bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!*pvt.optptr) 157bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 158bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return opt; 159bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 160bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } else { 161bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac /* Unknown option */ 162bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optopt = opt; 163bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac if (!*pvt.optptr) 164bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac optind++; 165bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac return '?'; 166bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac } 167bf2e821a55d8aa3de1cda7288a0e22883110fdc6Cigy Cyriac} 168