123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- #define _GNU_SOURCE
- #include <stddef.h>
- #include <getopt.h>
- #include <stdio.h>
- #include <string.h>
- extern int __optpos, __optreset;
- static void permute(char *const *argv, int dest, int src)
- {
- char **av = (char **)argv;
- char *tmp = av[src];
- int i;
- for (i=src; i>dest; i--)
- av[i] = av[i-1];
- av[dest] = tmp;
- }
- void __getopt_msg(const char *, const char *, const char *, size_t);
- static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
- static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
- {
- int ret, skipped, resumed;
- if (!optind || __optreset) {
- __optreset = 0;
- __optpos = 0;
- optind = 1;
- }
- if (optind >= argc || !argv[optind]) return -1;
- skipped = optind;
- if (optstring[0] != '+' && optstring[0] != '-') {
- int i;
- for (i=optind; ; i++) {
- if (i >= argc || !argv[i]) return -1;
- if (argv[i][0] == '-' && argv[i][1]) break;
- }
- optind = i;
- }
- resumed = optind;
- ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
- if (resumed > skipped) {
- int i, cnt = optind-resumed;
- for (i=0; i<cnt; i++)
- permute(argv, skipped, optind-1);
- optind = skipped + cnt;
- }
- return ret;
- }
- static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
- {
- optarg = 0;
- if (longopts && argv[optind][0] == '-' &&
- ((longonly && argv[optind][1]) ||
- (argv[optind][1] == '-' && argv[optind][2])))
- {
- int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
- int i, cnt, match;
- char *opt;
- for (cnt=i=0; longopts[i].name; i++) {
- const char *name = longopts[i].name;
- opt = argv[optind]+1;
- if (*opt == '-') opt++;
- for (; *name && *name == *opt; name++, opt++);
- if (*opt && *opt != '=') continue;
- match = i;
- if (!*name) {
- cnt = 1;
- break;
- }
- cnt++;
- }
- if (cnt==1) {
- i = match;
- optind++;
- optopt = longopts[i].val;
- if (*opt == '=') {
- if (!longopts[i].has_arg) {
- if (colon || !opterr)
- return '?';
- __getopt_msg(argv[0],
- ": option does not take an argument: ",
- longopts[i].name,
- strlen(longopts[i].name));
- return '?';
- }
- optarg = opt+1;
- } else {
- if (longopts[i].has_arg == required_argument) {
- if (!(optarg = argv[optind])) {
- if (colon) return ':';
- if (!opterr) return '?';
- __getopt_msg(argv[0],
- ": option requires an argument: ",
- longopts[i].name,
- strlen(longopts[i].name));
- return '?';
- }
- optind++;
- } else optarg = NULL;
- }
- if (idx) *idx = i;
- if (longopts[i].flag) {
- *longopts[i].flag = longopts[i].val;
- return 0;
- }
- return longopts[i].val;
- }
- if (argv[optind][1] == '-') {
- if (!colon && opterr)
- __getopt_msg(argv[0], cnt ?
- ": option is ambiguous: " :
- ": unrecognized option: ",
- argv[optind]+2,
- strlen(argv[optind]+2));
- optind++;
- return '?';
- }
- }
- return getopt(argc, argv, optstring);
- }
- int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
- {
- return __getopt_long(argc, argv, optstring, longopts, idx, 0);
- }
- int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
- {
- return __getopt_long(argc, argv, optstring, longopts, idx, 1);
- }
|