1 /*
2 * getopt_long() -- long options parser
3 *
4 * Portions Copyright (c) 1987, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Portions Copyright (c) 2003
8 * PostgreSQL Global Development Group
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $PostgreSQL: pgsql/src/port/getopt_long.c,v 1.6 2007/03/26 21:44:11 momjian Exp $
35 */
36
37 /*
38 * getopt.cpp -
39 *
40 * Copyright (c) 2009 Higepon(Taro Minowa) <higepon@users.sourceforge.jp>
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 *
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 *
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
56 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
57 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
59 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *
65 * $Id: getopt.cpp 183 2008-07-04 06:19:28Z higepon $
66 */
67
68 #include <stdio.h>
69 #include "getoptU.h"
70
71 using namespace scheme;
72
73 #ifndef HAVE_INT_OPTRESET
74 int optreset;
75 #endif
76
77 #define BADCH '?'
78 #define BADARG ':'
79 #define EMSG (ucs4char*)(UC(""))
80
81 int opterrU;
82 int optindU= 1;
83 int optoptU;
84 ucs4char *optargU;
85
strcspnU(const ucs4char * str1,const ucs4char * str2)86 static size_t strcspnU(const ucs4char* str1, const ucs4char* str2) {
87
88 const ucs4char* const head = str1;
89 const ucs4char* t;
90 for (; *str1; str1++) {
91
92 for (t = str2; *t; t++) if (*t == *str1) return str1 - head;
93 }
94 return str1 - head;
95 }
96
strncmpU(const ucs4char * s1,const ucs4char * s2,size_t n)97 static int strncmpU(const ucs4char *s1, const ucs4char *s2, size_t n)
98 {
99 for(size_t i = 0; i < n ; i++ ) {
100 if( s1[i] > s2[i] ) {
101 return 1;
102 }
103 if( s1[i] < s2[i] ) {
104 return -1;
105 }
106 if( s1[i] == s2[i] ) {
107 continue;
108 }
109 if( s1[i] == '\0' || s2[i] == '\0' ) {
110 break;
111 }
112 }
113 return 0;
114 }
115
strlenU(const ucs4char * s)116 static size_t strlenU(const ucs4char *s)
117 {
118 int c = 0;
119 while(*s++)
120 c++;
121 return c;
122 }
123
124 // strchr from OpenBSD
strchrU(const ucs4char * p,int ch)125 static ucs4char* strchrU(const ucs4char *p, int ch)
126 {
127 for (;; ++p) {
128 if (*p == ch)
129 return((ucs4char *)p);
130 if (!*p)
131 return((ucs4char *)NULL);
132 }
133 /* NOTREACHED */
134 }
135
getopt_longU(int argc,ucs4char * const argv[],const ucs4char * optstring,const struct optionU * longopts,int * longindex)136 int scheme::getopt_longU(int argc, ucs4char *const argv[],
137 const ucs4char *optstring,
138 const struct optionU * longopts, int *longindex)
139 {
140 static ucs4char *place = EMSG; /* option letter processing */
141 ucs4char *oli; /* option letter list index */
142
143 if (optreset || !*place)
144 { /* update scanning pointer */
145 optreset = 0;
146
147 if (optindU >= argc)
148 {
149 place = EMSG;
150 return -1;
151 }
152
153 place = argv[optindU];
154
155 if (place[0] != '-')
156 {
157 place = EMSG;
158 return -1;
159 }
160
161 place++;
162
163 if (place[0] && place[0] == '-' && place[1] == '\0')
164 { /* found "--" */
165 ++optindU;
166 place = EMSG;
167 return -1;
168 }
169
170 if (place[0] && place[0] == '-' && place[1])
171 {
172 /* long option */
173 size_t namelen;
174 int i;
175
176 place++;
177 namelen = strcspnU(place, UC("="));
178 for (i = 0; longopts[i].name != NULL; i++)
179 {
180 if (strlenU(longopts[i].name) == namelen
181 && strncmpU(place, longopts[i].name, namelen) == 0)
182 {
183 if (longopts[i].has_arg)
184 {
185 if (place[namelen] == '=')
186 optargU = place + namelen + 1;
187 else if (optindU < argc - 1)
188 {
189 optindU++;
190 optargU = argv[optindU];
191 }
192 else
193 {
194 if (optstring[0] == ':')
195 return BADARG;
196 if (opterrU)
197 fprintf(stderr,
198 "%s: option requires an argument -- %s\n",
199 ucs4string(argv[0]).ascii_c_str(), ucs4string(place).ascii_c_str());
200 place = EMSG;
201 optindU++;
202 return BADCH;
203 }
204 }
205 else
206 {
207 optargU = NULL;
208 if (place[namelen] != 0)
209 {
210 /* XXX error? */
211 }
212 }
213 optindU++;
214
215 if (longindex)
216 *longindex = i;
217
218 place = EMSG;
219
220 if (longopts[i].flag == NULL)
221 return longopts[i].val;
222 else
223 {
224 *longopts[i].flag = longopts[i].val;
225 return 0;
226 }
227 }
228 }
229
230 if (opterrU && optstring[0] != ':')
231 fprintf(stderr,
232 "%s: illegal option -- %s %d\n", ucs4string(argv[0]).ascii_c_str(), ucs4string(place).ascii_c_str(), __LINE__);
233 place = EMSG;
234 optindU++;
235 return BADCH;
236 }
237 }
238
239 /* short option */
240 optoptU = (int) *place++;
241
242 oli = strchrU(optstring, optoptU);
243 if (!oli)
244 {
245 if (!*place)
246 ++optindU;
247 if (opterrU && *optstring != ':') {
248 fprintf(stderr,
249 "%s: illegal option -- %s %d\n", ucs4string(argv[0]).ascii_c_str(), ucs4string(optoptU).ascii_c_str(), __LINE__);
250 }
251 return BADCH;
252 }
253
254 if (oli[1] != ':')
255 { /* don't need argument */
256 optargU = NULL;
257 if (!*place)
258 ++optindU;
259 }
260 else
261 { /* need an argument */
262 if (*place) /* no white space */
263 optargU = place;
264 else if (argc <= ++optindU)
265 { /* no arg */
266 place = EMSG;
267 if (*optstring == ':')
268 return BADARG;
269 if (opterrU)
270 fprintf(stderr,
271 "%s: option requires an argument -- %s\n",
272 ucs4string(argv[0]).ascii_c_str(), ucs4string(optoptU).ascii_c_str());
273 return BADCH;
274 }
275 else
276 /* white space */
277 optargU = argv[optindU];
278 place = EMSG;
279 ++optindU;
280 }
281 return optoptU;
282 }
283
284