1 /* Getopt for Microsoft C
2 This code is a modification of the Free Software Foundation, Inc.
3 Getopt library for parsing command line argument the purpose was
4 to provide a Microsoft Visual C friendly derivative. This code
5 provides functionality for both Unicode and Multibyte builds.
6 Date: 02/03/2011 - Ludvik Jerabek - Initial Release
7 Version: 1.0
8 Comment: Supports getopt, getopt_long, and getopt_long_only
9 and POSIXLY_CORRECT environment flag
10 License: LGPL
11 Revisions:
12 02/03/2011 - Ludvik Jerabek - Initial Release
13 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
14 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
15 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
16 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
17 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
18 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
19 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
20 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
21 **DISCLAIMER**
22 THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
23 EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
24 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
26 EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
27 APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
28 DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
29 USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
30 PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
31 YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
32 EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 */
34 #ifndef _CRT_SECURE_NO_WARNINGS
35 # define _CRT_SECURE_NO_WARNINGS
36 #endif
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <malloc.h>
40 #include "wingetopt.h"
41 
42 #ifdef __cplusplus
43     #define _GETOPT_THROW throw()
44 #else
45     #define _GETOPT_THROW
46 #endif
47 
48 int optind = 1;
49 int opterr = 1;
50 int optopt = '?';
51 enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
52 
53 //
54 //
55 //		Ansi structures and functions follow
56 //
57 //
58 
59 static struct _getopt_data_a
60 {
61     int optind;
62     int opterr;
63     int optopt;
64     char *optarg;
65     int __initialized;
66     char *__nextchar;
67     enum ENUM_ORDERING __ordering;
68     int __posixly_correct;
69     int __first_nonopt;
70     int __last_nonopt;
71 } getopt_data_a;
72 char *optarg_a;
73 
exchange_a(char ** argv,struct _getopt_data_a * d)74 static void exchange_a(char **argv, struct _getopt_data_a *d)
75 {
76     int bottom = d->__first_nonopt;
77     int middle = d->__last_nonopt;
78     int top = d->optind;
79     char *tem;
80     while (top > middle && middle > bottom)
81     {
82         if (top - middle > middle - bottom)
83         {
84             int len = middle - bottom;
85             register int i;
86             for (i = 0; i < len; i++)
87             {
88                 tem = argv[bottom + i];
89                 argv[bottom + i] = argv[top - (middle - bottom) + i];
90                 argv[top - (middle - bottom) + i] = tem;
91             }
92             top -= len;
93         }
94         else
95         {
96             int len = top - middle;
97             register int i;
98             for (i = 0; i < len; i++)
99             {
100                 tem = argv[bottom + i];
101                 argv[bottom + i] = argv[middle + i];
102                 argv[middle + i] = tem;
103             }
104             bottom += len;
105         }
106     }
107     d->__first_nonopt += (d->optind - d->__last_nonopt);
108     d->__last_nonopt = d->optind;
109 }
_getopt_initialize_a(const char * optstring,struct _getopt_data_a * d,int posixly_correct)110 static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct)
111 {
112     d->__first_nonopt = d->__last_nonopt = d->optind;
113     d->__nextchar = NULL;
114     d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT");
115     if (optstring[0] == '-')
116     {
117         d->__ordering = RETURN_IN_ORDER;
118         ++optstring;
119     }
120     else if (optstring[0] == '+')
121     {
122         d->__ordering = REQUIRE_ORDER;
123         ++optstring;
124     }
125     else if (d->__posixly_correct)
126         d->__ordering = REQUIRE_ORDER;
127     else
128         d->__ordering = PERMUTE;
129     return optstring;
130 }
_getopt_internal_r_a(int argc,char * const * argv,const char * optstring,const struct option_a * longopts,int * longind,int long_only,struct _getopt_data_a * d,int posixly_correct)131 int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct)
132 {
133     int print_errors = d->opterr;
134     if (argc < 1)
135         return -1;
136     d->optarg = NULL;
137     if (d->optind == 0 || !d->__initialized)
138     {
139         if (d->optind == 0)
140             d->optind = 1;
141         optstring = _getopt_initialize_a (optstring, d, posixly_correct);
142         d->__initialized = 1;
143     }
144     else if (optstring[0] == '-' || optstring[0] == '+')
145         optstring++;
146     if (optstring[0] == ':')
147         print_errors = 0;
148     if (d->__nextchar == NULL || *d->__nextchar == '\0')
149     {
150         if (d->__last_nonopt > d->optind)
151             d->__last_nonopt = d->optind;
152         if (d->__first_nonopt > d->optind)
153             d->__first_nonopt = d->optind;
154         if (d->__ordering == PERMUTE)
155         {
156             if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
157                 exchange_a ((char **) argv, d);
158             else if (d->__last_nonopt != d->optind)
159                 d->__first_nonopt = d->optind;
160             while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
161                 d->optind++;
162             d->__last_nonopt = d->optind;
163         }
164         if (d->optind != argc && !strcmp(argv[d->optind], "--"))
165         {
166             d->optind++;
167             if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
168                 exchange_a((char **) argv, d);
169             else if (d->__first_nonopt == d->__last_nonopt)
170                 d->__first_nonopt = d->optind;
171             d->__last_nonopt = argc;
172             d->optind = argc;
173         }
174         if (d->optind == argc)
175         {
176             if (d->__first_nonopt != d->__last_nonopt)
177                 d->optind = d->__first_nonopt;
178             return -1;
179         }
180         if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
181         {
182             if (d->__ordering == REQUIRE_ORDER)
183                 return -1;
184             d->optarg = argv[d->optind++];
185             return 1;
186         }
187         d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-'));
188     }
189     if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1])))))
190     {
191         char *nameend;
192         unsigned int namelen;
193         const struct option_a *p;
194         const struct option_a *pfound = NULL;
195         struct option_list
196         {
197             const struct option_a *p;
198             struct option_list *next;
199         } *ambig_list = NULL;
200         int exact = 0;
201         int indfound = -1;
202         int option_index;
203         for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++);
204         namelen = (unsigned int)(nameend - d->__nextchar);
205         for (p = longopts, option_index = 0; p->name; p++, option_index++)
206             if (!strncmp(p->name, d->__nextchar, namelen))
207             {
208                 if (namelen == (unsigned int)strlen(p->name))
209                 {
210                     pfound = p;
211                     indfound = option_index;
212                     exact = 1;
213                     break;
214                 }
215                 else if (pfound == NULL)
216                 {
217                     pfound = p;
218                     indfound = option_index;
219                 }
220                 else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
221                 {
222                     struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
223                     newp->p = p;
224                     newp->next = ambig_list;
225                     ambig_list = newp;
226                 }
227             }
228             if (ambig_list != NULL && !exact)
229             {
230                 if (print_errors)
231                 {
232                     struct option_list first;
233                     first.p = pfound;
234                     first.next = ambig_list;
235                     ambig_list = &first;
236                     fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
237                     do
238                     {
239                         fprintf (stderr, " '--%s'", ambig_list->p->name);
240                         ambig_list = ambig_list->next;
241                     }
242                     while (ambig_list != NULL);
243                     fputc ('\n', stderr);
244                 }
245                 d->__nextchar += strlen(d->__nextchar);
246                 d->optind++;
247                 d->optopt = 0;
248                 return '?';
249             }
250             if (pfound != NULL)
251             {
252                 option_index = indfound;
253                 d->optind++;
254                 if (*nameend)
255                 {
256                     if (pfound->has_arg)
257                         d->optarg = nameend + 1;
258                     else
259                     {
260                         if (print_errors)
261                         {
262                             if (argv[d->optind - 1][1] == '-')
263                             {
264                                 fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
265                             }
266                             else
267                             {
268                                 fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
269                             }
270                         }
271                         d->__nextchar += strlen(d->__nextchar);
272                         d->optopt = pfound->val;
273                         return '?';
274                     }
275                 }
276                 else if (pfound->has_arg == 1)
277                 {
278                     if (d->optind < argc)
279                         d->optarg = argv[d->optind++];
280                     else
281                     {
282                         if (print_errors)
283                         {
284                             fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
285                         }
286                         d->__nextchar += strlen(d->__nextchar);
287                         d->optopt = pfound->val;
288                         return optstring[0] == ':' ? ':' : '?';
289                     }
290                 }
291                 d->__nextchar += strlen(d->__nextchar);
292                 if (longind != NULL)
293                     *longind = option_index;
294                 if (pfound->flag)
295                 {
296                     *(pfound->flag) = pfound->val;
297                     return 0;
298                 }
299                 return pfound->val;
300             }
301             if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL)
302             {
303                 if (print_errors)
304                 {
305                     if (argv[d->optind][1] == '-')
306                     {
307                         fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
308                     }
309                     else
310                     {
311                         fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
312                     }
313                 }
314                 d->__nextchar = (char *)"";
315                 d->optind++;
316                 d->optopt = 0;
317                 return '?';
318             }
319     }
320     {
321         char c = *d->__nextchar++;
322         char *temp = (char*)strchr(optstring, c);
323         if (*d->__nextchar == '\0')
324             ++d->optind;
325         if (temp == NULL || c == ':' || c == ';')
326         {
327             if (print_errors)
328             {
329                 fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c);
330             }
331             d->optopt = c;
332             return '?';
333         }
334         if (temp[0] == 'W' && temp[1] == ';')
335         {
336             char *nameend;
337             const struct option_a *p;
338             const struct option_a *pfound = NULL;
339             int exact = 0;
340             int ambig = 0;
341             int indfound = 0;
342             int option_index;
343             if (longopts == NULL)
344                 goto no_longs;
345             if (*d->__nextchar != '\0')
346             {
347                 d->optarg = d->__nextchar;
348                 d->optind++;
349             }
350             else if (d->optind == argc)
351             {
352                 if (print_errors)
353                 {
354                     fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
355                 }
356                 d->optopt = c;
357                 if (optstring[0] == ':')
358                     c = ':';
359                 else
360                     c = '?';
361                 return c;
362             }
363             else
364                 d->optarg = argv[d->optind++];
365             for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++);
366             for (p = longopts, option_index = 0; p->name; p++, option_index++)
367                 if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar))
368                 {
369                     if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name))
370                     {
371                         pfound = p;
372                         indfound = option_index;
373                         exact = 1;
374                         break;
375                     }
376                     else if (pfound == NULL)
377                     {
378                         pfound = p;
379                         indfound = option_index;
380                     }
381                     else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
382                         ambig = 1;
383                 }
384                 if (ambig && !exact)
385                 {
386                     if (print_errors)
387                     {
388                         fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
389                     }
390                     d->__nextchar += strlen(d->__nextchar);
391                     d->optind++;
392                     return '?';
393                 }
394                 if (pfound != NULL)
395                 {
396                     option_index = indfound;
397                     if (*nameend)
398                     {
399                         if (pfound->has_arg)
400                             d->optarg = nameend + 1;
401                         else
402                         {
403                             if (print_errors)
404                             {
405                                 fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
406                             }
407                             d->__nextchar += strlen(d->__nextchar);
408                             return '?';
409                         }
410                     }
411                     else if (pfound->has_arg == 1)
412                     {
413                         if (d->optind < argc)
414                             d->optarg = argv[d->optind++];
415                         else
416                         {
417                             if (print_errors)
418                             {
419                                 fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
420                             }
421                             d->__nextchar += strlen(d->__nextchar);
422                             return optstring[0] == ':' ? ':' : '?';
423                         }
424                     }
425                     else
426                         d->optarg = NULL;
427                     d->__nextchar += strlen(d->__nextchar);
428                     if (longind != NULL)
429                         *longind = option_index;
430                     if (pfound->flag)
431                     {
432                         *(pfound->flag) = pfound->val;
433                         return 0;
434                     }
435                     return pfound->val;
436                 }
437 no_longs:
438                 d->__nextchar = NULL;
439                 return 'W';
440         }
441         if (temp[1] == ':')
442         {
443             if (temp[2] == ':')
444             {
445                 if (*d->__nextchar != '\0')
446                 {
447                     d->optarg = d->__nextchar;
448                     d->optind++;
449                 }
450                 else
451                     d->optarg = NULL;
452                 d->__nextchar = NULL;
453             }
454             else
455             {
456                 if (*d->__nextchar != '\0')
457                 {
458                     d->optarg = d->__nextchar;
459                     d->optind++;
460                 }
461                 else if (d->optind == argc)
462                 {
463                     if (print_errors)
464                     {
465                         fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
466                     }
467                     d->optopt = c;
468                     if (optstring[0] == ':')
469                         c = ':';
470                     else
471                         c = '?';
472                 }
473                 else
474                     d->optarg = argv[d->optind++];
475                 d->__nextchar = NULL;
476             }
477         }
478         return c;
479     }
480 }
_getopt_internal_a(int argc,char * const * argv,const char * optstring,const struct option_a * longopts,int * longind,int long_only,int posixly_correct)481 int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct)
482 {
483     int result;
484     getopt_data_a.optind = optind;
485     getopt_data_a.opterr = opterr;
486     result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct);
487     optind = getopt_data_a.optind;
488     optarg_a = getopt_data_a.optarg;
489     optopt = getopt_data_a.optopt;
490     return result;
491 }
getopt_a(int argc,char * const * argv,const char * optstring)492 int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW
493 {
494     return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0);
495 }
getopt_long_a(int argc,char * const * argv,const char * options,const struct option_a * long_options,int * opt_index)496 int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
497 {
498     return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0);
499 }
getopt_long_only_a(int argc,char * const * argv,const char * options,const struct option_a * long_options,int * opt_index)500 int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
501 {
502     return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0);
503 }
_getopt_long_r_a(int argc,char * const * argv,const char * options,const struct option_a * long_options,int * opt_index,struct _getopt_data_a * d)504 int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
505 {
506     return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0);
507 }
_getopt_long_only_r_a(int argc,char * const * argv,const char * options,const struct option_a * long_options,int * opt_index,struct _getopt_data_a * d)508 int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
509 {
510     return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0);
511 }
512 
513 //
514 //
515 //	Unicode Structures and Functions
516 //
517 //
518 
519 static struct _getopt_data_w
520 {
521     int optind;
522     int opterr;
523     int optopt;
524     wchar_t *optarg;
525     int __initialized;
526     wchar_t *__nextchar;
527     enum ENUM_ORDERING __ordering;
528     int __posixly_correct;
529     int __first_nonopt;
530     int __last_nonopt;
531 } getopt_data_w;
532 wchar_t *optarg_w;
533 
exchange_w(wchar_t ** argv,struct _getopt_data_w * d)534 static void exchange_w(wchar_t **argv, struct _getopt_data_w *d)
535 {
536     int bottom = d->__first_nonopt;
537     int middle = d->__last_nonopt;
538     int top = d->optind;
539     wchar_t *tem;
540     while (top > middle && middle > bottom)
541     {
542         if (top - middle > middle - bottom)
543         {
544             int len = middle - bottom;
545             register int i;
546             for (i = 0; i < len; i++)
547             {
548                 tem = argv[bottom + i];
549                 argv[bottom + i] = argv[top - (middle - bottom) + i];
550                 argv[top - (middle - bottom) + i] = tem;
551             }
552             top -= len;
553         }
554         else
555         {
556             int len = top - middle;
557             register int i;
558             for (i = 0; i < len; i++)
559             {
560                 tem = argv[bottom + i];
561                 argv[bottom + i] = argv[middle + i];
562                 argv[middle + i] = tem;
563             }
564             bottom += len;
565         }
566     }
567     d->__first_nonopt += (d->optind - d->__last_nonopt);
568     d->__last_nonopt = d->optind;
569 }
_getopt_initialize_w(const wchar_t * optstring,struct _getopt_data_w * d,int posixly_correct)570 static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct)
571 {
572     d->__first_nonopt = d->__last_nonopt = d->optind;
573     d->__nextchar = NULL;
574     d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT");
575     if (optstring[0] == L'-')
576     {
577         d->__ordering = RETURN_IN_ORDER;
578         ++optstring;
579     }
580     else if (optstring[0] == L'+')
581     {
582         d->__ordering = REQUIRE_ORDER;
583         ++optstring;
584     }
585     else if (d->__posixly_correct)
586         d->__ordering = REQUIRE_ORDER;
587     else
588         d->__ordering = PERMUTE;
589     return optstring;
590 }
_getopt_internal_r_w(int argc,wchar_t * const * argv,const wchar_t * optstring,const struct option_w * longopts,int * longind,int long_only,struct _getopt_data_w * d,int posixly_correct)591 int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct)
592 {
593     int print_errors = d->opterr;
594     if (argc < 1)
595         return -1;
596     d->optarg = NULL;
597     if (d->optind == 0 || !d->__initialized)
598     {
599         if (d->optind == 0)
600             d->optind = 1;
601         optstring = _getopt_initialize_w (optstring, d, posixly_correct);
602         d->__initialized = 1;
603     }
604     else if (optstring[0] == L'-' || optstring[0] == L'+')
605         optstring++;
606     if (optstring[0] == L':')
607         print_errors = 0;
608     if (d->__nextchar == NULL || *d->__nextchar == L'\0')
609     {
610         if (d->__last_nonopt > d->optind)
611             d->__last_nonopt = d->optind;
612         if (d->__first_nonopt > d->optind)
613             d->__first_nonopt = d->optind;
614         if (d->__ordering == PERMUTE)
615         {
616             if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
617                 exchange_w((wchar_t **) argv, d);
618             else if (d->__last_nonopt != d->optind)
619                 d->__first_nonopt = d->optind;
620             while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
621                 d->optind++;
622             d->__last_nonopt = d->optind;
623         }
624         if (d->optind != argc && !wcscmp(argv[d->optind], L"--"))
625         {
626             d->optind++;
627             if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
628                 exchange_w((wchar_t **) argv, d);
629             else if (d->__first_nonopt == d->__last_nonopt)
630                 d->__first_nonopt = d->optind;
631             d->__last_nonopt = argc;
632             d->optind = argc;
633         }
634         if (d->optind == argc)
635         {
636             if (d->__first_nonopt != d->__last_nonopt)
637                 d->optind = d->__first_nonopt;
638             return -1;
639         }
640         if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
641         {
642             if (d->__ordering == REQUIRE_ORDER)
643                 return -1;
644             d->optarg = argv[d->optind++];
645             return 1;
646         }
647         d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-'));
648     }
649     if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1])))))
650     {
651         wchar_t *nameend;
652         unsigned int namelen;
653         const struct option_w *p;
654         const struct option_w *pfound = NULL;
655         struct option_list
656         {
657             const struct option_w *p;
658             struct option_list *next;
659         } *ambig_list = NULL;
660         int exact = 0;
661         int indfound = -1;
662         int option_index;
663         for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++);
664         namelen = (unsigned int)(nameend - d->__nextchar);
665         for (p = longopts, option_index = 0; p->name; p++, option_index++)
666             if (!wcsncmp(p->name, d->__nextchar, namelen))
667             {
668                 if (namelen == (unsigned int)wcslen(p->name))
669                 {
670                     pfound = p;
671                     indfound = option_index;
672                     exact = 1;
673                     break;
674                 }
675                 else if (pfound == NULL)
676                 {
677                     pfound = p;
678                     indfound = option_index;
679                 }
680                 else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
681                 {
682                     struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
683                     newp->p = p;
684                     newp->next = ambig_list;
685                     ambig_list = newp;
686                 }
687             }
688             if (ambig_list != NULL && !exact)
689             {
690                 if (print_errors)
691                 {
692                     struct option_list first;
693                     first.p = pfound;
694                     first.next = ambig_list;
695                     ambig_list = &first;
696                     fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
697                     do
698                     {
699                         fwprintf (stderr, L" '--%s'", ambig_list->p->name);
700                         ambig_list = ambig_list->next;
701                     }
702                     while (ambig_list != NULL);
703                     fputwc (L'\n', stderr);
704                 }
705                 d->__nextchar += wcslen(d->__nextchar);
706                 d->optind++;
707                 d->optopt = 0;
708                 return L'?';
709             }
710             if (pfound != NULL)
711             {
712                 option_index = indfound;
713                 d->optind++;
714                 if (*nameend)
715                 {
716                     if (pfound->has_arg)
717                         d->optarg = nameend + 1;
718                     else
719                     {
720                         if (print_errors)
721                         {
722                             if (argv[d->optind - 1][1] == L'-')
723                             {
724                                 fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
725                             }
726                             else
727                             {
728                                 fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
729                             }
730                         }
731                         d->__nextchar += wcslen(d->__nextchar);
732                         d->optopt = pfound->val;
733                         return L'?';
734                     }
735                 }
736                 else if (pfound->has_arg == 1)
737                 {
738                     if (d->optind < argc)
739                         d->optarg = argv[d->optind++];
740                     else
741                     {
742                         if (print_errors)
743                         {
744                             fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
745                         }
746                         d->__nextchar += wcslen(d->__nextchar);
747                         d->optopt = pfound->val;
748                         return optstring[0] == L':' ? L':' : L'?';
749                     }
750                 }
751                 d->__nextchar += wcslen(d->__nextchar);
752                 if (longind != NULL)
753                     *longind = option_index;
754                 if (pfound->flag)
755                 {
756                     *(pfound->flag) = pfound->val;
757                     return 0;
758                 }
759                 return pfound->val;
760             }
761             if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL)
762             {
763                 if (print_errors)
764                 {
765                     if (argv[d->optind][1] == L'-')
766                     {
767                         fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
768                     }
769                     else
770                     {
771                         fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
772                     }
773                 }
774                 d->__nextchar = (wchar_t *)L"";
775                 d->optind++;
776                 d->optopt = 0;
777                 return L'?';
778             }
779     }
780     {
781         wchar_t c = *d->__nextchar++;
782         wchar_t *temp = (wchar_t*)wcschr(optstring, c);
783         if (*d->__nextchar == L'\0')
784             ++d->optind;
785         if (temp == NULL || c == L':' || c == L';')
786         {
787             if (print_errors)
788             {
789                 fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c);
790             }
791             d->optopt = c;
792             return L'?';
793         }
794         if (temp[0] == L'W' && temp[1] == L';')
795         {
796             wchar_t *nameend;
797             const struct option_w *p;
798             const struct option_w *pfound = NULL;
799             int exact = 0;
800             int ambig = 0;
801             int indfound = 0;
802             int option_index;
803             if (longopts == NULL)
804                 goto no_longs;
805             if (*d->__nextchar != L'\0')
806             {
807                 d->optarg = d->__nextchar;
808                 d->optind++;
809             }
810             else if (d->optind == argc)
811             {
812                 if (print_errors)
813                 {
814                     fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
815                 }
816                 d->optopt = c;
817                 if (optstring[0] == L':')
818                     c = L':';
819                 else
820                     c = L'?';
821                 return c;
822             }
823             else
824                 d->optarg = argv[d->optind++];
825             for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++);
826             for (p = longopts, option_index = 0; p->name; p++, option_index++)
827                 if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
828                 {
829                     if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name))
830                     {
831                         pfound = p;
832                         indfound = option_index;
833                         exact = 1;
834                         break;
835                     }
836                     else if (pfound == NULL)
837                     {
838                         pfound = p;
839                         indfound = option_index;
840                     }
841                     else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
842                         ambig = 1;
843                 }
844                 if (ambig && !exact)
845                 {
846                     if (print_errors)
847                     {
848                         fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
849                     }
850                     d->__nextchar += wcslen(d->__nextchar);
851                     d->optind++;
852                     return L'?';
853                 }
854                 if (pfound != NULL)
855                 {
856                     option_index = indfound;
857                     if (*nameend)
858                     {
859                         if (pfound->has_arg)
860                             d->optarg = nameend + 1;
861                         else
862                         {
863                             if (print_errors)
864                             {
865                                 fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
866                             }
867                             d->__nextchar += wcslen(d->__nextchar);
868                             return L'?';
869                         }
870                     }
871                     else if (pfound->has_arg == 1)
872                     {
873                         if (d->optind < argc)
874                             d->optarg = argv[d->optind++];
875                         else
876                         {
877                             if (print_errors)
878                             {
879                                 fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
880                             }
881                             d->__nextchar += wcslen(d->__nextchar);
882                             return optstring[0] == L':' ? L':' : L'?';
883                         }
884                     }
885                     else
886                         d->optarg = NULL;
887                     d->__nextchar += wcslen(d->__nextchar);
888                     if (longind != NULL)
889                         *longind = option_index;
890                     if (pfound->flag)
891                     {
892                         *(pfound->flag) = pfound->val;
893                         return 0;
894                     }
895                     return pfound->val;
896                 }
897 no_longs:
898                 d->__nextchar = NULL;
899                 return L'W';
900         }
901         if (temp[1] == L':')
902         {
903             if (temp[2] == L':')
904             {
905                 if (*d->__nextchar != L'\0')
906                 {
907                     d->optarg = d->__nextchar;
908                     d->optind++;
909                 }
910                 else
911                     d->optarg = NULL;
912                 d->__nextchar = NULL;
913             }
914             else
915             {
916                 if (*d->__nextchar != L'\0')
917                 {
918                     d->optarg = d->__nextchar;
919                     d->optind++;
920                 }
921                 else if (d->optind == argc)
922                 {
923                     if (print_errors)
924                     {
925                         fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
926                     }
927                     d->optopt = c;
928                     if (optstring[0] == L':')
929                         c = L':';
930                     else
931                         c = L'?';
932                 }
933                 else
934                     d->optarg = argv[d->optind++];
935                 d->__nextchar = NULL;
936             }
937         }
938         return c;
939     }
940 }
_getopt_internal_w(int argc,wchar_t * const * argv,const wchar_t * optstring,const struct option_w * longopts,int * longind,int long_only,int posixly_correct)941 int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct)
942 {
943     int result;
944     getopt_data_w.optind = optind;
945     getopt_data_w.opterr = opterr;
946     result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct);
947     optind = getopt_data_w.optind;
948     optarg_w = getopt_data_w.optarg;
949     optopt = getopt_data_w.optopt;
950     return result;
951 }
getopt_w(int argc,wchar_t * const * argv,const wchar_t * optstring)952 int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW
953 {
954     return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0);
955 }
getopt_long_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index)956 int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
957 {
958     return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0);
959 }
getopt_long_only_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index)960 int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
961 {
962     return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0);
963 }
_getopt_long_r_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index,struct _getopt_data_w * d)964 int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
965 {
966     return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0);
967 }
_getopt_long_only_r_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index,struct _getopt_data_w * d)968 int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
969 {
970     return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0);
971 }