Implemented based on [1] and [2] for optional arguments. optopt is handled FreeBSD-style, per [3]. Other GNU and FreeBSD extensions are purely accidental. [1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html [2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html [3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE */
| 61 | [3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE |
| 62 | */ |
| 63 | int getopt(int argc, wchar_t* const argv[], const wchar_t* optstring) { |
| 64 | int optchar = -1; |
| 65 | const wchar_t* optdecl = NULL; |
| 66 | |
| 67 | optarg = NULL; |
| 68 | opterr = 0; |
| 69 | optopt = 0; |
| 70 | |
| 71 | /* Unspecified, but we need it to avoid overrunning the argv bounds. */ |
| 72 | if (optind >= argc) |
| 73 | goto no_more_optchars; |
| 74 | |
| 75 | /* If, when getopt() is called argv[optind] is a null pointer, getopt() |
| 76 | shall return -1 without changing optind. */ |
| 77 | if (argv[optind] == NULL) |
| 78 | goto no_more_optchars; |
| 79 | |
| 80 | /* If, when getopt() is called *argv[optind] is not the character '-', |
| 81 | getopt() shall return -1 without changing optind. */ |
| 82 | if (*argv[optind] != '-') |
| 83 | goto no_more_optchars; |
| 84 | |
| 85 | /* If, when getopt() is called argv[optind] points to the string "-", |
| 86 | getopt() shall return -1 without changing optind. */ |
| 87 | if (wcscmp(argv[optind], L"-") == 0) |
| 88 | goto no_more_optchars; |
| 89 | |
| 90 | /* If, when getopt() is called argv[optind] points to the string "--", |
| 91 | getopt() shall return -1 after incrementing optind. */ |
| 92 | if (wcscmp(argv[optind], L"--") == 0) { |
| 93 | ++optind; |
| 94 | goto no_more_optchars; |
| 95 | } |
| 96 | |
| 97 | if (optcursor == NULL || *optcursor == '\0') |
| 98 | optcursor = argv[optind] + 1; |
| 99 | |
| 100 | optchar = *optcursor; |
| 101 | |
| 102 | /* FreeBSD: The variable optopt saves the last known option character |
| 103 | returned by getopt(). */ |
| 104 | optopt = optchar; |
| 105 | |
| 106 | /* The getopt() function shall return the next option character (if one is |
| 107 | found) from argv that matches a character in optstring, if there is |
| 108 | one that matches. */ |
| 109 | optdecl = wcschr(optstring, optchar); |
| 110 | if (optdecl) { |
| 111 | /* [I]f a character is followed by a colon, the option takes an |
| 112 | argument. */ |
| 113 | if (optdecl[1] == ':') { |
| 114 | optarg = ++optcursor; |
| 115 | if (*optarg == '\0') { |
| 116 | /* GNU extension: Two colons mean an option takes an |
| 117 | optional arg; if there is text in the current argv-element |
| 118 | (i.e., in the same word as the option name itself, for example, |
| 119 | "-oarg"), then it is returned in optarg, otherwise optarg is set |
| 120 | to zero. */ |