Windows 命令行解析工具(getopt)

  忘记了上次在哪里找到这个功能库,只有一个 .h 和 .c 文件,再次搜索的时候发现找不到了,结果只能在之前的代码中,两个文件提出使用,顾将这两个文件备份在这里。

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