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
7 Date: 02/03/2011 - Ludvik Jerabek - Initial Release
8 Version: 1.0
9 Comment: Supports getopt, getopt_long, and getopt_long_only
10 and POSIXLY_CORRECT environment flag
11 License: LGPL
12
13 Revisions:
14
15 02/03/2011 - Ludvik Jerabek - Initial Release
16 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
17 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
18 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
19 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
20 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
21 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
22 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
23 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
24
25 **DISCLAIMER**
26 THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
27 EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
28 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
29 PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
30 EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
31 APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
32 DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
33 USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
34 PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
35 YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
36 EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37 */
38 #define _CRT_SECURE_NO_WARNINGS
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <malloc.h>
42 #include "getopt.h"
43
44 #ifdef __cplusplus
45 #define _GETOPT_THROW throw()
46 #else
47 #define _GETOPT_THROW
48 #endif
49
50 int optind = 1;
51 int opterr = 1;
52 int optopt = '?';
53 enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
54
55 //
56 //
57 // Ansi structures and functions follow
58 //
59 //
60
61 static struct _getopt_data_a
62 {
63 int optind;
64 int opterr;
65 int optopt;
66 char *optarg;
67 int __initialized;
68 char *__nextchar;
69 enum ENUM_ORDERING __ordering;
70 int __posixly_correct;
71 int __first_nonopt;
72 int __last_nonopt;
73 } getopt_data_a;
74 char *optarg_a;
75
exchange_a(char ** argv,struct _getopt_data_a * d)76 static void exchange_a(char **argv, struct _getopt_data_a *d)
77 {
78 int bottom = d->__first_nonopt;
79 int middle = d->__last_nonopt;
80 int top = d->optind;
81 char *tem;
82 while (top > middle && middle > bottom)
83 {
84 if (top - middle > middle - bottom)
85 {
86 int len = middle - bottom;
87 for (int i = 0; i < len; i++)
88 {
89 tem = argv[bottom + i];
90 argv[bottom + i] = argv[top - (middle - bottom) + i];
91 argv[top - (middle - bottom) + i] = tem;
92 }
93 top -= len;
94 }
95 else
96 {
97 int len = top - middle;
98 for (int 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 for (int i = 0; i < len; i++)
546 {
547 tem = argv[bottom + i];
548 argv[bottom + i] = argv[top - (middle - bottom) + i];
549 argv[top - (middle - bottom) + i] = tem;
550 }
551 top -= len;
552 }
553 else
554 {
555 int len = top - middle;
556 for (int i = 0; i < len; i++)
557 {
558 tem = argv[bottom + i];
559 argv[bottom + i] = argv[middle + i];
560 argv[middle + i] = tem;
561 }
562 bottom += len;
563 }
564 }
565 d->__first_nonopt += (d->optind - d->__last_nonopt);
566 d->__last_nonopt = d->optind;
567 }
_getopt_initialize_w(const wchar_t * optstring,struct _getopt_data_w * d,int posixly_correct)568 static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct)
569 {
570 d->__first_nonopt = d->__last_nonopt = d->optind;
571 d->__nextchar = NULL;
572 d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT");
573 if (optstring[0] == L'-')
574 {
575 d->__ordering = RETURN_IN_ORDER;
576 ++optstring;
577 }
578 else if (optstring[0] == L'+')
579 {
580 d->__ordering = REQUIRE_ORDER;
581 ++optstring;
582 }
583 else if (d->__posixly_correct)
584 d->__ordering = REQUIRE_ORDER;
585 else
586 d->__ordering = PERMUTE;
587 return optstring;
588 }
_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)589 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)
590 {
591 int print_errors = d->opterr;
592 if (argc < 1)
593 return -1;
594 d->optarg = NULL;
595 if (d->optind == 0 || !d->__initialized)
596 {
597 if (d->optind == 0)
598 d->optind = 1;
599 optstring = _getopt_initialize_w (optstring, d, posixly_correct);
600 d->__initialized = 1;
601 }
602 else if (optstring[0] == L'-' || optstring[0] == L'+')
603 optstring++;
604 if (optstring[0] == L':')
605 print_errors = 0;
606 if (d->__nextchar == NULL || *d->__nextchar == L'\0')
607 {
608 if (d->__last_nonopt > d->optind)
609 d->__last_nonopt = d->optind;
610 if (d->__first_nonopt > d->optind)
611 d->__first_nonopt = d->optind;
612 if (d->__ordering == PERMUTE)
613 {
614 if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
615 exchange_w((wchar_t **) argv, d);
616 else if (d->__last_nonopt != d->optind)
617 d->__first_nonopt = d->optind;
618 while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
619 d->optind++;
620 d->__last_nonopt = d->optind;
621 }
622 if (d->optind != argc && !wcscmp(argv[d->optind], L"--"))
623 {
624 d->optind++;
625 if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
626 exchange_w((wchar_t **) argv, d);
627 else if (d->__first_nonopt == d->__last_nonopt)
628 d->__first_nonopt = d->optind;
629 d->__last_nonopt = argc;
630 d->optind = argc;
631 }
632 if (d->optind == argc)
633 {
634 if (d->__first_nonopt != d->__last_nonopt)
635 d->optind = d->__first_nonopt;
636 return -1;
637 }
638 if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
639 {
640 if (d->__ordering == REQUIRE_ORDER)
641 return -1;
642 d->optarg = argv[d->optind++];
643 return 1;
644 }
645 d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-'));
646 }
647 if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1])))))
648 {
649 wchar_t *nameend;
650 unsigned int namelen;
651 const struct option_w *p;
652 const struct option_w *pfound = NULL;
653 struct option_list
654 {
655 const struct option_w *p;
656 struct option_list *next;
657 } *ambig_list = NULL;
658 int exact = 0;
659 int indfound = -1;
660 int option_index;
661 for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++);
662 namelen = (unsigned int)(nameend - d->__nextchar);
663 for (p = longopts, option_index = 0; p->name; p++, option_index++)
664 if (!wcsncmp(p->name, d->__nextchar, namelen))
665 {
666 if (namelen == (unsigned int)wcslen(p->name))
667 {
668 pfound = p;
669 indfound = option_index;
670 exact = 1;
671 break;
672 }
673 else if (pfound == NULL)
674 {
675 pfound = p;
676 indfound = option_index;
677 }
678 else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
679 {
680 struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
681 newp->p = p;
682 newp->next = ambig_list;
683 ambig_list = newp;
684 }
685 }
686 if (ambig_list != NULL && !exact)
687 {
688 if (print_errors)
689 {
690 struct option_list first;
691 first.p = pfound;
692 first.next = ambig_list;
693 ambig_list = &first;
694 fwprintf(stderr, L"%ls: option '%ls' is ambiguous; possibilities:", argv[0], argv[d->optind]);
695 do
696 {
697 fwprintf (stderr, L" '--%ls'", ambig_list->p->name);
698 ambig_list = ambig_list->next;
699 }
700 while (ambig_list != NULL);
701 fputwc (L'\n', stderr);
702 }
703 d->__nextchar += wcslen(d->__nextchar);
704 d->optind++;
705 d->optopt = 0;
706 return L'?';
707 }
708 if (pfound != NULL)
709 {
710 option_index = indfound;
711 d->optind++;
712 if (*nameend)
713 {
714 if (pfound->has_arg)
715 d->optarg = nameend + 1;
716 else
717 {
718 if (print_errors)
719 {
720 if (argv[d->optind - 1][1] == L'-')
721 {
722 fwprintf(stderr, L"%ls: option '--%ls' doesn't allow an argument\n",argv[0], pfound->name);
723 }
724 else
725 {
726 fwprintf(stderr, L"%ls: option '%c%ls' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
727 }
728 }
729 d->__nextchar += wcslen(d->__nextchar);
730 d->optopt = pfound->val;
731 return L'?';
732 }
733 }
734 else if (pfound->has_arg == 1)
735 {
736 if (d->optind < argc)
737 d->optarg = argv[d->optind++];
738 else
739 {
740 if (print_errors)
741 {
742 fwprintf(stderr,L"%ls: option '--%ls' requires an argument\n",argv[0], pfound->name);
743 }
744 d->__nextchar += wcslen(d->__nextchar);
745 d->optopt = pfound->val;
746 return optstring[0] == L':' ? L':' : L'?';
747 }
748 }
749 d->__nextchar += wcslen(d->__nextchar);
750 if (longind != NULL)
751 *longind = option_index;
752 if (pfound->flag)
753 {
754 *(pfound->flag) = pfound->val;
755 return 0;
756 }
757 return pfound->val;
758 }
759 if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL)
760 {
761 if (print_errors)
762 {
763 if (argv[d->optind][1] == L'-')
764 {
765 fwprintf(stderr, L"%ls: unrecognized option '--%ls'\n",argv[0], d->__nextchar);
766 }
767 else
768 {
769 fwprintf(stderr, L"%ls: unrecognized option '%c%ls'\n",argv[0], argv[d->optind][0], d->__nextchar);
770 }
771 }
772 d->__nextchar = (wchar_t *)L"";
773 d->optind++;
774 d->optopt = 0;
775 return L'?';
776 }
777 }
778 {
779 wchar_t c = *d->__nextchar++;
780 wchar_t *temp = (wchar_t*)wcschr(optstring, c);
781 if (*d->__nextchar == L'\0')
782 ++d->optind;
783 if (temp == NULL || c == L':' || c == L';')
784 {
785 if (print_errors)
786 {
787 fwprintf(stderr, L"%ls: invalid option -- '%c'\n", argv[0], c);
788 }
789 d->optopt = c;
790 return L'?';
791 }
792 if (temp[0] == L'W' && temp[1] == L';')
793 {
794 wchar_t *nameend;
795 const struct option_w *p;
796 const struct option_w *pfound = NULL;
797 int exact = 0;
798 int ambig = 0;
799 int indfound = 0;
800 int option_index;
801 if (longopts == NULL)
802 goto no_longs;
803 if (*d->__nextchar != L'\0')
804 {
805 d->optarg = d->__nextchar;
806 d->optind++;
807 }
808 else if (d->optind == argc)
809 {
810 if (print_errors)
811 {
812 fwprintf(stderr,L"%ls: option requires an argument -- '%c'\n",argv[0], c);
813 }
814 d->optopt = c;
815 if (optstring[0] == L':')
816 c = L':';
817 else
818 c = L'?';
819 return c;
820 }
821 else
822 d->optarg = argv[d->optind++];
823 for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++);
824 for (p = longopts, option_index = 0; p->name; p++, option_index++)
825 if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
826 {
827 if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name))
828 {
829 pfound = p;
830 indfound = option_index;
831 exact = 1;
832 break;
833 }
834 else if (pfound == NULL)
835 {
836 pfound = p;
837 indfound = option_index;
838 }
839 else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
840 ambig = 1;
841 }
842 if (ambig && !exact)
843 {
844 if (print_errors)
845 {
846 fwprintf(stderr, L"%ls: option '-W %ls' is ambiguous\n",argv[0], d->optarg);
847 }
848 d->__nextchar += wcslen(d->__nextchar);
849 d->optind++;
850 return L'?';
851 }
852 if (pfound != NULL)
853 {
854 option_index = indfound;
855 if (*nameend)
856 {
857 if (pfound->has_arg)
858 d->optarg = nameend + 1;
859 else
860 {
861 if (print_errors)
862 {
863 fwprintf(stderr, L"%ls: option '-W %ls' doesn't allow an argument\n",argv[0], pfound->name);
864 }
865 d->__nextchar += wcslen(d->__nextchar);
866 return L'?';
867 }
868 }
869 else if (pfound->has_arg == 1)
870 {
871 if (d->optind < argc)
872 d->optarg = argv[d->optind++];
873 else
874 {
875 if (print_errors)
876 {
877 fwprintf(stderr, L"%ls: option '-W %ls' requires an argument\n",argv[0], pfound->name);
878 }
879 d->__nextchar += wcslen(d->__nextchar);
880 return optstring[0] == L':' ? L':' : L'?';
881 }
882 }
883 else
884 d->optarg = NULL;
885 d->__nextchar += wcslen(d->__nextchar);
886 if (longind != NULL)
887 *longind = option_index;
888 if (pfound->flag)
889 {
890 *(pfound->flag) = pfound->val;
891 return 0;
892 }
893 return pfound->val;
894 }
895 no_longs:
896 d->__nextchar = NULL;
897 return L'W';
898 }
899 if (temp[1] == L':')
900 {
901 if (temp[2] == L':')
902 {
903 if (*d->__nextchar != L'\0')
904 {
905 d->optarg = d->__nextchar;
906 d->optind++;
907 }
908 else
909 d->optarg = NULL;
910 d->__nextchar = NULL;
911 }
912 else
913 {
914 if (*d->__nextchar != L'\0')
915 {
916 d->optarg = d->__nextchar;
917 d->optind++;
918 }
919 else if (d->optind == argc)
920 {
921 if (print_errors)
922 {
923 fwprintf(stderr,L"%ls: option requires an argument -- '%c'\n",argv[0], c);
924 }
925 d->optopt = c;
926 if (optstring[0] == L':')
927 c = L':';
928 else
929 c = L'?';
930 }
931 else
932 d->optarg = argv[d->optind++];
933 d->__nextchar = NULL;
934 }
935 }
936 return c;
937 }
938 }
_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)939 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)
940 {
941 int result;
942 getopt_data_w.optind = optind;
943 getopt_data_w.opterr = opterr;
944 result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct);
945 optind = getopt_data_w.optind;
946 optarg_w = getopt_data_w.optarg;
947 optopt = getopt_data_w.optopt;
948 return result;
949 }
getopt_w(int argc,wchar_t * const * argv,const wchar_t * optstring)950 int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW
951 {
952 return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0);
953 }
getopt_long_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index)954 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
955 {
956 return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0);
957 }
getopt_long_only_w(int argc,wchar_t * const * argv,const wchar_t * options,const struct option_w * long_options,int * opt_index)958 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
959 {
960 return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0);
961 }
_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)962 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)
963 {
964 return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0);
965 }
_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)966 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)
967 {
968 return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0);
969 }
970