2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Parse command-line options
33 * This will point to the argument for the most recently returned
34 * option, if applicable.
39 * Current option index
41 * This is an index into the argv[] array. When getopt() returns -1,
42 * @c optind is the index to the first element that is not an option.
47 * Current option character index
49 * This is an index into the current element of argv[].
56 * When an unrecognised option is encountered, the actual option
57 * character is stored in @c optopt.
62 * Get option argument from argv[] array
64 * @v argc Argument count
65 * @v argv Argument list
66 * @ret argument Option argument, or NULL
68 * Grab the next element of argv[], if it exists and is not an option.
70 static const char * get_argv_argument ( int argc
, char * const argv
[] ) {
73 /* Don't overrun argv[] */
78 /* If next argv element is an option, then it's not usable as
84 /** Consume this argv element, and return it */
92 * @v argc Argument count
93 * @v argv Argument list
94 * @v opttext Option text within current argv[] element
95 * @v longopt Long option specification
96 * @ret option Option to return from getopt()
97 * @ret matched Found a match for this long option
99 static int match_long_option ( int argc
, char * const argv
[],
101 const struct option
*longopt
, int *option
) {
103 const char *argument
= NULL
;
105 /* Compare option name */
106 optlen
= strlen ( longopt
->name
);
107 if ( strncmp ( opttext
, longopt
->name
, optlen
) != 0 )
110 /* Check for inline argument */
111 if ( opttext
[optlen
] == '=' ) {
112 argument
= &opttext
[ optlen
+ 1 ];
113 } else if ( opttext
[optlen
] ) {
114 /* Long option with trailing garbage - no match */
118 /* Consume this argv element */
121 /* If we want an argument but don't have one yet, try to grab
122 * the next argv element
124 if ( ( longopt
->has_arg
!= no_argument
) && ( ! argument
) )
125 argument
= get_argv_argument ( argc
, argv
);
127 /* If we need an argument but don't have one, sulk */
128 if ( ( longopt
->has_arg
== required_argument
) && ( ! argument
) ) {
129 printf ( "Option \"%s\" requires an argument\n",
135 /* If we have an argument where we shouldn't have one, sulk */
136 if ( ( longopt
->has_arg
== no_argument
) && argument
) {
137 printf ( "Option \"%s\" takes no argument\n", longopt
->name
);
142 /* Store values and return success */
143 optarg
= ( char * ) argument
;
144 if ( longopt
->flag
) {
145 *(longopt
->flag
) = longopt
->val
;
148 *option
= longopt
->val
;
156 * @v argc Argument count
157 * @v argv Argument list
158 * @v opttext Option text within current argv[] element
159 * @v shortopt Option character from option specification
160 * @ret option Option to return from getopt()
161 * @ret matched Found a match for this short option
163 static int match_short_option ( int argc
, char * const argv
[],
164 const char *opttext
, int shortopt
,
165 enum getopt_argument_requirement has_arg
,
167 const char *argument
= NULL
;
169 /* Compare option character */
170 if ( *opttext
!= shortopt
)
173 /* Consume option character */
177 if ( has_arg
!= no_argument
) {
178 /* Consume remainder of element as inline argument */
184 /* Reached end of argv element */
189 /* If we want an argument but don't have one yet, try to grab
190 * the next argv element
192 if ( ( has_arg
!= no_argument
) && ( ! argument
) )
193 argument
= get_argv_argument ( argc
, argv
);
195 /* If we need an argument but don't have one, sulk */
196 if ( ( has_arg
== required_argument
) && ( ! argument
) ) {
197 printf ( "Option \"%c\" requires an argument\n", shortopt
);
202 /* Store values and return success */
203 optarg
= ( char * ) argument
;
209 * Parse command-line options
211 * @v argc Argument count
212 * @v argv Argument list
213 * @v optstring Option specification string
214 * @v longopts Long option specification table
215 * @ret longindex Index of long option (or NULL)
216 * @ret option Option found, or -1 for no more options
218 * Note that the caller must arrange for reset_getopt() to be called
219 * before each set of calls to getopt_long(). In Etherboot, this is
220 * done automatically by execv().
222 int getopt_long ( int argc
, char * const argv
[], const char *optstring
,
223 const struct option
*longopts
, int *longindex
) {
224 const char *opttext
= argv
[optind
];
225 const struct option
*longopt
;
227 enum getopt_argument_requirement has_arg
;
230 /* Check for end of argv array */
231 if ( optind
>= argc
)
234 /* Check for end of options */
235 if ( *(opttext
++) != '-' )
238 /* Check for long options */
239 if ( *(opttext
++) == '-' ) {
240 for ( longopt
= longopts
; longopt
->name
; longopt
++ ) {
241 if ( ! match_long_option ( argc
, argv
, opttext
,
245 *longindex
= ( longopt
- longopts
);
249 printf ( "Unrecognised option \"--%s\"\n", opttext
);
253 /* Check for short options */
256 opttext
= ( argv
[optind
] + nextchar
);
257 while ( ( shortopt
= *(optstring
++) ) ) {
258 has_arg
= no_argument
;
259 while ( *optstring
== ':' ) {
263 if ( match_short_option ( argc
, argv
, opttext
, shortopt
,
264 has_arg
, &option
) ) {
269 printf ( "Unrecognised option \"-%c\"\n", optopt
);