在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数 解析命令行

在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数 解析命令行

修改自 glibc 2.8 中的 getopt 等相关文件,直接加入工程,编译即可使用。
不知道有没有版权问题。
没有经过非常严格的测试。

getopt.h
  1/**//*
  2getopt.h
  3
  4Copyright (C) 2012, coreBugZJ, all rights reserved.
  5
  6在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数。
  7
  8修改自 glibc 2.8 中 getopt.h 文件,
  9*/

 10
 11
 12
 13
 14/**//* Declarations for getopt.
 15   Copyright (C) 1989-1994,1996-1999,2001,2003,2004
 16   Free Software Foundation, Inc.
 17   This file is part of the GNU C Library.
 18
 19   The GNU C Library is free software; you can redistribute it and/or
 20   modify it under the terms of the GNU Lesser General Public
 21   License as published by the Free Software Foundation; either
 22   version 2.1 of the License, or (at your option) any later version.
 23
 24   The GNU C Library is distributed in the hope that it will be useful,
 25   but WITHOUT ANY WARRANTY; without even the implied warranty of
 26   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 27   Lesser General Public License for more details.
 28
 29   You should have received a copy of the GNU Lesser General Public
 30   License along with the GNU C Library; if not, write to the Free
 31   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 32   02111-1307 USA.  */

 33
 34#ifndef _GETOPT_H
 35#define _GETOPT_H 1
 36
 37/**//* If __GNU_LIBRARY__ is not already defined, either we are being used
 38   standalone, or this is the first header included in the source file.
 39   If we are being used with glibc, we need to include <features.h>, but
 40   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
 41   not defined, include <ctype.h>, which will pull in <features.h> for us
 42   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
 43   doesn't flood the namespace with stuff the way some other headers do.)  */

 44#include <ctype.h>
 45
 46
 47#ifdef    __cplusplus
 48extern "C" {
 49#endif
 50
 51/**//* For communication from `getopt' to the caller.
 52   When `getopt' finds an option that takes an argument,
 53   the argument value is returned here.
 54   Also, when `ordering' is RETURN_IN_ORDER,
 55   each non-option ARGV-element is returned here.  */

 56
 57extern char *optarg;
 58
 59/**//* Index in ARGV of the next element to be scanned.
 60   This is used for communication to and from the caller
 61   and for communication between successive calls to `getopt'.
 62
 63   On entry to `getopt', zero means this is the first call; initialize.
 64
 65   When `getopt' returns -1, this is the index of the first of the
 66   non-option elements that the caller should itself scan.
 67
 68   Otherwise, `optind' communicates from one call to the next
 69   how much of ARGV has been scanned so far.  */

 70
 71extern int optind;
 72
 73/**//* Callers store zero here to inhibit the error message `getopt' prints
 74   for unrecognized options.  */

 75
 76extern int opterr;
 77
 78/**//* Set to an option character which was unrecognized.  */
 79
 80extern int optopt;
 81
 82/**//* Describe the long-named options requested by the application.
 83   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
 84   of `struct option' terminated by an element containing a name which is
 85   zero.
 86
 87   The field `has_arg' is:
 88   no_argument        (or 0) if the option does not take an argument,
 89   required_argument    (or 1) if the option requires an argument,
 90   optional_argument     (or 2) if the option takes an optional argument.
 91
 92   If the field `flag' is not NULL, it points to a variable that is set
 93   to the value given in the field `val' when the option is found, but
 94   left unchanged if the option is not found.
 95
 96   To have a long-named option do something other than set an `int' to
 97   a compiled-in constant, such as set a value from `optarg', set the
 98   option's `flag' field to zero and its `val' field to a nonzero
 99   value (the equivalent single-letter option character, if there is
100   one).  For long options that have a zero `flag' field, `getopt'
101   returns the contents of the `val' field.  */

102
103struct option
104{
105  const char *name;
106  /**//* has_arg can't be an enum because some compilers complain about
107     type mismatches in all the code that assumes it is an int.  */

108  int has_arg;
109  int *flag;
110  int val;
111}
;
112
113/**//* Names for the values of the `has_arg' field of `struct option'.  */
114
115#define no_argument        0
116#define required_argument    1
117#define optional_argument    2
118
119
120/**//* Get definitions and prototypes for functions to process the
121   arguments in ARGV (ARGC of them, minus the program name) for
122   options given in OPTS.
123
124   Return the option character from OPTS just read.  Return -1 when
125   there are no more options.  For unrecognized options, or options
126   missing arguments, `optopt' is set to the option letter, and '?' is
127   returned.
128
129   The OPTS string is a list of characters which are recognized option
130   letters, optionally followed by colons, specifying that that letter
131   takes an argument, to be placed in `optarg'.
132
133   If a letter in OPTS is followed by two colons, its argument is
134   optional.  This behavior is specific to the GNU `getopt'.
135
136   The argument `--' causes premature termination of argument
137   scanning, explicitly telling `getopt' that there are no more
138   options.
139
140   If OPTS begins with `--', then non-option arguments are treated as
141   arguments to the option '\0'.  This behavior is specific to the GNU
142   `getopt'.  */

143
144/**//* Many other libraries have conflicting prototypes for getopt, with
145   differences in the consts, in stdlib.h.  To avoid compilation
146   errors, only prototype getopt for the GNU C library.  */

147extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
148
149extern int getopt_long (int ___argc, char *const *___argv,
150            const char *__shortopts,
151                const struct option *__longopts, int *__longind);
152
153extern int getopt_long_only (int ___argc, char *const *___argv,
154                 const char *__shortopts,
155                     const struct option *__longopts, int *__longind);
156
157
158#ifdef    __cplusplus
159}

