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