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