Sean Anderson | 72eda50 | 2020-10-27 19:55:36 -0400 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | /* |
| 3 | * getopt.h - a simple getopt(3) implementation. |
| 4 | * |
| 5 | * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> |
| 6 | * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix |
| 7 | */ |
| 8 | |
| 9 | #ifndef __GETOPT_H |
| 10 | #define __GETOPT_H |
| 11 | |
| 12 | /** |
| 13 | * struct getopt_state - Saved state across getopt() calls |
| 14 | */ |
| 15 | struct getopt_state { |
| 16 | /** |
| 17 | * @index: Index of the next unparsed argument of @argv. If getopt() has |
| 18 | * parsed all of @argv, then @index will equal @argc. |
| 19 | */ |
| 20 | int index; |
| 21 | /* private: */ |
| 22 | /** @arg_index: Index within the current argument */ |
| 23 | int arg_index; |
| 24 | union { |
| 25 | /* public: */ |
| 26 | /** |
| 27 | * @opt: Option being parsed when an error occurs. @opt is only |
| 28 | * valid when getopt() returns ``?`` or ``:``. |
| 29 | */ |
| 30 | int opt; |
| 31 | /** |
| 32 | * @arg: The argument to an option, NULL if there is none. @arg |
| 33 | * is only valid when getopt() returns an option character. |
| 34 | */ |
| 35 | char *arg; |
| 36 | /* private: */ |
| 37 | }; |
| 38 | }; |
| 39 | |
| 40 | /** |
| 41 | * getopt_init_state() - Initialize a &struct getopt_state |
| 42 | * @gs: The state to initialize |
| 43 | * |
| 44 | * This must be called before using @gs with getopt(). |
| 45 | */ |
| 46 | void getopt_init_state(struct getopt_state *gs); |
| 47 | |
| 48 | int __getopt(struct getopt_state *gs, int argc, char *const argv[], |
| 49 | const char *optstring, bool silent); |
| 50 | |
| 51 | /** |
| 52 | * getopt() - Parse short command-line options |
| 53 | * @gs: Internal state and out-of-band return arguments. This must be |
| 54 | * initialized with getopt_init_context() beforehand. |
| 55 | * @argc: Number of arguments, not including the %NULL terminator |
| 56 | * @argv: Argument list, terminated by %NULL |
| 57 | * @optstring: Option specification, as described below |
| 58 | * |
| 59 | * getopt() parses short options. Short options are single characters. They may |
| 60 | * be followed by a required argument or an optional argument. Arguments to |
| 61 | * options may occur in the same argument as an option (like ``-larg``), or |
| 62 | * in the following argument (like ``-l arg``). An argument containing |
| 63 | * options begins with a ``-``. If an option expects no arguments, then it may |
| 64 | * be immediately followed by another option (like ``ls -alR``). |
| 65 | * |
| 66 | * @optstring is a list of accepted options. If an option is followed by ``:`` |
| 67 | * in @optstring, then it expects a mandatory argument. If an option is followed |
| 68 | * by ``::`` in @optstring, it expects an optional argument. @gs.arg points |
| 69 | * to the argument, if one is parsed. |
| 70 | * |
| 71 | * getopt() stops parsing options when it encounters the first non-option |
| 72 | * argument, when it encounters the argument ``--``, or when it runs out of |
| 73 | * arguments. For example, in ``ls -l foo -R``, option parsing will stop when |
| 74 | * getopt() encounters ``foo``, if ``l`` does not expect an argument. However, |
| 75 | * the whole list of arguments would be parsed if ``l`` expects an argument. |
| 76 | * |
| 77 | * An example invocation of getopt() might look like:: |
| 78 | * |
| 79 | * char *argv[] = { "program", "-cbx", "-a", "foo", "bar", 0 }; |
| 80 | * int opt, argc = ARRAY_SIZE(argv) - 1; |
| 81 | * struct getopt_state gs; |
| 82 | * |
| 83 | * getopt_init_state(&gs); |
| 84 | * while ((opt = getopt(&gs, argc, argv, "a::b:c")) != -1) |
| 85 | * printf("opt = %c, index = %d, arg = \"%s\"\n", opt, gs.index, gs.arg); |
| 86 | * printf("%d argument(s) left\n", argc - gs.index); |
| 87 | * |
| 88 | * and would produce an output of:: |
| 89 | * |
| 90 | * opt = c, index = 1, arg = "<NULL>" |
| 91 | * opt = b, index = 2, arg = "x" |
| 92 | * opt = a, index = 4, arg = "foo" |
| 93 | * 1 argument(s) left |
| 94 | * |
| 95 | * For further information, refer to the getopt(3) man page. |
| 96 | * |
| 97 | * Return: |
| 98 | * * An option character if an option is found. @gs.arg is set to the |
| 99 | * argument if there is one, otherwise it is set to ``NULL``. |
| 100 | * * ``-1`` if there are no more options, if a non-option argument is |
| 101 | * encountered, or if an ``--`` argument is encountered. |
| 102 | * * ``'?'`` if we encounter an option not in @optstring. @gs.opt is set to |
| 103 | * the unknown option. |
| 104 | * * ``':'`` if an argument is required, but no argument follows the |
| 105 | * option. @gs.opt is set to the option missing its argument. |
| 106 | * |
| 107 | * @gs.index is always set to the index of the next unparsed argument in @argv. |
| 108 | */ |
| 109 | static inline int getopt(struct getopt_state *gs, int argc, |
| 110 | char *const argv[], const char *optstring) |
| 111 | { |
| 112 | return __getopt(gs, argc, argv, optstring, false); |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * getopt_silent() - Parse short command-line options silently |
| 117 | * @gs: State |
| 118 | * @argc: Argument count |
| 119 | * @argv: Argument list |
| 120 | * @optstring: Option specification |
| 121 | * |
| 122 | * Same as getopt(), except no error messages are printed. |
| 123 | */ |
| 124 | static inline int getopt_silent(struct getopt_state *gs, int argc, |
| 125 | char *const argv[], const char *optstring) |
| 126 | { |
| 127 | return __getopt(gs, argc, argv, optstring, true); |
| 128 | } |
| 129 | |
| 130 | #endif /* __GETOPT_H */ |