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

getopt.h
1
/**//*
2
getopt.h
3
4
Copyright (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
48
extern "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
57
extern 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
71
extern int optind;
72
73
/**//* Callers store zero here to inhibit the error message `getopt' prints
74
for unrecognized options. */
75
76
extern int opterr;
77
78
/**//* Set to an option character which was unrecognized. */
79
80
extern 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
103
struct 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. */
147
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
148
149
extern int getopt_long (int ___argc, char *const *___argv,
150
const char *__shortopts,
151
const struct option *__longopts, int *__longind);
152
153
extern 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
/**//*
2
getopt_int.h
3
4
Copyright (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
38
extern 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. */
48
struct _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
123
extern 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
128
extern 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
133
extern 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
/**//*
2
getopt.c
3
4
Copyright (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 drepper@gnu.org
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
79
char *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. */
94
int optind = 1;
95
96
/**//* Callers store zero here to inhibit the error message
97
for unrecognized options. */
98
99
int 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
105
int optopt = '?';
106
107
/**//* Keep a global copy of all internal members of getopt_data. */
108
109
static struct _getopt_data getopt_data;
110
111
112
#ifndef getenv
113
extern 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
128
static void
129
exchange (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
187
static 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
278
int
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
756
int
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
775
int
776
getopt (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
/**//*
2
getopt1.c
3
4
Copyright (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
41
int
42
getopt_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
48
int
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
62
int
63
getopt_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
69
int
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
/**//*
2
test_getopt.c
3
4
Copyright (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
15
int 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", 1, 0, 0},
27
{"append", 0, 0, 0},
28
{"delete", 1, 0, 0},
29
{"verbose", 0, 0, 0},
30
{"create", 0, 0, 0},
31
{"file", 1, 0, 0},
32
{0, 0, 0, 0}
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