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 }