1 #ifndef __PARSE_OPTIONS_H__ 2 #define __PARSE_OPTIONS_H__ 3 4 #include <inttypes.h> 5 6 enum parse_opt_type { 7 /* special types */ 8 OPTION_END, 9 OPTION_ARGUMENT, 10 OPTION_GROUP, 11 /* options with no arguments */ 12 OPTION_BIT, 13 OPTION_BOOLEAN, 14 OPTION_INCR, 15 OPTION_SET_UINT, 16 OPTION_SET_PTR, 17 /* options with arguments (usually) */ 18 OPTION_STRING, 19 OPTION_INTEGER, 20 OPTION_LONG, 21 OPTION_CALLBACK, 22 OPTION_U64, 23 OPTION_UINTEGER, 24 }; 25 26 enum parse_opt_flags { 27 PARSE_OPT_KEEP_DASHDASH = 1, 28 PARSE_OPT_STOP_AT_NON_OPTION = 2, 29 PARSE_OPT_KEEP_ARGV0 = 4, 30 PARSE_OPT_KEEP_UNKNOWN = 8, 31 PARSE_OPT_NO_INTERNAL_HELP = 16, 32 }; 33 34 enum parse_opt_option_flags { 35 PARSE_OPT_OPTARG = 1, 36 PARSE_OPT_NOARG = 2, 37 PARSE_OPT_NONEG = 4, 38 PARSE_OPT_HIDDEN = 8, 39 PARSE_OPT_LASTARG_DEFAULT = 16, 40 }; 41 42 struct option; 43 typedef int parse_opt_cb(const struct option *, const char *arg, int unset); 44 /* 45 * `type`:: 46 * holds the type of the option, you must have an OPTION_END last in your 47 * array. 48 * 49 * `short_name`:: 50 * the character to use as a short option name, '\0' if none. 51 * 52 * `long_name`:: 53 * the long option name, without the leading dashes, NULL if none. 54 * 55 * `value`:: 56 * stores pointers to the values to be filled. 57 * 58 * `argh`:: 59 * token to explain the kind of argument this option wants. Keep it 60 * homogenous across the repository. 61 * 62 * `help`:: 63 * the short help associated to what the option does. 64 * Must never be NULL (except for OPTION_END). 65 * OPTION_GROUP uses this pointer to store the group header. 66 * 67 * `flags`:: 68 * mask of parse_opt_option_flags. 69 * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs) 70 * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs 71 * PARSE_OPT_NONEG: says that this option cannot be negated 72 * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in 73 * the long one. 74 * 75 * `callback`:: 76 * pointer to the callback to use for OPTION_CALLBACK. 77 * 78 * `defval`:: 79 * default value to fill (*->value) with for PARSE_OPT_OPTARG. 80 * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in 81 * the value when met. 82 * CALLBACKS can use it like they want. 83 */ 84 struct option { 85 enum parse_opt_type type; 86 int short_name; 87 const char *long_name; 88 void *value; 89 const char *argh; 90 const char *help; 91 92 int flags; 93 parse_opt_cb *callback; 94 intptr_t defval; 95 }; 96 97 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 98 #define check_vtype(v, type) \ 99 (BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v) 100 101 #define OPT_INTEGER(s, l, v, h) \ 102 { \ 103 .type = OPTION_INTEGER, \ 104 .short_name = (s), \ 105 .long_name = (l), \ 106 .value = check_vtype(v, int *), \ 107 .help = (h) \ 108 } 109 110 #define OPT_U64(s, l, v, h) \ 111 { \ 112 .type = OPTION_U64, \ 113 .short_name = (s), \ 114 .long_name = (l), \ 115 .value = check_vtype(v, u64 *), \ 116 .help = (h) \ 117 } 118 119 #define OPT_STRING(s, l, v, a, h) \ 120 { \ 121 .type = OPTION_STRING, \ 122 .short_name = (s), \ 123 .long_name = (l), \ 124 .value = check_vtype(v, const char **), (a), \ 125 .help = (h) \ 126 } 127 128 #define OPT_BOOLEAN(s, l, v, h) \ 129 { \ 130 .type = OPTION_BOOLEAN, \ 131 .short_name = (s), \ 132 .long_name = (l), \ 133 .value = check_vtype(v, bool *), \ 134 .help = (h) \ 135 } 136 137 #define OPT_INCR(s, l, v, h) \ 138 { \ 139 .type = OPTION_INCR, \ 140 .short_name = (s), \ 141 .long_name = (l), \ 142 .value = check_vtype(v, int *), \ 143 .help = (h) \ 144 } 145 146 #define OPT_GROUP(h) \ 147 { \ 148 .type = OPTION_GROUP, \ 149 .help = (h) \ 150 } 151 152 #define OPT_CALLBACK(s, l, v, a, h, f) \ 153 { \ 154 .type = OPTION_CALLBACK, \ 155 .short_name = (s), \ 156 .long_name = (l), \ 157 .value = (v), \ 158 (a), \ 159 .help = (h), \ 160 .callback = (f) \ 161 } 162 163 #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \ 164 { \ 165 .type = OPTION_CALLBACK, \ 166 .short_name = (s), \ 167 .long_name = (l), \ 168 .value = (v), \ 169 (a), \ 170 .help = (h), \ 171 .callback = (f), \ 172 .flags = PARSE_OPT_NOARG \ 173 } 174 175 #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 176 { \ 177 .type = OPTION_CALLBACK, \ 178 .short_name = (s), \ 179 .long_name = (l), \ 180 .value = (v), (a), \ 181 .help = (h), \ 182 .callback = (f), \ 183 .defval = (intptr_t)d, \ 184 .flags = PARSE_OPT_LASTARG_DEFAULT \ 185 } 186 187 #define OPT_END() { .type = OPTION_END } 188 189 enum { 190 PARSE_OPT_HELP = -1, 191 PARSE_OPT_DONE, 192 PARSE_OPT_UNKNOWN, 193 }; 194 195 /* 196 * It's okay for the caller to consume argv/argc in the usual way. 197 * Other fields of that structure are private to parse-options and should not 198 * be modified in any way. 199 **/ 200 struct parse_opt_ctx_t { 201 const char **argv; 202 const char **out; 203 int argc, cpidx; 204 const char *opt; 205 int flags; 206 }; 207 208 /* global functions */ 209 void usage_with_options(const char * const *usagestr, 210 const struct option *opts); 211 int parse_options(int argc, const char **argv, const struct option *options, 212 const char * const usagestr[], int flags); 213 #endif 214