dns response handling: ignore presence of wrong-type RRs
[musl] / src / misc / getopt_long.c
1 #define _GNU_SOURCE
2 #include <stddef.h>
3 #include <stdlib.h>
4 #include <limits.h>
5 #include <getopt.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include "stdio_impl.h"
9
10 extern int __optpos, __optreset;
11
12 static void permute(char *const *argv, int dest, int src)
13 {
14         char **av = (char **)argv;
15         char *tmp = av[src];
16         int i;
17         for (i=src; i>dest; i--)
18                 av[i] = av[i-1];
19         av[dest] = tmp;
20 }
21
22 static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
23
24 static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
25 {
26         int ret, skipped, resumed;
27         if (!optind || __optreset) {
28                 __optreset = 0;
29                 __optpos = 0;
30                 optind = 1;
31         }
32         if (optind >= argc || !argv[optind]) return -1;
33         skipped = optind;
34         if (optstring[0] != '+' && optstring[0] != '-') {
35                 int i;
36                 for (i=optind; ; i++) {
37                         if (i >= argc || !argv[i]) return -1;
38                         if (argv[i][0] == '-' && argv[i][1]) break;
39                 }
40                 optind = i;
41         }
42         resumed = optind;
43         ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
44         if (resumed > skipped) {
45                 int i, cnt = optind-resumed;
46                 for (i=0; i<cnt; i++)
47                         permute(argv, skipped, optind-1);
48                 optind = skipped + cnt;
49         }
50         return ret;
51 }
52
53 static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
54 {
55         optarg = 0;
56         if (longopts && argv[optind][0] == '-' &&
57                 ((longonly && argv[optind][1] && argv[optind][1] != '-') ||
58                  (argv[optind][1] == '-' && argv[optind][2])))
59         {
60                 int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
61                 int i, cnt, match;
62                 char *arg, *opt, *start = argv[optind]+1;
63                 for (cnt=i=0; longopts[i].name; i++) {
64                         const char *name = longopts[i].name;
65                         opt = start;
66                         if (*opt == '-') opt++;
67                         while (*opt && *opt != '=' && *opt == *name)
68                                 name++, opt++;
69                         if (*opt && *opt != '=') continue;
70                         arg = opt;
71                         match = i;
72                         if (!*name) {
73                                 cnt = 1;
74                                 break;
75                         }
76                         cnt++;
77                 }
78                 if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) {
79                         int l = arg-start;
80                         for (i=0; optstring[i]; i++) {
81                                 int j;
82                                 for (j=0; j<l && start[j]==optstring[i+j]; j++);
83                                 if (j==l) {
84                                         cnt++;
85                                         break;
86                                 }
87                         }
88                 }
89                 if (cnt==1) {
90                         i = match;
91                         opt = arg;
92                         optind++;
93                         if (*opt == '=') {
94                                 if (!longopts[i].has_arg) {
95                                         optopt = longopts[i].val;
96                                         if (colon || !opterr)
97                                                 return '?';
98                                         __getopt_msg(argv[0],
99                                                 ": option does not take an argument: ",
100                                                 longopts[i].name,
101                                                 strlen(longopts[i].name));
102                                         return '?';
103                                 }
104                                 optarg = opt+1;
105                         } else if (longopts[i].has_arg == required_argument) {
106                                 if (!(optarg = argv[optind])) {
107                                         optopt = longopts[i].val;
108                                         if (colon) return ':';
109                                         if (!opterr) return '?';
110                                         __getopt_msg(argv[0],
111                                                 ": option requires an argument: ",
112                                                 longopts[i].name,
113                                                 strlen(longopts[i].name));
114                                         return '?';
115                                 }
116                                 optind++;
117                         }
118                         if (idx) *idx = i;
119                         if (longopts[i].flag) {
120                                 *longopts[i].flag = longopts[i].val;
121                                 return 0;
122                         }
123                         return longopts[i].val;
124                 }
125                 if (argv[optind][1] == '-') {
126                         optopt = 0;
127                         if (!colon && opterr)
128                                 __getopt_msg(argv[0], cnt ?
129                                         ": option is ambiguous: " :
130                                         ": unrecognized option: ",
131                                         argv[optind]+2,
132                                         strlen(argv[optind]+2));
133                         optind++;
134                         return '?';
135                 }
136         }
137         return getopt(argc, argv, optstring);
138 }
139
140 int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
141 {
142         return __getopt_long(argc, argv, optstring, longopts, idx, 0);
143 }
144
145 int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
146 {
147         return __getopt_long(argc, argv, optstring, longopts, idx, 1);
148 }