160#endif
161
162
163#endif /* getopt.h */
164


getopt_int.h
  1/**//*
  2getopt_int.h
  3
  4Copyright (C) 2012, coreBugZJ, all rights reserved.
  5
  6在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数。
  7
  8修改自 glibc 2.8 中 getopt_int.h 文件,
  9*/

 10
 11
 12
 13
 14
 15/**//* Internal declarations for getopt.
 16   Copyright (C) 1989-1994,1996-1999,2001,2003,2004
 17   Free Software Foundation, Inc.
 18   This file is part of the GNU C Library.
 19
 20   The GNU C Library is free software; you can redistribute it and/or
 21   modify it under the terms of the GNU Lesser General Public
 22   License as published by the Free Software Foundation; either
 23   version 2.1 of the License, or (at your option) any later version.
 24
 25   The GNU C Library is distributed in the hope that it will be useful,
 26   but WITHOUT ANY WARRANTY; without even the implied warranty of
 27   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 28   Lesser General Public License for more details.
 29
 30   You should have received a copy of the GNU Lesser General Public
 31   License along with the GNU C Library; if not, write to the Free
 32   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 33   02111-1307 USA.  */

 34
 35#ifndef _GETOPT_INT_H
 36#define _GETOPT_INT_H    1
 37
 38extern int _getopt_internal (int ___argc, char *const *___argv,
 39                 const char *__shortopts,
 40                     const struct option *__longopts, int *__longind,
 41                 int __long_only);
 42
 43
 44/**//* Reentrant versions which can handle parsing multiple argument
 45   vectors at the same time.  */

 46
 47/**//* Data type for reentrant functions.  */
 48struct _getopt_data
 49{
 50  /**//* These have exactly the same meaning as the corresponding global
 51     variables, except that they are used for the reentrant
 52     versions of getopt.  */

 53  int optind;
 54  int opterr;
 55  int optopt;
 56  char *optarg;
 57
 58  /**//* Internal members.  */
 59
 60  /**//* True if the internal members have been initialized.  */
 61  int __initialized;
 62
 63  /**//* The next char to be scanned in the option-element
 64     in which the last option character we returned was found.
 65     This allows us to pick up the scan where we left off.
 66
 67     If this is zero, or a null string, it means resume the scan
 68     by advancing to the next ARGV-element.  */

 69  char *__nextchar;
 70
 71  /**//* Describe how to deal with options that follow non-option ARGV-elements.
 72
 73     If the caller did not specify anything,
 74     the default is REQUIRE_ORDER if the environment variable
 75     POSIXLY_CORRECT is defined, PERMUTE otherwise.
 76
 77     REQUIRE_ORDER means don't recognize them as options;
 78     stop option processing when the first non-option is seen.
 79     This is what Unix does.
 80     This mode of operation is selected by either setting the environment
 81     variable POSIXLY_CORRECT, or using `+' as the first character
 82     of the list of option characters.
 83
 84     PERMUTE is the default.  We permute the contents of ARGV as we
 85     scan, so that eventually all the non-options are at the end.
 86     This allows options to be given in any order, even with programs
 87     that were not written to expect this.
 88
 89     RETURN_IN_ORDER is an option available to programs that were
 90     written to expect options and other ARGV-elements in any order
 91     and that care about the ordering of the two.  We describe each
 92     non-option ARGV-element as if it were the argument of an option
 93     with character code 1.  Using `-' as the first character of the
 94     list of option characters selects this mode of operation.
 95
 96     The special argument `--' forces an end of option-scanning regardless
 97     of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
 98     `--' can cause `getopt' to return -1 with `optind' != ARGC.  */

 99
100  enum
101    {
102      REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
103    }
 __ordering;
104
105  /**//* If the POSIXLY_CORRECT environment variable is set.  */
106  int __posixly_correct;
107
108
109  /**//* Handle permutation of arguments.  */
110
111  /**//* Describe the part of ARGV that contains non-options that have
112     been skipped.  `first_nonopt' is the index in ARGV of the first
113     of them; `last_nonopt' is the index after the last of them.  */

114
115  int __first_nonopt;
116  int __last_nonopt;
117}
;
118
119/**//* The initializer is necessary to set OPTIND and OPTERR to their
120   default values and to clear the initialization flag.  */

