getopt_long.c revision 191736
1139804Simp/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ 2139013Sdavidxu 3112904Sjeff/*- 4112904Sjeff * Copyright (c) 2000 The NetBSD Foundation, Inc. 5112904Sjeff * All rights reserved. 6112904Sjeff * 7112904Sjeff * This code is derived from software contributed to The NetBSD Foundation 8112904Sjeff * by Dieter Baron and Thomas Klausner. 9112904Sjeff * 10112904Sjeff * Redistribution and use in source and binary forms, with or without 11112904Sjeff * modification, are permitted provided that the following conditions 12112904Sjeff * are met: 13112904Sjeff * 1. Redistributions of source code must retain the above copyright 14112904Sjeff * notice, this list of conditions and the following disclaimer. 15112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright 16112904Sjeff * notice, this list of conditions and the following disclaimer in the 17112904Sjeff * documentation and/or other materials provided with the distribution. 18112904Sjeff * 19112904Sjeff * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20112904Sjeff * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21112904Sjeff * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22112904Sjeff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23112904Sjeff * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24112904Sjeff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25112904Sjeff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26112904Sjeff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27112904Sjeff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28116182Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29116182Sobrien * POSSIBILITY OF SUCH DAMAGE. 30116182Sobrien */ 31162536Sdavidxu 32112904Sjeff#include "file.h" 33112904Sjeff 34131431Smarcel#ifndef lint 35112904SjeffFILE_RCSID("@(#)$File: getopt_long.c,v 1.5 2009/02/03 20:27:51 christos Exp $") 36115765Sjeff#endif /* lint */ 37112904Sjeff 38112904Sjeff#include <assert.h> 39161678Sdavidxu#ifdef HAVE_ERR_H 40161678Sdavidxu#include <err.h> 41112904Sjeff#else 42112904Sjeff#define warnx printf 43112904Sjeff#endif 44139013Sdavidxu#include <errno.h> 45112904Sjeff#ifdef HAVE_GETOPT_H 46112904Sjeff#include <getopt.h> 47139013Sdavidxu#else 48139013Sdavidxu#include "mygetopt.h" 49139013Sdavidxu#endif 50139013Sdavidxu#include <stdlib.h> 51139013Sdavidxu#include <string.h> 52139013Sdavidxu 53162536Sdavidxu#define REPLACE_GETOPT 54162536Sdavidxu 55162536Sdavidxu#ifndef _DIAGASSERT 56162536Sdavidxu#define _DIAGASSERT assert 57161678Sdavidxu#endif 58161678Sdavidxu 59161678Sdavidxu#ifdef REPLACE_GETOPT 60161678Sdavidxu#ifdef __weak_alias 61161678Sdavidxu__weak_alias(getopt,_getopt) 62161678Sdavidxu#endif 63139013Sdavidxuint opterr = 1; /* if error message should be printed */ 64161678Sdavidxuint optind = 1; /* index into parent argv vector */ 65139013Sdavidxuint optopt = '?'; /* character checked for validity */ 66161678Sdavidxuint optreset; /* reset getopt */ 67139013Sdavidxuchar *optarg; /* argument associated with option */ 68161678Sdavidxu#elif HAVE_NBTOOL_CONFIG_H && !HAVE_DECL_OPTRESET 69139013Sdavidxustatic int optreset; 70139013Sdavidxu#endif 71139013Sdavidxu 72161678Sdavidxu#ifdef __weak_alias 73139013Sdavidxu__weak_alias(getopt_long,_getopt_long) 74139013Sdavidxu#endif 75161678Sdavidxu 76161678Sdavidxu#define IGNORE_FIRST (*options == '-' || *options == '+') 77139013Sdavidxu#define PRINT_ERROR ((opterr) && ((*options != ':') \ 78139013Sdavidxu || (IGNORE_FIRST && options[1] != ':'))) 79161678Sdavidxu#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) 80161678Sdavidxu#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) 81139013Sdavidxu/* XXX: GNU ignores PC if *options == '-' */ 82139013Sdavidxu#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') 83139013Sdavidxu 84139013Sdavidxu/* return values */ 85161678Sdavidxu#define BADCH (int)'?' 86161678Sdavidxu#define BADARG ((IGNORE_FIRST && options[1] == ':') \ 87161678Sdavidxu || (*options == ':') ? (int)':' : (int)'?') 88161678Sdavidxu#define INORDER (int)1 89161678Sdavidxu 90161678Sdavidxu#define EMSG "" 91161678Sdavidxu 92161678Sdavidxustatic int getopt_internal(int, char **, const char *); 93161678Sdavidxustatic int gcd(int, int); 94161678Sdavidxustatic void permute_args(int, int, int, char **); 95161678Sdavidxu 96161678Sdavidxustatic const char *place = EMSG; /* option letter processing */ 97161678Sdavidxu 98161678Sdavidxu/* XXX: set optreset to 1 rather than these two */ 99161678Sdavidxustatic int nonopt_start = -1; /* first non option argument (for permute) */ 100161678Sdavidxustatic int nonopt_end = -1; /* first option after non options (for permute) */ 101161678Sdavidxu 102161678Sdavidxu/* Error messages */ 103161678Sdavidxustatic const char recargchar[] = "option requires an argument -- %c"; 104161678Sdavidxustatic const char recargstring[] = "option requires an argument -- %s"; 105161678Sdavidxustatic const char ambig[] = "ambiguous option -- %.*s"; 106161678Sdavidxustatic const char noarg[] = "option doesn't take an argument -- %.*s"; 107115765Sjeffstatic const char illoptchar[] = "unknown option -- %c"; 108161678Sdavidxustatic const char illoptstring[] = "unknown option -- %s"; 109161678Sdavidxu 110161678Sdavidxu 111161678Sdavidxu/* 112161678Sdavidxu * Compute the greatest common divisor of a and b. 113161678Sdavidxu */ 114161678Sdavidxustatic int 115161678Sdavidxugcd(a, b) 116161678Sdavidxu int a; 117161678Sdavidxu int b; 118161678Sdavidxu{ 119161678Sdavidxu int c; 120161678Sdavidxu 121161678Sdavidxu c = a % b; 122161678Sdavidxu while (c != 0) { 123161678Sdavidxu a = b; 124161678Sdavidxu b = c; 125161678Sdavidxu c = a % b; 126161678Sdavidxu } 127161678Sdavidxu 128161678Sdavidxu return b; 129161678Sdavidxu} 130161678Sdavidxu 131161678Sdavidxu/* 132161678Sdavidxu * Exchange the block from nonopt_start to nonopt_end with the block 133161678Sdavidxu * from nonopt_end to opt_end (keeping the same order of arguments 134161742Sdavidxu * in each block). 135161678Sdavidxu */ 136115765Sjeffstatic void 137115765Sjeffpermute_args(panonopt_start, panonopt_end, opt_end, nargv) 138161678Sdavidxu int panonopt_start; 139161678Sdavidxu int panonopt_end; 140161678Sdavidxu int opt_end; 141138224Sdavidxu char **nargv; 142161678Sdavidxu{ 143161678Sdavidxu int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 144161678Sdavidxu char *swap; 145161678Sdavidxu 146161678Sdavidxu _DIAGASSERT(nargv != NULL); 147161678Sdavidxu 148161678Sdavidxu /* 149161678Sdavidxu * compute lengths of blocks and number and size of cycles 150161678Sdavidxu */ 151161678Sdavidxu nnonopts = panonopt_end - panonopt_start; 152158377Sdavidxu nopts = opt_end - panonopt_end; 153161678Sdavidxu ncycle = gcd(nnonopts, nopts); 154161678Sdavidxu cyclelen = (opt_end - panonopt_start) / ncycle; 155161678Sdavidxu 156138224Sdavidxu for (i = 0; i < ncycle; i++) { 157115765Sjeff cstart = panonopt_end+i; 158161678Sdavidxu pos = cstart; 159161678Sdavidxu for (j = 0; j < cyclelen; j++) { 160161678Sdavidxu if (pos >= panonopt_end) 161161678Sdavidxu pos -= nnonopts; 162161678Sdavidxu else 163161678Sdavidxu pos += nopts; 164161678Sdavidxu swap = nargv[pos]; 165161678Sdavidxu nargv[pos] = nargv[cstart]; 166161678Sdavidxu nargv[cstart] = swap; 167161678Sdavidxu } 168161678Sdavidxu } 169161678Sdavidxu} 170161678Sdavidxu 171161678Sdavidxu/* 172161678Sdavidxu * getopt_internal -- 173138224Sdavidxu * Parse argc/argv argument vector. Called by user level routines. 174138224Sdavidxu * Returns -2 if -- is found (can be long option or end of options marker). 175138224Sdavidxu */ 176115765Sjeffstatic int 177161678Sdavidxugetopt_internal(nargc, nargv, options) 178161678Sdavidxu int nargc; 179161678Sdavidxu char **nargv; 180161678Sdavidxu const char *options; 181161678Sdavidxu{ 182161678Sdavidxu char *oli; /* option letter list index */ 183161678Sdavidxu int optchar; 184161678Sdavidxu 185161678Sdavidxu _DIAGASSERT(nargv != NULL); 186138224Sdavidxu _DIAGASSERT(options != NULL); 187161678Sdavidxu 188115310Sjeff optarg = NULL; 189161678Sdavidxu 190161678Sdavidxu /* 191161678Sdavidxu * XXX Some programs (like rsyncd) expect to be able to 192161678Sdavidxu * XXX re-initialize optind to 0 and have getopt_long(3) 193161678Sdavidxu * XXX properly function again. Work around this braindamage. 194161678Sdavidxu */ 195161678Sdavidxu if (optind == 0) 196139013Sdavidxu optind = 1; 197139013Sdavidxu 198139257Sdavidxu if (optreset) 199139257Sdavidxu nonopt_start = nonopt_end = -1; 200139013Sdavidxustart: 201139013Sdavidxu if (optreset || !*place) { /* update scanning pointer */ 202161678Sdavidxu optreset = 0; 203139257Sdavidxu if (optind >= nargc) { /* end of argument vector */ 204139257Sdavidxu place = EMSG; 205139013Sdavidxu if (nonopt_end != -1) { 206161678Sdavidxu /* do permutation, if we have to */ 207139013Sdavidxu permute_args(nonopt_start, nonopt_end, 208139013Sdavidxu optind, nargv); 209163697Sdavidxu optind -= nonopt_end - nonopt_start; 210161678Sdavidxu } 211161678Sdavidxu else if (nonopt_start != -1) { 212161678Sdavidxu /* 213161678Sdavidxu * If we skipped non-options, set optind 214161678Sdavidxu * to the first of them. 215161678Sdavidxu */ 216115310Sjeff optind = nonopt_start; 217161678Sdavidxu } 218161678Sdavidxu nonopt_start = nonopt_end = -1; 219161678Sdavidxu return -1; 220161678Sdavidxu } 221138224Sdavidxu if ((*(place = nargv[optind]) != '-') 222161678Sdavidxu || (place[1] == '\0')) { /* found non-option */ 223161678Sdavidxu place = EMSG; 224161678Sdavidxu if (IN_ORDER) { 225161678Sdavidxu /* 226161678Sdavidxu * GNU extension: 227161678Sdavidxu * return non-option as argument to option 1 228161678Sdavidxu */ 229161678Sdavidxu optarg = nargv[optind++]; 230161678Sdavidxu return INORDER; 231161678Sdavidxu } 232161678Sdavidxu if (!PERMUTE) { 233161678Sdavidxu /* 234161678Sdavidxu * if no permutation wanted, stop parsing 235161678Sdavidxu * at first non-option 236143149Sdavidxu */ 237143149Sdavidxu return -1; 238143149Sdavidxu } 239161678Sdavidxu /* do permutation */ 240161678Sdavidxu if (nonopt_start == -1) 241161678Sdavidxu nonopt_start = optind; 242161678Sdavidxu else if (nonopt_end != -1) { 243161678Sdavidxu permute_args(nonopt_start, nonopt_end, 244161678Sdavidxu optind, nargv); 245143149Sdavidxu nonopt_start = optind - 246143149Sdavidxu (nonopt_end - nonopt_start); 247143149Sdavidxu nonopt_end = -1; 248143149Sdavidxu } 249143149Sdavidxu optind++; 250143149Sdavidxu /* process next argument */ 251143149Sdavidxu goto start; 252143149Sdavidxu } 253161678Sdavidxu if (nonopt_start != -1 && nonopt_end == -1) 254139013Sdavidxu nonopt_end = optind; 255138224Sdavidxu if (place[1] && *++place == '-') { /* found "--" */ 256161678Sdavidxu place++; 257161678Sdavidxu return -2; 258138224Sdavidxu } 259138224Sdavidxu } 260139013Sdavidxu if ((optchar = (int)*place++) == (int)':' || 261139013Sdavidxu (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { 262139013Sdavidxu /* option letter unknown or ':' */ 263139013Sdavidxu if (!*place) 264161678Sdavidxu ++optind; 265161678Sdavidxu if (PRINT_ERROR) 266139013Sdavidxu warnx(illoptchar, optchar); 267139013Sdavidxu optopt = optchar; 268161678Sdavidxu return BADCH; 269161678Sdavidxu } 270139013Sdavidxu if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ 271161678Sdavidxu /* XXX: what if no long options provided (called by getopt)? */ 272139013Sdavidxu if (*place) 273139013Sdavidxu return -2; 274161678Sdavidxu 275161678Sdavidxu if (++optind >= nargc) { /* no arg */ 276161678Sdavidxu place = EMSG; 277161678Sdavidxu if (PRINT_ERROR) 278138224Sdavidxu warnx(recargchar, optchar); 279139257Sdavidxu optopt = optchar; 280139257Sdavidxu return BADARG; 281161678Sdavidxu } else /* white space */ 282139257Sdavidxu place = nargv[optind]; 283161678Sdavidxu /* 284161678Sdavidxu * Handle -W arg the same as --arg (which causes getopt to 285161678Sdavidxu * stop parsing). 286161678Sdavidxu */ 287161678Sdavidxu return -2; 288161678Sdavidxu } 289139257Sdavidxu if (*++oli != ':') { /* doesn't take argument */ 290161678Sdavidxu if (!*place) 291139257Sdavidxu ++optind; 292139257Sdavidxu } else { /* takes (optional) argument */ 293161678Sdavidxu optarg = NULL; 294161678Sdavidxu if (*place) /* no white space */ 295161678Sdavidxu optarg = (char *)place; 296139257Sdavidxu /* XXX: disable test for :: if PC? (GNU doesn't) */ 297139257Sdavidxu else if (oli[1] != ':') { /* arg not optional */ 298139257Sdavidxu if (++optind >= nargc) { /* no arg */ 299161678Sdavidxu place = EMSG; 300139257Sdavidxu if (PRINT_ERROR) 301161678Sdavidxu warnx(recargchar, optchar); 302161678Sdavidxu optopt = optchar; 303161678Sdavidxu return BADARG; 304161678Sdavidxu } else 305161678Sdavidxu optarg = nargv[optind]; 306161678Sdavidxu } 307139257Sdavidxu place = EMSG; 308139257Sdavidxu ++optind; 309161678Sdavidxu } 310161678Sdavidxu /* dump back option letter */ 311161678Sdavidxu return optchar; 312139257Sdavidxu} 313139013Sdavidxu 314138224Sdavidxu#ifdef REPLACE_GETOPT 315161678Sdavidxu/* 316161678Sdavidxu * getopt -- 317161678Sdavidxu * Parse argc/argv argument vector. 318161678Sdavidxu * 319138224Sdavidxu * [eventually this will replace the real getopt] 320138224Sdavidxu */ 321161678Sdavidxuint 322161678Sdavidxugetopt(nargc, nargv, options) 323161678Sdavidxu int nargc; 324138225Sdavidxu char * const *nargv; 325139013Sdavidxu const char *options; 326138224Sdavidxu{ 327161678Sdavidxu int retval; 328161678Sdavidxu 329161678Sdavidxu _DIAGASSERT(nargv != NULL); 330161678Sdavidxu _DIAGASSERT(options != NULL); 331138224Sdavidxu 332138224Sdavidxu retval = getopt_internal(nargc, (char **)nargv, options); 333139013Sdavidxu if (retval == -2) { 334139013Sdavidxu ++optind; 335139013Sdavidxu /* 336139013Sdavidxu * We found an option (--), so if we skipped non-options, 337139013Sdavidxu * we have to permute. 338115765Sjeff */ 339161678Sdavidxu if (nonopt_end != -1) { 340139013Sdavidxu permute_args(nonopt_start, nonopt_end, optind, 341161678Sdavidxu (char **)nargv); 342161678Sdavidxu optind -= nonopt_end - nonopt_start; 343161678Sdavidxu } 344158718Sdavidxu nonopt_start = nonopt_end = -1; 345139013Sdavidxu retval = -1; 346139013Sdavidxu } 347139013Sdavidxu return retval; 348139013Sdavidxu} 349139013Sdavidxu#endif 350139013Sdavidxu 351139013Sdavidxu/* 352139013Sdavidxu * getopt_long -- 353161678Sdavidxu * Parse argc/argv argument vector. 354161678Sdavidxu */ 355161678Sdavidxuint 356161678Sdavidxugetopt_long(nargc, nargv, options, long_options, idx) 357158718Sdavidxu int nargc; 358161678Sdavidxu char * const *nargv; 359158718Sdavidxu const char *options; 360139013Sdavidxu const struct option *long_options; 361139013Sdavidxu int *idx; 362139013Sdavidxu{ 363161678Sdavidxu int retval; 364161678Sdavidxu 365161678Sdavidxu#define IDENTICAL_INTERPRETATION(_x, _y) \ 366139013Sdavidxu (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ 367139013Sdavidxu long_options[(_x)].flag == long_options[(_y)].flag && \ 368139013Sdavidxu long_options[(_x)].val == long_options[(_y)].val) 369161678Sdavidxu 370115765Sjeff _DIAGASSERT(nargv != NULL); 371161678Sdavidxu _DIAGASSERT(options != NULL); 372115765Sjeff _DIAGASSERT(long_options != NULL); 373161678Sdavidxu /* idx may be NULL */ 374161678Sdavidxu 375161678Sdavidxu retval = getopt_internal(nargc, (char **)nargv, options); 376139013Sdavidxu if (retval == -2) { 377139013Sdavidxu char *current_argv, *has_equal; 378139013Sdavidxu size_t current_argv_len; 379139013Sdavidxu int i, ambiguous, match; 380115765Sjeff 381139013Sdavidxu current_argv = (char *)place; 382115765Sjeff match = -1; 383115765Sjeff ambiguous = 0; 384161678Sdavidxu 385161678Sdavidxu optind++; 386161678Sdavidxu place = EMSG; 387161678Sdavidxu 388139257Sdavidxu if (*current_argv == '\0') { /* found "--" */ 389161678Sdavidxu /* 390161678Sdavidxu * We found an option (--), so if we skipped 391161678Sdavidxu * non-options, we have to permute. 392161678Sdavidxu */ 393161678Sdavidxu if (nonopt_end != -1) { 394161678Sdavidxu permute_args(nonopt_start, nonopt_end, 395161678Sdavidxu optind, (char **)nargv); 396161678Sdavidxu optind -= nonopt_end - nonopt_start; 397161678Sdavidxu } 398161678Sdavidxu nonopt_start = nonopt_end = -1; 399161678Sdavidxu return -1; 400161678Sdavidxu } 401161678Sdavidxu if ((has_equal = strchr(current_argv, '=')) != NULL) { 402161678Sdavidxu /* argument found (--option=arg) */ 403161678Sdavidxu current_argv_len = has_equal - current_argv; 404161678Sdavidxu has_equal++; 405161678Sdavidxu } else 406161678Sdavidxu current_argv_len = strlen(current_argv); 407161678Sdavidxu 408161678Sdavidxu for (i = 0; long_options[i].name; i++) { 409161678Sdavidxu /* find matching long option */ 410161678Sdavidxu if (strncmp(current_argv, long_options[i].name, 411161678Sdavidxu current_argv_len)) 412139257Sdavidxu continue; 413115765Sjeff 414161678Sdavidxu if (strlen(long_options[i].name) == 415139257Sdavidxu (unsigned)current_argv_len) { 416161678Sdavidxu /* exact match */ 417115765Sjeff match = i; 418139257Sdavidxu ambiguous = 0; 419161678Sdavidxu break; 420161678Sdavidxu } 421161678Sdavidxu if (match == -1) /* partial match */ 422139013Sdavidxu match = i; 423139013Sdavidxu else if (!IDENTICAL_INTERPRETATION(i, match)) 424161678Sdavidxu ambiguous = 1; 425139257Sdavidxu } 426139257Sdavidxu if (ambiguous) { 427139013Sdavidxu /* ambiguous abbreviation */ 428139013Sdavidxu if (PRINT_ERROR) 429139257Sdavidxu warnx(ambig, (int)current_argv_len, 430138224Sdavidxu current_argv); 431138224Sdavidxu optopt = 0; 432161678Sdavidxu return BADCH; 433161678Sdavidxu } 434161678Sdavidxu if (match != -1) { /* option found */ 435161678Sdavidxu if (long_options[match].has_arg == no_argument 436161678Sdavidxu && has_equal) { 437161678Sdavidxu if (PRINT_ERROR) 438161678Sdavidxu warnx(noarg, (int)current_argv_len, 439161678Sdavidxu current_argv); 440161678Sdavidxu /* 441161678Sdavidxu * XXX: GNU sets optopt to val regardless of 442161678Sdavidxu * flag 443161678Sdavidxu */ 444161678Sdavidxu if (long_options[match].flag == NULL) 445161678Sdavidxu optopt = long_options[match].val; 446161678Sdavidxu else 447161678Sdavidxu optopt = 0; 448161678Sdavidxu return BADARG; 449161678Sdavidxu } 450138224Sdavidxu if (long_options[match].has_arg == required_argument || 451161678Sdavidxu long_options[match].has_arg == optional_argument) { 452138224Sdavidxu if (has_equal) 453161678Sdavidxu optarg = has_equal; 454161678Sdavidxu else if (long_options[match].has_arg == 455161678Sdavidxu required_argument) { 456161678Sdavidxu /* 457161678Sdavidxu * optional argument doesn't use 458161678Sdavidxu * next nargv 459161678Sdavidxu */ 460161678Sdavidxu optarg = nargv[optind++]; 461139751Sdavidxu } 462139751Sdavidxu } 463139751Sdavidxu if ((long_options[match].has_arg == required_argument) 464138224Sdavidxu && (optarg == NULL)) { 465138224Sdavidxu /* 466161678Sdavidxu * Missing argument; leading ':' 467161678Sdavidxu * indicates no error should be generated 468161678Sdavidxu */ 469139013Sdavidxu if (PRINT_ERROR) 470161678Sdavidxu warnx(recargstring, current_argv); 471139013Sdavidxu /* 472161678Sdavidxu * XXX: GNU sets optopt to val regardless 473139013Sdavidxu * of flag 474139013Sdavidxu */ 475139013Sdavidxu if (long_options[match].flag == NULL) 476139013Sdavidxu optopt = long_options[match].val; 477139013Sdavidxu else 478139013Sdavidxu optopt = 0; 479161678Sdavidxu --optind; 480161678Sdavidxu return BADARG; 481161678Sdavidxu } 482161678Sdavidxu } else { /* unknown option */ 483161678Sdavidxu if (PRINT_ERROR) 484163677Sdavidxu warnx(illoptstring, current_argv); 485163677Sdavidxu optopt = 0; 486161678Sdavidxu return BADCH; 487161678Sdavidxu } 488161678Sdavidxu if (long_options[match].flag) { 489161678Sdavidxu *long_options[match].flag = long_options[match].val; 490161678Sdavidxu retval = 0; 491161678Sdavidxu } else 492161678Sdavidxu retval = long_options[match].val; 493161678Sdavidxu if (idx) 494161678Sdavidxu *idx = match; 495161678Sdavidxu } 496161678Sdavidxu return retval; 497161678Sdavidxu#undef IDENTICAL_INTERPRETATION 498161678Sdavidxu} 499161678Sdavidxu