1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ 2 /* 3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana 4 * University Research and Technology 5 * Corporation. All rights reserved. 6 * Copyright (c) 2004-2005 The University of Tennessee and The University 7 * of Tennessee Research Foundation. All rights 8 * reserved. 9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 10 * University of Stuttgart. All rights reserved. 11 * Copyright (c) 2004-2005 The Regents of the University of California. 12 * All rights reserved. 13 * Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. 14 * Copyright (c) 2015-2016 Intel, Inc. All rights reserved. 15 * Copyright (c) 2016-2017 Los Alamos National Security, LLC. All rights 16 * reserved. 17 * Copyright (c) 2017 IBM Corporation. All rights reserved. 18 * $COPYRIGHT$ 19 * 20 * Additional copyrights may follow 21 * 22 * $HEADER$ 23 */ 24 25 /** 26 * @file 27 * 28 * General command line parsing facility for use throughout Open MPI. 29 * 30 * This scheme is inspired by the GNU getopt package. Command line 31 * options are registered. Each option can have up to three different 32 * matching tokens: a "short" name, a "single dash" name, and a "long" 33 * name. Each option can also take 0 or more arguments. Finally, 34 * each option can be repeated on the command line an arbitrary number 35 * of times. 36 * 37 * The "short" name can only be a single letter, and will be found 38 * after a single dash (e.g., "-a"). Multiple "short" names can be 39 * combined into a single command line argument (e.g., "-abc" can be 40 * equivalent to "-a -b -c"). 41 * 42 * The "single dash" name is a multi-character name that only 43 * requires a single dash. This only exists to provide backwards 44 * compatibility for some well-known command line options in prior 45 * MPI implementations (e.g., "mpirun -np 3"). It should be used 46 * sparingly. 47 * 48 * The "long" name is a multi-character name that is found after a 49 * pair of dashes. For example, "--some-option-name". 50 * 51 * A command line option is a combination of 1 or more of a short 52 * name, single dash name, and a long name. Any of the names may be 53 * used on the command line; they are treated as synonyms. For 54 * example, say the following was used in for an executable named 55 * "foo": 56 * 57 * \code 58 * opal_cmd_line_make_opt3(cmd, 'a', NULL, 'add', 1, "Add a user"); 59 * \endcode 60 * 61 * In this case, the following command lines are exactly equivalent: 62 * 63 * \verbatim 64 * shell$ foo -a jsmith 65 * shell$ foo --add jsmith 66 * \endverbatim 67 * 68 * Note that this interface can also track multiple invocations of the 69 * same option. For example, the following is both legal and able to 70 * be retrieved through this interface: 71 * 72 * \verbatim 73 * shell$ foo -a jsmith -add bjones 74 * \endverbatim 75 * 76 * The caller to this interface creates a command line handle 77 * (opal_cmd_line_t) with OBJ_NEW() and then uses it to register the 78 * desired parameters via opal_cmd_line_make_opt3(). Once all the 79 * parameters have been registered, the user invokes 80 * opal_cmd_line_parse() with the command line handle and the argv/argc 81 * pair to be parsed (typically the arguments from main()). The parser 82 * will examine the argv and find registered options and parameters. 83 * It will stop parsing when it runs into an recognized string token or 84 * the special "--" token. 85 * 86 * After the parse has occurred, various accessor functions can be 87 * used to determine which options were selected, what parameters were 88 * passed to them, etc.: 89 * 90 * - opal_cmd_line_get_usage_msg() returns a string suitable for "help" 91 * kinds of messages. 92 * - opal_cmd_line_is_taken() returns a true or false indicating 93 * whether a given command line option was found on the command 94 * line. 95 * - opal_cmd_line_get_argc() returns the number of tokens parsed on 96 * the handle. 97 * - opal_cmd_line_get_argv() returns any particular string from the 98 * original argv. 99 * - opal_cmd_line_get_ninsts() returns the number of times a 100 * particular option was found on a command line. 101 * - opal_cmd_line_get_param() returns the Nth parameter in the Mth 102 * instance of a given parameter. 103 * - opal_cmd_line_get_tail() returns an array of tokens not parsed 104 * (i.e., if the parser ran into "--" or an unrecognized token). 105 * 106 * Note that a shortcut to creating a large number of options exists 107 * -- one can make a table of opal_cmd_line_init_t instances and the 108 * table to opal_cmd_line_create(). This creates an opal_cmd_line_t 109 * handle that is pre-seeded with all the options from the table 110 * without the need to repeatedly invoke opal_cmd_line_make_opt3() (or 111 * equivalent). This opal_cmd_line_t instance is just like any other; 112 * it is still possible to add more options via 113 * opal_cmd_line_make_opt3(), etc. 114 */ 115 116 #ifndef OPAL_CMD_LINE_H 117 #define OPAL_CMD_LINE_H 118 119 #include "opal_config.h" 120 121 #include "opal/class/opal_object.h" 122 #include "opal/class/opal_list.h" 123 #include "opal/threads/mutex.h" 124 125 BEGIN_C_DECLS 126 /** 127 * \internal 128 * 129 * Main top-level handle. This interface should not be used by users! 130 */ 131 struct opal_cmd_line_t { 132 /** Make this an OBJ handle */ 133 opal_object_t super; 134 135 /** Thread safety */ 136 opal_recursive_mutex_t lcl_mutex; 137 138 /** List of ompi_cmd_line_option_t's (defined internally) */ 139 opal_list_t lcl_options; 140 141 /** Duplicate of argc from opal_cmd_line_parse() */ 142 int lcl_argc; 143 /** Duplicate of argv from opal_cmd_line_parse() */ 144 char **lcl_argv; 145 146 /** Parsed output; list of ompi_cmd_line_param_t's (defined internally) */ 147 opal_list_t lcl_params; 148 149 /** List of tail (unprocessed) arguments */ 150 int lcl_tail_argc; 151 /** List of tail (unprocessed) arguments */ 152 char **lcl_tail_argv; 153 }; 154 /** 155 * \internal 156 * 157 * Convenience typedef 158 */ 159 typedef struct opal_cmd_line_t opal_cmd_line_t; 160 161 /** 162 * Data types supported by the parser 163 */ 164 enum opal_cmd_line_type_t { 165 OPAL_CMD_LINE_TYPE_NULL, 166 OPAL_CMD_LINE_TYPE_STRING, 167 OPAL_CMD_LINE_TYPE_INT, 168 OPAL_CMD_LINE_TYPE_SIZE_T, 169 OPAL_CMD_LINE_TYPE_BOOL, 170 171 OPAL_CMD_LINE_TYPE_MAX 172 }; 173 /** 174 * \internal 175 * 176 * Convenience typedef 177 */ 178 typedef enum opal_cmd_line_type_t opal_cmd_line_type_t; 179 180 /** 181 * Command line option type, for use in 182 * mpirun --help output. 183 */ 184 enum opal_cmd_line_otype_t { 185 OPAL_CMD_LINE_OTYPE_GENERAL, 186 OPAL_CMD_LINE_OTYPE_DEBUG, 187 OPAL_CMD_LINE_OTYPE_OUTPUT, 188 OPAL_CMD_LINE_OTYPE_INPUT, 189 OPAL_CMD_LINE_OTYPE_MAPPING, 190 OPAL_CMD_LINE_OTYPE_RANKING, 191 OPAL_CMD_LINE_OTYPE_BINDING, 192 OPAL_CMD_LINE_OTYPE_DEVEL, 193 OPAL_CMD_LINE_OTYPE_COMPAT, /* Backwards compatibility */ 194 OPAL_CMD_LINE_OTYPE_LAUNCH, 195 OPAL_CMD_LINE_OTYPE_DVM, 196 OPAL_CMD_LINE_OTYPE_UNSUPPORTED, 197 OPAL_CMD_LINE_OTYPE_PARSABLE, 198 OPAL_CMD_LINE_OTYPE_NULL 199 }; 200 /** 201 * \internal 202 * 203 * Convenience typedef 204 */ 205 typedef enum opal_cmd_line_otype_t opal_cmd_line_otype_t; 206 207 /** 208 * Datatype used to construct a command line handle; see 209 * opal_cmd_line_create(). 210 */ 211 struct opal_cmd_line_init_t { 212 /** If want to set an MCA parameter, set its parameter name 213 here. */ 214 const char *ocl_mca_param_name; 215 216 /** "Short" name (i.e., "-X", where "X" is a single letter) */ 217 char ocl_cmd_short_name; 218 /** "Single dash" name (i.e., "-foo"). The use of these are 219 discouraged. */ 220 const char *ocl_cmd_single_dash_name; 221 /** Long name (i.e., "--foo"). */ 222 const char *ocl_cmd_long_name; 223 224 /** Number of parameters that this option takes */ 225 int ocl_num_params; 226 227 /** If this parameter is encountered, its *first* parameter it 228 saved here. If the parameter is encountered again, the 229 value is overwritten. */ 230 void *ocl_variable_dest; 231 /** If an ocl_variable_dest is given, its datatype must be 232 supplied as well. */ 233 opal_cmd_line_type_t ocl_variable_type; 234 235 /** Description of the command line option, to be used with 236 opal_cmd_line_get_usage_msg(). */ 237 const char *ocl_description; 238 239 /** Category for mpirun --help output */ 240 opal_cmd_line_otype_t ocl_otype; 241 }; 242 /** 243 * \internal 244 * 245 * Convenience typedef 246 */ 247 typedef struct opal_cmd_line_init_t opal_cmd_line_init_t; 248 249 /** 250 * Top-level command line handle. 251 * 252 * This handle is used for accessing all command line functionality 253 * (i.e., all opal_cmd_line*() functions). Multiple handles can be 254 * created and simultaneously processed; each handle is independant 255 * from others. 256 * 257 * The opal_cmd_line_t handles are [simplisticly] thread safe; 258 * processing is guaranteed to be mutually exclusive if multiple 259 * threads invoke functions on the same handle at the same time -- 260 * access will be serialized in an unspecified order. 261 * 262 * Once finished, handles should be released with OBJ_RELEASE(). The 263 * destructor for opal_cmd_line_t handles will free all memory 264 * associated with the handle. 265 */ 266 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_cmd_line_t); 267 268 /** 269 * Make a command line handle from a table of initializers. 270 * 271 * @param cmd OPAL command line handle. 272 * @param table Table of opal_cmd_line_init_t instances for all 273 * the options to be included in the resulting command line 274 * handler. 275 * 276 * @retval OPAL_SUCCESS Upon success. 277 * 278 * This function takes a table of opal_cmd_line_init_t instances 279 * to pre-seed an OPAL command line handle. The last instance in 280 * the table must have '\0' for the short name and NULL for the 281 * single-dash and long names. The handle is expected to have 282 * been OBJ_NEW'ed or OBJ_CONSTRUCT'ed already. 283 * 284 * Upon return, the command line handle is just like any other. A 285 * sample using this syntax: 286 * 287 * \code 288 * opal_cmd_line_init_t cmd_line_init[] = { 289 * { NULL, NULL, NULL, 'h', NULL, "help", 0, 290 * &orterun_globals.help, OPAL_CMD_LINE_TYPE_BOOL, 291 * "This help message" }, 292 * 293 * { NULL, NULL, NULL, '\0', NULL, "wd", 1, 294 * &orterun_globals.wd, OPAL_CMD_LINE_TYPE_STRING, 295 * "Set the working directory of the started processes" }, 296 * 297 * { NULL, NULL, NULL, '\0', NULL, NULL, 0, 298 * NULL, OPAL_CMD_LINE_TYPE_NULL, NULL } 299 * }; 300 * \endcode 301 */ 302 OPAL_DECLSPEC int opal_cmd_line_create(opal_cmd_line_t *cmd, 303 opal_cmd_line_init_t *table); 304 305 /* Add a table of opal_cmd_line_init_t instances 306 * to an existing OPAL command line handle. 307 * 308 * Multiple calls to opal_cmd_line_add are permitted - each 309 * subsequent call will simply append new options to the existing 310 * handle. Note that any duplicates will return an error. 311 */ 312 OPAL_DECLSPEC int opal_cmd_line_add(opal_cmd_line_t *cmd, 313 opal_cmd_line_init_t *table); 314 315 /** 316 * Create a command line option. 317 * 318 * @param cmd OPAL command line handle. 319 * @param entry Command line entry to add to the command line. 320 * 321 * @retval OPAL_SUCCESS Upon success. 322 * 323 */ 324 OPAL_DECLSPEC int opal_cmd_line_make_opt_mca(opal_cmd_line_t *cmd, 325 opal_cmd_line_init_t entry); 326 327 /** 328 * Create a command line option. 329 * 330 * @param cmd OPAL command line handle. 331 * @param short_name "Short" name of the command line option. 332 * @param sd_name "Single dash" name of the command line option. 333 * @param long_name "Long" name of the command line option. 334 * @param num_params How many parameters this option takes. 335 * @param dest Short string description of this option. 336 * 337 * @retval OPAL_ERR_OUT_OF_RESOURCE If out of memory. 338 * @retval OPAL_ERR_BAD_PARAM If bad parameters passed. 339 * @retval OPAL_SUCCESS Upon success. 340 * 341 * Adds a command line option to the list of options that an OPAL 342 * command line handle will accept. The short_name may take the 343 * special value '\0' to not have a short name. Likewise, the 344 * sd_name and long_name may take the special value NULL to not have 345 * a single dash or long name, respectively. However, one of the 346 * three must have a name. 347 * 348 * num_params indicates how many parameters this option takes. It 349 * must be greater than or equal to 0. 350 * 351 * Finally, desc is a short string description of this option. It is 352 * used to generate the output from opal_cmd_line_get_usage_msg(). 353 * 354 */ 355 OPAL_DECLSPEC int opal_cmd_line_make_opt3(opal_cmd_line_t *cmd, 356 char short_name, 357 const char *sd_name, 358 const char *long_name, 359 int num_params, 360 const char *desc); 361 362 /** 363 * Parse a command line according to a pre-built OPAL command line 364 * handle. 365 * 366 * @param cmd OPAL command line handle. 367 * @param ignore_unknown Whether to print an error message upon 368 * finding an unknown token or not 369 * @param ignore_unknown_option Whether to print an error message upon 370 * finding an unknown option or not 371 * @param argc Length of the argv array. 372 * @param argv Array of strings from the command line. 373 * 374 * @retval OPAL_SUCCESS Upon success. 375 * @retval OPAL_ERR_SILENT If an error message was printed. This 376 * value will only be returned if the command line was not 377 * successfully parsed. 378 * 379 * Parse a series of command line tokens according to the option 380 * descriptions from a OPAL command line handle. The OPAL command line 381 * handle can then be queried to see what options were used, what 382 * their parameters were, etc. 383 * 384 * If an unknown token is found in the command line (i.e., a token 385 * that is not a parameter or a registered option), the parsing will 386 * stop (see below). If ignore_unknown is false, an error message 387 * is displayed. If ignore_unknown is true, the error message is 388 * not displayed. 389 * 390 * Error messages are always displayed regardless of the value 391 * of ignore_unknown (to stderr, and OPAL_ERR_SILENT is 392 * returned) if: 393 * 394 * 1. A token was encountered that required N parameters, but <N 395 * parameters were found (e.g., "cmd --param foo", but --param was 396 * registered to require 2 option tokens). 397 * 398 * 2. An unknown token beginning with "-" is encountered. For 399 * example, if "--fo" is specified, and no "fo" option is 400 * registered (e.g., perhaps the user meant to type "--foo"), an 401 * error message is always printed, UNLESS this unknown token 402 * happens after a "--" token (see below). 403 * 404 * The contents of argc and argv are not changed during parsing. 405 * argv[0] is assumed to be the executable name, and is ignored during 406 * parsing, except when printing error messages. 407 * 408 * Parsing will stop in the following conditions: 409 * 410 * - all argv tokens are processed 411 * - the token "--" is found 412 * - an unrecognized token is found 413 * - a parameter registered with an integer type option finds a 414 * non-integer option token 415 * - a parameted registered N option tokens, but finds less then 416 * <N tokens available 417 * 418 * Upon any of these conditions, any remaining tokens will be placed 419 * in the "tail" (and therefore not examined by the parser), 420 * regardless of the value of ignore_unknown. The set of tail 421 * tokens is available from the opal_cmd_line_get_tail() function. 422 * 423 * Note that "--" is ignored if it is found in the middle an expected 424 * number of arguments. For example, if "--foo" is expected to have 3 425 * arguments, and the command line is: 426 * 427 * executable --foo a b -- other arguments 428 * 429 * This will result in an error, because "--" will be parsed as the 430 * third parameter to the first instance of "foo", and "other" will be 431 * an unrecognized option. 432 * 433 * Note that -- can be used to allow unknown tokens that begin 434 * with "-". For example, if a user wants to mpirun an executable 435 * named "-my-mpi-program", the "usual" way: 436 * 437 * mpirun -my-mpi-program 438 * 439 * will cause an error, because mpirun won't find single-letter 440 * options registered for some/all of those letters. But two 441 * workarounds are possible: 442 * 443 * mpirun -- -my-mpi-program 444 * or 445 * mpirun ./-my-mpi-program 446 * 447 * Finally, note that invoking this function multiple times on 448 * different sets of argv tokens is safe, but will erase any 449 * previous parsing results. 450 */ 451 OPAL_DECLSPEC int opal_cmd_line_parse(opal_cmd_line_t *cmd, 452 bool ignore_unknown, 453 bool ignore_unknown_option, 454 int argc, char **argv); 455 456 /** 457 * Return a consolidated "usage" message for a OPAL command line handle. 458 * 459 * @param cmd OPAL command line handle. 460 * 461 * @retval str Usage message. 462 * 463 * Returns a formatted string suitable for printing that lists the 464 * expected usage message and a short description of each option on 465 * the OPAL command line handle. Options that passed a NULL 466 * description to opal_cmd_line_make_opt3() will not be included in the 467 * display (to allow for undocumented options). 468 * 469 * This function is typically only invoked internally by the 470 * opal_show_help() function. 471 * 472 * This function should probably be fixed up to produce prettier 473 * output. 474 * 475 * The returned string must be freed by the caller. 476 */ 477 OPAL_DECLSPEC char *opal_cmd_line_get_usage_msg(opal_cmd_line_t *cmd) __opal_attribute_malloc__ __opal_attribute_warn_unused_result__; 478 479 /** 480 * Test if a given option was taken on the parsed command line. 481 * 482 * @param cmd OPAL command line handle. 483 * @param opt Short or long name of the option to check for. 484 * 485 * @retval true If the command line option was found during 486 * opal_cmd_line_parse(). 487 * 488 * @retval false If the command line option was not found during 489 * opal_cmd_line_parse(), or opal_cmd_line_parse() was not invoked on 490 * this handle. 491 * 492 * This function should only be called after opal_cmd_line_parse(). 493 * 494 * The function will return true if the option matching opt was found 495 * (either by its short or long name) during token parsing. 496 * Otherwise, it will return false. 497 */ 498 OPAL_DECLSPEC bool opal_cmd_line_is_taken(opal_cmd_line_t *cmd, 499 const char *opt) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2); 500 501 /** 502 * Return the number of arguments parsed on a OPAL command line handle. 503 * 504 * @param cmd A pointer to the OPAL command line handle. 505 * 506 * @retval OPAL_ERROR If cmd is NULL. 507 * @retval argc Number of arguments previously added to the handle. 508 * 509 * Arguments are added to the handle via the opal_cmd_line_parse() 510 * function. 511 */ 512 OPAL_DECLSPEC int opal_cmd_line_get_argc(opal_cmd_line_t *cmd) __opal_attribute_unused__; 513 514 /** 515 * Return a string argument parsed on a OPAL command line handle. 516 * 517 * @param cmd A pointer to the OPAL command line handle. 518 * @param index The nth argument from the command line (0 is 519 * argv[0], etc.). 520 * 521 * @retval NULL If cmd is NULL or index is invalid 522 * @retval argument String of original argv[index] 523 * 524 * This function returns a single token from the arguments parsed 525 * on this handle. Arguments are added bia the 526 * opal_cmd_line_parse() function. 527 * 528 * What is returned is a pointer to the actual string that is on 529 * the handle; it should not be modified or freed. 530 */ 531 OPAL_DECLSPEC char *opal_cmd_line_get_argv(opal_cmd_line_t *cmd, 532 int index); 533 534 /** 535 * Return the number of instances of an option found during parsing. 536 * 537 * @param cmd OPAL command line handle. 538 * @param opt Short or long name of the option to check for. 539 * 540 * @retval num Number of instances (to include 0) of a given potion 541 * found during opal_cmd_line_parse(). 542 * 543 * @retval OPAL_ERR If the command line option was not found during 544 * opal_cmd_line_parse(), or opal_cmd_line_parse() was not invoked on 545 * this handle. 546 * 547 * This function should only be called after opal_cmd_line_parse(). 548 * 549 * The function will return the number of instances of a given option 550 * (either by its short or long name) -- to include 0 -- or OPAL_ERR if 551 * either the option was not specified as part of the OPAL command line 552 * handle, or opal_cmd_line_parse() was not invoked on this handle. 553 */ 554 OPAL_DECLSPEC int opal_cmd_line_get_ninsts(opal_cmd_line_t *cmd, 555 const char *opt) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2); 556 557 /** 558 * Return a specific parameter for a specific instance of a option 559 * from the parsed command line. 560 * 561 * @param cmd OPAL command line handle. 562 * @param opt Short or long name of the option to check for. 563 * @param instance_num Instance number of the option to query. 564 * @param param_num Which parameter to return. 565 * 566 * @retval param String of the parameter. 567 * @retval NULL If any of the input values are invalid. 568 * 569 * This function should only be called after opal_cmd_line_parse(). 570 * 571 * This function returns the Nth parameter for the Ith instance of a 572 * given option on the parsed command line (both N and I are 573 * zero-indexed). For example, on the command line: 574 * 575 * executable --foo bar1 bar2 --foo bar3 bar4 576 * 577 * The call to opal_cmd_line_get_param(cmd, "foo", 1, 1) would return 578 * "bar4". opal_cmd_line_get_param(cmd, "bar", 0, 0) would return 579 * NULL, as would opal_cmd_line_get_param(cmd, "foo", 2, 2); 580 * 581 * The returned string should \em not be modified or freed by the 582 * caller. 583 */ 584 OPAL_DECLSPEC char *opal_cmd_line_get_param(opal_cmd_line_t *cmd, 585 const char *opt, 586 int instance_num, 587 int param_num); 588 589 /** 590 * Return the entire "tail" of unprocessed argv from a OPAL 591 * command line handle. 592 * 593 * @param cmd A pointer to the OPAL command line handle. 594 * @param tailc Pointer to the output length of the null-terminated 595 * tail argv array. 596 * @param tailv Pointer to the output null-terminated argv of all 597 * unprocessed arguments from the command line. 598 * 599 * @retval OPAL_ERROR If cmd is NULL or otherwise invalid. 600 * @retval OPAL_SUCCESS Upon success. 601 * 602 * The "tail" is all the arguments on the command line that were 603 * not processed for some reason. Reasons for not processing 604 * arguments include: 605 * 606 * \sa The argument was not recognized 607 * \sa The argument "--" was seen, and therefore all arguments 608 * following it were not processed 609 * 610 * The output tailc parameter will be filled in with the integer 611 * length of the null-terminated tailv array (length including the 612 * final NULL entry). The output tailv parameter will be a copy 613 * of the tail parameters, and must be freed (likely with a call 614 * to opal_argv_free()) by the caller. 615 */ 616 OPAL_DECLSPEC int opal_cmd_line_get_tail(opal_cmd_line_t *cmd, int *tailc, 617 char ***tailv); 618 619 END_C_DECLS 620 621 622 #endif /* OPAL_CMD_LINE_H */ 623