121#define _GETOPT_DATA_INITIALIZER    { 1, 1 }
122
123extern int _getopt_internal_r (int ___argc, char *const *___argv,
124                   const char *__shortopts,
125                   const struct option *__longopts, int *__longind,
126                   int __long_only, struct _getopt_data *__data);
127
128extern int _getopt_long_r (int ___argc, char *const *___argv,
129               const char *__shortopts,
130               const struct option *__longopts, int *__longind,
131               struct _getopt_data *__data);
132
133extern int _getopt_long_only_r (int ___argc, char *const *___argv,
134                const char *__shortopts,
135                const struct option *__longopts,
136                int *__longind,
137                struct _getopt_data *__data);
138
139#endif /* getopt_int.h */
140



getopt.c
  1/**//*
  2getopt.c
  3
  4Copyright (C) 2012, coreBugZJ, all rights reserved.
  5
  6在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数。
  7
  8修改自 glibc 2.8 中 getopt.c 文件,
  9*/

 10
 11
 12
 13
 14/**//* Getopt for GNU.
 15   NOTE: getopt is part of the C library, so if you don't know what
 16   "Keep this file name-space clean" means, talk to [email protected]
 17   before changing it!
 18   Copyright (C) 1987-1996,1998-2004,2008 Free Software Foundation, Inc.
 19   This file is part of the GNU C Library.
 20
 21   The GNU C Library is free software; you can redistribute it and/or
 22   modify it under the terms of the GNU Lesser General Public
 23   License as published by the Free Software Foundation; either
 24   version 2.1 of the License, or (at your option) any later version.
 25
 26   The GNU C Library is distributed in the hope that it will be useful,
 27   but WITHOUT ANY WARRANTY; without even the implied warranty of
 28   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 29   Lesser General Public License for more details.
 30
 31   You should have received a copy of the GNU Lesser General Public
 32   License along with the GNU C Library; if not, write to the Free
 33   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 34   02111-1307 USA.  */

 35
 36#include <stdio.h>
 37
 38/**//* Comment out all this code if we are using the GNU C Library, and are not
 39   actually compiling the library itself.  This code is part of the GNU C
 40   Library, but also included in many other GNU distributions.  Compiling
 41   and linking in this code is a waste when using the GNU C library
 42   (especially if it is a shared library).  Rather than having every GNU
 43   program understand `configure --with-gnu-libc' and omit the object files,
 44   it is simpler to just do this in the source for each such file.  */

 45
 46
 47#include <string.h>
 48
 49#define _(msgid) (msgid)
 50
 51
 52#ifndef attribute_hidden
 53# define attribute_hidden
 54#endif
 55
 56/**//* This version of `getopt' appears to the caller like standard Unix `getopt'
 57   but it behaves differently for the user, since it allows the user
 58   to intersperse the options with the other arguments.
 59
 60   As `getopt' works, it permutes the elements of ARGV so that,
 61   when it is done, all the options precede everything else.  Thus
 62   all application programs are extended to handle flexible argument order.
 63
 64   Setting the environment variable POSIXLY_CORRECT disables permutation.
 65   Then the behavior is completely standard.
 66
 67   GNU application programs can use a third alternative mode in which
 68   they can distinguish the relative order of options and other arguments.  */

 69
 70#include "getopt.h"
 71#include "getopt_int.h"
 72
 73/**//* For communication from `getopt' to the caller.
 74   When `getopt' finds an option that takes an argument,
 75   the argument value is returned here.
 76   Also, when `ordering' is RETURN_IN_ORDER,
 77   each non-option ARGV-element is returned here.  */

 78
 79char *optarg;
 80
 81/**//* Index in ARGV of the next element to be scanned.
 82   This is used for communication to and from the caller
 83   and for communication between successive calls to `getopt'.
 84
 85   On entry to `getopt', zero means this is the first call; initialize.
 86
 87   When `getopt' returns -1, this is the index of the first of the
 88   non-option elements that the caller should itself scan.
 89
 90   Otherwise, `optind' communicates from one call to the next
 91   how much of ARGV has been scanned so far.  */

 92
 93/**//* 1003.2 says this must be 1 before any call.  */
 94int optind = 1;
 95
 96/**//* Callers store zero here to inhibit the error message
 97   for unrecognized options.  */

 98
 99int opterr = 1;
100
101/**//* Set to an option character which was unrecognized.
102   This must be initialized on some systems to avoid linking in the
103   system's own getopt implementation.  */

