diff options
author | 2015-08-28 09:58:54 +0800 | |
---|---|---|
committer | 2015-09-01 12:44:00 +0800 | |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/ipxe/src/core/parseopt.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/core/parseopt.c')
-rw-r--r-- | qemu/roms/ipxe/src/core/parseopt.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/core/parseopt.c b/qemu/roms/ipxe/src/core/parseopt.c new file mode 100644 index 000000000..d268c0594 --- /dev/null +++ b/qemu/roms/ipxe/src/core/parseopt.c @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <getopt.h> +#include <ipxe/netdevice.h> +#include <ipxe/menu.h> +#include <ipxe/settings.h> +#include <ipxe/params.h> +#include <ipxe/timer.h> +#include <ipxe/parseopt.h> + +/** @file + * + * Command line option parsing + * + */ + +/** Return status code for "--help" option */ +#define ECANCELED_NO_OP __einfo_error ( EINFO_ECANCELED_NO_OP ) +#define EINFO_ECANCELED_NO_OP \ + __einfo_uniqify ( EINFO_ECANCELED, 0x01, "Nothing to do" ) + +/* Disambiguate the various error codes */ +#define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER ) +#define EINFO_EINVAL_INTEGER \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid integer value" ) +#define EINVAL_UNKNOWN_OPTION __einfo_error ( EINFO_EINVAL_UNKNOWN_OPTION ) +#define EINFO_EINVAL_UNKNOWN_OPTION \ + __einfo_uniqify ( EINFO_EINVAL, 0x02, "Unrecognised option" ) +#define EINVAL_MISSING_ARGUMENT __einfo_error ( EINFO_EINVAL_MISSING_ARGUMENT ) +#define EINFO_EINVAL_MISSING_ARGUMENT \ + __einfo_uniqify ( EINFO_EINVAL, 0x03, "Missing argument" ) + +/** +* Parse string value + * + * @v text Text + * @ret value String value + * @ret rc Return status code + */ +int parse_string ( char *text, char **value ) { + + /* Sanity check */ + assert ( text != NULL ); + + /* Parse string */ + *value = text; + + return 0; +} + +/** + * Parse integer value + * + * @v text Text + * @ret value Integer value + * @ret rc Return status code + */ +int parse_integer ( char *text, unsigned int *value ) { + char *endp; + + /* Sanity check */ + assert ( text != NULL ); + + /* Parse integer */ + *value = strtoul ( text, &endp, 0 ); + if ( *endp ) { + printf ( "\"%s\": invalid integer value\n", text ); + return -EINVAL_INTEGER; + } + + return 0; +} + +/** + * Parse timeout value (in ms) + * + * @v text Text + * @ret value Integer value + * @ret rc Return status code + */ +int parse_timeout ( char *text, unsigned long *value ) { + unsigned int value_ms; + int rc; + + /* Parse raw integer value */ + if ( ( rc = parse_integer ( text, &value_ms ) ) != 0 ) + return rc; + + /* Convert to a number of timer ticks */ + *value = ( ( value_ms * TICKS_PER_SEC ) / 1000 ); + + return 0; +} + +/** + * Parse network device name + * + * @v text Text + * @ret netdev Network device + * @ret rc Return status code + */ +int parse_netdev ( char *text, struct net_device **netdev ) { + + /* Sanity check */ + assert ( text != NULL ); + + /* Find network device */ + *netdev = find_netdev ( text ); + if ( ! *netdev ) { + printf ( "\"%s\": no such network device\n", text ); + return -ENODEV; + } + + return 0; +} + +/** + * Parse network device configurator name + * + * @v text Text + * @ret configurator Network device configurator + * @ret rc Return status code + */ +int parse_netdev_configurator ( char *text, + struct net_device_configurator **configurator ){ + + /* Sanity check */ + assert ( text != NULL ); + + /* Find network device configurator */ + *configurator = find_netdev_configurator ( text ); + if ( ! *configurator ) { + printf ( "\"%s\": no such configurator\n", text ); + return -ENOTSUP; + } + + return 0; +} + +/** + * Parse menu name + * + * @v text Text + * @ret menu Menu + * @ret rc Return status code + */ +int parse_menu ( char *text, struct menu **menu ) { + + /* Find menu */ + *menu = find_menu ( text ); + if ( ! *menu ) { + if ( text ) { + printf ( "\"%s\": no such menu\n", text ); + } else { + printf ( "No default menu\n" ); + } + return -ENOENT; + } + + return 0; +} + +/** + * Parse flag + * + * @v text Text (ignored) + * @ret flag Flag to set + * @ret rc Return status code + */ +int parse_flag ( char *text __unused, int *flag ) { + + /* Set flag */ + *flag = 1; + + return 0; +} + +/** + * Parse key + * + * @v text Text + * @ret key Key + * @ret rc Return status code + */ +int parse_key ( char *text, unsigned int *key ) { + + /* Interpret single characters as being a literal key character */ + if ( text[0] && ! text[1] ) { + *key = text[0]; + return 0; + } + + /* Otherwise, interpret as an integer */ + return parse_integer ( text, key ); +} + +/** + * Parse settings block name + * + * @v text Text + * @ret value Integer value + * @ret rc Return status code + */ +int parse_settings ( char *text, struct settings **value ) { + + /* Sanity check */ + assert ( text != NULL ); + + /* Parse scope name */ + *value = find_settings ( text ); + if ( ! *value ) { + printf ( "\"%s\": no such scope\n", text ); + return -EINVAL; + } + + return 0; +} + +/** + * Parse setting name + * + * @v text Text + * @v setting Named setting to fill in + * @v get_child Function to find or create child settings block + * @ret rc Return status code + * + * Note that this function modifies the original @c text. + */ +int parse_setting ( char *text, struct named_setting *setting, + get_child_settings_t get_child ) { + int rc; + + /* Sanity check */ + assert ( text != NULL ); + + /* Parse setting name */ + if ( ( rc = parse_setting_name ( text, get_child, &setting->settings, + &setting->setting ) ) != 0 ) { + printf ( "\"%s\": invalid setting\n", text ); + return rc; + } + + return 0; +} + +/** + * Parse existing setting name + * + * @v text Text + * @v setting Named setting to fill in + * @ret rc Return status code + * + * Note that this function modifies the original @c text. + */ +int parse_existing_setting ( char *text, struct named_setting *setting ) { + + return parse_setting ( text, setting, find_child_settings ); +} + +/** + * Parse and autovivify setting name + * + * @v text Text + * @v setting Named setting to fill in + * @ret rc Return status code + * + * Note that this function modifies the original @c text. + */ +int parse_autovivified_setting ( char *text, struct named_setting *setting ) { + + return parse_setting ( text, setting, autovivify_child_settings ); +} + +/** + * Parse form parameter list name + * + * @v text Text + * @ret params Parameter list + * @ret rc Return status code + */ +int parse_parameters ( char *text, struct parameters **params ) { + + /* Find parameter list */ + *params = find_parameters ( text ); + if ( ! *params ) { + if ( text ) { + printf ( "\"%s\": no such parameter list\n", text ); + } else { + printf ( "No default parameter list\n" ); + } + return -ENOENT; + } + + return 0; +} + +/** + * Print command usage message + * + * @v cmd Command descriptor + * @v argv Argument list + */ +void print_usage ( struct command_descriptor *cmd, char **argv ) { + struct option_descriptor *option; + unsigned int i; + int is_optional; + + printf ( "Usage:\n\n %s", argv[0] ); + for ( i = 0 ; i < cmd->num_options ; i++ ) { + option = &cmd->options[i]; + printf ( " [-%c|--%s", option->shortopt, option->longopt ); + if ( option->has_arg ) { + is_optional = ( option->has_arg == optional_argument ); + printf ( " %s<%s>%s", ( is_optional ? "[" : "" ), + option->longopt, ( is_optional ? "]" : "" ) ); + } + printf ( "]" ); + } + if ( cmd->usage ) + printf ( " %s", cmd->usage ); + printf ( "\n\nSee http://ipxe.org/cmd/%s for further information\n", + argv[0] ); +} + +/** + * Reparse command-line options + * + * @v argc Argument count + * @v argv Argument list + * @v cmd Command descriptor + * @v opts Options (already initialised with default values) + * @ret rc Return status code + */ +int reparse_options ( int argc, char **argv, struct command_descriptor *cmd, + void *opts ) { + struct option longopts[ cmd->num_options + 1 /* help */ + 1 /* end */ ]; + char shortopts[ cmd->num_options * 3 /* possible "::" */ + 1 /* "h" */ + + 1 /* NUL */ ]; + unsigned int shortopt_idx = 0; + int ( * parse ) ( char *text, void *value ); + void *value; + unsigned int i; + unsigned int j; + unsigned int num_args; + int c; + int rc; + + /* Construct long and short option lists for getopt_long() */ + memset ( longopts, 0, sizeof ( longopts ) ); + for ( i = 0 ; i < cmd->num_options ; i++ ) { + longopts[i].name = cmd->options[i].longopt; + longopts[i].has_arg = cmd->options[i].has_arg; + longopts[i].val = cmd->options[i].shortopt; + shortopts[shortopt_idx++] = cmd->options[i].shortopt; + assert ( cmd->options[i].has_arg <= optional_argument ); + for ( j = cmd->options[i].has_arg ; j > 0 ; j-- ) + shortopts[shortopt_idx++] = ':'; + } + longopts[i].name = "help"; + longopts[i].val = 'h'; + shortopts[shortopt_idx++] = 'h'; + shortopts[shortopt_idx++] = '\0'; + assert ( shortopt_idx <= sizeof ( shortopts ) ); + DBGC ( cmd, "Command \"%s\" has options \"%s\", %d-%d args, len %d\n", + argv[0], shortopts, cmd->min_args, cmd->max_args, cmd->len ); + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, shortopts, longopts, + NULL ) ) >= 0 ) { + switch ( c ) { + case 'h' : + /* Print help */ + print_usage ( cmd, argv ); + return -ECANCELED_NO_OP; + case '?' : + /* Print usage message */ + print_usage ( cmd, argv ); + return -EINVAL_UNKNOWN_OPTION; + case ':' : + /* Print usage message */ + print_usage ( cmd, argv ); + return -EINVAL_MISSING_ARGUMENT; + default: + /* Search for an option to parse */ + for ( i = 0 ; i < cmd->num_options ; i++ ) { + if ( c != cmd->options[i].shortopt ) + continue; + parse = cmd->options[i].parse; + value = ( opts + cmd->options[i].offset ); + if ( ( rc = parse ( optarg, value ) ) != 0 ) + return rc; + break; + } + assert ( i < cmd->num_options ); + } + } + + /* Check remaining arguments */ + num_args = ( argc - optind ); + if ( ( num_args < cmd->min_args ) || ( num_args > cmd->max_args ) ) { + print_usage ( cmd, argv ); + return -ERANGE; + } + + return 0; +} + +/** + * Parse command-line options + * + * @v argc Argument count + * @v argv Argument list + * @v cmd Command descriptor + * @v opts Options (may be uninitialised) + * @ret rc Return status code + */ +int parse_options ( int argc, char **argv, struct command_descriptor *cmd, + void *opts ) { + + /* Clear options */ + memset ( opts, 0, cmd->len ); + + return reparse_options ( argc, argv, cmd, opts ); +} |