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 }