104
105int optopt = '?';
106
107/**//* Keep a global copy of all internal members of getopt_data.  */
108
109static struct _getopt_data getopt_data;
110
111
112#ifndef getenv
113extern char *getenv ();
114#endif
115
116
117# define SWAP_FLAGS(ch1, ch2)
118
119/**//* Exchange two adjacent subsequences of ARGV.
120   One subsequence is elements [first_nonopt,last_nonopt)
121   which contains all the non-options that have been skipped so far.
122   The other is elements [last_nonopt,optind), which contains all
123   the options processed since those non-options were skipped.
124
125   `first_nonopt' and `last_nonopt' are relocated so that they describe
126   the new indices of the non-options in ARGV after they are moved.  */

127
128static void
129exchange (char **argv, struct _getopt_data *d)
130{
131  int bottom = d->__first_nonopt;
132  int middle = d->__last_nonopt;
133  int top = d->optind;
134  char *tem;
135
136  /**//* Exchange the shorter segment with the far end of the longer segment.
137     That puts the shorter segment into the right place.
138     It leaves the longer segment in the right place overall,
139     but it consists of two parts that need to be swapped next.  */

140
141  while (top > middle && middle > bottom)
142    {
143      if (top - middle > middle - bottom)
144    {
145      /**//* Bottom segment is the short one.  */
146      int len = middle - bottom;
147      register int i;
148
149      /**//* Swap it with the top part of the top segment.  */
150      for (i = 0; i < len; i++)
151        {
152          tem = argv[bottom + i];
153          argv[bottom + i] = argv[top - (middle - bottom) + i];
154          argv[top - (middle - bottom) + i] = tem;
155          SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
156        }

157      /**//* Exclude the moved bottom segment from further swapping.  */
158      top -= len;
159    }

160      else
161    {
162      /**//* Top segment is the short one.  */
163      int len = top - middle;
164      register int i;
165
166      /**//* Swap it with the bottom part of the bottom segment.  */
167      for (i = 0; i < len; i++)
168        {
169          tem = argv[bottom + i];
170          argv[bottom + i] = argv[middle + i];
171          argv[middle + i] = tem;
172          SWAP_FLAGS (bottom + i, middle + i);
173        }

174      /**//* Exclude the moved top segment from further swapping.  */
175      bottom += len;
176    }

177    }

178
179  /**//* Update records for the slots the non-options now occupy.  */
180
181  d->__first_nonopt += (d->optind - d->__last_nonopt);
182  d->__last_nonopt = d->optind;
183}

