File indexing completed on 2026-05-10 08:48:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef ISL_ARG_H
0011 #define ISL_ARG_H
0012
0013 #include <stddef.h>
0014 #include <stdlib.h>
0015
0016 #if defined(__cplusplus)
0017 extern "C" {
0018 #endif
0019
0020 struct isl_arg_choice {
0021 const char *name;
0022 unsigned value;
0023 };
0024
0025 struct isl_arg_flags {
0026 const char *name;
0027 unsigned mask;
0028 unsigned value;
0029 };
0030
0031 enum isl_arg_type {
0032 isl_arg_end,
0033 isl_arg_alias,
0034 isl_arg_arg,
0035 isl_arg_bool,
0036 isl_arg_child,
0037 isl_arg_choice,
0038 isl_arg_flags,
0039 isl_arg_footer,
0040 isl_arg_int,
0041 isl_arg_user,
0042 isl_arg_long,
0043 isl_arg_ulong,
0044 isl_arg_str,
0045 isl_arg_str_list,
0046 isl_arg_version
0047 };
0048
0049 struct isl_args;
0050
0051 struct isl_arg {
0052 enum isl_arg_type type;
0053 char short_name;
0054 const char *long_name;
0055 const char *argument_name;
0056 #define ISL_ARG_OFFSET_NONE ((size_t) -1)
0057 size_t offset;
0058 const char *help_msg;
0059 #define ISL_ARG_SINGLE_DASH (1 << 0)
0060 #define ISL_ARG_BOOL_ARG (1 << 1)
0061 #define ISL_ARG_HIDDEN (1 << 2)
0062 unsigned flags;
0063 union {
0064 struct {
0065 struct isl_arg_choice *choice;
0066 unsigned default_value;
0067 unsigned default_selected;
0068 int (*set)(void *opt, unsigned val);
0069 } choice;
0070 struct {
0071 struct isl_arg_flags *flags;
0072 unsigned default_value;
0073 } flags;
0074 struct {
0075 unsigned default_value;
0076 int (*set)(void *opt, unsigned val);
0077 } b;
0078 struct {
0079 int default_value;
0080 } i;
0081 struct {
0082 long default_value;
0083 long default_selected;
0084 int (*set)(void *opt, long val);
0085 } l;
0086 struct {
0087 unsigned long default_value;
0088 } ul;
0089 struct {
0090 const char *default_value;
0091 } str;
0092 struct {
0093 size_t offset_n;
0094 } str_list;
0095 struct {
0096 struct isl_args *child;
0097 } child;
0098 struct {
0099 void (*print_version)(void);
0100 } version;
0101 struct {
0102 int (*init)(void*);
0103 void (*clear)(void*);
0104 } user;
0105 } u;
0106 };
0107
0108 struct isl_args {
0109 size_t options_size;
0110 struct isl_arg *args;
0111 };
0112
0113 #define ISL_ARGS_START(s,name) \
0114 struct isl_arg name ## LIST[]; \
0115 struct isl_args name = { sizeof(s), name ## LIST }; \
0116 struct isl_arg name ## LIST[] = {
0117 #define ISL_ARGS_END \
0118 { isl_arg_end } };
0119
0120 #define ISL_ARG_ALIAS(l) { \
0121 .type = isl_arg_alias, \
0122 .long_name = l, \
0123 },
0124 #define ISL_ARG_ARG(st,f,a,d) { \
0125 .type = isl_arg_arg, \
0126 .argument_name = a, \
0127 .offset = offsetof(st, f), \
0128 .u = { .str = { .default_value = d } } \
0129 },
0130 #define ISL_ARG_FOOTER(h) { \
0131 .type = isl_arg_footer, \
0132 .help_msg = h, \
0133 },
0134 #define ISL_ARG_CHOICE(st,f,s,l,c,d,h) { \
0135 .type = isl_arg_choice, \
0136 .short_name = s, \
0137 .long_name = l, \
0138 .offset = offsetof(st, f), \
0139 .help_msg = h, \
0140 .u = { .choice = { .choice = c, .default_value = d, \
0141 .default_selected = d, .set = NULL } } \
0142 },
0143 #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h) { \
0144 .type = isl_arg_choice, \
0145 .short_name = s, \
0146 .long_name = l, \
0147 .offset = offsetof(st, f), \
0148 .help_msg = h, \
0149 .u = { .choice = { .choice = c, .default_value = d, \
0150 .default_selected = ds, .set = NULL } } \
0151 },
0152 #define ISL_ARG_PHANTOM_USER_CHOICE_F(s,l,c,setter,d,h,fl) { \
0153 .type = isl_arg_choice, \
0154 .short_name = s, \
0155 .long_name = l, \
0156 .offset = ISL_ARG_OFFSET_NONE, \
0157 .help_msg = h, \
0158 .flags = fl, \
0159 .u = { .choice = { .choice = c, .default_value = d, \
0160 .default_selected = d, .set = setter } } \
0161 },
0162 #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h) { \
0163 .type = isl_arg_choice, \
0164 .short_name = s, \
0165 .long_name = l, \
0166 .offset = offsetof(st, f), \
0167 .help_msg = h, \
0168 .u = { .choice = { .choice = c, .default_value = d, \
0169 .default_selected = ds, .set = setter } } \
0170 },
0171 #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl) { \
0172 .type = isl_arg_bool, \
0173 .short_name = s, \
0174 .long_name = l, \
0175 .offset = o, \
0176 .help_msg = h, \
0177 .flags = fl, \
0178 .u = { .b = { .default_value = d, .set = setter } } \
0179 },
0180 #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl) \
0181 _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
0182 #define ISL_ARG_BOOL(st,f,s,l,d,h) \
0183 ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
0184 #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl) \
0185 _ISL_ARG_BOOL_F(ISL_ARG_OFFSET_NONE,s,l,setter,0,h,fl)
0186 #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h) \
0187 ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
0188 #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl) { \
0189 .type = isl_arg_int, \
0190 .short_name = s, \
0191 .long_name = l, \
0192 .argument_name = a, \
0193 .offset = offsetof(st, f), \
0194 .help_msg = h, \
0195 .flags = fl, \
0196 .u = { .i = { .default_value = d } } \
0197 },
0198 #define ISL_ARG_INT(st,f,s,l,a,d,h) \
0199 ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
0200 #define ISL_ARG_LONG(st,f,s,lo,d,h) { \
0201 .type = isl_arg_long, \
0202 .short_name = s, \
0203 .long_name = lo, \
0204 .offset = offsetof(st, f), \
0205 .help_msg = h, \
0206 .u = { .l = { .default_value = d, .default_selected = d, \
0207 .set = NULL } } \
0208 },
0209 #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) { \
0210 .type = isl_arg_long, \
0211 .short_name = s, \
0212 .long_name = lo, \
0213 .offset = offsetof(st, f), \
0214 .help_msg = h, \
0215 .u = { .l = { .default_value = d, .default_selected = d, \
0216 .set = setter } } \
0217 },
0218 #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h) { \
0219 .type = isl_arg_long, \
0220 .short_name = s, \
0221 .long_name = lo, \
0222 .offset = offsetof(st, f), \
0223 .help_msg = h, \
0224 .u = { .l = { .default_value = d, .default_selected = ds, \
0225 .set = NULL } } \
0226 },
0227 #define ISL_ARG_ULONG(st,f,s,l,d,h) { \
0228 .type = isl_arg_ulong, \
0229 .short_name = s, \
0230 .long_name = l, \
0231 .offset = offsetof(st, f), \
0232 .help_msg = h, \
0233 .u = { .ul = { .default_value = d } } \
0234 },
0235 #define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl) { \
0236 .type = isl_arg_str, \
0237 .short_name = s, \
0238 .long_name = l, \
0239 .argument_name = a, \
0240 .offset = offsetof(st, f), \
0241 .help_msg = h, \
0242 .flags = fl, \
0243 .u = { .str = { .default_value = d } } \
0244 },
0245 #define ISL_ARG_STR(st,f,s,l,a,d,h) \
0246 ISL_ARG_STR_F(st,f,s,l,a,d,h,0)
0247 #define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h) { \
0248 .type = isl_arg_str_list, \
0249 .short_name = s, \
0250 .long_name = l, \
0251 .argument_name = a, \
0252 .offset = offsetof(st, f_l), \
0253 .help_msg = h, \
0254 .u = { .str_list = { .offset_n = offsetof(st, f_n) } } \
0255 },
0256 #define _ISL_ARG_CHILD(o,l,c,h,fl) { \
0257 .type = isl_arg_child, \
0258 .long_name = l, \
0259 .offset = o, \
0260 .help_msg = h, \
0261 .flags = fl, \
0262 .u = { .child = { .child = c } } \
0263 },
0264 #define ISL_ARG_CHILD(st,f,l,c,h) \
0265 _ISL_ARG_CHILD(offsetof(st, f),l,c,h,0)
0266 #define ISL_ARG_GROUP_F(l,c,h,fl) \
0267 _ISL_ARG_CHILD(ISL_ARG_OFFSET_NONE,l,c,h,fl)
0268 #define ISL_ARG_GROUP(l,c,h) \
0269 ISL_ARG_GROUP_F(l,c,h,0)
0270 #define ISL_ARG_FLAGS(st,f,s,l,c,d,h) { \
0271 .type = isl_arg_flags, \
0272 .short_name = s, \
0273 .long_name = l, \
0274 .offset = offsetof(st, f), \
0275 .help_msg = h, \
0276 .u = { .flags = { .flags = c, .default_value = d } } \
0277 },
0278 #define ISL_ARG_USER(st,f,i,c) { \
0279 .type = isl_arg_user, \
0280 .offset = offsetof(st, f), \
0281 .u = { .user = { .init = i, .clear = c} } \
0282 },
0283 #define ISL_ARG_VERSION(print) { \
0284 .type = isl_arg_version, \
0285 .u = { .version = { .print_version = print } } \
0286 },
0287
0288 #define ISL_ARG_ALL (1 << 0)
0289 #define ISL_ARG_SKIP_HELP (1 << 1)
0290
0291 void isl_args_set_defaults(struct isl_args *args, void *opt);
0292 void isl_args_free(struct isl_args *args, void *opt);
0293 int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
0294 unsigned flags);
0295
0296 #define ISL_ARG_DECL(prefix,st,args) \
0297 extern struct isl_args args; \
0298 st *prefix ## _new_with_defaults(void); \
0299 void prefix ## _free(st *opt); \
0300 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
0301
0302 #define ISL_ARG_DEF(prefix,st,args) \
0303 st *prefix ## _new_with_defaults() \
0304 { \
0305 st *opt = (st *)calloc(1, sizeof(st)); \
0306 if (opt) \
0307 isl_args_set_defaults(&(args), opt); \
0308 return opt; \
0309 } \
0310 \
0311 void prefix ## _free(st *opt) \
0312 { \
0313 isl_args_free(&(args), opt); \
0314 } \
0315 \
0316 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags) \
0317 { \
0318 return isl_args_parse(&(args), argc, argv, opt, flags); \
0319 }
0320
0321 #if defined(__cplusplus)
0322 }
0323 #endif
0324
0325 #endif