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