1/* 2 * Extracted from the glibc source tree, version 2.3.6 3 * 4 * Licensed under the GPL as per the whole glibc source tree. 5 * 6 * This file was modified so that getopt_long can be called 7 * many times without risking previous memory to be spoiled. 8 * 9 * Modified by Andre Noll and Lorenzo Bettini for use in 10 * GNU gengetopt generated files. 11 * 12 */ 13 14/* 15 * we must include anything we need since this file is not thought to be 16 * inserted in a file already using getopt.h 17 * 18 * Lorenzo 19 */ 20 21struct option 22{ 23 const char *name; 24 /* has_arg can't be an enum because some compilers complain about 25 type mismatches in all the code that assumes it is an int. */ 26 int has_arg; 27 int *flag; 28 int val; 29}; 30 31/* This version of `getopt' appears to the caller like standard Unix `getopt' 32 but it behaves differently for the user, since it allows the user 33 to intersperse the options with the other arguments. 34 35 As `getopt' works, it permutes the elements of ARGV so that, 36 when it is done, all the options precede everything else. Thus 37 all application programs are extended to handle flexible argument order. 38*/ 39/* 40 If the field `flag' is not NULL, it points to a variable that is set 41 to the value given in the field `val' when the option is found, but 42 left unchanged if the option is not found. 43 44 To have a long-named option do something other than set an `int' to 45 a compiled-in constant, such as set a value from `custom_optarg', set the 46 option's `flag' field to zero and its `val' field to a nonzero 47 value (the equivalent single-letter option character, if there is 48 one). For long options that have a zero `flag' field, `getopt' 49 returns the contents of the `val' field. */ 50 51/* Names for the values of the `has_arg' field of `struct option'. */ 52#ifndef no_argument 53#define no_argument 0 54#endif 55 56#ifndef required_argument 57#define required_argument 1 58#endif 59 60#ifndef optional_argument 61#define optional_argument 2 62#endif 63 64struct custom_getopt_data { 65 /* 66 * These have exactly the same meaning as the corresponding global variables, 67 * except that they are used for the reentrant versions of getopt. 68 */ 69 int custom_optind; 70 int custom_opterr; 71 int custom_optopt; 72 char *custom_optarg; 73 74 /* True if the internal members have been initialized. */ 75 int initialized; 76 77 /* 78 * The next char to be scanned in the option-element in which the last option 79 * character we returned was found. This allows us to pick up the scan where 80 * we left off. If this is zero, or a null string, it means resume the scan by 81 * advancing to the next ARGV-element. 82 */ 83 char *nextchar; 84 85 /* 86 * Describe the part of ARGV that contains non-options that have been skipped. 87 * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is 88 * the index after the last of them. 89 */ 90 int first_nonopt; 91 int last_nonopt; 92}; 93 94/* 95 * the variables optarg, optind, opterr and optopt are renamed with 96 * the custom_ prefix so that they don't interfere with getopt ones. 97 * 98 * Moreover they're static so they are visible only from within the 99 * file where this very file will be included. 100 */ 101 102/* 103 * For communication from `custom_getopt' to the caller. When `custom_getopt' finds an 104 * option that takes an argument, the argument value is returned here. 105 */ 106static char *custom_optarg; 107 108/* 109 * Index in ARGV of the next element to be scanned. This is used for 110 * communication to and from the caller and for communication between 111 * successive calls to `custom_getopt'. 112 * 113 * On entry to `custom_getopt', 1 means this is the first call; initialize. 114 * 115 * When `custom_getopt' returns -1, this is the index of the first of the non-option 116 * elements that the caller should itself scan. 117 * 118 * Otherwise, `custom_optind' communicates from one call to the next how much of ARGV 119 * has been scanned so far. 120 * 121 * 1003.2 says this must be 1 before any call. 122 */ 123static int custom_optind = 1; 124 125/* 126 * Callers store zero here to inhibit the error message for unrecognized 127 * options. 128 */ 129static int custom_opterr = 1; 130 131/* 132 * Set to an option character which was unrecognized. This must be initialized 133 * on some systems to avoid linking in the system's own getopt implementation. 134 */ 135static int custom_optopt = '?'; 136 137/* 138 * Exchange two adjacent subsequences of ARGV. One subsequence is elements 139 * [first_nonopt,last_nonopt) which contains all the non-options that have been 140 * skipped so far. The other is elements [last_nonopt,custom_optind), which contains 141 * all the options processed since those non-options were skipped. 142 * `first_nonopt' and `last_nonopt' are relocated so that they describe the new 143 * indices of the non-options in ARGV after they are moved. 144 */ 145static void exchange(char **argv, struct custom_getopt_data *d) 146{ 147 int bottom = d->first_nonopt; 148 int middle = d->last_nonopt; 149 int top = d->custom_optind; 150 char *tem; 151 152 /* 153 * Exchange the shorter segment with the far end of the longer segment. 154 * That puts the shorter segment into the right place. It leaves the 155 * longer segment in the right place overall, but it consists of two 156 * parts that need to be swapped next. 157 */ 158 while (top > middle && middle > bottom) { 159 if (top - middle > middle - bottom) { 160 /* Bottom segment is the short one. */ 161 int len = middle - bottom; 162 int i; 163 164 /* Swap it with the top part of the top segment. */ 165 for (i = 0; i < len; i++) { 166 tem = argv[bottom + i]; 167 argv[bottom + i] = 168 argv[top - (middle - bottom) + i]; 169 argv[top - (middle - bottom) + i] = tem; 170 } 171 /* Exclude the moved bottom segment from further swapping. */ 172 top -= len; 173 } else { 174 /* Top segment is the short one. */ 175 int len = top - middle; 176 int i; 177 178 /* Swap it with the bottom part of the bottom segment. */ 179 for (i = 0; i < len; i++) { 180 tem = argv[bottom + i]; 181 argv[bottom + i] = argv[middle + i]; 182 argv[middle + i] = tem; 183 } 184 /* Exclude the moved top segment from further swapping. */ 185 bottom += len; 186 } 187 } 188 /* Update records for the slots the non-options now occupy. */ 189 d->first_nonopt += (d->custom_optind - d->last_nonopt); 190 d->last_nonopt = d->custom_optind; 191} 192 193/* Initialize the internal data when the first call is made. */ 194static void custom_getopt_initialize(struct custom_getopt_data *d) 195{ 196 /* 197 * Start processing options with ARGV-element 1 (since ARGV-element 0 198 * is the program name); the sequence of previously skipped non-option 199 * ARGV-elements is empty. 200 */ 201 d->first_nonopt = d->last_nonopt = d->custom_optind; 202 d->nextchar = NULL; 203 d->initialized = 1; 204} 205 206#define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\0') 207 208/* return: zero: continue, nonzero: return given value to user */ 209static int shuffle_argv(int argc, char *const *argv,const struct option *longopts, 210 struct custom_getopt_data *d) 211{ 212 /* 213 * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been 214 * moved back by the user (who may also have changed the arguments). 215 */ 216 if (d->last_nonopt > d->custom_optind) 217 d->last_nonopt = d->custom_optind; 218 if (d->first_nonopt > d->custom_optind) 219 d->first_nonopt = d->custom_optind; 220 /* 221 * If we have just processed some options following some 222 * non-options, exchange them so that the options come first. 223 */ 224 if (d->first_nonopt != d->last_nonopt && 225 d->last_nonopt != d->custom_optind) 226 exchange((char **) argv, d); 227 else if (d->last_nonopt != d->custom_optind) 228 d->first_nonopt = d->custom_optind; 229 /* 230 * Skip any additional non-options and extend the range of 231 * non-options previously skipped. 232 */ 233 while (d->custom_optind < argc && NONOPTION_P) 234 d->custom_optind++; 235 d->last_nonopt = d->custom_optind; 236 /* 237 * The special ARGV-element `--' means premature end of options. Skip 238 * it like a null option, then exchange with previous non-options as if 239 * it were an option, then skip everything else like a non-option. 240 */ 241 if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) { 242 d->custom_optind++; 243 if (d->first_nonopt != d->last_nonopt 244 && d->last_nonopt != d->custom_optind) 245 exchange((char **) argv, d); 246 else if (d->first_nonopt == d->last_nonopt) 247 d->first_nonopt = d->custom_optind; 248 d->last_nonopt = argc; 249 d->custom_optind = argc; 250 } 251 /* 252 * If we have done all the ARGV-elements, stop the scan and back over 253 * any non-options that we skipped and permuted. 254 */ 255 if (d->custom_optind == argc) { 256 /* 257 * Set the next-arg-index to point at the non-options that we 258 * previously skipped, so the caller will digest them. 259 */ 260 if (d->first_nonopt != d->last_nonopt) 261 d->custom_optind = d->first_nonopt; 262 return -1; 263 } 264 /* 265 * If we have come to a non-option and did not permute it, either stop 266 * the scan or describe it to the caller and pass it by. 267 */ 268 if (NONOPTION_P) { 269 d->custom_optarg = argv[d->custom_optind++]; 270 return 1; 271 } 272 /* 273 * We have found another option-ARGV-element. Skip the initial 274 * punctuation. 275 */ 276 d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-')); 277 return 0; 278} 279 280/* 281 * Check whether the ARGV-element is a long option. 282 * 283 * If there's a long option "fubar" and the ARGV-element is "-fu", consider 284 * that an abbreviation of the long option, just like "--fu", and not "-f" with 285 * arg "u". 286 * 287 * This distinction seems to be the most useful approach. 288 * 289 */ 290static int check_long_opt(int argc, char *const *argv, const char *optstring, 291 const struct option *longopts, int *longind, 292 int print_errors, struct custom_getopt_data *d) 293{ 294 char *nameend; 295 const struct option *p; 296 const struct option *pfound = NULL; 297 int exact = 0; 298 int ambig = 0; 299 int indfound = -1; 300 int option_index; 301 302 for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++) 303 /* Do nothing. */ ; 304 305 /* Test all long options for either exact match or abbreviated matches */ 306 for (p = longopts, option_index = 0; p->name; p++, option_index++) 307 if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) { 308 if ((unsigned int) (nameend - d->nextchar) 309 == (unsigned int) strlen(p->name)) { 310 /* Exact match found. */ 311 pfound = p; 312 indfound = option_index; 313 exact = 1; 314 break; 315 } else if (pfound == NULL) { 316 /* First nonexact match found. */ 317 pfound = p; 318 indfound = option_index; 319 } else if (pfound->has_arg != p->has_arg 320 || pfound->flag != p->flag 321 || pfound->val != p->val) 322 /* Second or later nonexact match found. */ 323 ambig = 1; 324 } 325 if (ambig && !exact) { 326 if (print_errors) { 327 fprintf(stderr, 328 "%s: option `%s' is ambiguous\n", 329 argv[0], argv[d->custom_optind]); 330 } 331 d->nextchar += strlen(d->nextchar); 332 d->custom_optind++; 333 d->custom_optopt = 0; 334 return '?'; 335 } 336 if (pfound) { 337 option_index = indfound; 338 d->custom_optind++; 339 if (*nameend) { 340 if (pfound->has_arg != no_argument) 341 d->custom_optarg = nameend + 1; 342 else { 343 if (print_errors) { 344 if (argv[d->custom_optind - 1][1] == '-') { 345 /* --option */ 346 fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", 347 argv[0], pfound->name); 348 } else { 349 /* +option or -option */ 350 fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", 351 argv[0], argv[d->custom_optind - 1][0], pfound->name); 352 } 353 354 } 355 d->nextchar += strlen(d->nextchar); 356 d->custom_optopt = pfound->val; 357 return '?'; 358 } 359 } else if (pfound->has_arg == required_argument) { 360 if (d->custom_optind < argc) 361 d->custom_optarg = argv[d->custom_optind++]; 362 else { 363 if (print_errors) { 364 fprintf(stderr, 365 "%s: option `%s' requires an argument\n", 366 argv[0], 367 argv[d->custom_optind - 1]); 368 } 369 d->nextchar += strlen(d->nextchar); 370 d->custom_optopt = pfound->val; 371 return optstring[0] == ':' ? ':' : '?'; 372 } 373 } 374 d->nextchar += strlen(d->nextchar); 375 if (longind != NULL) 376 *longind = option_index; 377 if (pfound->flag) { 378 *(pfound->flag) = pfound->val; 379 return 0; 380 } 381 return pfound->val; 382 } 383 /* 384 * Can't find it as a long option. If this is not getopt_long_only, or 385 * the option starts with '--' or is not a valid short option, then 386 * it's an error. Otherwise interpret it as a short option. 387 */ 388 if (print_errors) { 389 if (argv[d->custom_optind][1] == '-') { 390 /* --option */ 391 fprintf(stderr, 392 "%s: unrecognized option `--%s'\n", 393 argv[0], d->nextchar); 394 } else { 395 /* +option or -option */ 396 fprintf(stderr, 397 "%s: unrecognized option `%c%s'\n", 398 argv[0], argv[d->custom_optind][0], 399 d->nextchar); 400 } 401 } 402 d->nextchar = (char *) ""; 403 d->custom_optind++; 404 d->custom_optopt = 0; 405 return '?'; 406} 407 408static int check_short_opt(int argc, char *const *argv, const char *optstring, 409 int print_errors, struct custom_getopt_data *d) 410{ 411 char c = *d->nextchar++; 412 const char *temp = strchr(optstring, c); 413 414 /* Increment `custom_optind' when we start to process its last character. */ 415 if (*d->nextchar == '\0') 416 ++d->custom_optind; 417 if (!temp || c == ':') { 418 if (print_errors) 419 fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); 420 421 d->custom_optopt = c; 422 return '?'; 423 } 424 if (temp[1] == ':') { 425 if (temp[2] == ':') { 426 /* This is an option that accepts an argument optionally. */ 427 if (*d->nextchar != '\0') { 428 d->custom_optarg = d->nextchar; 429 d->custom_optind++; 430 } else 431 d->custom_optarg = NULL; 432 d->nextchar = NULL; 433 } else { 434 /* This is an option that requires an argument. */ 435 if (*d->nextchar != '\0') { 436 d->custom_optarg = d->nextchar; 437 /* 438 * If we end this ARGV-element by taking the 439 * rest as an arg, we must advance to the next 440 * element now. 441 */ 442 d->custom_optind++; 443 } else if (d->custom_optind == argc) { 444 if (print_errors) { 445 fprintf(stderr, 446 "%s: option requires an argument -- %c\n", 447 argv[0], c); 448 } 449 d->custom_optopt = c; 450 if (optstring[0] == ':') 451 c = ':'; 452 else 453 c = '?'; 454 } else 455 /* 456 * We already incremented `custom_optind' once; 457 * increment it again when taking next ARGV-elt 458 * as argument. 459 */ 460 d->custom_optarg = argv[d->custom_optind++]; 461 d->nextchar = NULL; 462 } 463 } 464 return c; 465} 466 467/* 468 * Scan elements of ARGV for option characters given in OPTSTRING. 469 * 470 * If an element of ARGV starts with '-', and is not exactly "-" or "--", 471 * then it is an option element. The characters of this element 472 * (aside from the initial '-') are option characters. If `getopt' 473 * is called repeatedly, it returns successively each of the option characters 474 * from each of the option elements. 475 * 476 * If `getopt' finds another option character, it returns that character, 477 * updating `custom_optind' and `nextchar' so that the next call to `getopt' can 478 * resume the scan with the following option character or ARGV-element. 479 * 480 * If there are no more option characters, `getopt' returns -1. 481 * Then `custom_optind' is the index in ARGV of the first ARGV-element 482 * that is not an option. (The ARGV-elements have been permuted 483 * so that those that are not options now come last.) 484 * 485 * OPTSTRING is a string containing the legitimate option characters. 486 * If an option character is seen that is not listed in OPTSTRING, 487 * return '?' after printing an error message. If you set `custom_opterr' to 488 * zero, the error message is suppressed but we still return '?'. 489 * 490 * If a char in OPTSTRING is followed by a colon, that means it wants an arg, 491 * so the following text in the same ARGV-element, or the text of the following 492 * ARGV-element, is returned in `custom_optarg'. Two colons mean an option that 493 * wants an optional arg; if there is text in the current ARGV-element, 494 * it is returned in `custom_optarg', otherwise `custom_optarg' is set to zero. 495 * 496 * If OPTSTRING starts with `-' or `+', it requests different methods of 497 * handling the non-option ARGV-elements. 498 * See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 499 * 500 * Long-named options begin with `--' instead of `-'. 501 * Their names may be abbreviated as long as the abbreviation is unique 502 * or is an exact match for some defined option. If they have an 503 * argument, it follows the option name in the same ARGV-element, separated 504 * from the option name by a `=', or else the in next ARGV-element. 505 * When `getopt' finds a long-named option, it returns 0 if that option's 506 * `flag' field is nonzero, the value of the option's `val' field 507 * if the `flag' field is zero. 508 * 509 * The elements of ARGV aren't really const, because we permute them. 510 * But we pretend they're const in the prototype to be compatible 511 * with other systems. 512 * 513 * LONGOPTS is a vector of `struct option' terminated by an 514 * element containing a name which is zero. 515 * 516 * LONGIND returns the index in LONGOPT of the long-named option found. 517 * It is only valid when a long-named option has been found by the most 518 * recent call. 519 * 520 * Return the option character from OPTS just read. Return -1 when there are 521 * no more options. For unrecognized options, or options missing arguments, 522 * `custom_optopt' is set to the option letter, and '?' is returned. 523 * 524 * The OPTS string is a list of characters which are recognized option letters, 525 * optionally followed by colons, specifying that that letter takes an 526 * argument, to be placed in `custom_optarg'. 527 * 528 * If a letter in OPTS is followed by two colons, its argument is optional. 529 * This behavior is specific to the GNU `getopt'. 530 * 531 * The argument `--' causes premature termination of argument scanning, 532 * explicitly telling `getopt' that there are no more options. If OPTS begins 533 * with `--', then non-option arguments are treated as arguments to the option 534 * '\0'. This behavior is specific to the GNU `getopt'. 535 */ 536 537static int getopt_internal_r(int argc, char *const *argv, const char *optstring, 538 const struct option *longopts, int *longind, 539 struct custom_getopt_data *d) 540{ 541 int ret, print_errors = d->custom_opterr; 542 543 if (optstring[0] == ':') 544 print_errors = 0; 545 if (argc < 1) 546 return -1; 547 d->custom_optarg = NULL; 548 549 /* 550 * This is a big difference with GNU getopt, since optind == 0 551 * means initialization while here 1 means first call. 552 */ 553 if (d->custom_optind == 0 || !d->initialized) { 554 if (d->custom_optind == 0) 555 d->custom_optind = 1; /* Don't scan ARGV[0], the program name. */ 556 custom_getopt_initialize(d); 557 } 558 if (d->nextchar == NULL || *d->nextchar == '\0') { 559 ret = shuffle_argv(argc, argv, longopts, d); 560 if (ret) 561 return ret; 562 } 563 if (longopts && (argv[d->custom_optind][1] == '-' )) 564 return check_long_opt(argc, argv, optstring, longopts, 565 longind, print_errors, d); 566 return check_short_opt(argc, argv, optstring, print_errors, d); 567} 568 569static int custom_getopt_internal(int argc, char *const *argv, const char *optstring, 570 const struct option *longopts, int *longind) 571{ 572 int result; 573 /* Keep a global copy of all internal members of d */ 574 static struct custom_getopt_data d; 575 576 d.custom_optind = custom_optind; 577 d.custom_opterr = custom_opterr; 578 result = getopt_internal_r(argc, argv, optstring, longopts, 579 longind, &d); 580 custom_optind = d.custom_optind; 581 custom_optarg = d.custom_optarg; 582 custom_optopt = d.custom_optopt; 583 return result; 584} 585 586static int custom_getopt_long (int argc, char *const *argv, const char *options, 587 const struct option *long_options, int *opt_index) 588{ 589 return custom_getopt_internal(argc, argv, options, long_options, 590 opt_index); 591} 592