Imported Upstream version 3.2.0
[platform/upstream/libwebsockets.git] / win32port / win32helpers / getopt_long.c
1 \r
2 /*\r
3  * Copyright (c) 1987, 1993, 1994, 1996\r
4  *      The Regents of the University of California.  All rights reserved.\r
5  *\r
6  * Redistribution and use in source and binary forms, with or without\r
7  * modification, are permitted provided that the following conditions\r
8  * are met:\r
9  * 1. Redistributions of source code must retain the above copyright\r
10  *    notice, this list of conditions and the following disclaimer.\r
11  * 2. Redistributions in binary form must reproduce the above copyright\r
12  *    notice, this list of conditions and the following disclaimer in the\r
13  *    documentation and/or other materials provided with the distribution.\r
14  * 3. All advertising materials mentioning features or use of this software\r
15  *    must display the following acknowledgement:\r
16  *      This product includes software developed by the University of\r
17  *      California, Berkeley and its contributors.\r
18  * 4. Neither the name of the University nor the names of its contributors\r
19  *    may be used to endorse or promote products derived from this software\r
20  *    without specific prior written permission.\r
21  *\r
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
32  * SUCH DAMAGE.\r
33  */\r
34 #include <assert.h>\r
35 #include <errno.h>\r
36 #include <stdio.h>\r
37 #include <stdlib.h>\r
38 #include <string.h>\r
39 #include "getopt.h"\r
40 \r
41 #define lws_ptr_diff(head, tail) \\r
42                         ((int)((char *)(head) - (char *)(tail)))\r
43 \r
44 extern int        opterr;       /* if error message should be printed */\r
45 extern int        optind;       /* index into parent argv vector */\r
46 extern int        optopt;       /* character checked for validity */\r
47 extern int        optreset;     /* reset getopt */\r
48 extern char *optarg;    /* argument associated with option */\r
49 \r
50 #define __P(x) x\r
51 #define _DIAGASSERT(x) assert(x)\r
52 \r
53 static char * __progname __P((char *));\r
54 int getopt_internal __P((int, char * const *, const char *));\r
55 \r
56 static char *\r
57 __progname(nargv0)\r
58         char * nargv0;\r
59 {\r
60         char * tmp;\r
61 \r
62         _DIAGASSERT(nargv0 != NULL);\r
63 \r
64         tmp = strrchr(nargv0, '/');\r
65         if (tmp)\r
66                 tmp++;\r
67         else\r
68                 tmp = nargv0;\r
69         return(tmp);\r
70 }\r
71 \r
72 #define BADCH   (int)'?'\r
73 #define BADARG  (int)':'\r
74 #define EMSG    ""\r
75 \r
76 /*\r
77  * getopt --\r
78  *      Parse argc/argv argument vector.\r
79  */\r
80 int\r
81 getopt_internal(nargc, nargv, ostr)\r
82         int nargc;\r
83         char * const *nargv;\r
84         const char *ostr;\r
85 {\r
86         static char *place = EMSG;              /* option letter processing */\r
87         char *oli;                              /* option letter list index */\r
88 \r
89         _DIAGASSERT(nargv != NULL);\r
90         _DIAGASSERT(ostr != NULL);\r
91 \r
92         if (optreset || !*place) {              /* update scanning pointer */\r
93                 optreset = 0;\r
94                 if (optind >= nargc || *(place = nargv[optind]) != '-') {\r
95                         place = EMSG;\r
96                         return (-1);\r
97                 }\r
98                 if (place[1] && *++place == '-') {      /* found "--" */\r
99                         /* ++optind; */\r
100                         place = EMSG;\r
101                         return (-2);\r
102                 }\r
103         }                                       /* option letter okay? */\r
104         if ((optopt = (int)*place++) == (int)':' ||\r
105             !(oli = strchr(ostr, optopt))) {\r
106                 /*\r
107                  * if the user didn't specify '-' as an option,\r
108                  * assume it means -1.\r
109                  */\r
110                 if (optopt == (int)'-')\r
111                         return (-1);\r
112                 if (!*place)\r
113                         ++optind;\r
114                 if (opterr && *ostr != ':')\r
115                         (void)fprintf(stderr,\r
116                             "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);\r
117                 return (BADCH);\r
118         }\r
119         if (*++oli != ':') {                    /* don't need argument */\r
120                 optarg = NULL;\r
121                 if (!*place)\r
122                         ++optind;\r
123         } else {                                /* need an argument */\r
124                 if (*place)                     /* no white space */\r
125                         optarg = place;\r
126                 else if (nargc <= ++optind) {   /* no arg */\r
127                         place = EMSG;\r
128                         if ((opterr) && (*ostr != ':'))\r
129                                 (void)fprintf(stderr,\r
130                                     "%s: option requires an argument -- %c\n",\r
131                                     __progname(nargv[0]), optopt);\r
132                         return (BADARG);\r
133                 } else                          /* white space */\r
134                         optarg = nargv[optind];\r
135                 place = EMSG;\r
136                 ++optind;\r
137         }\r
138         return (optopt);                        /* dump back option letter */\r
139 }\r
140 \r
141 #if 0\r
142 /*\r
143  * getopt --\r
144  *      Parse argc/argv argument vector.\r
145  */\r
146 int\r
147 getopt2(nargc, nargv, ostr)\r
148         int nargc;\r
149         char * const *nargv;\r
150         const char *ostr;\r
151 {\r
152         int retval;\r
153 \r
154         if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {\r
155                 retval = -1;\r
156                 ++optind; \r
157         }\r
158         return(retval);\r
159 }\r
160 #endif\r
161 \r
162 /*\r
163  * getopt_long --\r
164  *      Parse argc/argv argument vector.\r
165  */\r
166 int\r
167 getopt_long(nargc, nargv, options, long_options, index)\r
168         int nargc;\r
169         char ** nargv;\r
170         char * options;\r
171         struct option * long_options;\r
172         int * index;\r
173 {\r
174         int retval;\r
175 \r
176         _DIAGASSERT(nargv != NULL);\r
177         _DIAGASSERT(options != NULL);\r
178         _DIAGASSERT(long_options != NULL);\r
179         /* index may be NULL */\r
180 \r
181         if ((retval = getopt_internal(nargc, nargv, options)) == -2) {\r
182                 char *current_argv = nargv[optind++] + 2, *has_equal;\r
183                 int i, current_argv_len, match = -1;\r
184 \r
185                 if (*current_argv == '\0') {\r
186                         return(-1);\r
187                 }\r
188                 if ((has_equal = strchr(current_argv, '=')) != NULL) {\r
189                         current_argv_len = lws_ptr_diff(has_equal, current_argv);\r
190                         has_equal++;\r
191                 } else\r
192                         current_argv_len = (int)strlen(current_argv);\r
193 \r
194                 for (i = 0; long_options[i].name; i++) { \r
195                         if (strncmp(current_argv, long_options[i].name, current_argv_len))\r
196                                 continue;\r
197 \r
198                         if (strlen(long_options[i].name) == (unsigned)current_argv_len) { \r
199                                 match = i;\r
200                                 break;\r
201                         }\r
202                         if (match == -1)\r
203                                 match = i;\r
204                 }\r
205                 if (match != -1) {\r
206                         if (long_options[match].has_arg == required_argument ||\r
207                             long_options[match].has_arg == optional_argument) {\r
208                                 if (has_equal)\r
209                                         optarg = has_equal;\r
210                                 else\r
211                                         optarg = nargv[optind++];\r
212                         }\r
213                         if ((long_options[match].has_arg == required_argument)\r
214                             && (optarg == NULL)) {\r
215                                 /*\r
216                                  * Missing argument, leading :\r
217                                  * indicates no error should be generated\r
218                                  */\r
219                                 if ((opterr) && (*options != ':'))\r
220                                         (void)fprintf(stderr,\r
221                                       "%s: option requires an argument -- %s\n",\r
222                                       __progname(nargv[0]), current_argv);\r
223                                 return (BADARG);\r
224                         }\r
225                 } else { /* No matching argument */\r
226                         if ((opterr) && (*options != ':'))\r
227                                 (void)fprintf(stderr,\r
228                                     "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);\r
229                         return (BADCH);\r
230                 }\r
231                 if (long_options[match].flag) {\r
232                         *long_options[match].flag = long_options[match].val;\r
233                         retval = 0;\r
234                 } else \r
235                         retval = long_options[match].val;\r
236                 if (index)\r
237                         *index = match;\r
238         }\r
239         return(retval);\r
240 }\r