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