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