// Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. // // If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option // element. The characters of this element (aside from the initial '-') are option characters. If // `getopt' is called repeatedly, it returns successively each of the option characters from each of // the option elements. // // If `getopt' finds another option character, it returns that character, updating `woptind' and // `nextchar' so that the next call to `getopt' can resume the scan with the following option // character or ARGV-element. // // If there are no more option characters, `getopt' returns `EOF'. Then `woptind' is the index in // ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so // that those that are not options now come last.) // // OPTSTRING is a string containing the legitimate option characters. If an option character is seen // that is not listed in OPTSTRING, return '?' after printing an error message. If you set // `wopterr' to zero, the error message is suppressed but we still return '?'. // // If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text // in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. // Two colons mean an option that wants an optional arg; if there is text in the current // ARGV-element, it is returned in `w.woptarg', otherwise `w.woptarg' is set to zero. // // If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option // ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. // // Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the // abbreviation is unique or is an exact match for some defined option. If they have an argument, // it follows the option name in the same ARGV-element, separated from the option name by a `=', or // else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that // option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is // zero. // // LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. // // LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a // long-named option has been found by the most recent call. // // If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only) { if (!initialized) _wgetopt_initialize(optstring); woptarg = NULL; if (nextchar == NULL || *nextchar == '\0') { int retval = _advance_to_next_argv(argc, argv, longopts); if (retval != 0) return retval; } // Decode the current option-ARGV-element. // Check whether the ARGV-element is a long option. // // If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't // consider it an abbreviated form of a long option that starts with f. Otherwise there would // be no way to give the -f short option. // // On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do // consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg // "u". // // This distinction seems to be the most useful approach. if (longopts != NULL && (argv[woptind][1] == '-' || (long_only && (argv[woptind][2] || !wcschr(shortopts, argv[woptind][1]))))) { int retval; if (_handle_long_opt(argc, argv, longopts, longind, long_only, &retval)) return retval; } return _handle_short_opt(argc, argv); }
// Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. // // If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option // element. The characters of this element (aside from the initial '-') are option characters. If // `getopt' is called repeatedly, it returns successively each of the option characters from each of // the option elements. // // If `getopt' finds another option character, it returns that character, updating `woptind' and // `nextchar' so that the next call to `getopt' can resume the scan with the following option // character or ARGV-element. // // If there are no more option characters, `getopt' returns `EOF'. Then `woptind' is the index in // ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so // that those that are not options now come last.) // // OPTSTRING is a string containing the legitimate option characters. If an option character is seen // that is not listed in OPTSTRING, return '?' after printing an error message. If you set // `wopterr' to zero, the error message is suppressed but we still return '?'. // // If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text // in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. // Two colons mean an option that wants an optional arg; if there is text in the current // ARGV-element, it is returned in `w.woptarg', otherwise `w.woptarg' is set to zero. // // If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option // ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. // // Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the // abbreviation is unique or is an exact match for some defined option. If they have an argument, // it follows the option name in the same ARGV-element, separated from the option name by a `=', or // else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that // option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is // zero. // // LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. // // LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a // long-named option has been found by the most recent call. // // If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only) { woptarg = NULL; if (woptind == 0) optstring = _wgetopt_initialize(optstring); if (nextchar == NULL || *nextchar == '\0') { // Advance to the next ARGV-element. if (ordering == PERMUTE) { // If we have just processed some options following some non-options, exchange them so // that the options come first. if (first_nonopt != last_nonopt && last_nonopt != woptind) exchange(argv); else if (last_nonopt != woptind) first_nonopt = woptind; // Skip any additional non-options and extend the range of non-options previously // skipped. while (woptind < argc && (argv[woptind][0] != '-' || argv[woptind][1] == '\0')) woptind++; last_nonopt = woptind; } // The special ARGV-element `--' means premature end of options. Skip it like a null option, // then exchange with previous non-options as if it were an option, then skip everything // else like a non-option. if (woptind != argc && !wcscmp(argv[woptind], L"--")) { woptind++; if (first_nonopt != last_nonopt && last_nonopt != woptind) exchange(argv); else if (first_nonopt == last_nonopt) first_nonopt = woptind; last_nonopt = argc; woptind = argc; } // If we have done all the ARGV-elements, stop the scan and back over any non-options that // we skipped and permuted. if (woptind == argc) { // Set the next-arg-index to point at the non-options that we previously skipped, so the // caller will digest them. if (first_nonopt != last_nonopt) woptind = first_nonopt; return EOF; } // If we have come to a non-option and did not permute it, either stop the scan or describe // it to the caller and pass it by. if ((argv[woptind][0] != '-' || argv[woptind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; woptarg = argv[woptind++]; return 1; } // We have found another option-ARGV-element. Skip the initial punctuation. nextchar = (argv[woptind] + 1 + (longopts != NULL && argv[woptind][1] == '-')); } // Decode the current option-ARGV-element. // Check whether the ARGV-element is a long option. // // If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't // consider it an abbreviated form of a long option that starts with f. Otherwise there would // be no way to give the -f short option. // // On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do // consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg // "u". // // This distinction seems to be the most useful approach. if (longopts != NULL && (argv[woptind][1] == '-' || (long_only && (argv[woptind][2] || !my_index(optstring, argv[woptind][1]))))) { wchar_t *nameend; const struct woption *p; const struct woption *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; // set to zero by Anton int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) ; //!OCLINT(empty body) // Test all long options for either exact match or abbreviated matches. for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!wcsncmp(p->name, nextchar, nameend - nextchar)) { if ((unsigned int)(nameend - nextchar) == (unsigned int)wcslen(p->name)) { // Exact match found. pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { // First nonexact match found. pfound = p; indfound = option_index; } else // Second or later nonexact match found. ambig = 1; } if (ambig && !exact) { if (wopterr) fwprintf(stderr, _(L"%ls: Option '%ls' is ambiguous\n"), argv[0], argv[woptind]); nextchar += wcslen(nextchar); woptind++; return '?'; } if (pfound != NULL) { option_index = indfound; woptind++; if (*nameend) { // Don't test has_arg with >, because some C compilers don't allow it to be used on // enums. if (pfound->has_arg) woptarg = nameend + 1; else { if (wopterr) { if (argv[woptind - 1][1] == '-') // --option fwprintf(stderr, _(L"%ls: Option '--%ls' doesn't allow an argument\n"), argv[0], pfound->name); else // +option or -option fwprintf(stderr, _(L"%ls: Option '%lc%ls' doesn't allow an argument\n"), argv[0], argv[woptind - 1][0], pfound->name); } nextchar += wcslen(nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (woptind < argc) woptarg = argv[woptind++]; else { if (wopterr) fwprintf(stderr, _(L"%ls: Option '%ls' requires an argument\n"), argv[0], argv[woptind - 1]); nextchar += wcslen(nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += wcslen(nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } // Can't find it as a long option. If this is not getopt_long_only, or the option starts // with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a // short option. if (!long_only || argv[woptind][1] == '-' || my_index(optstring, *nextchar) == NULL) { if (wopterr) { if (argv[woptind][1] == '-') // --option fwprintf(stderr, _(L"%ls: Unrecognized option '--%ls'\n"), argv[0], nextchar); else // +option or -option fwprintf(stderr, _(L"%ls: Unrecognized option '%lc%ls'\n"), argv[0], argv[woptind][0], nextchar); } nextchar = (wchar_t *)L""; woptind++; return '?'; } } // Look at and handle the next short option-character. { wchar_t c = *nextchar++; wchar_t *temp = const_cast<wchar_t *>(my_index(optstring, c)); // Increment `woptind' when we start to process its last character. if (*nextchar == '\0') ++woptind; if (temp == NULL || c == ':') { if (wopterr) { fwprintf(stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], (wint_t)c); } woptopt = c; if (*nextchar != '\0') woptind++; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { // This is an option that accepts an argument optionally. if (*nextchar != '\0') { woptarg = nextchar; woptind++; } else woptarg = NULL; nextchar = NULL; } else { // This is an option that requires an argument. if (*nextchar != '\0') { woptarg = nextchar; // If we end this ARGV-element by taking the rest as an arg, we must advance to // the next element now. woptind++; } else if (woptind == argc) { if (wopterr) { // 1003.2 specifies the format of this message. fwprintf(stderr, _(L"%ls: Option requires an argument -- %lc\n"), argv[0], (wint_t)c); } woptopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else // We already incremented `woptind' once; increment it again when taking next // ARGV-elt as argument. woptarg = argv[woptind++]; nextchar = NULL; } } return c; } }