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