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.
19 FILE_LICENCE ( GPL2_OR_LATER
);
28 * Parse command-line options
35 * This will point to the argument for the most recently returned
36 * option, if applicable.
41 * Current option index
43 * This is an index into the argv[] array. When getopt() returns -1,
44 * @c optind is the index to the first element that is not an option.
49 * Current option character index
51 * This is an index into the current element of argv[].
58 * When an unrecognised option is encountered, the actual option
59 * character is stored in @c optopt.
64 * Get option argument from argv[] array
66 * @v argc Argument count
67 * @v argv Argument list
68 * @ret argument Option argument, or NULL
70 * Grab the next element of argv[], if it exists and is not an option.
72 static const char * get_argv_argument ( int argc
, char * const argv
[] ) {
75 /* Don't overrun argv[] */
80 /* If next argv element is an option, then it's not usable as
86 /** Consume this argv element, and return it */
94 * @v argc Argument count
95 * @v argv Argument list
96 * @v opttext Option text within current argv[] element
97 * @v longopt Long option specification
98 * @ret option Option to return from getopt()
99 * @ret matched Found a match for this long option
101 static int match_long_option ( int argc
, char * const argv
[],
103 const struct option
*longopt
, int *option
) {
105 const char *argument
= NULL
;
107 /* Compare option name */
108 optlen
= strlen ( longopt
->name
);
109 if ( strncmp ( opttext
, longopt
->name
, optlen
) != 0 )
112 /* Check for inline argument */
113 if ( opttext
[optlen
] == '=' ) {
114 argument
= &opttext
[ optlen
+ 1 ];
115 } else if ( opttext
[optlen
] ) {
116 /* Long option with trailing garbage - no match */
120 /* Consume this argv element */
123 /* If we want an argument but don't have one yet, try to grab
124 * the next argv element
126 if ( ( longopt
->has_arg
!= no_argument
) && ( ! argument
) )
127 argument
= get_argv_argument ( argc
, argv
);
129 /* If we need an argument but don't have one, sulk */
130 if ( ( longopt
->has_arg
== required_argument
) && ( ! argument
) ) {
131 printf ( "Option \"%s\" requires an argument\n",
137 /* If we have an argument where we shouldn't have one, sulk */
138 if ( ( longopt
->has_arg
== no_argument
) && argument
) {
139 printf ( "Option \"%s\" takes no argument\n", longopt
->name
);
144 /* Store values and return success */
145 optarg
= ( char * ) argument
;
146 if ( longopt
->flag
) {
147 *(longopt
->flag
) = longopt
->val
;
150 *option
= longopt
->val
;
158 * @v argc Argument count
159 * @v argv Argument list
160 * @v opttext Option text within current argv[] element
161 * @v shortopt Option character from option specification
162 * @ret option Option to return from getopt()
163 * @ret matched Found a match for this short option
165 static int match_short_option ( int argc
, char * const argv
[],
166 const char *opttext
, int shortopt
,
167 enum getopt_argument_requirement has_arg
,
169 const char *argument
= NULL
;
171 /* Compare option character */
172 if ( *opttext
!= shortopt
)
175 /* Consume option character */
179 if ( has_arg
!= no_argument
) {
180 /* Consume remainder of element as inline argument */
186 /* Reached end of argv element */
191 /* If we want an argument but don't have one yet, try to grab
192 * the next argv element
194 if ( ( has_arg
!= no_argument
) && ( ! argument
) )
195 argument
= get_argv_argument ( argc
, argv
);
197 /* If we need an argument but don't have one, sulk */
198 if ( ( has_arg
== required_argument
) && ( ! argument
) ) {
199 printf ( "Option \"%c\" requires an argument\n", shortopt
);
204 /* Store values and return success */
205 optarg
= ( char * ) argument
;
211 * Parse command-line options
213 * @v argc Argument count
214 * @v argv Argument list
215 * @v optstring Option specification string
216 * @v longopts Long option specification table
217 * @ret longindex Index of long option (or NULL)
218 * @ret option Option found, or -1 for no more options
220 * Note that the caller must arrange for reset_getopt() to be called
221 * before each set of calls to getopt_long(). In Etherboot, this is
222 * done automatically by execv().
224 int getopt_long ( int argc
, char * const argv
[], const char *optstring
,
225 const struct option
*longopts
, int *longindex
) {
226 const char *opttext
= argv
[optind
];
227 const struct option
*longopt
;
229 enum getopt_argument_requirement has_arg
;
232 /* Check for end of argv array */
233 if ( optind
>= argc
)
236 /* Check for end of options */
237 if ( *(opttext
++) != '-' )
240 /* Check for long options */
241 if ( *(opttext
++) == '-' ) {
242 for ( longopt
= longopts
; longopt
->name
; longopt
++ ) {
243 if ( ! match_long_option ( argc
, argv
, opttext
,
247 *longindex
= ( longopt
- longopts
);
251 printf ( "Unrecognised option \"--%s\"\n", opttext
);
255 /* Check for short options */
258 opttext
= ( argv
[optind
] + nextchar
);
259 while ( ( shortopt
= *(optstring
++) ) ) {
260 has_arg
= no_argument
;
261 while ( *optstring
== ':' ) {
265 if ( match_short_option ( argc
, argv
, opttext
, shortopt
,
266 has_arg
, &option
) ) {
271 printf ( "Unrecognised option \"-%c\"\n", optopt
);