parser_dependencies.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*!
  2. \file lib/gis/parser_dependencies.c
  3. \brief GIS Library - Argument parsing functions (dependencies between options)
  4. (C) 2014 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Glynn Clements Jun. 2014
  8. */
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <grass/gis.h>
  13. #include <grass/glocale.h>
  14. #include "parser_local_proto.h"
  15. struct vector {
  16. size_t elsize;
  17. size_t increment;
  18. size_t count;
  19. size_t limit;
  20. void *data;
  21. };
  22. static void vector_new(struct vector *v, size_t elsize, size_t increment)
  23. {
  24. v->elsize = elsize;
  25. v->increment = increment;
  26. v->count = 0;
  27. v->limit = 0;
  28. v->data = NULL;
  29. }
  30. static void vector_append(struct vector *v, const void *data)
  31. {
  32. void *p;
  33. if (v->count >= v->limit) {
  34. v->limit += v->increment;
  35. v->data = G_realloc(v->data, v->limit * v->elsize);
  36. }
  37. p = G_incr_void_ptr(v->data, v->count * v->elsize);
  38. memcpy(p, data, v->elsize);
  39. v->count++;
  40. }
  41. struct rule {
  42. int type;
  43. int count;
  44. void **opts;
  45. };
  46. static struct vector rules = {sizeof(struct rule), 50};
  47. void G_option_rule(int type, int nopts, void **opts)
  48. {
  49. struct rule rule;
  50. rule.type = type;
  51. rule.count = nopts;
  52. rule.opts = opts;
  53. vector_append(&rules, &rule);
  54. }
  55. static void make_rule(int type, void *first, va_list ap)
  56. {
  57. struct vector opts;
  58. void *opt;
  59. vector_new(&opts, sizeof(void *), 10);
  60. opt = first;
  61. vector_append(&opts, &opt);
  62. for (;;) {
  63. opt = va_arg(ap, void*);
  64. if (!opt)
  65. break;
  66. vector_append(&opts, &opt);
  67. }
  68. G_option_rule(type, opts.count, (void**) opts.data);
  69. }
  70. static int is_flag(const void *p)
  71. {
  72. if (st->n_flags) {
  73. const struct Flag *flag;
  74. for (flag = &st->first_flag; flag; flag = flag->next_flag)
  75. if ((const void *) flag == p)
  76. return 1;
  77. }
  78. if (st->n_opts) {
  79. const struct Option *opt;
  80. for (opt = &st->first_option; opt; opt = opt->next_opt)
  81. if ((const void *) opt == p)
  82. return 0;
  83. }
  84. G_fatal_error(_("Internal error: option or flag not found"));
  85. }
  86. static int is_present(const void *p)
  87. {
  88. if (is_flag(p)) {
  89. const struct Flag *flag = p;
  90. return (int) flag->answer;
  91. }
  92. else {
  93. const struct Option *opt = p;
  94. return opt->count > 0;
  95. }
  96. }
  97. static char *get_name(const void *p)
  98. {
  99. if (is_flag(p)) {
  100. char *s;
  101. G_asprintf(&s, "-%c", ((const struct Flag *) p)->key);
  102. return s;
  103. }
  104. else
  105. return G_store(((const struct Option *) p)->key);
  106. }
  107. static int count_present(const struct rule *rule, int start)
  108. {
  109. int i;
  110. int count = 0;
  111. for (i = start; i < rule->count; i++)
  112. if (is_present(rule->opts[i]))
  113. count++;
  114. return count;
  115. }
  116. static const char *describe_rule(const struct rule *rule, int start,
  117. int disjunction)
  118. {
  119. char *s = get_name(rule->opts[start]);
  120. int i;
  121. for (i = start + 1; i < rule->count - 1; i++) {
  122. char *s0 = s;
  123. char *ss = get_name(rule->opts[i]);
  124. s = NULL;
  125. G_asprintf(&s, "%s>, <%s", s0, ss);
  126. G_free(s0);
  127. G_free(ss);
  128. }
  129. if (rule->count - start > 1) {
  130. char *s0 = s;
  131. char *ss = get_name(rule->opts[i]);
  132. s = NULL;
  133. G_asprintf(&s, disjunction ? _("<%s> or <%s>") : _("<%s> and <%s>"), s0, ss);
  134. G_free(s0);
  135. G_free(ss);
  136. }
  137. return s;
  138. }
  139. static void append_error(const char *msg)
  140. {
  141. st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
  142. st->error[st->n_errors++] = G_store(msg);
  143. }
  144. /*! \brief Sets the options to be mutually exclusive.
  145. When running the module, at most one option from a set can be
  146. provided.
  147. */
  148. void G_option_exclusive(void *first, ...)
  149. {
  150. va_list ap;
  151. va_start(ap, first);
  152. make_rule(RULE_EXCLUSIVE, first, ap);
  153. va_end(ap);
  154. }
  155. static void check_exclusive(const struct rule *rule)
  156. {
  157. if (count_present(rule, 0) > 1) {
  158. char *err;
  159. G_asprintf(&err, _("Options %s are mutually exclusive"),
  160. describe_rule(rule, 0, 0));
  161. append_error(err);
  162. }
  163. }
  164. /* at least one option from a set */
  165. void G_option_required(void *first, ...)
  166. {
  167. va_list ap;
  168. va_start(ap, first);
  169. make_rule(RULE_REQUIRED, first, ap);
  170. va_end(ap);
  171. }
  172. static void check_required(const struct rule *rule)
  173. {
  174. if (count_present(rule, 0) < 1) {
  175. char *err;
  176. G_asprintf(&err, _("At least one of the following options is required: %s"),
  177. describe_rule(rule, 0, 0));
  178. append_error(err);
  179. }
  180. }
  181. /*! \brief Define a list of options from which at least one option
  182. is required if first option is present.
  183. If the first option is present, at least one of the other
  184. options must also be present.
  185. If you want all options to be provided use G_option_requires_all()
  186. function.
  187. If you want more than one option to be present but not all,
  188. call this function multiple times.
  189. */
  190. void G_option_requires(void *first, ...)
  191. {
  192. va_list ap;
  193. va_start(ap, first);
  194. make_rule(RULE_REQUIRES, first, ap);
  195. va_end(ap);
  196. }
  197. static void check_requires(const struct rule *rule)
  198. {
  199. if (!is_present(rule->opts[0]))
  200. return;
  201. if (count_present(rule, 1) < 1) {
  202. char *err;
  203. G_asprintf(&err, _("Option %s requires at least one of %s"),
  204. get_name(rule->opts[0]), describe_rule(rule, 1, 1));
  205. append_error(err);
  206. }
  207. }
  208. /*! \brief Define additionally required options for an option.
  209. If the first option is present, all the other options must also
  210. be present.
  211. If it is enough if only one option from a set is present,
  212. use G_option_requires() function.
  213. \see G_option_collective()
  214. */
  215. void G_option_requires_all(void *first, ...)
  216. {
  217. va_list ap;
  218. va_start(ap, first);
  219. make_rule(RULE_REQUIRES_ALL, first, ap);
  220. va_end(ap);
  221. }
  222. static void check_requires_all(const struct rule *rule)
  223. {
  224. if (!is_present(rule->opts[0]))
  225. return;
  226. if (count_present(rule, 1) < rule->count - 1) {
  227. char *err;
  228. G_asprintf(&err, _("Option %s requires all of %s"),
  229. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  230. append_error(err);
  231. }
  232. }
  233. /* if the first option is present, none of the other options may also (should?)
  234. be present. */
  235. void G_option_excludes(void *first, ...)
  236. {
  237. va_list ap;
  238. va_start(ap, first);
  239. make_rule(RULE_EXCLUDES, first, ap);
  240. va_end(ap);
  241. }
  242. static void check_excludes(const struct rule *rule)
  243. {
  244. if (!is_present(rule->opts[0]))
  245. return;
  246. if (count_present(rule, 1) > 0) {
  247. char *err;
  248. G_asprintf(&err, _("Option %s is mutually exclusive with all of %s"),
  249. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  250. append_error(err);
  251. }
  252. }
  253. /* if any option is present, all the other options must also be present
  254. all or nothing from a set */
  255. void G_option_collective(void *first, ...)
  256. {
  257. va_list ap;
  258. va_start(ap, first);
  259. make_rule(RULE_COLLECTIVE, first, ap);
  260. va_end(ap);
  261. }
  262. static void check_collective(const struct rule *rule)
  263. {
  264. int count = count_present(rule, 0);
  265. if (count > 0 && count < rule->count) {
  266. char *err;
  267. G_asprintf(&err, _("Either all or none of %s must be given"),
  268. describe_rule(rule, 0, 0));
  269. append_error(err);
  270. }
  271. }
  272. void G__check_option_rules(void)
  273. {
  274. unsigned int i;
  275. for (i = 0; i < rules.count; i++) {
  276. const struct rule *rule = &((const struct rule *) rules.data)[i];
  277. switch (rule->type) {
  278. case RULE_EXCLUSIVE:
  279. check_exclusive(rule);
  280. break;
  281. case RULE_REQUIRED:
  282. check_required(rule);
  283. break;
  284. case RULE_REQUIRES:
  285. check_requires(rule);
  286. break;
  287. case RULE_REQUIRES_ALL:
  288. check_requires_all(rule);
  289. break;
  290. case RULE_EXCLUDES:
  291. check_excludes(rule);
  292. break;
  293. case RULE_COLLECTIVE:
  294. check_collective(rule);
  295. break;
  296. default:
  297. G_fatal_error(_("Internal error: invalid rule type: %d"),
  298. rule->type);
  299. break;
  300. }
  301. }
  302. }
  303. void G__describe_option_rules(void)
  304. {
  305. unsigned int i;
  306. for (i = 0; i < rules.count; i++) {
  307. const struct rule *rule = &((const struct rule *) rules.data)[i];
  308. switch (rule->type) {
  309. case RULE_EXCLUSIVE:
  310. fprintf(stderr, "Exclusive: %s", describe_rule(rule, 0, 0));
  311. break;
  312. case RULE_REQUIRED:
  313. fprintf(stderr, "Required: %s", describe_rule(rule, 0, 1));
  314. break;
  315. case RULE_REQUIRES:
  316. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  317. describe_rule(rule, 1, 1));
  318. break;
  319. case RULE_REQUIRES_ALL:
  320. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  321. describe_rule(rule, 1, 0));
  322. break;
  323. case RULE_EXCLUDES:
  324. fprintf(stderr, "Excludes: %s => %s", get_name(rule->opts[0]),
  325. describe_rule(rule, 1, 0));
  326. break;
  327. case RULE_COLLECTIVE:
  328. fprintf(stderr, "Collective: %s", describe_rule(rule, 0, 0));
  329. break;
  330. default:
  331. G_fatal_error(_("Internal error: invalid rule type: %d"),
  332. rule->type);
  333. break;
  334. }
  335. }
  336. }
  337. /*!
  338. \brief Checks if there is any rule RULE_REQUIRED.
  339. \return 1 if there is such rule
  340. \return 0 if not
  341. */
  342. int G__has_required_rule(void)
  343. {
  344. size_t i;
  345. for (i = 0; i < rules.count; i++) {
  346. const struct rule *rule = &((const struct rule *) rules.data)[i];
  347. if (rule->type == RULE_REQUIRED)
  348. return TRUE;
  349. }
  350. return FALSE;
  351. }