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