arg.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright 2008-2009 Katholieke Universiteit Leuven
  3. *
  4. * Use of this software is governed by the MIT license
  5. *
  6. * Written by Sven Verdoolaege, K.U.Leuven, Departement
  7. * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
  8. */
  9. #ifndef ISL_ARG_H
  10. #define ISL_ARG_H
  11. #include <stddef.h>
  12. #include <stdlib.h>
  13. #if defined(__cplusplus)
  14. extern "C" {
  15. #endif
  16. struct isl_arg_choice {
  17. const char *name;
  18. unsigned value;
  19. };
  20. struct isl_arg_flags {
  21. const char *name;
  22. unsigned mask;
  23. unsigned value;
  24. };
  25. enum isl_arg_type {
  26. isl_arg_end,
  27. isl_arg_alias,
  28. isl_arg_arg,
  29. isl_arg_bool,
  30. isl_arg_child,
  31. isl_arg_choice,
  32. isl_arg_flags,
  33. isl_arg_footer,
  34. isl_arg_int,
  35. isl_arg_user,
  36. isl_arg_long,
  37. isl_arg_ulong,
  38. isl_arg_str,
  39. isl_arg_str_list,
  40. isl_arg_version
  41. };
  42. struct isl_args;
  43. struct isl_arg {
  44. enum isl_arg_type type;
  45. char short_name;
  46. const char *long_name;
  47. const char *argument_name;
  48. #define ISL_ARG_OFFSET_NONE ((size_t) -1)
  49. size_t offset;
  50. const char *help_msg;
  51. #define ISL_ARG_SINGLE_DASH (1 << 0)
  52. #define ISL_ARG_BOOL_ARG (1 << 1)
  53. #define ISL_ARG_HIDDEN (1 << 2)
  54. unsigned flags;
  55. union {
  56. struct {
  57. struct isl_arg_choice *choice;
  58. unsigned default_value;
  59. unsigned default_selected;
  60. int (*set)(void *opt, unsigned val);
  61. } choice;
  62. struct {
  63. struct isl_arg_flags *flags;
  64. unsigned default_value;
  65. } flags;
  66. struct {
  67. unsigned default_value;
  68. int (*set)(void *opt, unsigned val);
  69. } b;
  70. struct {
  71. int default_value;
  72. } i;
  73. struct {
  74. long default_value;
  75. long default_selected;
  76. int (*set)(void *opt, long val);
  77. } l;
  78. struct {
  79. unsigned long default_value;
  80. } ul;
  81. struct {
  82. const char *default_value;
  83. } str;
  84. struct {
  85. size_t offset_n;
  86. } str_list;
  87. struct {
  88. struct isl_args *child;
  89. } child;
  90. struct {
  91. void (*print_version)(void);
  92. } version;
  93. struct {
  94. int (*init)(void*);
  95. void (*clear)(void*);
  96. } user;
  97. } u;
  98. };
  99. struct isl_args {
  100. size_t options_size;
  101. struct isl_arg *args;
  102. };
  103. #define ISL_ARGS_START(s,name) \
  104. struct isl_arg name ## LIST[]; \
  105. struct isl_args name = { sizeof(s), name ## LIST }; \
  106. struct isl_arg name ## LIST[] = {
  107. #define ISL_ARGS_END \
  108. { isl_arg_end } };
  109. #define ISL_ARG_ALIAS(l) { \
  110. .type = isl_arg_alias, \
  111. .long_name = l, \
  112. },
  113. #define ISL_ARG_ARG(st,f,a,d) { \
  114. .type = isl_arg_arg, \
  115. .argument_name = a, \
  116. .offset = offsetof(st, f), \
  117. .u = { .str = { .default_value = d } } \
  118. },
  119. #define ISL_ARG_FOOTER(h) { \
  120. .type = isl_arg_footer, \
  121. .help_msg = h, \
  122. },
  123. #define ISL_ARG_CHOICE(st,f,s,l,c,d,h) { \
  124. .type = isl_arg_choice, \
  125. .short_name = s, \
  126. .long_name = l, \
  127. .offset = offsetof(st, f), \
  128. .help_msg = h, \
  129. .u = { .choice = { .choice = c, .default_value = d, \
  130. .default_selected = d, .set = NULL } } \
  131. },
  132. #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h) { \
  133. .type = isl_arg_choice, \
  134. .short_name = s, \
  135. .long_name = l, \
  136. .offset = offsetof(st, f), \
  137. .help_msg = h, \
  138. .u = { .choice = { .choice = c, .default_value = d, \
  139. .default_selected = ds, .set = NULL } } \
  140. },
  141. #define ISL_ARG_PHANTOM_USER_CHOICE_F(s,l,c,setter,d,h,fl) { \
  142. .type = isl_arg_choice, \
  143. .short_name = s, \
  144. .long_name = l, \
  145. .offset = ISL_ARG_OFFSET_NONE, \
  146. .help_msg = h, \
  147. .flags = fl, \
  148. .u = { .choice = { .choice = c, .default_value = d, \
  149. .default_selected = d, .set = setter } } \
  150. },
  151. #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h) { \
  152. .type = isl_arg_choice, \
  153. .short_name = s, \
  154. .long_name = l, \
  155. .offset = offsetof(st, f), \
  156. .help_msg = h, \
  157. .u = { .choice = { .choice = c, .default_value = d, \
  158. .default_selected = ds, .set = setter } } \
  159. },
  160. #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl) { \
  161. .type = isl_arg_bool, \
  162. .short_name = s, \
  163. .long_name = l, \
  164. .offset = o, \
  165. .help_msg = h, \
  166. .flags = fl, \
  167. .u = { .b = { .default_value = d, .set = setter } } \
  168. },
  169. #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl) \
  170. _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
  171. #define ISL_ARG_BOOL(st,f,s,l,d,h) \
  172. ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
  173. #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl) \
  174. _ISL_ARG_BOOL_F(ISL_ARG_OFFSET_NONE,s,l,setter,0,h,fl)
  175. #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h) \
  176. ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
  177. #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl) { \
  178. .type = isl_arg_int, \
  179. .short_name = s, \
  180. .long_name = l, \
  181. .argument_name = a, \
  182. .offset = offsetof(st, f), \
  183. .help_msg = h, \
  184. .flags = fl, \
  185. .u = { .i = { .default_value = d } } \
  186. },
  187. #define ISL_ARG_INT(st,f,s,l,a,d,h) \
  188. ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
  189. #define ISL_ARG_LONG(st,f,s,lo,d,h) { \
  190. .type = isl_arg_long, \
  191. .short_name = s, \
  192. .long_name = lo, \
  193. .offset = offsetof(st, f), \
  194. .help_msg = h, \
  195. .u = { .l = { .default_value = d, .default_selected = d, \
  196. .set = NULL } } \
  197. },
  198. #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) { \
  199. .type = isl_arg_long, \
  200. .short_name = s, \
  201. .long_name = lo, \
  202. .offset = offsetof(st, f), \
  203. .help_msg = h, \
  204. .u = { .l = { .default_value = d, .default_selected = d, \
  205. .set = setter } } \
  206. },
  207. #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h) { \
  208. .type = isl_arg_long, \
  209. .short_name = s, \
  210. .long_name = lo, \
  211. .offset = offsetof(st, f), \
  212. .help_msg = h, \
  213. .u = { .l = { .default_value = d, .default_selected = ds, \
  214. .set = NULL } } \
  215. },
  216. #define ISL_ARG_ULONG(st,f,s,l,d,h) { \
  217. .type = isl_arg_ulong, \
  218. .short_name = s, \
  219. .long_name = l, \
  220. .offset = offsetof(st, f), \
  221. .help_msg = h, \
  222. .u = { .ul = { .default_value = d } } \
  223. },
  224. #define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl) { \
  225. .type = isl_arg_str, \
  226. .short_name = s, \
  227. .long_name = l, \
  228. .argument_name = a, \
  229. .offset = offsetof(st, f), \
  230. .help_msg = h, \
  231. .flags = fl, \
  232. .u = { .str = { .default_value = d } } \
  233. },
  234. #define ISL_ARG_STR(st,f,s,l,a,d,h) \
  235. ISL_ARG_STR_F(st,f,s,l,a,d,h,0)
  236. #define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h) { \
  237. .type = isl_arg_str_list, \
  238. .short_name = s, \
  239. .long_name = l, \
  240. .argument_name = a, \
  241. .offset = offsetof(st, f_l), \
  242. .help_msg = h, \
  243. .u = { .str_list = { .offset_n = offsetof(st, f_n) } } \
  244. },
  245. #define _ISL_ARG_CHILD(o,l,c,h,fl) { \
  246. .type = isl_arg_child, \
  247. .long_name = l, \
  248. .offset = o, \
  249. .help_msg = h, \
  250. .flags = fl, \
  251. .u = { .child = { .child = c } } \
  252. },
  253. #define ISL_ARG_CHILD(st,f,l,c,h) \
  254. _ISL_ARG_CHILD(offsetof(st, f),l,c,h,0)
  255. #define ISL_ARG_GROUP_F(l,c,h,fl) \
  256. _ISL_ARG_CHILD(ISL_ARG_OFFSET_NONE,l,c,h,fl)
  257. #define ISL_ARG_GROUP(l,c,h) \
  258. ISL_ARG_GROUP_F(l,c,h,0)
  259. #define ISL_ARG_FLAGS(st,f,s,l,c,d,h) { \
  260. .type = isl_arg_flags, \
  261. .short_name = s, \
  262. .long_name = l, \
  263. .offset = offsetof(st, f), \
  264. .help_msg = h, \
  265. .u = { .flags = { .flags = c, .default_value = d } } \
  266. },
  267. #define ISL_ARG_USER(st,f,i,c) { \
  268. .type = isl_arg_user, \
  269. .offset = offsetof(st, f), \
  270. .u = { .user = { .init = i, .clear = c} } \
  271. },
  272. #define ISL_ARG_VERSION(print) { \
  273. .type = isl_arg_version, \
  274. .u = { .version = { .print_version = print } } \
  275. },
  276. #define ISL_ARG_ALL (1 << 0)
  277. #define ISL_ARG_SKIP_HELP (1 << 1)
  278. void isl_args_set_defaults(struct isl_args *args, void *opt);
  279. void isl_args_free(struct isl_args *args, void *opt);
  280. int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
  281. unsigned flags);
  282. #define ISL_ARG_DECL(prefix,st,args) \
  283. extern struct isl_args args; \
  284. st *prefix ## _new_with_defaults(void); \
  285. void prefix ## _free(st *opt); \
  286. int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
  287. #define ISL_ARG_DEF(prefix,st,args) \
  288. st *prefix ## _new_with_defaults() \
  289. { \
  290. st *opt = (st *)calloc(1, sizeof(st)); \
  291. if (opt) \
  292. isl_args_set_defaults(&(args), opt); \
  293. return opt; \
  294. } \
  295. \
  296. void prefix ## _free(st *opt) \
  297. { \
  298. isl_args_free(&(args), opt); \
  299. } \
  300. \
  301. int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags) \
  302. { \
  303. return isl_args_parse(&(args), argc, argv, opt, flags); \
  304. }
  305. #if defined(__cplusplus)
  306. }
  307. #endif
  308. #endif