These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / core / parseopt.c
1 /*
2  * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <getopt.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/menu.h>
35 #include <ipxe/settings.h>
36 #include <ipxe/params.h>
37 #include <ipxe/timer.h>
38 #include <ipxe/parseopt.h>
39 #include <config/branding.h>
40
41 /** @file
42  *
43  * Command line option parsing
44  *
45  */
46
47 /** Return status code for "--help" option */
48 #define ECANCELED_NO_OP __einfo_error ( EINFO_ECANCELED_NO_OP )
49 #define EINFO_ECANCELED_NO_OP \
50         __einfo_uniqify ( EINFO_ECANCELED, 0x01, "Nothing to do" )
51
52 /* Disambiguate the various error codes */
53 #define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
54 #define EINFO_EINVAL_INTEGER \
55         __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid integer value" )
56 #define EINVAL_UNKNOWN_OPTION __einfo_error ( EINFO_EINVAL_UNKNOWN_OPTION )
57 #define EINFO_EINVAL_UNKNOWN_OPTION \
58         __einfo_uniqify ( EINFO_EINVAL, 0x02, "Unrecognised option" )
59 #define EINVAL_MISSING_ARGUMENT __einfo_error ( EINFO_EINVAL_MISSING_ARGUMENT )
60 #define EINFO_EINVAL_MISSING_ARGUMENT \
61         __einfo_uniqify ( EINFO_EINVAL, 0x03, "Missing argument" )
62
63 /**
64 * Parse string value
65  *
66  * @v text              Text
67  * @ret value           String value
68  * @ret rc              Return status code
69  */
70 int parse_string ( char *text, char **value ) {
71
72         /* Sanity check */
73         assert ( text != NULL );
74
75         /* Parse string */
76         *value = text;
77
78         return 0;
79 }
80
81 /**
82  * Parse integer value
83  *
84  * @v text              Text
85  * @ret value           Integer value
86  * @ret rc              Return status code
87  */
88 int parse_integer ( char *text, unsigned int *value ) {
89         char *endp;
90
91         /* Sanity check */
92         assert ( text != NULL );
93
94         /* Parse integer */
95         *value = strtoul ( text, &endp, 0 );
96         if ( *endp ) {
97                 printf ( "\"%s\": invalid integer value\n", text );
98                 return -EINVAL_INTEGER;
99         }
100
101         return 0;
102 }
103
104 /**
105  * Parse timeout value (in ms)
106  *
107  * @v text              Text
108  * @ret value           Integer value
109  * @ret rc              Return status code
110  */
111 int parse_timeout ( char *text, unsigned long *value ) {
112         unsigned int value_ms;
113         int rc;
114
115         /* Parse raw integer value */
116         if ( ( rc = parse_integer ( text, &value_ms ) ) != 0 )
117                 return rc;
118
119         /* Convert to a number of timer ticks */
120         *value = ( ( value_ms * TICKS_PER_SEC ) / 1000 );
121
122         return 0;
123 }
124
125 /**
126  * Parse network device name
127  *
128  * @v text              Text
129  * @ret netdev          Network device
130  * @ret rc              Return status code
131  */
132 int parse_netdev ( char *text, struct net_device **netdev ) {
133
134         /* Sanity check */
135         assert ( text != NULL );
136
137         /* Find network device */
138         *netdev = find_netdev ( text );
139         if ( ! *netdev ) {
140                 printf ( "\"%s\": no such network device\n", text );
141                 return -ENODEV;
142         }
143
144         return 0;
145 }
146
147 /**
148  * Parse network device configurator name
149  *
150  * @v text              Text
151  * @ret configurator    Network device configurator
152  * @ret rc              Return status code
153  */
154 int parse_netdev_configurator ( char *text,
155                                 struct net_device_configurator **configurator ){
156
157         /* Sanity check */
158         assert ( text != NULL );
159
160         /* Find network device configurator */
161         *configurator = find_netdev_configurator ( text );
162         if ( ! *configurator ) {
163                 printf ( "\"%s\": no such configurator\n", text );
164                 return -ENOTSUP;
165         }
166
167         return 0;
168 }
169
170 /**
171  * Parse menu name
172  *
173  * @v text              Text
174  * @ret menu            Menu
175  * @ret rc              Return status code
176  */
177 int parse_menu ( char *text, struct menu **menu ) {
178
179         /* Find menu */
180         *menu = find_menu ( text );
181         if ( ! *menu ) {
182                 if ( text ) {
183                         printf ( "\"%s\": no such menu\n", text );
184                 } else {
185                         printf ( "No default menu\n" );
186                 }
187                 return -ENOENT;
188         }
189
190         return 0;
191 }
192
193 /**
194  * Parse flag
195  *
196  * @v text              Text (ignored)
197  * @ret flag            Flag to set
198  * @ret rc              Return status code
199  */
200 int parse_flag ( char *text __unused, int *flag ) {
201
202         /* Set flag */
203         *flag = 1;
204
205         return 0;
206 }
207
208 /**
209  * Parse key
210  *
211  * @v text              Text
212  * @ret key             Key
213  * @ret rc              Return status code
214  */
215 int parse_key ( char *text, unsigned int *key ) {
216
217         /* Interpret single characters as being a literal key character */
218         if ( text[0] && ! text[1] ) {
219                 *key = text[0];
220                 return 0;
221         }
222
223         /* Otherwise, interpret as an integer */
224         return parse_integer ( text, key );
225 }
226
227 /**
228  * Parse settings block name
229  *
230  * @v text              Text
231  * @ret value           Integer value
232  * @ret rc              Return status code
233  */
234 int parse_settings ( char *text, struct settings **value ) {
235
236         /* Sanity check */
237         assert ( text != NULL );
238
239         /* Parse scope name */
240         *value = find_settings ( text );
241         if ( ! *value ) {
242                 printf ( "\"%s\": no such scope\n", text );
243                 return -EINVAL;
244         }
245
246         return 0;
247 }
248
249 /**
250  * Parse setting name
251  *
252  * @v text              Text
253  * @v setting           Named setting to fill in
254  * @v get_child         Function to find or create child settings block
255  * @ret rc              Return status code
256  *
257  * Note that this function modifies the original @c text.
258  */
259 int parse_setting ( char *text, struct named_setting *setting,
260                     get_child_settings_t get_child ) {
261         int rc;
262
263         /* Sanity check */
264         assert ( text != NULL );
265
266         /* Parse setting name */
267         if ( ( rc = parse_setting_name ( text, get_child, &setting->settings,
268                                          &setting->setting ) ) != 0 ) {
269                 printf ( "\"%s\": invalid setting\n", text );
270                 return rc;
271         }
272
273         return 0;
274 }
275
276 /**
277  * Parse existing setting name
278  *
279  * @v text              Text
280  * @v setting           Named setting to fill in
281  * @ret rc              Return status code
282  *
283  * Note that this function modifies the original @c text.
284  */
285 int parse_existing_setting ( char *text, struct named_setting *setting ) {
286
287         return parse_setting ( text, setting, find_child_settings );
288 }
289
290 /**
291  * Parse and autovivify setting name
292  *
293  * @v text              Text
294  * @v setting           Named setting to fill in
295  * @ret rc              Return status code
296  *
297  * Note that this function modifies the original @c text.
298  */
299 int parse_autovivified_setting ( char *text, struct named_setting *setting ) {
300
301         return parse_setting ( text, setting, autovivify_child_settings );
302 }
303
304 /**
305  * Parse form parameter list name
306  *
307  * @v text              Text
308  * @ret params          Parameter list
309  * @ret rc              Return status code
310  */
311 int parse_parameters ( char *text, struct parameters **params ) {
312
313         /* Find parameter list */
314         *params = find_parameters ( text );
315         if ( ! *params ) {
316                 if ( text ) {
317                         printf ( "\"%s\": no such parameter list\n", text );
318                 } else {
319                         printf ( "No default parameter list\n" );
320                 }
321                 return -ENOENT;
322         }
323
324         return 0;
325 }
326
327 /**
328  * Print command usage message
329  *
330  * @v cmd               Command descriptor
331  * @v argv              Argument list
332  */
333 void print_usage ( struct command_descriptor *cmd, char **argv ) {
334         struct option_descriptor *option;
335         unsigned int i;
336         int is_optional;
337
338         printf ( "Usage:\n\n  %s", argv[0] );
339         for ( i = 0 ; i < cmd->num_options ; i++ ) {
340                 option = &cmd->options[i];
341                 printf ( " [-%c|--%s", option->shortopt, option->longopt );
342                 if ( option->has_arg ) {
343                         is_optional = ( option->has_arg == optional_argument );
344                         printf ( " %s<%s>%s", ( is_optional ? "[" : "" ),
345                                  option->longopt, ( is_optional ? "]" : "" ) );
346                 }
347                 printf ( "]" );
348         }
349         if ( cmd->usage )
350                 printf ( " %s", cmd->usage );
351         printf ( "\n\nSee " PRODUCT_COMMAND_URI " for further information\n",
352                  argv[0] );
353 }
354
355 /**
356  * Reparse command-line options
357  *
358  * @v argc              Argument count
359  * @v argv              Argument list
360  * @v cmd               Command descriptor
361  * @v opts              Options (already initialised with default values)
362  * @ret rc              Return status code
363  */
364 int reparse_options ( int argc, char **argv, struct command_descriptor *cmd,
365                       void *opts ) {
366         struct option longopts[ cmd->num_options + 1 /* help */ + 1 /* end */ ];
367         char shortopts[ cmd->num_options * 3 /* possible "::" */ + 1 /* "h" */
368                         + 1 /* NUL */ ];
369         unsigned int shortopt_idx = 0;
370         int ( * parse ) ( char *text, void *value );
371         void *value;
372         unsigned int i;
373         unsigned int j;
374         unsigned int num_args;
375         int c;
376         int rc;
377
378         /* Construct long and short option lists for getopt_long() */
379         memset ( longopts, 0, sizeof ( longopts ) );
380         for ( i = 0 ; i < cmd->num_options ; i++ ) {
381                 longopts[i].name = cmd->options[i].longopt;
382                 longopts[i].has_arg = cmd->options[i].has_arg;
383                 longopts[i].val = cmd->options[i].shortopt;
384                 shortopts[shortopt_idx++] = cmd->options[i].shortopt;
385                 assert ( cmd->options[i].has_arg <= optional_argument );
386                 for ( j = cmd->options[i].has_arg ; j > 0 ; j-- )
387                         shortopts[shortopt_idx++] = ':';
388         }
389         longopts[i].name = "help";
390         longopts[i].val = 'h';
391         shortopts[shortopt_idx++] = 'h';
392         shortopts[shortopt_idx++] = '\0';
393         assert ( shortopt_idx <= sizeof ( shortopts ) );
394         DBGC ( cmd,  "Command \"%s\" has options \"%s\", %d-%d args, len %d\n",
395                argv[0], shortopts, cmd->min_args, cmd->max_args, cmd->len );
396
397         /* Parse options */
398         while ( ( c = getopt_long ( argc, argv, shortopts, longopts,
399                                     NULL ) ) >= 0 ) {
400                 switch ( c ) {
401                 case 'h' :
402                         /* Print help */
403                         print_usage ( cmd, argv );
404                         return -ECANCELED_NO_OP;
405                 case '?' :
406                         /* Print usage message */
407                         print_usage ( cmd, argv );
408                         return -EINVAL_UNKNOWN_OPTION;
409                 case ':' :
410                         /* Print usage message */
411                         print_usage ( cmd, argv );
412                         return -EINVAL_MISSING_ARGUMENT;
413                 default:
414                         /* Search for an option to parse */
415                         for ( i = 0 ; i < cmd->num_options ; i++ ) {
416                                 if ( c != cmd->options[i].shortopt )
417                                         continue;
418                                 parse = cmd->options[i].parse;
419                                 value = ( opts + cmd->options[i].offset );
420                                 if ( ( rc = parse ( optarg, value ) ) != 0 )
421                                         return rc;
422                                 break;
423                         }
424                         assert ( i < cmd->num_options );
425                 }
426         }
427
428         /* Check remaining arguments */
429         num_args = ( argc - optind );
430         if ( ( num_args < cmd->min_args ) || ( num_args > cmd->max_args ) ) {
431                 print_usage ( cmd, argv );
432                 return -ERANGE;
433         }
434
435         return 0;
436 }
437
438 /**
439  * Parse command-line options
440  *
441  * @v argc              Argument count
442  * @v argv              Argument list
443  * @v cmd               Command descriptor
444  * @v opts              Options (may be uninitialised)
445  * @ret rc              Return status code
446  */
447 int parse_options ( int argc, char **argv, struct command_descriptor *cmd,
448                     void *opts ) {
449
450         /* Clear options */
451         memset ( opts, 0, cmd->len );
452
453         return reparse_options ( argc, argv, cmd, opts );
454 }