184
185/**//* Initialize the internal data when the first call is made.  */
186
187static const char *
188_getopt_initialize (int argc, char *const *argv, const char *optstring,
189            struct _getopt_data *d)
190{
191  /**//* Start processing options with ARGV-element 1 (since ARGV-element 0
192     is the program name); the sequence of previously skipped
193     non-option ARGV-elements is empty.  */

194
195  d->__first_nonopt = d->__last_nonopt = d->optind;
196
197  d->__nextchar = NULL;
198
199  d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
200
201  /**//* Determine how to handle the ordering of options and nonoptions.  */
202
203  if (optstring[0== '-')
204    {
205      d->__ordering = RETURN_IN_ORDER;
206      ++optstring;
207    }

208  else if (optstring[0== '+')
209    {
210      d->__ordering = REQUIRE_ORDER;
211      ++optstring;
212    }

213  else if (d->__posixly_correct)
214    d->__ordering = REQUIRE_ORDER;
215  else
216    d->__ordering = PERMUTE;
217
218
219  return optstring;
220}

221
222/**//* Scan elements of ARGV (whose length is ARGC) for option characters
223   given in OPTSTRING.
224
225   If an element of ARGV starts with '-', and is not exactly "-" or "--",
226   then it is an option element.  The characters of this element
227   (aside from the initial '-') are option characters.  If `getopt'
228   is called repeatedly, it returns successively each of the option characters
229   from each of the option elements.
230
231   If `getopt' finds another option character, it returns that character,
232   updating `optind' and `nextchar' so that the next call to `getopt' can
233   resume the scan with the following option character or ARGV-element.
234
235   If there are no more option characters, `getopt' returns -1.
236   Then `optind' is the index in ARGV of the first ARGV-element
237   that is not an option.  (The ARGV-elements have been permuted
238   so that those that are not options now come last.)
239
240   OPTSTRING is a string containing the legitimate option characters.
241   If an option character is seen that is not listed in OPTSTRING,
242   return '?' after printing an error message.  If you set `opterr' to
243   zero, the error message is suppressed but we still return '?'.
244
245   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
246   so the following text in the same ARGV-element, or the text of the following
247   ARGV-element, is returned in `optarg'.  Two colons mean an option that
248   wants an optional arg; if there is text in the current ARGV-element,
249   it is returned in `optarg', otherwise `optarg' is set to zero.
250
251   If OPTSTRING starts with `-' or `+', it requests different methods of
252   handling the non-option ARGV-elements.
253   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
254
255   Long-named options begin with `--' instead of `-'.
256   Their names may be abbreviated as long as the abbreviation is unique
257   or is an exact match for some defined option.  If they have an
258   argument, it follows the option name in the same ARGV-element, separated
259   from the option name by a `=', or else the in next ARGV-element.
260   When `getopt' finds a long-named option, it returns 0 if that option's
261   `flag' field is nonzero, the value of the option's `val' field
262   if the `flag' field is zero.
263
264   The elements of ARGV aren't really const, because we permute them.
265   But we pretend they're const in the prototype to be compatible
266   with other systems.
267
268   LONGOPTS is a vector of `struct option' terminated by an
269   element containing a name which is zero.
270
271   LONGIND returns the index in LONGOPT of the long-named option found.
272   It is only valid when a long-named option has been found by the most
273   recent call.
274
275   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
276   long-named options.  */

277
278int
279_getopt_internal_r (int argc, char *const *argv, const char *optstring,
280            const struct option *longopts, int *longind,
281            int long_only, struct _getopt_data *d)
282{
283  int print_errors = d->opterr;
284  if (optstring[0== ':')
285    print_errors = 0;
286
287  if (argc < 1)
288    return -1;
289
290  d->optarg = NULL;
291
292  if (d->optind == 0 || !d->__initialized)
293    {
294      if (d->optind == 0)
295    d->optind = 1;    /**//* Don't scan ARGV[0], the program name.  */
296      optstring = _getopt_initialize (argc, argv, optstring, d);
297      d->__initialized = 1;
298    }

299
300  /**//* Test whether ARGV[optind] points to a non-option argument.
301     Either it does not have option syntax, or there is an environment flag
302     from the shell indicating it is not an option.  The later information
303     is only used when the used in the GNU libc.  */

304# define NONOPTION_P (argv[d->optind][0!= '-' || argv[d->optind][1== '\0')
305
306  if (d->__nextchar == NULL || *d->__nextchar == '\0')
307    {
308      /**//* Advance to the next ARGV-element.  */
309
310      /**//* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
311     moved back by the user (who may also have changed the arguments).  */

312      if (d->__last_nonopt > d->optind)
313    d->__last_nonopt = d->optind;
314      if (d->__first_nonopt > d->optind)
315    d->__first_nonopt = d->optind;
316
317      if (d->__ordering == PERMUTE)
318    {
319      /**//* If we have just processed some options following some non-options,
320         exchange them so that the options come first.  */

321
322      if (d->__first_nonopt != d->__last_nonopt
323          && d->__last_nonopt != d->optind)
324        exchange ((char **) argv, d);
325      else if (d->__last_nonopt != d->optind)
326        d->__first_nonopt = d->optind;
327
328      /**//* Skip any additional non-options
329         and extend the range of non-options previously skipped.  */

330
331      while (d->optind < argc && NONOPTION_P)
332        d->optind++;
333      d->__last_nonopt = d->optind;
334    }

335
336      /**//* The special ARGV-element `--' means premature end of options.
337     Skip it like a null option,
338     then exchange with previous non-options as if it were an option,
339     then skip everything else like a non-option.  */

340
341      if (d->optind != argc && !strcmp (argv[d->optind], "--"))
342    {
343      d->optind++;
344
345      if (d->__first_nonopt != d->__last_nonopt
346          && d->__last_nonopt != d->optind)
347        exchange ((char **) argv, d);
348      else if (d->__first_nonopt == d->__last_nonopt)
349        d->__first_nonopt = d->optind;
350      d->__last_nonopt = argc;
351
352      d->optind = argc;
353    }

354
355      /**//* If we have done all the ARGV-elements, stop the scan
356     and back over any non-options that we skipped and permuted.  */

357
358      if (d->optind == argc)
359    {
360      /**//* Set the next-arg-index to point at the non-options
361         that we previously skipped, so the caller will digest them.  */

362      if (d->__first_nonopt != d->__last_nonopt)
363        d->optind = d->__first_nonopt;
364      return -1;
365    }

366
367      /**//* If we have come to a non-option and did not permute it,
368     either stop the scan or describe it to the caller and pass it by.  */

369
370      if (NONOPTION_P)
371    {
372      if (d->__ordering == REQUIRE_ORDER)
373        return -1;
374      d->optarg = argv[d->optind++];
375      return 1;
376    }

377
378      /**//* We have found another option-ARGV-element.
379     Skip the initial punctuation.  */

380
381      d->__nextchar = (argv[d->optind] + 1
382          + (longopts != NULL && argv[d->optind][1== '-'));
383    }

384
385  /**//* Decode the current option-ARGV-element.  */
386
387  /**//* Check whether the ARGV-element is a long option.
388
389     If long_only and the ARGV-element has the form "-f", where f is
390     a valid short option, don't consider it an abbreviated form of
391     a long option that starts with f.  Otherwise there would be no
392     way to give the -f short option.
393
394     On the other hand, if there's a long option "fubar" and
395     the ARGV-element is "-fu", do consider that an abbreviation of
396     the long option, just like "--fu", and not "-f" with arg "u".
397
398     This distinction seems to be the most useful approach.  */

399
400  if (longopts != NULL
401      && (argv[d->optind][1== '-'
402      || (long_only && (argv[d->optind][2]
403                || !strchr (optstring, argv[d->optind][1])))))
404    {
405      char *nameend;
406      const struct option *p;
407      const struct option *pfound = NULL;
408      int exact = 0;
409      int ambig = 0;
410      int indfound = -1;
411      int option_index;
412
413      for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
414    /**//* Do nothing.  */ ;
415
416      /**//* Test all long options for either exact match
417     or abbreviated matches.  */

418      for (p = longopts, option_index = 0; p->name; p++, option_index++)
419    if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
420      {
421        if ((unsigned int) (nameend - d->__nextchar)
422        == (unsigned int) strlen (p->name))
423          {
424        /**//* Exact match found.  */
425        pfound = p;
426        indfound = option_index;
427        exact = 1;
428        break;
429          }

430        else if (pfound == NULL)
431          {
432        /**//* First nonexact match found.  */
433        pfound = p;
434        indfound = option_index;
435          }

436        else if (long_only
437             || pfound->has_arg != p->has_arg
438             || pfound->flag != p->flag
439             || pfound->val != p->val)
440          /**//* Second or later nonexact match found.  */
441          ambig = 1;
442      }

443
444      if (ambig && !exact)
445    {
446      if (print_errors)
447        {
448          fprintf (stderr, _("%s: option '%s' is ambiguous\n"),
449               argv[0], argv[d->optind]);
450        }

451      d->__nextchar += strlen (d->__nextchar);
452      d->optind++;
453      d->optopt = 0;
454      return '?';
455    }

456
457      if (pfound != NULL)
458    {
459      option_index = indfound;
460      d->optind++;
461      if (*nameend)
462        {
463          /**//* Don't test has_arg with >, because some C compilers don't
464         allow it to be used on enums.  */

465          if (pfound->has_arg)
466        d->optarg = nameend + 1;
467          else
468        {
469          if (print_errors)
470            {
471
472              if (argv[d->optind - 1][1== '-')
473            {
474              /**//* --option */
475              fprintf (stderr, _("\
476%s: option '--%s' doesn't allow an argument\n"),
477                   argv[0], pfound->name);
478            }

479              else
480            {
481              /**//* +option or -option */
482              fprintf (stderr, _("\
483%s: option '%c%s' doesn't allow an argument\n"),
484                   argv[0], argv[d->optind - 1][0],
485                   pfound->name);
486            }

487
488            }

489
490          d->__nextchar += strlen (d->__nextchar);
491
492          d->optopt = pfound->val;
493          return '?';
494        }

495        }

496      else if (pfound->has_arg == 1)
497        {
498          if (d->optind < argc)
499        d->optarg = argv[d->optind++];
500          else
501        {
502          if (print_errors)
503            {
504              fprintf (stderr,
505                   _("%s: option '%s' requires an argument\n"),
506                   argv[0], argv[d->optind - 1]);
507            }

508          d->__nextchar += strlen (d->__nextchar);
509          d->optopt = pfound->val;
510          return optstring[0== ':' ? ':' : '?';
511        }

512        }

513      d->__nextchar += strlen (d->__nextchar);
514      if (longind != NULL)
515        *longind = option_index;
516      if (pfound->flag)
517        {
518          *(pfound->flag) = pfound->val;
519          return 0;
520        }

521      return pfound->val;
522    }

523
524      /**//* Can't find it as a long option.  If this is not getopt_long_only,
525     or the option starts with '--' or is not a valid short
526     option, then it's an error.
527     Otherwise interpret it as a short option.  */

528      if (!long_only || argv[d->optind][1== '-'
529      || strchr (optstring, *d->__nextchar) == NULL)
530    {
531      if (print_errors)
532        {
533
534          if (argv[d->optind][1== '-')
535        {
536          /**//* --option */
537          fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
538               argv[0], d->__nextchar);
539        }

540          else
541        {
542          /**//* +option or -option */
543          fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
544               argv[0], argv[d->optind][0], d->__nextchar);
545        }

546
547        }

548      d->__nextchar = (char *"";
549      d->optind++;
550      d->optopt = 0;
551      return '?';
552    }

553    }

554
555  /**//* Look at and handle the next short option-character.  */
556
557  {
558    char c = *d->__nextchar++;
559    char *temp = strchr (optstring, c);
560
561    /**//* Increment `optind' when we start to process its last character.  */
562    if (*d->__nextchar == '\0')
563      ++d->optind;
564
565    if (temp == NULL || c == ':')
566      {
567    if (print_errors)
568      {
569
570        fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
571
572      }

573    d->optopt = c;
574    return '?';
575      }

576    /**//* Convenience. Treat POSIX -W foo same as long option --foo */
577    if (temp[0== 'W' && temp[1== ';')
578      {
579    char *nameend;
580    const struct option *p;
581    const struct option *pfound = NULL;
582    int exact = 0;
583    int ambig = 0;
584    int indfound = 0;
585    int option_index;
586
587    /**//* This is an option that requires an argument.  */
588    if (*d->__nextchar != '\0')
589      {
590        d->optarg = d->__nextchar;
591        /**//* If we end this ARGV-element by taking the rest as an arg,
592           we must advance to the next element now.  */

593        d->optind++;
594      }

595    else if (d->optind == argc)
596      {
597        if (print_errors)
598          {
599        fprintf (stderr,
600             _("%s: option requires an argument -- '%c'\n"),
601             argv[0], c);
602          }

603        d->optopt = c;
604        if (optstring[0== ':')
605          c = ':';
606        else
607          c = '?';
608        return c;
609      }

610    else
611      /**//* We already incremented `d->optind' once;
612         increment it again when taking next ARGV-elt as argument.  */

613      d->optarg = argv[d->optind++];
614
615    /**//* optarg is now the argument, see if it's in the
616       table of longopts.  */

617
618    for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
619         nameend++)
620      /**//* Do nothing.  */ ;
621
622    /**//* Test all long options for either exact match
623       or abbreviated matches.  */

624    for (p = longopts, option_index = 0; p->name; p++, option_index++)
625      if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
626        {
627          if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
628        {
629          /**//* Exact match found.  */
630          pfound = p;
631          indfound = option_index;
632          exact = 1;
633          break;
634        }

635          else if (pfound == NULL)
636        {
637          /**//* First nonexact match found.  */
638          pfound = p;
639          indfound = option_index;
640        }

641          else
642        /**//* Second or later nonexact match found.  */
643        ambig = 1;
644        }

645    if (ambig && !exact)
646      {
647        if (print_errors)
648          {
649        fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
650             argv[0], argv[d->optind]);
651          }

652        d->__nextchar += strlen (d->__nextchar);
653        d->optind++;
654        return '?';
655      }

656    if (pfound != NULL)
657      {
658        option_index = indfound;
659        if (*nameend)
660          {
661        /**//* Don't test has_arg with >, because some C compilers don't
662           allow it to be used on enums.  */

663        if (pfound->has_arg)
664          d->optarg = nameend + 1;
665        else
666          {
667            if (print_errors)
668              {
669            fprintf (stderr, _("\
670%s: option '-W %s' doesn't allow an argument\n"),
671                 argv[0], pfound->name);
672              }

673
674            d->__nextchar += strlen (d->__nextchar);
675            return '?';
676          }

677          }

678        else if (pfound->has_arg == 1)
679          {
680        if (d->optind < argc)
681          d->optarg = argv[d->optind++];
682        else
683          {
684            if (print_errors)
685              {
686            fprintf (stderr,
687                 _("%s: option '%s' requires an argument\n"),
688                 argv[0], argv[d->optind - 1]);
689              }

690            d->__nextchar += strlen (d->__nextchar);
691            return optstring[0== ':' ? ':' : '?';
692          }

693          }

694        d->__nextchar += strlen (d->__nextchar);
695        if (longind != NULL)
696          *longind = option_index;
697        if (pfound->flag)
698          {
699        *(pfound->flag) = pfound->val;
700        return 0;
701          }

702        return pfound->val;
703      }

704      d->__nextchar = NULL;
705      return 'W';    /**//* Let the application handle it.   */
706      }

707    if (temp[1== ':')
708      {
709    if (temp[2== ':')
710      {
711        /**//* This is an option that accepts an argument optionally.  */
712        if (*d->__nextchar != '\0')
713          {
714        d->optarg = d->__nextchar;
715        d->optind++;
716          }

717        else
718          d->optarg = NULL;
719        d->__nextchar = NULL;
720      }

721    else
722      {
723        /**//* This is an option that requires an argument.  */
724        if (*d->__nextchar != '\0')
725          {
726        d->optarg = d->__nextchar;
727        /**//* If we end this ARGV-element by taking the rest as an arg,
728           we must advance to the next element now.  */

729        d->optind++;
730          }

731        else if (d->optind == argc)
732          {
733        if (print_errors)
734          {
735            fprintf (stderr,
736                 _("%s: option requires an argument -- '%c'\n"),
737                 argv[0], c);
738          }

739        d->optopt = c;
740        if (optstring[0== ':')
741          c = ':';
742        else
743          c = '?';
744          }

745        else
746          /**//* We already incremented `optind' once;
747         increment it again when taking next ARGV-elt as argument.  */

748          d->optarg = argv[d->optind++];
749        d->__nextchar = NULL;
750      }

751      }

752    return c;
753  }

754}

755
756int
757_getopt_internal (int argc, char *const *argv, const char *optstring,
758          const struct option *longopts, int *longind, int long_only)
759{
760  int result;
761
762  getopt_data.optind = optind;
763  getopt_data.opterr = opterr;
764
765  result = _getopt_internal_r (argc, argv, optstring, longopts,
766                   longind, long_only, &getopt_data);
767
768  optind = getopt_data.optind;
769  optarg = getopt_data.optarg;
770  optopt = getopt_data.optopt;
771
772  return result;
773}

774
775int
776getopt (int argc, char *const *argv, const char *optstring)
777{
778  return _getopt_internal (argc, argv, optstring,
779               (const struct option *0,
780               (int *0,
781               0);
782}

783




getopt1.c
 1/**//*
 2getopt1.c
 3
 4Copyright (C) 2012, coreBugZJ, all rights reserved.
 5
 6在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数。
 7
 8修改自 glibc 2.8 中 getopt1.c 文件,
 9*/

10
11
12
13
14
15
16/**//* getopt_long and getopt_long_only entry points for GNU getopt.
17   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
18     Free Software Foundation, Inc.
19   This file is part of the GNU C Library.
20
21   The GNU C Library is free software; you can redistribute it and/or
22   modify it under the terms of the GNU Lesser General Public
23   License as published by the Free Software Foundation; either
24   version 2.1 of the License, or (at your option) any later version.
25
26   The GNU C Library is distributed in the hope that it will be useful,
27   but WITHOUT ANY WARRANTY; without even the implied warranty of
28   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29   Lesser General Public License for more details.
30
31   You should have received a copy of the GNU Lesser General Public
32   License along with the GNU C Library; if not, write to the Free
33   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
34   02111-1307 USA.  */

35
36
37#include "getopt.h"
38#include "getopt_int.h"
39
40
41int
42getopt_long (int argc, char *const *argv, const char *options,
43         const struct option *long_options, int *opt_index)
44{
45  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
46}

47
48int
49_getopt_long_r (int argc, char *const *argv, const char *options,
50        const struct option *long_options, int *opt_index,
51        struct _getopt_data *d)
52{
53  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
54                 0, d);
55}

56
57/**//* Like getopt_long, but '-' as well as '--' can indicate a long option.
58   If an option that starts with '-' (not '--') doesn't match a long option,
59   but does match a short option, it is parsed as a short option
60   instead.  */

61
62int
63getopt_long_only (int argc, char *const *argv, const char *options,
64          const struct option *long_options, int *opt_index)
65{
66  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
67}

68
69int
70_getopt_long_only_r (int argc, char *const *argv, const char *options,
71             const struct option *long_options, int *opt_index,
72             struct _getopt_data *d)
73{
74  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
75                 1, d);
76}

77




test_getopt.c
 1/**//*
 2test_getopt.c
 3
 4Copyright (C) 2012, coreBugZJ, all rights reserved.
 5
 6在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数。
 7
 8修改自 glibc 2.8 中 getopt.c 文件,
 9*/

10
11
12#include <stdio.h>
13#include "getopt.h"
14
15int main (int argc, char **argv)
16{
17        int c;
18        int digit_optind = 0;
19
20        while (1)
21        {
22                int this_option_optind = optind ? optind : 1;
23                int option_index = 0;
24                static struct option long_options[] =
25                {
26                        {"add"100},
27                        {"append"000},
28                        {"delete"100},
29                        {"verbose"000},
30                        {"create"000},
31                        {"file"100},
32                        {0000}
33                }
;
34
35                c = getopt_long (argc, argv, "abc:d:0123456789",
36                        long_options, &option_index);
37                if (c == -1)
38                        break;
39
40                switch (c)
41                {
42                case 0:
43                        printf ("option %s", long_options[option_index].name);
44                        if (optarg)
45                                printf (" with arg %s", optarg);
46                        printf ("\n");
47                        break;
48
49                case '0':
50                case '1':
51                case '2':
52                case '3':
53                case '4':
54                case '5':
55                case '6':
56                case '7':
57                case '8':
58                case '9':
59                        if (digit_optind != 0 && digit_optind != this_option_optind)
60                                printf ("digits occur in two different argv-elements.\n");
61                        digit_optind = this_option_optind;
62                        printf ("option %c\n", c);
63                        break;
64
65                case 'a':
66                        printf ("option a\n");
67                        break;
68
69                case 'b':
70                        printf ("option b\n");
71                        break;
72
73                case 'c':
74                        printf ("option c with value `%s'\n", optarg);
75                        break;
76
77                case 'd':
78                        printf ("option d with value `%s'\n", optarg);
79                        break;
80
81                case '?':
82                        break;
83
84                default:
85                        printf ("?? getopt returned character code 0%o ??\n", c);
86                }

87        }

88
89        if (optind < argc)
90        {
91                printf ("non-option ARGV-elements: ");
92                while (optind < argc)
93                        printf ("%s ", argv[optind++]);
94                printf ("\n");
95        }

96
97        return 0;
98}

99




你可能感兴趣的:(在 Windows 平台下使用 Linux 的 getopt, getopt_long, getopt_long_only 函数 解析命令行)