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-2017 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 * pmix_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 * (pmix_cmd_line_t) with OBJ_NEW() and then uses it to register the
78 * desired parameters via pmix_cmd_line_make_opt3(). Once all the
79 * parameters have been registered, the user invokes
80 * pmix_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 * - pmix_cmd_line_get_usage_msg() returns a string suitable for "help"
91 * kinds of messages.
92 * - pmix_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 * - pmix_cmd_line_get_argc() returns the number of tokens parsed on
96 * the handle.
97 * - pmix_cmd_line_get_argv() returns any particular string from the
98 * original argv.
99 * - pmix_cmd_line_get_ninsts() returns the number of times a
100 * particular option was found on a command line.
101 * - pmix_cmd_line_get_param() returns the Nth parameter in the Mth
102 * instance of a given parameter.
103 * - pmix_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 pmix_cmd_line_init_t instances and the
108 * table to pmix_cmd_line_create(). This creates an pmix_cmd_line_t
109 * handle that is pre-seeded with all the options from the table
110 * without the need to repeatedly invoke pmix_cmd_line_make_opt3() (or
111 * equivalent). This pmix_cmd_line_t instance is just like any other;
112 * it is still possible to add more options via
113 * pmix_cmd_line_make_opt3(), etc.
114 */
115
116 #ifndef PMIX_CMD_LINE_H
117 #define PMIX_CMD_LINE_H
118
119 #include "pmix_config.h"
120
121 #include "src/class/pmix_object.h"
122 #include "src/class/pmix_list.h"
123 #include "src/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 pmix_cmd_line_t {
132 /** Make this an OBJ handle */
133 pmix_object_t super;
134
135 /** Thread safety */
136 pmix_recursive_mutex_t lcl_mutex;
137
138 /** List of ompi_cmd_line_option_t's (defined internally) */
139 pmix_list_t lcl_options;
140
141 /** Duplicate of argc from pmix_cmd_line_parse() */
142 int lcl_argc;
143 /** Duplicate of argv from pmix_cmd_line_parse() */
144 char **lcl_argv;
145
146 /** Parsed output; list of ompi_cmd_line_param_t's (defined internally) */
147 pmix_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 pmix_cmd_line_t pmix_cmd_line_t;
160
161 /**
162 * Data types supported by the parser
163 */
164 enum pmix_cmd_line_type_t {
165 PMIX_CMD_LINE_TYPE_NULL,
166 PMIX_CMD_LINE_TYPE_STRING,
167 PMIX_CMD_LINE_TYPE_INT,
168 PMIX_CMD_LINE_TYPE_SIZE_T,
169 PMIX_CMD_LINE_TYPE_BOOL,
170
171 PMIX_CMD_LINE_TYPE_MAX
172 };
173 /**
174 * \internal
175 *
176 * Convenience typedef
177 */
178 typedef enum pmix_cmd_line_type_t pmix_cmd_line_type_t;
179
180 /**
181 * Command line option type, for use in
182 * mpirun --help output.
183 */
184 enum pmix_cmd_line_otype_t {
185 PMIX_CMD_LINE_OTYPE_GENERAL,
186 PMIX_CMD_LINE_OTYPE_DEBUG,
187 PMIX_CMD_LINE_OTYPE_OUTPUT,
188 PMIX_CMD_LINE_OTYPE_INPUT,
189 PMIX_CMD_LINE_OTYPE_MAPPING,
190 PMIX_CMD_LINE_OTYPE_RANKING,
191 PMIX_CMD_LINE_OTYPE_BINDING,
192 PMIX_CMD_LINE_OTYPE_DEVEL,
193 PMIX_CMD_LINE_OTYPE_COMPAT, /* Backwards compatibility */
194 PMIX_CMD_LINE_OTYPE_LAUNCH,
195 PMIX_CMD_LINE_OTYPE_DVM,
196 PMIX_CMD_LINE_OTYPE_UNSUPPORTED,
197 PMIX_CMD_LINE_OTYPE_PARSABLE,
198 PMIX_CMD_LINE_OTYPE_NULL
199 };
200 /**
201 * \internal
202 *
203 * Convenience typedef
204 */
205 typedef enum pmix_cmd_line_otype_t pmix_cmd_line_otype_t;
206
207 /**
208 * Datatype used to construct a command line handle; see
209 * pmix_cmd_line_create().
210 */
211 struct pmix_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 pmix_cmd_line_type_t ocl_variable_type;
234
235 /** Description of the command line option, to be used with
236 pmix_cmd_line_get_usage_msg(). */
237 const char *ocl_description;
238
239 /** Category for mpirun --help output */
240 pmix_cmd_line_otype_t ocl_otype;
241 };
242 /**
243 * \internal
244 *
245 * Convenience typedef
246 */
247 typedef struct pmix_cmd_line_init_t pmix_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 pmix_cmd_line*() functions). Multiple handles can be
254 * created and simultaneously processed; each handle is independant
255 * from others.
256 *
257 * The pmix_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 pmix_cmd_line_t handles will free all memory
264 * associated with the handle.
265 */
266 PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_cmd_line_t);
267
268 /**
269 * Make a command line handle from a table of initializers.
270 *
271 * @param cmd PMIX command line handle.
272 * @param table Table of pmix_cmd_line_init_t instances for all
273 * the options to be included in the resulting command line
274 * handler.
275 *
276 * @retval PMIX_SUCCESS Upon success.
277 *
278 * This function takes a table of pmix_cmd_line_init_t instances
279 * to pre-seed an PMIX 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 * pmix_cmd_line_init_t cmd_line_init[] = {
289 * { NULL, NULL, NULL, 'h', NULL, "help", 0,
290 * &orterun_globals.help, PMIX_CMD_LINE_TYPE_BOOL,
291 * "This help message" },
292 *
293 * { NULL, NULL, NULL, '\0', NULL, "wd", 1,
294 * &orterun_globals.wd, PMIX_CMD_LINE_TYPE_STRING,
295 * "Set the working directory of the started processes" },
296 *
297 * { NULL, NULL, NULL, '\0', NULL, NULL, 0,
298 * NULL, PMIX_CMD_LINE_TYPE_NULL, NULL }
299 * };
300 * \endcode
301 */
302 PMIX_EXPORT int pmix_cmd_line_create(pmix_cmd_line_t *cmd,
303 pmix_cmd_line_init_t *table);
304
305 /* Add a table of pmix_cmd_line_init_t instances
306 * to an existing PMIX command line handle.
307 *
308 * Multiple calls to pmix_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 PMIX_EXPORT int pmix_cmd_line_add(pmix_cmd_line_t *cmd,
313 pmix_cmd_line_init_t *table);
314
315 /**
316 * Create a command line option.
317 *
318 * @param cmd PMIX command line handle.
319 * @param entry Command line entry to add to the command line.
320 *
321 * @retval PMIX_SUCCESS Upon success.
322 *
323 */
324 PMIX_EXPORT int pmix_cmd_line_make_opt_mca(pmix_cmd_line_t *cmd,
325 pmix_cmd_line_init_t entry);
326
327 /**
328 * Create a command line option.
329 *
330 * @param cmd PMIX 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 PMIX_ERR_OUT_OF_RESOURCE If out of memory.
338 * @retval PMIX_ERR_BAD_PARAM If bad parameters passed.
339 * @retval PMIX_SUCCESS Upon success.
340 *
341 * Adds a command line option to the list of options that an PMIX
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 pmix_cmd_line_get_usage_msg().
353 *
354 */
355 PMIX_EXPORT int pmix_cmd_line_make_opt3(pmix_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 PMIX command line
364 * handle.
365 *
366 * @param cmd PMIX 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 PMIX_SUCCESS Upon success.
375 * @retval PMIX_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 PMIX command line handle. The PMIX 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 PMIX_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 pmix_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 PMIX_EXPORT int pmix_cmd_line_parse(pmix_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 PMIX command line handle.
458 *
459 * @param cmd PMIX 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 PMIX command line handle. Options that passed a NULL
466 * description to pmix_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 * pmix_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 PMIX_EXPORT char *pmix_cmd_line_get_usage_msg(pmix_cmd_line_t *cmd) __pmix_attribute_malloc__ __pmix_attribute_warn_unused_result__;
478
479 /**
480 * Test if a given option was taken on the parsed command line.
481 *
482 * @param cmd PMIX 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 * pmix_cmd_line_parse().
487 *
488 * @retval false If the command line option was not found during
489 * pmix_cmd_line_parse(), or pmix_cmd_line_parse() was not invoked on
490 * this handle.
491 *
492 * This function should only be called after pmix_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 PMIX_EXPORT bool pmix_cmd_line_is_taken(pmix_cmd_line_t *cmd,
499 const char *opt) __pmix_attribute_nonnull__(1) __pmix_attribute_nonnull__(2);
500
501 /**
502 * Return the number of arguments parsed on a PMIX command line handle.
503 *
504 * @param cmd A pointer to the PMIX command line handle.
505 *
506 * @retval PMIX_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 pmix_cmd_line_parse()
510 * function.
511 */
512 PMIX_EXPORT int pmix_cmd_line_get_argc(pmix_cmd_line_t *cmd) __pmix_attribute_unused__;
513
514 /**
515 * Return a string argument parsed on a PMIX command line handle.
516 *
517 * @param cmd A pointer to the PMIX 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 * pmix_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 PMIX_EXPORT char *pmix_cmd_line_get_argv(pmix_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 PMIX 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 pmix_cmd_line_parse().
542 *
543 * @retval PMIX_ERR If the command line option was not found during
544 * pmix_cmd_line_parse(), or pmix_cmd_line_parse() was not invoked on
545 * this handle.
546 *
547 * This function should only be called after pmix_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 PMIX_ERR if
551 * either the option was not specified as part of the PMIX command line
552 * handle, or pmix_cmd_line_parse() was not invoked on this handle.
553 */
554 PMIX_EXPORT int pmix_cmd_line_get_ninsts(pmix_cmd_line_t *cmd,
555 const char *opt) __pmix_attribute_nonnull__(1) __pmix_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 PMIX 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 pmix_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 pmix_cmd_line_get_param(cmd, "foo", 1, 1) would return
578 * "bar4". pmix_cmd_line_get_param(cmd, "bar", 0, 0) would return
579 * NULL, as would pmix_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 PMIX_EXPORT char *pmix_cmd_line_get_param(pmix_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 PMIX
591 * command line handle.
592 *
593 * @param cmd A pointer to the PMIX 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 PMIX_ERROR If cmd is NULL or otherwise invalid.
600 * @retval PMIX_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 pmix_argv_free()) by the caller.
615 */
616 PMIX_EXPORT int pmix_cmd_line_get_tail(pmix_cmd_line_t *cmd, int *tailc,
617 char ***tailv);
618
619 END_C_DECLS
620
621
622 #endif /* PMIX_CMD_LINE_H */