1
1
openmpi/opal/util/cmd_line.h
Nathan Hjelm 2acd0f83de Revert "Revert r27451 and r27456 - the cmd line parser is incorrectly marking the application as an MCA parameter".
It appears the problem was not with the command line parser but the rsh plm. I don't know why this problem was not occuring before the command line parser changes but it appears to be resolved now.

This commit was SVN r27527.

The following SVN revision numbers were found above:
  r27451 --> open-mpi/ompi@d59034e6ef
  r27456 --> open-mpi/ompi@ecdbf34937
2012-10-30 19:45:18 +00:00

575 строки
22 KiB
C

/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2012 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* @file
*
* General command line parsing facility for use throughout Open MPI.
*
* This scheme is inspired by the GNU getopt package. Command line
* options are registered. Each option can have up to three different
* matching tokens: a "short" name, a "single dash" name, and a "long"
* name. Each option can also take 0 or more arguments. Finally,
* each option can be repeated on the command line an arbitrary number
* of times.
*
* The "short" name can only be a single letter, and will be found
* after a single dash (e.g., "-a"). Multiple "short" names can be
* combined into a single command line argument (e.g., "-abc" can be
* equivalent to "-a -b -c").
*
* The "single dash" name is a multi-character name that only
* requires a single dash. This only exists to provide backwards
* compatibility for some well-known command line options in prior
* MPI implementations (e.g., "mpirun -np 3"). It should be used
* sparingly.
*
* The "long" name is a multi-character name that is found after a
* pair of dashes. For example, "--some-option-name".
*
* A command line option is a combination of 1 or more of a short
* name, single dash name, and a long name. Any of the names may be
* used on the command line; they are treated as synonyms. For
* example, say the following was used in for an executable named
* "foo":
*
* \code
* opal_cmd_line_make_opt3(cmd, 'a', NULL, 'add', 1, "Add a user");
* \endcode
*
* In this case, the following command lines are exactly equivalent:
*
* \verbatim
* shell$ foo -a jsmith
* shell$ foo --add jsmith
* \endverbatim
*
* Note that this interface can also track multiple invocations of the
* same option. For example, the following is both legal and able to
* be retrieved through this interface:
*
* \verbatim
* shell$ foo -a jsmith -add bjones
* \endverbatim
*
* The caller to this interface creates a command line handle
* (opal_cmd_line_t) with OBJ_NEW() and then uses it to register the
* desired parameters via opal_cmd_line_make_opt3(). Once all the
* parameters have been registered, the user invokes
* opal_cmd_line_parse() with the command line handle and the argv/argc
* pair to be parsed (typically the arguments from main()). The parser
* will examine the argv and find registered options and parameters.
* It will stop parsing when it runs into an recognized string token or
* the special "--" token.
*
* After the parse has occurred, various accessor functions can be
* used to determine which options were selected, what parameters were
* passed to them, etc.:
*
* - opal_cmd_line_get_usage_msg() returns a string suitable for "help"
* kinds of messages.
* - opal_cmd_line_is_taken() returns a true or false indicating
* whether a given command line option was found on the command
* line.
* - opal_cmd_line_get_argc() returns the number of tokens parsed on
* the handle.
* - opal_cmd_line_get_argv() returns any particular string from the
* original argv.
* - opal_cmd_line_get_ninsts() returns the number of times a
* particular option was found on a command line.
* - opal_cmd_line_get_param() returns the Nth parameter in the Mth
* instance of a given parameter.
* - opal_cmd_line_get_tail() returns an array of tokens not parsed
* (i.e., if the parser ran into "--" or an unrecognized token).
*
* Note that a shortcut to creating a large number of options exists
* -- one can make a table of opal_cmd_line_init_t instances and the
* table to opal_cmd_line_create(). This creates an opal_cmd_line_t
* handle that is pre-seeded with all the options from the table
* without the need to repeatedly invoke opal_cmd_line_make_opt3() (or
* equivalent). This opal_cmd_line_t instance is just like any other;
* it is still possible to add more options via
* opal_cmd_line_make_opt3(), etc.
*/
#ifndef OPAL_CMD_LINE_H
#define OPAL_CMD_LINE_H
#include "opal_config.h"
#include "opal/class/opal_object.h"
#include "opal/class/opal_list.h"
#include "opal/threads/mutex.h"
BEGIN_C_DECLS
/**
* \internal
*
* Main top-level handle. This interface should not be used by users!
*/
struct opal_cmd_line_t {
/** Make this an OBJ handle */
opal_object_t super;
/** Thread safety */
opal_mutex_t lcl_mutex;
/** List of cmd_line_option_t's (defined internally) */
opal_list_t lcl_options;
/** Duplicate of argc from opal_cmd_line_parse() */
int lcl_argc;
/** Duplicate of argv from opal_cmd_line_parse() */
char **lcl_argv;
/** Parsed output; list of cmd_line_param_t's (defined internally) */
opal_list_t lcl_params;
/** List of tail (unprocessed) arguments */
int lcl_tail_argc;
/** List of tail (unprocessed) arguments */
char **lcl_tail_argv;
};
/**
* \internal
*
* Convenience typedef
*/
typedef struct opal_cmd_line_t opal_cmd_line_t;
/**
* Data types supported by the parser
*/
enum opal_cmd_line_type_t {
OPAL_CMD_LINE_TYPE_NULL,
OPAL_CMD_LINE_TYPE_STRING,
OPAL_CMD_LINE_TYPE_INT,
OPAL_CMD_LINE_TYPE_SIZE_T,
OPAL_CMD_LINE_TYPE_BOOL,
OPAL_CMD_LINE_TYPE_MAX
};
/**
* \internal
*
* Convenience typedef
*/
typedef enum opal_cmd_line_type_t opal_cmd_line_type_t;
/**
* Datatype used to construct a command line handle; see
* opal_cmd_line_create().
*/
struct opal_cmd_line_init_t {
/** If want to set an MCA parameter, set its parameter name
here. */
const char *ocl_mca_param_name;
/** "Short" name (i.e., "-X", where "X" is a single letter) */
char ocl_cmd_short_name;
/** "Single dash" name (i.e., "-foo"). The use of these are
discouraged. */
const char *ocl_cmd_single_dash_name;
/** Long name (i.e., "--foo"). */
const char *ocl_cmd_long_name;
/** Number of parameters that this option takes */
int ocl_num_params;
/** If this parameter is encountered, its *first* parameter it
saved here. If the parameter is encountered again, the
value is overwritten. */
void *ocl_variable_dest;
/** If an ocl_variable_dest is given, its datatype must be
supplied as well. */
opal_cmd_line_type_t ocl_variable_type;
/** Description of the command line option, to be used with
opal_cmd_line_get_usage_msg(). */
const char *ocl_description;
};
/**
* \internal
*
* Convenience typedef
*/
typedef struct opal_cmd_line_init_t opal_cmd_line_init_t;
/**
* Top-level command line handle.
*
* This handle is used for accessing all command line functionality
* (i.e., all opal_cmd_line*() functions). Multiple handles can be
* created and simultaneously processed; each handle is independant
* from others.
*
* The opal_cmd_line_t handles are [simplisticly] thread safe;
* processing is guaranteed to be mutually exclusive if multiple
* threads invoke functions on the same handle at the same time --
* access will be serialized in an unspecified order.
*
* Once finished, handles should be released with OBJ_RELEASE(). The
* destructor for opal_cmd_line_t handles will free all memory
* associated with the handle.
*/
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_cmd_line_t);
/**
* Make a command line handle from a table of initializers.
*
* @param cmd OPAL command line handle.
* @param table Table of opal_cmd_line_init_t instances for all
* the options to be included in the resulting command line
* handler.
*
* @retval OPAL_SUCCESS Upon success.
*
* This function takes a table of opal_cmd_line_init_t instances
* to pre-seed an OPAL command line handle. The last instance in
* the table must have '\0' for the short name and NULL for the
* single-dash and long names. The handle is expected to have
* been OBJ_NEW'ed or OBJ_CONSTRUCT'ed already.
*
* Upon return, the command line handle is just like any other. A
* sample using this syntax:
*
* \code
* opal_cmd_line_init_t cmd_line_init[] = {
* { NULL, NULL, NULL, 'h', NULL, "help", 0,
* &orterun_globals.help, OPAL_CMD_LINE_TYPE_BOOL,
* "This help message" },
*
* { NULL, NULL, NULL, '\0', NULL, "wd", 1,
* &orterun_globals.wd, OPAL_CMD_LINE_TYPE_STRING,
* "Set the working directory of the started processes" },
*
* { NULL, NULL, NULL, '\0', NULL, NULL, 0,
* NULL, OPAL_CMD_LINE_TYPE_NULL, NULL }
* };
* \endcode
*/
OPAL_DECLSPEC int opal_cmd_line_create(opal_cmd_line_t *cmd,
opal_cmd_line_init_t *table);
/**
* Create a command line option.
*
* @param cmd OPAL command line handle.
* @param entry Command line entry to add to the command line.
*
* @retval OPAL_SUCCESS Upon success.
*
*/
OPAL_DECLSPEC int opal_cmd_line_make_opt_mca(opal_cmd_line_t *cmd,
opal_cmd_line_init_t entry);
/**
* Create a command line option.
*
* @param cmd OPAL command line handle.
* @param short_name "Short" name of the command line option.
* @param sd_name "Single dash" name of the command line option.
* @param long_name "Long" name of the command line option.
* @param num_params How many parameters this option takes.
* @param dest Short string description of this option.
*
* @retval OPAL_ERR_OUT_OF_RESOURCE If out of memory.
* @retval OPAL_ERR_BAD_PARAM If bad parameters passed.
* @retval OPAL_SUCCESS Upon success.
*
* Adds a command line option to the list of options that an OPAL
* command line handle will accept. The short_name may take the
* special value '\0' to not have a short name. Likewise, the
* sd_name and long_name may take the special value NULL to not have
* a single dash or long name, respectively. However, one of the
* three must have a name.
*
* num_params indicates how many parameters this option takes. It
* must be greater than or equal to 0.
*
* Finally, desc is a short string description of this option. It is
* used to generate the output from opal_cmd_line_get_usage_msg().
*
*/
OPAL_DECLSPEC int opal_cmd_line_make_opt3(opal_cmd_line_t *cmd,
char short_name,
const char *sd_name,
const char *long_name,
int num_params,
const char *desc);
/**
* Parse a command line according to a pre-built OPAL command line
* handle.
*
* @param cmd OPAL command line handle.
* @param ignore_unknown Whether to print an error message upon
* finding an unknown token or not
* @param argc Length of the argv array.
* @param argv Array of strings from the command line.
*
* @retval OPAL_SUCCESS Upon success.
* @retval OPAL_ERR_SILENT If an error message was printed. This
* value will only be returned if the command line was not
* successfully parsed.
*
* Parse a series of command line tokens according to the option
* descriptions from a OPAL command line handle. The OPAL command line
* handle can then be queried to see what options were used, what
* their parameters were, etc.
*
* If an unknown token is found in the command line (i.e., a token
* that is not a parameter or a registered option), the parsing will
* stop (see below). If ignore_unknown is false, an error message
* is displayed. If ignore_unknown is true, the error message is
* not displayed.
*
* Error messages are always displayed regardless of the value
* of ignore_unknown (to stderr, and OPAL_ERR_SILENT is
* returned) if:
*
* 1. A token was encountered that required N parameters, but <N
* parameters were found (e.g., "cmd --param foo", but --param was
* registered to require 2 option tokens).
*
* 2. An unknown token beginning with "-" is encountered. For
* example, if "--fo" is specified, and no "fo" option is
* registered (e.g., perhaps the user meant to type "--foo"), an
* error message is always printed, UNLESS this unknown token
* happens after a "--" token (see below).
*
* The contents of argc and argv are not changed during parsing.
* argv[0] is assumed to be the executable name, and is ignored during
* parsing, except when printing error messages.
*
* Parsing will stop in the following conditions:
*
* - all argv tokens are processed
* - the token "--" is found
* - an unrecognized token is found
* - a parameter registered with an integer type option finds a
* non-integer option token
* - a parameted registered N option tokens, but finds less then
* <N tokens available
*
* Upon any of these conditions, any remaining tokens will be placed
* in the "tail" (and therefore not examined by the parser),
* regardless of the value of ignore_unknown. The set of tail
* tokens is available from the opal_cmd_line_get_tail() function.
*
* Note that "--" is ignored if it is found in the middle an expected
* number of arguments. For example, if "--foo" is expected to have 3
* arguments, and the command line is:
*
* executable --foo a b -- other arguments
*
* This will result in an error, because "--" will be parsed as the
* third parameter to the first instance of "foo", and "other" will be
* an unrecognized option.
*
* Note that -- can be used to allow unknown tokens that begin
* with "-". For example, if a user wants to mpirun an executable
* named "-my-mpi-program", the "usual" way:
*
* mpirun -my-mpi-program
*
* will cause an error, because mpirun won't find single-letter
* options registered for some/all of those letters. But two
* workarounds are possible:
*
* mpirun -- -my-mpi-program
* or
* mpirun ./-my-mpi-program
*
* Finally, note that invoking this function multiple times on
* different sets of argv tokens is safe, but will erase any
* previous parsing results.
*/
OPAL_DECLSPEC int opal_cmd_line_parse(opal_cmd_line_t *cmd,
bool ignore_unknown,
int argc, char **argv);
/**
* Return a consolidated "usage" message for a OPAL command line handle.
*
* @param cmd OPAL command line handle.
*
* @retval str Usage message.
*
* Returns a formatted string suitable for printing that lists the
* expected usage message and a short description of each option on
* the OPAL command line handle. Options that passed a NULL
* description to opal_cmd_line_make_opt3() will not be included in the
* display (to allow for undocumented options).
*
* This function is typically only invoked internally by the
* opal_show_help() function.
*
* This function should probably be fixed up to produce prettier
* output.
*
* The returned string must be freed by the caller.
*/
OPAL_DECLSPEC char *opal_cmd_line_get_usage_msg(opal_cmd_line_t *cmd) __opal_attribute_malloc__ __opal_attribute_warn_unused_result__;
/**
* Test if a given option was taken on the parsed command line.
*
* @param cmd OPAL command line handle.
* @param opt Short or long name of the option to check for.
*
* @retval true If the command line option was found during
* opal_cmd_line_parse().
*
* @retval false If the command line option was not found during
* opal_cmd_line_parse(), or opal_cmd_line_parse() was not invoked on
* this handle.
*
* This function should only be called after opal_cmd_line_parse().
*
* The function will return true if the option matching opt was found
* (either by its short or long name) during token parsing.
* Otherwise, it will return false.
*/
OPAL_DECLSPEC bool opal_cmd_line_is_taken(opal_cmd_line_t *cmd,
const char *opt) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2);
/**
* Return the number of arguments parsed on a OPAL command line handle.
*
* @param cmd A pointer to the OPAL command line handle.
*
* @retval OPAL_ERROR If cmd is NULL.
* @retval argc Number of arguments previously added to the handle.
*
* Arguments are added to the handle via the opal_cmd_line_parse()
* function.
*/
OPAL_DECLSPEC int opal_cmd_line_get_argc(opal_cmd_line_t *cmd) __opal_attribute_unused__;
/**
* Return a string argument parsed on a OPAL command line handle.
*
* @param cmd A pointer to the OPAL command line handle.
* @param index The nth argument from the command line (0 is
* argv[0], etc.).
*
* @retval NULL If cmd is NULL or index is invalid
* @retval argument String of original argv[index]
*
* This function returns a single token from the arguments parsed
* on this handle. Arguments are added bia the
* opal_cmd_line_parse() function.
*
* What is returned is a pointer to the actual string that is on
* the handle; it should not be modified or freed.
*/
OPAL_DECLSPEC char *opal_cmd_line_get_argv(opal_cmd_line_t *cmd,
int index);
/**
* Return the number of instances of an option found during parsing.
*
* @param cmd OPAL command line handle.
* @param opt Short or long name of the option to check for.
*
* @retval num Number of instances (to include 0) of a given potion
* found during opal_cmd_line_parse().
*
* @retval OPAL_ERR If the command line option was not found during
* opal_cmd_line_parse(), or opal_cmd_line_parse() was not invoked on
* this handle.
*
* This function should only be called after opal_cmd_line_parse().
*
* The function will return the number of instances of a given option
* (either by its short or long name) -- to include 0 -- or OPAL_ERR if
* either the option was not specified as part of the OPAL command line
* handle, or opal_cmd_line_parse() was not invoked on this handle.
*/
OPAL_DECLSPEC int opal_cmd_line_get_ninsts(opal_cmd_line_t *cmd,
const char *opt) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2);
/**
* Return a specific parameter for a specific instance of a option
* from the parsed command line.
*
* @param cmd OPAL command line handle.
* @param opt Short or long name of the option to check for.
* @param instance_num Instance number of the option to query.
* @param param_num Which parameter to return.
*
* @retval param String of the parameter.
* @retval NULL If any of the input values are invalid.
*
* This function should only be called after opal_cmd_line_parse().
*
* This function returns the Nth parameter for the Ith instance of a
* given option on the parsed command line (both N and I are
* zero-indexed). For example, on the command line:
*
* executable --foo bar1 bar2 --foo bar3 bar4
*
* The call to opal_cmd_line_get_param(cmd, "foo", 1, 1) would return
* "bar4". opal_cmd_line_get_param(cmd, "bar", 0, 0) would return
* NULL, as would opal_cmd_line_get_param(cmd, "foo", 2, 2);
*
* The returned string should \em not be modified or freed by the
* caller.
*/
OPAL_DECLSPEC char *opal_cmd_line_get_param(opal_cmd_line_t *cmd,
const char *opt,
int instance_num,
int param_num);
/**
* Return the entire "tail" of unprocessed argv from a OPAL
* command line handle.
*
* @param cmd A pointer to the OPAL command line handle.
* @param tailc Pointer to the output length of the null-terminated
* tail argv array.
* @param tailv Pointer to the output null-terminated argv of all
* unprocessed arguments from the command line.
*
* @retval OPAL_ERROR If cmd is NULL or otherwise invalid.
* @retval OPAL_SUCCESS Upon success.
*
* The "tail" is all the arguments on the command line that were
* not processed for some reason. Reasons for not processing
* arguments include:
*
* \sa The argument was not recognized
* \sa The argument "--" was seen, and therefore all arguments
* following it were not processed
*
* The output tailc parameter will be filled in with the integer
* length of the null-terminated tailv array (length including the
* final NULL entry). The output tailv parameter will be a copy
* of the tail parameters, and must be freed (likely with a call
* to opal_argv_free()) by the caller.
*/
OPAL_DECLSPEC int opal_cmd_line_get_tail(opal_cmd_line_t *cmd, int *tailc,
char ***tailv) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2);
END_C_DECLS
#endif /* OPAL_CMD_LINE_H */